一个对话让你明白架构师究竟是作什么的?


(程序员:)我要成为一个软件架构师。
    (资深架构师:)对一个年轻的工程师来讲,这是一个很好的目标。
(程序员:)我要领导一个团队,还要作全部关于数据库、框架和Web服务器的重要决定。
    (资深架构师: )好吧,若是是这样,你就不必成为一个软件架构师了。
(程序员:)固然有必要了!我要成为一个可以作全部重要决定的人。
    (资深架构师:)这样很好,只是你没有列出哪些才是重要的决定。你刚才说的那些跟重要的决定没有什么关系。
(程序员:)你说什么?难道数据库不重要?你知道咱们在数据库上面花了多少钱吗?
    (资深架构师:)可能不少。不过数据库仍然不是最重要的。
(程序员:)你怎么能这么说呢?数据库但是整个系统的心脏啊!全部的数据都保存在这里,它们在这里被排序,被索引,被访问。若是没有数据库,整个系统就没法运做!
    (资深架构师:)数据库只不过是一个IO设备,它提供了一些有用的工具对数据进行排序、查询,并生成报表,但这些工具都只是整个系统的附属品。
(程序员:)附属品?真是难以想象。
    (资深架构师:)是的,附属品。你的系统业务逻辑或许会用到这些工具,但这些工具并不是业务逻辑固有的组成部分。若是有必要,你能够随时替换掉这些工具,但业务逻辑仍是那些业务逻辑。
(程序员:)好吧,不过若是把这些工具替换掉,咱们就要从新实现业务逻辑了。
    (资深架构师:)那是你的问题。
(程序员:)为何这么说?
    (资深架构师:)你认为业务逻辑依赖数据库,但实际上不是这样的。若是你的架构足够好,最起码业务逻辑不该该依赖数据库。
(程序员:)这太疯狂了。我怎么可能建立出不使用这些工具的业务逻辑?
    (资深架构师:)我并无说业务逻辑不要使用数据库工具,个人意思是它们不该该依赖这些工具。业务逻辑不该该知道使用的是哪种数据库。
(程序员:)若是业务逻辑对数据库一无所知,它怎么使用这些工具呢?
    (资深架构师:)依赖反转。你要让数据库依赖业务逻辑,而不是让业务逻辑依赖数据库。
(程序员:)你的话让人费解。
    (资深架构师:)费解吗?我讲的但是软件架构。这个就是依赖反转原则,让下层策略来依赖上层策略。
(程序员:)那就更加费解了!既然上层策略(假设你指的是业务逻辑)要调用下层策略(假设你指的是数据库),那么就应该是上层策略依赖依赖下层策略,就像调用者依赖被调用者同样。这是众所周知的!
    (资深架构师:)在运行时确实是这样的,但在编译时咱们要把依赖反转过来。上层策略的代码里不要引用任何下层策略的代码。
(程序员:)拜托!不引用代码就没法调用它们。
    (资深架构师:)固然能够调用了。面向对象就能够作到。
(程序员:)面向对象对真实世界进行建模,把数据和函数组合到对象里,把代码组织成直观的结构。
    (资深架构师:)这是他们告诉你的吗?
(程序员:)全部人都知道的,这不是很明显的事情吗?
    (资深架构师:)确实如此。不过,面向对象是能够作到不引用也能调用的。
(程序员:)好吧,那它是怎么作到的?
    (资深架构师:)你应该知道,在面向对象系统里对象会给其它对象发送消息的,对吧?
(程序员:)是的,固然。
    (资深架构师:)那么你就该知道,消息发送者是不知道消息接收者是什么类型的。
(程序员:)这要看使用的是哪种语言了。在Java里,发送者最起码要知道接收者的基本类型。在Ruby里,发送者知道接收者必定会处理它所发送的消息。
    (资深架构师:)是的。不过不论是哪种状况,发送者都不知道接收者具体的类型。
(程序员:)嗯,是的。
    (资深架构师:)因此发送者能够给接收者传递一个函数,让接收者执行这个函数,这样发送者就不须要知道接收者是什么类型了。
(程序员:)没错。我了解你的意思。不过发送者仍然依赖接收者。
    (资深架构师:)在运行时确实是的,但在编译时不是这样的。发送者的代码里并无引用接收者的代码。实际上,是接收者的代码依赖了发送者的代码。
(程序员:)啊!但发送者仍然会依赖接收者的类。
        (资深架构师:)看来须要用代码来讲明了,我用Java来写些代码。首先是发送者代码:
public class Sender {
  private Receiver receiver;
  public Sender(Receiver r) {
    receiver = r;
  }
  public void doSomething() {
    receiver.receiveThis();
  }
  public interface Receiver {
    void receiveThis();
  }
}
        (资深架构师:)下面是接收者代码:
public class SpecificReceiver implements Sender.Receiver {
  public void receiveThis() {
    //这里会作一些有趣的事情
  }
}
        (资深架构师:)能够看到,接收者代码依赖了发送者代码,也就是说SpecificReceiver依赖了Sender。同时能够看到,发送者代码对接收者代码一无所知。
(程序员:)哈,你做弊了。你把接收者的接口放到了发送者的类里了。
    (资深架构师:)你开始明白了。
(程序员:)明白什么?
    (资深架构师:)固然是架构原则啊。发送者持有接收者必须实现的接口。
(程序员:)若是这意味着我要使用内部类,那么……
    (资深架构师:)使用内部类只是方法之一,还有其它的方法。
(程序员:)请等一下。最开始咱们讨论的是数据库,那这些跟数据库又有什么关系呢?
        (资深架构师:)让咱们来看一下其它代码吧。首先是一个简单的业务逻辑
public class BusinessRule {
  private BusinessRuleGateway gateway;
  public BusinessRule(BusinessRuleGateway gateway) {
    this.gateway = gateway;
  }
  public void execute(String id) {
    gateway.startTransaction();
    Something thing = gateway.getSomething(id);
    thing.makeChanges();
    gateway.saveSomething(thing);
    gateway.endTransaction();
  }
}
(程序员:)这个业务逻辑没有作什么事情啊。
    (资深架构师:)这只是个例子。在实际实现业务逻辑的时候,不会有不少相似这样的类的。
(程序员:)好吧。那么Gateway是用来作什么的呢?
        (资深架构师:)它为业务逻辑提供了全部访问数据的方法。下面是它的代码:
public interface BusinessRuleGateway {
  Something getSomething(String id);
  void startTransaction();
  void saveSomething(Something thing);
  void endTransaction();
}
        (资深架构师:)要注意,这个接口是在businessRules包里面的。
(程序员:)好吧。那Something这个类又是用来作什么的呢?
        (资深架构师:)它表明一个简单的业务对象。我把它放在另外一个叫entities的包里。
public class Something {
  public void makeChanges() {
    //...
  }
}
        (资深架构师:)最后须要实现BusinessRuleGateway接口,这个实现类会知道相关的数据库细节:
public class MySqlBusinessRuleGateway implements BusinessRuleGateway {
  public Something getSomething(String id) {
    // 从MySQL里读取一些数据
  }
  public void startTransaction() {
    // 开始一个事务
  }
  public void saveSomething(Something thing) {
    // 把数据保存到MySQL
  }
  public void endTransaction() {
    // 结束事务
  }
}
    (资深架构师:)能够看到,业务逻辑是在运行时对数据库进行调用的。而在编译时,是database包引用了businessRules包。
(程序员:)好吧,我想我明白了。你用多态性隐藏了数据库实现。不过在业务逻辑里,仍然引用了数据库的工具接口。
    (资深架构师:)不,不是这样的。咱们并无打算为业务逻辑提供全部的数据库工具接口,而是业务逻辑建立了它们所须要的接口。在实现这些接口的时候,能够调用相应的工具。
(程序员:)嗯,这样的话,若是业务逻辑须要全部的工具,那么你必须把全部工具都放到Gateway接口里。
    (资深架构师:)哈,我以为你仍是没有明白。
(程序员:)不明白什么?我以为已经很清楚了。
    (资深架构师:)每一个业务逻辑只定义它所须要的接口。
(程序员:)等等,什么意思?
    (资深架构师:)这个叫做接口分离原则。每一个业务逻辑只使用一部分数据库工具,因此每一个业务逻辑只定义可以知足须要的接口。
(程序员:)这样的话,你就会有不少接口,并且有不少实现类。
    (资深架构师:)哈,是的。你开始明白了。
(程序员:)这样子很浪费时间!我为何要这样作呢?
    (资深架构师:)这样作是为了让代码更干净,而且节省时间。
(程序员:)算了吧,这样只会增长更多的代码。
    (资深架构师:)相反,这实际上是很重要的架构决定,这跟你以前所说的那些所谓的重要决定是不同的。
(程序员:)什么意思?
    (资深架构师:)还记得你刚开始说你要成为一个软件架构师吗?你还想要作全部重要的决定?
(程序员:)是啊,我是这么想过。
    (资深架构师:)你想作全部关于数据库、Web服务和框架的决定。
(程序员:)是啊,而你却说它们都不重要,还说它们其实跟重要的决定不相干。
    (资深架构师:)没错,它们确实跟重要的决定不相干。一个软件架构师真正要作的重要决定都在数据库、Web服务器和框架以外。
(程序员:)但首先要先决定用什么数据库、Web服务器或框架啊!
   (资深架构师:)实际上应该在开发后期才开始作这些事情——在你掌握了更多信息以后。
   (资深架构师:)当架构师草率地决定要使用一个数据库,后来却发现使用文件系统效率更高。
   (资深架构师:)当架构师草率的决定使用一个Web服务器,后来却发现团队须要的不过是一个socket借口。
   (资深架构师:)当架构师草率地决定使用一个框架,后来却发现框架提供的功能是团队不须要的,反而给团队带来了诸多约束。
   (资深架构师:)当架构师在掌握了足够多的信息后才决定该用什么数据库、Web服务器或框架。
   (资深架构师:)当架构师为团队鉴别出运行缓慢、耗费资源的IO设备和框架,这样他们就能够构建飞速运行的轻量级测试环境。
   (资深架构师:)当架构师把注意力放在那些真正重要的事情上,并把那些不重要的事情放在一边。
(程序员:)我彻底不知道你在说什么了。
    (资深架构师:)好吧,若是在若干年后你尚未转作管理,或许会明白这一切的……
程序员

文档来源:IT虾米网数据库

相关文章
相关标签/搜索