小步快跑是这样玩的(上)
软件的发展规律就是这样的,起初十分简单明了,使我们可以轻松地进行合理的设计。接着开始变更,业务变得越来越复杂,程序也随之变得越来越复杂了。正是因为软件开始由简单软件向复杂软件转变,而我们的设计却没有合理地调整,最后导致了我们的系统越维护越困难,成为了不可被扣的遗留系统——IT攻城狮永远的痛。这就是遗留系统产生的根本原因。
因此,解决遗留系统的根本办法,就是在软件由简单软件向复杂软件转变的关键时刻,适时做出调整,使软件重新回到高质量的状态。这里,我们要做出的调整被称为重构,而做出这种调整的最佳方式,就是“小步快跑”啦。说得那么玄乎,到底什么是“小步快跑”呢?说不尽千言万语,倒不如一个简单的示例:
故事是这样的,当用户登录一个网站时,网站往往需要给用户打一个招呼:“hi, XXX! ”。同时,如果此时是上午则显示“Good morning! ”,如果是下午则显示“Good afternoon! ”,除此显示“Good night! ”。对于这样一个需求我们在一个HelloWorld类中写了十来行代码:
/** * The Refactoring's hello-world program * @author fangang */public class HelloWorld { /** * Say hello to everyone * @param now * @param user * @return the words what to say */ public String sayHello(Date now, String user){ //Get current hour of day Calendar calendar = Calendar.getInstance(); calendar.setTime(now); int hour = calendar.get(Calendar.HOUR_OF_DAY);
//Get the right words to say hello String words = null; if(hour>=6 && hour<12){ words = "Good morning!"; }else if(hour>=12 && hour<19){ words = "Good afternoon!"; }else{ words = "Good night!"; } words = "Hi, "+user+". "+words; return words; }}
如果需求没有变更,一切都是美好的。但事情总是这样,当软件第一次提交,变更就开始了。系统总是不能直接获得用户名称,而是先获得他的userId,然后通过userId从数据库中获得用户名。后面的问候可能需要更加精细,如中午问候“Good noon! ”、傍晚问候“Good evening! ”、午夜问候“Good midnight! ”。除此之外,用户希望在一些特殊的节日,如新年问候“Happy new year! ”、情人节问候“Happy valentine’s day! ”、三八妇女节问候“Happy women’s day! ”,等等。除了已经列出的节日,他们还希望临时添加一些特殊的日子,因此问候语需要形成一个库,并支持动态添加。不仅如此,这个问候库应当支持多语言,如选择英语则显示“Good morning! ”,而选择中文则显示“上午好!”……总之,各种不同的需求被源源不断地被用户提出来,因此我们的设计师开始头脑发热、充血、开始思维混乱。是的,如果你期望你自己能一步到位搞定所有这些需求,你必然会感到千头万绪、顾此失彼,进而做出错误的设计。但如果你学会了“小步快跑”的开发模式,一切就变得没有那么复杂了。
首先,我们观察原程序,发现它包含三个相对独立的功能代码段,因此我们采用重构中的“抽取方法”,将它们分别抽取到三个函数getHour(), getFirstGreeting(), getSecondGreeting()中,并让原函数对其引用:
/** * The Refactoring's hello-world program * @author fangang */public class HelloWorld { /** * Say hello to everyone * @param now * @param user * @return the words what to say */ public String sayHello(Date now, String user){ //这里将原有的代码通过“抽取方法”抽取到3个函数中 int hour = getHour(now); return getFirstGreeting(user)+getSecondGreeting(hour); }
/** * Get current hour of day. * @param now * @return current hour of day */ private int getHour(Date now){ Calendar calendar = Calendar.getInstance(); calendar.setTime(now); return calendar.get(Calendar.HOUR_OF_DAY); }
/** * Get the first greeting. * @param user * @return the first greeting */ private String getFirstGreeting(String user){ return "Hi, "+user+". "; }
/** * Get the second greeting. * @param hour * @return the second greeting */ private String getSecondGreeting(int hour){ if(hour>=6 && hour<12){ return "Good morning!"; }else if(hour>=12 && hour<19){ return "Good afternoon!"; }else{ return "Good night!"; } }}
这次重构虽然使程序结构发生了较大变化,但其中真正执行的代码却没有变化,还是那些代码。随后,我们核对需求发现,用户需求分成了两个不同的分支:对用户问候语的变更,和关于时间的问候语变更。为此,我们再次对HelloWorld的程序进行了分裂,运用重构中的“抽取类”,将对用户问候的程序分裂到GreetingToUser类中,将关于时间的问候程序分裂到GreetingAboutTime类中:
/** * The Refactoring's hello-world program * @author fangang */public class HelloWorld { /** * Say hello to everyone * @param now * @param user * @return the words what to say */ public String sayHello(Date now, String user){ GreetingToUser greetingToUser = new GreetingToUser(user); GreetingAboutTime greetingAboutTime = new GreetingAboutTime(now); return greetingToUser.getGreeting() + greetingAboutTime.getGreeting(); }}
/** * The greeting to user * @author fangang */public class GreetingToUser { private String user; /** * The constructor with user * @param user */ public GreetingToUser(String user){ this.user = user; } /** * @return greeting to user */ public String getGreeting(){ return "Hi, "+user+". "; }}
/** * The greeting about time. * @author fangang */public class GreetingAboutTime { private Date date; public GreetingAboutTime(Date date){ this.date = date; } /** * @param date * @return the hour of day */ private int getHour(Date date){ Calendar calendar = Calendar.getInstance(); calendar.setTime(date); return calendar.get(Calendar.HOUR_OF_DAY); } /** * @return the greeting about time */ public String getGreeting(){ int hour = getHour(date); if(hour>=6 && hour<12){ return "Good morning!"; }else if(hour>=12 && hour<19){ return "Good afternoon!"; }else{ return "Good night!"; } }}
(续)
相关文档
[url=http://fangang.iteye.com/blog/1985399]遗留系统:IT攻城狮永远的痛[/url]
[url=http://fangang.iteye.com/blog/1986749]需求变更是罪恶之源吗? [/url]
[url=http://fangang.iteye.com/blog/1988080]系统重构是个什么玩意儿[/url]
[url=http://fangang.iteye.com/blog/1998147]我们应当改变我们的设计习惯[/url]
[url=http://fangang.iteye.com/blog/1999066]小步快跑是这样玩的(上)[/url]
[url=http://fangang.iteye.com/blog/1999068]小步快跑是这样玩的(下)[/url]
[url=http://fangang.iteye.com/blog/2002581]代码复用应该这样做(1)[/url]
[url=http://fangang.iteye.com/blog/2002582]代码复用应该这样做(2)[/url]
[url=http://fangang.iteye.com/blog/2002585]代码复用应该这样做(3)[/url]
[url=http://fangang.iteye.com/blog/2010722]做好代码复用不简单(1)[/url]
特别说明:希望网友们在转载本文时,应当注明作者或出处,以示对作者的尊重,谢谢!
小步快跑是这样玩的(上)相关推荐
- 小步快跑是这样玩的(下)
系统重构到这一步,我们来看看用户关于时间问候语部分的变更需求:问候需要更加精细,如中午问候"Good noon! ".傍晚问候"Good evening! ". ...
- 大话重构连载11:小步快跑是这样玩的
说了那么多,相信你对小步快跑的概念有了一个初步的印象,但理解还不是很深.让我们来看一看一个实际工作中的例子,来亲身感受一下什么是大布局,什么是大设计,什么是小设计. 还是回到前面那个Hello Wor ...
- 创业者如何小步快跑,从0开始实现自己的产品?
2019独角兽企业重金招聘Python工程师标准>>> 某周末和学员聊完,兴起,在在行上的分类里面找自己.可是在产品里面,找来找去,完全不见踪影,反而在研发和运营里面找到了我的话题, ...
- log4net直切ElasticSearch,小步快跑首选
很多小步快跑的公司,开发人员可能就3-4个,面对巨大业务压力,日连夜的赶着上线,快速试错,自然就没时间搭建一些基础设施,比如说logCenter,但初期项目不稳定,bug又多,每次都跑到生产去找日志, ...
- 弘辽科技:淘宝悄悄公布新规,在电商赛道小步快跑。
疫情又来了,全国人民的生活节奏再次慢了下来.线下生活越慢,对线上服务的要求就越高,尤其是电商. 今年刚开始,淘宝在不动声色中推出了不少新规则.先是年初灰度测试了"未发货秒退款",对 ...
- 小步快跑,快速迭代:安全运营的器术法道
作者 | 腾讯安全平台部 lake2 在进行安全体系建设工作的时候,人们往往容易看到的成果是新研发了一个安全系统,采用了一个新的技术,似乎做出一个系统采用一种技术就可以一劳永逸地解决某类问题了.可现实 ...
- 智能手机的终场战事:小步快跑进入“智慧时代”
撰文 / 张贺飞 编辑 / 沈洁 2022年的春季发布会,照旧是一番热闹景象. OPPO.荣耀.华为.三星等品牌陆续推出新品,经历过2021年的"小阳春"后,几乎所有的主流厂商都在 ...
- 基于JSoup库的java爬虫开发学习——小步快跑
因某需求,需要使用java从网页上爬取一些数据来使用,花了点时间看了一下JSoup,简单介绍一下 jsoup is a Java library for working with real-world ...
- 干货|软件开发,小步真能快跑吗?
点击上方"中兴开发者社区",关注我们 每天读一篇一线开发者原创好文 作者简介 作者乐攀是非常优秀的程序员,有10多年的程序设计和开发经验,近年来致力于敏捷软件开发管理和技术实践的落 ...
最新文章
- Xshell配置ssh使用密钥公钥(publice key)登录
- Zuul:构建高可用网关之多维度限流
- 8个容易被忽略但不能忽略的SD-WAN功能-Vecloud
- c++Selection Sort选择排序的实现算法(附完整源码)
- 画毛毛虫代码计算机图形学,考试计算机图形学考试计算机图形学.docx
- 一些Vue开发小技巧,让你开发更便捷
- 表生成器@TableGenerator
- element 输入框点击事件_Element Input输入框的使用方法
- vb 数组属性_[读书笔记]CSAPP:7[VB]机器级表示:函数
- 8.微服务设计 --- 监控
- hdu acm 1016
- (附源码)ssm自助游服务系统 毕业设计 250858
- thinkphp5.1接入银联支付
- buuctf————[羊城杯 2020]login
- 迪进面向ConnectCore系统模块推出Digi ConnectCore语音控制软件
- Python 【哔哩哔哩】短视频的自动上传与发布实例演示,,同时支持抖音、快手、小红书、微视、西瓜视频、微信视频号等平台的视频自动化同步发布
- 微信小程序-天气预报1.0版本
- linux_添加一个普通用户
- Pywin32:Python库的简介、安装和使用攻略
- GO/KEGG富集分析泡泡图中为什么基因的数目是小数?
热门文章
- 什么是Knife4j?
- OC语言——基本语法和思想
- mysql和虚拟主机区别_mysql和虚拟主机的区别是什么
- matlab用plot三点画圆_怎样用Matlab 过三个点画外接圆?
- 调焦后焦实现不同距离成像_相机的“对焦”和“变焦”,这二者有什么区别?...
- 二叉树的顺序结构及实现
- brew cask install 解决慢的问题
- 2006年最值得期待的大片
- php h5 调用摄像头_利用html5调用本地摄像头拍照上传图片
- perl脚本实战总结