读函数式编程思维笔记05_现实应用

1. Java 8

1.1. 除了增加函数式特性,还增加了一些配合使用的语法糖衣

1.2. 函数式接口

1.2.1. SAM(Single Abstract Method,单抽象方法)接口

1.2.1.1. 含有单一方法的接口是Java的一种习惯用法

1.2.1.2. Runnable和Callable接口都是有代表性的例子

1.2.2. 对旧有SAM接口的增强,它允许我们用lambda块取代传统的匿名类来就地实例化一个接口

1.3. 默认方法

1.3.1. 一些在接口类型中声明的,以default关键字标记的,非抽象、非静态的public方法(且带有方法体定义)

1.4. mixin

1.4.1. 介于接口和父类之间的一种结构

1.4.2. 和接口一样都是类型,都可以执行instanceof检查,也都遵循一样的扩展规则

1.4.3. Ruby、Groovy等类似语言也允许通过mixin的形式,在既有的类层次上增补功能

1.5. Optional类型

1.5.1. min()等内建方法都不直接返回结果值,而是返回一个Optional结构

1.5.2. 提供了ifPresent()方法,可以用在终结操作的位置上,设定在仅当存在有效结果时执行的一个代码块

1.6. stream

1.6.1. 不存储值,只担当从输入源引出的管道角色,一直连接到终结操作上产生输出

1.6.2. 尽可能做到缓求值

1.6.3. 可以没有边界(无限长)

1.6.3.1. 用limit()、findFirst()等方法来取得其一部分子集

1.6.4. 用过之后必须重新生成新的stream才能再次操作

1.6.4.1. 消耗品

1.6.5. 操作分类

1.6.5.1. 中间操作

1.6.5.1.1. 一律返回新的stream,并且总是缓求值的

1.6.5.2. 终结操作

1.6.5.2.1. 遍历stream,产生结果值和副作用

2. 函数式的基础设施

2.1. 架构

2.1.1. 架构永远是取舍的结果

2.1.2. 从根本上贯彻“值不可变”的思路,最大化地发挥其优点

2.1.2.1. Java不允许字典型集合中的键在它被集合引用期间发生取值的变化,值不可变的对象完全符合这项要求

2.1.2.2. Groovy用语法糖衣掩盖了实现值不可变性的繁琐细节

2.1.2.2.1. 添加@Immutable标注

2.1.3. 测试是为了确认代码中成功地制造了我们需要的变化

2.1.3.1. 测试的真正目的是对可变事物的检验——可变的事物越多,就需要越多的测试来保证其正确性

2.1.3.2. 可变的状态越多,要求的测试也越多。

2.1.4. 值不可变的对象天生就是线程安全的,完全不会发生同步方面的问题

2.1.4.1. 具有原子性的失败(failure atomicity):只要对象构造完毕,就不会再发生由值可变性引发的失败

2.1.5. 实现一个值不可变的Java类

2.1.5.1. 把所有的字段都标记为final

2.1.5.1.1. 要么在声明时初始化,要么在构造器中初始化

2.1.5.2. 把类标记为final,防止被子类覆盖

2.1.5.3. 不要提供无参数的构造器

2.1.5.3.1. 一个值不可变的对象,它的一切状态都必须通过构造器来设定
2.1.5.3.2. 值不可变的类根本不应该出现无参数的构造器
2.1.5.3.2.1. 必须提供无参数的构造器,考虑用一个私有的无参数构造器来满足框架的要求
2.1.5.3.2.2. 私有的构造器仍然可以通过反射来访问

2.1.5.4. 提供至少一个构造器

2.1.5.5. 除了构造器之外,不要提供任何制造变化的方法

2.1.5.5.1. 标记了final的对象引用并不等于它所指向的一切都不可改变
2.1.5.5.2. 需要预防性地复制所有通过getXXX方法返回的对象引用

2.1.6. 命令-查询职责隔离架构

2.1.6.1. (Command-Query Responsibility Segregation,CQRS)

2.1.7. 最终一致性(eventual consistency)

2.1.7.1. 不对模型的变更操作施加硬性的时间限制,而只是保证,当更新发生后,模型最终会回复到一致的状态

2.1.7.2. 事务要求系统满足ACID(即原子性Atomic、一致性Consistent、隔离性Isolated、持久性Durable的缩写)性质,而最终一致性要求满足BASE(即基本可用Basically Available、软状态Soft state、最终一致性Eventual consistency的缩写)性质

2.1.7.3. 读取与变更分离之后,逻辑可得到简化

2.1.7.3.1. 承担读取职责的部分可以全面实现值不可变的性质

2.2. Web框架

2.2.1. 整个Web看作是一系列从请求到响应的变换

2.2.1.1. Web领域与函数式编程简直是天作之合

2.2.2. 路由框架

2.2.3. 以函数作为路由的目标

2.2.4. 领域专用语言(DSL)

2.2.4.1. 表达能力有限,专门针对一个狭窄问题域的计算机编程语言

2.2.4.2. 内部DSL是在其宿主语言之上构造出来的新“语言”,且利用宿主语言的语法糖衣来形成自身的风格

2.2.4.2.1. Ruby on Rails Web框架
2.2.4.2.2. C#语言的LINQ扩展

2.2.5. 与构建工具紧密集成

2.2.5.1. 和命令行的构建工具紧密集成,用构建工具来执行从生成新项目骨架到运行测试的一切任务

2.3. 数据库

2.3.1. Datomic是一种值不可变的数据库

2.3.1.1. 存储值而非数据,它的空间利用效率并不低

2.3.1.2. 进入到库里的每一笔事实都会被打上时间戳

2.3.1.3. 在信息上增加了时间的概念,使得每一笔事实都总是维持在正确的上下文里

2.3.1.4. 永久地记录所有的schema变更和数据变更

2.3.1.5. 读取和写入分离

2.3.1.5.1. Datomic拥有一个CQRS系统的内在

2.3.1.6. 事件驱动型架构中的值不可变性和时间戳

2.3.1.6.1. 依靠一个事件流来反映应用程序的状态变化,而一个捕获所有信息并加上时间戳记的数据库,正好可以完美地扮演事件流的角色,数据库本身的特性即可满足回退和重放事件的需求
posted @ 2023-01-24 08:31  躺柒  阅读(56)  评论(0编辑  收藏  举报