文档章节

配置编程:让项目开发从多样到统一

暗夜在火星
 暗夜在火星
发布于 2012/12/12 12:47
字数 3199
阅读 102
收藏 2
点赞 0
评论 0

 

配置编程:让项目开发从多样到统一

暗夜在火星 20121211日星期二

前记:

在再一次(前面省略N次重构不计)通过重构,把目前正在开发的一个项目模块系统化后,忽然有些开发心得,故记如下。

一直都说,软件开发是一门艺术。

而笔者前段时间也有接触摄影,从中了解到摄影从入门到精通也分开三个阶段,分别就是:简单、多样、统一。在做了这么多项目开发后,笔者也发现,软件开发也同样经历着以上三个阶段。开发人员像摄影师一样,通过不断的实践,从中摸索,略有所悟。

笔者作为众多开发人员之一,也将自己的一些感悟在此与大家分享。

简单:

记得刚上大学的时候,教我们编程的那位老先生就说:编程,越简单越好。

诚然,开发领域也一直信奉着KISS原则,把软件开发得简单明了以致看不到的缺陷(而不是把项目搞得复杂以致找不到明显的缺陷)。

然后理想总是很丰满,现实总是很露骨。

基本上所有的项目都是要求拥有各种各样的功能、多个模块、N个子系统。虽然秉承着“高内聚、低耦合”的思想,还是逃避不了复杂多变的命运,更别说客户频频变更的需求。于是也就有了以下的多样。

多样:

当一个项目拥有一定人用户时,或者成为产品时,其功能多样性导致系统的复杂性,总让开发人员很纠结。特别当没有统一的策略或者解决方案时,更会让项目陷入混乱,甚至让项目中止。

比如(以笔者正在开发的项目为例):一个需要同步本地和服务器邮件联系人的模块,当联系人发生改变时,需要同步更新本地和服务器相应联系人的最后更新时间,因为在本地维护了一份所有联系人最后更新时间的列表,用于对比与服务器的时间,如果一致则不用更新。那么,何时调用更新最后修改时间操作呢?

目前假设在以下几个时机需要更新:

1.       客户修改本地联系人时

2.       从服务器更新联系人到本地时

3.       同步本地联系人到服务器时(此情况发生在客户有多个客户端时,类似SVN

如果让以上时机(可能还会有更时机),再由开发人员手动调用的话,问题就来了。因为开发人员往往不会意识到需要更新本地最后修改时间而忘了调用。特别是当有多个开发人员分别负责以上各个模块时!当发现因为没有更新最后修改时间而出问题追究到开发人员时,他或许很无辜并惊讶问道:哈?!需要更新最后修改时间吗?什么时候的事。。。

这时,就需要一种统一的手段进行控制,也就是以下将要重点讨论的:统一。

统一:

不得不说,软件开发行业虽然发展才几十年,但已经有了很多前人宝贵丰富的系统体系理论,并蕴含着各种哲理。

现在,很多框架,系统或者网站都采用了统一的处理方案,如统一的异常处理机制、统一的日记纪录方式、统一的接入方式。正是这样高度统一的思想,使得系统集成更加方便。像Eclipse就提供了一致的插件接入,从而吸引了众多的开发人员;像Yii开发框架使用了一致的日记纪录方式,使得开发人员很好查看错误信息;像新浪的开放平台也一样。

可以看到,统一的思想已经普遍并成熟,更重要的是得到了很好的应用。

本文的主题是重构,但正如真正的作家的功底不是在于捏词造句,而是在于其人生阅历。同样,重构只是一种开发的手段,途径,真正需要的还是一种思想,一种指导思想。比如单职责设计原则、“优先使用对象组合,而不是类继承”的面向对象设计原则、敏捷开发中提到的测试驱动编程等。

而我现在想要分享的是:优先考虑配置编程,而不实现编程。

同样,结合笔者刚才那个项目进行详细讲解。

在此项目中,有一模块是需要对本地和服务器间的邮件联系人进行同步。而同步策略有以下4种:

1.         冲突时提示

2.         双向同步

3.         单向同步,OutlookExtMail

4.         单向同步,ExtMailOutlook

利用策略模式,设计的类图如下:

尽管这样的设计在整体上效果很好,但当到了各个策略具体实现时,问题就来了。因为源自于以下的项目需求:

 

发现如果让各个策略类各自完成相应的同步操作话,会导致每个策略类都会很复杂,业务层面不易统一维护。而通过分析(其实笔者是重构了,再重构,才得出来的分析)可知,同步最终的操作,也就是实现可分别以下5种情况:

1.  不需要处理(很诱人,但不是唯一的一种情况)

2.  同步本地到服务器

3.  更新到本地

4.  从本地删除

5.  从服务器删除

试想一下,如果没有一种统一的处理方式,各个策略类各自需要处理以上各种情况会是怎样的复杂?虽然有些策略不需要考虑其中某些操作情况。

但,如果具体的策略类不需要考虑实现,而是考虑配置编程,开发难度会不会大大降低?

恩,这里停顿一下,因为关键的时候来了。先刷下微博吧,清醒一下头脑先。

。。。

。。。

好,回来继续。

配置?对,就是配置。

我们可以就以上5种情况分别作相应的标记,如下所示:

protected bool isLocalNeedUpdate;

protected bool isServerNeedUpdate;

protected bool isLocalNeedDelete;

protected bool isServerNeedDelete;

那么再结合模板方法,在父类的策略类中加下以下的模板方法函数:

class ExtSyncPersonalContactStrategy 

{ 

    protected bool isLocalNeedUpdate; 

        protected bool isServerNeedUpdate; 

        protected bool isLocalNeedDelete; 

        protected bool isServerNeedDelete; 


/// <summary> 

        /// 模板方法 

        /// </summary> 

        /// <param name="strvCardName">等待同步的联系人</param> 

        virtual public void DownloadContactFormServerByNames(List<string> strvCardName) 

        { 

            foreach (string strName in strvCardName) 

            { 

                isLocalNeedUpdate = isServerNeedUpdate = false; 

                isLocalNeedDelete = isServerNeedDelete = false; 


                //分情况处理 

                if (IsLocalExits(strName) && IsServerExits(strName)) 

                { 

                    //1. 本地与服务器都存在 

                    SyncContactBetweenLoaclAndServer(strName); 

                } 

                else if (IsLocalExits(strName) && ! IsServerExits(strName)) 

                { 

                    //2. 本地存在,但服务器没有 

                    SyncContactIfLocalExist(strName); 

                } 

                else 

                { 

                    //3. 本地没有,但服务器存在 

                    SyncContactIfServerExist(strName); 

                } 


                if(isLocalNeedUpdate) 

                { 

                    //更新到本地操作 

                } 


                if(isServerNeedUpdate) 

                { 

                    //同步到服务器操作 

                } 


                if(isLocalNeedDelete) 

                { 

                    //从本地删除操作 

                } 


                if(isServerNeedDelete) 

                { 

                    //从服务器删除操作 

                } 

            } 

        } 


        virtual protected void SyncContactBetweenLoaclAndServer(string strName) 

        { 


        } 


        virtual protected void SyncContactIfLocalExist(string strName) 

        { 


        } 


        virtual protected void SyncContactIfServerExist(string strName) 

        { 


        } 

}//end of class ExtSyncPersonalContactStrategy

 

补充说明:

以上代码是简化版,以突出需要分享的思想:优先考虑配置编程,而不实现编程。

其中,bool IsLocalExits(string strName) bool IsServerExits(string strName)分别用来判断是否存在本地或者存在服务器。

而三个虚函数则是分别针对三种不同情况的具体不同处理,主要是修改相关配置。

       目前,策略父类的类图如下所示:

经过这样统一后,开发人员就可以根据不同的具体策略类选择重写感兴趣的虚函数,从而修改不同的配置,即可实现同步。而无须再编写各种实现操作代码(虽然很可能也是复制,但同样也是个问题)。

下面再以双向同步子类的实现深度说明。

由于双向同步策略的业务规则是:本地、服务器那方最新则以哪方为准,一方不存在则以存在的一方为准,则其子类实现代码如下:

class ExtBothwaySyncPersonalContact : ExtSyncPersonalContactStrategy 

    { 

        override protected void SyncContactBetweenLoaclAndServer(string strName) 

        { 

            int cResult = CompareLocalAndServerByName(strName); 

            if (cResult > 0) 

                isServerNeedUpdate = true; 

            else if (cResult < 0) 

                isLocalNeedUpdate = true; 

        } 


        override protected void SyncContactIfLocalExist(string strName) 

        { 

            isServerNeedUpdate = true; 

        } 


        override protected void SyncContactIfServerExist(string strName) 

        { 

            isLocalNeedUpdate = true; 

        } 

}//end of class ExtBothwaySyncPersonalContact 


其中CompareLocalAndServerByName函数存在于父类,用于比较本地与服务器的最后更新时间,如下所示: 


/// <summary> 

        /// 比较本地和服务器的规则 

        /// </summary> 

        /// <param name="strName"></param> 

        /// <returns>-1表示本地版本旧,0表示相同,1表示本地版新</returns> 

        protected int CompareLocalAndServerByName(string strName) 

        { 

            // 

        }

是不是子类的实现变得如此简单?!

或许你感觉不到,好吧,让你看一下,我在没有领悟出以上解决方案前的双向同步类的实现代码,对比一下,你就会发现有明显的不同了。

算了,代码太长,看着也累。

其实想想也会发现,每个操作都不是简单的几行代码,虽然在很好的封装情况下,会精简到一两行,通过委托的方式实现。但是依然要对各个不同的情况进行处理,而达不到一致的最终处理方式。

另外一个项目例子?

      

笔者之前在某游戏后台系统开发时,曾需要根据玩家的ID或者名称查询游戏中与该玩家相关的所有纪录数据。如玩家的物品、副本等大类,其中大类中又有各小类查询。基本算起来有8个大类,共40多个小类。大概类结构图如下:

考虑到查询的操作流程一致,唯一不同的是不同的查询限制条件,如时间范围、玩家ID或者名称。因此,我们可以将操作流程统一到查询父类,扩展子类只需要简单修改以上配置条件即可。

如扩展的一子类:

<?php 

require_once('LogQuery.class.php'); 


/** 

 * 盟会查询类 

 */ 

class GangLogQuery extends LogQuery 

{ 

    /** 

     * 实现父类初始化函数 

     * 值得注意的是这里的匹配规则 

     */ 

       protected function initialize() 

       { 

               //在此配置。。。 

       } 

} 

?>

经过这样重构(原来的情况不得不说有点混乱),最直接的成效就是,当用户需要添加一个大类查询或者小类查询时,原来要3个小时(包括修改代码、测试、发布),现在只需要5分钟!而且,正确率高。因为它是如此简单而明显没有问题。

小结:

       最后小结一下。

优先考虑配置编程,而不实现编程”适用在以下情况(也是本文讨论分享的):

当模块内有一系列不同的处理方式,最终根据不同情况以相同方式进行处理时。

当然,还有另外的情况,如用在工厂方法里。

但这里,暂且只讨论上述情况。此时可以结合设计模式里的模板方法进行重构。

好处:

通过将开发重点转移到配置上,使得开发难度大减低,而且让项目开发达到了一致性。因为开发人员需要做的,仅仅是修改配置即可完成相应的功能。

特别在类似游戏开发中,有各种任务、各种装备、各种场景,而有时同一模块内,操作流程一相,不同的是参数。因此,更可以考虑配置编程。

先前,笔者在一家游戏公司开发时,就学习了这种“策略”,而且通过编写宏命令,直接将保存在Excel里面的各个参数转成相应的配置实现的类。这样,既避免了烦锁的代码编写,又保证了数据的正确性。

说得通俗一点,配置编程的好处就是:类似使用QQ,用户设置了不同的在线状态,系统就人执行相应不同的操作。

说得专业一点,其好处就是:你可以告诉系统你想要什么,让系统知道做什么,而不用再去考虑如何实现。犹如SQL查询一样,在此我们不妨把配置编程称做为“仿4GL”的语言。

最后,仿造正在看的《领域驱动设计与模式实战》书中经常提到的一句话来结语,那就是:多样,统一?重构。(原话是:经灯,绿灯,重构)

© 著作权归作者所有

共有 人打赏支持
暗夜在火星

暗夜在火星

粉丝 150
博文 160
码字总数 310930
作品 1
广州
程序员
开源WEB统一开发框架项目期待您的加盟

源WEB统一开发框架是针对中等规模的交互式网站产品的付费型开源项目;目的是为了适应目前异地合作开发web项目的需要,以及顺应未来分散式工作方法的方向。主要包括底部分布式框架以及源代码管...

datou
2010/03/14
1K
0
java入门学习之路

java是面向对象的编程,个人觉得记忆比较重要。 第一阶段 java基础部分 unix开发环境 熟练掌握开发中常用的操作系统linux的安装及使用:掌握文件系统、网络、用户管理方法:能熟练使用vi和v...

瑞克3号
2017/07/10
0
0
基于 docker 的 PaaS 系统--LAIN

Lain 是一个基于 docker 的 PaaS 系统。 其面向技术栈多样寻求高效运维方案的高速发展中的组织,devops 人力缺乏的 startup ,个人开发者。 统一高效的开发工作流,降低应用运维复杂度;在 ...

匿名
2016/05/17
1K
0
收藏|学习Python编程的6本书籍

本文与大家分享一些Python编程语言的入门书籍,其中不乏经典。有关书籍的介绍,大部分截取自官方介绍。 Python基础教程(Begining Python) 《Python基础教程(第2版·修订版)》是经典的Pyt...

诸葛玥
2017/12/28
0
0
沈晓军/mini-jdbc

mini-jdbc - 介绍&使用说明 sxjun @2016-01-15 使用MiniJdbc的项目:LarvaFrame(供参考) 该项目仍在持续完善中... 一、mini-jdbc介绍 1、mini-jdbc:针对spring jdbc的一些不方便的地方,做了...

沈晓军
2016/01/28
0
0
实现基于ASP.NET MVC快速开发平台

最近一个月,自己利用业余时间开发一个基于ASP.NET MVC快速开发平台。现在勉强算个原型,但是感觉不是那么回事,把实现的过程写出来,欢迎大家拍砖。 开发思想:利用Asp.Net MVC的思想,实现自...

王二狗子11
01/01
0
0
实现基于ASP.NET MVC快速开发平台

最近一个月,自己利用业余时间开发一个基于ASP.NET MVC快速开发平台。现在勉强算个原型,但是感觉不是那么回事,把实现的过程写出来,欢迎大家拍砖。 开发思想:利用Asp.Net MVC的思想,实现自...

晨曦之光
2012/03/09
0
0
通用面向对象脚本--coos

coos通用面向对象脚本 common object-oriented scripts Script Library 是本人在大量企业级网站系统开发中和阅读大量书籍后提炼出的一个开源脚本库。 目标是提供一个跨浏览器,兼容性好,独立...

热血狂徒
2011/06/16
1K
0
分布式配置管理平台--Disconf

Distributed Configuration Management Platform(分布式配置管理平台) 专注于各种 分布式系统配置管理 的通用组件/通用平台, 提供统一的配置管理服务。 包括 百度、滴滴打车、银联、网易、拉...

knightliao
2015/04/13
67.8K
19
面向UI编程:ui.js 1.0 粗糙版本发布,分布式开发+容器化+组件化+配置化框架,从无到有的艰难创造

有朋友提出一看来是懵逼的,根本不知道什么是面向UI编程的思想,下面是我之前写的博客,描述的这中思想,下面为地址,参考下就明了很多了。 1. 前端思想实现:面向UI编程 2. 面向UI编程框架:...

仲强
2017/02/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

CoreText进阶(七)-添加自定义View和对其

CoreText进阶(七)-添加自定义View和对其 其它文章: CoreText 入门(一)-文本绘制 CoreText入门(二)-绘制图片 CoreText进阶(三)-事件处理 CoreText进阶(四)-文字行数限制和显示更多...

aron1992
9分钟前
0
0
Python爬虫 爬取百合网的女人们和男人们

学Python也有段时间了,目前学到了Python的类。个人感觉Python的类不应称之为类,而应称之为数据类型,只是数据类型而已!只是数据类型而已!只是数据类型而已!重要的事情说三篇。 据书上说...

p柯西
21分钟前
0
0
在Java中,你真的会日期转换吗

1.什么是SimpleDateFormat 在java doc对SimpleDateFormat的解释如下: SimpleDateFormatis a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows fo......

Java小铺
29分钟前
0
0
Linux系统梳理---系统搭建(二):tomcat的安装和使用

上一章讲到JDK的安装使用,这一章主要记录下服务器tomcat的安装以及部署一个项目. 1.下载tomcat,这里下载的是apache-tomcat-8.5.32.tar.gz 2.创建文件夹,便于管理,和JDK一样,在usr目录下创建t...

勤奋的蚂蚁
40分钟前
0
0
ES15-聚合

1.Terms Aggregation 分组聚合 2.Filter Aggregation 过滤聚合

贾峰uk
41分钟前
0
0
【2018.07.19学习笔记】【linux高级知识 20.27-20.30】

20.27 分发系统介绍 20.28 expect脚本远程登录 20.29 expect脚本远程执行命令 20.30 expect脚本传递参数

lgsxp
44分钟前
0
0
10.32/10.33 rsync通过服务同步~10.35 screen工具

通过服务的方式同步要编辑配置文件:[root@linux-xl ~]# vim /etc/rsyncd.confport=873log file=/var/log/rsync.logpid file=/var/run/rsyncd.pidaddress=192.168.43.21[tes...

洗香香
47分钟前
0
0
与女儿谈商业模式 (3):沃尔玛的成功模式

分类:与女儿谈商业模式 | 标签: 经济学 沃尔玛 陈志武 2007-05-10 09:09阅读(11279)评论(30) 与女儿谈商业模式 (3):沃尔玛的成功模式 陈志武 /文 沃尔玛(Wal-Mart)是另一个有意思的财...

祖冲之
54分钟前
0
0
网页加载速度优化方法总结

1、减少请求 最大的性能漏洞就是一个页面需要发起几十个网络请求来获取诸如样式表、脚本或者图片这样的资源,这个在相对低带宽和高延迟的移动设备连接上来说影响更严重。 2、整合资源 对开发...

Jack088
59分钟前
0
0
dubbo学习

https://blog.csdn.net/houshaolin/article/details/76408399

喵五郎
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部