代码规范
命名规范
输入检测
代码设计
对于coder,面对问题会直觉使用计算机可以理解地逻辑来描述和表达待解决的问题和具体的求解过程。
但是这样的程序只能满足当前的需求,程序不容易维护,不容易扩展,不容易复用。
面向对象
封装
- 业务逻辑与界面逻辑的分离
继承
- 当系统当中的操作需要增加或者修改,而这些操作拥有一个共性,那么就可以增加一个接口或者父类。在内部定义好操作,在子类当中进行实现
- 当新的操作加入进来,只需要继承即可。当旧的操作需要改变,只需要修改对应的子类即可
- 例如计算薪资的问题
多态
- 工厂模式
经验
- 面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有系统属性和功能的对象的抽象集合才是类
原则
以活字印刷为例。
- 可维护:要改,只需要改要改之字
- 可复用:活字的模板并非用完就无用,可以在之后的印刷重复使用
- 可扩展:若要加字,只需另刻字
- 灵活性好:若字要竖排,则移动活字即可。
可维护
易扩展
易复用
灵活性好
类设计技巧
- 一定要保证数据私有
这是最重要的;绝对不要破坏封装性。有时候,需要编写一个访问器方法或更改器方法,但是最好还是保持实例域的私有性。很多惨痛的经验告诉我们,数据的表示形式很可能会改变,但它们的使用方式却不会经常发生变化。当数据保持私有时,它们的表示形式的变化不会对类的使用者产生影响,即使出现 bug 也易于检测。
- 一定要对数据初始化
Java 不对局部变量进行初始化,但是会对对象的实例域进行初始化。最好不要依赖于系统的默认值 , 而是应该显式地初始化所有的数据,具体的初始化方式可以是提供默认值,也可以是在所有构造器中设置默认值。
- 不要在类中使用过多的基本类型
就是说,用其他的类代替多个相关的基本类型的使用。这样会使类更加易于理解且易于修改。例如,用一个称为Address的新的类替换一个Customer类中以下的实例域:
1 | private String street ; |
这样,可以很容易处理地址的变化,例如,需要增加对国际地址的处理。
- 不是所有的域都需要独立的域访问器和域更改器
或许,需要获得或设置雇员的薪金。 而一旦构造了雇员对象,就应该禁止更改雇用日期,并且在对象中,常常包含一些不希望别人获得或设置的实例域,例如,在Address类中,存放州缩写的数组。
- 将职责过多的类进行分解
这样说似乎有点含糊不清,究竟多少算是“过多”?每个人的看法不同。但是,如果明显地可以将一个复杂的类分解成两个更为简单的类,就应该将其分解(但另一方面,也不要走极端。设计10个类,每个类只有一个方法,显然有些矫枉过正了)
- 类名和方法名要能够体现它们的职责
与变量应该有一个能够反映其含义的名字一样,类也应该如此
- 优先使用不可变的类
LocalDate类以及java.time包中的其他类是不可变的—没有方法能修改对象的状态。类似 plusDays 的方法并不是更改对象,而是返回状态已修改的新对象
更改对象的问题在于,如果多个线程试图同时更新一个对象,就会发生并发更改。其结果是不可预料的。如果类是不可变的,就可以安全地在多个线程间共享其对象。
因此,要尽可能让类是不可变的,这是一个很好的想法。对于表示值的类,如一个字符串或一个时间点,这尤其容易。计算会生成新值,而不是更新原来的值。
当然,并不是所有类都应当是不可变的。如果员工加薪时让raiseSalary方法返回一个新的Employee对象,这会很奇怪。