写代码,你以为的快方法,可能是慢方法

c53a86cdc864d481ffbc4bda641f8e84.png

周一来到,小明接手了一个需求。

要搞一次促销抽奖活动,奖池里配置了很多奖项,我们需要按运营预先配置的概率抽中一个奖项。

解决思路貌似很简单,生成一个随机数,匹配符合该随机数生成概率的奖项即可。

实现貌似也很简单。

很快,弄了两张表。

3e73e91dcc3616555ddf0c6a372501ad.png

很快,弄了三个类。

c662f049e31820cd47b17ab8760df7bf.png

41c528141123326ec8a29b599348b480.png

很快,搞定,上线,花费时间不到半天,小明很得意。

可是,需求变化也很快。

产品经理找到小明,规则变化了,要增加过去两个月内购买过10个订单以上的用户才可以参与抽奖。

小明应该把代码添加到哪个位置呢?

需求再次变化了,未来三天购买订单数满足跨店才能参加抽奖。

小明应该把代码添加到哪个位置呢?

即使后面来的两次需求,都找到了自己的添加位置,第四次、五次。。。呢。

每次添加新代码的时候,如何快速的定位?

开发完成后,测试人员要不要全回归测试呢?

毕竟你都改动到了好几处地方了,如果不全回归,以前的代码会不会有问题呢?

如果这样都做了,后面没增加一个需求变化,到底是快,还是慢了呢?

业务逻辑复杂了,业务的逻辑、状态会散落到大量方法中,你没有抽象,就没有办法模块化,就不能区分核心和周边,需求越来越多,你就只能硬写,你的这种硬写,往往都是写到了核心模块里面了,之所以成为核心,不就是希望你不要总是改变它吗,要尽可能将其变为只读的,否则,你当初的快就是后来的慢;

上面的编程方式是哪种方式呢,什么编程风格?

基于“Service + 贫血模型”的实现。

大家,为什么总是习惯用上面那种方式编写代码呢?

可能是业务简单到就是基于SQL的CRUD。

可能是在service层中可以定义任何操作。

可能是思维已固化。

可能是转型成本太大。

可能是。。。

如何应对变化,如何不让当初的快,变成后面的慢呢。

就是要千方百计地将核心模块和周边模块,变成正交性的设计,让核心模块变成只读,每次来一个需求只需要修改或增加周边模块就好了。

8c248a1107e1a4b059b95a7b21bf2a91.png

那如何才能一步一步实现正交设计的代码呢,最原始的基础就是要用丰满的面向对象技术,用丰满的面向对象技术的基础方法又是充血模型。

基于贫血模型的传统的开发模式,比较适合业务比较简单的系统开发;相对应的,基于充血模型的 DDD 开发模式,更适合业务复杂的系统开发;比如,包含各种利息计算模型、还款模型等复杂业务的金融系统;

应用基于充血模型的 DDD 的开发模式,需要事先理清楚所有的业务,定义领域模型所包含的属性和方法;领域模型相当于可复用的业务中间层;新功能需求的开发,都基于之前定义好的这些领域模型来完成;

越复杂的系统,对代码的复用性、易维护性要求就越高,就越应该花更多的时间和精力在前期设计上;而基于充血模型的 DDD 开发模式,正好需要前期做大量的业务调研、领域模型设计,所以它更加适合这种复杂系统的开发;

好了,小明也觉得使用丰满的对象编程技术,会比较好。

那问题来了,小明需要第一次,就按照这样的编程风格编程吗?

第一次就需要考虑那么的周全吗?

第一次就需要面向未来设计吗?

我个人的建议,你可以被子弹打中一次,但是不要被打中第二次。

为什么这样说呢。

4040f4b1c61bc182f1e41d5cc8fdd341.png

对这个图还有印象吗,整洁架构,向内依赖,最”内“里面是什么呢。

是个领域模型。

如果你第二次,第三次依然没有抽象出领域模型,你的每一次以为的快,都是为后面每一次的慢,埋下了“因缘”。

有没有好的策略,来指导如何判断要不要搞成所谓的领域形式呢。

个人建议:

1、判断是否你的程序只为一个业务方服务。比如财务人员要用到、营销人员要用到、运营人员要用到。如果是,就要提前考虑沉淀出业务领域模型。

2、判断是否你的程序只为一个业务模式服务。比如拼团业务要用到、国际业务要用到、健康业务要用到。如果是,就要提前考虑好业务身份的判断且抽象共享服务。

有没有好的原则,我按照这样的原则进行设计,进行开发就是能符合”高大上“的技术范的领域模型呢。

个人建议:

1、SOLID设计原则和23设计模式,优选SOLID设计原则。你问我为啥这样选,打个比喻的话,SOLD就像独孤九剑,23设计模式就像九阳真经。练招式起步容易,而且那些SOLID原则里面所包含的内容的内核,你只要”细思极恐“下,暂且用这个词语,一样能有一翻“洞天”。

练习独孤九剑也需要悟得。

当你可以将这其中的5个设计原则能够融汇贯通的时候,也是你的任督二脉打通之时。

85a4865b242b6cb426f6792378c051e7.png

当然,还有其它简单易行的原则,比如DRY、KISS、YAGNI、LOD等等。

2、增加辅助措施,没有规范,则显凌乱,若要有序,执行编程规范,同时把代码重构养成日常行为。

3e79bd80a0a0f68cd9fa73ef248e3eb1.png

小明想,思维建议策略有了,设计指导原则也有了,有没有代码让我学习一番呢。

如今,学习,最不缺的就是代码,看开源软件。

Tomcat程序就是非常优秀的开源软件,你不会不这样认为吧,你的程序打包都发布到它的容器里面了,这里面有非常优雅的设计。

试想,Tomcat这样的web容器是怎么样接收我们的http请求的呢。

我们的queryOrder请求为什么就被送到相应的动作上执行的呢。

Tomcat要为每一个请求都加一个if else来判断,才能实现不同动作请求到不同类文件上面吗。

如果都加上这样的if else判断,是要在业务类里面增加吗,那不就跟业务类耦合了吗。

因此,Tomcat的程序的设计者们,想了很优美的设计思路。

他们发明了 Servlet 容器,Servlet 容器用来加载和管理业务类。HTTP 服务器不直接跟业务类打交道,而是把请求交给 Servlet 容器去处理,Servlet 容器会将请求转发到具体的 Servlet,如果这个 Servlet 还没创建,就加载并实例化这个 Servlet,然后调用这个 Servlet 的接口方法。因此 Servlet 接口其实是 Servlet 容器跟具体业务类之间的接口。

736a0eddce77eb66e93783ee9cf24288.png

图自 李号双

这个设计里面,充满了浓浓的我们先前说的SOLID味道和正交设计的味道,你可以找出来吗。

只有当我们具备了,良好的开抽象维意识,开闭认知意识,原则学习意识,分合执行意识,实践到了,也就摸到了,我们写程序起初的慢,才是后续增加需求的快。

----END----

这里记录,我每周碰到的,或想到的,引起触动,或感动的,事物的思考及笔记。不见得都对,但开始思考记录总是好的。

与爱学习、爱思考、爱记录的你共勉。

参考资料:

https://tech.meituan.com/2017/12/22/ddd-in-practice.html 《领域驱动设计在互联网业务开发中的实践》 美团技术团队

https://www.cnblogs.com/wod-Y/p/12337721.html 《如何利用基于充血模型的DDD开发一个虚拟钱包系统》杨海星

https://time.geekbang.org/column/article/95480?cid=100027701 《你应该知道的Servlet规范和Servlet容器》李号双

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值