先讲一个小故事,张三是一个程序员,在金九银十的季节去了一家新公司就职。新的公司看起来前景不错,做的内容也是行业前沿的产品,张三发誓自己要在新的公司一展宏图,用自己精湛的开发技术为公司的上市添砖加瓦。
就职的第一天公司开放了代码的权限,张三迫不及待的熟悉起了公司的核心项目。
然后,心凉了半截,公司的项目就像是一个垃圾场,各种恶心的代码堆成山。他要做的事情,就是去维护这些老项目。在那一刻,张三内心的幻想瞬间破灭。
在维护了一段时间屎山项目之后,事情似乎出现了转机,终于有一天,有一个新项目下来,老板任命张三是负责人,全权负责这个全新的项目,张三内心狂喜,终于可以证明自己了。
“我一定要让代码显得优雅,跟烂代码说再见。” — 张三
刚开始非常顺利,张三用了各种设计模式,疯狂抽象业务,越做越有劲。感觉一身的才学终于有了展示的机会,那种爽快的感觉无语言表
但是项目是多人合作的,随着时间的流逝,项目的迭代,很多新人开始不按照预定的规范来开发代码。
为了图方便,微服务如雨后春笋般一个个往外面冒,在代码里面毫不犹豫地填充了一个又一个if语句。
张三本能的觉得不对,他开始手动的限制那些不符合规范的代码提交。可是项目时间的压力越来越大,张三终于迫于交付压力放开了限制。
项目顺利的交付完成了,但是奇怪的代码缺永久的留在了项目中。
慢慢的,原始的精美的设计开始变得越来越臃肿,逻辑变得复杂无比。
没有人敢去重构,也确实不可能重构了。
终于,张三实在无法忍受,在金九银十的季节辞职去了一家新公司就职,新的公司看起来前景不错,做的内容也是行业前沿的产品,张三发誓自己要在新的公司一展宏图,用自己精湛的开发技术为公司的上市添砖加瓦…
这样的故事在互联网行业内一遍一遍的发生,似乎任何项目随着时间的演进,一个个补丁打到最后都会变成屎山型项目,充斥着各种历史遗留问题,新功能开发越来越慢,最终无法演进走向项目的终结。
有些互联网公司会为了延长这个项目的生命周期,在某个节点聘请资深的软件架构师,他们往往熟读《重构》,用各种各样的技术手段去延缓这个过程。具体可以延缓多久,基本得看架构师的水平。
最近我在网上冲浪的时候发现了一个叫做"产品架构"的概念,再结合曾经做烂的一个个项目,忽然有了些许感悟。
研发人员习惯用技术解决问题,但问题的解法是多样的,或许从另一个角度切入,会有新的解法。当然,无论用什么方法,归根到底,都是人的问题,这里只是提供一种思路,仅供参考。
就像软件架构一样,产品设计,也是有架构的。
在做项目的很多时候我们觉得从技术上,所有的问题都能得到解决,但是整个项目,却在不知不觉间一步步的走向屎山型项目。按照研发的思维,问题的根源是抽象的还不够,技术水平不行,需要更强大的架构师来重构。
于是,公司聘请了资深的软件架构师,历经一段时间,似乎项目变得好了一些,但是走向屎山的方向并没有发生改变,只是延缓了而已。然后到了某种情况只能抛弃,重新开始。
回过头才发现,我们的主要精力都在解决技术上的问题了。
这种现象的出现大概率是产品架构的问题,而不是技术架构上面的问题。
按照网上的一种说法,产品架构就是在充分理解产品用户需求基础上对产品数据流转的逻辑梳理。
我对产品架构的理解是从"理念世界"开始的。
编程是用计算机能够理解的语言来描述现实事物,计算机能够理解的语言是什么?是逻辑。在编程的时候,研发人员需要在脑海中构思出整个事件的全貌,并且用逻辑的语言将它描述出来。
在西方的哲学里面有一个"理念世界"的说法,大概意思是人们做的任何事情,都是在脑海中预先构建出事物的本体,再到现实中对预先构建的内容进行模仿。
这与我们编程的过程何其的相似!!!
那么产品呢?是否也遵循这个过程?
我回想起以前做项目时的思考方式,发现确实如此,我们或多或少都需要在脑海中构建出这款产品的运行轨迹。但是在做项目的时候,作为研发,我们其实都在想如何用技术解决问题,却忽略了更重要的东西。
任何产品都是为了解决客户的问题而存在,解决客户的问题是根本,无论用什么手段…
产品架构设计的好,技术的实现就会变得无比顺滑。因为是在充分理解产品用户需求基础上对产品数据流转的逻辑梳理,逻辑理顺了,代码就好写了。
在设计之前,先解决人的问题,什么样的人适合做产品架构?
产品架构就是在充分理解产品用户需求基础上对产品数据流转的逻辑梳理。
所以我们需要一个这样的人,他需要具备以下素质
有了这些素质,就可以开始构建我们的"理念世界"了
构建"理念世界"其实就是将现实中将要发生的事情,用面向对象设计思维将事情转换成纯粹的逻辑描述,这个过程叫抽象
举个例子,如果我们需要做一个流量治理类型的产品,抽象过程大概是这样的
流量治理基本分为2个大的内容 - 流量监控,流量管理,这是核心价值。
而传统的流量治理工具基本都是采用SDK的方式实现,它们普遍具有以下的问题。
如果能解决此类型的问题将会使得服务网格在流量治理解决方案上会优于SDK的方式,这是比较优势。
有了上面的分析,我们就可以得出 如果我们希望这个产品可以快速升级且侵入性弱,这势必不能与客户的代码进行强绑定。
那么我们就需要一种与语言无关,又能够做到流量监控,流量管理的手段,所以只能去操作系统上面找。
如果我们能操纵操作系统上的某些功能,使得流量在进入服务之前,先进入我们编写的程序中,就做到了语言无关。
思路大概是这样,一个请求进来,先被操作系统转发到我们编写的程序中,然后我们自己编写的程序会将数据上报到某个东西那里保存起来,最后我们的程序转发到真正的服务中,流量监控就做完了。
那么,我们发现还需要一个用于存储上报数据的东西,它需要具备持久化的能力。
在这个流程当中,我们使用了一种设计模式,叫sidecar模式,我们就用sidecar称呼我们自己编写的程序好了,存储的那个就叫数据库。
接下来推导一下流量控制的逻辑,要做到流量控制,当然得需要用到sidecar,毕竟流量已经被操作系统转发到了sidecar上面,我们可以做过处理之后再转发到真正的服务当中。那么我们就需要一个另外的东西,它来告诉sidecar要怎么对流量进行处理,毕竟每个sidecar需要处理的东西是不同的,而且策略内容需要持久化,不然找不到与sidecar的对应关系。我们可以把这个东西叫做控制端
所以流程大概变成了这样,控制端配置流量控制策略,控制端将策略下发到sidecar上面,一个流量请求过来,被操纵系统转发到sidecar,sidecar先上报流量数据到数据库,然后根据流量策略对流量进行处理,最后将请求转发到真正的服务中。
在完全理想的状态下,通过这样一个流程,我们基本实现了流量治理的核心能力,并且这个流程相比SDK的方式更具有优势,这就是所谓"理念世界"的构建过程,纯粹的逻辑描述。
"理念世界"是否正确的唯一衡量标准就是它是否完全正确的描述了现实。就像面向对象思维里面的类和对象的关系,"理念世界"是对现实的抽象。
要想知道抽象的好不好,有一个非常有效的办法。
随便找几个人,在他的面前把你的逻辑念一遍。如果表述的过程是顺畅的,对方能够理解并且没有感觉到逻辑上的遗漏,这个抽象就是比较好的。
在做项目的时候,可以把这个过程尽量的描述给不同岗位的人,一边加深团队成员对产品的理解一边又通过不断的表述来完善这个流程没有考虑完善的内容。
当"理念世界"被建立,就需要在现实中对它进行模仿,在软件工程学当中,这一步就要开始脱离设计,到实操的阶段了。
一般项目分2类,一类是从零开始,一类是存量项目
从零开始的项目在动手之前,一般会面临2个问题,一个是从哪开始?一个是要模仿到什么程度?
回到之前流量治理工具的例子。
我们通过流程可以很清楚的发现有几点是一切的基石。
所以在没有外部特殊情况干扰的时候 流量监控
功能肯定要优先于流量控制
功能做,这是从哪开始。
至于做到什么程度主要依托于时间,人员的关系,看实际情况把握。但无论做多少,只要方向是对的,对整个产品的迭代都是具有正向的意义。
而且通过这张图,服务划分也变得很清楚明了,接下来交给研发时,每个服务的边界也有明确的规定。
就算研发人员出现新入职或者水平良莠不齐的现象,在这个框架内所能造成的破坏力也有限,不会对整个产品造成结构性的问题,在未来的某个时候只需要找一个足够强的研发重新写一遍,问题就都解决了。
存量项目的落地就十分的复杂,历史遗留害人不浅…
大的思路应该是先用"抽象"映照现实,看看到底现在的代码是否完全符合"抽象"的"流程",先搞清楚现状再想办法修枝剪叶。
当然,最重要的是人,人如果有问题,任何方法都不好使。所以一个大牛强过一百个菜逼。
如果有新的需求到来时,还是要先抽象,任何正当的需求都是符合逻辑的,如果抽象出来不符合逻辑,那肯定是需求挖掘的不够,不能盲目的加代码。
还是那个例子,如果需要添加一个对sidecar的监控,那流程就会变成这样。
但是监控单独拎出来是否有必要?如果没有必要的话流程可以变成这样。
这2种形态没有优劣之分,可以结合具体情况做选择。
如果有了解到服务网格领域的朋友应该很早就发现了,我说的这个例子就是一个弱鸡版Istio的诞生。
我尝试着从需求出发,纯粹的逻辑推导Istio的架构。很多有名的开源项目为什么历经这么多年,非但没有变成屎山,反而越来越精炼,这里面一定有些什么东西是值得去探讨的。
这里只是提供一种解决问题的方法,解决问题的核心还得看人,一群dalao,无论用什么方法做出来的东西都精美而优雅~