大家好,这里记录,我每周读到的技术书籍、专栏、文章以及遇到的工作上的技术经历的思考,不见得都对,但开始思考总是好的。
模式痴迷症
不知道你有没有这样的经历,在日常工作中,当我们进行代码设计的时候,或者在做代码review的时候,甚至刚开始聊需求方案的时候,经常就会有同学会给你说XX模式就可以实现了。
你说,这是好事,还是坏事。
如果你想体验软件设计的秩序感、设计的美感,设计的乐趣,那么亲自动手参加几次设计模式的实践,是一个很好能够帮你达成上述愿望的方式。另外,如果你曾经构思过或者遇到过通过使用设计模式得到的优秀设计,也一样能深刻体会其中的精妙。
但,凡事都有个度。
如果你在一个代码工程中遇到了遍地密布的模式,但是呢,设计却是很糟糕的代码,之前的那种模式带来的美感,便又会烟消云散,反而又会看到模式的可畏。
对,你过度设计了。
或者,反映到具体模式设计上,叫做模式痴迷。
所谓模式痴迷,就是指某人对模式过于痴迷,以至于无法不在代码中使用模式。
“陷入模式痴迷的程序员可能会费尽心力地在系统中使用模式,他们仅仅是为了实现模式的体验,甚至是想为了编写出的确优秀并且复杂的代码从而进行炫耀。”--《重构与模式》
来,一起看个”案例“,有一个需求,让我们打印一个Hello World进行输出。
好,写了下面这段程序。
大家都看懂这段代码了吧。
你确信明白需求了吗,这里的需求是要打印一个Hello World。
是啊,打印了,上面这段程序就是啊,你看我用了单例、工厂等,多有设计感,哦,还有内部类,增加了简洁性呢。
大家,在自己过往的工作经历中见过类似于上面的Hello World程序吗。
这段Hello World的程序很显然就是过度设计了,所谓过度设计,就是指代码的灵活性和复杂性超出所需。
最近我们在对几百个应用做梳理,大体上每个架构师都要识别出应用中需要改进的地方,并提供改进方案以及DEMO,但是呢,我们不能因为之前代码乱,不够美,就要进行过度包装,我们切不能从一个极端走向另一个极端。
混乱的代码会影响效率,过度设计的代码也同样会影响效率,比如你从其他人手中接收了含有一个过度设计的工程代码时,你是不是必须得先花一些时间来了解这样设计的许多微妙的地方,然后才能自如地扩展或者维护它呢。
这不也是在变相的影响生产效率吗。
我得坦诚地交代一件事情,其实,我自己曾经也犯过模式痴迷的错误,因为写出上述那样的Hello World程序,对周围的小伙伴很有震撼力,甚至在部门内还能收获几枚粉丝。
事实上,我们大多数人都是通过犯错误来学习的。
那,如何改正呢。
就是定期的回顾自己的代码,进行重构。重构的过程不仅仅是为原先的代码增加一些扩展性的结构,也可以是删去一些“冗赘的外衣”。
真正的模式之乐,来自睿智地使用模式。重构使我们的注意力集中在去除重复、简化代码和使代码清晰表达的意图上。
上面其实一直在说一个过渡设计的问题,我们每个人当初学习设计模式的时候,都想掌握一种灵活、精妙甚至非常优雅的面向对象设计方法,可有时候走过了,唯模式不编程,就是另外一个极端了。
那如果设计不足又会怎样呢,接下来我们谈谈这个话题。
设计不足又会导致什么呢
其实在我们的日常生产工作过程中,上面说的过度设计的经历是要比设计不足少的多的,也就是大多数情况下我们的设计是匮乏的,我们重构的目标也是为了弥补这种当时的匮乏。
下面是《重构与模式》这本书给出的设计不足的常见原因:
程序员没有时间,没有抽出时间,或者时间不允许进行重构;
程序员在何为好的软件设计方面知识不足;
程序员被要求在既有系统中快速地添加新功能;
程序员被迫同时进行太多项目;
这些都是活生生的现实。来一个需求,我就在原有的代码上堆一个功能,再来一个需求,就再堆一个功能,当时很快,业务方也满意,但是,你的软件开发节奏会逐渐变成“快、慢、更慢”,到最后很多业务方都涌到你身边,你的老板身边,开始要排期,开始投诉你。
1、系统的1.0版很快就交付了,但是代码质量很差;
2、系统的2.0版也交付了,但质量低劣的代码使我们慢了下来;
3、在企图交付未来版本时,随着劣质代码的倍增,开发速度也越来越慢,最后人们对系统、程序员乃至使大家陷于这种境地的整个过程都失去了信心;
4、到了4.0版时或者之后,我们意识到这样肯定不行,开始考虑推倒重来。
你不觉得这样代价太大了么。
怎么办,就是持续重构。
这次重构就跟修改过度设计下的代码的思路相反,去识别代码中那些贫血的设计,在上周的思考中我们引用了24种代码的臭味,如果再进一步概括的话,可以总结有下面七种臭味。
我们发现或识别的这些种代码臭味,常常是由于违反了一个或者多个设计原则而导致的。这里所说的设计原则就是SOLID原则。
这些原则都是数十年软件工程经验来之不易的成果,而且它不是某一个人的成果,而是许许多多软件开发人员和研究人员的思想和著作的结晶。
大家,可以大胆去使用这些原则来识别我们工程中的坏代码,我现在在我的团队就是这么做的。关于SOLID更多实践的阐述大家可以翻看公众号之前的技术文章。
以上是我们讲了侧重代码设计上的话题,比如设计原则,这个可能是算属于微观设计,还有设计模式,这个可能算属于中观设计,那么还有一种设计,服务之间的设计,这个可能算是宏观设计,接下来就让我们一起看看微服务设计。
你认为微服务设计中最难的是什么
有的同学,可能会发现,前几次一周思考系列文章中,经常来谈微服务。可能会说,这个话题早就不火了,何谓火和不火呢,微服务所包含的服务的理念,在之前的面向服务架构(SOA)时代就一直存在,未来也不会灭亡,以后它在我们的架构生产中不仅无处不在,而且大家还不会感知到它的存在,但它就是架构血液的一部分。
图自《微服务实战》1.4
大家做架构设计的时候都已很了解分布式系统,而微服务体现了天然的分布式特性,但分布式系统要比单体应用更加脆弱,你需要非常仔细且细心地考虑服务之间的通信,以避免可用性的问题,甚至是连锁故障。
但这还是微服务最难的地方。
我们今天要谈的是另外一个更难的话题,这个话题也是微服务设计中最困难的部分:如何决定服务的职责范围。
为什么说职责范围是最难的呢,我先从业务上来举一个例子,比如订单服务和库存服务,这是两个独立的服务吧,但是对于订单服务来讲,必须要考虑是否有足够的库存,不然就超卖了;另外一方面,对于库存服务来讲,要根据订单的增加来调整库存量,不然库存数也不对了。
你说你已经把订单服务和库存服务的职责分清楚了,现在它们不是还有联系吗。
这就是弱耦合的本质,我们从来没有说过不耦合,对吧,如果不耦合,那可能就是两个不同的公司了,如果一个企业业务系统要能够整体为用户提供服务,一定是耦合的,只不过呢,我们在做架构设计的时候,是奔着弱耦合的方向去的。
注:其实两个不同的公司之间可能也是有耦合关系的,比如接入微信登录,对接支付宝支付,它们都通过http接口在不同企业的服务之间进行通讯。
不知道现在大家对这个“最难”是否有了一定感觉了,如果还没有,我再结合自己深刻的切身体会,跟大家从另外一个层面来说一说。
鉴于我工作的职责,常常被拉进技术仲裁的讨论,说的接地气点,就是PK之中。这不是单体组织内,而是跨组织,因为每个服务的背后都可能是一个团队,那么在这个过程中呢,有时面临的还不仅仅是技术上的问题,还会有其它政治性的问题,不过呢,还好,今天我们只谈技术。
目前,根据我自己的认知,市面上有两本书讲微服务讲的非常好,大胆些讲,就是使劲看这两本书就够了。一本是《微服务架构设计模式》,另外一本是《微服务实战》,这两本书在我之前写的文章内容中都有引用过,《微服务实战》这本书呢,相比第一本,估计大家知道的占少数,大家可以重点读一读其中的第3章和第4章。
有的时候大家买书,看了之后觉得不值得,其实,大可不必这样闹心,我一直觉得只要哪怕有一句话让你高潮,就是值得。何况,我说的这两章都是这本书的高潮部分。
这个话题意犹未尽,后续思考系列继续。
恭喜你,又思考一次。
忆往期,还看今朝: