系统架构师-基础到企业应用架构-企业应用架构
為什么80%的碼農都做不了架構師?>>> ??
一、上篇回顧
????? 我們先來回顧下上篇講解的內容,我們前面的幾節分別講述了,業務邏輯層、數據訪問層、服務層、表現層,我們了解了這些分層的職責和分層之間的大概的關聯
關系,本篇可能主要是簡單的介紹下企業應用的幾類模式,結合這幾個分層直接的交互來完成系統功能的構建。我們還是先對我們學習的四個分層的職責和功能做個大
概的回顧,我們先來看看下圖來回顧下我們講述的內容。
?????
????? 我想通過上圖,大家能回憶起我們講述的相關內容,然后整理好自己的思路,我們本文將會針對這幾個分層進行相應的模式的講解,并且會結合實例來說明企業應
用架構的簡單應用。我想這也是大家關心的內容,我也希望大家能多提出寶貴意見,大家共同提高。
????? 之前說是提供PDF文件的下載的,以提供給需要學習的朋友更方便的形式,但是由于最近時間有限,沒能整理好,等過陣子提供一個完整的整合好的PDF版本,提
供給大家下載,還望大家見諒。
二、開篇
????? 本篇我們將針對我們前面講述的幾個分層做個簡單的整合,就是通過一個簡單的實例代碼來說明下,我們給出的一個可能的企業應用架構模式去完成企業應用,并
且順帶分析下,企業應用中可能存在的瓶頸等,當然可能本章只是點出一些概念,然后在后面的章節中去完成,比如我們的性能優化,性能瓶頸等,這些我們后面通過
這篇:系統架構師-基礎到企業應用架構-性能優化(架構瓶頸)(后續篇)詳細的分析。當然由于本章主要是基于前面講述的內容的一個整合和分析,可能部分觀點
還有更好的改進方案,還希望大家多提出寶貴意見和您的建議,謝謝!那么我們先來看看我們本章講述的內容吧:
?????
????? 本章主要講述下各分層之間的交互方式及可行的設計方案,并且分析我們在每個分層采用什么樣的模式,及給出相應的示例代碼,當然這里可能講述的不會是最好
的實現方案,還期待大家提出更好的改進方案。
三、本文提綱
????? 1、內容回顧
????? 2、開篇
????? 3、本文提綱
????? 4、企業應用架構實例
??????????? 4.1、企業應用架構中的物理分層
??????????? 4.2、數據訪問層分析
??????????? 4.3、業務邏輯層分析
??????????? 4.4、服務層分析
??????????? 4.5、表現層分析
??????????? 4.6、分析總結
????? 5、結束語
????? 6、系列進度
????? 7、下篇預告
四、企業應用架構實例
???????? 4.1、企業應用架構的物理分層
????? 本節將會分層的相關介紹,并且分析分層的原因,為下篇:系統架構師-基礎到企業應用架構-分層[上篇] 做鋪墊。
???? 分層我想對大家來說都不會太陌生。因為我們平時在開發的過程中一般都是采用分層架構的方式,通過分層將系統的功能進行劃分,我們將系
統中的若干有共同特征的部分放在一個分層中,然后通過分層之間的交互去完成系統的功能。
???? 我們看看企業應用的幾種應用程序模式:
?????
??? 1、單擊應用程序就是一些本地服務的應用程序,這個應該沒啥特別的難度,例如Office應用程序,當然現在有在線版本的Office,這個應用的太多了。
??? 2、客戶端/服務器的形式,特別是在WinForm、WPF、SilverLight方面的應用等,例如我們的常用的OutLook,雖然不是采用.NET平臺開發的,但是原理一樣就
是通過客戶端通過通信服務來訪問服務器,然后取回相應的郵件信息返回給客戶端,相當于我們通過客戶端的形式來訪問Web服務。
??? 3、Web服務:通過將開發的Web服務器部署在服務器上,然后我們就可以通過輸入HTTP網址的形式來訪問web服務,我們這里是通過瀏覽器來完成的,其實這個
模式也是客戶端/服務器的形式。只不過這時的客戶端變成瀏覽器+服務頁面,然后通過瀏覽器來完成Web服務的訪問。
??? 4、其他服務:我們這里主要是針對一些其他的設備,例如通信設備等方面的訪問,比如說我們現在提供一個衛星定位的服務,那么通過設備調用服務來完成,告知
用戶的GPS定位信息等。很多這個方面的應用。這個方向應該是未來的一個主流吧。
??? 我們上面簡單的講述了系統的物理分層的形式,那么我們來看看如何對系統的功能進行分層,也就是我們下面要詳細講解的實例分析。
? ???? 4.2、數據訪問層分析
???? 數據訪問層我們知道是唯一一個可以與數據庫之間直接進行交互的分層,數據訪問層必須滿足的幾個功能和職責,我們這里就不復述了,我們本篇可能就是直接給
出數據訪問層的相關實現,并且分析出數據訪問層與其他層之間的交互。
????? 大家可能一看就知道是什么意思,可能在您的眼中應該就和你們平時項目中采用的分層結構有點類似吧。
????? 我這里的數據訪問層提供所有的數據庫訪問服務。我們來看看基本的服務功能吧
????? 我們這里定義了一個DDL語句操作的枚舉,CUD的枚舉,因為我們提供了一個統一的數據訪問服務,通過Excute來完成。
/// <summary> /// 數據訪問操作類型 /// </summary> public enum DDLType { Create, Update, Delete }???? 這里用枚舉來定義數據庫字段與查詢條件值之間的關系
/// <summary> /// 數據字段與字段值之間的關系表達式 /// </summary> public enum FieldExpressionType { EquleTo, BeginThen, LessThen, BetweenAnd, Like }??? 我們再來看看我們定義的查詢條件的接口
/// <summary> /// 定義子查詢接口 /// </summary> public interface ICondition { int Add(string fieldName,object value,FieldExpressionType fetType); int Add(ICondition condition); string WhereCondition; string OrderCondition; }??? 數據訪問層接口代碼
/// <summary> /// 定義統一的數據訪問服務 /// </summary> public interface IDataAccess { #region CUD int Create<T>(T item); int Update<T>(T item); int Delete<T>(T item); int Execute<T>(T item,DDLType ddlType); #endregion #region Read服務 List<T> Query<T>(ICondition condition); T GetModelByPrimaryKey<T>(object key); List<T> GetAll<T>(); #endregion #region 事務操作 void BeginTransaction(); bool Commit(); bool RollBack(); bool IsTransaction; #endregion }??? 我們知道具體的代碼我們是通過反射+特性的形式來完成數據庫操作語句的生成的,我們來看看可行的代碼,屬性項特性的定義。
/// <summary> /// Model中的字段屬性特性 /// </summary> [AttributeUsage(AttributeTargets.All, AllowMultiple = false)] public class PropertyAttribute : Attribute { private string dbColumnName; private bool isPrimary; private DbType dbType; private object defaultValue; private bool isIdentify; private int length; public string DbColumnName { get { return this.dbColumnName; } set { this.dbColumnName = value; } } public bool IsPrimary { get { return this.isPrimary; } set { this.isPrimary = value; } } public bool IsIdentify { get { return this.isIdentify; } set { this.isIdentify = value; } } public DbType DbType { get { return this.dbType; } set { this.dbType = value; } } public object DefaultValue { get { return this.defaultValue; } set { this.defaultValue = value; } } public int DbLength { get { return this.length; } set { this.length = value; } } public PropertyAttribute(string dbName, bool isPrimery, DbType type,object dValue) { this.dbColumnName = dbName; this.isPrimary = isPrimery; this.dbType = type; this.defaultValue = this.GetDefaultValue(); } private object GetDefaultValue() { return new object(); } public PropertyAttribute(string dbName) { this.dbColumnName = dbName; this.isPrimary = false; this.dbType = DbType.String; this.defaultValue = this.GetDefaultValue(); } public PropertyAttribute(string dbName,bool isPrimery) { this.dbColumnName = dbName; this.isPrimary = isPrimery; this.dbType = DbType.String; this.defaultValue = this.GetDefaultValue(); } public PropertyAttribute(string dbName, bool isPrimery, DbType type) { this.dbColumnName = dbName; this.isPrimary = isPrimery; this.dbType = type; this.defaultValue = null; } }??? 我們再來看看基于表上的特性
/// <summary> /// 基于表的自定義特性類 /// </summary> [AttributeUsage(AttributeTargets.All, AllowMultiple = false)] public class TableAttribute : Attribute { private string dbTableName; public TableAttribute(string dbName) { this.dbTableName = dbName; } public string TableName { get { return this.dbTableName; } set { this.dbTableName = value; } } }根據反射取出表名/// <summary> /// 返回Model對應的數據庫表名 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="model"></param> /// <returns></returns> public string DbTableName<T>(T model) { string dbName = string.Empty; DPM.Common.TableAttribute attr = null; object[] attributes = model.GetType().GetCustomAttributes(typeof(DPM.Common.TableAttribute), true); if (attributes.Length > 0) { attr = (DPM.Common.TableAttribute)attributes[0]; } if (attr != null) dbName = attr.TableName; return dbName; }根據反射取出表中的列/// <summary> /// 動態創建表中字段列表 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="model"></param> /// <returns></returns> public string InitDbColumns<T>(T model) { StringBuilder commandBuilder = new StringBuilder(); DPM.Common.PropertyAttribute attr = null; foreach (PropertyInfo property in model.GetType().GetProperties()) { object[] attributes = property.GetCustomAttributes(typeof(DPM.Common.PropertyAttribute), true); if (attributes.Length > 0) { attr = (DPM.Common.PropertyAttribute)attributes[0]; } if(commandBuilder.length>0)commandBuilder.Append(“,”);commandBuilder.Append(attr.DbColumnName); } return commandBuilder.ToString(); }?????? 當然這里只是給出了簡單的示例,我們來看看生成的Insert 語句的格式吧
/// <summary> /// 動態創建表中字段更新列表 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="model"></param> /// <returns></returns> public string InitInsertColumns<T>(T model) { StringBuilder filedBuilder = new StringBuilder(); StringBuilder valueBuilder = new StringBuilder(); StringBuilder commandBuilder = new StringBuilder(); DPM.Common.PropertyAttribute attr = null; foreach (PropertyInfo property in model.GetType().GetProperties()) { object[] attributes = property.GetCustomAttributes(typeof(DPM.Common.PropertyAttribute), true); if (attributes.Length > 0) { attr = (DPM.Common.PropertyAttribute)attributes[0]; } if (attr.DbColumnName == "") continue; if (attr.IsIdentify) continue; if (filedBuilder.Length > 0) { filedBuilder.Append("," + attr.DbColumnName); valueBuilder.Append("," + property.GetValue(model, null)); } else { filedBuilder.Append(attr.DbColumnName); valueBuilder.Append(property.GetValue(model, null)); } } commandBuilder.Append(SqlDMLText.LKH); commandBuilder.Append(filedBuilder.ToString()); commandBuilder.Append(SqlDMLText.RKH); commandBuilder.Append(SqlDMLText.VALUES); commandBuilder.Append(SqlDMLText.LKH); commandBuilder.Append(valueBuilder.ToString()); commandBuilder.Append(SqlDMLText.RKH); return commandBuilder.ToString(); }?????? 其他的語句類似了,這部分詳細的代碼我們會在ORM篇詳細的講述,并且對反射的性能通過優化來提供性能。
?????? 我們來總結下數據訪問層應該有的功能吧。我認為應該提供以下的功能
?????? 這樣的一個數據訪問層基本上能夠滿足功能的需要。當然我這里就不把代碼全部貼出來了,太多
了,我們接下來講講業務邏輯層吧。
????????? 4.3、業務邏輯層分析
????? 上篇我們貼出來了一些比較典型的數據訪問層的代碼,當然沒有上全部的代碼,本文將會提供demo實例下載,大家可以參考其中的部分代碼。我們來看看業務層
中的每個業務對象應該具有什么樣的智能呢?我們知道我們這里不建議業務對象直接來訪問數據訪問層,那么我們如何實現持久化透明的方式呢?我記得之前我講述業
務邏輯層的時候也提到這個方面的要求了,還有不少熱心的園友問我如何實現,我這里給出幾個可能的辦法,當然如果有更好的辦法,還請大家多多提出。我這里給出
個簡單的業務對象的職責,當然我這里給出的職責是我理解的在我的這個實例中業務對象應該具有的職責。
????? 接下來我們看看業務邏輯層的職責吧,然后我們給出示例代碼
?????
????? 我們來舉例說明一個業務對象可能具有的功能吧?我們這里以還是以B2C系統為例吧,我們來說說訂單的可能行為吧:
/// <summary> /// 訂單 /// </summary> public class Order { /// <summary> /// 產品列表 /// </summary> private List<Product> products = new List<Product>(); /// <summary> /// 獲取訂單的金額 /// </summary> /// <param name="order"></param> /// <returns></returns> public decimal GetOrderCount(Model.Order order) { decimal totalCount = 0; foreach (Product product in products) { totalCount += product.Cash; } return totalCount; } /// <summary> /// 獲取該訂單下的所有產品 /// </summary> /// <param name="order"></param> /// <returns></returns> public List<Product> GetProduct(Model.Order order) { return new List<Product>(); } }???? 當然這里面的取得與訂單相關的產品列表,因為我們沒有設計在DTO中默認包含這個屬性,那么我們這里其實可以考慮增加延遲加載的形式,一旦加載后,也可以
第一次加載后,緩存起來,下次使用的過程中直接取出來。
????? 我們來看看與這個訂單業務邏輯相關的服務層代碼
/// <summary> /// 訂單服務 /// </summary> public class OrderService { private List<Model.Product> products = new List<Model.Product>(); /// <summary> /// 持久化透明的方式 /// </summary> /// <param name="order"></param> /// <param name="type"></param> /// <returns></returns> public int Execute(Model.Order order,DAL.DDLType type) { return DAL.SQLServer.Instance.Execute(order, type); } /// <summary> /// 獲取訂單的總金額 /// </summary> /// <param name="order"></param> /// <returns></returns> public decimal GetOrderCash(Model.Order order) { BLL.Order = new BLL.Order(order); return order.GetOrderCount(); } /// <summary> /// 保存訂單信息 /// </summary> /// <param name="order"></param> /// <param name="type"></param> /// <returns></returns> public int SaveOrder(Model.Order order, DAL.DDLType type) { int iAff = 0; //將與訂單相關的產品信息也同步進行保存。 //我們這里通過事務的方式進行處理 try { DAL.SQLServer.Instance.BeginTransaction(); //具體的邏輯 //插入產品信息 foreach (Model.Product product in products) { DAL.SQLServer.Instance.Create(product); iAff++; } //插入訂單信息 iAff+= DAL.SQLServer.Instance.Create(order); DAL.SQLServer.Instance.Commit(); return iAff; } catch { DAL.SQLServer.Instance.RollBack(); return 0; } finally { DAL.SQLServer.Instance.Dispose(); } } }????? 通過上面的代碼我們可以看出,目前的業務邏輯層中的業務對象只是處理自身的相關業務邏輯,通過服務層與數據層進行交互,然后業務對象并不關系自身的
CRUD的業務,而是通過服務層來完成的,那么對于CUD我想大家應該沒有什么爭議,因為持久化透明只是說把業務邏輯層原本通過繼承或者是實現接口,或者依賴注
入的形式來完成持久化的操作。
????? 我們這里則是將這樣的持久化操作提出來放在服務層來完成,這樣可以降低業務層與數據訪問層的依賴,那么大家肯定關心如何實現業務邏輯對象的查詢服務呢?
我的思路是這樣的,大家請看看是否合理,或者您有好的思路或者想法一定要告知我,不甚感激!
?????
????? 不知道我們上面的上圖是否表述的很清楚,還請大家多多的批評指出。當然上述的模式,可能在實際的企業應用中還是有點困難的,還有一種業務邏輯層的持久化
透明實現。就是通過AOP來完成,或者是通過代理類來實現。這里說心里話,我對AOP的具體實現并沒有研究過,但是通過動態注入的方式的確可以實現這個功能。具
體的實現方式就交給大家來完成了。
?????? 4.4服務層分析
????? 服務層作為協調業務對象進行相應的業務流的控制,當然服務層只是協調業務對象之間的交互,并不是負責具體的業務邏輯,這里的服務層應該是只負責業務對象
之間的交互。當然我這里還把部分對數據完整性,數據類型等方面的內容放在服務層來做。下面來說明服務層可能包含的功能:
?????
????? 我們在業務邏輯層中也貼出了部分代碼。當然服務層中其實還可以有很多的內容,比如通過我們在前面的服務層講解時介紹的幾個模式,我們也都是可以在服務層
中應用的。當然我們這里的實例代碼可能就不會貼出這幾個模式了,我們這里舉例來說明服務層中的部分服務代碼。例如我們前面經常舉例說明的訂單管理中的提醒功
能。
????? 比如我們有時候我們的提醒功能,需要郵件提醒或者是短信提醒的幾種服務方式,這時候我們可以通過提供統一的服務接口,然后不需要單獨的在界面層去單獨的
定義,我們通過接口的形式為后期的變化方便擴展,我們來給出部分代碼:
/// <summary> /// 提醒服務 /// </summary> public interface IAlarmService { /// <summary> /// 發送消息的服務 /// </summary> /// <param name="reciveObject">接收方</param> /// <param name="title">標題</param> /// <param name="content">消息內容</param> /// <returns></returns> bool SendMessage(string reciveObject,string title,string content); }我們來看看郵件提醒服務的簡單實現代碼public class EmailAlarm : IAlarmService { #region IAlarmService 成員 /// <param name="strSmtpServer">郵件服務器(如果是163郵箱就寫smtp.163.com)</param> /// strSmtpServer /// <param name="strFrom">發件人的帳號</param> /// strFrom /// <param name="strFromPass">發件人密碼</param> /// strFromPass public bool SendMessage(string reciveObject, string title, string content) { bool isSuccess = true; MailSetting model = DAL.SQLServer.Instance.GetModelByPrimaryKey<MailSetting>(); try { System.Net.Mail.SmtpClient client = new SmtpClient(model.strSmtpServer); client.UseDefaultCredentials = false; client.Credentials = new System.Net.NetworkCredential(model.strFrom, model.strFromPass); client.DeliveryMethod = SmtpDeliveryMethod.Network; System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage(model.strFrom, reciveObject, title, content); message.BodyEncoding = System.Text.Encoding.UTF8; message.IsBodyHtml = true; client.Send(message); } catch { isSuccess = false; } return isSuccess; } #endregion }????? 短信服務也和郵件服務類似,通過實現接口來提供服務,那么我們在比如說訂單,或者其他的可能會提醒的地方,就可以通過自定義實現不同的格式服務,來完成
調用。
?????? 4.5、表現層分析
???? 我們都知道表現層是最終顯示與用戶交互的功能的,那么我們的表現層是怎么來調用服務層的呢?我們這里的實例是采用服務層調用的方式來完成。我們這里通過
定義接口的形式,然后通過實現不同的用戶UI,然后我們通過展示器來調用服務層,然后將服務層中的處理結果返回給展示器,展示器與視圖之間進行交互,我們來看
看表現層的層級關系。
????? 大家看到這個圖請不要詫異,這里的展示器層可能還會直接訪問業務邏輯層,也可能直接訪問數據訪問層,這
些都是有可能的,我們需要根據項目具體的情況去決定。
???? 我們來看看UI層的視圖代碼:
???? 我們在視圖中保持展示器的引用。
/// <summary> /// 定義統一的視圖接口代碼 /// </summary> public interface IView { /// <summary> /// 展示器訪問器 /// </summary> B2C.Presenter.IPresenter Presenter { get; set; } }我們來看看展示器中的部分代碼/// <summary> /// 展示器接口 /// </summary> public interface IPresenter { /// <summary> /// 重新生成視圖 /// </summary> /// <returns></returns> string Review() { return string.Empty; } /// <summary> /// 操作Model /// </summary> /// <typeparam name="T"></typeparam> /// <param name="?"></param> /// <returns></returns> T Controller<T>(T item); }????? 視圖層通過依賴注入的方式,或者是屬性注入,還是實現接口的方式來實現展示器的引用,展示器提供接處理用戶操作的功能,然后根據處理后的結果決定是否刷
新視圖。
????? 當然如果你這里是借助的MVC框架來實現的話,可能控制器中的代碼就要是訪問服務層,或者業務邏輯層,數據訪問層了,可能代碼的形式會有所不同。其實我們
還有更好的方式去實現視圖的展現。比如我們可以讓視圖層與XML文件進行綁定的形式,展示器通過生成XML文件,然后視圖層界面去解析這個XML文件中的相應配
置,來完成展示,這樣的話,可能視圖層不需要處理單獨的代碼,而且視圖可以通過序列化與反序列化的形式,視圖的更改或者操作都可以有系統自動完成,而不需要
提供展示器來完成。當然這樣的形式僅限簡單的應用程序時,通過這樣的形式來處理可能會比較靈活。
?????? 4.6、分析總結
????? 我們上面主要講述了企業架構中的一個可能的架構,當然這樣的架構不是最好的方案,還需要大家多多討論和交流,我只是根據自己的經驗,結合一些項目中的一
些問題進行了總結之后分析這樣的架構模式,還不知道在實際的姓名中是否能滿足適應性和很好的擴展性,這個還有待檢驗,我這里并沒有給出完整的代碼實現,只是
給出一種可能的架構模式的結構,具體的實現代碼還需要大家自己完善。
????? 我們總結下我們講述的內容:
????? 1、分析了四個層次中我們對于設計的考慮和各分層中職責和他們之間的交互,我這里是通過實體層來處理DTO的。
????? 2、舉例給出部分代碼說明每個分層的職責并且分工要明確。
????? 3、表現層中與其他各層之間可能的交互關系。
????? 我想通過上面的可能的模式分析,給大家一個思路,讓大家通過這個思路有個更多的思考。
五、結束語
????? 本篇主要講述的是一個架構思路,給出的代碼可能不是完全的,只是給了一個各層的大概的結構,因為要實現這樣的一個完整的實例demo,那是需要非常多的代
碼和要考慮的因素很多,本篇很多內容并沒有涵蓋,不過我想這樣的方式是不太好的,我后面會盡量將前面講過的內容,整理出來,以后講述實例的時候盡量就是一個
可以運行的demo實例。
六、系列進度
前篇
????? 1、系統架構師-基礎到企業應用架構系列之--開卷有益
????? 2、系統架構師-基礎到企業應用架構-系統建模[上篇]
????? 3、系統架構師-基礎到企業應用架構-系統建模[中篇](上)
????? 4、系統架構師-基礎到企業應用架構-系統建模[中篇](下)
????? 5、系統架構師-基礎到企業應用架構-系統建模[下篇]
????? 6、系統架構師-基礎到企業應用架構-系統設計規范與原則[上篇]
????? 7、系統架構師-基礎到企業應用架構-系統設計規范與原則[下篇]
????? 8、系統架構師-基礎到企業應用架構-設計模式[上篇]
????? 9、系統架構師-基礎到企業應用架構-設計模式[中篇]
????? 10、系統架構師-基礎到企業應用架構-設計模式[下篇]
中篇
?? ? ?11、系統架構師-基礎到企業應用架構-企業應用架構
????? 12、系統架構師-基礎到企業應用架構-分層[上篇]
????? 13、系統架構師-基礎到企業應用架構-分層[中篇]
????? 14、系統架構師-基礎到企業應用架構-分層[下篇]
????? 15、系統架構師-基礎到企業應用架構-表現層
????? 16、系統架構師-基礎到企業應用架構-服務層
????? 17、系統架構師-基礎到企業應用架構-業務邏輯層
????? 18、系統架構師-基礎到企業應用架構-數據訪問層
????? 19、系統架構師-基礎到企業應用架構-組件服務
????? 20、系統架構師-基礎到企業應用架構-安全機制
后篇
????? 21、單機應用、客戶端/服務器、多服務、企業數據總線全解析
????? 22、系統架構師-基礎到企業應用架構-單機應用(實例及demo)
????? 23、系統架構師-基礎到企業應用架構-客戶端/服務器(實例及demo)
????? 24、系統架構師-基礎到企業應用架構-多服務(實例及demo)
????? 25、系統架構師-基礎到企業應用架構-企業數據總線(實例及demo)
????? 26、系統架構師-基礎到企業應用架構-性能優化(架構瓶頸)
????? 27、系統架構師-基礎到企業應用架構-完整的架構方案實例[上篇]
????? 28、系統架構師-基礎到企業應用架構-完整的架構方案實例[中篇]
????? 29、系統架構師-基礎到企業應用架構-完整的架構方案實例[下篇]
????? 30、系統架構師-基礎到企業應用架構-總結及后續
七、下篇預告
????? 下一篇我們將會開始講解系統架構中的分層-上-中-下進行相關討論及設計方案分析,這些都是本人在工作中的經驗總結,由于本人能力有限,不足之處,
還請大家多多指出。希望大家持續關注!
原文鏈接: http://www.cnblogs.com/hegezhou_hot/archive/2010/10/17/1853909.html
轉載于:https://my.oschina.net/dtec/blog/43783
總結
以上是生活随笔為你收集整理的系统架构师-基础到企业应用架构-企业应用架构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AgileEAS.NET平台开发实例-药
- 下一篇: VB无所不能之三:VB截获Windows