Java开关/案例方法推荐长度为

时间:2016-05-03 11:22:17

标签: java oop switch-statement

我是一名学生,我正在致力于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方法拆分为更小的方法的最佳方法是什么。

3 个答案:

答案 0 :(得分:3)

你正在把条款放在一起......不一定属于一起。

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

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

但是,回答原始问题(这实际上是一个不好的问题;因为它邀请基于意见的答案,例如我的):上面的代码至少“根本不干净”。实际上,我发现它非常可怕,并且在这些枚举案例中添加“更多”的想法对我来说听起来非常糟糕。除此之外,你不会以这种方式使用枚举 - 这种“切换”应该对客户端代码不可见;相反,你会依赖多态性;并简单地告诉某些对象调用一些方法...

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

许多人认为这很疯狂,但我觉得它真的是“更好”的方法,现在已经练了好几个月了。它确实阻止我创建像你的例子那样无法测试的代码。

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

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

答案 1 :(得分:0)

示例代码就是:示例代码。它不是一个功能正常的软件,它只是一个教育工具,就像一张剖面图。它的唯一目的是展示某些东西是如何工作的,并且它经常会包含你不会在生产代码中加入的东西。

示例代码的一个典型特征是放弃封装并减少间接数量,以便事物更加本地化,​​您可以从上到下读取代码,如文本页面。

这就是你在这里看到的:他们试图演示一步一步的过程,因此他们按照每个步骤在代码中跟随另一个步骤的方式格式化代码。

答案 2 :(得分:0)

Java最缺乏使用的功能之一是可以向枚举添加行为(例如方法)。因此,请问自己,您的示例中所需的行为是否足够通用,以便由枚举本身执行(全部或部分)。