没有银弹-谈谈软件设计的几个矛盾

原创
2014/06/16 10:57
阅读数 1W

最近在做项目的重构和功能改进,设计做了很多,也发生了一些争执。其实总结下来,很多争执的内容其实早就是经典的问题。这些问题没有孰优孰劣,具体采用哪种方案,还得因地制宜,详细分析项目需求和复杂度之后,再做决定。之前很多人都试图只从宏观指导思想来决定设计,最后大家谁也不服谁,所以先把问题确定下来,至少以后思考问题会直接一点。

1. 拆分与合并

从现实世界来说,事物本身就是互相联系的,从这个观点来看,任何对事物的拆分都是不完全正确的。

但是软件开发中,人的理解能力是有限的,而拆分目前看来是降低单个项目复杂度最有效的办法。

拆分有很多级别,最小的可能是拆分代码段,用多个函数代替单个函数,然后是用多个类代替单个类,在Java里面,还可以拆分package,然后拆分jar包,最后拆分成不同的项目。

之前有过很多的争执,关于一个项目要拆还是不拆,以及如何拆。关于这个,我的建议是:

  1. 拆与不拆没有对错

    Windows是微内核架构,Linux是单内核架构。微内核意味着内核很小,你可以通过很多个模块去补充它,内核与模块是解耦的。Linux是单内核,就表示所有内核功能会在编译时就确定。可能大家都觉得微内核更好,很多时候它确实更好,但是Linus有个经典的论断:“你不需要管理各个模块,但是你需要处理模块之间的依赖,这个可能比模块本身更复杂”。因为事物本身就是互相联系的,你觉得他们不存在耦合,只是当前使用场景用不到而已。

  2. 系统内部实现对外部透明,保留拆或者不拆的选择权。

    项目自身的复杂度,完全可以靠内部实现解决,对外保持约定好的API,这样对于以后内部的重构,会简单得多。相反,如果暴露了内部实现,那么修改就很困难了。

  3. 对于项目拆分,如果没有充足的理由支持拆分,就不要拆。

    不成熟的拆分,最常见的结果是,随着需求的变化,你不得不打破这种解耦关系,这样反而会带来更多的问题。建议是需求稳定之后,再考虑拆分。

  4. 在系统内部多多进行代码级别的拆分,管理复杂度。

    相比项目的拆分,函数和类级别的拆分成本非常低,值得多用。

2. 配置化与灵活性

一段代码,如果使用一遍,那么我们就直接通过代码实现了。如果我们有几十上百个类似的任务,那么我们就不希望写重复的代码了,我们希望能够通过配置几个不同的参数,从而实现不同的任务。如果以后还有不断变化的需求,我们甚至不希望自己写配置,而是有一个运营后台来让需求方(可能是不懂开发的人)直接完成配置。

配置化的开发方式往往对开发者来说有很大的诱惑,从而忽略其中的成本,这个配置最近还有个很火的名字,叫做DSL。但其实配置化和灵活性是矛盾的,配置的表述能力自然要弱于通用语言。当然,也有人尝试使用配置解决所有问题,结果只不过是发明了一门很难用的语言而已。

我自己的框架WebMagic是一个经典的配置与灵活性权衡的例子。WebMagic是一个垂直爬虫框架,爬虫最复杂的是规则的编写,你可以认为这是一个可配置的东西。公司基于它做了一个配置后台,即使是这样,仍然有一些情况,不得不手写Java代码来实现一些功能。

对于这个问题,我的建议是:

  1. 先写代码解决问题,但是提前约定接口。

    第一个阶段,没有谁能预测以后的需求,所以先用你熟悉的代码实现。可以根据你的输入和输出,约定程序级别的接口,相比配置化,这一般来说会容易,如果接口设计得当,也会有具有很大灵活性,以后基本无需更改。

  2. 在有一定积累之后,基于以往的任务做配置化。

    配置的内容是什么呢?首先公共逻辑肯定会在整体框架中,配置的内容应该是不同任务彼此独特的部分。这个配置格式,或者DSL的语法的约定,首先应该基于已有的任务,然后可能考虑一下未来的情况。我是个实践主义者,所以我更多的会参考已有的情况,如果发现这个配置化的框架,对之前的任务都不能满足,那么就需要思考一下它的可行性和必要性了。

  3. 在任何时候都保留能使用代码实现的能力。

    我是个实用主义者。有了配置,如果不提供代码实现的能力,而又有一些复杂的需求,那么就只能扩展配置的能力了。这样只可能会导致这个配置解决框架变得极其庞大和复杂,而相对收益却很低。这个时候,可以通过配置解决大部分问题,然后通过代码解决少量问题,也是不错的选择。

3. 总结

其实还有很多东西没说到,以后补充吧。以上的建议都是抛砖引玉,未必是最合适的方案,欢迎大家讨论。

总结一句话:软件设计要适应并满足需求,同时不断演化。

展开阅读全文
打赏
12
80 收藏
分享
加载中
面向接口编程,内部实现透明,便于重构
2014/06/29 23:14
回复
举报
2014/06/25 18:03
回复
举报
分久必合,合久必分
2014/06/24 12:53
回复
举报
DSL设计或者说配置式编程本身没有错(say what you want, not how to do),错就错在DSL选用XML作为表达语言,而XML本身的表达太受限了。。
2014/06/22 09:11
回复
举报
mark
2014/06/18 18:12
回复
举报

引用来自“中山野鬼”的评论

要啥,给啥,搞定,收钱,大家开心才是好。。。。其他都是自恋自艾。。。哈。

引用来自“黄亿华”的评论

越来越觉得有道理了!
实用主义者 @中山野鬼
2014/06/18 09:42
回复
举报
黄亿华博主

引用来自“中山野鬼”的评论

要啥,给啥,搞定,收钱,大家开心才是好。。。。其他都是自恋自艾。。。哈。
越来越觉得有道理了!
2014/06/18 09:39
回复
举报
说没有银弹不如说没有金刚钻,有点装B
2014/06/18 09:10
回复
举报
要啥,给啥,搞定,收钱,大家开心才是好。。。。其他都是自恋自艾。。。哈。
2014/06/17 21:00
回复
举报
额。“设计”好像没有对错。
2014/06/17 17:08
回复
举报
更多评论
打赏
22 评论
80 收藏
12
分享
返回顶部
顶部