1.规则1.1.传递参数,返回结果1.1.1.异常和中断都不算返回结果1.2.减少共享的可变数据结构能帮助你降低维护和调试程序的代价2.耦合性2.1.软件系统中各组件之间是否相互独立3.内聚性3.1.系统的各相关部分之间如何协作4.无状态的行为4.1.流水线中的函数不会由于需要等待从另一个方法中读取变量,或者由于需要写入的变量同时有另一个方法正在写而发生中断4.2.无须担心锁引起的各种问题4.3.充分发掘系统的并发能力5.副作用5.1.函数的效果已经超出了函数自身的范畴5.2.除了构造器内的初始化操作,对类中数据结构的任何修改,包括字段的赋值操作5.3.抛出一个异常5.4.进行输入/输出操作6.无副作用6.1.纯粹的6.2.如果一个方法既不修改它内嵌类的状态,也不修改其他对象的状态,使用return返回所有的计算结果6.3.如果构成系统的各个组件都能遵守这一原则,该系统就能在完全无锁的情况下,使用多核的并发机制,因为任何一个方法都不会对其他的方法造成干扰6.4.了解程序中哪些部分是相互独立的7.不可变对象7.1.一旦完成初始化就不会被任何方法修改状态7.2.一旦一个不可变对象初始化完毕,它永远不会进入到一个无法预期的状态7.3.线程安全的8.声明式编程8.1.关注要做什么8.2.更加接近问题陈述9.命令式编程9.1.指令和计算机底层的词汇非常相近9.2.专注于如何实现10.引用透明性10.1.没有可感知的副作用10.1.1.不改变对调用者可见的变量10.1.2.不抛出异常10.1.3.不进行I/O10.2.如果一个函数只要传递同样的参数值,总是返回同样的结果,那这个函数就是引用透明的11.记忆化11.1.缓存11.2.对代价昂贵或者需长时间计算才能得到结果的变量值的优化11.2.1.通过保存机制而不是重复计算12.函数式编程12.1.程序有一定的副作用12.1.1.该副作用不会被其他的调用者感知12.1.1.1.如果没人能感知的话,函数式也允许进行变更,这意味着可以修改局部变量12.1.2.调用者不需要知道,或者完全不在意这些副作用12.2.如果有副作用12.2.1.必须设法隐藏它们的非函数式行为12.2.2.否则就不能调用这些方法12.2.3.需要确保它们对数据结构的任何修改对于调用者都是不可见的,可以通过首次复制,或者捕获任何可能抛出的异常实现这一目的12.3.函数式的函数或方法都只能修改本地变量12.3.1.所有的字段都为final类型12.3.2.所有的引用类型字段都指向不可变对象12.3.3.引用的对象都应该是不可修改的对象12.4.选择使用引用透明的函数12.5.不应该抛出任何异常12.5.1.选择在本地局部地使用异常,避免通过接口将结果暴露给其他方法,这种方式既取得了函数式的优点,又不会过度膨胀代码13.局部函数式(partial function)13.1.大多数的输入值都返回一个确定的结果13.2.对另一些输入值,它的结果是未定义的,甚至不返回任何结果13.2.1.除法,如果除法的第二操作数是013.2.2.开平方运算,开平方的参数为负数13.2.3.使用Optional类型14.纯粹的函数式编程14.1.不提供像while或者for这样的迭代结构14.1.1.这种结构经常隐藏着陷阱,诱使你修改对象15.递归recursion15.1.函数式编程特别推崇的一种技术15.2.培养你思考要“做什么”的编程风格15.3.每个程序都能使用无须修改的递归重写,通过这种方式避免使用迭代15.3.1.采用递归可以取代迭代式的结构,比如while循环15.3.2.使用递归,可以消除每步都需更新的迭代变量15.4.递归的形式通常效率都更差一些15.4.1.因为每次执行递归方法调用都会在调用栈上创建一个新的栈帧,用于保存每个方法调用的状态(即它需要进行的乘法运算),这个操作会一直指导程序运行直到结束15.4.2.很容易遭遇StackOverflowError异常15.5.大多数时候编程的效率要比细微的执行时间差异重要得多15.6.尾调优化(tail-call optimization)15.6.1.编写方法的一个迭代定义,不过迭代调用发生在函数的最后15.6.1.1.调用发生在尾部15.6.2.Java不支持这种优化15.6.3.Scala、Groovy和Kotlin,支持对这种形式的递归的优化15.6.3.1.最终实现的效果和迭代不相上下(它们的运行速度几乎是相同的)