最近重读了Robert C. Martin的《敏捷软件开发》。
这本书是我刚入行的时候买的,当时读了一遍,觉得很有道理,但很多东西理解不深。这几年做了不少项目,也踩了不少坑,再回过头来读这本书,发现里面的很多观点都说到了点子上,很多建议都非常有价值。
Robert C. Martin大家都叫他"Uncle Bob",是软件开发领域的泰斗级人物。他是敏捷宣言的签署者之一,也是SOLID原则的提出者。《敏捷软件开发》这本书是他的代表作之一,出版二十多年了,至今仍然被很多人奉为经典。
这篇文章我想聊聊这本书,以及它为什么能成为经典。从敏捷宣言、设计原则到实践方法,分享一下我的读书笔记和感悟。
如果你是做软件开发的,不管你是刚入行的新人还是有经验的老手,我都推荐你读一下这本书。它不会教你具体的编程语言或框架,但会教你如何写出好的代码、如何做好的设计、如何成为一个优秀的软件工程师。
先说明一下,我读的是中文版,不同版本的翻译可能会有差异。而且这本书出版比较早,有些例子和技术可能已经过时了,但背后的原则和思想是永不过时的。
敏捷的本质是什么
在讲具体内容之前,先说说敏捷的本质。
现在很多人一谈敏捷,就想到Scrum、站会、迭代、用户故事这些具体的实践。但这些只是敏捷的表象,不是敏捷的本质。
敏捷的本质,在2001年的敏捷宣言里说得很清楚:
"我们正在通过亲身实践和帮助他人实践,揭示更好的软件开发方法。通过这项工作,我们认为:
个体和互动 高于 流程和工具 可工作的软件 高于 详尽的文档 客户合作 高于 合同谈判 响应变化 高于 遵循计划
也就是说,尽管右项有其价值,我们更重视左项的价值。"
这四句话就是敏捷的核心。它不是一套具体的流程或工具,而是一种价值观和思维方式。它强调人比流程重要,能运行的软件比文档重要,和客户合作比合同谈判重要,响应变化比按计划走重要。
很多团队学敏捷,只学了表面的形式,没有理解背后的价值观。比如每天开站会,但只是走形式,大家轮流汇报一下,没有真正的沟通和协作;比如做迭代,但每个迭代都在赶进度,没有真正的反馈和改进;比如写用户故事,但只是把需求换了个名字,没有真正从用户的角度出发。
这样的敏捷,只是"伪敏捷",不仅不能提高效率,反而会增加团队的负担。
Uncle Bob在书里反复强调,敏捷不是银弹,不是用了敏捷就一定能成功。敏捷是一种思维方式,一种价值观,需要团队真正理解并践行,才能发挥作用。
这也是这本书能成为经典的原因之一。它没有教你一套固定的流程,而是教你敏捷背后的原则和思想。只要理解了这些原则和思想,你可以根据自己的团队和项目情况,灵活地实践敏捷。
SOLID原则:面向对象设计的基石
这本书最重要的内容之一,就是SOLID原则。
SOLID是五个面向对象设计原则的首字母缩写,分别是:
单一职责原则(Single Responsibility Principle) 开闭原则(Open-Closed Principle) 里氏替换原则(Liskov Substitution Principle) 接口隔离原则(Interface Segregation Principle) 依赖倒置原则(Dependency Inversion Principle)
这五个原则是Uncle Bob提出的,现在已经成为面向对象设计的基石。几乎所有的设计模式、架构模式,背后都有这五个原则的影子。
先说说单一职责原则。这个原则说的是,一个类或者模块,应该只有一个引起它变化的原因。也就是说,一个类只应该做一件事,只有一个职责。
很多人写代码,喜欢把所有功能都塞到一个类里,结果这个类变得又大又复杂,什么都做,什么都做不好。这样的代码,改一个地方可能会影响很多地方,维护起来非常痛苦。
单一职责原则告诉我们,要把大的类拆分成小的类,每个类只负责一个功能。这样每个类都很简单,职责清晰,修改的时候影响范围也小。
当然,单一职责不是说类越小越好,而是说一个类的职责应该是内聚的,相关的功能放在一起,不相关的功能分开。怎么划分职责,需要根据业务场景和变化的原因来判断。
然后是开闭原则。这个原则说的是,软件实体应该对扩展开放,对修改关闭。也就是说,当需求变化的时候,应该通过添加新的代码来扩展功能,而不是修改已有的代码。
为什么要对修改关闭?因为修改已有的代码,可能会引入新的bug,可能会影响依赖它的其他模块。而添加新的代码,风险就小很多。
怎么实现开闭原则?关键是抽象。通过定义抽象的接口或基类,让具体的实现可以灵活替换。当需要新功能的时候,添加一个新的实现类就行了,不需要修改已有的代码。
很多设计模式,比如策略模式、工厂模式、观察者模式,本质上都是在实现开闭原则。
接下来是里氏替换原则。这个原则说的是,子类必须能够替换掉它们的父类,而不会引起任何问题。也就是说,在任何使用父类的地方,都可以用子类来代替,程序的行为不应该发生变化。
这个原则是Barbara Liskov提出的,它强调的是继承的正确用法。继承不是为了代码复用,而是为了多态和抽象。如果子类不能替换父类,那就不应该用继承,而应该用组合。
很多人用继承用错了,只是为了复用父类的代码,结果子类和父类的行为不一致,导致各种问题。里氏替换原则就是提醒我们,继承要慎用,要确保子类真的是父类的一种特殊情况。
然后是接口隔离原则。这个原则说的是,客户端不应该依赖它不需要的接口。也就是说,接口要小而专,不要大而全。
很多人喜欢定义一个大而全的接口,里面有很多方法。但实现这个接口的类,可能只需要其中的几个方法,其他方法都用空实现或者抛异常。这样的接口,既不好用,也容易出问题。
接口隔离原则告诉我们,要把大接口拆分成小接口,每个接口只包含相关的方法。客户端只需要依赖它真正需要的接口,不需要知道其他的方法。
最后是依赖倒置原则。这个原则说的是,高层模块不应该依赖低层模块,两者都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。
简单来说,就是要面向接口编程,而不是面向实现编程。高层模块定义业务逻辑,低层模块实现具体细节,两者都通过抽象接口来交互。这样,高层模块不依赖具体的低层实现,低层实现可以灵活替换。
依赖倒置原则是实现松耦合的关键。只有依赖抽象,才能做到模块之间的解耦,才能方便地测试、替换和扩展。
这五个原则,每一个都值得深入学习和实践。它们不是什么高深的理论,而是从无数项目的经验教训中总结出来的智慧。遵循这些原则,你的代码会更清晰、更灵活、更易维护。
设计模式:原则的具体应用
除了SOLID原则,这本书还讲了很多设计模式。
设计模式不是什么神奇的东西,它就是前人在面对特定问题时,总结出来的最佳解决方案。每个设计模式,背后都体现了SOLID原则。
Uncle Bob在书里没有罗列所有的设计模式,而是精选了几个最常用、最重要的模式,详细讲解了它们的适用场景、实现方式和优缺点。
比如工厂模式,用来解决对象创建的问题。当你需要根据不同的条件创建不同的对象时,用工厂模式可以把创建逻辑封装起来,客户端不需要知道具体的创建过程。
比如策略模式,用来解决算法切换的问题。当你有多种算法或行为,需要在运行时动态切换时,用策略模式可以把每种算法封装成独立的类,通过接口来调用。
比如观察者模式,用来解决事件通知的问题。当一个对象的状态变化需要通知多个其他对象时,用观察者模式可以实现松耦合的通知机制。
比如装饰器模式,用来解决功能动态扩展的问题。当你需要给一个对象动态添加功能时,用装饰器模式可以在不修改原对象的情况下,包装一层新的功能。
这些设计模式,每一个都有它的适用场景。不是所有地方都要用设计模式,用得不好反而会增加代码的复杂度。只有当你遇到了对应的问题,并且这个模式确实能帮你解决问题的时候,才应该用它。
Uncle Bob在书里反复强调,不要为了用模式而用模式。设计模式是工具,不是目的。如果一个简单的方法就能解决问题,就不要硬套一个复杂的模式。
这也是这本书能成为经典的原因之一。它不是教你死记硬背设计模式,而是教你理解每个模式背后的原则和思想,让你知道什么时候该用,什么时候不该用。
敏捷实践:从原则到行动
有了原则和模式,还要落实到具体的实践中。这本书的后半部分,讲了很多敏捷开发的实践方法。
第一个是测试驱动开发(TDD)。
TDD的流程是:先写一个失败的测试,然后写最少的代码让测试通过,然后重构代码。这样循环往复,每一步都很小,每一步都有测试保障。
很多人对TDD有误解,觉得写测试浪费时间,会拖慢开发速度。但实际上,TDD能大大提高代码质量,减少后期的bug和维护成本。而且有了测试之后,重构和修改代码就有了保障,不用担心改坏了什么。
Uncle Bob是TDD的坚定支持者,他在书里详细讲解了TDD的方法和好处。他认为,TDD不是一个测试技术,而是一个开发技术,它能改变你写代码的方式,让你写出更简洁、更可测试、更易维护的代码。
第二个是重构。
重构就是在不改变代码外部行为的前提下,改善代码的内部结构。重构不是重写,不是推翻重来,而是在现有代码的基础上,一步一步地改善。
重构的前提是有测试。只有有了测试保障,你才能放心地重构,不用担心改坏了功能。所以TDD和重构是相辅相成的,先有测试,再重构。
重构的时机也很重要。不要等到代码烂得不行了才重构,那时候重构的成本太高了。应该在日常开发中,随时重构,看到不好的代码就改,保持代码的整洁。
Uncle Bob说,每次你看到不好的代码,都应该顺手把它改好。就像童子军规则一样:离开营地的时候,要让营地比你来的时候更干净。
第三个是持续集成。
持续集成就是团队成员频繁地把代码合并到主干,每次合并都通过自动化构建和测试来验证。这样可以尽早发现集成问题,避免到了项目末期才发现各种冲突和bug。
持续集成需要自动化的构建和测试工具,需要团队养成频繁提交代码的习惯。它能大大提高团队的协作效率,减少集成的痛苦。
第四个是结对编程。
结对编程就是两个人一起写代码,一个人敲键盘,另一个人在旁边看,随时提出建议和发现问题。两个人定期交换角色。
很多人觉得结对编程浪费人力,两个人做一个人的工作。但实际上,结对编程能大大提高代码质量,减少bug,而且两个人互相学习,知识共享,对团队的成长很有好处。
当然,结对编程不是所有时候都适合。对于简单的、机械性的任务,结对编程可能确实浪费。但对于复杂的、有挑战性的任务,结对编程的效果非常好。
这些实践方法,都是敏捷原则的具体体现。它们不是必须全部都用,而是可以根据团队的情况,选择适合的来实践。重要的是理解背后的原则,然后在实践中不断调整和改进。
为什么它能成为经典
说了这么多,回到最初的问题:《敏捷软件开发》为什么能成为经典?
我觉得有几个原因。
第一,它讲的是原则和思想,而不是具体的技术。
技术更新换代很快,今天流行的框架,明天可能就过时了。但原则和思想是永不过时的。SOLID原则、设计模式、TDD、重构,这些东西二十年前有用,今天有用,二十年后依然有用。
这本书没有教你用什么语言、什么框架、什么工具,而是教你软件开发的基本原则和思维方式。只要你还在做软件开发,这些东西就用得上。
第二,它有很强的实践性。
这本书不是一本纯理论的书,它有大量的代码示例和实际案例。Uncle Bob用具体的代码,展示了不好的设计是什么样的,怎么用原则和模式来改善,改善之后的代码是什么样的。
这种从实际问题出发,一步步展示解决过程的写法,让读者很容易理解和模仿。很多人读完之后,就能在自己的项目中应用这些原则和方法。
第三,它的作者是真正的大师。
Robert C. Martin有几十年的软件开发经验,经历了从大型机到PC、从结构化编程到面向对象的多个时代。他不是在空谈理论,而是在分享他几十年的经验和智慧。
书里的很多观点,都是他从无数项目的成功和失败中总结出来的。这种来自实践的智慧,比任何理论都更有说服力。
第四,它影响了整整一代程序员。
这本书出版之后,被翻译成多种语言,在全世界广泛传播。很多程序员都是读着这本书长大的,SOLID原则、设计模式、TDD这些概念,通过这本书深入人心。
可以说,这本书塑造了现代软件开发的很多实践和文化。直到今天,很多公司的面试还在考SOLID原则和设计模式,很多团队的代码规范还在遵循这本书里的建议。
当然,这本书也不是完美的。它出版比较早,有些例子和技术已经过时了;它主要讲面向对象,对函数式编程等其他范式涉及不多;它的有些观点,在今天看来可能有争议。
但这些都不影响它的经典地位。一本经典的书,不是因为它永远正确,而是因为它提出了有价值的问题,给出了有启发性的答案,能让一代又一代的读者从中受益。
给读者的建议
最后,给想读这本书的朋友一些建议。
第一,不要急着一次读完。这本书内容很丰富,每一章都值得仔细品味。可以慢慢读,读一章,思考一下,在工作中实践一下,然后再读下一章。
第二,边读边写代码。这本书有很多代码示例,不要只看,要自己动手写一写。把不好的代码改好,体会一下设计原则和模式的作用。只有亲手实践过,才能真正理解。
第三,结合自己的项目来读。读的时候,想想自己项目里的代码,有没有违反这些原则的地方,有没有可以用设计模式改善的地方。把书里的知识用到实际项目中,才是真正的学习。
第四,带着批判的眼光读。不要把书里的每一句话都当成真理,要结合自己的经验和思考,判断哪些适合自己,哪些不适合。大师的经验也不是万能的,要根据自己的情况灵活运用。
第五,读完之后继续学习。这本书只是一个起点,不是终点。读完之后,可以继续读更多的书,做更多的实践,不断提升自己的技术水平。
写在最后
《敏捷软件开发》是一本值得反复阅读的书。
每次读,都会有新的收获。刚入行的时候读,觉得很新鲜,学到了很多新知识;工作几年之后读,发现很多踩过的坑书里早就讲过了,后悔没有早点认真读;现在再读,对很多原则和思想有了更深的理解,也能在工作中更熟练地应用。
这就是经典的魅力。它不会因为时间的流逝而褪色,反而会随着你的成长,不断给你新的启发。
如果你是做软件开发的,我强烈推荐你读一下这本书。它可能不会立刻让你的技术水平突飞猛进,但它会在潜移默化中影响你的编程习惯和思维方式,让你成为一个更好的程序员。
最后用Uncle Bob的一句话来结束这篇文章:"真正的专业人士,不是那些懂得最多技术的人,而是那些始终遵循原则、追求质量、对代码负责的人。"
愿你我都能成为这样的专业人士。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录