编程心智(一)——代码架构与系统架构

写在开头的话

想写这个系列文章很久了,但是对于一个重度的拖延症患者来说,决定写一个系列文章还是颇有挑战。最开始,只想写一两片文章分享一下自己对于编程的感悟。但随着时间越拖越久,发现想写的东西越来越多。直到今天,居然发现我的博客的To-Do-List(目前我在使用WunderList,很好用的一个To-Do-List工具)文章数达到了10篇,终于说服自己动笔了。
“编程心智”这个词这段时间一直萦绕在我的脑海中,我觉得这个词最能表达我想分享了内容了。我希望通过这个系列文章分享自己对于代码、编程、架构以及软件工程的理解与感悟,另外,还有隐藏在代码后面的程序员心智。所有文章仅代表个人观点,没有是非对错的标准。如果你对文章中的观点不认同,还请给我留言,不同的声音对于进步有着极大的促进。

选择“代码架构与系统架构”作为第一篇文章是因为我发现很多人对“架构”的误解很深,而且国内关于“代码架构”的分享和书籍凤毛麟角,似乎只有流弊的“系统架构”才能成为谈资。我不太能理解这个现象,好像大部分人都完全不用操心“如何写好代码”这回事,似乎只要有一个看上去比较“完美”的系统架构就能解决所有的事情。但根据我的实际经验,现实情况往往不是这样,有时候甚至相反。有些项目的系统架构图画的非常“漂亮”,引入了很多新潮的技术,每个组件都划分的很清楚,系统之间如何通信,模块之间如何引用等等都一目了然。但是当你去看项目的真实代码时,完全是另外一番景象。至于为什么会这样,我想很大一部分原因是“系统架构图”已经沦为了一种满足KPI考核手段,而通常你的老板不会深入地去理解你的代码,更不要说指出其中的问题了。

系统架构

相信很多人对系统架构都不陌生,只要是从事软件开发领域的人,或多或少都接触过系统架构。系统架构最直观的表现就是系统架构图,下图就是一张系统架构图,摘自李智慧老师大型网站技术架构:核心原理与案例分析

部署架构图

系统架构是一个比较大的概念,从技术角度来看,它往往以部署架构图的形式出现(上图就是);而换到业务视图,它又以另外一种形式出现,如下图。

业务架构图

不论是部署架构图还是业务架构图,它们都反映了系统与系统之间的一种关联关系,从更加宏观的角度反映系统在全局中的作用和定位。如果你是某个系统的开发者或者负责人,那么你的系统会在系统架构图中以一个方框出现。通过系统架构图,你的老板和同事能很直观地了解到你的系统在全局中的位置以及你服务的层次。这样做有好处的,它降低了技术人员之间以及技术和业务人员之间地沟通成本。

实际上,关于系统采用什么样的中间件、何种数据库和缓存、选用哪种服务框架等等,甚至今年非常火的微服务架构,这些统统都属于系统架构的范畴。关于系统架构方面的书籍和文章已经非常多了,而且国内的分享也主要集中于此,我就不再这方面展开了。

代码架构

相比于系统架构,代码架构对很多人可能就陌生许多。我刚刚去Google一下,发现甚至没有关于“代码架构”的权威定义。那么什么是代码架构呢?打个比方,如果你的系统在系统架构图中只是一个方框,那么代码架构就是介绍这个方框是如何组成和实现的。代码架构的关注点在一个工程(Project)内部,它描述了你的整个工程代码是如何组织和实现的。简而言之,系统架构是宏观层面的体现,而代码架构是微观层面的体现。

在我的博客中有很多关于DDD的文章,而DDD本身就是一种代码架构。除此之外,还有MVC、CQRS、Event Souring等等。那么,设计模式是否也可以成为代码架构呢?在某种程度上是的,因为它可以指导你如何组织代码的实现,如何在代码层面解耦,但是,光光通过设计模式你无法组织起你的整个工程代码,所以从严格意义上讲,设计模式并不是一种代码架构。代码架构也可以通过图文的形式表现,不过这完全取决于你采用何种代码架构。下图是我目前负责的一个系统的代码架构,这个系统的核心在于策略语言(Policy)。

六边形架构

熟悉DDD的人一眼就可以看出来这是DDD种的经典六边形架构(题外话,至今我不太明白为什么是六边形)。如果你的工程采用MVC或者CQRS架构进行组织,可能会画出完全不一样的架构图。我很庆幸,在我正式的职业编程生涯的早期接触到了DDD这种编程思想,它对我的编程生涯影响很大,让我少走了很多弯路。如果你还没有接触过DDD,我希望你能立马买一本Eric Evans领域驱动设计:软件核心复杂性应对之道,细细研读此书,字里行间都体现着作者对软件开发的深刻理解。

为什么我说代码架构是如此的重要?是因为其奠定了大型系统的基石。我认为衡量一个优秀的程序员的能力之一就包含其对复杂问题的解决能力。现实的问题往往比理论复杂很多,很多时候需要妥协、折中、权衡和取舍,如何在这些取舍之中不影响到软件的核心,这需要大量的经验。当然,这是有规律可循的,那就是代码架构。

好的代码架构会帮助你理解你的业务,哪些部分是你系统的核心,哪些部分只是技术层面的实现。换句话说,好的代码架构不光能知道你如何去组织你的代码,还能加深你对系统的理解。反过来,随着你对系统理解的不断深入,你又能更好的调整你的代码以适应新的变化。是不是所有的项目都需要代码架构呢?这取决于你的问题域。如果你的项目仅仅是一个Hello World程序,又或者是一个数据采集脚步,那么使用代码架构来组织代码可能没什么作用,反而使得你的代码变得更加复杂和臃肿。那么什么情况下你需要使用代码架构呢?我认为只要满足以下两个条件就行。

  • 你有一个相对固定的业务场景。固定意味着你要处理的问题域是有边界的,比如订单系统、库存系统、用户中心等等,它们所要处理的问题是比较集中和固定的。

  • 你要解决的问题相对比较复杂。这看上去本身就比较矛盾,因为“复杂”本身就是相对的。这里的复杂的意义在于,你要处理的问题领域本身就具有复杂性。也许起初问题本身并不复杂,但随着时间的推移,系统要处理的问题也越来越复杂了,这要求你对问题有一定的前瞻性。

事实上,上面两个条件是很容易满足,之所以还列出来因为在实际的开发过程中,我确实遇到过在以上两点犯错的情况。这主要出现在刚刚开始正式编程生涯的毕业生,他们对业务和要做的事理解程度不够,如果有经验丰富的程序员带的话,可以避免走一些弯路。正是因为上诉条件门槛较低,所以代码架构的应用场景非常广泛。有可能你现在的项目就在使用MVC架构,只是你没有意思到。我建议程序员能有意识地去了解你的代码架构,深入的思考一下目前的代码组织方式是最为合理的吗?

小结

说了这么多,希望自己把代码架构和系统架构的核心点说明白了。两者都非常地重要,但是应用的场景各不相同,两者结合使用才能让你做出一个高质量的系统。相比于系统架构,代码架构往往被人们所遗留,但这并不代表其不重要。依我之见,代码架构的应用场景更为广泛,因为大部分的公司和项目其实并不需要一个复杂和“高大上”的系统架构,而与我们日常交互最多的就是一行一行的代码。深入的了解你的项目代码是如何组织对程序员来说是十分重要的,好的代码架构能起到事半功倍的效果。最后,个人建议将代码架构纳入到KPI的评判之中,最为直观的表现就是“技术债务”。好的代码架构会把项目的技术债务维持在一个比较低的水平;相反,糟糕的代码结构会让项目的“技术债务”越滚越大,最终到了不可收拾的程度。不过,技术债务如何量化,以及是否需要量化,目前这方面有着很多不同的身影,但是,能意识到这个问题的存在,至少,我们在向高水平的软件开发者迈出了一大步。

写在最后的话

编程心智这个系列我会持续地更新,但更新时间就不确定了。前面也说了,我是一个重度的拖延症患者,而且,最近项目的事情很多,一个接着一个。我会努力做到一个月一篇的。

坚持原创技术分享,您的支持将鼓励我继续创作!