美文网首页
第十二、十三章:迭进和并发编程

第十二、十三章:迭进和并发编程

作者: hklbird | 来源:发表于2016-11-16 19:58 被阅读10次

一、迭进

Kent Beck关于简单设计的四条原则:

  • 运行所有测试
  • 不可重复
  • 表达程序猿的意图
  • 尽可能减少类和方法的数量
  • 以上顾着按其重要程度排序

1.1 简单设计规则1:运行所有测试

设计的首要目的是设计出如预期一般工作的系统。
  全面测试并持续通过所有测试的系统,就是可测试系统。看似浅显,但却重要。不可测试的系统不可验证。不可验证的系统不可部署。紧耦合的代码难以编写测试。同样,测试编写越多,就越会遵循DIP之类的规则。

1.2 简单设计规则2~4:重构

有了测试,就能保持代码和类的整洁,方法就是递增式地重构代码。完成修改,运行测试,保证没有破坏任何东西。所以,<b>测试消除了清除代码就会破坏代码的恐惧</b>。
  重构的过程中,可以应用有关优秀软件设计的一切知识。提升内聚性,降低耦合度,切分关注切面,模块化系统关注面,缩小函数和类的尺寸,选用更好的名称。即消除重复,保证表现力,尽可能较少类和方法数量。

1.3不可重复

重复是拥有良好设计系统的大敌。Repeat Code代表extra work,意味着extra risk。大量重复可以用模板方法来消除。

1.4表现力

这需要尝试,让后来者易于阅读代码。

1.5尽可能减少类和方法

这是为了防止教条主义,片面追求设计原则,从而导致过度切分。例如给每一个类编写接口,所有行为都切分为数据类和行为类。但是这是优先级最低的一条。

二、并发编程

对象是过程的抽象,线程是调度的抽象。——James O Coplien

并发是一种解耦策略。它帮助我们把做什么(目的)和何时(时机)做分解开。这种解耦能有效改进应用程序的吞吐量和结构。
并发编程很难,往往不细心,你会搞出不知道什么鬼的恶心东西出来。看看下面的迷思和误解:

  • 并发总能改变性能
    并发有时候能改变性能,但一般在多个线程或处理器之间能风向大量等待时间的时候管用。
  • 编写并发程序无须修改设计
    这是完全bullshit。目的和时机的解耦代表着往往对系统结构产生巨大的影响。
  • 在采用Web或EJB容器的时候,理解并发问题其实不重要。
      实际上你最好理解并发在干什么。
      总结一下:并发有额外的开销;正确的并发是复杂的;并发缺陷并不总能重现,所以被当做是“基因突变”;并发往往需要对设计策略的根本性的修改。

2.1并发防御原则

2.1.1单一权责原则

SRP:方法、类、组件应当只有一个修改理由。

  • 并发相关代码有自己的开发、修改和调优生命周期
  • 并发相关代码有自己要对付的挑战,和并发相关代码不同
  • 并发编程错误不可控,可能会导致game over、
      建议:分离相关代码和其他代码。

2.1.2推论:限制数据作用域

如我们所见,连个线程修改共享对象的统一字段时。采用临界区域形式保护(synchronize)。限制临界区数目,临界区数目越多:

  • 忘记保护一个或多个临界区——破坏了共享数据的代码。
  • 花力气保护一切都受到保护。(遵循DRY原则:Don't repeat yourself)
  • 很难找到错误源。

2.1.3推论:使用数据副本和线程尽可能独立

避免共享数据的方法就是一开始就避免共享数据。
  让每个线程在自己的世界里存在,不与其他线程论短长。

2.2执行模型

基础定义:互斥、线程饥饿、死锁、活锁。
  执行模型:

  • 生产者-消费者:生产者和消费者之间的队列是一种限定资源。
  • 读者-作者模型:当存在一个主要围读者线程提供资源的共享资源,其偶尔才被作者进行写。协调吞吐量很重要。
  • 宴席哲学家:获得所有资源,执行,否则等待。

2.3警惕同步方法的依赖和保持同步区域微小

同步方法之间的依赖会导致并发代码中的狡猾缺陷。Java有synchronize关键字,保护单个方法,然而,如果再同一共享类中有多个同步方法,系统就可能写得不太正确了。
<b>建议:避免使用一个共享对象的多个方法。</b>
  三种对写代码保护方法:

  • 基于客户端锁定
  • 基于服务端锁定
  • 适配服务器
      尽量减少同步区。

2.4很难编写正确的关闭代码和测试线程代码

关闭的建议:尽早考虑关闭问题,尽早令其工作。
  尽管测试无法证明代码的正确性,但测试可以降低风险。
  测试的建议:编写有潜力暴露问题的测试,在不同的环境下频繁运行。

  • 将伪失败看做是线程的问题:不要讲系统错误归咎于“基因突变”。
  • 先使非先线程代码可工作:不要同时最终非线程缺陷和线程缺陷。
  • 编写可插拔的线程代码:在不同配置环境下运行。
  • 编写可调整的线程代码。
  • 运行多余处理器数量的线程。
  • 在不同平台运行。
  • 调整代码并强迫错误发生。

相关文章

网友评论

      本文标题:第十二、十三章:迭进和并发编程

      本文链接:https://www.haomeiwen.com/subject/hgbrpttx.html