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

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

1. 拆分与合并

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

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

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

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

1.拆与不拆没有对错

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

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

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

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

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

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

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

2. 配置化与灵活性

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

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

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

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

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

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

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

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

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

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

3. 总结

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

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

时间: 2024-07-30 10:27:16

没有银弹-谈谈软件设计的几个矛盾的相关文章

从一个圈套For循环来谈软件设计[原创]

设计|循环|原创 从一个圈套For循环来谈软件设计 武汉华中师范大学信管系 谢刚 摘要:就自己的一次实际经历来谈谈软件设计过程中应该注意的一些细节 关键字:软件设计 需求分析      前段时间,跟外面公司设计一个MIS系统(使用工具是PB8.0+MSSQL),是一个关于安全生产的.为了体现我们设计人员的高质量服务,我在<需求说明>之外又帮他们设计了一个功能,就是:在每次这个功能窗口打开时,到数据库中去自动检测看看有没有冲突数据:也就是说,两个一模一样的器材是否被安装了到了两个不同的机器上.这

由学习《软件设计重构》所想到的代码review(二)

前言 对于一个程序员来讲如何来最直接的来衡量他的技术能力和产出呢?我想最直观的作法是看他的代码编写能力,就拿我经常接触的一些程序员来看,他们买了很多技术重构类书籍,但是看完后代码编写能力并没有显著提高.有人说可以用代码review工具啊,但是像市面上的这些代码review工具,只能帮助我们解决表面的bug和规范点,还无法帮助我们发现更深层次的设计问题. 上一篇<由学习<软件设计重构>所想到的代码review(一)>我结合<软件设计重构>这本书谈谈在进行代码review的

由学习《软件设计重构》所想到的代码review(一)

前言 对于一个程序员来讲如何来最直接的来衡量他的技术能力和产出呢?我想最直观的作法是看他的代码编写能力,就拿我经常接触的一些程序员来看,他们买了很多技术重构类书籍,但是看完后代码编写能力并没有显著提高.有人说可以用代码review工具啊,但是像市面上的这些代码review工具,只能帮助我们解决表面的bug和规范点,还无法帮助我们发现更深层次的设计问题. 下面我将结合<软件设计重构>这本书谈谈在进行代码review的时候,需要关注的哪些点. 一.技术债务 何为技术债务? 技术债务是有意或无意的做

如何写软件设计文档

软件设计的不同模型:瀑布式.快速原型法以及迭代式 自从1968年提出"软件工程"概念以来,软件开发领域对于借鉴传统工程的原则.方法,以提高质量.降低成本的探索就从未停止过.而在这个过程中,提出了许多不同的软件开发模型,典型的有:瀑布式,快速原型法,以及迭代式开发等. 瀑布式模型 是由W.W.Royce在1970年最初提出的软件开发模型,在瀑布模型中,开发被认为是按照需求分析,设计,实现,测试 (确认), 集成,和维护顺序的进行. 快速原型法 快速原型模型的第一步是建造一个快速原型,实现

软件设计漫谈之二:设计模式只是一把锤子!

              设计模式只是一把锤子!     谈起设计模式,那是几乎无人不知,无人不晓,大名鼎鼎的"GOF"(中文有的翻译为"四人帮")惊世之作,真是"平生不识GOF,学尽设计也枉然!"     然而,设计模式真的是软件设计的"瑞士军刀",切.削.锯.钻样样精通么?     读过设计模式的朋友估计不少,但真正注意过<设计模式>的副标题的估计很少,而这个副标题却是避免误解设计模式的关键.<设计模式

ANDROID首席设计师谈移动与软件设计

  在 2014 年Accel设计大会上,Android 设计副总Matias Duarte就软件设计接受 The Verge 主编Josh Topolsky访问,在采访时他强调并呼吁:过去设计的出发点是为不同设备开发各自的独立应用,但今时不同往日,软件设计者应当琢磨如何只开发一款应用,并在不同设备上运行. 观看地址:优酷 Matias 在 Google 任职已近 4 年,之前供职于 Palm.Helio.Danger,在用户体验设计方面积累了精深经验和良好口碑. 在访问中,Matias 首先分

怎样在家自学软件设计

问题描述 怎样在家自学软件设计 我是一名高中生,但什么都不懂,想在家自学软件设计,请问各位大神,买什么书籍好? 解决方案 http://www.ed2000.com/ShowFile.asp?FileID=221694 可以下载视频,资料很全 解决方案二: 你想学什么,或者想写那类型的软件.最好先看下计算机基础,再看下网络基础.最好能先看看数字电路.8008cup指令集...如果想学习网页方向的,直接学html,或者直接上手网页三剑客... 解决方案三: 先从C语言学期吧,至少知道什么是编程,编

谈谈软件下载站的几种盈利模式

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 大家好,通过上次写了关于06年07年的经历的两篇文章,<年赚两万元让我加入了站长行列> < 年赚两万元让我加入了站长行列(二)后,我再次写一下08年搞的一个软件下载网站的一些经验心得吧! 在08年后我开始发力搞软件下载网站了,07年搞了一个资料下载网站,发现还是有有盈利的,之前的程序是在淘宝购买的,我发现现在已经不用购买新的

关于软件设计的一个问题

问题描述 关于软件设计的一个问题 要求是这样的: 要实现一个程序X定时从第三方获取数据并存储,并且我自己的程序A也可以通过此程序X从第三方主动获取需要的数据,这个程序X应该用什么实现? windows service可以么? 解决方案 1.定时程序通过windows的service来定时同步数据 2.程序A通过自己的业务接口去第三方系统获取数据,不要和定时程序公用.如果你的定时程序也是在程序A中,则你可以公用相同的代码,否则还是单独使用各自的代码. 至于如何同步数据,可以通过sockete.ht