1

假设我们有一个类,其中包含一些方法,其中至少有一个具有相当复杂的性质:

class Example {
    public function Example()
    {
    }

    private function complexFunction():void
    {
        //Do this
        //And do that
        //And of course do that
        //and do not forget that
    }

    private function otherImportantFunction():void
    {
        //Do something
    }

    //[...]
}

现在“complexFunction()”已经变得很长而且有点复杂。因此,增加可读性的一件好事是将“complexFunction()”拆分为较小的子函数。我通常这样做:

class Example {
    public function Example()
    {
    }

    private function complexFunction():void
    {
        doThis();
        doThat();
        andOfCourseDoThat();
        andDoNotForgetThat();
    }

    private function doThis():void
    {
        //Do This
    }

    private function doThat():void
    {
        //Do That
    }

    private function andOfCourseDoThat():void
    {
        //And of course do that
    }

    private function andDoNotForgetThat():void
    {
        //And do not forget that
    }

    private function otherImportantFunction():void
    {
        //Do something
    }

    //[...]
}

但是现在这个类已经被小函数淹没了,这些小函数的唯一目的是在“complexFunction()”中被调用一次。更频繁地进行这种“拆分”,就很难发现所有这些辅助函数之间的重要方法。

至少这一直是发生在我身上的事情,而清晰度确实因此而受到影响。这让我想知道你是否知道解决这个困境的方法?当然有办法或“最佳实践”来处理这个问题?我梦想有一种方法可以将功能组合在一起,或者将次要功能从属于高级功能,而无需为此创建一个全新的类。还是它是这样做的?

4

3 回答 3

0

仅仅因为一个函数很“长”并不会使它变得更复杂,有些事情只需要很多行代码。
举个例子:

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
loader.contentLoaderInfo.addEventListener(Event.INIT, initHandler);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
loader.contentLoaderInfo.addEventListener(Event.OPEN, openHandler);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
loader.contentLoaderInfo.addEventListener(Event.UNLOAD, unLoadHandler);
loader.contentLoaderInfo.addEventListener(MouseEvent.CLICK, clickHandler);
var request:URLRequest = new URLRequest(url);
loader.load(request);

是“长”吗?是
它是否具有高循环复杂度?不
你可以清楚地理解这里发生了什么,而且很容易理解。
你会发现低 CC 值的函数/方法总是更容易阅读。
另一方面,具有高(+20)CC 值的方法应该竖起红旗。
将方法拆分为单独的辅助方法并不能消除手头的问题,实际上会使编译器变得更糟,因为现在它必须分配专门用于那些只会被调用一次的方法的资源。经验法则是避免超过 20 的 CC 值。
当你超过 20 时,是时候开始重新考虑你的类设计,因为它变得紧密耦合。

也许你应该问的问题是。

 How can I reduce the Cyclomatic Complexity of this?
于 2013-05-03T13:58:44.740 回答
0

我个人发现,如果将复杂代码拆分为简单的函数,它会大大提高复杂代码的可读性。我在呈现的代码中并没有真正得到的是那些更简单的函数组合成一个函数的方式,这似乎只适用于根本不返回任何东西的函数(它们似乎有一些效果)。恕我直言,从更简单的函数构建复杂函数的一种更自然的方法是通过函数组合、案例区分或类似的方式......

于 2013-05-03T13:56:22.003 回答
0

将一个大功能拆分为多个功能是正确的。前提是它不是类似于AddOne()而不是value++. 特别是您可能会更频繁地重复使用的功能。

当您的课程充满了多个函数(或长函数)时,重新考虑您的课程的功能可能是个好主意。尽量让你的班级只学习一门学科。例如,一个类的一个好主意是使其与用户相关。可以在其中完成创建或删除用户之类的操作。例如,甚至可以将用户与他们拥有的汽车进行匹配。但不要在用户类中包含保存或删除汽车的函数。将其保存为不同的课程。

在这种情况下,您的 Example-class 将具有 User-class 和 Car-class 的实例。如果它看起来像这样,那么您正在高效地编程:

class Example {
    function Example()
    {
    }

    function complexFunction():void
    {
        Car newCar = new Car("KK-E8", Color.Red, true);
        carManager.Add(newCar);
        User newUser = new User("Moritz", "Krohn", Country.Germany, true);
        userManager.Add(newUser);
        newUser.addCar(newCar);
        ...
    }

碰巧有些班级往往会变大,即使你试图让事情井井有条。这从来都不是一件坏事,长函数也不是坏事。试着把事情分开,尽量不要重复代码太多(为此创建函数),并尝试将彼此相关的事情放在单独的类中。

于 2013-05-03T12:56:41.430 回答