近两个月来,自己都在架构设计中痛苦挣扎着。很多人都会奇怪,做架构设计是多么另人心动的事情呀,怎么会痛苦呢?原因很简单,就是我不会!本人就职以来并没有系统的学习过架构设计,只是在工作中用到过一些如UML画类图等知识,而更多的,就是上头分配任务给我做,而让我从头做架构设计,从来没有过。我不知从何开始。
对不知的事物,我都是从搜索引擎开始。我在网络上畅游,想找到对我有用的东西,可是我发现用架构这个关键词去搜索,找到很多的是软件架构这个词条,还有一些网址。我把词条通读后,发现对我还是有帮助的(因为我是零基础),但这好像远远不够。我想找这方面的教程,找到一些培训的课程的目录,里面好多都是我想学习的,但是并没有找到书籍。尝试过不同关键字后,找到了两本外文书,是叙述如何做框架的,专业术语太多,我只好先放弃了。功夫不负有心人,找到了两本中文教程。开始了我的边学边实践的旅程。整个过程是很痛苦的,因为身边并没有人给你指导,只能靠着一两本书,自己也不知道书中是否就是适合自己的,就这样的摸索着,在最后完成后才感受到一些喜悦。
其实无论做什么事,都要清楚要干什么。这在我们做软件中就是要深入理解需求。这一点说起来容易,做起来很难。我的痛苦经历告诉我,表达不清的需求太多,不明确就意味着这个东西不好做。很多时候,客户是表达不清自己要什么的,那么需要我们去引导。这时有经验的大牛就会发挥很大的左右。还有很多功能点遗漏,不定什么时候客户想起来了,让你给加上。需求的不确定,对架构的要求就很高了。能够支持扩展的架构才是好架构。
从需求中找出重点功能,围绕着它塑造你的概念架构。有位老师这样总结到:有这样两种常见的情况,业务流程不变而业务单元可变,方案就是利用设计模式构建软件框架;另一种是业务单元不变而流程变化,方案就是需要适应业务流程敏捷性处理的面向服务的架构。我遇到的情况属于第一种。
我需要一种框架。这方面我得到了同事的大力支持。给出了非常好的适应变化的框架。举个耳熟能详的例子,《Java编程思想》中讲解内部时引入了一个Control框架,对,就是这种思想。
//: Event.java // The common methods for any control event package c07.controller; abstract public class Event { private long evtTime; public Event(long eventTime) { evtTime = eventTime; } public boolean ready() { return System.currentTimeMillis() >= evtTime; } abstract public void action(); abstract public String description(); } ///:~
/: Controller.java // Along with Event, the generic // framework for all control systems: package c07.controller; // This is just a way to hold Event objects. class EventSet { private Event[] events = new Event[100]; private int index = 0; private int next = 0; public void add(Event e) { if(index >= events.length) return; // (In real life, throw exception) events[index++] = e; } public Event getNext() { boolean looped = false; int start = next; do { next = (next + 1) % events.length; // See if it has looped to the beginning: if(start == next) looped = true; // If it loops past start, the list // is empty: if((next == (start + 1) % events.length) && looped) return null; } while(events[next] == null); return events[next]; } public void removeCurrent() { events[next] = null; } } public class Controller { private EventSet es = new EventSet(); public void addEvent(Event c) { es.add(c); } public void run() { Event e; while((e = es.getNext()) != null) { if(e.ready()) { e.action(); System.out.println(e.description()); es.removeCurrent(); } } } } ///:~
那么如何使用呢?一个greenhouse的例子:
//: GreenhouseControls.java // This produces a specific application of the // control system, all in a single class. Inner // classes allow you to encapsulate different // functionality for each type of event. package c07.controller; public class GreenhouseControls extends Controller { private boolean light = false; private boolean water = false; private String thermostat = "Day"; private class LightOn extends Event { public LightOn(long eventTime) { super(eventTime); } public void action() { // Put hardware control code here to // physically turn on the light. light = true; } public String description() { return "Light is on"; } } private class LightOff extends Event { public LightOff(long eventTime) { super(eventTime); } public void action() { // Put hardware control code here to // physically turn off the light. light = false; } public String description() { return "Light is off"; } } private class WaterOn extends Event { public WaterOn(long eventTime) { super(eventTime); } public void action() { // Put hardware control code here water = true; } public String description() { return "Greenhouse water is on"; } } private class WaterOff extends Event { public WaterOff(long eventTime) { super(eventTime); } public void action() { // Put hardware control code here water = false; } public String description() { return "Greenhouse water is off"; } } private class ThermostatNight extends Event { public ThermostatNight(long eventTime) { super(eventTime); } public void action() { // Put hardware control code here thermostat = "Night"; } public String description() { return "Thermostat on night setting"; } } private class ThermostatDay extends Event { public ThermostatDay(long eventTime) { super(eventTime); } public void action() { // Put hardware control code here thermostat = "Day"; } public String description() { return "Thermostat on day setting"; } } // An example of an action() that inserts a // new one of itself into the event list: private int rings; private class Bell extends Event { public Bell(long eventTime) { super(eventTime); } public void action() { // Ring bell every 2 seconds, rings times: System.out.println("Bing!"); if(--rings > 0) addEvent(new Bell( System.currentTimeMillis() + 2000)); } public String description() { return "Ring bell"; } } private class Restart extends Event { public Restart(long eventTime) { super(eventTime); } public void action() { long tm = System.currentTimeMillis(); // Instead of hard-wiring, you could parse // configuration information from a text // file here: rings = 5; addEvent(new ThermostatNight(tm)); addEvent(new LightOn(tm + 1000)); addEvent(new LightOff(tm + 2000)); addEvent(new WaterOn(tm + 3000)); addEvent(new WaterOff(tm + 8000)); addEvent(new Bell(tm + 9000)); addEvent(new ThermostatDay(tm + 10000)); // Can even add a Restart object! addEvent(new Restart(tm + 20000)); } public String description() { return "Restarting system"; } } public static void main(String[] args) { GreenhouseControls gc = new GreenhouseControls(); long tm = System.currentTimeMillis(); gc.addEvent(gc.new Restart(tm)); gc.run(); } } ///:~
有了这种框架的思想,下面就容易做到“把稳定和变化分离开”,做到封装变化。
细化架构的时候,需要确定各模块的接口和数据结构。一个好的数据结构会让你的架构增光不少。一个原则,就是要把数据结构设计好,让其适应变化。
这个时候就可以开始基类的定义了,画类图、时序图等等。文档也是必不可少。
这方面我还没有好好做就开始编码了,而且框架也在适当的修改着。
这只是一个开始,以后还能有机会做设计,就不会想这次这样痛苦和难堪了。