技术团队中,财富即代码,但并不是所有的代码都是财富,有些代码可能是毒药。前段时间看到一篇文章,“你写的代码,是别人的噩梦吗?”,虽然标题针对我们技术人员来说,可能有点刺耳,但有时候确实是不争的事实。
在码奴圈,有一句话很流行:“能运行工作的代码就是好代码”。这句话没有对与错,在小的创业团队或人员能力不足的情况,能运行工作的代码确实是好代码,因为它解决了我们当时的问题。在对于有追求的技术人员来说,特别是在一个多人开发的团队中,产品功能在不停的迭代、优化,好代码就会我们的开发效率与维护效率带来成倍的提升。
何谓“好代码”,每个人的答案其实是不一样的。但说到“坏代码”,大家应该都能说出一箩筐来。
我先说一下我认为的“坏代码”:可读性差、业务逻辑相互缠绕、代码复用性低,这样带来的后果将是隐藏bug、团队其他人员调用或维护难以入手,更严重的可能就是重构。有时候可能陷入不停的重构循环当中去。原因有二:1.自己写的代码,没有重构到关键点上;2.下一个重构者与上一个开发者不分伯仲。
那好代码就是坏代码的反面:可读性强、业务逻辑低耦合高内聚、代码复用性高、有良好的可拓展性。
说了这么多,解决问题才是王道,如何才能按照上面说的好代码的目标开发,下面分享给大家一个容易入手的方法。
一、面向用例编程(横向):
1.先把系统按照功能进行划分,细化成多个功能模块。做到每个模块的功能是相对独立的,但也有可能一个模块与另一个模块有交互。
2.将功能需求进行抽象,达到高内聚、低耦合的标准,明确该功能模块的参与者是什么。
3.对每一个功能模块进行业务分析,看看是否能再按照子功能进行细分,细分后形成具体的用例。
4.对具体用例进行分析,理清用例与参与者的关系、参与者与参与者的关系、以及用例与用例的关系。
将功能需求划分成一个个独立的用例后,我们就能很清晰的表达功能需求的分离与组合。即先造一个个通用的轮子,然后对这些轮子按照业务需求进行组装。这样就能达到有良好的组件颗粒度,很好的满足了代码结构清晰、复用性强、组件可任意插拔、各个功能可以独立测试(单元测试)的目标。
面向用例编程的核心是把业务分解成一个个小的独立的case(解耦),在根据业务需求将相关case聚集、组装在一起(内聚)。最终又回归到我们经常说的低耦合、高内聚的目标之上。大到模块划分、小到函数定义,都是同样的方法。业务case集成一个模块,功能函数聚集成一个类。
面向用例编程也是封装的一种体现。将内部逻辑封装在一个盒子(case)里,对外只需要暴露接口。调用者也只需要关注接口,不关心底层逻辑。
所以在我们开发之前,进行业务建模,还是很重要的。
二、分层架构(纵向)
上面说的面向用例编程是从横向对业务功能进行解耦,那分层架构就是从纵向上对功能职责的划分。不论是后端开发、前端开发还是客户端开发,分层架构很普遍。通常我们会在纵向上对项目进行三层划分:展示层、业务逻辑层、数据访问层。MVC、MVP、MVVM都是为了更好的分层。
在团队成员中,经常会有人质疑分层,认为有时候明明是一个很简单的逻辑,非要搞几层数据转换,把结构搞的比较复杂。这个观点也没有错,在生活中能用简单的方法完成一件事情却故意把事情搞的很复杂,确实是多此一举。但我们通常是做一个复杂、庞大且不停迭代更新的项目,功能业务可能会像网状一样交织在一起。如果没有清晰的结构、各个组件各司其职,如何能保证多人开发的团队敏捷高效的共同开发,发现问题及时定位问题所在。
三、建立约束(规则)
约束即规范,团队成员按照一套统一的规范开发,尽可能的降低沟通成本(了解现有代码逻辑成本、业务调用成本、维护成本等)。约束包括一下几个方面:
1.命名规范:按照规范进行合理的命名,BEAN、ENTITY、DTO、API等都分别代表不同的标签或职责。看到名称就知道它能做什么事情。
2.分模块、分包:每一个组件或包都有自己明确定义的职责,不可以乱放。presenter包只放Presenter,config包只放配置文件等。
3.统一的结构:项目主体要统一结构,坚决不能出现相似业务不同代码结构,这样只会让参与项目的其他成员不知所错。
4.代码检查:如果有可能或有条件的话,通过工具或插件进行项目代码的检查,可以是静态的编译检查,也可以是动态的运行时检查。
总之,建立约束,就是让项目的参与者开发出来的代码尽可能的保持风格一致。
上面说了这么多,我们在开发过程中,只要代码具有低耦合、高内聚、可拓展、有良好的可读性,就是给团队创造财富。
一种MVP的实现方式,目标:代码高度复用、良好的组件颗粒度、方便进行单元测试,结构尽量清晰简单的高内聚低耦合的分层结构。