如何写好代码

一、软件生命周期

代码是最容易写的,因为随便怎么写,只要符合语法就能够运行起来,代码也是最难写的,要想让代码容易维护,还要和业务一起长大, 使得软件架构容易随着业务的长大做出新的拆分、合并,并要保证正确性。同时达到这么多的要求是非常困难的。

软件生命周期中有两个最主要的子生命周期:软件开发生命周期和软件运行生命周期。其中,软件运行生命周期是核心生命周期,软件开发生命周期是为软件运行生命周期服务的,所以软件开发时必须要考虑到软件运行生命周期的特质,这一特质也决定了代码应该如何组织和编写。

软件实际上是对现实业务的模拟、虚拟化。结合软件的核心生命周期,也就是运行生命周期,可以看出软件主要是完成对业务生命周期的模拟,在此基础上完成用户的访问生命周期,使得用户能够到达模拟的业务生命周期。因此,代码主要由两部分组成:

  • 1、表达业务生命周期的代码。
    很多人把这部分叫作业务逻辑( Domain Logic)或者叫业务模型( Domain Model )。这部分是来源于生活与业务, 必须和现实生活及业务保持致,忠实于现实中的业务。
  • 2、表达用户访问生命周期的代码。
    软件的核心生命周期就是为用户提供对业务的访问,使得业务逻辑能够服务于用户。而为了让用户能够访问到所模拟的业务逻辑,则必须要提供访问通道。表达访问生命周期的代码就是业务生命周期对外的访问通道,软件的核心价值通过这部分代码展现出来。

二、软件代码由三个部分组成

图一

要模拟一个完整的人,就需要业务(Busines )部分来实现业务的逻辑,完成对业务生命周期的模拟。业务的状态要靠存储(Repository)来存储持久化,相当于现实生活中的文件柜。

那服务(Serice )是用来做什么的呢?

首先,由于计算机和软件没有自己的意志,因此其内部生命周期的变化就要由外部的人来推动,这时需要提供个访问通道给外部的用户。但如果把业务直接给用户访问,那么用户是很难和业务沟通的,因为这些专业术语,不是用户所能够理解的。 比如客户去银行,接待客户的是更接近用户语言的银行柜员,而不是银行内部的专业业务人员。柜员就是一个服务,以用户听得懂的方式和用户沟通,并把用户的要求转换为业务的语言,再由银行内部的专业业务人员执行相应的操作,柜员最后把执行的结果转换为用户的语言,为其服务。所以在这里服务提供的就是一个访问通道,为用户提供个容易访问银行专业服务的访问方式。

另方面,企业为了接待用户的访问,一定会设个前台。 客户对企业的访问由前台来接待。这样做的好处是,可以防止内部业务人员的工作被外部的访问随意打断,使得内部业务人员可以专心自己的本职工作。如果总是被外部访问打断,业务人员的工作效率就会非常低。此时,这个前台就是一个服务。

最后,不同的用户访问,也要提供不同的服务,以避免不同的用户之间相互影响。比如银行的柜员,对VIP和普通用户就是不同的通道。

服务作为一个通道的含义是什么呢?通道的意思就是不包含业务逻辑。这意味着软件工程师所写的服务代码中是不能够包含业务逻辑的。

从上图可以看出,服务为完成用户访同生命周期,承担的责任包括了组合业务和存储这两个,还要提供给用户访问。这部分的代码任务太多,代码人员的负担比较重,也容易引起服务的代码失控。为解决这个问题,需要把用户访问生命周期再展开分析下。 用户要完成访问业务逻辑生命周期, 需要做如下事情:

  • 服务首先要把业务的状态从存储中加载。这是一个生命周期,主体为业务状态获取;
  • 服务调用并组合业务逻辑完成业务的访问。这是个生命周期, 主体为业务访问;
  • 服务把业务逻辑执行后的状态保存到存储中。这是个生命周期,主体为业务状态保存。

也就是说服务访问业务逻辑的生命周期可以拆分为三个子生命周期。这三个子生命周期中,服务调用并组合业务逻辑完成业务访问是核心生命周期。所以服务还可以继续进行拆分,只保留组合业务逻辑即可,而状态保存则交给单独的组件,就形成了以核心生命周期为主轴,非核心生命期围绕核心生命周期的树状架构,Service -->Glue Code -->Business是核心生命周期,也就是树干,这样存储可以独立应对其变化,服务可以独立应对用户的需求变化,黏合代码(Glue Code)负责从外部存储加载和保存业务逻辑的状态,把业务逻辑包装成具备记忆能力的虚拟人,供服务进行组合调用。

黏合代码是什么意思呢?业务逻辑属于行为是没有记忆的,而存储属于记忆是没有逻辑的。要把行为和记忆黏合在一起,才能够模拟一个人。 因此黏合代码只有做到了这一点,对外才算是一个真正的虚拟人。服务作为通道把黏合代码和用户联系起来,成为了业务虚拟人和用户的桥梁。这和银行的柜员作用是一样的,这就是现实生活如何在软件中实现模拟的。

代码拆分之后,每一个部分都能够独立地变化。用户需求的变化、业务的变化和存储的变化,互相之间就不会产生连锁响应,并可以提升开发的并行度。如下图所示:


图二

三、什么叫业务逻辑

根据以上的代码分工可以很清楚地看到,业务中的代码是最重要的,代码是系统的核心。服务与黏合代码中的代码起通道作用,这是为了让用户的请求能够方问到业务代码。因为真正干活的是业务代码,所以服务和黏合代码中的代码都是访问逻辑。而业务中描述的都是业务的生命周期活动,也就是人们通常所说的业务逻辑。

访问逻辑的特点是组合代码,即常见的顺序调用。这种代码里既不会有计算也不会有if else等判断,只有简单的组合代码,用于组合下层的节点所提供的功能,方便上一层节点的调用。

四、业务逻辑分散的危害

如果业务逻辑不是内聚的就会散落到很多其他地方去,比如散落到服务代码、黏合代码或存储代码中,这会造成哪些问题呢?如果服务代码中混人了业务逻辑,则服务做了两件或者两件以上的事情。典型的情况就是两个不同的访问生命周期合并在一个服务中实现。

比如两个不同类的用户共享一个服务方法,并在服务中判断区分这两类的访间分别处理,这就是人为造成的不必要逻辑。一且某个用户访同生命周期发生变动,共享的另一个访问生命周期的执行就必定会受到影响。被影响的用户访问生命周期自己是不会跳出来说的,因为软件逻辑没有自己的意志,需要用户推动才可以。往往只会等到上线之后,最终用户推动访问生命周期活动时,发现受影响了才会显现出来,此时已经造成生产事故了。

如果有足够的责任感,也会主动去沟通所共享的其他生命周期是否受影响。可是其他共享访问的责任方并没有动力来配合,何况有可能还会给自己增加工作量。这就形成了权责不对等,导致发现问题的沟通成本非常高,因此最后都是不了了之,等待生产事故出现来教训大家。

最可惜的是即便引发了生产事故,责任方还是意识不到这个问题是因为共享了访问通道面造成的,导致类似的问题一面再再而三地发生,修改代码也变得战战兢兢,大家都疲惫不堪。

这就是为什么不同用户的访问通道一定要隔离,不能重用,不能互相影响。必须把这个服务代码拆分,把不同访同生命周期主体的访问通道分离,确保每个服务只做一件事情, 只为一类用户提供通道,确保不同用户的访问生命周期之间没有共享,保证用户访同生命周期本身的内聚,确保不同类型用户的访问通道是独立的。

拆分之后,用户端就要自行组合不同的服务来完成自己的执行流程。如果不拆分的话上线后会出现很多不可预料的问题,最终会因为用户的利益受损而返工,从而也损害了自己的利益。很多软件工程师上线时会没有信心,大部分原因就在此。

五、代码误解

服务代码、黏合代码和存储代码不能有逻辑,很多软件工程师在实际的操作中非常不理解。要么认为这个根本做不到,要么认为增大了工作量。

做到这一点确实需要很多的学习成本,特别是要克服对业务的恐惧。我的游泳教练曾和我说过这些话,令我至今都记忆犹新,大意如下:“业余选手要确保呼吸,总想把头抬起来,身体反而沉下去。只有克服呼吸进水的恐惧,把头往水里压下去,身体才能够从水里浮起来,这样才能真正确保呼吸。真正专业的习惯往往与人们日常的反应相反”。如果真正想快速地完成代码工作,就要克服自己对时间的恐惧,真正的去研究业务的核心生命周期,研究相关利益人的利益,把这个变成日常的习惯。写代码的时候让该出现逻辑的地方出现逻料,让不该出现的地方不要出现。而一旦不该出现的地方出现了逻辑,就要马上采取行动纠正过来。

摘自《聊聊架构》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351