0

在一个可以工作的应用程序中,我看到了这个可怕的代码:

class SomeUglyClass extends Thread {
    ArrayList<SomeData> someDataStructure = new ArrayList<SomeData>();
    Handler mHandler = new Handler() {
        // a lot
        // writing to someDataStructure
    }
    public void run() {
        int some_count, ...;
        while(true) {
            // a lot
            // r/w access to someDataStructure

            try {
                Thread.sleep(1, 0);
            } catch (Exception e) {
                break;
            }               
        }
    } // end of run(), total 500 lines of code
} // end of SomeUglyClass, total 4K lines of code

也许您已经看到了这段代码的问题。如果没有,它们是:

  1. mHandler附加到 UI 线程(因为它是由加载类的线程创建的,也就是主线程)

  2. 没有活套(这实际上是错误

  3. 该线程浪费CPU时间并耗尽电池

  4. someDataStructure不是线程安全的,但同步基本访问操作无济于事;在无限循环中同步大块代码可能会阻塞受保护的资源并使其对其他线程不可用;最后,不仅如此someDataStructure,整个类都基于只有一个线程可以运行其代码的假设。

  5. 我不能只添加looper,因为run()必须运行无限循环,同时Looper.loop();也是一个无限循环。一个线程不能运行两个无限循环。

尽管有这个史诗般的架构失败,但代码确实在做一些事情,它不能立即重写,它是 4K 行代码,而且我通常只能猜测代码真正做了什么。

我需要重构它。它应该是一系列保留功能的小步骤。

我如何重构这个了不起的代码?

4

3 回答 3

1

您应该尝试关注点分离:首先尝试将整个班级分成许多最小的班级,每个班级负责做/处理一件事。

你可能有一些数据访问(读/写数据)、服务(隔离的业务逻辑)和 UI。您可以使用事件总线在对象之间解耦(考虑otto)并且可能是依赖注入(考虑Dagger)。

这种分离过程将帮助您了解每段代码在做什么以及不同部分之间的依赖关系,从而使编写单元/集成测试更加容易。

于 2015-01-26T10:00:46.243 回答
0

第一步是改变:

    public void run() {
        int some_count, ...;
        while(true) {
            // a lot
            // r/w access to someDataStructure

            try {
                Thread.sleep(1, 0);
            } catch (Exception e) {
                break;
            }               
        }
    }

至:

    @Override
    public void run() {
        Looper.prepare();
        mHandler = new MyHandler();
        mHandler.post(run_step);
        Looper.loop();
    }

    Runnable run_step = new Runnable() {
        int some_count, ...;

        @Override
        public void run()
        {
            //while(true) {
                // a lot
                // r/w access to someDataStructure

                mIntoThreadHandler.postDelayed(this, 1);
            //}
        }
    }

这保留了功能,但仍然浪费 CPU 时间。紧急bug已修复,问题已关闭;我不能向我的管理层推销“必须重构才能杀死可怕的代码”,但我可以推销“如果我重构,这可以更快地工作”,因此打开了一个新的单独问题。啊!

PS没有机会出售“大量测试”

于 2015-01-27T11:41:38.230 回答
0

添加大量测试,使用版本控制,然后根据需要慢慢工作。

于 2015-01-26T09:32:36.300 回答