写了这么多年代码,依旧做不好一个项目
做好一个项目是人力
、产品
、业务
、技术
、运营
的结合,可能还叠加一点时机的因素,就我们码农而言,工作就是搬砖,实现产品, 给业务提供支撑。
“给祖传代码加 BUG 修 BUG”,“拿起键盘一把梭”这些戏谑程序员的话,听多了真的会让程序员麻木,仿佛大家都是这么干的。
从业多年,堆过 shi 山,接手过祖传代码, 已经不能沉下气去查看、调试 shi 山代码, 说实话,很累。
本人一直推崇写流畅、自然、可自解释的代码,让优雅成为一种习惯, 给自己留个念想、给后人留个好评。
温故而知新,聊一聊现代编程几大常见的编程原则
普世原则 | |
KISS (Keep It Simple Stupid) | 保持系统结构简单可信赖 |
YAGNI (you aren't gonna need it) | 当前确实需要,再去做 |
Do The Simplest Things That Could Possibly Work | 思考最简单可行的办法 |
Separation of Concerns | 关注点分离 |
Keep Things DRY | 保持代码结构清爽 Don't repeat yourself |
Code For The Maintainer | 站在维护者角度写代码 |
Avoid Premature Optimization | 避免提前优化 |
Boy-Scout Rule | 清扫战场:清理口水话注释、无效代码 |
模块(类)间 | |
Minimise Coupling | 低耦合 |
Law of Demeter | Don't talk to strangers,对象方法只接触该接触的对象、字段、入参 |
Composition Over Inheritance | 组合而不是继承 |
Orthogonality | 正相关,概念上不相关的事物不应在系统中强行相关 |
Robustness Principle | 代码健壮性 |
Inversion of Control | 控制反转 |
模块(类) | |
Maximise Cohesion | 高内聚 |
Likov Substitution Principle | 里斯替代原则:将程序中对象替换到子类型实例,不会报错。 |
Open/Closed Principle | 设计的实体对扩展开放,对修改关闭 |
Single Responsiblity Principle | 单一责任原则 |
Hide Implementation Details | 隐藏实施细节 |
Curly's Law | 柯里定律:为确定目标编写特定代码 |
Encapsulate What Changes | 封装变化 |
Interface Segregation Principle | 接口隔离原则 |
Command Query Separation | 命令查询分离 |
KISS
大多数系统保持简单,会运行的很好。
- 更少的代码消耗更好的时间,产生更少的 bug,并且容易修改
- 复杂业务都是由简单代码堆砌而成
- 完美并不是“没有什么东西可以再加”,而是“没有什么东西可以被去掉”
YAGNI
YAGNI 代表“you aren't gonna need it.”,不要自以为是的提前实现某些边角,直到真正需要的时候,再来做。
- 提前做明天才需要做的工作,意味着当前迭代中需要花费更多精力
- 导致代码膨胀,软件变得臃肿且复杂
Separation of Concerns
关注点分离是一种将计算机程序分为不同部分的设计原则,这样每个部分都可以解决一个单独的关注点。例如应用程序的业务逻辑是一个问题,而用户界面是另外一个问题,更改用户界面不应要求更改业务逻辑,反之亦然。
- 简化应用程序的开发和维护
- 如果关注点分离得很好,则各个部分可以重复使用,也可以独立开发和更新。
Interface Segregation Principle
接口隔离,将胖接口修改为多个小接口,调用接口的代码应该比实现接口的代码更依赖于接口
。
why:如果一个类实现了胖接口的所有方法(部分方法在某次调用时并不需要),那么在该次调用时我们就会发现此时出现了(部分并不需要的方法),而并没有机制告诉我们我们现在不应该使用这部分方法。
how: 避免胖接口,类永远不必实现违反单一职责原则的接口。可以根据实际多职责划分为多接口,类实现多接口后, 在调用时以特定接口指代对象,这样这个对象只能体现特定接口的方法,以此体现接口隔离。
public interface IA { void getA(); } interface IB { void getB(); } public class Test : IA, IB { public string Field { get; set; } public void getA() { throw new NotImplementedException(); } public void getB() { throw new NotImplementedException(); } } class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); IA a = new Test(); a.getA(); // 在这个调用处只能看到接口IA的方法, 接口隔离 } }
Command Query Separation
命令查询分离: 操作方法就只写操作逻辑,查询方法就只写查询逻辑,并以明显的方法名区分自己的动作。
有了这个原则,程序员可以更加自信地进行编码:由于查询方法不会改变状态,因此可以在任何地方以任何顺序使用,使用操作方法时,也心中有数。
End
懂得这么多道理,却依旧过不好这一生。前人总结的编程原则和方法论需要在实践中感悟,束之高阁,则始终不能体会编程的魅力和快感。