《改善 C# 程序的157个建议》读书笔记
第三部分:编码规范及习惯;
[命名规范] [代码整洁] [规范开发行为]
标 [+] 的为需要注意的,或可以关注的;
标 [-] 的为个人不赞同的;
[+] 指示的是其下方的建议项。
# 第三部分 编码规范及习惯
# 第10章 命名规范
# 1. 命名空间与程序集 命名方式
- 公司组织名称
<Company>.<Component>
[+] * 使用域名(Java世界中常见)
Com.Microsoft.<Component>
命名空间与程序集没有必然关系,
命名空间是逻辑分组;
程序集是物理分组;
# 2. 对于编译成 DLL 的程序集,建议命名空间与程序集名称一致。
[+] ##### 3. 命名空间使用复数 另外,不要添加无意义前缀或后缀。 建议:System.Collections 不建议:System.Collection, System.AllCollections
# 4. 避免与 BCL 和 FCL 命名重复
BCL (Base Class Library)
FCL (Framework Class Library)
[+] ##### 5. 类型命名:名词或名词词组 类型是现实中的实际对象,是名词。
动词:对象的行为,而不是类型本身。
[+] ##### 6. 接口命名:形容词组 接口:Can Do; 表示具备某种能力。
# 7. 派生类使用基类名字做后缀
XxxException : Exception XxxAttribute : Attribute XxxEventArgs : EventArgs
# 8. 泛型使用 T 做前缀
# 9. 枚举
枚举类型:复数
枚举元素:单数
# 10. 公开元素:PascalCasing 命名
# 11. 考虑用类名作为属性名
public Company Company {get;set;}
# 12. 私有或局部变量:camelCasing 命名
# 13. 有条件地使用前缀
member : m_
static : s_
在变量较多时,可以谨慎考虑使用。
不过,变量较多时,考虑重构。
[+++] ##### 14. 使用肯定性的短语命名布尔类型 前缀:Is Can Has ... 好:IsChecked 坏:Checked
# 15. 使用后缀表示已有类型的新版本。
X509Certificate
X509Certificate2
不得不这样时,加后缀,而不是前缀,便于被发现。
[+] ##### 16. 委托与事件*类型*应添加上后缀 XxxDelegate XxxCallback XxxEventHandler
[+] ##### 17. 委托和事件*变量*使用动词或形容词短语命名 Click SizeChanged 表示动作(委托)或事件的发生,状态的变化(事件)
[+] ##### 18. 事件处理器(事件的订阅函数)或委托处理器命名 组合: 事件变量所属对象_事件变量名 委托变量所属对象On委托变量名
好:NameOnPropertyChanged 坏:NameChanged (看起来像事件的变量名)
# 第11章 代码整洁
# 1. 使用默认的访问修饰符
不是很赞同。 原因:添加默认的修饰符,如 internal class,是在显式声明这个类不应该被变成 public 的, 而不是忘记添加访问修饰符了。可以一定程度上防止他人随意修改访问权限。
[+++] ##### 2. 不知道该不该用大括号,就用。 增加代码可读性。
下面的例子中,Resharper 等工具会提示 else
无需书写,以减少代码层级,但在这种情况下,
建议可以加上 else {}
,因为代码可读性明显提示。代码之间的关系和条理更清楚。
private bool Check()
{
if(xxx)
{
// ...
return true;
}
else
{
// ...
return false;
}
}
# 3. 总是使用有意义的命名。
同时,避免一心二意,同一个变量,在一段代码中应只表示一个含义。
[++] ##### 4. 方法的抽象级别应在同一层级。
坏:
public void Init()
{
// xxx
RemoteInit();
}
这个例子中,Init 方法先进行了部分初始化工作,然后调用 RemoteInit 完成另一部分初始化工作。
好:
public void Init()
{
LocalInit();
RemoteInit();
}
建议的做法是,将两部分初始化工作都抽象为相同层级的方法(LocalInit 和 RemoteInit),在 Init 中调用。 层级更清晰。
# 5. (单一职责)一个方法只做一件事。
事情可大可小,但方法过长过负责时,就要考虑拆分。
# 6. (单一职责)避免过长的方法和过长的类。
过长的方法和过长的类是重构的首选目标。
# 7. (高内聚,最小知识)只对外公布必要的操作。
# 8. 重构多个相关属性为一个类。
e.g. 如一个 Person 类中,有地址,邮编,邮箱,电话,手机号等等属性,就应该考虑将其抽象为联系方式一个类。
# 9. 不重复代码
[+] ##### 10. 使用表驱动法避免过长的 if 和 switch 分支。 使用字典、数组、索引等代替 if 和 switch 。 这个一种设计思路哦。
# 11. 使用匿名方法,Lambda 表达式代替方法。
# 12. 使用事件访问器替换公开的事件成员变量。
这个,C# 已经自动实现啦,无需考虑。
[-] ##### 13. 最少,甚至是不要注释。 这个,不赞同。 写了注释不能成为代码本身糟糕的借口,但不代表不需要写注释,尤其是公开的方法,复杂的逻辑。 建议:保持代码本身的优雅,但不过分追求精简注释。
# 14. 如抛出异常,则必须要注释。
方法内部会抛出异常,在方法签名上方需要写注释。
/// <Summary>
/// 注释
/// </Summary>
/// <exception cref="System.IO.IOException">什么情况下会抛出该异常</exception>
public void Xxx()
{
// ...
throw new IOException("XXX");
}
# 第12章 规范开发行为
[+++] ##### 1. 避免过度设计,在敏捷中重构 瀑布式开发:分析->设计->实现->测试。(试用与类似于建筑这样的"不可重构"的行业)缺点:不能很好地应对变化。 敏捷开发:关键词——迭代。(Spring) 敏捷使用“用户故事(User Story)”来核定需求和工作量。一个迭代提供一个完成的用户故事的实现,交付给客户(真实客户,或者测试部门,运营等。)
[+++] ##### 2. 单元测试 * TDD * 使用单元测试框架
# 3. 利用特性为应用程序提供多个版本
e.g. 条件编译 [Conditional("ONLINE")] [Conditional("OFFLINE")]
# 4. 界面的自动化测试
工具:Code UI Automation
END