本文章是由機器翻譯。

在練習的模式

透過組態的慣例

Jeremy Miller

內容

語言創新的影響
說它一次,並僅一次
合理的預設值
透過組態的慣例
接下來的步驟

有您曾經覺得多少時間,在您的專案花費在與您花 wrestling 純粹的技術問題的時間,核心問題上嗎?一些可能會說所有新的軟體技術和技巧最重要目標是減少,軟體開發人員的意圖] 和 [在解析的程式碼中,目的之間的距離。業界持續已引發的抽象概念,以允許開發人員花更多的時間傳送功能和較少的時間撰寫低階基礎結構層級 (但有仍在長方式移。

思考這一分鐘。如果您要顯示您的業務代表您的程式碼 — 假設它們是實際上很願意閱讀與您的程式碼 — 該程式碼中有多少會它們在乎呢?這些商務代表將可能只注意程式碼,表示系統的商務功能。該程式碼會就是系統的 「 本質 」。另一方面,它們可能不會有任何的程式碼 (例如型別宣告、 組態設定、 try / catch 區塊和泛型條件約束興趣。該程式碼會是基礎結構或"典禮,」,您,程式的開發人員必須通過來發行程式碼。

在這個資料行的前一個 installments 我已主要探討基本設計概念 」 和 「 原則,最其中有已設計 Canon 的一部分很一段時間。這個時間大約我想要查看一些較新的技巧,您可以採用以減少的儀式,在程式碼量。可能您,新的部分這些概念,但我相信這一切會主流內有幾年的.NET 的一部分]。

語言創新的影響

我要考慮的第一個因數都是程式設計語言,以及如何使用程式設計語言的選擇。為了說明的程式設計語言的儀式,程式碼中量影響,讓我們將小的 detour 考慮的歷程記錄 musty 頁面。

稍早的這個十年我已建立大型系統,在 Visual Basic 6.0。每個方法就可以看起來像您在 [ 圖 1 ] 中看到。每個單一位元的程式碼都是儀式。

[圖 1 的獨立的儀式

Sub FileOperations()
    On Error Goto ErrorHandler

    Dim A as AType
    Dim B as AnotherType

    ' Put some code here

    Set A = Nothing
    Set B = Nothing
    ErrorHandler:
        Err.Raise Err.Number, _
            "FileOperations" & vbNewLine & Err.Source, _
            Err.Description, _
            Err.HelpFile, _
            Err.HelpContext
Exit Sub

我用來相當的現成的數量在每個方法上建立更容易偵錯的堆疊追蹤的對等用法。 我也必須取值的方法內的變數 (設定 A = Nothing) 來釋放這些物件。 我有嚴格的標準,只是為了驗證在錯誤處理和物件清除已編碼正確地在每個方法上的程式碼檢閱的。 所有的儀式的中間的實際的程式碼的系統的本質浮動某處。

今天,Contemporary 的程式設計語言,例如,C# 或 Visual Basic.NET 向前閃爍。 現在,記憶體回收排除大部分的明確的記憶體清除您用來在 Visual Basic 6.0 程式設計的表面。 這樣您就不再需要這麼做您自己的例外狀況的堆疊追蹤是內建本身,Microsoft.NET Framework。 如果考慮,當您移至.NET Framework 已排除所有 rote 照本宣科程式碼,您可以說.NET 相容語言屬於更具生產力和讀取比 Visual Basic 6.0 因為減少典禮的程式碼中。

.NET Framework 一個大的跳躍點但尚未完成語言演進,不是。 我們考慮簡單的屬性,在 C# 中實作傳統的方式:

public class ClassWithProperty {
  // Higher Ceremony
  private string _name;
  public string Name {
    get { return _name; }
    set { _name = value; }
  }
}

這個程式碼的本質是只要類別 ClassWithProperty 有名為名稱的字串屬性。 讓我們來向前快轉到 C# 3.0,並執行相同的 [自動] 屬性中:

public class ClassWithProperty {
  // Lower Ceremony
  public string Name { get; set; }
}

這個程式碼有為傳統樣式屬性,完全相同的目的,但它需要的少,造成顯著的 「 編譯器非搜尋程式碼]。

通常,但是,軟體開發人員不需要絕對控制程式設計語言。我一定會想我們應該利用新的程式設計語言創新功能或甚至其他的語言時, 的時候討論您可以使用現今主流的 C# 和 Visual Basic 的設計概念。

中心網域的驗證

.NET Framework 一來幾乎若要在使用者介面工具,例如 ASP.NET 驗證器控制項中加入宣告式的欄位層級驗證。所有相同我認為有利會將驗證邏輯,在實際網域模型類別上, 或由網域服務,這些原因至少關閉:

  1. 驗證邏輯是商務邏輯考量點,而且我想偏好的商務邏輯類別中包含所有的商務邏輯]。
  2. 放入與使用者介面可能會中斷連線的網域服務的網域模型的驗證邏輯會降低複製整個螢幕,並讓相同的驗證邏輯以會運用在非使用者介面 (說它一次只能一次,還會再) 應用程式所公開的服務 (Web 服務,例如) 中。
  3. 會比較最容易比測試實作為使用者介面的一部分的相同邏輯模型撰寫驗證邏輯單位和接受度測試。

說它一次,並僅一次

您會發現透過單一資料欄位的定義的相關內容需要變更的專案的中途時怎麼辦呢?在太過的許多的情況下的小的變更至資料庫將您不同部分的中介層資料存取程式碼,進行的類似的變更和甚至到使用者介面層級,為了要容納單一邏輯變更 ripple 透過您的應用程式。

在過去的公司在中,我們呼叫 rippling 從小型資料欄位的效果會變更,蟲孔中彈出 anti-pattern。想要取得離開的小的變更,在一個被 teleported 全透過圖層的位置。您會藉由減少不必要的分層,減緩蟲孔中彈出效果,與的第一個步驟。在更困難,但更 rewarding 步驟是找出方法一次,唯一的一次,請說它。

它之後,並只會在原則指出,有之後應該只在說是在系統中任何事實或原則在單一授權來源,整個。讓我們來建置 Web 應用程式,以建立的範例、 讀取、 更新,和刪除 (CRUD) 功能。這個是系統的主要關心編輯和儲存資料的欄位。這些欄位需要在畫面中編輯、 驗證伺服器上,儲存在資料庫,及希望驗證在用戶端為適用的更好的使用者經驗,但您想要的 「 這個欄位是必要的或此欄位必須為不超過 50 個字元 」,程式碼中只指定一次。

有不同的方式,您可能需要的幾個。您可以讓資料庫結構描述主要的定義,並從結構描述產生同時中介層和使用者簡報的程式碼。您也無法定義某種外部的中繼資料儲存區,例如為 XML 檔案,中的 [資料] 欄位,然後使用程式碼產生,建置資料庫結構描述、 任何的中介層物件和使用者介面畫面]。個人,我不是風扇的大規模的程式碼產生,因此我的小組選擇另一個的方向。

我們通常設計網域模型類別先,和我們考慮要由網域模型的實體類別的驗證邏輯。簡單的驗證規則,例如必要的欄位和最大字串長度規則,我們會裝飾與驗證屬性,例如,位址類別,如 [圖 2 ] 中所示的屬性。

[圖 2 使用驗證屬性

public class Address : DomainEntity {
  [Required, MaximumStringLength(250)]
  public string Address1 { get; set; }

  [Required, MaximumStringLength(250)]
  public string City { get; set; }

  [Required]
  public string StateOrProvince { get; set; }

  [Required, MaximumStringLength(100)]
  public string Country { get; set; }

  [Required, MaximumStringLength(50)]
  public string PostalCode { get; set; }

  public string TimeZone { get; set; }
}

使用屬性 (Attribute),以指定驗證規則是一項簡單且相當常見的技術。 您也都能說因為驗證規則表示以宣告方式而非使用命令式的程式碼實作,您已通過典禮本質與測試。

現在,但是,您需要在資料庫複寫所需的欄位和最大字串長度的規則。 萬一我的小組我們使用 NHibernate。 我們的保存性機制 NHibernate 的強大功能之一是從,就可以使用來建立資料庫結構描述,並保持與網域模型 (這項策略很明顯地最在新的專案中) 在同步的 NHibernate 對應產生資料定義語言 (DDL) 程式碼。 為了產生資料庫,從網域模型的這項策略要有用,它所需的我們將額外的資訊加入 NHibernate 對應標記不可為 Null 的欄位,並將指定字串的長度。

我們可以使用新的 Fluent NHibernate 機制定義我們物件的對應。 在我們安裝程式的程式碼的 Fluent NHibernate,我們建立自動慣例對應中所教導 Fluent NHibernate 如何處理在的 [必要] 」 和 「 我們的模型類別 MaximumStringLength] 屬性,以 [圖 3 ] 所示的程式碼。

[圖 3] 處理 NHibernate 中的屬性

public class MyPersistenceModel : PersistenceModel {
  public MyPersistenceModel() {
    // If a property is marked with the [Required]
    // attribute, make the corresponding column in
    // the database "NOT NULL"
    Conventions.ForAttribute<RequiredAttribute>((att, prop) => {
      if (prop.ParentIsRequired) {
        prop.SetAttribute("not-null", "true");
      }
    });

    // Uses the value from the [MaximumStringLength]
    // attribute on a property to set the length of 
    // a string column in the database
    Conventions.ForAttribute<MaximumStringLengthAttribute>((att, prop) => {
      prop.SetAttribute("length", att.Length.ToString());
    });
  }
}

這些慣例現在會套用至專案中所有的對應。 位址類別,我只要告訴 Fluent NHibernate,保存的屬性:

public class AddressMap : DomainMap<Address> {
  public AddressMap() {
    Map(a => a.Address1);
    Map(a => a.City);
    Map(a => a.TimeZone);
    Map(a => a.StateOrProvince);
    Map(a => a.Country);
    Map(a => a.PostalCode);
  }
}

現在,我已經之驗證屬性的相關,教導 Fluent NHibernate,我可以產生 DDL 位址資料表 (請參閱 [圖 4 )。 請注意,在 [圖 4 ] 中,SQL 中字串的長度符合從 [MaximumStringLength] 屬性,位址類別上定義。 同樣地,NULL / NOT NULL 值依照從 [必要] 屬性 (Attribute),該位址類別上。

[圖 4 在產生 DDL 程式碼

CREATE TABLE [dbo].[Address](
  [id] [bigint] IDENTITY(1,1) NOT NULL,
  [StateOrProvince] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
  [Country] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
  [PostalCode] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
  [TimeZone] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [Address1] [nvarchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
  [Address2] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  [City] [nvarchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
PRIMARY KEY CLUSTERED 
(
  [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

我們已投入衍生從網域模型的物件上的 [驗證] 屬性的資料庫結構的某些基礎結構中,但我們仍會有在幾用戶端驗證 」 和 「 用戶端的外觀。 我們希望執行簡單的輸入的驗證,在瀏覽器,並在標記必要的欄位) 項目,以更好的使用者經驗的某種方式。

我的小組已經到達的解決方案是讓知道驗證屬性 (Attribute) 的輸入項目的 HTML 呈現。 (內容,我們使用在 ASP.NET 模型檢視控制器,或 MVC,Framework Beta1 與 Web Form 引擎為我們檢視引擎)。 [圖 5 顯示標記可能外觀的位址] 檢視的我們的系統中。

[圖 5 位址檢視標記

<div class="formlayout_body">
  <p><%= this.TextBoxFor(m => m.Address1).Width(300)%></p>
  <p><%= this.TextBoxFor(m => m.Address2).Width(300) %></p>
  <p>
    <%= this.TextBoxFor(m => m.City).Width(140) %>
    <%= this.DropDownListFor(m => 
        m.StateOrProvince).FillWith(m => m.StateOrProvinceList) %>
  </p>
  <p><%= this.TextBoxFor(m => m.PostalCode).Width(80) %></p>        
  <p><%= this.DropDownListFor(m => 
         m.Country).FillWith(m => m.CountryList) %></p>
  <p><%= this.DropDownListFor(m => 
         m.TimeZone).FillWith(m => m.DovetailTimeZoneList) %></p>
</div>

TextBoxFor] 和 [DropDownListFor 則是用於在我們 MVC) 架構的所有檢視一般的基底檢視中,小 HTML 協助程式。 TextBoxFor 的簽名碼如下所示:

public static TextBoxExpression<TModel> TextBoxFor< TModel >(
  this IViewWithModel< TModel > viewPage, 
  Expression<Func< TModel, object>> expression)

  where TModel : class {
    return new TextBoxExpression< TModel >(
    viewPage.Model, expression);
  }

請注意,在這段程式碼中重要的是輸入的引數是的運算式 (運算式 < Func < TModel,物件 >> 為精準)。 建構 HTML 文字方塊的實際,時 TextBoxExpression 類別將會:

  1. 剖析運算式,並找出實際 PropertyInfo 物件,繫結屬性]。
  2. 詢問驗證屬性 (Attribute) 的存在,PropertyInfo。
  3. 依此呈現文字方塊的 HTML。

我們只會加入名為需要繫結至屬性的所有 HTML 項目類別會以 [必要] 屬性標記。 同樣地,如果我們可以繫結的屬性上,找到 [MaximumStringAttribute],我們將 maxlength 屬性符合屬性來限制使用者輸入,以允許長度 HTML 文字方塊的設定。 產生的 HTML 看起來像這樣:

<p><label>Address:</label>
<input type="text" name="Address1" value="" 
       maxlength="250" style="width: 300px;" 
       class="required textinput" /></p>

只要編輯 CSS 類別所需的外觀很容易控制項的必要欄位的外觀 (我們在淺藍色畫面上設定必要的欄位的色彩)。 我們使用的方便足夠,只尋找所需的類別,在輸入的項目上的存在,jQuery 驗證外掛程式,在實際用戶端驗證。 文字項目的最大長度會強制執行直接輸入的項目上設定 maxlength 屬性。

以任何方式是這完整實作。 建立一段時間,實際實作不是那麼困難。 硬碟的一部分,想透過消除重複的中繼資料及多個的層級中的程式碼的方法。 我相信許多小組也無法蓄勢待發上的我的小組產生資料庫物件模型,不過沒關係因為我真正的目標是只為您提供關於如何您可能使用,例如它一次和一次主體以簡化您自己的開發工作的一些想法。

合理的預設值

在前一節中,我會顯示一個非常小範例 (透過的 AddressMap] 類別中) 表示物件關聯的 Fluent NHibernate 對應 (ORM)。 以下是稍微複雜一點的範例,表示位址的物件參考從站台類別:

public SiteMap() {
  // Map the simple properties
  // The Site object has an Address property called PrimaryAddress
  // The code below sets up the mapping for the reference between
  // Site and the Address class
  References(s => s.PrimaryAddress).Cascade.All();
  References(s => s.BillToAddress).Cascade.All();
  References(s => s.ShipToAddress).Cascade.All();
}

當您設定 ORM 工具時,您通常需要:

  1. 指定的實體類別對應至資料表名稱。
  2. 指定主索引鍵欄位的實體的而且通常也會指定某種策略的指派主索引鍵的值。 (是它自動編號] / [資料庫序列嗎? 或者,不會在系統指派的主索引鍵的值嗎? 或執行您使用 GUID 主索引鍵嗎?)
  3. 將物件屬性或欄位,對應至資料表資料行中。
  4. 至其中一個 「 關係從某個物件 (例如,從站台位址,對應) 的另一個時,您需要指定外部索引鍵 ORM 工具可以使用加入父代和子資料錄的資料行。

是一般冗長的工作。 是,您必須遵循取得 ORM,保存物件的典禮。 幸運的是,您可以排除一些在 tedium 透過內嵌某些合理的預設值,在我們的程式碼 (請注意的大寫字母)。

您可能注意到,我沒有未指定資料表名稱、 主要金鑰策略或任何的外部索引鍵欄位名稱的對應範例。 在我的小組 Fluent NHibernate 對應超級類別,我們可以設定一些預設值對我們的對應:

public abstract class DomainMap<T> : ClassMap<T>, 
  IDomainMap where T : DomainEntity {

  protected DomainMap() {
    // For every DomainEntity class, use the Id property
    // as the Primary Key / Object Identifier
    // and use an Identity column in SQL Server,
    // or an Oracle Sequence
    UseIdentityForKey(x => x.Id, "id");
    WithTable(typeof(T).Name);
  }
}

opinionated 軟體

 

您可能會注意到我說明採用的慣例為 「 限制 」。 背後透過組態的慣例,原理的一部分是讓 「 opinionated 軟體 」 所建立的設計上有人工的條件約束。

opinionated 架構會需要開發人員可以執行動作,以特定方式幾乎到點排除的彈性。proponents opinionated 軟體的感覺這些條件約束讓開發更有效率移除開發人員的決策,並提升一致性的。

一個由我的小組的意見是網域模型的所有類別完全一個單一的長屬性,呼叫識別碼所都識別的:

public virtual long Id { get; set; }

一個簡單的規則但它在設計上有深遠的影響數。因為在相同的方式中識別所有的實體類別,您還能使用單一的儲存機制類別,而非書寫的每個最上層實體的儲存機制類別的特製化。在相同的 vein 在 Web 應用程式中處理的 URL 是一致在實體類別而不需要登錄特殊的路由規則,每個實體。

下列這個意見會降低將加入新的項目型別的基礎結構成本。這種方法的缺點是它會很難配合自然的金鑰或甚至複合金鑰,或使用物件識別項的 GUID。那不是我的小組的問題,但它無法輕鬆地封鎖從採用我們的意見的另一個小組。

現在,如何您強制實施這些意見?第一個步驟直接建立,一般瞭解和這些意見在小組內的合約。通知開發人員可代表有效地使用其利用這些 opinionated 的設計選擇最佳的機會。同樣地,慣例,透過組態可以是近端的嚴重損壞,如果開發人員不熟悉現有的慣例或令人混淆,慣例。

您可能也考慮使用靜態程式碼分析工具做為您連續的整合組建的一部分,來自動強制執行專案的慣例的動作。

在此程式碼中我們正在設定原則的所有類別的子類別 (Subclass) domain­entity 會被識別碼屬性,指派識別策略所識別。資料表名稱,被假設為類別的名稱相同。現在,我們永遠都可以覆寫這些選項,針對每個-類別,但我們很少所必須執行這項操作 (名為使用者的類別必須對應至名為使用者,為了避免與 SQL Server 中的保留字發生衝突的資料表)。相同的方式 Fluent NHibernate 會假設外部索引鍵名稱根據參考另一個類別的屬性名稱。

授與,這不是儲存程式碼,每個對應類別的多行,但是讓部分對應執行更容易讀取藉由減少整體的雜音程式碼,對應中不同。

透過組態的慣例

軟體開發人員已取得更多的生產力,並藉由移動命令式的程式碼和宣告式 XML 組態至行為,讓系統更多動態進行搜尋。許多開發人員會覺得 XML 組態的激增太遠了,已成為是有害的作法。透過明確設定的預設值的策略是也稱為慣例透過組態。

透過組態的慣例是設計原理和技術,欲套用可以從程式碼,而不需要明確的程式碼的結構隱含的預設值)。其概念是為了讓開發人員擔心 unconventional 部分應用程式和架構只能簡化開發。

現在向右,許多人就播放與 ASP.NET Framework MVC 並實驗不同的方式使用它。MVC 的 Web 程式開發模型中有幾個的可能是一個好的機會,透過組態套用慣例的重複程式碼的來源。

MVC 模型中的單一要求的基本流程中,以下是五個步驟:

  1. 接收用戶端的 URL。在路由的子系統會剖析 URL 中,並判斷處理這個 URL 的控制器的名稱。
  2. 從控制器名稱,由路由子系統,建置,或找出適當的控制站物件。
  3. 叫用正確的控制器的方法。
  4. 選取適當的檢視,並封送處理模型資料從控制器的方法產生這個檢視中。
  5. 呈現檢視。

移出方塊,沒有一些重複的儀式在建置 ASP.NET MVC 架構,您可以採用一些嚴格的慣例來降低 Web 網頁。

在第一個工作是連線至 Web 網站與適當的控制器類別的傳入的 URL。在.MVC Framework 路由程式庫可以詢問 URL,並判斷控制器的名稱。MVC) 架構將會詢問註冊的 IControllerFactory 物件控制站物件符合控制器符合控制站名稱由傳入的 URL。

許多小組直接委派至的控制項 (IOC) 工具的反向的控制器建構。萬一我的小組中,我們會使用開放原始碼 StructureMap 工具解析名稱的控制器執行個體:

public class StructureMapControllerFactory 
  : IControllerFactory {

  public IController CreateController(
    RequestContext requestContext, string controllerName) {

    // Requests the named Controller from the 
    // StructureMap container
    return ObjectFactory.GetNamedInstance<IController>(
      controllerName.ToLowerInvariant());
  }
}

您需要註冊的所有控制器類別名稱與 IOC 容器要求控制器相當簡單,但第一個。 稍候 ! 不,加入一些典禮架構? 年份或兩個前的我會有使進行控制器類別的明確 IOC 設定如下:

public static class ExplicitRegistration {
  public static void BootstrapContainer() {
    ObjectFactory.Initialize(x => {
      x.ForRequestedType<IController>().AddInstances(y => {
        y.OfConcreteType<AddressController>().WithName("address");
        y.OfConcreteType<ContactController>().WithName("contact");

        // and so on for every possible type of Controller
      });
    });
  }
}

這個程式碼會表示純 tedium] 和 [原因沒有其他比若要餵送 IOC 工具存在的典禮。 如果您查看登錄程式碼在接近,您會注意到它是下列一致的模式。 AddressController 登錄為位址,並 contact­controller 登錄為連絡人]。 而非明確地設定每個控制器,您可以只建立自動決定路由每個控制器類別的名稱慣例。

幸好,還有直接支援在 StructureMap 慣例-基礎登錄,讓您可以建立新的 ControllerConvention 的自動註冊任何實體的型別,IController 的:

public class ControllerConvention : TypeRules, ITypeScanner {
  public void Process(Type type, PluginGraph graph) {
    if (CanBeCast(typeof (IController), type)) {
      string name = type.Name.Replace("Controller", "").ToLower();
      graph.AddType(typeof(IController), type, name);
    }
  }
}

接下來,您還會需要一些 bootstraps StructureMap 容器使用,新的慣例,如 [圖 6 ] 所示的程式碼。 就位並在啟動載入 IOC 容器的一部分新的 ControllerConvention 一旦 IOC 登錄,而不需要任何明確的設定,部分的開發人員會自動加入任何新的控制器類別,以將加入至應用程式。 因此沒有錯誤和錯誤因為開發人員忘了加入新的組態項目的新畫面。

圖 6 新慣例 StructureMap

/// <summary>
/// This code would be in the same assembly as 
/// the controller classes and would be executed
/// in the Application_Start() method of your
/// Web application
/// </summary>
public static class SampleBootstrapper {
  public static void BootstrapContainer() {
    ObjectFactory.Initialize(x => {
      // Directs StructureMap to perform auto registration
      // on all the Types in this assembly
      // with the ControllerConvention
      x.Scan(scanner => {
        scanner.TheCallingAssembly();
        scanner.With<ControllerConvention>();
        scanner.WithDefaultConventions();
      });
    });
  }
}

為快速筆記,我要說明的自動註冊此策略的可能在所有 IOC 容器,只要 IOC 容器公開,以程式設計方式註冊 API 我知道的而.NET Framework 的。

接下來的步驟

在的最後的所有有關減少您的目的和程式碼,讓發生這種情況,目的之間的距離和 Friction。許多,我在本專欄中所顯示的技術其實有關可讓程式碼 「 只圖它出 「 使用命名慣例,而不是明確的程式碼,或尋找要避免在系統中複製資訊的方法。我還會重複使用資訊屬性,以減少機械的工作中被埋使用反射的一些技巧。

所有的這些設計的概念可以減少重複的儀式,開發工作中的但在價格方面。detractors 慣例,透過組態的抱怨有關 「 繼承 」 魔法 」 方法的中。內嵌到您的程式碼或 Framework 的意見將會從在這些意見,不為適合新的案例中可能重複使用。

發生大量的我無法涵蓋此時,我可能涵蓋更新資料行中的其他主題。我一定會想要探索如何語言導向程式設計 ; 替代語言 (例如 F #,[IronRuby,] 和 [IronPython 和 [內部網域特定語言的使用方式會影響的軟體設計程序中。

您問題或意見寄至mmpatt@Microsoft.com.

Jeremy Miller C# 的 Microsoft MVP 也是開放原始碼的作者StructureMap工具與.NET,即將的相依性資料隱碼storyTeller 工具為 supercharged FIT 測試.NET]。造訪他的部落格網底的樹狀結構的開發人員CodeBetter 網站的一部分。