API设计指南(话剧篇)
程序员的成就感可以来源于:1,解决了够复杂的问题;2,让别人能更容易的解决问题(复用自己的成果)。如果你解决了一组有共性的问题,并且想让别人遇到类似问题时不必重新发明轮子而直接复用你的成果以期获得更多成就感,便有可能会产生一个问题。或者更一般的情况:在模块化开发的时候,我们需要创造一些API给别人使用,如果我们的设计不合理,以至于暴露的接口不够“pretty”,别人在使用的时候便会在心里犯嘀咕,更恶劣的情况是“客户”弃之而再次重新发明轮子(自己既是API的消费者又是API的创造者,这样再“terrible”的设计也会被完成了功能需求所隐藏)。
当我们看到.NET FrameWork时,惊艳其完美的OOP封装,能把很复杂的系统功能以如此简洁的接口暴露给程序员。甚至于很多人不满足于熟练的使用其本身,而去探究其实现,探索其背后隐藏的东西,开源的呼声由此愈发响亮。也许我们很少有机会去设计一个很大规模的FrameWork去让很多人使用,但在稍具规模的.NET项目开发中,每个程序员越来越多的成为具体功能模块的提供者,供给项目中的其他人去调用。当我们自己编写模块完成功能并给别人暴露使用接口时, 我们会怎么去思考,设计和权衡呢。
接口的使用
Master:为什么使用接口呢?
Beginner:接口隔离了契约和具体实现
Master:你也能使用抽象类达成此目呀
Beginner:为什么我要这样做呢?
Master:这样的话你就可以在将来增加新成员
Beginner:所以接口不怎么管用是吧?
Master:不,接口很适合于值类型和多继承
Beginner:哦,我需要利用多继承去创建泛型和非泛型集合
Master:很好,你做了正确的选择
关于密封类
Master:为什么使用密封类呢?
Beginner:这是个潜规则
Master:但是为什么呢?
Beginner:它比较安全
Master:怎样变得安全的呢?
Beginner:因为这样就不能覆盖类成员
Master:但是你可以只密封需要密封的那部分啊
Beginner:好吧,但是我仍然需要测试扩展性
Master:当所有的成员是密封的或者非虚的你才可以使用密封类
Beginner:但是这样的话怎么解决继承问题呢
Master:提供一个辅助方法去解决这个问题
Beginner:我明白了
结构的使用
Master:这个该用结构吗?
Beginner:我不是太清楚
Master:什么时候你会使用结构?
Beginner:我不知道
Master:在设计指南里面有写呢,基本上如果一个类型比较小,不可变的,有值类型的语义,我们就会使用结构
Beginner:“不可变”具体是什么意思?
Master:当你实例化一个对象后不能改变其值
Beginner:为什么这是如此重要呢?
Master:可变的值类型(可变的拷贝)会迷惑使用者
Beginner:你说它得比较小,那到底多小呢?
Master:我们为此做过实验,结果是16字节或更小
Beginner:好的,我想你最初问的那个该设计成结构
异常和错误代码
Master:你为什么返回了一个错误码?
Beginner:因为它不是一个异常条件
Master:你是怎么考虑异常条件的?
Beginner:呃,当一些非期待的事情发生时,比如删除一个并不存在的文件错误
Master:恩,在托管代码中我们用异常来报告所有的错误。这有很多原因,主要是为了一致性。举个例子。你不能在构造函数或者属性里返回错误码
Beginner:但是异常很慢的呢
Master:用 TryParse模式解决
当我们看到.NET FrameWork时,惊艳其完美的OOP封装,能把很复杂的系统功能以如此简洁的接口暴露给程序员。甚至于很多人不满足于熟练的使用其本身,而去探究其实现,探索其背后隐藏的东西,开源的呼声由此愈发响亮。也许我们很少有机会去设计一个很大规模的FrameWork去让很多人使用,但在稍具规模的.NET项目开发中,每个程序员越来越多的成为具体功能模块的提供者,供给项目中的其他人去调用。当我们自己编写模块完成功能并给别人暴露使用接口时, 我们会怎么去思考,设计和权衡呢。
每个公司都有自己的编码规范/设计指南,本文不打算介绍枯燥的具体条文框框,而想以一种轻松的形式去展示几段对话,看看别人是怎么思考的(本文重点不是技术层面的复用技术,如对文中所述技术细节有不解之处,拉出去打PP)。下面让我们来看看一篇小话剧,对话的角色:Beginner & Master。
接口的使用
Master:为什么使用接口呢?
Beginner:接口隔离了契约和具体实现
Master:你也能使用抽象类达成此目呀
Beginner:为什么我要这样做呢?
Master:这样的话你就可以在将来增加新成员
Beginner:所以接口不怎么管用是吧?
Master:不,接口很适合于值类型和多继承
Beginner:哦,我需要利用多继承去创建泛型和非泛型集合
Master:很好,你做了正确的选择
关于密封类
Master:为什么使用密封类呢?
Beginner:这是个潜规则
Master:但是为什么呢?
Beginner:它比较安全
Master:怎样变得安全的呢?
Beginner:因为这样就不能覆盖类成员
Master:但是你可以只密封需要密封的那部分啊
Beginner:好吧,但是我仍然需要测试扩展性
Master:当所有的成员是密封的或者非虚的你才可以使用密封类
Beginner:但是这样的话怎么解决继承问题呢
Master:提供一个辅助方法去解决这个问题
Beginner:我明白了
结构的使用
Master:这个该用结构吗?
Beginner:我不是太清楚
Master:什么时候你会使用结构?
Beginner:我不知道
Master:在设计指南里面有写呢,基本上如果一个类型比较小,不可变的,有值类型的语义,我们就会使用结构
Beginner:“不可变”具体是什么意思?
Master:当你实例化一个对象后不能改变其值
Beginner:为什么这是如此重要呢?
Master:可变的值类型(可变的拷贝)会迷惑使用者
Beginner:你说它得比较小,那到底多小呢?
Master:我们为此做过实验,结果是16字节或更小
Beginner:好的,我想你最初问的那个该设计成结构
异常和错误代码
Master:你为什么返回了一个错误码?
Beginner:因为它不是一个异常条件
Master:你是怎么考虑异常条件的?
Beginner:呃,当一些非期待的事情发生时,比如删除一个并不存在的文件错误
Master:恩,在托管代码中我们用异常来报告所有的错误。这有很多原因,主要是为了一致性。举个例子。你不能在构造函数或者属性里返回错误码
Beginner:但是异常很慢的呢
Master:用 TryParse模式解决
Beginner:好的
Hope you can enjoy this, and get you want!
Rise our ability!