记录在应用软件架构方面的认知成长

83 阅读10分钟

背景

这周和以前团队的外包兄弟吃饭,他说他要换团队了,有些惭愧,他是我担任组长的时候招进来的,我们在一起工作有三年,后来因为一些原因,我换团队离开了,以前团队的兄弟们也都各奔东西,相比之前的境况要好,而不多的几个同事还在原团队,也都混的比较好,只有他因身份的原因,即使付出再多,也没啥更好的经济提升。

往事回想很多,又收了回来,我想问问他现在负责的还是之前的业务吗?当时经过我们开发的那个版本后,接到后续需求的时候开发过程有受到什么阻力吗?(主要是想了解下会不会因为软件架构原因,导致开发难度很大),所以就有了下面的对话:

我: 为什么会想换团队?
他: 主要是现在负责的业务干的没意思了,而且团队为了提效,把很多工作都安排到了他一个人头上,有时候刚要写代码,就有人找过来沟通,干的很累。
我: 是负责的业务比较难吗?
他: 倒也不是,现在负责的业务的主体架构还是当时202x年的时候的架构,很多需求在原来架构上都可以开发,现在每次开发都是考虑业务逻辑,技术上不是很难,一直重复这样的需求工作,做着没意思,没有之前有收获。

和他聊到这里,我舒了口气(心想当时我们干的还是很可以的,哈哈),在心里也祝愿他在以后的新团队能越来越好。

记得那年,团队一起做需求,那时候的我还比较青涩,接了一个工作量比较大,同时也是产品卖点的需求。第一次负责这么大的需求,心里有些激动,心想着终于可以一展拳脚了。

在这个过程中,我是第一次完整负责软件架构设计,从整个工作过程中学习到了思考问题的系统思维,受益良多。

认知

在进行比较完整的软件架构设计之前,我理解的软件架构设计是画各种高大上的框图,比如下面的这些: image.png

在经历过之后,我理解到了架构图其实并没有固定的形式,它是在软件架构设计过程中输出的一部分,通过它,尚未开发需求的的开发人员可以快速理清软件的整体脉络,但是软件架构并不止架构图,好的软件架构设计是需要可以实际指导到开发

画架构与盖房子存在不同。在没有进行过比较复杂的软件架构设计的时候,我以为架构设计就是把架构图画出来,然后网上的架构图比较多样,对于实际的架构设计,很难有指导性。

在我进行架构设计的过程中,结合公司内的业务流程及在深入主导业务架构设计,逐渐总结出来了一点经验(本文主要是依据DDD架构思想:领域驱动设计Domain-Driven-Design)。

第一步,明确产品需求。与产品沟通清楚需求(这个阶段需要反复沟通),进行需求的串讲与反串讲,这个过程中需要邀请上相应的开发人员和测试人员,这样可以最大程度的保证对需求的理解没有出现纰漏(比如软件的功能性指标的明确,有些产品可能只想到具体的功能,未考虑到产品功能性指标,需要在这个沟通阶段根据各方输入敲定下来)。

image.png

第二步,理清所有外部依赖,明确理解了在开始做需求的架构设计时,作为主责“软件设计师”(我喜欢将架构师称为软件设计师,这样感觉更贴切一些),首先需要识别当前业务与外部业务的关系是怎样的,是不是存在依赖与被依赖关系,外部业务与即将开发业务的哪些功能是有相关性的。(这里假设以QQ的频道功能为例,进行一步步的软件设计实践,本文仅简单示例,实际的QQ频道业务应该是相当复杂的)

image.png 在这个设计阶段中,是需要将新增需求的所有外部依赖关系确认清楚,输出可能是一个框图,在表明当前软件的内部大体结构前提下,绘制出软件中新增的业务(图中黄色框表示);同时绘制出所有的外部依赖(图中绿框表示);另外,需要标出数据流转关系(图中虚线箭头表示)。

第三步,理清新增业务与其他内部业务关联关系,识别出了本业务与外部业务的依赖关系之后,接下来需要做的事情就是理清本次需求会设计哪些独立的功能域,它是从属于已有业务内,还是独立的新业务,如果是从属于已有的业务,这时候就需要确认它与已有业务的关联关系是怎样的,数据是如何流转的。此时才可能会涉及到绘制分层架构图,其实无论什么形式的架构图,我觉得比较重要的是明确出业务内各个独立功能之间的关系。

image.png 在这一步中,需要将框图画细,将存在业务关联的本应用的其他业务也绘制出来,并通过可分辩的线段,标注出新增业务与其他已有业务的关联关系。

第四步,业务内部拆分,如果新增业务复杂,还需要对新增业务进行内部拆解,如果在第三步设计时,已经理清了当前应用各个独立功能之间的关系,那接下来就需要确定各个功能内的设计,需要的数据结构,独立功能要应用的架构模式(MVVM),这里需要详细到具体到会新增哪些类(Activity,ViewModel,Model,Repo,data class等),如果其中存在复杂的业务逻辑,需要软件设计师在架构设计文档中写出复杂业务逻辑可行的伪代码。

image.png 这里我做了简单的拆分,实际上如果按照前面的步骤一步步执行过来,在这个阶段会拆的更细,我在这里就班门弄斧了。

那对于单个功能域而言,应用软件开发中经常提及的MVVM、MVI等就可以适用了,当然如果在在对新增业务进行拆分时,发现有些业务的核心逻辑比较复杂,比如频道搜索,它可能涉及到非常多的情况,比如:

  1. 输入内容解析(可能输入的是乱码,也可能输入的是敏感词等)
  2. 搜索过程(经历缓存、内存、网络等多个阶段)
  3. 展示(展示排序逻辑) 以上这些情况如果觉得有必要,需要在设计阶段将对对应的关键逻辑输出出来,避免在开发阶段存在争议,重复讨论。

第五步,单元测试设计,需要涉及比较合理范围的单元测试,在需求开展前确认出哪些逻辑是可以进行单元测试的,这比较重要,试想一下,如果开发前对重要逻辑确定好输入以及预期的输出,并以单元测试进行校验保证,那么到了实际的逻辑开发阶段,就可能避免因关键逻辑功能异常而出现的功能实现错误。

第六步,安全设计,比较重要,但是经常忽视的安全设计,这里可以参考行业内的一些软件安全核查项,对于已设计的架构逐项进行软件安全确认,对于可能存在的风险点,如果是业务必须,则需要设计出相应的安全方案,比如对于网络传输数据做加密(这里又会涉及到哪种加密算法安全高效的问题),在这个阶段,比较重要的是,应用设计师需要与后台架构设计师不断沟通对齐,确定下需要新增的接口以及新增的数据结构。

第七步,兼容性设计 不同android版本的兼容性,不同硬件的设备,不同地域使用,不同网络环境等

第八步,可测试性设计

第九步,将设计出来的软件架构与各个业务进行评审沟通,敲定一份大家都认可的软件架构设计。

第十步,参与到关键的需求开发中,和兄弟们一起进行开发,这样才会让大家接受你,不觉得你是一个只会画图,没啥技术的架构师。同时在实际编码过程中,也会发现自己在软件设计上的问题,不断的修正,提升自己。

思考

现在回想起来,第一次做大的软件架构,还是把事情想的太简单了,但是也很感激那次机会,有机会去尝试,在后面又及时做了架构优化,让后来维护的同事收益。

非常感谢那次契机:

  1. 刚好遇到旧业务改版
  2. 有试错机会
  3. 自身也参与其中进行开发,和兄弟们关系更近了,成就了别人,自己也得到了成长

最近的一年内,我的大部分工作内容是在帮助各业务进行细节优化,这个过程也是异常痛苦和收获很多的,一方面,我了解的是通用技术,而各个业务遇到的实际情况各不相同,在与相应的开发沟通时,也发现业务责任人深陷需求之中,无暇顾及技术,很多代码中看似使用了MVVM,但实际上仅仅是定义了名为XXXViewModel的类,需求排期很满,开发人员吐槽做需求是在“屎山拉屎”,没谁敢去动现有的架构,生怕脱不了身。

我也尽力在不影响当前的主要工作的前提下,为他们提供一些帮助,其实作为开发人员,他们也知道需要对现有业务做及时的架构优化,可惜工作安排上不会留出这个时间(这也可能是整个经济下行的情况下,各个公司优化提效后的现状)。

之前和我的leader聊,他的思想就很启发我,他觉得作为技术团队,是需要有自己的技术竞争力的,而只交付需求,显然是无法积累出这种技术竞争力。这需要合理的工作安排,一个团队中既需要开发需求的人,也需要关注技术的人,这可以作为主管的绩效考核的组成部分,这样就会在工作安排时预留出人力。

成长

在软件开发领域,思想是格外重要的,这并不是说技术深度的挖掘不重要,我当时就是在软件设计的过程中慢慢顿悟,得到了成长,后来用这种思想去看优秀的开源框架,新的业务代码,很快可以掌握到其中的关键。

在业务重合度比较高的今天,一个技术团队如果需要持续保持技术竞争力,在完成日常的产品需求外,还需要考虑对现有业务做技术优化。而做在开始进行技术优化时,不妨从整体出发,利用软件设计的思想,层层剖析,把握软件层级的关键,这样的一次技术优化可能会很难,但应该会让人成长很多,当然,一切的前提是老板觉得这个工作有价值。