读函数式编程思维笔记05_现实应用 读函数式编程思维笔记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.依靠一个事件流来反映应用程序的状态变化,而一个捕获所有信息并加上时间戳记的数据库,正好可以完美地扮演事件流的角色,数据库本身的特性即可满足回退和重放事件的需求