自表达代码的的特点
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 "lesson does not exist."; 10 } 11 12 code = checkLessonExpired(lessonId); 13 if (code != 0) { 14 return "lesson is expired."; 15 } 16 17 code = checkLessonVacance(lessonId); 18 if (code != 0) { 19 return "lesson has no vacance."; 20 } 21 22 code = registerLessonRemote(userId, lessonId); 23 if (code != 0) { 24 return "failed to register lesson."; 25 } 26 return ""; 27 }
上述代码在阅读方面有如下问题:
1. code变量的意思在不停的变化。
2. 返回值的String类型在上层很难使用。
这段代码改为自表达方式书写是如下形式:
public void registerLesson(int userId, int lessonId) throws BusinessException { checkUserId(userId); checkLessonId(lessonId); checkLessonExpired(lessonId); checkLessonVacance(lessonId); registerLessonRemote(userId, lessonId); }
这两种代码的书写方式的差别很明显,自表达的方式有如下优点
1. 没有局部变量
2. 代码不需要返回值
3. 方法签名的异常对上层调用来说很方便。
2. 基本不需要注释
代码需要注释的原因是因为代码的名称和参数不容易理解。比如 (a+ b) >>> 1;意思不是很容易理解。
自表达代码主张代码的书写本身就是自己的意思。这也正是自表达代码的意思由来。
自表达代码阅读起来就像读小说一样,就植物大战僵尸为例:
1 public abstract class Plant { 2 public Weapon weapon; 3 public Health health; 4 5 public void fire() { 6 weapon.fire(); 7 } 8 }
而武器的定义:
1 public abstract class Weapon { 2 public Bullet bullet; 3 public void fire() { 4 GameWorld.getInstance.append(bullet); 5 } 6 }
如此这般,代码基本上不需要注释就很容易明白。
3. 代码结构清晰
比如,书写一个Android输入法的时候,需要判定输入方式的语言类型:Hiragana,Full-Katakana,Half-Katakana, Full-Alphabet, Half-Alphabet, Half-Number。而且需要考虑输入的键盘类型,QWERTY键盘,Kana键盘,12键键盘。
那么在判定一个输入的时候代码会写成这样:
1 public boolean onKey(int primaryCode) { 2 String keyChar =""; 3 if (keyMode = QWERTY) { 4 keyChar = getQwertChar(primaryCode); 5 } else if (keyMode == JAPANESE_50) { 6 keyChar = getJapanese50Char(primaryCode); 7 } else if (keyMode == NUMBER) { 8 keyChar = getNumberChar(primaryCode); 9 } 10 appendComposingChar(keyChar); 11 }
上述代码中的每个方法都要判定当前的语言类型,例如:
1 public String getJapanese50Char(int primaryCode) { 2 switch (language) { 3 case HIRAGANA: 4 return HIRAGANA_TABLE[primaryode]; 5 case FULL_KATAKANA: 6 return FULL_KATAKANA[primaryCode]; 7 case HALF_KATAKANA: 8 return HALF_KATAKANA[primaryCode]; 9 case FULL_ALPHABET: 10 return FULL_ALPHABET[primaryCode]; 11 case HALF_ALPHABET: 12 return HALF_ALPHABET[primaryCode]; 13 case HALF_NUMBER: 14 return HALF_NUMBER[primaryCode]; 15 } 16 }
同样,其他的方法也要如此的写。
但是当键盘上的键按下时,并不是组装候选文字的情况,代码需要继续扩展。到处都会是重复和类似。
简单的改写如下:
1 public interface Language { 2 String getKey(int primaryCode); 3 }
1 public Hiragana implements Language { 2 public String getKey(int primaryCode) { 3 return HIRAGANA[primaryCode]; 4 } 5 }
这会让代码能够具备更好的扩展性。
并且分层清晰,让代码更容易理解。