契约式编程

DbC的核心思想是对软件系统中的元素之间相互合作以及“责任”与“义务”的比喻。这种比喻从商业活动中“客户”与“供应商”达成“契约”而得来。例如:
供应商必须提供某种产品(责任),并且他有权期望客户已经付款(权利)。
客户必须付款(责任),并且有权得到产品(权利)。
契约双方必须履行那些对所有契约都有效的责任,如法律和规定等。
同样的,如果在面向对象程序设计中一个类的函数提供了某种功能,那么它要:
期望所有调用它的客户模块都保证一定的进入条件:这就是函数的先验条件—客户的义务和供应商的权利,这样它就不用去处理不满足先验条件的情况。
保证退出时给出特定的属性:这就是函数的后验条件—供应商的义务,显然也是客户的权利。
在进入时假定,并在退出时保持一些特定的属性:不变式。
契约就是这些权利和义务的正式形式。我们可以用“三个问题”来总结DbC,并且作为设计者要经常问:
它期望的是什么?
它要保证的是什么?
它要保持的是什么?
很多编程语言都有对这种断言的支持。然而DbC认为这些契约对于软件的正确性至关重要,它们应当是设计过程的一部分。实际上,DbC提倡首先写断言。
契约的概念扩展到了方法/过程的级别。对于一个方法的契约通常包含下面这些信息:
可接受和不可接受的值或类型,以及它们的含义
返回的值或类型,以及它们的含义
可能出现的错误以及异常情况的值和类型,以及它们的含义
副作用
先验条件
后验条件
不变式
(不太常见)性能上的保证,如所用的时间和空间
继承中的子类型可以弱化先验条件(但不可以加强它们),并且可以加强后验条件和不变式(但不能弱化它们)。这些原则很接近Liskov代换原则。
所有类之间的关系就是客户与供应商的关系。一个客户在调用供应商的功能时有义务不去违反供应商所需的状态。相应的,供应商也有义务为客户提供它所需的状态和数据。例如,供应商的delete功能要求客户在data buffer当中有数据存在。相应的,供应商要保证当delete功能完成后,data buffer中的数据已被删除。其它的设计契约还有不变式。不变式保证类的状态在任何功能被执行后都保持在一个可接受的状态。
当使用契约时,供应商不应对契约条件是否被满足进行校验。大体的思想是,利用契约条件校验为保护网,在契约被违反的情况下代码要“死翘翘”(fail hard)。DbC的“死翘翘”概念让对契约行为的调试变简单,因为每个过程的行为意图被定义得很清楚。它和一种叫作defensive programming的方法明显不同,在那种方法里,供应商要负责解决先验条件不满足的情况。相对通常的情况下,在DbC和defensive programming中,如果客户违反了先验条件供应商都会抛出异常—由客户来负责解决这种情况。DbC让供应商的工作更简单。
DbC同时也定义了软件模块的正确性条件:
如果对一个供应商的调用之前类的不变式和先验条件是真,那么在调用后不变式和后验条件也为真。
当调用供应商时,软件模块应保证不违反供应商的先验条件。
因为契约条件在程序运行中不应被违反,它们可以只作为调试代码,或者在发布版本中被移除从而得到更好的性能。
DbC也能帮助代码重用,因为每段代码的契约都被很好的文档化了。模块的契约可以被当做软件文档来 描述模块的行为。

——————-from Wikipedia

为啥要抄这个呢,因为我司比较蠢…接口的字段都是变化的…..

面向对象编程

意味着几件事情。
第一,参与这个系统的角色一定有多个,若只有一个角色,且只有一个动作,那就退化成面向过程编程。
第二,需要规约出系统的各个角色,以及相互之间的交互
第三,根据需要抽象出各种抽象层。
第四,每个抽象层的实现就是面向过程编程

note1.其实所谓的组件化就是合理的抽象出系统内的角色,然后以服务的形式对外运行,而非原来的代码层面的内联。
note2.现有大部分编程事件都是面向过程的层次,很少涉及设计,也少有人员想要先去设计

开发流程

产品提出需求->产品经理及项目经理评估需求->开发测试产品确定,细化需求,给出需求用例->测试给出测试用例->开发测试共同给出技术方案->开发->迭代测试->上线

需求必须留档,且产品需给出User Case角度的用例

其中用例可用于系统的自动化

测试用例是以黑箱角度给出,且应为产品的UserCase的细化
用例必须留档,提出bug必须依据用例,并生成bug用例进行验证

每次迭代只应该做增量测试,每天自动化做全量测试

用例Example:
测试:
动作:用户激活账号
前置条件:用户账号已注册且保持未激活状态
执行接口/事件:*.do 点击xxxx按钮,激活如下事件
预期:接口返回/事件结束/抛出异常/etc

产品:
测试:
动作:用户激活账号
前置条件:用户账号已注册且保持未激活状态
预期:用户成功激活账号

另外,开发和测试其实应该要求是一样的,都应该懂代码,完全的黑箱非自动化的测试是会搞死人的

SOA与REST关系

REST是实现SOA的一种技术手段
比如服务与服务之间的通信采用REST接口。
但其实服务与服务之间通信不仅是可以REST,同时可以用消息队列,分发器,soap等等
更具体的是,SOA代表一种战略意图,REST是实现战略意图的一种战术

有一些不得不吐槽的

新技术真的好么,我并不觉得,至少我所在的层级很不喜欢各种新技术
我原来从来没用过MyBatis,总听说多好多好,但是在绝大部分场景下,都不如我直接用spring jdbc template来的方便,它那套orm转换预设了太多假设,为了解决那一堆不符合假设的场景又发明一堆概念。

比方说一个很简单的例子:

  • 我的数据库的时间字段是varchar类型保存的,那么我用Spring jdbc大概会需要对一个表对象写大约二十行的代码做orm转换。
  • 但是我用Mybatis也不见得少几行,特别是用xml写sql的时候还要自己指定Handler来做转换。
  • 有一点更不方便,项目大部分都采用spring做对象管理,当基础包和上层应用都用spring管理了,而基础包却依赖了某个特定的spring配置项,然后大家就呵呵了

其实最中心想吐槽的应该是,基础包应该尽可能的少依赖外部,或者说自有配置应该打包输出并封装在自己的项目,不要和上层应用发生耦合,会造成各种的不舒服.

数据同步

网络传输的数据结构要点:

要能区分出数据来源

要能区分数据新旧

要能分辨数据正确性

除了对数据结构的直接操作,其他都应该是外部组件

数据状态

正常

过旧

冲突(定义为异常状态需要使用者自己处理)

以上抽象成Condition

可能的复杂点

多数据冲突同一个数据,组件不解决,应该由业务处理

组件需要保证每次同步都将会是原子操作,故而多线程并发会是难点

尽可能使的组件易于扩展(尽量用接口编程)

Gradle简易使用说明

无idea情况下

建立一个目录,shell进入相应的目录,执行gradle init就能够创建一个java项目了

gradle采用约定大于配置的模式,类似maven,以下是一个gradle项目目录结构:

├─.gradle
│  ├─3.3
│  │  └─taskArtifacts
│  ├─3.5
│  │  ├─file-changes
│  │  ├─fileContent
│  │  └─taskHistory
│  └─buildOutputCleanup
├─.idea
│  ├─libraries
│  └─modules
│      ├─module1
│      └─module2
├─build
│  ├─libs
│  └─tmp
│      └─jar
├─gradle
│  └─wrapper
├─module1
│  ├─build
│  │  ├─classes
│  │  │  ├─main
│  │  │  │  └─com
│  │  │  │      └─michaelssss
│  │  │  └─test
│  │  │      └─com
│  │  │          └─michaelssss
│  │  ├─libs
│  │  ├─reports
│  │  │  └─tests
│  │  │      └─test
│  │  │          ├─classes
│  │  │          ├─css
│  │  │          ├─js
│  │  │          └─packages
│  │  ├─test-results
│  │  │  └─test
│  │  │      └─binary
│  │  └─tmp
│  │      ├─compileJava
│  │      ├─compileTestJava
│  │      │  └─emptySourcePathRef
│  │      └─jar
│  └─src
│      ├─main
│      │  └─java
│      │      └─com
│      │          └─michaelssss
│      └─test
│          └─java
│              └─com
│                  └─michaelssss
└─module2
    ├─build
    │  ├─classes
    │  │  ├─main
    │  │  │  └─com
    │  │  │      └─michaelssss
    │  │  └─test
    │  │      └─com
    │  │          └─michaelssss
    │  ├─libs
    │  ├─reports
    │  │  └─tests
    │  │      └─test
    │  │          ├─classes
    │  │          ├─css
    │  │          ├─js
    │  │          └─packages
    │  ├─test-results
    │  │  └─test
    │  │      └─binary
    │  └─tmp
    │      ├─compileJava
    │      │  └─emptySourcePathRef
    │      ├─compileTestJava
    │      │  └─emptySourcePathRef
    │      └─jar
    └─src
        ├─main
        │  └─java
        │      └─com
        │          └─michaelssss
        └─test
            └─java
                └─com
                    └─michaelssss

idea能直接识别gradle项目,不用做额外配置

使用gradle简易动作:

gradle clean build test –fullstacktrace