【问题标题】:Java switch/case method recomended lengthJava switch/case方法推荐长度
【发布时间】:2016-05-03 11:22:16
【问题描述】:

我是一名学生,正在撰写关于 SSL/TLS 和 JSSE 的论文。在 oracle 提供的实现示例中(在此处找到:http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#AppA)我找到了实现示例:

   public void doHandshake(SocketChannel socketChannel,
                        SSLEngine     engine,
                        ByteBuffer    myNetData, 
                        ByteBuffer    peerNetData) throws Exception {

    // 2)
    int appBufferSize = engine.getSession().getApplicationBufferSize();
    // 3)
    ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
    ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);

    // 4)
    engine.beginHandshake();
    SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();

    // 5)
    while (hs != SSLEngineResult.HandshakeStatus.FINISHED
            && hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {

        switch (hs) {

            case NEED_UNWRAP:
                // Receive handshaking data from peer
                if (socketChannel.read(peerNetData) < 0) {
                    // The channel has reached end-of-stream
                }

                // Process incoming handshaking data
                peerNetData.flip();
                SSLEngineResult res = engine.unwrap(peerNetData, peerAppData);
                peerNetData.compact();
                hs = res.getHandshakeStatus();

                // Check status
                switch (res.getStatus()) {
                    case OK:
                        // Handle OK status
                        break;

        // Handle other status: BUFFER_UNDERFLOW, BUFFER_OVERFLOW, CLOSED
                    //...
                }
                break;

            case NEED_WRAP:
                // Empty the local network packet buffer.
                myNetData.clear();

                // Generate handshaking data
                res = engine.wrap(myAppData, myNetData);
                hs = res.getHandshakeStatus();

                // Check status
                switch (res.getStatus()) {
                    case OK:
                        myNetData.flip();

                        // Send the handshaking data to peer
                        while (myNetData.hasRemaining()) {
                            socketChannel.write(myNetData);
                        }
                        break;

        // Handle other status:  BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED
                    //...
                }
                break;

            case NEED_TASK:
                // Handle blocking tasks
                break;

    // Handle other status:  // FINISHED or NOT_HANDSHAKING
            //...
        }
    }

// Processes after handshaking
    //   ...
}

现在,根据我对正确 OOP 架构的了解,方法不应超过 20 行,但我发现 Oracle 会犯这种基本的架构错误很奇怪。任何超过 20 行的内容都应分割成单独的方法,但也有例外。我想知道,这是那些例外之一吗?如果没有,将 switch/case 方法拆分为更小的方法的最佳方法是什么。

【问题讨论】:

  • 您的机构可能正试图向您灌输良好的习惯,但世界上到处都是不符合您可能被教导的最佳实践的代码。即使在非常专业的代码中。不要感到惊讶。
  • 没有“正确的 OOP 架构”,只有很多关于什么是正确的观点。
  • 不应该超过20行? 20已经太多了。大约 4 或 6 行是合理的。
  • 您可以在论文中编写任何您喜欢的代码。没有人会对其进行代码审查以符合公司标准。您的论文旨在扩展知识的界限,而不是五年内 24/7 全天候执行。

标签: java oop switch-statement


【解决方案1】:

您将术语放在一起......不一定属于一起。

您可以创建一个出色的 OOP 设计......并且在您的每个方法中仍然有很多代码。

您可以遵循clean code 规则,例如避免包含多个一个 single level of abstraction任何 方法;并且最终的设计可能很糟糕并且“不是 OOP”(但我认为:这很难 - 如果您遵循所有干净的代码规则,您会自动创建更好的 OOP 设计)。

但是,要回答原始问题(这实际上是一个糟糕的问题;因为它会邀请基于意见的答案,例如我的):上面的代码至少“一点也不干净”。实际上,我觉得这很可怕,在这些枚举案例中塞进“更多”的想法对我来说听起来非常糟糕。除此之外,您不会以这种方式使用枚举——这种“开关”应该对客户端代码不可见;相反,您将依赖多态性;并简单地告诉在某个对象上调用一些方法...

我多年来一直在练习干净的代码,发现生成的代码更易于阅读和维护。在“干净的代码”中;好吧,如前所述:您不会将多个 switch 语句放入一个方法中。每个循环;并且每个中断案例......都将放在他们自己的方法中。

许多人认为这很疯狂,但我发现它确实是“更好”的方法,经过几个月的练习。它确实使我无法创建像您的示例那样不可测试的代码。

回答你的第二个问题:这真的很难。人们必须了解整个设计,然后一点一点地拆开它并重构它的元素。但这当然需要您拥有一套完整的单元/功能测试(因此您表明您的更改不会破坏整个事情)。因此,“改进”此类代码的通用方法是:

  1. 了解更改现有软件的真实成本。你不应该仅仅因为“糟糕的代码”而改变东西。您需要一个好的(商业)理由来证明更改代码的费用是合理的。
  2. 确保您有良好的测试。如果有测试,请测量它们的覆盖范围(以评估现有测试的“好”程度)。如果没有测试...开始编写它们。
  3. 测试到位后...开始重新设计、重构并丢弃无法回收的部件。

【讨论】:

    【解决方案2】:

    示例代码就是这样:示例代码。它不是一个功能性的软件,它只是一个教育工具,就像一个剖面图。它的唯一目的是展示某些东西是如何工作的,而且它通常会包含您不会放入生产代码中的东西。

    示例代码的一个典型特征是放弃封装并减少间接次数,使事情更加本地化,​​您可以从上到下阅读代码,就像一页文本一样。

    这就是您在此处看到的:他们试图演示一个逐步的过程,因此他们以一种在代码中每个步骤都遵循另一个步骤的方式来格式化代码。

    【讨论】:

      【解决方案3】:

      Java 最未被充分利用的特性之一是向枚举添加行为(例如方法)的可能性。所以问问自己,你的例子中需要的行为是否足够普遍,可以由枚举本身(全部或部分)执行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-29
        相关资源
        最近更新 更多