11 2012 档案
摘要:最后我们来讲一下代码风格的问题1. 魔法数字,也有叫数字常量的 总之,就是一个数字戳在那,谁也不知道这是什么意思, 这种代码还会导致一个问题就是代码的值发生变化的时候,无法确保所有的相关代码都得到修改。 OpenWnn里这种情况太多了,就不一一列举了。 同样的字符串常量也是一个问题。 对于这种情况,定义成常量并不是解决问题的唯一办法,还有很多更好的办法,比如,拆分类。2. 静态表 Java代码中的静态块static{}可以让一部分固定的赋值代码提前执行,但是如果用不好这个特性,反而这个会成为代码的问题。 RomKan代码中的romkanTable ,表示输入的英文字母是如何转换成为假名的。 但
阅读全文
摘要:结构问题是所有问题中最严重的问题,这里的很多问题都反映了作者缺少基本常识。代码的结构就像房屋的结构一样,是支撑整个代码的框架。如果房屋的结构不够结实,房屋就会倒塌。如果代码的结构不够良好那么修改Bug或者对应需求变更的时候就要付出昂贵的代价。1. 缺少MVC结构 严重程度:非常高 输入法和其他应用程序一样,都是由:数据(Model),视图(View)和控制器(Control)构成的,但是OpenWnn没有按照MVC划分类包,也难以区分哪部分代码是数据,那部分代码是视图。2.错误的从属关系 严重程度:非常高 各种对象之间应该有一定的从属关系,例如:图书管理有书架,书架上面有图书。就绝不可以说书里
阅读全文
摘要:接前文,我们继续分析OpenWnn的注释问题1. 为了注释而注释 严重程度:中 注释就是把方法或者变量的名称再重写一遍,这种工作纯属是浪费时间,可以不用花费这种工时。/** Current key-mode */ protected int mCurrentKeyMode; 这种情况在OpenWnn中特别多。2. 啰嗦的注释 严重程度:低 本来可以很短就能够写完的注释,却要写很长的注释,结果也没有因为写的长对于理解产生有益的帮助。 这种情况在OpenWnn中非常少。3. 步步皆注释 严重程度:中 这种情况会拉开代码间距,使代码变得不再流畅。 这种情况在OpenWnn中也非常少。4.缺少注释..
阅读全文
摘要:什么是错题本? 最近一直有热心读者提出:能否找到一个写的不太好的工程例子,然后解析其中的代码错误,让我们能够从中更为直观的体会到糟糕的代码书写。这么多年接触了许多糟糕的代码,但是苦于不能公开,也难以做到。不过,后来接触到了OpenWnn,这是一个很好的工程,它的代码中几乎充斥着各种各样的代码书写坏习惯。就好像中学生的错题本一样,打开一看都是各式各样的错误。足以警醒以后不再犯同样的错误。本章我们将对OpenWnn的代码问题进行解析,从命名、注释、结构和风格四个方面分别进行阐述。什么是OpenWnn呢? 我在前面的博客里至少两次提到这个工程。这是一个Android下的开源日文输入法,由Omron
阅读全文
摘要:今天又写了一个游戏 ——连连看,这个是个很经典的游戏,我也想来试试看,如何实现它。关键部分在于如何判定两个选中单元格是可以相连的。经过分析,可以看到,连接的方式为一下几种模式不管上述的哪种模式,都可以总结为如下的公式:沿着x方向的所有x进行遍历,对于任何一个x来说,y1-y2之间的连接线如果是可以连接的,而且,x1,y1~x,y1和x2,y2, x, y2之间都是可以连通的,那么这两个点就是可以连接的。具体算法实现如下: 1 package org.stephen.connecty.control; 2 3 import org.stephen.connecty.model.Cell; 4 .
阅读全文
摘要:好了,代码已经写到这里,基本功能都具备了,下面来进行一些收尾工作吧。1. GameOver的判定。首先在每次消除以后都进行GameOver判定。1 if (game.isOver()) {2 EventDispatcher.send(Event.GAME_OVER);3 }然后实现GameOver判定算法。 1 public boolean isOver() { 2 for (int x = 0; x < ROW_COUNT; x++) { 3 for (int y ...
阅读全文
摘要:接上节我们发现的遗留问题。先来解决GridBagLayout的问题。MainFrame.build方法修改如下: 1 public void build() { 2 this.setLayout(null); 3 this.setSize(480, 480); 4 balls = new JButton[12][12]; 5 6 for (int y = 0; y < 12; y++) { 7 for (int x = 0; x < 12; x++) { 8 JBu...
阅读全文
摘要:下一步,我们来实现消除。消除分两步,第一步消除选中的小球,第二步,降落。先说消除,在BallActionListener中进行分支处理即可。1 public void actionPerformed(ActionEvent e) {2 Game game = Game.getInstance();3 if (game.isSelectedBall(x, y)) {4 game.destroySelectedBalls();5 } else {6 game.startSelect(x, y);...
阅读全文
摘要:然后,我们实现点击小球的动作。点击小球的时候,分为两步,第一步:选中;第二步,清除。本章先研究选中。首先,我们需要了解点击的小球的位置,但是,之前的设计并没有传入相关的参数。所以我们先来重构BallActionListener 1 package org.stephen.bubblebreaker.listener; 2 3 import java.awt.event.ActionEvent; 4 import java.awt.event.ActionListener; 5 6 import org.stephen.bubblebreaker.control.EventDispatche..
阅读全文
摘要:本章,我们来讨论如何为游戏加上动作。先从整体上考虑,很多Java例子程序喜欢直接在代码中加入:button.addActionListener(new ActionListener() { public void performAction(Event e) {}});这样的代码。这是不好的,因为这不符合单一职责原则,ActionListener应该独立出去,单独成类。这样,当发生问题的时候也容易寻找。有两种形式,一种是本文采用的单独成类的形式,另外一种是在对应的对象中声明内部类。例如:class MyButton.ActionListener {}。整体上来讲,我们会加入:StartActi
阅读全文
摘要:在写了这么多理论之后,读者都对实践比较感兴趣。那么如何写自表达代码呢?我们跳开理论部分(以后我会补充理论部分),直接进入实践部分,从本章开始,将以消小球这个游戏为例,以Java代码为样本,引导大家一步一步书写自表达式代码。消小球是一款见于Windows Mobile上的游戏,在12x12的方格子里随即放置各种颜色的小球。选中至少两个相邻的同颜色小球,再次点击,就消除选中的小球,消除的小球的个数累加作为得到的分数,消掉小球以后上面的小球会降落,某列被消除以后,会将其左边的列拉过来,直到无法继续消除位置。好了,游戏规则介绍完毕。那么我们开始在Eclipse里建立工程。Java工程,名称Bubble
阅读全文
摘要:CVS全称叫做:Concurrent Version System。并发版本系统。经常出现命令运行错误且不易修复。有Eclipse插件Visual Source Safe官方提醒需要经常备份数据。和Visual Studio结合的很好。需要用锁来工作,一旦锁定别人无法打开。会造成死锁文件问题。SVN全称叫做Subversion。常用的免费工具,许多开源工程用的就是Subversion有Eclipse插件保存修改履历git分布式版本管理工具免费工具有Eclipse插件能进行变更跟踪运行速度快采用分布式存储,数据更加稳定和Linux结合的更好。Android采用的就是git管理的代码。
阅读全文
摘要:配置管理(Configuration Management)是为了确保软件开发过程中的产品的一致性、稳定性、可追溯性、回滚性等一系列目的而采取的技术上和管理上的手段的总称。往往由于软件开发过程当中重心放在了“开发”本身,配置管理往往被当成了不重要的环节而被忽略了。提起配置管理,很多人都会认为把文档和代码放在版本管理工具里就叫做配置管理了。顶多是做做目录划分,权限设置,签入签出规则设定等。做到上述这些只是做到了版本管理(Version Control),而不是配置管理。除了上述这些之外,配置管理还要求能够保证灵活性、时效性等目的。另外,做好配置管理的一个重要的作用是高效快速而稳定的发布系统。在开
阅读全文
摘要:假设我们在测试一个电子邮件地址的网页输入框,下面是相关的需求描述:当该文本框输入一个“电子邮件”以后,点击保存按钮,如果输入的是正确的电子邮件地址,则转入下一页,否则提示一个消息框,显示“你输入的不是合格的电子邮件,请重新输入”。点击“确认”按钮以后,焦点回落在电子邮件地址输入框里,并且光标放在文本框最后一个文字后面。没有选中文字。原来的输入文字内容不变。那么我们应该测试多少?1. 对话框显示的消息是否要测试?2. 对话框的确定按钮点击是否要测试?3. 对话框的关闭按钮点击是否要测试?4. 焦点回落是否要测试?5. 光标位置是否要测试?6. 选中文字是否要测试?7. 文本框的文字内容是否要测试
阅读全文
摘要:我们以Android平台下的输入法为例。假设在OpenWnn输入法(代码请到http://source.android.com/source/downloading.html上找),接入硬件盘的时候,日文输入模式下,按下Shift + T键输入的不是T。应该怎么定位?onKeyDown(int keyCode,KeyEvent event)是入口,然后找到硬件盘的处理方法onEvent();然后再继续找processHardwareKeyboardInputChar(),再继续...再继续...----这种恶梦式的Bug定位主要原因是代码的架构问题。代码的架构不够清晰导致Bug发生时无法快速定
阅读全文
摘要:假设有一个文本框,需要校验输入内容是否是电子邮件,那么应该测试多少种用例呢?1. 英文的电子邮件地址 abc@gmail.com2. 带下划线,点号的电子邮件地址 a.b.c@gmail.com a-b-c@gmail.com a-b.c@gmail.com a.b-c@gmail.com a.b@gmail.coma-b@gmail.com a_b@gmail.com a.b_c@gmail.com a-b_c@gmail.com a_b_c@gmail.com3. 很长的电子邮件地址 abcdefghijklmnopqrstuvwxzy@gmail.com4.纯数字的电子邮件地址 123.
阅读全文
摘要:完成一个级联下拉列表框(例如:省市联动)需要多少行代码呢?问过若干人,答案从100行到几万行的都有。那么对于一个二级联动下拉列表框需要这么多代码的话,那么一个四级的联动下拉列表框(比如:品牌、分类、类型、型号)又需要多少行代码?对于这个问题,我们推荐的是,每个增加一个下拉列表框只要2行。当然,这没有计算写成通用结构的代码。那么,我们来看看是什么样的代码能够通用到这种程度,可以每增加一个下拉列表框只需要2行就可以了。为了简单起见,我们采用两套级联下拉列表框来实现例子。一个是省市下拉列表框,另一个是产品下拉列表框。先上代码: 1 <HTML encoding="UTF-8"
阅读全文
摘要:假设书写一个网上售书系统,其中一个图书编辑页面,如果可以写成这样,你会怎么感觉? 1 <HMTL> 2 <head> 3 #{title 'BookEdit.Edit'/} 4 </head> 5 <body> 6 #{form action='BookEdit.save()'} 7 #{EditBar title='book.edit.isbn', text=${Book.isbn} /} 8 #{EditBar title='book.edit.name', text=${Boo
阅读全文
摘要:加班费本来是保护劳动者的制度。但是实际操作中,它却沦为赏恶罚善的工具,促使着企业朝着更差的方向发展。我并不是要反对加班费制度,毕竟这种对于劳动者的保护制度应该拥护。但是,如果研究加班的产生原因以及结果,就不难发现加班费其实滋长了加班,并降低了开发效率。这是一个行为模式的问题:加班 -> 加班费(经济补偿) -> 没有人约束 -> 继续加班 -> 得到更多经济补偿 -> 故意降低效率。如果降低效率可以拿到加班费,并且,如果长期降低效率的话,可以拿到很多加班费。当问题第一次发生的时候,那是问题。当问题第二次发生的时候,那叫重复问题。当问题连续三次发生的时候,那就应该叫
阅读全文
摘要:软件开发的行业标准是按照工时收费。企业一般按照下列公式来计算收费、成本和毛利润的。 收费额度 = 估算的开发工时 x 工时单价直接成本 = 开发工时 x 工时平均成本 毛利润 =收费额度 - 直接成本 如果开发投入工时和估算的工时相等的情况下,毛利润 = (工时单价 - 平均成本) x 投入工时那么,企业在某个人身上全年的收益按照如下公式计算收益 = 单价 x有工作的工时- 成本价 x 全年的时间 所以,开发企业为了提高收益率,往往会关注一个指标:稼动率(即:工作饱满度) 稼动率 = 有工作的时间/全年的时间 全年的时间是个固定值,所以雇主会尽量的增加员工的有工作时间,以保持利润水平。当然,降
阅读全文
摘要:1.面向对象编程(Object Oriented Programming) 面向对象编程把所有的事物都抽象为对象。即使虚拟的存在也要抽象为对象,比如:关系,状态;有些即使在客观世界中不被定义为对象的东西在面向对象的世界里也会被定义为对象,比如:行为,动作。 和面向过程编程强调:顺序、选择、循环不同,面向对象强调:包含、继承、实现、组合这些关系。面向对象的特点是:封装(Encapsulate)、多态(Polymophism)和继承(Inheritage)。2.依赖注入(Dependency Injection) 当依赖是动态的时候,可以通过在外部配置依赖类的名称的方式,通过反射来将依赖逐步引入。
阅读全文
摘要:RumtimeException是一种UncheckedException。UncheckException是一种不需要在方法签名中声明的异常类型。广为知道的RuntimeException的子类有NullPointerException,StringOutOfBoundsException。ArrayIndexOutOfBoundsException之类的。在代码运行的过程中由于变量为空或者数组越界等情况就会发生这种异常。当异常发生的时候,由于没有try-catch会产生程序意外退出的情况。为了避免发生这种异常而导致应用程序意外退出,需要对代码进行try-catch或者是在调用前进行非空判定
阅读全文
摘要:自表达代码的的特点1. 代码的返回值意思明确看一个报名程序的书写,这是采用非自表达方式书写的。 1 public String registerLesson(int userId, int lessonId) { 2 int code = checkUserId(userId); 3 if (code != 0) { 4 return "user does not exist."; 5 } 6 7 code = checkLessonId(lessonId); 8 if (code != 0) { 9 return "l...
阅读全文
摘要:详细设计是V模型或者瀑布开发中的一个重要的环节。这个阶段负责把概要设计进行细化,并为代码书写作出指导。可以说是一个承上启下的重要环节。但是现实的情况真的如此吗?我们来反思一下:(1)详细设计和代码的吻合程度有多高? 假设在项目中,代码在测试后修改完毕提交后,并不修改详细设计,则详细设计和代码之间并不吻合,并且很大程度上,吻合度会非常低。 如果详细设计和最终的代码并不吻合,那么这样的详细设计并不能给将来的维护带来任何帮助。 如果详细设计并不能给后续带来帮助,为什么要书写它呢?因为——详细设计是用来指导代码书写的。(2)详细设计对代码的指导意义有多大? 详细设计的类图是用来定义类框架之间的关系的;
阅读全文
摘要:除前文所介绍的技巧之外,下列的内容也往往由于不知道而没有加以利用。1. transient关键词2. volatile关键词3. static块4. inline关键词5. Serializable接口6. synchronized关键词下述的方法7.toString()方法8.clone()方法9.equals()方法10.getClass()方法*这一章简略写了。
阅读全文
摘要:劣质代码产生的另外一个原因是管理者的误导,具体的误导行为有如下几种形式:1. 莫名其妙的代码规范 代码规范是为了能够让团队的程序员写出的代码像是一个人写的。本身是好事,但是如果代码规范制定的时候只是照搬照抄,那么代码规范很可能沦为损害代码质量的帮凶。 A. 每行修改的代码都要加注释每行修改的代码都要增加注释是在没有版本管理工具的时候的做法。因为这样可以对比修改的代码。 这种代码的修改方式导致了一个很重要的功能——重构——无法使用。因为每次重构的时候都会变更很多代码,并且没有增加注释。 正确的做法是把修改履历增加到版本工具里。 B. 修改时减少代码的修改量 修改代码时尽量减少代码的修改量是为了减
阅读全文
摘要:我们在研究自表达代码之前,首先要先弄明白代码的本质。在研究代码的本质之前,我们看一下音乐设备的发展:留声机 -> 磁带 -> CD -> Mp3不论设备怎么变化,有一点没有变化的是:这些设备都是用来记录声波信息的——不管记录的形式是塑料还是磁介质。那么代码是如何发展的呢?纸带打孔 -> 汇编语言 -> 解释语言(BASIC) -> 高级语言(C) -> 面向对象语言(C++) ...->一般情况来说,编程语言的主要作用是在人和计算机之间建立翻译机制,把人类能懂的语言写出代码转换成二进制代码。但是,除此之外,代码还有一个更重要的作用被忽视了——代码
阅读全文
摘要:软件开发业的人常喜欢用生产制造业来比喻软件开发业的事情。由于对生产制造业的不熟悉,而是根据臆断和推测来进行的比喻,常常出现错误的结论。为此本文特地就生产制造业的情况和软件行业的类似于不同进行说明。1. Working Cell 提起生产制造业,第一印象往往都是生产线。但是生产线已经是在软件业出现之前的事情,如今的生产制造业早已经不是以前那种生产线的时代了。生产制造业以前是采用生产线的方式进行生产,生产线把生产工序分成各个阶段(熟悉吧?),每个阶段生产的产物都是下个阶段的输入。 生产制造业目前采用的方法叫做Working Cell。Working Cell是把生产人员分成各个工作小组,每个小组.
阅读全文
摘要:和其他工业一样,从经济角度上来说,软件开发注重三个重要的指标Quality 质量Cost 成本Delivery 交货期Q-C-D三个指标综合起来考虑软件项目是否成功。质量 按照bug数量来测量成本 按照投入的工时来测量(以后还会讨论《软件开发按工时收费的荒谬之处》)交货期 按照交货时间来测量一般企业在改进的时候总是困扰于一件事情:QCD三个指标无论如何都无法改进。过去人们在用油纸伞,后来人们用折叠伞。因为折叠伞在:质量成本交货期方面都比油纸伞有优势。在其他的生产制造行业也有同样的例子,比如:电灯和蜡烛,打火机和火柴,等等,不一而足。那么在软件行业也有这样的改进方式吗?答案是肯定的。在软件的几十
阅读全文
摘要:为了能够减少二次Bug率,一般组织都有一套Bug跟踪流程用来确保Bug修改的正确性。下面是一个典型的Bug跟踪流程。登记Bug -> 原因分析 -> 修改方案 -> 影响性分析 -> 修改 -> 测试 -> 测试组再测试这个Bug跟踪流程基本上会有一个较高的Bug率,我的经验显示,这个流程的二次Bug率在20%左右,即每修改10个Bug,其中有2个可能没修改完全或者是引起新的Bug。于是,一个改进的Bug跟踪流程出现了。登记Bug -> 原因分析 -> 修改方案 -> 方案确认 -> 影响性分析 -> 修改 -> 修改代码
阅读全文
摘要:等待在软件开发过程中的浪费比例应该是最大的。下面这些种等待,在你的项目中是否也发生过呢?(1)等待客户确认(2)等待上司命令(3)等待环境构筑(4)等待前一个阶段的成果物(5)等待Bug修改完毕(6)等待测试结果(7)等待UI设计图(8)等待不知道什么——莫名其妙的等待其实大可不必发生这些等待。首先,要弄明白发生等待的原因,只有这样才能够找到根本去消除一些不必要的等待。等待是怎么发生的呢?第一种等待工序定义错误造成的。为什么两个工序之间需要空闲时间呢?因为这两个工序是由不同的人来完成的。一个人工作的时候另外一个人必须等待。---------------比如:以Bug修改为例,测试人员登记Bug
阅读全文
摘要:SQA是Software Quality Assurance的缩写,意为:软件质量保证。通过了CMMI认证的组织往往会设置有专职的SQA人员。有时,他们也有另外一个名称:PPQAProcess and Product Quality Assurance。过程与产品质量保证。这个角色是通过对组织中的各个开发团队的开发过程进行跟踪,统计和总结,来提出全盘改进企业开发能力成熟度的。但是实际上他们并没有起到这个作用。他们的作用恰好相反,是用来拉低企业开发和管理水平的。这就是搅混水的SQA/PPQA的题目由来。我跟踪过一些组织的SQA的工作方式,事实说明他们是拉低企业的开发和管理水平的。那么为什么会产生
阅读全文
摘要:一般软件开发组织,在软件项目结束时会进行项目总结会,利用项目中的统计数据对项目中发生的成败得失进行总结分析,然后制定出改进计划,以希望在下次项目可以做的更好。然而,多年过去之后,对比一下现在的数据和当初的数据,基本上可以得出一个结论:这么多年没有丝毫改进,甚至还有退步的迹象。这是发生在很多地方的现象。为什么会发生这种现象呢?本人就那些无用的项目总结会以及无用的过程改进建议进行原因分析以及提出解决对策。 项目总结会的原意是遵照戴明环(P-D-C-A)进行改进的一种方式。它通过对项目发生的成败得失进行总结,并且制定详细具体的行动方案,以达到团队能力成熟度提升的目的。 项目总结会要由以下要素构成:
阅读全文
摘要:软件开发到处都需要英语。对于人英语不是母语来说,英语能力不足直接影响到代码中用到的单词以及语法,以及能够表达的意思。1、单词试试看,下列单词,不查字典能认识几个:a.wildcardb.assertionc.infinited.inherite.concurrentf.offsetg.abbreviationh.acceleratei.cryptoj.cipherk.gregorianl.exponentm.asteriskn.semicolono.flushp.atomicq.EOFr.SSLs.CSSt.pythonu.weak referencev.NaNw.duplicate上述这些单
阅读全文