C#knowledge

King丶Knight發表於2010-05-29

1 轉到定義: F12;
2 設定書籤:Ctr+K+K;
3 設定任務: //TODO:something,檢視任務Ctrl+W+T;
4 查詢:Ctrl+ F, Ctrl+Shift+F;
5 強迫智慧感知:Ctrl+J;
6 強迫智慧感知顯示引數資訊:Ctrl-Shift-空格;
7 格式化整個塊:Ctrl+K+F;
8 全螢幕:Alt+Shift+Enter;
9 設定書籤:Ctrl+B+T,跳轉書籤:Ctrl+B+N
10 檢查括號匹配(在左右括號間切換): Ctrl +]
11 選中從游標起到行首(尾)間的程式碼: Shift + Home(End)
12 在方法定義和呼叫之點切換:Ctrl+Shift+7(8)
13 設定斷點:F9
14 查詢所有引用: Shift + F12
15 註釋程式碼,助記方法,Edit + Comments:Ctrl + E,C
16 取消註釋, 助記方法:Edit + UnComments:Ctrl + E,U
17 格式程式碼, 助記方法:Edit + Document(只能在程式碼能編繹的情況下起使用):Ctrl + E,D
18 收攏程式碼:Ctrl+M, O
19 選中自己圈中的長方塊:Alt+Shift+滑鼠
20 除錯模式下,“除錯——視窗——反彙編”,或者ctrl + alt + d
21 按下Ctrl+Enter會在上面插入一個空行,Ctrl+Shift+Enter則會在下面插入一個空行。游標會移至新行的開始處。
22 使用Tab增加縮排,Shift+Tab減少縮排(相應的選單命令在Edit - Advanced 中)
23 格式化整篇程式碼: Ctrl+K, D
24 用Ctrl+W選中當前字
25 單個節點摺疊與開啟開關: Ctrl+M, M
26 使用Ctrl+G跳至指定行
27 使用Ctrl+Delete和Ctrl+Backspace分別刪除後繼和前驅的詞
28 使用Ctrl+L剪下當前行,Ctrl+Shift+L刪除當前行
29 如何建立書籤並在其中進行跳轉?(推薦)按下Ctrl+K, Ctrl+K 可以建立/取消一個書籤,該命令繫結至Edit.ToggleBookmark,如果你的快捷鍵與此不同,可通過命令來檢視具體的快捷鍵。
30 使用Ctrl+J來幫助語句完成。

C#.NET中關於結構與類之間的區別
 類與結構的例項比較
 類與結構的差別
 如何選擇結構還是類

  一.類與結構的示例比較:

  結構示例:

  publicstructPerson
  {
   stringName;
   intheight;
   intweight;

  publicbooloverWeight()
   {
    //implementsomething
   }
  }

  類示例:
  publicclassTestTime
  {
   inthours;
   intminutes;
   intseconds;

   publicvoidpasstime()
   {
    //implementationofbehavior
   }
  }

  呼叫過程:

  publicclassTest
  {
   publicstaticovidMain
   {
    PersonMyperson=newPerson//宣告結構
    TestTimeMytime=NewTestTime//宣告類
   }
  }

  從上面的例子中我們可以看到,類的宣告和結構的宣告非常類似,只是限定符後面是struct還是class的區別,而且使用時,定義新的結構和定義新的類的方法也非常類似。那麼類和結構的具體區別是什麼呢?

二.類與結構的差別

  1.值型別與引用型別

  結構是值型別:值型別在堆疊上分配地址,所有的基型別都是結構型別,例如:int對應System.int32結構,string對應system.string結構,通過使用結構可以建立更多的值型別

  類是引用型別:引用型別在堆上分配地址

  堆疊的執行效率要比堆的執行效率高,可是堆疊的資源有限,不適合處理大的邏輯複雜的物件。所以結構處理作為基型別對待的小物件,而類處理某個商業邏輯

  因為結構是值型別所以結構之間的賦值可以建立新的結構,而類是引用型別,類之間的賦值只是複製引用

  注:

  1.雖然結構與類的型別不一樣,可是他們的基型別都是物件(object),c#中所有型別的基型別都是object

  2.雖然結構的初始化也使用了New操作符可是結構物件依然分配在堆疊上而不是堆上,如果不使用“新建”(new),那麼在初始化所有欄位之前,欄位將保持未賦值狀態,且物件不可用

2.繼承性

  結構:不能從另外一個結構或者類繼承,本身也不能被繼承,雖然結構沒有明確的用sealed宣告,可是結構是隱式的sealed.

  類:完全可擴充套件的,除非顯示的宣告sealed否則類可以繼承其他類和介面,自身也能被繼承

  注:雖然結構不能被繼承可是結構能夠繼承介面,方法和類繼承介面一樣

  例如:結構實現介面

  interfaceIImage
  {
   voidPaint();
  }

  structPicture:IImage
  {
   publicvoidPaint()
   {
      //paintingcodegoeshere
   }
   privateintx,y,z; //otherstructmembers
  }  

  3.內部結構:

  結構:

  沒有預設的建構函式,但是可以新增建構函式

  沒有解構函式

  沒有abstract和sealed(因為不能繼承)

  不能有protected修飾符

  可以不使用new初始化

  在結構中初始化例項欄位是錯誤的

  類:

   有預設的建構函式
 有解構函式
 可以使用abstract和sealed
 有protected修飾符
 必須使用new初始化

  三.如何選擇結構還是類

  討論了結構與類的相同之處和差別之後,下面討論如何選擇使用結構還是類:

  1.堆疊的空間有限,對於大量的邏輯的物件,建立類要比建立結構好一些

  2.結構表示如點、矩形和顏色這樣的輕量物件,例如,如果宣告一個含有1000個點物件的陣列,則將為引用每個物件分配附加的記憶體。在此情況下,結構的成本較低。

  3.在表現抽象和多級別的物件層次時,類是最好的選擇

 

  4.大多數情況下該型別只是一些資料時,結構時最佳的選擇


物件導向設計思想(C#)
有了翅膀才能飛,欠缺靈活的程式碼就象凍壞了翅膀的鳥兒。不能飛翔,就少了幾許靈動的氣韻。我們需要給程式碼帶去溫暖的陽光, 讓僵冷的翅膀重新飛起來。結合例項,通過應用OOP、設計模式和重構,你會看到程式碼是怎樣一步一步復活的。 為了更好的理解設計思想,例項儘可能簡單化。但隨著需求的增加,程式將越來越複雜。此時就有修改設計的必要, 重構和設計模式就可以派上用場了。最後當設計漸趨完美后,你會發現,即使需求不斷增加,你也可以神清氣閒,不用為程式碼設計而煩惱了。

      假定我們要設計一個媒體播放器。該媒體播放器目前只支援音訊檔案mp3和wav。如果不談設計,設計出來的播放器可能很簡單:

public class MediaPlayer
{  
   private void PlayMp3()
   {
      MessageBox.Show("Play the mp3 file.");
   }

   private void PlayWav()
   {
      MessageBox.Show("Play the wav file.");
   }

   public void Play(string audioType)
   {     
      switch (audioType.ToLower())
      {
          case ("mp3"):
             PlayMp3();
             break;
          case ("wav"):
             PlayWav();
             break;            
      }     
   }
}

       自然,你會發現這個設計非常的糟糕。因為它根本沒有為未來的需求變更提供最起碼的擴充套件。如果你的設計結果是這樣,那麼當你為應接不暇的需求變更而焦頭爛額的時候,你可能更希望讓這份設計到它應該去的地方,就是桌面的回收站。仔細分析這段程式碼,它其實是一種最古老的面向結構的設計。如果你要播放的不僅僅是mp3和wav,你會不斷地增加相應地播放方法, 然後讓switch子句越來越長,直至達到你視線看不到的地步。

       好吧,我們先來體驗物件的精神。根據OOP的思想,我們應該把mp3和wav看作是一個獨立的物件。那麼是這樣嗎?

public class MP3
{
   public void Play()
   {
       MessageBox.Show("Play the mp3 file.");
   }
}

       好樣的,你已經知道怎麼建立物件了。更可喜的是,你在不知不覺中應用了重構的方法,把原來那個垃圾設計中的方法名字改為了 統一的Play()方法。你在後面的設計中,會發現這樣改名是多麼的關鍵!但似乎你並沒有擊中要害, 以現在的方式去更改MediaPlayer的程式碼,實質並沒有多大的變化。
        既然mp3和wav都屬於音訊檔案,他們都具有音訊檔案的共性,為什麼不為它們建立一個共同的父類呢?

public class AudioMedia
{
   public void Play()
   {
       MessageBox.Show("Play the AudioMedia file.");
   }
}

        現在我們引入了繼承的思想,OOP也算是象模象樣了。得意之餘,還是認真分析現實世界吧。其實在現實生活中,我們播放的只會是某種具體型別的音訊檔案,因此這個AudioMedia類並沒有實際使用的情況。對應在設計中,就是:這個類永遠不會被例項化。所以,還得動一下手術,將其改為抽象類。好了,現在的程式碼有點OOP的感覺了:

 

        看看現在的設計,即滿足了類之間的層次關係,同時又保證了類的最小化原則,更利於擴充套件(到這裡,你會發現play方法名改得多有必要)。 即使你現在又增加了對WMA檔案的播放,只需要設計WMA類,並繼承AudioMedia,重寫Play方法就可以了,
MediaPlayer類物件的Play方法根本不用改變。

       是不是到此就該畫上圓滿的句號呢?然後刁鑽的客戶是永遠不會滿足的,他們在抱怨這個媒體播放器了。因為他們不想在看足球比賽的時候,只聽到主持人的解說,他們更渴望看到足球明星在球場奔跑的英姿。也就是說,他們希望你的媒體播放器能夠支援視訊檔案。你又該痛苦了,因為在更改硬體設計的同時,原來的軟體設計結構似乎出了問題。因為視訊檔案和音訊檔案有很多不同的地方,你可不能偷懶,讓視訊檔案物件認音訊檔案作父親啊。你需要為視訊檔案設計另外的類物件了,假設我們支援RM和MPEG格式的視訊:

public abstract class VideoMedia
{
   public abstract void Play();
}

public class RM:VideoMedia
{
   public override void Play()
   {
       MessageBox.Show("Play the rm file.");
   }
}

public class MPEG:VideoMedia
{
   public override void Play()
   {
       MessageBox.Show("Play the mpeg file.");
   }
}

        糟糕的是,你不能一勞永逸地享受原有的MediaPlayer類了。因為你要播放的RM檔案並不是AudioMedia的子類。

        不過不用著急,因為介面這個利器你還沒有用上(雖然你也可以用抽象類,但在C#裡只支援類的單繼承)。雖然視訊和音訊格式不同,別忘了,他們都是媒體中的一種,很多時候,他們有許多相似的功能,比如播放。根據介面的定義,你完全可以將相同功能的一系列物件實現同一個介面:

public interface IMedia
{
   void Play();
}

public abstract class AudioMedia:IMedia
{
   public abstract void Play();
}

public abstract class VideoMedia:IMedia
{
   public abstract void Play();
}

       再更改一下MediaPlayer的設計就OK了:

public class MediaPlayer

   public void Play(IMedia media)
   {     
       media.Play();
   }
}

        現在可以總結一下,從MediaPlayer類的演變,我們可以得出這樣一個結論:在呼叫類物件的屬性和方法時,儘量避免將具體類物件作為傳遞引數,而應傳遞其抽象物件,更好地是傳遞介面,將實際的呼叫和具體物件完全剝離開,這樣可以提高程式碼的靈活性。

        不過,事情並沒有完。雖然一切看起來都很完美了,但我們忽略了這個事實,就是忘記了MediaPlayer的呼叫者。還記得文章最開始的switch語句嗎?看起來我們已經非常漂亮地除掉了這個煩惱。事實上,我在這裡玩了一個詭計,將switch語句延後了。雖然在MediaPlayer中,程式碼顯得乾淨利落,其實煩惱只不過是轉嫁到了MediaPlayer的呼叫者那裡。
例如,在主程式介面中:
 
Public void BtnPlay_Click(object sender,EventArgs e)
{
    switch (cbbMediaType.SelectItem.ToString().ToLower())
    {
        IMedia media;
        case ("mp3"):
             media = new MP3();
             break;
        case ("wav"):
             media = new WAV();
             break;  
        //其它型別略;
    }
    MediaPlayer player = new MediaPlayer();
    player.Play(media);
}
       使用者通過選擇cbbMediaType組合框的選項,決定播放哪一種檔案,然後單擊Play按鈕執行。

       現在該設計模式粉墨登場了,這種根據不同情況建立不同型別的方式,工廠模式是最拿手的。先看看我們的工廠需要生產哪些產品呢?雖然這裡有兩種不同型別的媒體AudioMedia和VideoMedia(以後可能更多),但它們同時又都實現IMedia介面,
所以我們可以將其視為一種產品,用工廠方法模式就可以了。首先是工廠介面:

public interface IMediaFactory
{
   IMedia CreateMedia();
}

       然後為每種媒體檔案物件搭建一個工廠,並統一實現工廠介面:

public class MP3MediaFactory:IMediaFactory
{
   public IMedia CreateMedia()
   {
       return new MP3();
   }
}
public class RMMediaFactory:IMediaFactory
{
   public IMedia CreateMedia()
   {
       return new RM();
   }
}
//其它工廠略;

寫到這裡,也許有人會問,為什麼不直接給AudioMedia和VideoMedia類搭建工廠呢?很簡單,因為在AudioMedia和VideoMedia中,分別還有不同的型別派生,如果為它們搭建工廠,則在CreateMedia()方法中,仍然要使用Switch語句。而且既然這兩個類都實現了IMedia介面,可以認為是一種型別,為什麼還要那麼麻煩去請動抽象工廠模式,來生成兩類產品呢? 可能還會有人問,即使你使用這種方式,那麼在判斷具體建立哪個工廠的時候,不是也要用到switch語句嗎?我承認這種看法是對的。不過使用工廠模式,其直接好處並非是要解決switch語句的難題,而是要延遲物件的生成,以保證的程式碼的靈活性。當然,我還有最後一招殺手鐗沒有使出來,到後面你會發現,switch語句其實會完全消失。

還有一個問題,就是真的有必要實現AudioMedia和VideoMedia兩個抽象類嗎?讓其子類直接實現介面不更簡單?對於本文提到的需求, 我想你是對的,但不排除AudioMedia和VideoMedia它們還會存在區別。例如音訊檔案只需要提供給音效卡的介面,而視訊檔案還需要提供給顯示卡的介面。如果讓MP3、WAV、RM、MPEG直接實現IMedia介面,而不通過AudioMedia和VideoMedia,在滿足其它需求的設計上也是不合理的。當然這已經不包括在本文的範疇了。

現在主程式介面發生了稍許的改變:
Public void BtnPlay_Click(object sender,EventArgs e)
{
IMediaFactory factory = null;
    switch (cbbMediaType.SelectItem.ToString().ToLower())
    {
        case ("mp3"):
             factory = new MP3MediaFactory();
             break;
        case ("wav"):
             factory = new WAVMediaFactory();
             break;  
        //其他型別略;
    }
    MediaPlayer player = new MediaPlayer();
    player.Play(factory.CreateMedia());
}

寫到這裡,我們再回過頭來看MediaPlayer類。這個類中,實現了Play方法,並根據傳遞的引數,呼叫相應媒體檔案的Play方法。在沒有工廠物件的時候,看起來這個類物件執行得很好。如果是作為一個類庫或元件設計者來看,他提供了這樣一個介面,供主介面程式設計師呼叫。然而在引入工廠模式後,在裡面使用MediaPlayer類已經多餘了。所以,我們要記住的是,重構並不僅僅是往原來的程式碼新增新的內容。當我們發現一些不必要的設計時,還需要果斷地刪掉這些冗餘程式碼。
Public void BtnPlay_Click(object sender,EventArgs e)
{
IMediaFactory factory = null;
    switch (cbbMediaType.SelectItem.ToString().ToLower())
    {       
        case ("mp3"):
             factory = new MP3MediaFactory();
             break;
        case ("wav"):
             factory = new WAVMediaFactory();
             break;  
        //其他型別略;
    }
    IMedia media = factory.CreateMedia();
    media.Play();
}

如果你在最開始沒有體會到IMedia介面的好處,在這裡你應該已經明白了。我們在工廠中用到了該介面;而在主程式中,仍然要使用該介面。使用介面有什麼好處?那就是你的主程式可以在沒有具體業務類的時候,同樣可以編譯通過。因此,即使你增加了新的業務,你的主程式是不用改動的。

不過,現在看起來,這個不用改動主程式的理想,依然沒有完成。看到了嗎?在BtnPlay_Click()中,依然用new建立了一些具體類的例項。如果沒有完全和具體類分開,一旦更改了具體類的業務,例如增加了新的工廠類,仍然需要改變主程式,何況討厭的switch語句仍然存在,它好像是翅膀上滋生的毒瘤,提示我們,雖然翅膀已經從僵冷的世界裡復活,但這雙翅膀還是有病的,並不能正常地飛翔。

是使用配置檔案的時候了。我們可以把每種媒體檔案類型別的相應資訊放在配置檔案中,然後根據配置檔案來選擇建立具體的物件。
並且,這種建立物件的方法將使用反射來完成。首先,建立配置檔案:

<appSettings>
  <add key="mp3" value="WingProject.MP3Factory" />
  <add key="wav" value="WingProject.WAVFactory" />
  <add key="rm" value="WingProject.RMFactory" />
  <add key="mpeg" value="WingProject.MPEGFactory" />
</appSettings>

然後,在主程式介面的Form_Load事件中,讀取配置檔案的所有key值,填充cbbMediaType組合框控制元件:
public void Form_Load(object sender, EventArgs e)
{
cbbMediaType.Items.Clear();
foreach (string key in ConfigurationSettings.AppSettings.AllKeys)
{
   cbbMediaType.Item.Add(key);
}
cbbMediaType.SelectedIndex = 0;
}

最後,更改主程式的Play按鈕單擊事件:
Public void BtnPlay_Click(object sender,EventArgs e)
{
string mediaType = cbbMediaType.SelectItem.ToString().ToLower();
string factoryDllName = ConfigurationSettings.AppSettings[mediaType].ToString();
//MediaLibray為引用的媒體檔案及工廠的程式集;
IMediaFactory factory = (IMediaFactory)Activator.CreateInstance("MediaLibrary",factoryDllName).Unwrap();
IMedia media = factory.CreateMedia();
media.Play();
}

現在鳥兒的翅膀不僅僅復活,有了可以飛的能力;同時我們還賦予這雙翅膀更強的功能,它可以飛得更高,飛得更遠!

享受自由飛翔的愜意吧。設想一下,如果我們要增加某種媒體檔案的播放功能,如AVI檔案。那麼,我們只需要在原來的業務程式集中建立AVI類,並實現IMedia介面,同時繼承VideoMedia類。另外在工廠業務中建立AVIMediaFactory類,並實現IMediaFactory介面。假設這個新的工廠型別為WingProject.AVIFactory,則在配置檔案中新增如下一行:
<add key="AVI" value="WingProject.AVIFactory" />。
而主程式呢?根本不需要做任何改變,甚至不用重新編譯,這雙翅膀照樣可以自如地飛行!


 

public abstract class AudioMedia
{
   public abstract void Play();
}

public class MP3:AudioMedia
{
   public override void Play()
   {
       MessageBox.Show("Play the mp3 file.");
   }
}

public class WAV:AudioMedia
{
   public override void Play()
   {
       MessageBox.Show("Play the wav file.");
   }
}

public class MediaPlayer

   public void Play(AudioMedia media)
   {     
       media.Play();
   }
}

 

public class WAV
{
   public void Play()
   {
       MessageBox.Show("Play the wav file.");
   }
}
物件導向的關聯式資料庫設計
一、概念的區分
  有些人把物件導向的資料庫設計(即資料庫模式)思想與物件導向資料庫管理系統(OODBMS)理論混為一談。其實前者是資料庫使用者定義資料庫模式的思路,後者是資料庫管理程式的思路。使用者使用物件導向方法學可以定義任何一種DBMS資料庫,即網路型、層次型、關係型、物件導向型均可,甚至檔案系統設計也照樣可以遵循物件導向的思路。 物件導向的思路或稱規範可以用於系統分析、系統設計、程式設計,也可以用於資料 結構設計、資料庫設計。OOSE自上至下、自始至終地貫徹物件導向思路,是一個一氣呵成 的統一體。物件導向的資料庫設計只是 OOSE 的一個環節。

  二、資料庫設計的重要性

  一般資料庫設計方法有兩種,即屬性主導型和實體主導型。屬性主導型從歸納資料庫應用的屬性出發,在歸併屬性集合(實體)時維持屬性間的函式依賴關係。實體主導型則先 從尋找對資料庫應用有意義的實體入手,然後通過定義屬性來定義實體。一般現實世界的 實體數在屬性數 1/10 以下時,宜使用實體主導型設計方法。物件導向的資料庫設計是從物件模型出發的,屬於實體主導型設計。 一般資料庫應用系統都遵循以下相關開發步驟:

1設計應用系統結構;

2 選擇便於將應
   用程式與DBMS結合的DBMS體系結構,如RDBMS;

3 根據應用程式使用的環境平臺,選擇適宜的DBMS(如Oracle)和開發工具(如PB);

4 設計資料庫,編寫定義資料庫模式的SQL程式;

5 編寫確保資料正確錄入資料庫的使用者介面應用程式;

6 錄入資料庫資料;

7 執行各種與 資料庫相關的應用程式,以確認和修正資料庫的內容。

  對以上各步驟,有幾點需要說明:

(1) 這不是瀑布模型,每一步都可以有反饋。
  在公路局系統中,以上各步不僅有反饋、有反覆,還有並行處理。比如一些庫表在數 據錄入時,另一些庫表設計還在修改。這與我們的遞增式開發方法有關,也與物件導向的 特徵有關。

(2) 上述順序不是絕對的,大多數場合是從第三步開始的。

(3) 對大多數資料庫應用系統來說,上述各步中最重要、最困難的不是應用系統設計而是資料庫設計。

  三、DBMS的支援和資料庫設計

  多資料庫應用系統開發者不重視資料庫設計的原因是:他們太迷信DBMS,認為購入一個功能強大的DBMS後資料庫設計就不困難、不重要了。一些國內外的資料庫教材常常 是在為DBMS的開發廠商做宣傳,而很少站在資料庫使用者角度,從資料庫應用系統出發介紹資料庫設計方法。結果往往使讀者搞不清書中介紹的是資料庫管理程式的設計思想,還是 應用這種 DBMS 進行資料庫設計的思想。 其實,DBMS只是給使用者為已採用的資料庫提供一個舞臺,而是否使用這個舞臺上的道具以及唱什麼戲,則完全取決於使用者的戲劇指令碼和導演(開發者)的安排。例如,公路局系統所使用的資料庫管理系統,是以二維表為基本管理單元、支援所有關係代數操作、支援 實體完整性與實體間參照完整性的全關係型RDBMS,而我們要在這個舞臺上利用上述"道具"設計一個物件導向的關聯式資料庫。

  四、應用物件模型與RDBMS模型的對映

  資料庫設計(模式)是否支援應用系統的物件模型,這是判斷是否是物件導向資料庫系統的基本出發點。由於應用系統設計在前,資料庫設計隨後,所以應用系統物件模型向 資料庫模式的對映是物件導向資料庫設計的關鍵。

  1. 三層資料庫模式物件導向模型的擴充套件

  一般資料庫設計多參照ANSL/SPARC關於資料庫模式的3層標準結構提案。最接近物理資料庫的內部模式由DBMS提供的SQL來描述。概念模式可以由若干個內部模式聚集而成 ,它是由資料庫使用者規範的一些表的集合。例如,公路局計劃處資料庫模式、機務處資料 庫模式等,它們是邏輯資料庫,常常通過庫表ID來界定庫邊界。一般的概念模式是資料庫 物理模式作用域的邊界,它能實現資料庫的物理意義、特定DBMS 的特殊操作對外部應用 程式的資訊隱蔽。外部模式是從特定使用者應用角度看待的資料庫模式,從不同的應用出發對同一概念模式可以給出多種不同的外部模式。例如:公路綠化情況查詢應用看到的資料 庫是公路上的樹木種類、數量、分佈比率等, 樑隧道狀況查詢應用看到的是公路上的橋 樑、隧道長度、個數、路段等,但是它們可能訪問的是同一個庫表的不同子集。 當外部應用系統以物件模型進行抽象時,從各個應用出發抽象出的物件模型可以對映 到外部模型上,對此我們不妨稱之為外部物件模型。但是,外部模型只是概念模型的子集 ,所以物件導向的資料庫設計核心在於系統物件模型(不妨稱之為概念物件模型) 向資料 庫概念模型的對映(參見圖1) 。

  2. 物件模型向資料庫表的對映規則

  由於RDBMS是以二維表為基本管理單元的,所以物件模型最終是由二維表及表間關係來描述的。換言之,物件模型向資料庫概念模型的對映就是向資料庫表的變換過程。有關的變換規則簡單歸納如下:

(1) 一個物件類可以對映為一個以上的庫表,當類間有一對多的關係時,一個表也可 以對應多個類。

(2) 關係(一對一、一對多、多對多以及三項關係)的對映可能有多種情況,但一般映 射為一個表,也可以在物件類表間定義相應的外來鍵。對於條件關係的對映,一個表至少應 有3個屬性。

(3) 單一繼承的泛化關係可以對超類、子類分別對映表,也可以不定義父類表而讓子 類表擁有父類屬性;反之,也可以不定義子類表而讓父類表擁有全部子類屬性。

(4) 對多重繼承的超類和子類分別對映表,對多次多重繼承的泛化關係也對映一個表 。 (5) 對對映後的庫表進行冗餘控制調整,使其達到合理的關係正規化。

  3. 資料庫模式要面向應用系統

  我們選擇物件導向的系統設計也好,物件導向的資料庫設計也好,根本目的是服務於應用系統的需要。 以公路局計劃處子系統為例。計劃處的最大工作量就是處理成堆的報表,因此如何有 效地存取這些報表是計劃處資料庫設計的關鍵。考慮到每月上交的報表是同構的,我們可 以建立一張庫表去儲存同一種報表,例如公路工程月報表。但是又產生另一個問題,當使用者想查詢某個月的公路工程月報表時,如何從庫表中取出資料呢?按照資料庫的思想應該 有一個主鍵來標識這張報表。在公路局的報表裡,區別月報表靠上報時間和上報單位,但 如果為每條記錄都加上這兩個欄位,無疑會加大庫表冗餘,增加查詢時間,降低效率。更何 況每張報表都有單位負責人、填表人的屬性,那麼怎樣解決這個問題呢?我們設計了超類 物件 X3 表和流水號表。
  將它們加入由應用物件模型對映出的資料庫概念模型後,得到圖2所示的結構。
  每一個應用模組物件對應建立一張流水號表,同一類的報表屬同一流水號表,由流水號表統一管理。流水號表對各分局、處室提交和建立的每一張報表分配一個流水號,該流 水號在整個資料庫中是唯一的,因此在庫中存放任何一張報表都是明確的。流水號的資料型別為 Char(10),前4位為表號,後6位為序列號,其中序列號取自X3表中最大序列號。也 就是說,流水號就是物件識別符號,報表是一個物件,一個物件識別符號唯一決定一個物件。流 水號一旦被分配出去後,在這張報表的生存期內就具有了永久不變性。無論報表的內容及 結構怎麼變化,它都不變,直到報表被刪除,流水號才會消失。流水號表是父類,報表是子類,流水號表之間的聯絡只能通過 X3 表。5個應用模組物件完全對映到資料庫概念模型中,形成應用物件與資料庫物件的一一對應,保持了5個應用物件在目標系統設計中原有的 獨立性,具有很好的封裝性和資訊隱蔽性。儘管流水號表會有一些冗餘,但它是值得的。

  五、物件導向關聯式資料庫設計效果

  在公路局系統設計中,從某種意義上講,是資料庫設計的物件導向特徵最終奠定了整個系統的物件導向性,才使物件導向方法在程式開發階段全面開花。其效果歸納如下:

  1. 資料庫結構清晰
  便於實現OOP由於實現了應用模組物件對資料庫物件的完全對映,資料庫邏輯模型可以自然且直接 地模擬現實世界的實體關係。公路局使用者所處的當前物理世界、系統開發者所抽象的系 統外部功能,與支援系統功能的內部資料庫 (資料結構)一一對應,所以使用者、開發者和數 據庫維護人員可以用一致的語言進行溝通。 特別是對多數不瞭解公路局業務的程式開發人員來說,這種將應用物件與相應的資料 物件封裝在物件統一體中的設計方法,大大減輕了程式實現的難度,使他們只要知道加工的資料及所需的操作即可,而且應用程式大多雷同,可以多處繼承由設計人員抽象出來的 、預先開發好的各種物理級超類。

  2. 資料庫物件具有獨立性,便於維護
  除了資料庫表物件與應用模組物件一一對應外,在邏輯物件模型中我們沒有設計多重 繼承的泛化關係,所以這樣得到的資料庫結構基本上是由父表類和子表類構成的樹型層次 結構,表類間很少有繼承以外的複雜關係,是一個符合區域性化原則的結構,從而使資料庫表 資料破壞的影響控制在區域性範圍且便於修復,給公路局系統開通後的資料庫日常維護工作帶來便利。

  3. 需求變更時程式與資料庫重用率高,修改少
  在對映應用物件時,除關係對映規範化後可能出現一對多的表對映外,大多數應用對 象與表物件是一一對應的。我們可以把規範化處理後的、由一個應用物件對映出來的多個表看成一個資料庫物件。因此當部分應用需求變更時,首先,系統修改可以不涉及需求 不變更的部分。其次,變更部分的修改可以基本上只限於追加或刪除程式模組或追加新庫 表,而基本上不必修改原有程式程式碼或原有庫表定義,從而大大減少了工作量,降低了工作難度。

  六、最簡單的就是最好的

  客觀世界是錯綜複雜的,電腦科學理論的發展也越來越高深、複雜。然而,人類探索理論和技術的最終目的是:讓客觀世界的複雜變簡單,最簡單的就是最好的。
  為此我們 給出以下幾點忠告:

  1. 慎用外來鍵

  RDBMS 支援複雜關係的能力很強,無論使用者怎麼在邏輯上設定外來鍵,它基本上都能從 物理上幫使用者實現。但是外來鍵把許多獨立的實體牽連在一起,不僅使 RDBMS 維持資料一 致性負擔沉重,也使資料庫應用複雜化,加重了程式開發負擔。這樣的資料庫很難理解,很 難實現資訊隱蔽性設計,往往把簡單問題複雜化。

  2. 適當冗餘

  減少資料庫冗餘的設計思路產生於70年代,它是促使 DBMS 進步的重要動力之一。然 而,猶如為了節省2個位元組的儲存空間而釀成了如今全球為之頭痛的2000年問題一樣,它是 計算機硬體主導時代的產物。以今天國內計算機市場價格為例,6G伺服器硬碟的價格不過 2000元,而上海物價局 1996 年頒發的一個人月軟體開發的指導價約8000元,即一個人月 的軟體價格就可以購買20G左右的硬碟。即使有5萬行資料的庫表,每個記錄壓縮40字元的 冗餘,單純計算合計也不足2M,即節省0.6元錢的磁碟空間。 今天的世界已進入軟體主導的計算機時代。因此,最容易理解、應用開發工作量最少 、維護最簡單的資料庫結構才是最好的。只要資料完整性、一致性不受威脅,有些冗餘,不足為慮。換言之,最節省軟體成本 (而不是硬體成本) 的是最好的。

物件導向資料庫的正確評價與選擇
一、概述
就象關聯式資料庫一樣,市場上有許多物件導向的資料庫(Object-Oriented Database,OODB)可供選擇。然而,OODB在價格、功能、特色和體系上沒有什麼統一的標準。本文將幫助你理解各種OODB系統之間的一些差別,在為應用選擇合適的OODB時,幫助你縮小挑選的範圍。

根據標準的不同,我用於評估這些產品的參考資料也是五花八門。在大多數情況下,本文的評價以個人經驗和看法為基礎;另外一些細節直接從評測軟體或供應商提供的資料資料獲得。在作出選擇之前,務必針對你的應用進行全面的測試。畢竟,你我看法可能有所不同。

我們將要分析的四種OODB產品是ObjectStore、Versant Developer Suite、Poet FastObjects和Objectivity。每一種產品將從以下幾個方面進行評估:
價格和許可 順從性 相容性 特色 效能 可伸縮性和可用性
二、價格和許可
工程成本包括兩個方面:初始成本和維護費用。初始成本往往在評估中起支配作用,但象年度支援、聯機討論、新手培訓等問題都應該成為產品成本的考慮因素。即使和它的競爭者大型RDBMS相比,OODB的價格通常顯得很昂貴。

標準考慮…評估軟體可免費下載的、全功能的試用軟體。開發版許可價格低價格,以使用者數量為基礎的許可。產品許可價格低價格,按照CPU數量為單位的許可,低廉的年度維護費用。聯機支援負責的技術支援人員,大量有用的技術說明、示範和論壇。活躍的使用者社團大量的熱心使用者,新聞組裡豐富有益的活動,非官方網站的支援。
三、順從性
和關聯式資料庫相比,OODB一般對順從標準的要求不是那麼嚴格。大多數OODB都用自己獨特的方法實現各種特色功能。由於還沒有明確的標準評價OODB,所以物件資料庫管理組織(Object Database Management Group,ODMG)的標準是當前最好的準繩。但各個OODB各自為政卻帶來了一些麻煩,要找出一個完全順從ODMG 2.0或3.0規範的OODB產品很困難(與已經有一年曆史的3.0規範相比,2.0規範是一個相當寬鬆和不完善的規範)。也許在不遠的將來,我們將用Java Data Object(JDO)規範評價Java OODB。
標準考慮…對“物件定義語言”(ODL)的順從完全遵從ODMG 3.0規範有關物件定義的規範。對“物件查詢語言”(OQL)的順從完全遵從ODMG 3.0規範有關查詢的規範。對Java的順從性完全遵從ODMG 3.0規範意味著正確實現Java API/繫結。對C++的順從性完全遵從ODMG 3.0規範意味著正確實現C++ API。對Smalltalk的順從性完全遵從ODMG 3.0規範(如果你的系統不太可能用到Smalltalk,那麼這只是一個可選的標準)。
四、相容性
無論是語言還是平臺,工程對可伸縮性的要求會日益增加。OODB不應該在任何一方面影響這種可伸縮性。然而,平臺支援的代價很昂貴,它要求進行廣泛的測試和大量的文件說明。因此,一些供應商的產品只支援數量很少的平臺。要找出一個和各種主流OO語言(如C++、Java、Smalltalk)緊密結合的方案是相當困難的。

標準考慮…支援的平臺廣泛的平臺支援——我總是考慮三個關鍵的平臺:Linux,Win2000,和Solaris。你優先考慮的平臺可能有所不同。Java整合廣泛的JDK支援,緊緊跟蹤最新的JDK規範。C++整合廣泛的編譯器支援持久類的特殊化避免緊密結合——尋找那些不要求修改程式碼中持久類的資料庫。這是一種與偏好有關的選擇,所以你應該認真研究處理後擴充套件和擴充套件/實現方式相比的優缺點。可嵌入的版本只佔用少量的磁碟空間、RAM;具有取消一些非核心功能的能力。
五、特色
每一種資料庫方案都有自己的一些獨特的功能。下面我特別指出一些核心功能,因為這些功能對於開發工程來說具有很高的價值:

標準考慮…資料庫瀏覽管理資料庫、修改內容、更新模式和生成內容報表的能力。客戶端緩衝改善“熱點”資料庫響應速度的能力;在確保物件同步的前提下,使得對資料庫的提取操作減到最少。資料庫安全使用者、使用者組訪問控制,最好在物件(如果不是容器的話)的層次上進行。XML支援無縫地從資料庫提取、向資料庫插入XML的工具。IDE整合和TogetherSoft之類提高開發效率的環境整合能夠提高開發效率。
六、效能
在效能的某些方面,OODB佔有優勢;但在其他方面,OODB又有所不足。在這裡提供每一種產品詳細的效能測試資料顯得過於冗長,但理解可能影響效能的體系和功能方面的侷限是很重要的。

標準考慮…加鎖策略應用-物件級的加鎖機制能夠帶來很大的方便,但頁面級的加鎖機制在某些條件下能夠帶來效能上的飛躍。負載平衡透明地分佈資料庫、呼叫遠端伺服器上的方法、在併發執行緒/訪問之間共享物件的能力。最大的資料庫大小越大越好。事務支援檢查點:由多個執行緒共享一個事務,一個執行緒佔用多個事務,巢狀事務;當某個給定產品的實現影響了你的應用時,確保你自己理解了結合客戶端緩衝時客戶端/伺服器端同步的工作機制。有關查詢/效能的資訊提取這些資訊的能力,它能夠幫助你找出效能瓶頸;OODB提供的優化和調整選項通常要比RDB少,但一些幫你提取效能資訊和解釋查詢執行計劃的工具仍很有用。
七、可伸縮性和可用性
雖然並非每一個工程都要求有企業級的恢復、可用性、可伸縮性功能,瞭解你所選擇的OODB方案能夠隨著工程一起發展而提供這方面的能力是值得的。

標準考慮…失敗轉移主伺服器出現問題時,透明地切換到冗餘資料庫。負載平衡把負載分佈到冗餘伺服器、把物件分割到多個伺服器、同步多個客戶端物件緩衝之間資料檢視的能力。複製和增量備份無縫地複製資料,支援負載平衡和恢復的能力。專用的查詢引擎(Ad hoc query engine)豐富的查詢語言,允許對資料的快速訪問;理想情況下,它應該能夠跨越沒有直接關聯的物件連線資料。
八、產品評論
下面,我按照前文提出的標準評估以下產品:

ObjectStore Versant Developer Suite Poet FastObjects Objectivity
請參考Cetus OODB area,那裡有一個相當新的OODB供應商清單。
標準ObjectStoreVersant Developer SuitePoetObjectivity背景資訊供應商Object DesignVersantPoetObjectivity產品主頁ObjectStoreVDSFastObjectsObjectivity技術參考[29]Spec 或 PDF data sheetOverview 或 manualsJava 或 C++PDF overview 或 specific data sheets版本6.06.0t7 8.0[16]6.0價格和許可試用版本30天試用[1]60天試用功能限制90天試用許可費用[2][2][2][2]聯機支援尚可[3][9]尚可[9]好[19]很好使用者社團[23]中等[4]中等較小中等順從性ODL順從性NNN不完整的2.0/3.0支援OQL順從性NN[10]ODMG 3.0[17]NJava介面遵從ODMG 3.0ODMG 3.0ODMG 3.0ODMG 3.0C++介面支援ODMG 3.0N/A不完整的2.0/3.0支援Smalltalk介面N/AN/AN/AODMG 3.0相容性支援的Unix作業系統Linux,Solaris,HP-UX,IRIX,AIX,Tru64 [ref]Linux,Solaris,HP-UX,IRIX,SGI,Tru64 [ref]Linux,Solaris,HP-UX[ref]Linux,Solaris,HP-UX,IRIX,AIX,Tru64 [ref]支援的Windows作業系統98,NT4,2000 [ref]NT4,2000 [ref]98,NT4,2000 [ref]98,NT4,2000 [ref]JDK要求1.0,1.1–1.3[22]1.2,1.31.1-1.31.22,1.3持久類的特殊化N[5]N[5]N[5]Y[24]可嵌入的版本YNY[18]N功能資料庫瀏覽器YYYY客戶端緩衝YYYY資料庫安全資料庫或者段的使用者/組控制資料庫的使用者控制[14]特定類和資料庫的使用者/組控制資料庫的使用者控制XML支援YY[15]部分[20]部分[20]效能加鎖策略資料庫,頁,或者物件物件級物件級容器級[25]最大的資料庫大小[7]數百個GB?數十個GB到數百個GB?[12]?根據報告,它達到了TB級事務支援死鎖檢測,MVCC [8]分散式事務管理(類似於MVCC的概念)檢查點,共享或並行的事務,巢狀事務檢查點,死鎖檢測,共享或並行的事務提供有關查詢/效能的資訊YN[13]NN[26]可伸縮性失敗轉移(failover)YYY可選[27]負載平衡部分[6]部分[11]部分[21]可選[27]複製和增量備份YYY可選[27]專門的查詢引擎(Ad hoc query engine)沒有OQL。使用集合和查詢物件Y[10]Y (OQL)Y[28]
■ 結束語
我希望自己還沒有給人以OODB狂熱鼓吹者的印象——對於我所使用的大多數應用,我認為應用OODB帶有一定的風險。然而,一旦你理解並熟悉了OODB,它們可以成為很方便的工具。我個人比較看好Poet和ObjectStore,但我覺得它們都很有用。

■ 註解
[1]只提供單例項個人版(Single-instance Personal Edition,PSE)供下載。[2]報價可以從銷售代表處獲得。[3]部分支援服務只提供給有效維護合同的擁有者訪問。[4]社團規模只相對其他OODB產品而言。OODB的使用者社團遠遠小於關聯式資料庫的使用者社團。[5]持久類必須進行事後處理。[6]多個資料庫之間的負載平衡看來不太可能。相反,處理通過客戶端緩衝得以分佈,它把更多的邏輯和計算任務透明地移到了客戶端,從而減小了伺服器的負載。[7]這些資料未經證實,主要從供應商的宣告獲得。在討論資料庫大小的時候,物件的複雜性、大小、“合理的應答時間”等問題都是必須考慮的因素。[8]多版本併發控制(Multiversion Concurrency Control,MVCC)是一種非標準的技術,在併發讀取/寫入操作期間用來維持緩衝客戶端和伺服器端資料檢視的一致性。[9]可以從大量線上演示、FAQ、論壇獲益,所有這一切都對現有和潛在使用者開放。[10]實現了一種私有的VQL語言,它和OQL有一些共同點。[11]通過複製實現部分負載平衡能力;根據推測,負載平衡可能通過把請求重定向到多個資料庫實現,但這一點未經證實。多個資料庫之間的透明覆制確保了每一個OODB上都有一份最新的資料。[12]需要64位的版本,以便超越大量在內村、記錄計數等方面的2^32限制;Versant的64位版本已經構造完畢,但還沒有在所有它所支援的平臺上經過驗證。[13]提供一些用於查詢調整和計時的工具。[14]如果不是我在什麼地方錯過,它似乎沒有提到粒度更小的安全機制或者是在API中提供這方面的能力。我找到特別提及的只是通過OS強制的資料庫檔案許可權實現的資料庫級訪問控制。[15]需要單獨提供的工具。[16]Poet分三種形式:t2(實時嵌入式Java),e7(嵌入式Java/C++),以及t7(企業Java/C++)。版本號沒有明確顯示,t7的v8.0得自檔案的版本號,當前是8.0.0.19。[17]不能保證它完整地支援ODMG 3.0 OQL,但覆蓋範圍看來相當廣泛。[18]包含一個C++或Java的嵌入式版本,以及一個Java的實時嵌入式版本。[19]聯機支援網站community.fastobjects.com的內容非常全面,但速度常常很慢。我擁有高速連線,但它有規律地返回頁面超時錯誤。[20]我只能通過命令列介面使用批量匯入/匯出功能。[21]沒有分散式功能的任何明顯標記,而且我也沒有用過一個分散式的配置。如果Poet的配置中資料庫複製帶有“reader scalability”選項,負載平衡可以在某種程度上得以實現,使得查詢可以對只讀的從屬資料庫進行。[22]至少JDK 1.2看來最好,你將得到更好的集合支援和避免一些已經有報導的“quirk”問題(未能肯定是否為JDK 1.1解決了這些問題)。[23]很難進行評估。我從收入和Internet/新聞組的討論入手分析。請把它看成是一種猜測。[24]持久類的標識或者是它從ooObj派生,或者它實現IooObj介面。[25]雖然對整個容器加鎖聽起來嚇人,但它的基本思想是,它會顯著減少加鎖伺服器的負載。[26]通過API呼叫和統計功能提供一些執行時查詢除錯能力。[27]一些資料,例如這一份說明,顯示出這些選項會增加成本。[28]沒有提供類似OQL的等價語言。SQL++是一種遵從SQL的功能,允許針對OODB進行SQL查詢;容器支援一個scan()方法,以及支援“謂詞查詢語言”表示式(Predicate Query Language)。[29]這四種產品都提供評估版供下載。下載軟體包附帶的文件和示例一般都比較完善。
物件導向軟體開發的十大原則 (二)
當定義方法的引數時,一定要使它們可以擴充套件。例如,下面這行程式碼是不可擴充套件的:

   Public Function PlaceOrder(sLastName as String, sFirstName as String, sAddress as String)

  要想呼叫這個方法你必須傳遞這3個引數。但是如果你以後決定在定單上還需要電話號碼,就必須修改函式簽名,這就破壞了相容性以及每個呼叫此方法的程式碼段。為了防止這個問題的發生,一個更好的解決方法是:在一個容器中傳遞引數。你可以使用記錄集、變數陣列或 XML字串來傳遞更普通的引數。

  當轉移到.NET時,這個技巧就不是十分必要了,因為在.NET中你可以進行函式裝載,這樣就可以具有兩套不同引數的同一個函式:

Public Function PlaceOrder(sLastName _
as String, sFirstName as String, sAddress as String)
Public Function PlaceOrder(sLastName _
as String, sFirstName as String, _
sAddress as String, sPhone as String)

    6. 現在就使用XML

  XML提供了一個管理狀態和在應用程式的元件之間傳遞它的很好方法。 你可以用任何喜歡的格式來定義XML,然後可以從XML字串插入、更新、刪除或回顧任何資訊。

  XML最好的一點是它的跨平臺性並擁有獨立的銷售商。XML既不是Microsoft的技術也不是Sun的技術,是**網聯盟W3C控制著這個標準,具體細節請參見原文。

  XML成為了.NET中的資料存取標準,所以現在就使用會使你一路領先。

  7. 定義靈活的介面

  介面(Interfaces)提供了一個在執行時間插入元件的很好途徑。你可以定義一個介面,建立一個執行它的類,然後就可以在任何時間,很容易地用任何執行同一介面的其它類來代替這個類。

  例如,你可以開發一個郵件列表的標籤列印元件,並且定義這個元件所要求的標準介面。在這個例子中,那個介面包括名字和地址資訊。然後,任何執行這個介面的類都可以使用這個元件,而不需要對其進行任何修改。一個執行標籤列印介面的客戶類可以使用這個元件來列印客戶郵件標籤,一個執行標籤列印介面的職員類可以使用這個元件來列印薪水標籤等。

  8. 繼承功能

  繼承是OOP的一個關鍵原則,它允許你定義一個物件的基礎功能,然後將那個功能應用於物件的特定子類中。

  例如,你可以為一個客戶(Customer)物件定義基礎功能,可以恢復和儲存資料以及計算一個折扣。然後就可以定義一個政府客戶物件,讓它繼承客戶物件的所有功能,但是遮蔽掉折扣計算,因為給政府客戶的折扣更高。

  在VB.NET中,你很快就能實現這些。

  9. 按照模型進行處理

  開發一個描述交易的域模型對於理解應用程式的目的以及它應該解決的問題是非常有用的。 但是有一個常見的錯誤是取得域的模型並試圖為它編碼。相反,你應該融合域模型到一個執行模型中,這個執行模型定義瞭如何建立類的方法。融合過程中,需要考慮許多因素,請參閱建立物件模型。

  10. 瞭解OOP,使用OOP

  所有的.NET都是物件導向的。現在你對OOP瞭解得越多,理解得越好,將來轉移到.NET就越容易。在所有專案中都要準備好使用類模型。如果你不瞭解OOP,或者雖然你瞭解它但是並不真正理解它,可以採用一個OOP類。OOP技術很快就會成為你的第二個自我,你會發現想記起原來是怎麼編碼的都很困難。

物件導向軟體開發的十大原則 (轉一)
  對於開發人員來說,時時回過頭來檢查一下應用程式是非常有用的。考慮一下這個應用程式是否達到了預期目的?是否遵循了最佳方案?要想實現目的是否還存在更好的方法?溫故而知新,也許你會從回顧中發現新的思路。
  本文就提出10種頂尖的物件導向的程式設計技術來幫助你對應用程式進行評價,希望你使用這10個頂尖技術從物件導向的程式設計中獲得最大利益。
  1. 重新審視物件的宣告操作
  如何宣告物件變數會給物件的使用和效能帶來重大的影響。你應該使用這個語法:
    Private m_oCust As Ccustomer
注意一定要使用正確的範圍。在大多數情況下,你希望物件變數是私有的。如果只是在一個特定的程式中需要這個物件,就可以用Dim來宣告它是屬於那個程式私有的。如果在整個類或表單模組中都需要它的話,就應該用Private 在那個類或表單的頂部宣告它。按照習慣,在模組層宣告的變數要加一個字首 "m_",以表示用於模組層或成員變數。如果需要從類外部使用物件變數,就不要將變數設成Public,寧可定義一個Property Get程式來使用物件變數,這樣就防止了其它程式碼不用你不希望的方法去使用變數。
  在宣告中,總是使用類名稱,而不要使用 "As Object",因為使用 "As Object" 會使物件變數成為後期捆綁(late-bound)。這就意味著在執行時間之前,Visual Basic不知道你將使用的物件型別,因此它不能給你提供自動列表成分(物件屬性和方法的下拉選單)。更重要的是,在執行時會對早期捆綁(early-bound)物件造成明顯的效能衝擊。
  最後,在宣告中不要使用"New"這個關鍵字。使用關鍵字"New"時,將在引用它的任何時間自動建立物件,這對效能會造成輕微的影響,因為每個物件的屬性和方法呼叫都必須進行校驗以確定物件是否被建立了。使用"New"這個關鍵字還會給除錯帶來噩夢,因為在物件被破壞之後,如果你不經意地再次引用它的話,應用程式會自動地重新建立物件。當你準備移植到.NET時,理解這一點更加重要,因為在那裡關鍵字"New"有一個不同的意義。在.NET中,關鍵字"New"允許你在宣告時建立一個物件,比如下面這條語句將建立一個新的Customer物件:
   Private mo_Cust as New CCustomer()
  2. 重視物件清除行為
 當不再需要物件變數時,一定要釋放它們,然後VB就會破壞與變數相聯絡的物件,從而釋放應用程式中的記憶體。使用下面的程式碼釋放一個物件:
   Set x = Nothing
  3. 封裝的重大作用
  Encapsulate(封裝)從字面上講就是放入封套或"放在一個殼子中"。從物件導向程式設計 (OOP) 的角度來看,這意味著將所有與一個物件相關的資料和處理都放在它的類中。
  封裝有時候指的是資訊隱藏,因為你將物件的資料藏在了類的內部。如果其它的類需要使用資料,可以使用屬性程式(.NET 中的屬性宣告)來暴露這些資料。這個行為為類提供了控制, 它控制使用者可以如何觀看或重新整理資料,並且防止其它物件誤用資料。
  封裝使得物件之間的互動作用變得簡單化。一個物件不用知道另一個物件的全部資料或者其資料是如何管理的,就能夠使用這個物件。例如,一個Customer物件可能有名字和地址屬性以及電話號碼、信用歷史和其它相關域。如果一個Invoice 物件想要使用一個 Customer 物件,它可以為發票請求名字和地址,而不需要知道Customer是從哪裡獲取那個資料的,或者其它資料元素是什麼。
  對於如何為可擴充套件的標記語言(XML)將文件物件模型 (DOM) 封裝在一個包裝類中的解決方案,請參考此文,這使你能夠更容易地與一個XML檔案進行互動作用,而不需要知道DOM的細節。
  4. 狀態監視問題
  良好的基於元件的開發技術會頻繁地要求無狀態的物件。無狀態物件沒有保持的屬性,只有方法。你可以訪問一個無狀態的元件,執行方法,然後不需要獲取方法呼叫間的任何資料就可以完成處理。
  有一些OOP方面的文章提出沒有屬性的物件就不是物件。 但是我們現在忽略這個語義上的問題,你可以建立有方法而沒有屬性的類。當你從事COM+或Web開發時,經常會需要這樣做。一個ASP頁面可以在一個元件上執行一個方法來完成一個特殊的處理,然後再釋放元件,不用為管理物件狀態而費心。
  5. 傳遞引數的可擴充套件性
  引數提供了類的方法之間傳遞資訊的途徑。你需要用引數向方法傳遞任何必要的資料,特別是當你需要無狀態物件的時候。
  例如,無狀態物件Customer 的PlaceOrder方法要求把客戶的資訊作為引數傳遞給它,然後PlaceOrder方法就用這個資訊來完成必要的處理。