自表达代码的特点

自表达代码的的特点

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 }

这会让代码能够具备更好的扩展性。
并且分层清晰,让代码更容易理解。

 

 

 

 

posted @   史蒂芬.王  阅读(355)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示