欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

11个系统的《代码整洁之道》阅读笔记

最编程 2024-01-15 11:30:11
...

"Complexity kills. It sucks the life out of developers, it makes products difficult to plan, build and test."(复杂要人命,它消磨开发者的生命,让产品难于规划、构建和测试在这里插入图片描述

1.如何建造一个城市

  • 1.每个城市都有一组人管理不同的部分,有人负责全局,其他人负责细节

  • 2.深化出恰当的抽象等级和模块,好让个人和他们所管理的“组件”即便在不了解全局时也能有效地运转

2.将系统的构造与使用分开

  • 1.构造与使用是非常不一样的过程

  • 2.软件系统应将启始过程和启始过程之后的运行时逻辑分离开,在启始过程中构建应用对象,也会存在互相缠结的依赖关系

  • 3.将构造与使用分开的方法之一是将全部构造过程搬迁到main或被称为main的模块中,设计系统的其余部分时,假设所有对象都已正确构造和设置

  • 4.可以使用抽象工厂模式让应用自行控制何时创建对象,但构造的细节却隔离于应用程序代码之外

  • 5.控制反转 将第二权责从对象中拿出来,转移到另一个专注于此的对象中,从而遵循了单一权责原则。在依赖管理情景中,对象不应负责实体化对自身的依赖,反之,它应当将这份权责移交给其他“有权力”的机制,从而实现控制的反转

Jndi查找是DI的一种部分实现,在JNDI中,对象请求目录服务器提供一种符合某个特定名称的“服务”。

延后初始化的好处

  • 多数DI容器在需要对象之前并不构造对象,
  • 其次,许多这类容器提供调用工厂或者代理的机制,而这种机制可谓延迟赋值或类似的优化处理所用

3.扩容

  • 1.“一开始就做对系统”纯属神话 ,反之,我们应该只去实现今天的用户故事,然后重构,明天再扩展系统、实现新的用户故事,这就是迭代和增量敏捷的精髓所在。测试驱动开发、重构以及它们打造出的整洁代码,在代码层面保证了这个过程的实现

  • 2.软件系统与物理系统可以类比。它们的架构都可以递增式的增长,只要我们持续将关注面恰当地切分

横贯式关注面:

  • 原则上,可以从模块、封装的角度推理持久化策略。但是在实践上,却不得不将实现了持久化策略的代码铺展到许多对象中,这就是横贯式关注面
  • 实际上,EJB架构处理持久化、安全和事务的方法是“预期“面向方面编程,而Aop是一种恢复横贯式关注面模块化的普适手段,在AOP中,被称为方面的模块构造指明了系统中哪些点的行为会以某种一致的方式被修改,从而支持某种特定的场景。这种说明是用某种简洁的声明或编程机制来实现的。

以持久化为例,可以声明哪些对象和属性(或其模式)应当被持久化,然后将持久化任务委托给持久化框架。行为的修改由 AOP 框架以无损方式在目标代码中进行。

4.Java代理

  • 1.适用于简单情况,例如在单独的对象或类中包装方法调用。然而,JDK 提供的动态代理仅能与接口协同工作对于代理类,你得使用字节码操作库,比如 CGLIB、ASM 或 Javassist

代码量和复杂度是代理的两个大弱点,创建整洁代码变得很难。

如下例子: 在这里插入图片描述在这里插入图片描述 ==即便是对于这么简单的例子,也有很多相对复杂的代码==。

5.纯Java AOP框架

幸运的是,编程工具能自动处理大多数代理模版代码。在数个 Java 框架中,代理都是内嵌的,如 Spring AOP 和 JBoss AOP 等,从而能够从纯 Java 代码实现面向方面编程。在 Spring 中,你将业务逻辑编码成旧式 Java AOP 对象。==POJO (Plain Ordinary Java Object,简单的 Java 对象,实际就是普通 JavaBean。)自扫门前雪==,并不依赖于企业框架(或其他域)。因此,它在概念上更简单、更易于测试驱动。相对简单性也较易于保证正确地实现相应的用户故事,并为未来的用户故事维护和改进代码。

使用描述性配置文件或 API ,你把需要的应用程序构架组合起来,包括持久化、事务、安全、缓存、恢复等横贯性问题。在许多情况下,你实际上只是指定 Sprint 或 Jboss 类库,框架以对用户透明的方式处理使用 Java 代理或字节代码库的机制。这些声明驱动了依赖注入(DI)容器,DI 容器再实体化主要对象,并按需将对象连接起来。

6.AspectJ的方面

通过方面来实现关注面切分的功能最全的工具是 AspectJ 语言,一种提供 “一流的” 将方面作为模块构造处理支持的 Java 扩展。在 80% ~ 90% 用到方面特性的情况下,Spring AOP 和 JBoss AOP 提供的纯 Java 实现手段足够使用

然而,AspectJ 的弱势在于,需要采用几种新工具,学习新语言构造和使用方式。

7.测试驱动系统架构

  • 1.通过方面式(AOP)的手段切分关注面的威力不可低估。假使你能用POJO编写应用程序的领域逻辑,在代码层面与架构关注面分离开,就有可能真正地用测试来驱动架构。

  • 2.没必要先做大设计(Big Design Up Front,BDUF),BDUF甚至是有害的,它阻碍改进,因为心理上会抵制丢弃即成之事,也因为架构上的方案选择影响到后续的设计思路。

  • 3.我们可以从“简单自然”但切分良好的架构开始做软件项目,快速交付可工作的用户故事,随着规模的增长添加更多基础架构。

  • 4.最佳的系统架构由模块化的关注面领域组成,每个关注面均用纯Java(或其他语言)对象实现,不同的领域之间用最不具有侵害性的方面或类方面工具整合起来,这种架构能测试驱动,就像代码一样。

8.优化决策

  • 1.模块化和关注面切分成就了 分散化管理和决策

  • 2.延迟决策至最后一刻也是好手段,它让我们能够基于最有可能的信息做出选择提前决策是一种预备只是不足的决策。如果决策太早,就会绝少太多客户反馈、关于项目的思考和实施经验。

  • 3.拥有模块化关注面的POJO系统提供的敏捷能力,允许我们基于最新的知识做出优化的、时机刚好的决策,决策的复杂性也降低了。

9.明智使用添加了可论证价值的标准

有了标准,就 更易复用 想法和组件、雇用拥有相关经验的人才、封装好点子,以及将组件连接起来。不过,创立标准的过程有时却漫长到行业等不及的程度,有些标准没能与它要服务的采用者的真实需求相结合

10.系统需要领域特定语言

  • 1.领域特定语言(Domain-Specific Language, DSL)是一种单独的小型脚本语言或以标准语言写就的API,领域专家可以用它编写读像是组织严谨的散文一般的代码

  • 2.领域特定语言允许所有抽象层级和应用程序中的所有领域,从高级策略到底层细节,使用POJO来表达

  • 3.DSL 在有效使用时能提升代码惯用法和设计模式之上的抽象层次。它允许开发者在恰当的抽象层级上直指代码的初衷。

11.小结:

本章主要讲述了系统整洁,要达到系统整洁,需要注意模块功能的划分,注意简单的Been对象不与业务逻辑耦合在一起,做到职责单一

项目初始阶段,就将未来系统方方面面考虑周全,提供一大堆目前尚不要求的API或者功能点是不必要的,所要做到的是划分好各个功能模块,注意各个模块之间的可扩展性与相互隔离。这样方便后面不断进行扩展和重构优化,快速迭代敏捷开发。

12.示例:

构造与使用分离,会使得类之间的耦合度下降,方便后续进行实现上的替换修改。 举个相对简单的例子说明:

	public class HandlerImpl {
        public void handler() {
              Component component= new component();
              component.handle();
           }
    }

在这个例子中,由于构造与使用没有分离,即HandlerImpl即是Component的构造者(调用了构造函数),又是Component的执行者(调用了方法),在之后假设需要将Component的实现替换为接口实现类,或者其它类,就会导致整个系统中很多类似这样的地方都需要进行替换为

 Component component= new ComponentImpl();
 Component2 component= new Component2();

这样修改太多,耦合度太高,影响后续维护。 类似"分离构造与使用"可以使用类似工厂模式+面向接口编程,如:

	 public class HandlerImpl {
                public void handler() {
                    Component component= ComponentFactory.getComponent();
                    component.handle();
                }
            }
            
            public class ComponentFactory {
                public static Component getComponent() {
                    Component component= new componentImpl1();
                    return;
                }
            }

后续即便替换Component的实现,或者增加对使用Component条件的判断,都只需要修改构造器ComponentFactory而不需要取修改所有使用的地方:

 		public class ComponentFactory {
                public static Component getComponent() {
                    if (...) {
                       return new componentImpl1(); 
                    }
                    if (...) {
                        return new componentImpl2(); 
                    }
                }
            }

13.参考文献

《代码整洁之道》 daimajiaoliu.com/daima/4edf2… www.jianshu.com/p/c44eca6ad… juejin.cn/post/684490… blog.****.net/pengbo66656…

关注公众号“程序员面试之道”

回复“面试”获取面试一整套大礼包!!!

本公众号分享自己从程序员小白到经历春招秋招斩获10几个offer的面试笔试经验,其中包括【Java】、【操作系统】、【计算机网络】、【设计模式】、【数据结构与算法】、【大厂面经】、【数据库】期待你加入!!!

1.计算机网络----三次握手四次挥手

2.梦想成真-----项目自我介绍

3.你们要的设计模式来了

4.震惊!来看《这份程序员面试手册》!!!

5.一字一句教你面试“个人简介”

6.接近30场面试分享