第一行代码上面的CoolWeather app的地域查询部分已经熟悉了两遍。心里痒痒地进行了一次重构。
没有源代码的支持,一切的改动都是出自于你自己的想法,所以每一次卡壳的时候都要自己思考,而且修改一处bug会导致其他bug出现。这就是闷头自己写代码的下场吧。
其实很多的修改都是可以避免的,于是总结出了一下几点。
1、动手写代码之前,数据流的关系,基本的逻辑关系已经要清晰。
如CoolWeather中:
描绘出大概的逻辑。然后想想数据流是如何连接的。通过网站提供的地点的code可以唯一确定一个地方。那么把它作为主键,其他的都要围绕着展开。这一点后来我还要说。
2、进行代码重用的最重要的观点,如同《headfirst设计模式》中说的,要分清变的部分和不变的部分,然后分别下手,提取不变的部分进行重用,提取变的部分进行修饰。
通过上面的流程图我们可以看出来。Province,City,County三者的数据流程的相似的地方,都是查询数据库,没有的话再去网络加载,加载完毕后查询数据库。
同时数据结构上也有相似的地方。都拥有name和code,parentCode三个字段或者name,code,parent两个字段。相同的地方还有网络查询的网址都是某个网址+code+.xml。
那么不同的地方在哪里呢?其实流程的不同和数据结构的不同时一脉相承的。Province在最上层,其没有parentCode。而County在最下层,将其作为区域进行进一步的迭代查询可则会产生错误。
利用相似地方:
相似的逻辑数据结构->使用相同的Area数据结构包含最多的name,code,parentCode三个字段。
使用高级的查询低级->使用高级的Code进行数据库检索低级数据。
使用相似的网络查询(网址+code)->使用查询函数将parentcode进行网络低级查询。
不一样的地方:
Province没有上一级,无法通过上一级code进行查询->将Area的code字段初始化为空字符串,避免空指针异常。检测code为空字符串判断为Province。
County没有下一级,作为关键字查询数据库和网络都是逻辑错误->检测出County后将其任务函数留空。
在实践中还是不可避免地出现了一些问题。不过也学到了不少。
(第一次重构的github链接:https://github.com/maxinzhe/CoolWeather5点击打开链接 )
1、sendHttpRequest函数中启动了新的线程去查询网络获取对象。这时本来打算在查询结束后进行查询并更新uI的函数就会同步和网络查询并行。导致再次查找为空进行网 络查询。使得最后的列表中有了很多的重复的对象。——>将查询函数放在网络查询的结尾进行执行,(如果使用sychornize不当还会导致第二次的查询。)
2、修改位置后的query()函数虽然避免了多线程的混乱,但是其中的adaper.notifiSetChanged()函数要刷新ui导致异常。——>将query加入到runOnUiThread进行执行。
3、犹豫重构中国只使用Code作为唯一的信息链接。导致返回上级菜单的时候无法获得上级的标题名称。——>建立栈来进行存储名字。但连续两级退出的逻辑上bug没有解 决。其实使用多个activity存在一个天然的栈可以逐级退出,但是本例中这里没有新建activity。
4、访问网络的编码中将存取结果存入了省级的数据库,导致仍然查询为空,而省级数据库重复添加了多次市级元素。——>数据结构的设计不够直观,容易造成误解。应该 将省和省下的市作为整体的数据结构。市和市下的县作为整体的的数据结构。在返回和查询的过程中进行压栈和弹栈的操作。整体取出数据结构。
除了以上的bug以外,还有一个感想。就是大的结构从一开始就应该考虑到所有的用例来进行设计。并尽量使用可靠的现成的结构去承载。出现bug后的补救修改虽然必要,但是由此造成的逻辑混乱会让进一步的修改举步维艰。