昨天看到博客园的一篇新闻《程序员的回归式进化》,该新闻非常有意思,展示了同一段“Hello World”代码,一个1年编程经验、一个2年编程经验、一个3年编程经验、一个5年编程经验和一个10年编程经验的不同写法。这些写法中,让人啼笑皆非的是5年工作经验的程序员编写的代码看起来如此的复杂、如此的有技术含量,而10年工作经验的程序员编写的代码竟然和1年工作经验的程序员是一样的,真是有点讽刺,呵呵~~。


不过,笑过之后,还是让我忍不住陷入沉思。本人已经写了11年的C#代码,写了3年的Java代码,还使用过汇编语言、C语言、Delphi、PowerBuilder、C++、ASP、PHP、C++ Builder等写过不少代码,经历的项目和产品也不算少了。我一直在追求如何使软件开发变得更为简单,这种简单不仅仅是对于我自己,更是对于整个团队。


企业级软件天生就是复杂的,为什么呢?如果一个软件市场不错的话,那么这个软件总是会不断的进行演化,代码数量总是在不停的增加。以Spring为例,0.91版本发布时只有1万多点代码,1.0发布时有2万多代码,1.2发布时有4万多,2.0发布时有6万多,2.5发布时有7万行代码(以上数据参考《Java应用架构设计》),代码越多意味着越复杂。如果这些代码中,还存在技术债、设计腐化、循环依赖等各种内在的问题,那你想想看,如何使其回归简单?如果你加入一家公司,不幸的要去维护一个现有的系统,你如何回归简单?千万别告诉我,你要重新编写一套,这只是简单的技术思维而已!


回过头来,我们再看看那个5年经验的代码。其实该程序员的写法没有错,他已经学会了如何使用DI进行解耦合了,猜得不错的话,他也是学会了设计模式,甚至掌握了一些OOP的设计原则。但是如果整个应用系统都充斥了这样的代码,那我估计谁看谁发疯!


那么这个懂DI、懂设计模式、懂OOP设计原则的有经验的程序员犯啥错了?很简单,我觉得他什么错也没有犯,他只是依然缺乏经验而已。


看了那个代码,我觉得第5年写的那个,其实最主要的是没有考虑系统和业务角度去考虑变化和不变之处,而只是单纯的体现了技术。


道法自然
操作系统的功能边界是清晰的,而企业级开发的对象是人,人的需求是复杂的,所以功能也是多变的。
单独的一个模块,企业级开发没有操作系统复杂,当模块逐渐变成一张大网的时候,能从网里脱身出来,就很不容易了。而且还要有时间的制约。




抛开团队管理和协作层面,我们单从技术层面来考虑,想要使应用系统的开发变得简单,有效的方法就是化整为零,将复杂大系统拆分成小的、简单的、能够组合的“代码块”,简化系统开发并间接提高软件系统的可维护性和可扩展性。那问题是,这个“代码块”应该是怎样的粒度?下图是软件系统“自上而下”架构图(该图参照《Java应用架构设计》),服务/子系统的粒度大,类的粒度小,系统的展现层粒度一般比较大,而数据访问层粒度小。粒度越小,系统越抽象,越灵活;粒度越大,系统越简单,可复用性越低,扩展性越差。


p_w_picpath


想要使系统开发变得简单,选择“模块”作为开发、复用粒度较为合适,模块符合高内聚、低耦合,在模块内部,我们倾向于使用1年工作经验或者10年工作经验的代码,模块内部依赖关系较少,较为清晰,不宜在内部搞太多的抽象。在我们的实践过程中,模块内部不会使用IoC,也不太提倡使用太多抽象,会使用非常直接、简单的编码规则,使1年经验的开发人员能够编写模块业务逻辑。那么5年工作经验的那些代码适合在哪使用呢?


我的答案就是“模块间的边界”。通过对模块间的边界使用OOP的SOLID原则,能够更大提高模块的复用性和扩展性,同时还能够保持模块内部的简单,这或许就是在技术层面回归简单的一种较好的方法了!


企业级软件系统的复杂,不仅仅是技术层面,相反,管理与团队协作更容易影响系统的成败。一个复杂软件系统通常都是由团队协作来实现的,一个完整的团队通常有高级工程师、中级工程师和初级工程师,高级工程师负责架构和设计、中级工程师负责编码、初级工程师仅是入门。有效的解决三种层次工程师的协作,尽量减少交互、协作、学习的成本,能影响后续的维护成本。在我看来,良好的协作模型应该促使三者的工作更加的Focus,专注于自己开发的业务逻辑。同样的,模块化也能够很好解决三者的协作。一方面,通过模块化,我们可以消除软件架构(或者成为统一架构);另一方面,高级工程师负责框架类模块、中级工程师负责业务类模块、初级工程师快速入门协助开发,三者可以进行并行开发,而且代码互相隔离,互不影响。从这个角度看,初级工程师的入门速度也将极大提高。


因此,回归简单的一个好方法就是:(1)化整为零,将系统进行模块化划分;(2)在模块内部保持简单,使用1年或者10年经验代码,在模块间交互部分的代码使用5年经验的编码更是,应用OOP的SOLID、设计模式、SOA等抽象技术,提升模块的可复用行和可扩展性。


@量子计算机
引用楼主园龄离10年还差3年啊。你现在知道要简单是一个正确的方向了,等三年后你这么干,那就是做到了,怎么做呢?
抛弃iOpenWorks,OSGi.NET等这些你现在还当宝贝的玩意,把你曾经的心血,当垃圾,然后呢?然后去使用Json,Restful,等这些小玩意,这就是真简单了。

不要以为做到简单很容易,那是在割你的肉,楼主别受不了又删贴啊。

你园龄已经快10年了,然道理解不了我的文章和那篇新闻的含义吗?你真的觉得什么都不用就最简单了?我们就说车,有自行车、三轮车、出租车、小轿车,有低档、中档和高档的车,单纯用“Hello World”来搞点自行车的玩意可行,因为简单。你要是用“Hello World”来充斥着四轮车,可行吗?现在搞出那么多架构,那么多框架,比如Spring,照你说的,都是没有必要的大东西了。

我园龄7年,C#写了11年,写过几十个项目,厌倦了系统不停变化,厌倦了团队成员胡乱整代码,也厌倦了复杂的东西。我原来在Sybase的一个同事,他已经工作了10几年了,是框架的架构师,产品统一使用插件化/模块化框架,产品组开发的是插件。我们开发插件的时候基本不需要和框架打交道,插件可以清晰分层,经历那么多人维护之后,插件还能继续维护,这是另一种“简单”,不是你说的那种“简单”。企业级的软件本身就是复杂的,不谈想Eclipse这样的大系统,我们做的能耗监控、热力分布式系统就不那么简单了,需要不停的进行需求变更,需要处理很大数据量。让厉害的人负责抽象的部分,让菜鸟负责简单的功能,然后进行组合,这是以前的经验告诉我的,我以前那些非常厉害的同事教给我的。我不是现在才想简单,早就想简单了。想要简单当然不容易,该抽象的需要抽象,该简单的需要简单,什么样的人适合做什么合理分配,条理清晰。

iOpenWorks/OSGi.NET是我设计的,一方面是参照我以前的同事的架构思想,另一方面是参照OSGi强大的功能来做的。使用OSGi.NET框架不是用于支撑很复杂的技术,只是用于支撑更好的协作,更好的能让高手写抽象模块、菜鸟写简单功能模块,仅此而已,我就是想用这样的框架来追求我以前接触过的简单。我们已经应用该框架3年多了,发展越来越好,我干么要将其当垃圾扔掉呢?OSGi.NET原理确实不简单,但是谁需要去了解它呢?就像我们以前不需要去了解架构师设计的框架一样。你不用倚老卖老,虽然你园龄比我长,我已经见过比你年龄更长的,从他们身上我学习更多。建议你以后可以多给别人提供意见,但是少给别人下结论,事实上,很多事情到你挂的那天你也不一定就是对的。


总结的非常好,老程序员的作用不是编码,而是面对各种设计方案的时候,可以用经验来权衡,考量,规避风险。
粒度,复杂度,这些东西,只有犯过无数次错误,有血的教训的人,才能深刻理解重要性的,


确实如此,这些规则很多时候,说出来特别虚,但是确实是需要有教训才有深刻体验。

一般而言,1~3年,还是学习基本技能,3~5年学点高级技能,10年的同志一般要做的是设计和架构、编写高级代码,底下还有团队,如果你带了几个团队,就知道简单有多重要了,底下的人啥都能给你折腾出来,只有清晰简单的规则才能长远。


为什么企业级的开发就一定要很复杂,难道比操作系统内核还要复杂?

不复杂的话,那么多的软件开发方法、开发技巧是用来干么的?非得操作系统才需要吗?


企业级软件系统在不停的演化,对产品质量要求高,涉及开发人员多,当然,技术本身也较为复杂。


项目团队中,难免 会有 能力强,能力差 的队员。

如果两种人 都 做 同一种事:只是 能力强的做的多,能力差的做得少 —— 最后的结果往往是,能力强的特别累,能力差的特别闲;

所以,将 粒度细化, 能力强的给能力差的 提供架构,降低 能力差的队友的开发门槛:让能力差的队友 也能 在不拖延时间的基础上,实现 能力强的队友 才能实现的 复杂功能;

——这才是软件架构之道呀。