zoukankan      html  css  js  c++  java
  • (原创)谈谈架构师的职责(二)

      在谈架构师分内的事情之前想先谈谈为什么要做架构,这个问题其实挺有意思的,一种是被动的一种是主动的。被动的做架构设计是因为设计者内心并不太愿意去做设计,不愿意做设计的原因挺多的,比如,项目开发周期短,觉得没有足够时间去做设计。或者,认为设计很麻烦,除了UML设计、设计文档之类的还有设计评审什么的。或者,觉得设计没什么作用,属于浪费时间。或者,不懂设计,不知道如何下手等原因,不一而足。虽然内心不情愿,但由于一些外部原因,却又不得不去做设计,比如,是公司规范要求,有些公司是按照CMMI规范的,必须要有设计文档,或者,是领导要求做设计等等原因。总之,这种被动的设计会带来很多问题。

    1. 走形式,只是为了应付检查或者为了完成任务。这样可能出现一些比较奇怪的事情,先开发后补设计文档,往往是开发完成之后才写设计文档,我曾经就看到过这样的事情,这样导致的结果是,没有设计,设计只是为了生成一个设计文档。还有一种情况就是东拼西凑几个图和几段文字组成一个所谓的设计文档,这其实只是仅仅是形式上的设计文档,因为很多公司都找了一个所谓的标准的设计文档模板,设计者只要填充其中的内容即可,填充完了就是设计完了,这种设计文档模板和八股文非常相似。设计者或许都不太清楚为什么要这样设计,只知道按照八股文的作法去填充,只是因为文档要这些东西。这样导致的后果是,设计者迷迷糊糊,开发者更是不知所云,这样导致的结果是,设计是设计,开发是开发,二者没有任何关系,仅仅是为了完成任务。
    2. 本末倒置,设计的目的是为了梳理业务逻辑、解决开发过程中可能遇到的问题,使我们的开发工作变得容易,目的是指导开发,提高软件产品的品质。设计不是为了生成文档,不是为了应付检查或者完成任务,否则就是本末倒置,也失去了设计的意义。

      不愿意做设计的原因很多,但是最重要的原因是没有体会到设计的重要性,不知道为什么要做设计,以为设计就是几个图和设计文档,繁琐而无大用,心底是有些排斥的。为什么要做设计?这个问题很重要,很多人说我很少或者几乎不做设计,但是我一样完成了项目的开发,以此证明设计或者不设计都可以,是无所谓的。是的,不设计一样完成开发项目,这种事情很普遍,我看到不少项目,没有任何设计文档,因为根本就没有设计过,内部的对象关系如同蜘蛛网一样,而且随着新需求的增加,代码就变得更加混乱了,这样带来的后果是修改或者扩展都很困难,不能快速响应新需求。另外,别人维护时,很难看懂代码的意图,如果要了解其含义,不得不查看大量的代码,还不能确保一定理解了原来的思路,这样带来的问题是可维护性非常差,而且修改很容易破坏原有结构,使代码变得越来越难以理解和难以维护。这样的软件产品,表面上看似乎还在运行,但是内部遍布着坑,bug难以查找和解决,改了这里就错了那里,改一个地方还不行,还要改一系列的地方,直到某一天,发现这样做下去太痛苦了,不仅不能快速响应市场,原来的维护还很费劲,最后不得不推倒重来。我这里并不是说不做设计的项目一定会糟糕到这个地步,如果你的项目,虽然没有经过设计,却仍然运行得很好,那我可以说你的运气很好,也许是没有遇到需求的变更,也许没有遇到挑剔的用户。如果你做的好几个项目都没有设计仍然运行得很好,那我就只能说你对产品和业务真的很精通,开发即设计乃神人,我等凡人可望不可即也。但我仍然想说的是,如果你是凡人且继续根据经验主义不做设计就去开发的话,那迟早要栽跟头!

      为什么要做设计,关于这个问题我想以我的一点经历来说说,以前做过一个项目,这个项目比较小,正常情况下,两个人大概两周多就能做完,也许以为项目很小,能很快完成,就没有做设计,我觉得业务逻辑不复杂,能够在开发的时候设计好,于是直接就开始做了。项目是做一个统计库给前端使用,统计库主要是根据一些统计类型来统计,根据这个特点,开发时将每个统计类型抽象成一个统计类,这是个比较典型的策略模式,第一周做得还比较顺利,完成了60%,第二周的时候发现有个有个特殊的业务类型需要处理,这个业务类型可以嵌套多个其它的业务类型,这时,已经感觉策略模式就显得不那么合适了,但想着只是一个特殊情况,就特殊处理吧,在策略模式中再增加一些条件判断些用来处理嵌套统计类型,随着后面开发和测试不断的深入,又发现有几种特殊情况要处理,看着开发时间都过半了,也不愿意大改了,想尽快完成任务,于是,又是在一些策略类中加判断,导致本来可以复用的嵌套统计代码都不方便复用,调试起来也很不方便,最后回头来看,程序结构显得混乱,还有不少重复代码,没有美感可言,显得很丑陋,随着后面新需求的不断加入,代码已经变得难以扩展和修改了。

      为了不使代码继续腐化下去,就不得不停止开发,从架构上重构了。重构的时候我不再直接开发,而是先做设计,通过对业务流程进行分析,将业务的流程归类出来,充分的了解业务过程是什么样的,再结合业务流程图做用例分析,通过用例分析来确定我们的我们的系统到底有多少用例,用例之间的关系是怎么样的,最终画出系统的用例图。业务建模结束之后邀请产品人员帮忙分析,业务流程的归纳是否合理,业务用例是否涵盖了所有的用例。业务建模阶段使我完全明白了整个业务流程和细节,这为之后的设计带来非常大的便利。之后,我再根据前面的业务建模做系统分析,根据包的设计原则和单一职责原则划分组件,将各个组件的耦合性降到最低,组件划分好之后再进行类的设计。类的设计时考虑到要解决嵌套统计的问题,就不能再用策略模式了,改成桥接模式和组合模式,这两个模式结合起来可以完美的解决嵌套统计的问题,关于他们结合的细节可以参考我前面的介绍:composite模式和bridge模式是天生的好朋友。这个设计大概花了将近一周时间,不过这个设计只是UML设计,不包括设计文档,因为时间比较紧,UML设计文档转换为word设计文档的工作并没有做。在UML设计完成之后就开始开发了,开发阶段非常顺利,开发时间实际上只花了一周时间。重构后,整个架构非常清晰,由于都是单一职责的,没有重复逻辑,修改起来也很方便,且完全可以灵活的应对新增需求,符合开闭原则。

      也许有人要说,这是由于我没有深入了解业务导致设计不合理的导致的结果。是的,是我没有深入的学习业务,在开发阶段草率的做出了不成熟的抽象和设计,导致后面特殊业务规则出现时,不能适应变化。但是,这个问题其实完全可以在设计阶段就可以发现,从而可以避免在开发过半的时候发现问题而大改。如果一开始就做设计,然后将设计推销给产品工程师,推销给开发者,很多问题就能及早发现,而不是边开发边设计,导致不能从整体上去把握。边开发边设计,往往还导致头痛医头脚痛医脚,结构混乱,使开发变得困难,最后还受限于开发时间而不得不沿错误的方向走下去,最终做出一个失败的产品。

      很多时候我们不可能一下子就了解全部的业务,这需要一个学习和消化的过程,而设计阶段就是将业务变为软件实现的过程,这个过程是业务的充分消化吸收的过程,这个过程如果顺利通过,则后面的开发就会变得非常容易,因为设计到类图了,而且在设计阶段将已经将绝大部分问题都解决了,剩下工作只是如何完成这些具体的类而已。这个经历给我很大的启示,哪怕是一个一两周的小项目也要做架构设计,因为设计可以帮助我们梳理业务逻辑,避免因为业务逻辑的不熟悉而导致的不合理的抽象和归纳,不合理的抽象会导致架构不能应对正常的变化,还难用,开发也变得不顺利,轻则导致开发延期,重则项目失败。

      关于设计的目标,架构设计看似耽误时间,实际上为了将业务逻辑合理的组织起来,解决开发阶段会遇到的问题,并最终指导开发顺利的完成。如果设计不是用来指导开发,或者对开发来说没有作用,甚至起反作用,那么设计对于开发来说就是无用的,这个设计做得也是失败的,是浪费时间的。设计是为了解决开发过程中会遇到的问题,并最终指导开发的,如果没有达到这个目标,那么这个设计就是失败的。

      关于设计的时间,以我上面的那个重构项目为例,设计花了一周时间,本来按照正常的开发周期来说,一周时间肯定是不够的,因为除了UML分析之外还要编写设计文档。但是由于项目很小,且开发周期很短,我就只做了UML设计,然后后面的开发都是依据UML设计去开发的,UML设计转化为文档的工作就省掉了,这节省了不少时间,这样做是否合适呢?我觉得在一定程度上是没问题的,因为UML设计本质上就是已经完成了的架构设计,一图胜千言,UML图本来就是程序员交流的介质,方便开发者交流和理解,也能方便的指导开发,仅仅做UML设计对于项目开发来说没问题,不过对非专业的技术人员来说可能显得过于抽象和难懂,这时才需要将UML抓换为word文档,通过文档详细解释UML设计。架构设计看似慢,实则快,不管项目多小,都要做设计,好的设计不仅可以指导开发还可以加快开发,是非常有必要的。

      关于设计和文档,有很多人将二者混淆起来,认为设计就是文档,其实二者不是密不可分的,关键是设计,文档是对设计的解释和描述,架构设计的精髓在于UML设计,通过几张UML图就能清晰而深刻的表达设计思想,一图胜千言,设计不是为了生成文档,文档只是设计的结果而已,很多人本末倒置,以为像八股文一样填充好设计文档就是完成了设计,这是非常错误的想法。我更喜欢看UML图而不是看文档,因为文档啰嗦半天都赶不上一张图直接。开发人员应该通过UML设计文档而不是word文档来开发,UML设计简短而直接,一来可以清楚的知道自己所开发的东西是整体架构的哪一部分,该如何开发;二来可以更深入的理解架构,减少破坏架构的失误。

     未完待续...

  • 相关阅读:
    [LC] 347. Top K Frequent Elements
    [LC] 659. Split Array into Consecutive Subsequences
    [LC] 430. Flatten a Multilevel Doubly Linked List
    [LC] 271. Encode and Decode Strings
    [LC] 373. Find K Pairs with Smallest Sums
    [LC] 1048. Longest String Chain
    [LC] 297. Serialize and Deserialize Binary Tree
    ubuntu 创建 PyCharm 桌面快捷方式 (或者叫 启动器 )
    scala private 和 private[this] 的区别
    %s %r 区别 转
  • 原文地址:https://www.cnblogs.com/qicosmos/p/3705689.html
Copyright © 2011-2022 走看看