从MVC到MVP,记一次代码重构

时间:2021-11-01 04:11:13

前言

手底下一直在做一个项目,从交互看起来也没怎么复杂,但由于历史原因,底下有二十多个依赖工程,到目前我也没有把依赖工程具体的东西搞明白。在代码里边偶尔能看到13年的记录,也经过了无数人的手。代码的逻辑结构非常混乱,也许是修修补补太多了吧。哈哈,几年后如果有人接手是不是也会这么说我。这次迭代交互和视觉要进行一次大的改版,新的交互改变了整体的框架,所以也就乘此机会,一边重构,一边修改新的交互。到目前以进行一个半月,再此过程中感谢我的同事浪平哥的指导。本篇不讲MVP的细节,只是简单的说说这次重构的一些体会,鄙人愚钝,不当之处,敬请赐教。

认识MVP

发现Android出现的一些新技术会在各种博客、微信公众号瞬间扩散,在各大网站也会有更新。MVP已经在很久前出现了,有幸有机会能够在项目中实战,网上有许多的教程,还有官方的Demo,在此就不做深入分析了,仅谈一谈自己的理解。

MVC和MVP

MVC是我们之前的开发中一直用的开发模式,这种开发模式结构简单,开发速度快,代码量少。但是View和Contrl基本都在Activity中完成,造成项目中的Activity干的事情太多,逻辑混乱,可读性差。数据和UI纠结在一起,在迭代过程中不好修改。就像拉着一辆破车跑,实在是让人举步维艰。MVP的优势在于让数据和UI分离,V层只管UI的显示操作,M层按照业务划分,根据不同业务有对应不同的model完成网络访问、数据库读取等所欲的数据操作。P层是一个协调者的角色,他将从M层拿到数据,并协调分配给不同的UI,完成在界面上指定控件显示指定的数据。这样分工更加明确,业务之间耦合少,方便修改。

MVP最简模型

  • Entity

    public class Monkey(){
        private name;
        set***
        get***
    }
    
  • M层

    public class Model{

    public Monkey getData(){
        Monkey monkey=new Monkey();
        //也许是访问数据库或者网络等复杂的操作
        monkey.setName("code");
        return monkey;
    }
    

    }

  • P层

    public class Presenter{
        private mIView;
        private mModel;
        public Presenter(){
            mModel=new Model();//初始化一个model
        }
        public attachView(IView view){
            mIView=view;
        }
        public string initData(){
            return mModel.getData().getName();
        }
        public void showView(){
            mIView.show();
        }
    }
    
  • V层

    public interface IView{
        void show();
    }
    
    public class TestActivity extends Activity implements IView{
        private TextView mTextview;//UI
        private String mName;//数据
        private Presenter mPresenter;
    
    
        protect void onCreate(){
            mTextView=(TextView)findeById(R.id.xxx);
            mPrsenter=new Presenter();
            mPrsenter.attchView(this);
            mName=mPresenter.initData();
            mPrsennter.showView();
        }
        public void show(){
            mTextView.setText(mName);
        }
    
    }
    

    上述还有许多就没有表现出来,比如当Activity销毁的时候,应该调用Presenter的一个destory的方法销毁P层,同样的在M层中也要写一个destory的方法供P层调用进行销毁操作,这里一可以避免数据混乱,二也是清除缓存数据,释放内存。还有比如,我们大部分复杂一点的UI控件的显示或者隐藏等和数据有关,这个时候我们就要把基础的数据通过P层交给UI,将与UI相关的数据暴露在UI层中,这UI层中进行判断等操作。如果需要进行异步加载数据,可以采用回调的方式将数据返回到UI层;

重构之路

原代码分析

重构前接手项目有一两个月的时间,紧张的迭代进度并没有给我许多的时间去熟悉代码,中间由于项目的迭代计划出现一些问题,这个空余的时间给了我熟悉代码的机会,然而到后边真正重构的时候才发现做了许多的无用功。

  • 快速熟悉代码的方法
    • 首先从UI分析,可以用逻辑结构图画出来,每个模块有哪些界面,这些界面对应的Activity,fragment是哪个,以便后边看一目了然;
    • 使用Debug调试,在有操作的等关键的地方打好点,一步步调试,看看程序是怎么跑的;
    • 再烂的代码都会有他的套路,而且这个套路运用在整个程序各个地方的开发之中,我经历的项目并不是很多,但是这个问题想想也能确定。所以,如果你对这个套路搞清楚了,这个程序在你的面前就会变得透明的,是一堆骨架。
  • 需要输出的文档
    • 功能结构图,也就是上面说的UI界面对应的Acitivty和Fragment;
    • 数据加载分析文档,每个软件必定会牵涉到数据,我这里的数据加载不是网络或者数据库的原始数据,而是程序运行时数据的读取、传递、计算等缓存的数据。我用的是用表格的形式,填写了某一个实体类,实体类中包含的数据元素以及值。不过后来发现,这里不要弄的太详细,这里边的数据太复杂了。不要把太多的时间放在这里,主要的目的在于把数据加载的过程了解清楚,重构的时候难免要动这一块,不过真正动的时候再用Debug调试了解详细信息就好了。

重构中的一些发现

  • 写好基础Model业务层

    在前期的准备工作中,分析得出某一些Model层业务是几乎所有Model层公有的,这个时候我们要将一些公有的业务写到一个基类里边。每个软件都会有不同的模块,然后我们可以在不同的模块也写一个基类,然后在具体的业务层的model中继承这个基类就可以了,这样节省了许多的代码,也将业务分的更加清晰。

  • 分拆原有工具类方法到Model层

    在MVC模式的开发中,我们避免Activity中的代码过多,常常将某一些共有的操作放到一个工具类中,比如数据库的读取,然后不同的Activity有不同的操作,这些都写在一个工具类中,我们不好分辨谁是谁的。这些活都是由model层来干的,我们可以通过Ctrl+G搜索这个工具类的每一个方法被谁调用了,然后分别将这些方法copy到对应的model层去。

  • 除了 if 记得也要写好 else

    发现以前的代码里边有许多容错处理,比如常常做的是 if 某某某不等于null,然后才进行什么操作,但是else就不管了,这样出了问题好难查,如果我们程序写的时候就在else 中抛出一个异常或者打一个log说明这种情况什么为null,出的什么问题。这样bug来了,找到问题也就是分分钟的事情。为什么敢去重构代码,这是一个高风险的活,因为我在每个可能存在问题的地方都有Log说明,问题来了也好找。

  • 从不知何处下手到感觉这只是一个套路

    我的同事已经将一个独立的新模块完全用MVP模式写的,为了学习MVP模式,我这个模块写了一个demo,深刻觉得当无从下手的时候一定要让自己动手。刚进行重构的时候,都不清楚该怎么写model,怎么写presenter,但是经过一段时间的改造,已经觉得没有那么有挑战性了,我只是将代码的逻辑结构进行了一些调整,基本写的是一些框架性的东西,然后将原有的代码copy进去,实现具体的细节。写到后边都觉得自己只是在进行一些体力劳动,也许是项目时间太紧,我没有时间去优化,写的过程中也感觉到有些地方还待改进。说的这么多,主要是想说,重构不难,难在开头。

  • 不要心急,逐步重构

    毕竟项目还处在迭代的计划中,产品不可能让我一直整代码,所以这是一个逐步完成的工作,也许是我们原代码实在太散了,得花点时间才动的了。不过此次重构也只是完成了大部分的模块。所以重构也不是把代码翻个底朝天,虽然我再做的时候有些地方实在无法忍受,给改造了。但是也得考虑时间已经风险,所以要注意要一步一步的蚕食,别大口吃,最后搞不完留一堆碎渣子。路漫漫其修远兮,哈哈!

结语

项目的此次重构还有许多不完善的地方需要优化,MVC也好MVP也好,关键得让你的工作变的高效,减少无用功。所以,从长远出发,如果你的项目目前是一堆陈旧的代码,是时候重构啦。对于一些项目,从MVC到MVP是一种进步,也是重新梳理程序逻辑的一次机会。重构确实要花一些精力,但是如果你不动他,那么你永远就是开着拖拉机跟赛跑,累死也不见效。算了,又水了一篇,哈哈,做为一只猿,码码字也算是本业啦。希望各位大神赐教。