- 浏览: 538402 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
飞天奔月:
public List<String> gener ...
实践中的重构30_不做油漆匠 -
在世界的中心呼喚愛:
在世界的中心呼喚愛 写道public class A {
...
深入理解ReferenceQueue GC finalize Reference -
在世界的中心呼喚愛:
在世界的中心呼喚愛 写道在世界的中心呼喚愛 写道在classB ...
深入理解ReferenceQueue GC finalize Reference -
在世界的中心呼喚愛:
在世界的中心呼喚愛 写道在classB的finalize上打断 ...
深入理解ReferenceQueue GC finalize Reference -
在世界的中心呼喚愛:
iteye比较少上,如果可以的话,可以发e-mail交流:ch ...
深入理解ReferenceQueue GC finalize Reference
很多应用程序的主要目的就是用计算机来代替人处理真实世界中的问题。真实世界和计算机世界之间有着巨大的差异。编程语言,编程方法一直以来都有一个重要的发展方向,提供一个平台,尽量减少这个差异。面向对象语言,面向领域编程,为解决该问题在不同层次提供了解决方案。
在代码级别,也可以通过种种方式减少这个差异。
先看下面一段代码,需求和场景是这样的。
查询用户列表,传入一个整数,指定一次查询返回用户数的上限。
有3个不同的数据源可以用来查询用户信息,这3个数据源在查询的时候是有优先级的。即先查询第1个数据源,如果得到的用户数少于上限,则到第2个数据源查询,如果还是少于上限,则到第3个数据源查询。
如果你耐心的看完了这段代码,我只能说佩服了。一眼看到5层的if嵌套,我已经是半晕状态了。我承认,我没有耐心看完这段代码。
该方法的需求和场景都是比较简单的,因此应该存在简单的写法。
重写的代码如下:
这里首先对参数加上final修饰符,明确表明方法中不会修改该参数。其次,去除掉了if嵌套,用相似的代码结构试图更清晰更直白的表明这段代码的意图。
这段代码有这样一些小的问题,可以持续改进。
1 如果可以预期该方法返回的用户列表大小的话,可以设置初始的列表大小。
2 如果遵循查询结果为空,返回空列表而不是null的话,可以是代码更紧凑。
这样看上去好多了。这里遵循的原则就是平铺直叙的用编程语言翻译需求,试图用接近自然语言的表达方式实现需求,从而减少两个世界的差异。
更好的一种方式是先用自然语言(或者伪代码)描述需求的实现,然后翻译成真正的代码。
用自然语言描述这个需求的实现如下:
1 新建一个空的用户列表。
2 计算下一次查询的上限。
3 到数据源1去查询。
4 添加结果到用户列表。
5 如果用户列表达到上限则返回。
6 计算下一次查询的上限。
7 到数据源2去查询。
8 添加结果到用户列表。
9 如果用户列表达到上限则返回。
10 计算下一次查询的上限。
11 到数据源3去查询。
12 添加结果到用户列表。
13 返回。
这个实现的描述和真实的实现很像,即使没有实现,看着这个自然语言的实现翻译成对应的代码实现也很容易。
当然,计算机编程是复杂的,这里的实现还是有一个潜在的问题。代码中有重复的结构。鉴于这里的实现已经比较简单了,所以没有进一步去掉这个重复的结构。但是,如果需求改变,需要查询更多的数据源,或者可配置的数据源,代码可以做以下演进。
在方法体中,方式1和方式2都是可行的。对于简单的循环,尾部的一个判断跳出看上去比一个多行的条件判断更清晰一点。
在代码级别,也可以通过种种方式减少这个差异。
先看下面一段代码,需求和场景是这样的。
查询用户列表,传入一个整数,指定一次查询返回用户数的上限。
有3个不同的数据源可以用来查询用户信息,这3个数据源在查询的时候是有优先级的。即先查询第1个数据源,如果得到的用户数少于上限,则到第2个数据源查询,如果还是少于上限,则到第3个数据源查询。
public List<User> getUserList_0(int maxSize) { List<User> userList; int selectSize = 0; userList = getUserListFromSource1(maxSize); if (null != userList) { if (userList.size() < maxSize) { selectSize = maxSize - userList.size(); List<User> userList2 = getUserListFromSource2(selectSize); if (null != userList2 && !userList2.isEmpty()) { userList.addAll(userList2); if (userList.size() < maxSize) { selectSize = maxSize - userList.size(); List<User> userList3 = getUserListFromSource3(selectSize); if (null != userList3 && !userList3.isEmpty()) { userList.addAll(userList3); } } } } } else { userList = getUserListFromSource2(maxSize); if (userList.size() < maxSize) { selectSize = maxSize - userList.size(); List<User> userList4 = getUserListFromSource3(selectSize); if (null != userList4 && !userList4.isEmpty()) { userList.addAll(userList4); } } } return userList; }
如果你耐心的看完了这段代码,我只能说佩服了。一眼看到5层的if嵌套,我已经是半晕状态了。我承认,我没有耐心看完这段代码。
该方法的需求和场景都是比较简单的,因此应该存在简单的写法。
重写的代码如下:
public List<User> getUserList_1(final int maxSize) { List<User> userList = new ArrayList<User>(); List<User> temList; int selectSize = maxSize - userList.size(); temList = getUserListFromSource1(selectSize); if (temList != null) { userList.addAll(temList); } if (userList.size() >= maxSize) { return userList; } selectSize = maxSize - userList.size(); temList = getUserListFromSource2(selectSize); if (temList != null) { userList.addAll(temList); } if (userList.size() >= maxSize) { return userList; } selectSize = maxSize - userList.size(); temList = getUserListFromSource3(selectSize); if (temList != null) { userList.addAll(temList); } return userList; }
这里首先对参数加上final修饰符,明确表明方法中不会修改该参数。其次,去除掉了if嵌套,用相似的代码结构试图更清晰更直白的表明这段代码的意图。
这段代码有这样一些小的问题,可以持续改进。
1 如果可以预期该方法返回的用户列表大小的话,可以设置初始的列表大小。
2 如果遵循查询结果为空,返回空列表而不是null的话,可以是代码更紧凑。
public List<User> getUserList_2(final int maxSize) { List<User> userList = new ArrayList<User>(maxSize); int selectSize = maxSize - userList.size(); userList.addAll(getUserListFromSource1(selectSize)); if (userList.size() >= maxSize) { return userList; } selectSize = maxSize - userList.size(); userList.addAll(getUserListFromSource2(selectSize)); if (userList.size() >= maxSize) { return userList; } selectSize = maxSize - userList.size(); userList.addAll(getUserListFromSource3(selectSize)); return userList; }
这样看上去好多了。这里遵循的原则就是平铺直叙的用编程语言翻译需求,试图用接近自然语言的表达方式实现需求,从而减少两个世界的差异。
更好的一种方式是先用自然语言(或者伪代码)描述需求的实现,然后翻译成真正的代码。
用自然语言描述这个需求的实现如下:
1 新建一个空的用户列表。
2 计算下一次查询的上限。
3 到数据源1去查询。
4 添加结果到用户列表。
5 如果用户列表达到上限则返回。
6 计算下一次查询的上限。
7 到数据源2去查询。
8 添加结果到用户列表。
9 如果用户列表达到上限则返回。
10 计算下一次查询的上限。
11 到数据源3去查询。
12 添加结果到用户列表。
13 返回。
这个实现的描述和真实的实现很像,即使没有实现,看着这个自然语言的实现翻译成对应的代码实现也很容易。
当然,计算机编程是复杂的,这里的实现还是有一个潜在的问题。代码中有重复的结构。鉴于这里的实现已经比较简单了,所以没有进一步去掉这个重复的结构。但是,如果需求改变,需要查询更多的数据源,或者可配置的数据源,代码可以做以下演进。
interface UserQueryService { List<User> queryUserList(int maxSize); } class UserQueryServiceImpl_1 implements UserQueryService { @Override public List<User> queryUserList(int maxSize) { return getUserListFromSource1(maxSize); } } class UserQueryServiceImpl_2 implements UserQueryService { @Override public List<User> queryUserList(int maxSize) { return getUserListFromSource2(maxSize); } } class UserQueryServiceImpl_3 implements UserQueryService { @Override public List<User> queryUserList(int maxSize) { return getUserListFromSource3(maxSize); } } public List<User> getUserList_3(final int maxSize) { // 这里的userQueryServices可以从配置文件中生成,也可以用户传入。 // 这里为了演示,硬编码一下。 List<UserQueryService> userQueryServices = new ArrayList<UserQueryService>(); userQueryServices.add(new UserQueryServiceImpl_1()); userQueryServices.add(new UserQueryServiceImpl_2()); userQueryServices.add(new UserQueryServiceImpl_3()); List<User> userList = new ArrayList<User>(maxSize); // 方式1 for (UserQueryService service : userQueryServices) { int selectMaxSize = maxSize - userList.size(); userList.addAll(service.queryUserList(selectMaxSize)); if (userList.size() >= maxSize) { break; } } // 方式2 for (int i = 0; i < userQueryServices.size() && userList.size() < maxSize; i++) { UserQueryService service = userQueryServices.get(i); int selectMaxSize = maxSize - userList.size(); userList.addAll(service.queryUserList(selectMaxSize)); } return userList; }
在方法体中,方式1和方式2都是可行的。对于简单的循环,尾部的一个判断跳出看上去比一个多行的条件判断更清晰一点。
发表评论
-
simplehbase v0.98.1开始支持hbase0.98
2014-12-29 21:52 781https://github.com/zhang-xzhi/s ... -
hbase轻量级中间件simplehbase v1.0简介
2014-12-13 18:56 951https://github.com/zhang-xzhi/s ... -
hbase的CoprocessorProtocol及一个简单的通用扩展实现V2
2014-12-04 18:02 865hbase中的CoprocessorProtocol机制. ... -
hbase 0.94.0 0.94.9 0.94.24 功能不兼容初步分析
2014-12-04 16:14 612hbase 0.94.0 0.94.9 0.94.24 功能不 ... -
可以查看java对象的MemoryUtil简介
2014-09-14 21:01 1262MemoryUtil 关于java对象内存的基本知识,请参考 ... -
java对象的大小_基础知识
2014-09-14 20:59 988引言 Java的对象被jvm管理,单个对象如何布局,大小如何, ... -
gcviewer v0.3 一个解析CMS GC日志的GUI程序
2014-09-07 23:00 1089GCviewer https://github.com/z ... -
simplehbase版本变更
2014-07-14 13:42 740https://github.com/zhang-xzhi/s ... -
hbase ORM simplehbase/simplehbaseviewer v0.8简介及使用说明
2014-05-07 00:50 1035https://github.com/zhang-xzhi/s ... -
HBase Client使用注意点
2014-04-21 12:52 1957HBase Client使用注意点: 1 HTable线程 ... -
文件编码自动检测及编码转换encodechecker v0.5
2014-04-15 00:35 1825由于很多软件都不能准确自动识别文件编码,因此写了个文件编码识别 ... -
[perf] java常用基本操作性能测试-异常
2014-03-08 09:53 1160性能测试: 由于软硬件及其复杂,本结果只具有参考意义。 代码: ... -
[perf] java常用基本操作性能测试-反射
2014-03-07 13:06 1078性能测试: 由于软硬件及其复杂,本结果只具有参考意义。 代码: ... -
hbase轻量级中间件simplehbase v0.2简介
2013-12-22 17:58 1510https://github.com/zhang-xzhi/s ... -
mysql的一些性能数据
2012-12-01 16:04 974这个并不是一个严谨的性能测试,而是就简单的一些场景记录一些数据 ... -
有关于时间
2012-12-01 15:55 948int型如果表示ms的话,那也就是24天而已。 double ... -
我对移位操作的误解
2012-11-30 20:52 955一直以为java的移位操作只能操作int,原来是自己的误解。l ... -
Java Concurrency in Practice读书笔记
2011-08-13 10:03 2927目录 Chapter 1. Introduction 2 1. ... -
bug fix 记录
2011-01-07 21:58 1208p1 Caused by: org.xml.sax.SAXP ... -
实践中的重构01-05
2010-11-13 01:06 1179目录 实践中的重构01_ ...
相关推荐
在文字叙述上,本书摒弃了枯燥的平铺直叙,采用案例与问题引导式;同时,本书还增加了“温馨提示”、“例程一点通”、“经验分享”、“一语中的”等版块,彰显了本书以读者为本的人性化的特点。
【思路】:建议大家用2分钟得自我介绍,面试官较喜欢的自我介绍(1)有亮点,每一小段都有一个亮点,而不是平铺直叙(2) 有互动:每一小段都会和面试官互动,而不是自说自话,但是切记,这种互动并不需要面试官配合...
“平铺直叙”则形容一种直接叙述的方式,符合语境;“言不及义”通常指言语空洞、无关紧要,但若用于翻译不准确则有失偏颇;“山高水低”本指意外的不幸,若用于描述领略路途的美景则不太恰当;“目不交睫”形容人因...
C语言作为一门基础且重要的编程语言,其教学方式长期以来多采用传统的平铺直叙方式,导致学生难以产生浓厚的学习热情。针对这一问题,文章提出了以案例为中心的教材改革策略。 C语言自1972年诞生以来,因其功能强大...
由于学生的基础层次不一,教师平铺直叙的讲解方式难以激发学生的兴趣,导致学生对PLC的工作原理和程序设计的理解不深入,难以做到熟练应用和独立思考。这直接影响了学生在实验中的操作能力和创新能力。 2. 缺乏实际...
信息技术学科包含许多专业性的知识和术语,传统的平铺直叙往往难以激发学生的学习兴趣。作者建议在课前设置自主体验任务,例如让学生为Python制作自我介绍,这样既可以使学生带着问题走进课堂,又可以在教师的引导下...
书中内容并非平铺直叙,而是将神经生物学、认知心理学和学习理论等研究领域的最新成果融入教学之中,使读者在探索网页设计的过程中,通过生动有趣的方式,激发学习HTML、CSS和XHTML的兴趣。 HTML是构建网页的骨架,...
反问句往往用于强调说话者的强烈情感或明确立场,而陈述句则平铺直叙,更为客观冷静。在实际教学中,教师应注重句式的语境分析,让学生通过实例来理解这些句式的不同用途,而不仅仅是停留在表面形式上的比较。 综上...
5. **概述法**:这是一种按照时间顺序、逻辑层次或因果关系进行讲解的方法,也称作平铺直叙,常用于概括性介绍景点或事件。 6. **触景生情法**:此方法要求导游根据眼前的景色引发情感,借题发挥进行讲解,要求自然...
教学内容不再仅仅是知识点的平铺直叙,而是围绕核心教学目标和任务进行合理地组织与展开。这种方法有助于学生明确学习目标,减少学习的盲目性,让学生在学习过程中更有方向感和目的性。 对于学生而言,任务驱动教学...
初期的习题课和新课教学让实习生积累了宝贵经验,同时也暴露了一些问题,如紧张、讲解过于平铺直叙、课堂控制不够灵活等。通过指导教师的反馈和自我反思,实习生逐渐改进,提高自己的教学水平。 在班主任实习方面,...
崔老师在未来的教学中可以更加注重语言表达的生动活泼,避免平铺直叙。在讲解作画方法和欣赏作品时,应该注意逻辑顺序,减少语言上的冗余,以提高教学效率。只有这样,才能确保每个学生都能在愉快的氛围中有效学习。...
比如,伯瑙德夫人的智斗故事被详尽描绘,而敌人的简单搜查则一带而过,通过这样的案例分析,学生能够理解如何根据文章主题的需要来确定内容的详略,避免文章内容平铺直叙,缺乏波澜。 同时,教师还提供了多个写作...
他的小说不满足于平铺直叙地讲述故事,而是将历史的背景和个体的遭遇紧密地结合起来。在这样的叙述中,历史不再是单纯的时间和事件的叠加,而是转化为小说中人物的生活经验和心理状态的投影。双雪涛通过个人命运的...
传统教学中,教师往往平铺直叙地讲解,而忽视了激发学生兴趣的关键点。例如,李明芳老师在教授《丑小鸭》这一课时,选择了丑小鸭的“不幸”话语作为导入,成功地吸引了学生的注意力,并引导他们深入文本,挖掘背后的...
教师在引导学生进行课堂活动时,有时语言可能过于平铺直叙,缺乏感染力,这可能会让学生们的兴趣有所下降。体态语言作为无声的教育手段,其运用也需要更为精准和多样化,这样才能更有效地抓住学生的眼球,使他们更...
通过这样的学习,学生可以领悟到在写作中如何运用细节来突出人物性格,而不仅仅是平铺直叙地描述事件。这种写作技巧的学习,是语文教学中不可或缺的部分,它能够有效地提升学生的写作能力和对人物描绘的敏感度。 ...
4. **突出重点和亮点**:在汇报中,强调方案的独特性和价值点,避免平铺直叙。这可以通过使用案例、数据和视觉工具来增强说服力。 5. **共鸣与互动**:尝试与听众建立共鸣,让他们参与到讨论中来,而不是单方面的...
本书的标题“Head First Python”暗示了其教学方法,即通过直观、互动的方式,以问题和答案的形式引导读者思考和学习,与传统的平铺直叙的教学方法有所不同。这种方法也被其他“Head First”系列书籍所采用,例如在...
此外,侯方域在描述两位演员较量时,并没有平铺直叙,而是巧妙地通过观众的反应来凸显双方技艺的高下,细节的描写让角色形象更加立体。比如李伶的第一次胜利后,观众的热烈反响以及第二次较量后李伶的谦卑态度,这些...