zoukankan      html  css  js  c++  java
  • 重构之重与敏捷之轻身份证号重构回顾

    寻找重构的案例

    重构的案例不好选取,我们自己实际的项目当然有不少重构的情况,却不适合作为文章阐述出来。并不是因为保密的考量,而是业务本身的内容太复杂。当然,这个复杂是相对的,对短短一篇文章来说,那怕是最小一部分的业务逻辑拿出来,也显容量不够。而且,过多的阐述业务逻辑,导致喧宾夺主,掩盖了重构的注意力。所以,要选取一个大家都熟悉的东西,身份证号恰恰中了我第一个要求。

    即然是重构,必然要有个原始的版本,而且,要完成了实际的功能。开源中国的代码分享也刚好为我提供了一个资源库。代码分享这个平台,真是太理想了,代码规模不大不小,每一个分享又有一个明确的目标功能。
    看起来,确实是个金矿。可是随着深入的搜索查看,能进入我目标范围的却是寥寥无几。大部分代码只是粘合剂,把外部库的调用综合起来,完成一个任务而已。还有些代码,方法体太大,而代码却是简单重复,似乎重构的必要,却未能展现出重构该有的不同侧面,而且也有前面所提到的毛病,是粘合剂代码块。
    (本文版权属于© 2012 - 2013 予沁安

    而当我看到身份证这三个字,才眼睛一亮,看似简单的身份征号包括了太多内容:

    1. 它是一个典型业务域的Value Object(不要与C#语法概念的Value Object混淆),我们自己的系统中,刚好也有做一个身份证号值对象的想法。之前我们已经作一个月份对象(YearMonth),非常好用,但是,因为功能多代码量大,不适合作短篇。
    2. 它没有对外部库的依赖。不是说,我只能对这种独立的代码重构,而是限于篇幅和重点突出的考虑。
    3. 它的业务逻辑很大众化,谁没有身份证呢?
    4. 分享代码已经把足够的业务逻辑包含进起,我所做的就是保持这个不变全力集中在重构上。再完美不过的重构案例了。

    敏捷的方式重构和作文

    让子弹飞

    定下了目标,当开始做的时候,满脑子都是想法。原代码是Java,要改成C#; getXX可以用属性方式,更为简捷;既然是Value Object,似乎用Struct比用Class更合适;作为Value,它应该是个不变类(Immutable),因此不应该动态解析,在构造器中解析,更为恰当; Validation的实现也不太合适……
    是的,像我这样资深的敏捷实践者,在第一时间仍有这种冲动,太多想法马上实现的冲动。这其实是人的一种天性,没关系,我就让思维的子弹先飞一会儿。
    子弹乱飞之后的寂静,我想到的第一件事情就是补测试。说到测试,我用MSpec曾屡屡想为MSpec做个入门介绍,却一直未能成文,而直接使用MSpec的博文我却已经写了不少, 大家就在实际用例中学习Machine.Specification吧。
    说是补测试,其实从Java到C#的编泽错误修改已经开始了不少改动。测试这一块是原代码完全缺失,补上这个,可以说是重构的一部分。

    迭代一:

    准备工作做了不少,到最后,真正测试只写了一个GetAddress()。而这成为了我的第一天。第一个测试成为我第一天的目标,围绕这个目标,我放弃一切与此无关的工作,特别是之前子弹乱飞的内容。

    迭代二:

    第二天,要做的事情一下子非常明确,按部就班的把其它的功能测试一一补全:生日,性别等等。几乎不太用脑子,有时候,事情就是这样,有波涛汹涌,有风平浪静,唯有测试是船舵。
    从测试的条数来看,第二天进展很快。写出来的内容也显丰富。

    迭代三:

    第三天的进展就顺利多了。把各个功能测试一一补全通过,如生日,性别和验证。其中有个小插曲,验证逻辑提炼成独立的类。总结起来没有什么好说的,重构本身却有看头。

    迭代四:

    到了第四天,才真正开始做我想要做的事情,整理逻辑,清理代码。再加上代码覆盖工具DotCover的帮助,VS的复杂度分析,从另一个侧面对重构效果加以验证。其实应该在重构之前也分析一下代码,两相比较一下,效果会好很多。

    从此,xx和xx过上了幸福的生活......

    我的博文算是结束了,可是作为代码的改进,其实并没有结束,甚至我最开始的想法,有一部分都还没有完成,如struct。我还丢掉了一部分业务,如15位号码转换18位。这是作为重构的展示已经足够。最重要的是,我已经创立了一个健壮的<测试-实现>对,这个基础上你可以继续完善。

    代码本身的技术含量并不多,但重构的流程,任务细分,小步前进的理念,却表达的非常充分。作为体验,如果你能按照我走过的流程,再踏踏实实走一遍,会有完全不同的感觉。敏捷是实践,重构是实践,唯有实践才能体验实践。

    (本文版权属于© 2012 - 2013 予沁安 | 转载请注明作者和出处

    从优秀到卓越
    皓月碧空,漫野如洗,行往卓越的路上

  • 相关阅读:
    Python+Selenium隐式等待操作代码
    Python+Selenium显示等待操作代码
    Python+Selenium键盘的几种操作:send_keys(Keys.CONTROL,'a')
    Selenium find_element_by_css_selector定位输入框报selenium.common.exceptions.NoSuchElementException的解决方法
    Python+selenium 鼠标三种(双击/右击/悬浮)操作方式(附代码!!)
    Selenium之find_element_by_css_selector三种定位方法,附代码!
    《jmeter:菜鸟入门到进阶》系列
    软件测试最基础的的面试题目~
    .NET页面事件执行顺序
    如何在ashx处理页中获取Session值
  • 原文地址:https://www.cnblogs.com/Wonner/p/refactory_socialid_summary.html
Copyright © 2011-2022 走看看