伴着2018年收官的鹅毛大雪,依旧在路上欢(Ku)快(B)驰骋,IT菜鸟分享今天的收获--《代码整洁之道》
1有意义的命名:
例子:别用accountList来指称一组账号,除非它真是List类型。可用accountGroup或bunchOfAccounts,甚至直接用accounts都会好一些。
3) 提防使用不同之处较小的名称。如:XYZControllerForAStrings和XYZControllerForBStrings
4) 做有意义的区分: sourceData和destinationData/targetData
5) 使用读得出来的名称:whs==woHenShuai
6) 使用可搜索的名称: 名称长短应与其作用域大小相对应。
7) 类名和对象应该是名词或名词短语,方法名应是动词或动词短语。
8) 每个概念对应一个词,别用双关语,使用解决方案领域名称,使用源自所涉及问题领域的名称,添加有意义的语境(state)
2函数
短小更短小,只做一件事(单一职责SRP、开放闭合OCP), 见名知意(setAndCheckIfExists), 使用异常替代返回错误码,抽离try/catch代码块。
3注释:注释简单明了刚刚好,不多也不少。
4格式:缩进、水平对齐。一个开发团队尽量保持一种格式规则。
5对象和数据结构
对象曝露(pu lu)行为--操作数据的函数,隐藏数据。便于添加新对象类型而无需修改既有行为,同时也难以在既有对象中添加新行为;数据结构曝露其数据,没有明显行为。便于向既有数据结构添加新行为,同时也难以向既有函数添加新数据结构。
DTO(Data Transfer Objects-数据传送对象),是一个只有公共变量、没有函数的类。常用于数据库通信、解析套接字传递的消息之类场景中。
6 错误处理:
使用异常而非返回码,先写try-catch-finally语句可以用TDD(测试驱动方法)构建其他代码逻辑。
使用不可控异常(可控异常违反了开放/闭合原则),避免别返回null值和别传递null值。这一块可以查看Java的可控异常(checked exception) 和 unchecked exception
7 边界:边界上的代码需要清晰的分割和定义了期望的测试。应该避免我们的代码过多的了解第三方代码中的特定信息。
8 单元测试:测试嗲吗和生产代码一样重要。
TDD三定律:
每个测试都清晰地分为三个环节:构造-操作-检验(Build-Operate-Check)。一是环节构造测试数据,二是操作测试数据,三个是不跟检验操作是否得到期望的结果。
9 类
类的名称应当描述其权责。实际上,命名正是帮助判断类的长度的第一个手段。自顶向下原则:如果有公共静态常量,应该先出现,然后是私有静态变量,以及私有实体变量。很少会有公共变量,公共函数应该跟在变量列表后面。
单一职责原则:类或模块应有且有只有一条加以修改的理由。类只应有一个权责—只有一条修改的理由。系统应该由许多短小的类而不是少量巨大的类组成。每个小类封装一个权责,只有一个修改的原因,并与少数其他类一起协同达成期望的系统行为。
内聚:类应该只有少量实体变量。类中的每个方法都应操作一个或多个这种变量。通常而言,方法操作的变量越多,就越粘聚到类上。
依赖倒置原则(DIP-Dependency Inversion Principle):类应该依赖于抽象(接口或抽象类)而不是依赖于具体细节。
将系统的构造和使用分开
软件系统应将起始过程和起始过程后之后的运行时逻辑分离开,在起始过程中构建应用对象,也会存在相互缠结的依赖关系。
真正的依赖注入还要更进一步。类并不直接分解其依赖,而是完全被动的。它提供可用于注入依赖的赋值器方法或构造器参数(或二者皆有)。在构造过程中,DI容器实体化需要的对象(通常按需创建),并使用构造器参数或赋值器方法将依赖链接到一起。至于哪个依赖对象真正得到使用,是通过配置文件或在一个有特殊目的构造模块中编程决定。
并发防御原则:
Java相关:
字节码分析:第5行的是原子操作,Java内存模型中32位值的赋值操作是不可中断的。
getNextId()方法中第09行的的++value 和 value ++ 的区别(初值为42)如下:
前递增和后递增并不是原子的,什么地方有共享对象/值,哪些代码会导致并发读/写问题,如何防止这种并发问题发生。
非锁定方案:CAS(比较并交换)AtomicBoolean/AtomicInteger/AtomicReference
非线程安全类:数据库连接、Java.util中的容器、Servlet
方法之间的依赖可能破坏并发代码: