Monthly Archives: May 2016

LLVM tutorial写的很棒

LLVM project的 tutorial 真心不错,从lex, parser, AST, JIT, optimization 甚至debug info generating都介绍到了,而且还用了最新的C++ 11/14标准,实在是编译器入门兼练习C++新标准的好资料啊,即使是门外汉,一个星期也能撸个自己设计的语言原型了,带JIT的哦!想起自己刚学习编译原理入门的时候,哪有这种好的资料,都是死啃龙书,LR1那一章不知道撸了多少遍啊……

面向对象设计的日常 (一)

无论是developer或者architect,先掌握好面向对象设计的技术吧,自从设计模式普及推广开来,面向对象设计似乎变得没那么难了,大家熟练运用,甚至死记硬背了Adapter,Singleton,Factory,Abstract Factory,Strategy,Command,Vistor几种模式后,code似乎都写的像模像样了,但最难的把真实世界(系统)抽象化的能力根本还是一团浆糊,大多数情况下是堆叠一堆设计模式去“套”业务,实在套不上的,来个全是静态方法的Util类,还不行?再来个含糊的全能Context类总行了吧,我自己感觉Spring的广泛使用对这种畸形设计起到了推波助澜的作用,多美好啊,再也不用认真思考对象之间的关系,对象之间的交互过程,千篇一律的无参构造函数,惨绝人寰的set/get方法冗长列表,需要的接口统统注入进来,还容易沾沾自喜,我这可是面向接口编程哦。
举个简单的例子,一个REST的api sdk,大多数api都需要一个http header包含了一个token,这个token可以通过post username和password调用另一个authentication service endpoint去获得,
一般的思路,对于接口AuthenticationService我们会有下面的考虑,这本身是非常正常的,因为对于一般的authentication service它的职责就是认证用户,但在这个case里,其实authentication service的职责是提供访问token,所以下面的这种就是一个生搬硬套,过于死板的设计,依赖于经验,我们很多人的第一个版本很可能都是下面这样,包括我自己。

class AuthenticationService {
    public AuthenticationService(String endPoint){
        this.endPoint = endPoint; 
    }

    public String getToken(username, password) {
        return fetchToken(this.endPoint,username,password, ....);
    }   
}

而下面这种设计则更好的体现了在这种上下文中的authentication service的职责,

class AuthenticationService {
    public AuthenticationService(String endPoint,String userName, String password){
        this.endPoint = endPoint;
        this.userName = userName;
        this.password = password;
    }

    public String getToken() {
        return fetchToken(this.endPoint,this.userName,this.password, ....);
    }
}

这两种版本的根本区别在于是不是认为username和password是AuthenticationService本身的一部分,在这个case里它显然应该是。

我自己总结的面向对象设计的三个基本准则,

  • 对象应该尽量是immutable的,所以当业务类有大量的set方法时,要慎重考虑设计,Spring框架注入需要的不在此列,

  • 接口是行为抽象的集合,可以这么想,我有一个实现了接口的类对象,现在已经完全构造好了,那么我有什么方法可以调用,

  • 你的设计出来以后,给别的developer使用友不友好,使用者是不是要大量的了解某种细节才能使用

最后一点非常容易自我检查设计是不是有坏味道。

一家之言,大家可以自己体会和发表见解。