近兩個月來,自己都在架構設計中痛苦掙紮著。很多人都會奇怪,做架構設計是多麼另人心動的事情呀,怎麼會痛苦呢?原因很簡單,就是我不會!本人就職以來並沒有系統的學習過架構設計,只是在工作中用到過一些如UML畫類圖等知識,而更多的,就是上頭分配任務給我做,而讓我從頭做架構設計,從來沒有過。我不知從何開始。
對不知的事物,我都是從搜尋引擎開始。我在網路上暢遊,想找到對我有用的東西,可是我發現用架構這個關鍵詞去搜尋,找到很多的是軟體架構這個詞條,還有一些網址。我把詞條通讀後,發現對我還是有協助的(因為我是零基礎),但這好像遠遠不夠。我想找這方面的教程,找到一些培訓的課程的目錄,裡面好多都是我想學習的,但是並沒有找到書籍。嘗試過不同關鍵字後,找到了兩本外文書,是敘述如何做架構的,專業術語太多,我只好先放棄了。功夫不負有心人,找到了兩本中文教程。開始了我的邊學邊實踐的旅程。整個過程是很痛苦的,因為身邊並沒有人給你指導,只能靠著一兩本書,自己也不知道書中是否就是適合自己的,就這樣的摸索著,在最後完成後才感受到一些喜悅。
其實無論做什麼事,都要清楚要幹什麼。這在我們做軟體中就是要深入理解需求。這一點說起來容易,做起來很難。我的痛苦經曆告訴我,表達不清的需求太多,不明確就意味著這個東西不好做。很多時候,客戶是表達不清自己要什麼的,那麼需要我們去引導。這時有經驗的大牛就會發揮很大的左右。還有很多功能點遺漏,不定什麼時候客戶想起來了,讓你給加上。需求的不確定,對架構的要求就很高了。能夠支援擴充的架構才是好架構。
從需求中找出重點功能,圍繞著它塑造你的概念架構。有位老師這樣總結到:有這樣兩種常見的情況,商務程序不變而業務單元可變,方案就是利用設計模式構建軟體架構;另一種是業務單元不變而流程變化,方案就是需要適應商務程序敏捷性處理的面向服務的架構。我遇到的情況屬於第一種。
我需要一種架構。這方面我得到了同事的大力支援。給出了非常好的適應變化的架構。舉個耳熟能詳的例子,《Java編程思想》中講解內部時引入了一個Control架構,對,就是這種思想。
//: Event.java// The common methods for any control eventpackage 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(); } } ///:~
有了這種架構的思想,下面就容易做到“把穩定和變化分離開”,做到封裝變化。
細化架構的時候,需要確定各模組的介面和資料結構。一個好的資料結構會讓你的架構增光不少。一個原則,就是要把資料結構設計好,讓其適應變化。
這個時候就可以開始基類的定義了,畫類圖、時序圖等等。文檔也是必不可少。
這方面我還沒有好好做就開始編碼了,而且架構也在適當的修改著。
這隻是一個開始,以後還能有機會做設計,就不會想這次這樣痛苦和難堪了。