双向数据绑定UML类图设计

面向对象设计第一步是设计类的继承结构和类的实例依赖组合关系,而最好的表达莫过于UML类图。

考虑一个支持数据双向绑定的GridView的设计,首先设计ViewModel的类继承和对象关系

ViewModel类体系

ViewModel对象关系

以及View的类体系结构

View继承体系

View对象结构

最后处理双向绑定关系

双向绑定

响应式编程(Reactive Programming):自动恢复的能力(Resilience)

传统的应用在处理错误时

  • 粒度太粗,出现错误时,整个服务终止,然后做失效恢复,自动化一点的比如集群某一节点失效之后的Failover
  • 粒度太细,出现错误时,在错误出现的位置处理,典型的,比如根据函数返回值做判断。Java中的异常处理虽然可以交给调用堆栈的上级对象方法处理,仍然只能在有限的范围内处理,不能异步处理,而且将正常的应用逻辑和错误处理混在一起。

响应式编程要求应用快速响应错误,并快速的自动恢复,不影响业务逻辑的正常运作。这要求将错误也作为一种事件抛出,交给Supervisor角色去异步处理,而正常的业务逻辑与Supervisor是分开的,不会受到影响。把错误作为一等国民对待,对错误建模,在应用设计过程中一开始就考虑错误处理。

软件开发之道——面向对象设计是方法论

有人吐槽面向对象设计过于复杂,只要Design by Contract,Prefer Composition over Inheritance,Loose Couple就可以了。我要说,这样的认识层次还不够高。这就好比,因为红学家把红楼梦整的特玄乎,而认为红楼梦本身不是好作品。

面向对象分析与设计,是一种方法论,是我们认识世界和改造世界的方法的理论。接口,继承,多态,SOLID等等都只是表象,我们需要做的是透过现象看到本质——那就是,不要从一开始就尝试去具体解决一个问题,或者实现一个需求,而是去描述一个问题,即建模。面向对象设计只是众多建模方式的一种,函数式编程以函数为中心建模,状态机以状态和变迁为中心建模,而面向对象以对象为中心建模则是最符合人们对客观世界的认识的。正如做人一样,有自己的世界观作为准则,做事的时候不必拘泥于具体的某个方法。

Android 项目模块化开发

伴随移动设备的智能化,移动应用呈现出爆发式的增长。当应用多了以后,应用框架也就自然而然的提上日程。框架设计的第一步就是模块化,实现公共模块和应用模块,模块之间通过接口通信,然后才可能去更进一步的考虑依赖注入,MVC框架,领域和事件模型。Android在模块化方面继承了Java的特点,允许以jar包的方式组织和发布模块,不同的是Android必须将jar包打包进apk,不支持从ClassPath动态载入模块。

在Android模块依赖管理有两个经常遇见的问题:

  1. 为了将依赖的jar打包进apk,不仅仅要将jar加入依赖列表,还需要指定jar是Exportable的。在Eclipse下,要将jar的路径加入Build Path,还需要将其加入Export Path。用maven来进行模块构建以及依赖管理时,要将依赖的项目加入dependencies列表,并且注意scope不能指定为provided。如果打包好的apk在运行时报错,可以分析一下logcat的输出,如果发现NoClassDefFound之类的错误,则说明有一些依赖的包没有Export(另一个引起这个错误的原因是代码混淆没有配置好,这个以后再讨论)。有时候子类的定义没有找到的话,也会报父类找不到,所以需要仔细的看日志,找到根源的类。有时候Eclipse编译出来的apk可用,maven编译的不可用,这个时候可以考虑解压缩apk和反编译dex,找到maven编译的apk缺少的包和类。
  2. 有一些依赖的jar包只是编译期需要,而在运行时是不需要的,比如javax开头的包,在Eclipse下,不需要Export,而maven则需要指定其scope为provided。

最后,再强调一下,仔细的分析log,不能忽视任何警告和错误信息。

软件开发之道——演绎思维到归纳思维的转换

从面向过程到面向对象是一种思维方式的转变。面向过程是演绎思维,从一般到特殊,是由上而下的解决一个问题;而面向对象是归纳思维,从特殊到一般,是由下而上的描述一个问题

我们可以看到现代软件工程也是逐渐的从演绎向归纳变化:

  1. 面向过程是演绎思维,因为其关注的是流程,具体的怎样解决一个问题,表现为函数的逻辑组装。 面向对象是归纳思维,其关注的是对象建模,先抽象出共性和对象之间的关系。
  2. 同步编程是演绎思维,所谓同步就是一根筋,把问题分解为几个步骤,每一步都依赖于上一步的结果。 异步编程是归纳思维,整个系统通过异步事件驱动,所以要先抽象出事件模型。
  3. 瀑布模型是演绎思维,计划式的开发,一开始就关注具体的业务,每一步计划都依赖于上一步的计划,从一开始就希望控制整个过程。 敏捷模型是归纳思维,演进式的开发,要求从一开始归纳出最基本的Task,然后逐渐演化到更具体的业务,其实和面向对象从接口到具现类是一个道理

Disruptor Illustrated by Metaphor

What is disruptor

LMAX disruptor is a high performance alternative to bounded queues for exchanging data between concurrent threads. Disruptor is first applied in financial and messaging systems for its high performance.

Disruptor throughput compared to queue
Throughput

Latency compared to queue
Latency

Showing mechanical sympathy to modern CPU designs, disruptor is so fast in a parallel and staged environment. Following explains this in detail.

Parallel Programming

The best way to explain technology is by metaphor. As is said:

Technology is similar, thought behind is the key.

Metaphor in real world

You are the boss of a fast food restaurant, what are you supposed to do to serve more customers? You hire a waitress with fast hands.

Waitress with fast hands
Fasthand

However the speed of waitress is limited, so you hire another waitress. Now the two process requests in parallel, and total throughput is doubled.

Hire two waitresses
Morewaitress

Technology

Parallel programming is just the same. with a high speed CPU, programs can run fast, result in high throughput and low latency. However CPU speed is limited to several GHZ, so more CPU cores are introduced, and programs can run in parallel.

CPU speed is limited, but the core numbers obey Moore’s law
Moore's law

Staged processing

Metaphor

Your restaurant grows rapidly, so you must extend your business to more cities, even more countries. As the boss you can not manage all of your employee by yourself, instead you hire managers.

an organization is composed of multiple stages
Organization charts

Technology

Modern CPU has multiple level caches, and the architecture is similar to an organization.

CPU cache contains multiple stages
CPU cache

Amdahl’s law

Metaphor

In real world there is all kind of inefficiency, one department may depend on another. That’s why management theories exists.

Technology

In a program, how can we optimize process in such a parallel and staged environment?

Amdahl’s law

The speedup of a program using multiple processors in parallel computing is limited by the time needed for the sequential fraction of the program. If %5 of the program cannot compute in parallel, the speedup can only reach 20 times no matter how many processors there are.

Amdahl’s law
Amdahl's law

To remove inefficiency, just find the bottleneck that can not run in parallel, namely avoid shared resources.

Optimization: Batch message

The first bottleneck is main memory access, which is expensive.

Metaphor

Manager collect status of employees, but they do not send to the boss you one by one, instead they wait until all the status are collected, and send to you in a batch.

Technology

Similarly, CPU cache is split to cache lines, and batch read data from main memory.

Disruptor use ring buffer to place objects padding together in memory so as to avoid false sharing and cache miss.

Ring buffer
ringbuffer

Optimization: Lock free synchronization

Another bottleneck is shared locks.

Metaphor

People manager and product manager both manage employees. They can exchange status of employees directly since their offices are close to each other.

Technology

Synchronization for shared resource is expensive.

  1. Lock: involves context switch, which is quite expensive.
  2. CAS: lock instruction pipeline and complex to program.

lock penalty
Lock penalty

Disruptor use lock free memory barrier to synchronize sequence of ring buffer. Two cores in CPU talk to each other directly via memory barrier to exchange resource state, so as to avoid accessing shared locks.

memory barrier
Memory barrier

Reference

  1. LMAX disruptor on github
  2. Disruptor Technical Paper
  3. Mechanical sympathy
  4. Disruptor presentation@QCON
  5. Moore’s law@Wikipedia
  6. Amdahl’s law@Wikipedia
  7. Ring buffer@Wikipedia
  8. Memory Barriers: a Hardware View for Software Hackers