【选择恐惧症】需不需要通用设计?

96
杰嗒嗒的阿杰
2017.06.08 09:01* 字数 1374

症前兆

经常会遇到这样的问题:一份需求下来,在做设计的时候就会开始纠结了:到底需不需要先抽象公共元素进行通用设计,再来进行功能的细化设计呢?还是直接根据需求为每个功能进行设计?

症分析

出现这种情况通常是因为需求中存在着一些相似的地方,但是结合需求分析又感觉没有什么通用的东西可设计,抽象不出功能点。但是如果直接就进行具体设计又感觉可能无法满足日后的扩展性,显得设计没有什么技术含量,结果老半天都没有办法定下方案。

这样很容易就会走上两条极端的道路:决定需要通用设计的人设计了很多扩展功能,结果发现需求的发展与预想的功能不符,前期定下来的功能扩展都被否定了。而另外一些决定不需要通用设计的人,因为产品需求的快速发展,需求的不断调整和增加,由于缺乏通用层支撑,使得开发周期变得越来越长,越来越难维护。最后两种情况都避免不了走上重构的命运。

症解决

对于需不需要通用设计,不同的人可能有不同的见解,但是基于程序的可扩展性原则来考虑,个人觉得不管在什么时候都应该囊括这一层在设计里面,只是这层设计的重度视需求来定而已。毕竟是互联网的时代,在产品需要快速迭代的环境中,通用设计也应该顺应潮流,跟着产品的步伐进行快速迭代,不要想着一蹴而就。

举个例子,如果我们要开发一款社交app,里面包括个人信息、好友、聊天等等的UI界面。这些元素看起来都是没有什么关联性的,但是运用面向对象的分析(如果对面向对象分析理解比较模糊的同学,可以看一下之前写的一篇文章《我眼中的面向对象分析》)总能找到对应存在的关系。

基于MVC的设计模式,上面的需求我们可以先为其定义出数据模型的基类DataModel和视图逻辑处理的控制器基类ViewController来作为通用层次的核心类型,如:

class DataModel
{
    function getProperty(name:string):object;
    function setProperty(name:string,value:object):void;
}

class ViewController
{
    property view:View;
}

上面的两个核心类型其实就能组成应用的通用层了(在实际情况中通用层不仅仅包含抽象的内容,还应该包含一些工具类,服务等,这里为了方便说明问题,所以这里抽取了通用层的一部分来进行阐述),结构也相对很简单,这就是通用层的原型。所以不一定说通用设计要很复杂看上去功能很强大才是好,要知道设计没有最好的,只有最合适的。我们能允许它这么简单只是因为我们的需求还没达到需要一个更强大的体系来支撑而已。

随着应用的发展需求在不断地增加和调整,假如需要对所有数据进行本地缓存,UI上出现了一些列表类型的视图,这个时候我们就可以需求再次进行分析,对之前通用层进行扩展:如在DataModel中加入save方法,并为ViewController继承ListViewController。如:

class DataModel
{
    function getProperty(name:string):object;
    function setProperty(name:string,value:object):void;
    function save ();
}

class ViewController
{
    property view:View;
}

class ListViewController extends ViewController
{
    property dataSource:Array;
}

由上面代码可见,通用层在需求增加的时候得以进一步的完善。也可以从这个例子中看到了通用层的设计不是一步到位的实现,而是随着需求的增加、调整而改变和完善的。

貌似例子并没有说明通用设计的必要性,其实仔细想想这个必要已经融入到例子中了。试想如果没有前期的简单设计抽象,在调整数据源缓存本地的需求时,你是否需要为每个数据模型设计独立的缓存实现?即使你能够忍受为每个数据源写缓存实现,假如日后缓存的方式由文件存储变换到数据库存储,那么你是否又需要为每个数据模型进行调整?这样细想是否能够体会通用层的作用的重要性呢?

症总结

综上所述,本人总结了自己的一些观点:

  • 通用设计是必须要有的,但其复杂程度视需求而定,应该跟随需求的步伐来完善
  • 通用设计应该包含一类事物的抽象、常用功能以及服务的整合
  • 通用设计能够指导后续的相关设计
  • 通用设计能够减少后续开发的功能量及提高工作效率

其他症状

《【选择恐惧症】接口?虚基类?》

阿杰谈程序设计