
1. 学习完前面的三大模式:正常模式,插入模式和可视模式后,现在步入了命令模式。
:,/或?, 和<C-r>=分别进入到Ex命令,搜索和表达式,它们都被称作命令模式, 以前还常常把正常模式说成是命令模式。:后的是Ex命令,是因为我们仍然沿袭了 Vim 的前身 Ex。我在 Mac 下输入命令ex就会看到这个
进入到 Vim 的 Ex mode, 输入
visual命令就是正常的 Vim 界面。Vim 之于 Ex 就像 Gui 之于 Shell, Vim 的 Ex 命令可以做任何操作,见:h ex-cmd-index。2. 命令模式在
:提示符下输入时可以使用插入模式下的很多命令,如<C-w>,<C-u>,<C-k>,<C-v>,<C-r>{reg}, 甚至是<C-r>=,就是不能用 motion 命令,光标移得靠方向键3. 在阅读本章之前对 Vi 的命令模式只能用不觉明厉来形容,它对我的贡献仅仅是
:wq之类的,模式查找,简单替换,再就是执行一些未设置快捷键插件功能。也一直未理解替换怎么是%s/abc/dev, 只是依葫芦画瓢,现在终于可以在本章中理解那些命令了。从中真的能体会到 Ex 命令模式的乐趣,Ex 是不会把整个文件内容显示在屏幕上的, Ex 命令通常由 范围 + 命令 组成。:2 -- 光标跳到第一行,正常模式下可以 2G, 或 2gg
:print -- 打印当前行的内容范围和命令一般会写在一块,范围可借用同样意义的特殊字符,默认操作当前行,因此下面一系列的命令就好理解了 Read More
第八章:边界
本章关于如何学习使用第三方组件
- 第三组件或框架追求普适性,而使用者则想要集中满足特定的需求
- 学习第三方组件首当其冲当然还是文档,其次重要的是它的单元测试,我甚至是把单元测试当作文档的一部分来看待。其实更重要的方法是学习性测试(learning tests), 通过测试来学习才是切实的体验,是一种精确的试验,我们甚至可以用自己的测试来验证第三方组件的新版本
- 边界上会发生有趣的事,这就要求我们对它清晰的分割和定义,以避免我们的代码过多地了解第三方组件中的特定信息,依靠你能控制的东西好过依靠你控制不了的东西,免得日后受它控制。简而言之就是尽可能隔离边界,在边界改动时只需要修改一下适配器,对的适配
第九章:单元测试
这一章我自认为是很重要的,特别是正在采用测试驱动开发/设计(TDD) 的程序员来讲。充分,良好的单元测试是保证我对生产代码大刀阔斧的关键,这也就是 TDD 的最后一个 D 又能理解了 Design 的原由
Read More
第四章:注释
- 别给糟糕的代码加注释 -- 重新写吧
- 什么也不会比乱七八糟的注释更有本事搞乱一个模块。什么也不会比陈旧,提供错误信息的注释更有破坏性
- 若编程语方足够有表达力,或者我们长于用这些语方来表达意图,就不那么需要注释 -- 也许根本不需要
- 注释的恰当用法是弥补我们在用代码表达意图时遭遇的失败。注释总是一种失败
- 不准确的注释要比没注释坏得多。它们满口胡言。代码,只有代码能忠实的告诉你它做的事
- 好注释不多,如法律信息,警示等。我都不觉得
TODO是多好的东西 - 大多数注释都是坏注释,甚至一些 IDE 自动生成的代码也加一堆的废话注释,分散阅读注意力。我也写过那种日志式注释,这本是版本控制系统干的事。
- 很奇怪 IntelliJ IDEA 还在自动为新建的类加下创建者,代码是团队共有,时间长了根本就与作者无半毛关系。我经常碰到这种写有作者的代码哭笑不得,直接把原作者改了或删了也不太好,还不如把文件删了,新建一个没有作者注释的类
- 直接把代码注释掉是种讨厌的做法,自己可能不会再启用,其他人以为很重要更不敢删。不用了最好果断删掉,版本控制系统会帮你记住历史。
- 个人认为,注释会胡说八道,产品代码和测试代码不会撒谎。有功夫写注释还不如写好测试用例,测试需要维护,它本身就是最真实的文档。
修改私有属性来 Mock 可能不是一种很好的测试方式, 因为属性名是动态的,但有时不得已而为了,例如下面的代码:1public class UserService { 2 private ExternalApi external = ExternalApi.default(); 3 private UserDao userDao; 4 5 public UserService(UserDao userDao) { 6 this.userDao = userDao; 7 } 8 9 public User findUserById(int id) { 10 return userDao.findById(external.convertId(id)); 11 } 12}
测试时欲隔离对 ExternalApi 的外部依赖, 当然可以把它也作为构造函数的一个参数,这样创建 UserService 实例时就可以 Mock external 属性。不过 external 经常是不变的,所以作为方法参数的必要性也不大。这就希望能在构造出 UserService 之后对 external 私有属性进行 Mock 处理。
在 Mockito 1.x 和 2.x 下要使用不同的方式,分别使用到 Whitebox 和 FieldSetter 类,它们都来自于mockito.internal.util.reflection包,可见 Mockito 打心底不推荐直接使用它们,但谁叫它们是 public 的呢。还有一种方式是使用 PowerMock + Mockito, 这是后话。 Read More
第一章:整洁代码
- 代码即设计
- 童子军军规:把露营地清理得比来时还干净,签入代码前是否已做重构
- 你湎自行实践,且体验自己失败。你须观察他人的实践与失败
- 勒布朗(LeBlanc) 法则:稍后等于永不 (Later equals never)
- 赶上期限的唯一方法--做得快的唯一方法--就是始终尽可能保持代码整洁
- 缺乏“代码感”的程序员,看混乱是混乱,无处着手。有“代码感”的程序员能从混乱中看出其他的可能与变化
- 不好的代码引诱别人做没规矩的优化,搞出一堆混乱来
- 整洁的代码只做好一件事,糟糕的代码想做太多事,它意图混乱,目的含混
- 整洁的代码从不隐藏设计者的意图
- 整洁的代码只提供一种而非多种做一件事的途径
- 整洁的代码总是看起来像是某位特别在意它的人写的
- 回放我们编码过程显示,多多数时间都是在滚动屏幕,浏览其他模块
- 读与写花费时间的比例超过 10:1, 写新代码时,我们一直在读旧代码
- 编写代码的难度,取决于读周边代码的难度

1. Vim 的模式: 通常我们说有三种模式,正常模式(Normal Mode), 插入模式(Inert Mode) 和可视模式(Visual Mode). 其实除此之外还有
4) Operator-Pending Mode: 就是正常模式下按下操作(Operator) 指令(如 c, d 等) 后,等待输入移动(Motion) 指示时的模式。这时 Escape 或 Motion 指令后退回到正常模式
5) Insert Normal Mode: 在插入模式时,按下<Ctrl-o>组合键后进入该模式, 此时可接受一个 Action (Operator + Motion = Action), 比如3dd, 然后自动返回到插入模式。<Esc>也能从 Insert Normal Mode 返回到插入模式。这方便了插入模式只想执行一次指令操作时来回切换, Insert Normal Mode 在 Vim 的状态栏中显示为下图那样 - NORMAL --(insert) --
6) 替换模式(Replace Mode)
-- REPLACE --,R会进到替换模式,随后输入往后覆盖,可尝试<Insert>键;r{char}和gr{char}临时进入单字符的替换模式,替换完当前字符立即退到正常模式,也就是光标不往下走。
7) 可视替换模式(Visual Replace Mode)-- VREPLACE --, 用gR进入该模式,在处理tab字符时会更友好,还有别的好处吧,所以该书建议尽量用可视替换模式。
8) 可视模式(Visual Mode),这就复杂了。它有三个子模式:
character-wise Visual mode---- VISUAL;
line-wise Visual mode---- VISUAL LINE --
block-wise Visual mode---- VISUAL BLOCK --
9) 选择模式(Select Mode),可视模式下选择了内容后用<C-g>可在两种模式下切换,状态栏-- VISUAL --和-- SLECT --的不同,还有选择模式下直接输入就会替换当前的内容,与其他编辑器的行为一样,而可视模式需要按c来替换当前内容。 Read More
最初接触 Mockito 还思考并尝试过如何用它来 mock 返回值为 void 的方法,然而 Google 查找到的一般都会说用doThrow()的办法doThrow(new RuntimeException()).when(mockObject).methodWithVoidReturn();
因为无法使用常规的when(mockObject.foo()).thenReturn(...)的方法。
当时我就纳闷,为何我想 mock 一个返回值为 void 的方法,却是在模拟抛出一个异常,现在想来如果一个返回值为 void 的方法,为何要去 mock 这个方法呢?
回想一个我们要 mock 一个方法的意图是什么:- 在特定输入参数的情况下期待需要的输出结果(返回值)
- 在方法抛出某种类型异常调用者作出的反应
对于 void 返回值的方法,如果要验证有没有被调用过几次可以在事后用verify()方法去断言。所以基本上对于 void 返回值的方法一般可不用去 mock 它,只需用 verify() 去验证,或者就是像前面一样模拟出现异常时的情况。
所以本文并不像是去直接回答标题所示的问题: Mockito 如何 mock 返回值为 void 的方法,而是如何应对 mock 对象的 void 方法 Read More
Mockito 可以帮助我们创建 Mock 对象,mock 被调用的方法,断言调用次数,在方法参数不易确定的情况下还能帮我们捕获参数。下面是我们第一个问题:为什么要捕获调用参数
在被 mocker 方法调用参数明确的情况下可无需捕获参数,例如,下面的情景:1@Test 2public void dontCaptureArgument() { 3 UserDao userDao = Mockito.mock(UserDao.class); 4 UserService userService = new UserService(userDao); 5 6 User user = new User(1, "Yanbin"); 7 userService.saveUser(user); //假如它的实现是 userDao.save(user) 8 9 verify(userDao, times(1)).save(user); //断言了 userDao.save(user) 操作的还是 user 对象 10}
如果 UserService 的 save(user) 最终操作的不是同一个对象,它的实现稍加变化如下 Read More
Vim 的东西时而学一点,但很快又会忘记,就是最简单的 h, j, k, l 来移动光标都会有所迟疑,因为一直未强迫自己完全脱离方向键来使用 Vim,下个目标是 87 键的键盘都嫌多,打算入一个 61 键的 WSAD 键盘, HHKB 还是有些极端了。

找到了一本学习 Vim 的好书 《Practical Vim》第二版,阅读时把对自己有用的东西仅当笔记记下来备忘,这个其实更应该记录在我的 Evernote 中作为私有笔记。重点的东西我在书中注解了,这里的笔记只能算是一个补充。 Read More
- 我们知道 Java 8 增加了一些很有用的 API, 其中一个就是 Optional. 如果对它不稍假探索, 只是轻描淡写的认为它可以优雅的解决 NullPointException 的问题, 于是代码就开始这么写了那么不得不说我们的思维仍然是在原地踏步, 只是本能的认为它不过是 User 实例的包装, 这与我们之前写成
1Optional<User> user = ...... 2if (user.isPresent()) { 3 return user.getOrders(); 4} else { 5 return Collections.emptyList(); 6}实质上是没有任何分别. 这就是我们将要讲到的使用好 Java 8 Optional 类型的正确姿势.1User user = ..... 2if (user != null) { 3 return user.getOrders(); 4} else { 5 return Collections.emptyList(); 6}
在里约奥运之时, 新闻一再提起五星红旗有问题, 可是我怎么看都看不出来有什么问题, 后来才道是小星星膜拜中央的姿势不对. 因此我们千万也别对自己习以为常的事情觉得理所当然, 丝毫不会觉得有何不妥, 换句话说也就是当我们切换到 Java 8 的 Optional 时, 不能继承性的对待过往 null 时的那种思维, 应该掌握好新的, 正确的使用 Java 8 Optional 的正确姿势. Read More