[畢業生的商業軟件開發之路]開發第一個Windows應用程序
近期開始接觸到在校學生、高校實習生和畢業生,在此說一下筆者對這些徘徊在職場門口的學生一些建議,希望能給這些初學者進入軟件開發行業帶來一些幫助,使得畢業生能更順利的進入軟件開發公司開始職場生涯,人生來一個完美的轉彎。
---------------------------------------------------------------------------
---------------------------------------------------------------------------
開發第一個Windows應用程序
在本章筆者帶著讀者使用VS.NET2010開發第一個Windowns應用程序。初步了解使用C#進行Windows應用開發。
本軟件的功能需求就是開發一個能進行加減乘除的計算器。
建立C# Windows應用程序項目

在該對話框中,筆者進行以下四步操作。
1. 在“已安裝的模板”樹[袁永福版權所有]狀列表中選中“Windows”節點。
2. 在右邊的列表中選中“Windows 窗體應用程序”項目。
3. 在“名稱”文本框中輸入“第一個Windows應用程序”。
4. 在“位置”文本框中輸入保存程序文件的目錄路徑。

學過VB的可以發現,這個用戶界面和VB的用戶界面很相似。對于會VB的初學者來說,使用C#開發Windows應用程序和VB差不多,只是后臺編程語言由VB改成C#。
在這個VS.NET的用戶界面中,主要的用戶界面元素有最左邊是控件工具箱,中間是窗體設計器,右上方為工程資源樹狀列表,右下方為控件屬性編輯列表。
WinForm控件工具箱
該界面最左邊為Windows控件工具箱,上面列出了所有的可以使用的控件。用戶按下該列表中的某個控件圖標,然后鼠標拖拽到左邊的窗體上即可在窗體上新建一個指定類型的控件。比如如下圖所示,用戶按下“Button”項目然后拖拽到窗體上,則會在窗體上新增了一個按鈕控件,控件的位置就是鼠標光標所在位置,控件大小采用默認大小。
另外當工具箱中的控件項目按下后,將鼠標移動到窗體設計器中。此時鼠標光標就變成附加控件圖[袁永福版權所有]標的十字形。比如用戶按下“Button”項目,然后鼠標移動到窗體設計器中,則鼠標光標樣式為“
”。此時開發人員在窗體設計器中使用鼠標拖拽操作在窗體上畫上一個指定位置指定大小的控件。
在默認情況下,控件工具箱中列出的控件是夠用的。但這里并沒有列出微軟.NET框架自帶的所有的Windows控件,而且也不包含第三方的控件,為了使用沒有默認列出的控件,筆者需要往控件工具箱上添加新的控件。

該對話框中最重要的是“.NET Framework組件”分頁標簽頁面。該頁面列出了本系統安裝的基于.NET平臺的組件。
在.NET組件頁面[袁永福版權所有]中列出了目前VS.NET所能識別的所有的Windows控件,人們可以在某個控件前面設置打勾使得該控件能顯示在工具箱的控件列表中,不打勾就不顯示。
對于從第三方獲得的已經開發好的控件,開發者可以點擊“瀏覽”按鈕來選擇包含控件的.NET程序集文件,比如“MyControls.DLL”。然后控件列表中出現了開發人員選擇的.NET程序集中所包含的控件項目,開發人員就可以在這些控件前面打勾使其顯示在工具項目中的控件列表中。
WinForm窗體設計器
窗體設計器具有以下幾個主要功能
1. 開發人員可以從左邊的控件工具箱中拖拽圖標到窗體上來在窗體中放置各種各樣的控件,控件的位置就是鼠標拖拽到的位置,控件的大小為默認大小;開發人員也可以按下控件工具箱中的控件圖標,然后在窗體中拖拽畫出指定位置指定大小的控件。
2. 開發人員可以很方便的使用鼠標拖拽操作來移動控件在窗體中的位置或者修改控件的大小。當窗體中存在可容納子控件的容器控件時,開發人員拖拽時可以修改控件的父子關系。
3. 開發人員可以點擊選中某個控件,然后在右邊的屬性列表中查看和修改控件的屬性。
4. 開發人員可以雙擊控件,而且控件具有默認事件,則用戶界面會切換到C#代碼編輯界面,并自動構造出響應控件默認事件的C#代碼結構。開發人員可以直接輸入響應控件事件的程序代碼了。
可以看到窗體在設[袁永福版權所有]計時的顯示效果就基本上等于運行時的顯示效果。實現了一種“所見即所得”的可視化界面設計功能。
可視化軟件開發
微軟的集成開發環境“Microsoft Visual Studio”中的Visual就是“可視化”的意思。微軟最早是在Visual Basic中實現了可視化的用戶界面設計功能,這引起了軟件開發方法的革命。
比如對于上圖的那個對話框,在沒有可視化程序開發時,開發人員需要手動的編寫以下的代碼來構造出本窗體的用戶界面。
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.TextBox txtNumber1;
private System.Windows.Forms.ComboBox cboOperator;
private System.Windows.Forms.TextBox txtNumber2;
private System.Windows.Forms.Button btnCalculate;
private System.Windows.Forms.TextBox txtResult;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.txtNumber1 = new System.Windows.Forms.TextBox();
this.cboOperator = new System.Windows.Forms.ComboBox();
this.txtNumber2 = new System.Windows.Forms.TextBox();
this.btnCalculate = new System.Windows.Forms.Button();
this.txtResult = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// txtNumber1
//
this.txtNumber1.Location = new System.Drawing.Point(12, 40);
this.txtNumber1.Name = "txtNumber1";
this.txtNumber1.Size = new System.Drawing.Size(84, 21);
this.txtNumber1.TabIndex = 0;
//
// cboOperator
//
this.cboOperator.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboOperator.FormattingEnabled = true;
this.cboOperator.Items.AddRange(new object[] {
"+",
"-",
"*",
"/"});
this.cboOperator.Location = new System.Drawing.Point(96, 40);
this.cboOperator.Name = "cboOperator";
this.cboOperator.Size = new System.Drawing.Size(44, 20);
this.cboOperator.TabIndex = 1;
//
// txtNumber2
//
this.txtNumber2.Location = new System.Drawing.Point(140, 40);
this.txtNumber2.Name = "txtNumber2";
this.txtNumber2.Size = new System.Drawing.Size(76, 21);
this.txtNumber2.TabIndex = 0;
//
// btnCalculate
//
this.btnCalculate.Location = new System.Drawing.Point(216, 39);
this.btnCalculate.Name = "btnCalculate";
this.btnCalculate.Size = new System.Drawing.Size(32, 23);
this.btnCalculate.TabIndex = 2;
this.btnCalculate.Text = "=";
this.btnCalculate.UseVisualStyleBackColor = true;
//
// txtResult
//
this.txtResult.Location = new System.Drawing.Point(248, 40);
this.txtResult.Name = "txtResult";
this.txtResult.ReadOnly = true;
this.txtResult.Size = new System.Drawing.Size(87, 21);
this.txtResult.TabIndex = 0;
//
// frmMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(356, 122);
this.Controls.Add(this.btnCalculate);
this.Controls.Add(this.cboOperator);
this.Controls.Add(this.txtResult);
this.Controls.Add(this.txtNumber2);
this.Controls.Add(this.txtNumber1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "frmMain";
this.Text = "計算器";
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.TextBox txtNumber1;
private System.Windows.Forms.ComboBox cboOperator;
private System.Windows.Forms.TextBox txtNumber2;
private System.Windows.Forms.Button btnCalculate;
private System.Windows.Forms.TextBox txtResult;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.txtNumber1 = new System.Windows.Forms.TextBox();
this.cboOperator = new System.Windows.Forms.ComboBox();
this.txtNumber2 = new System.Windows.Forms.TextBox();
this.btnCalculate = new System.Windows.Forms.Button();
this.txtResult = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// txtNumber1
//
this.txtNumber1.Location = new System.Drawing.Point(12, 40);
this.txtNumber1.Name = "txtNumber1";
this.txtNumber1.Size = new System.Drawing.Size(84, 21);
this.txtNumber1.TabIndex = 0;
//
// cboOperator
//
this.cboOperator.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboOperator.FormattingEnabled = true;
this.cboOperator.Items.AddRange(new object[] {
"+",
"-",
"*",
"/"});
this.cboOperator.Location = new System.Drawing.Point(96, 40);
this.cboOperator.Name = "cboOperator";
this.cboOperator.Size = new System.Drawing.Size(44, 20);
this.cboOperator.TabIndex = 1;
//
// txtNumber2
//
this.txtNumber2.Location = new System.Drawing.Point(140, 40);
this.txtNumber2.Name = "txtNumber2";
this.txtNumber2.Size = new System.Drawing.Size(76, 21);
this.txtNumber2.TabIndex = 0;
//
// btnCalculate
//
this.btnCalculate.Location = new System.Drawing.Point(216, 39);
this.btnCalculate.Name = "btnCalculate";
this.btnCalculate.Size = new System.Drawing.Size(32, 23);
this.btnCalculate.TabIndex = 2;
this.btnCalculate.Text = "=";
this.btnCalculate.UseVisualStyleBackColor = true;
//
// txtResult
//
this.txtResult.Location = new System.Drawing.Point(248, 40);
this.txtResult.Name = "txtResult";
this.txtResult.ReadOnly = true;
this.txtResult.Size = new System.Drawing.Size(87, 21);
this.txtResult.TabIndex = 0;
//
// frmMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(356, 122);
this.Controls.Add(this.btnCalculate);
this.Controls.Add(this.cboOperator);
this.Controls.Add(this.txtResult);
this.Controls.Add(this.txtNumber2);
this.Controls.Add(this.txtNumber1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "frmMain";
this.Text = "計算器";
this.ResumeLayout(false);
this.PerformLayout();
}
編寫這樣的代碼是枯燥范圍而且效率低下的過程。開發人員在編寫代碼的過程中需要在腦海中想象出這段代碼運行后的窗體界面。需要多次運行程序顯示窗體查看運行效果后修改代碼進行控件位置大小的微調。當窗體界面中需要新增或刪除控件時會影響其他控件的排版,此時又得多次運行程序顯示窗體來修改代碼進行微調。
當窗體界面很復雜,開發人員需要編寫和維護幾千行的構造窗體用戶界面的代碼,這一大段代碼開發和維護成本是非常高的。
而是用可視化的窗[袁永福版權所有]體用戶界面設計功能能大大降低設計和維護窗體用戶界面的成本。在窗體設計器中,開發人員即可看到控件在窗體中的排版效果,并能比較精確的進行控件排版微調,還可以使用控件的屬性編輯器來編輯控件屬性,并能實時的看到用戶界面的修改效果。這樣能很大的提高用戶界面設計工作效率,縮短開發和維護時間。
另外從開發方式來說,可視化用戶界面設計降低了勞動強度。在沒有可視化設計前,開發人員完全靠寫代碼來拼湊軟件用戶界面,寫代碼是一種高強度的勞動,開發人員需要端坐在電腦前,腦子里想出代碼,然后雙手在鍵盤上快速的輸入代碼,此時無論身體還是精神處于一定的緊張狀態,勞動強度高,比較容易疲勞。
而可視化用戶界面設計過程中,大部分操作是靠鼠標操作的,單手即可完成,因此開發人員不需要端坐,而可以采用比較休閑舒適的坐姿,而且設計過程比較簡單,大腦思考不多,此時身體和精神處于較為放松的狀態,勞動強度低,不容易疲勞。
有人認為可視化設計降低了對軟件開發人員的要求,對于其成長不利。個人覺得并不是這樣的。
可視化操作掩蓋了軟件用戶界面的后臺實現,由于人們普遍具有惰性,能使用可視化操作完成用戶界面的設計任務后就不深究其后臺的實現,這確實不利于開發人員的技術鉆研。不過學海無涯,軟件開發涉及到很多很多技術的細節,若開發人員要了解軟件開發過程中所有的技術細節,尤其是構造用戶界面的比較枯燥乏味的技術細節,這會耗掉相當多的精力,從而減少了對其他技術細節的關注度。
現代軟件的開發內容分為技術內容和業務內容。對于行業應用軟件,開發人員應當將主要精力放置在行業業務細節,需要花大精力來理解客戶業務需求,包括客戶的業務數據和執行流程。只有深入理解了業務,開發人員才能利用軟件開發技術來開發符合業務內容的應用軟件。因此開發人員應當花費主要精力在深入理解客戶業務上,充分掌握客戶的業務細節。
由于人的精力是有限的,因此開發人員應當盡量少的降低對技術細節的精力消耗量,這就是各種應用系統框架出現的原始需求。可視化程序設計就能隱藏大量的技術細節,使得開發人員能快速高效的設計程序,降低花在軟件開發技術細節上的精力消耗。這優化了開發人員的精力配置,使得開發人員不必糾纏在軟件技術細節問題上,更注重于業務的理解和實現,提高軟件開發的生產效率。
而且可視化軟件設計能降低對開發人員的水平要求,由于可視化軟件開發操作簡單,不需要寫代碼,這能降低軟件開發人員的水平要求,使得大量的低級軟件開發人員也能參與商業軟件的開發。
一般來說,一個企業的軟件開發人員是高水平的開發人員少,低水平的開發人員多。高水平的開發人員能開發和維護上萬行的源代碼,而低水平的開發人員只能維護幾千行的源代碼,而高校實習生們只能編寫幾百行的源代碼。因此不能指望低水平的開發人員能通過編寫程[袁永福版權所有]序代碼來構造軟件的用戶界面。
若沒有可視化軟件開發,則企業中必然存在大量的不能投入實際工作的開發人員,這對企業來說會有巨大的不必要的成本浪費。而可視化軟件開發掩蓋了一些技術細節,使得低水平的開發人員能比較獨立的進行軟件的用戶界面開發,這樣企業中所有的開發人員都能投入實際工作,不會浪費人力資源,提高企業的盈利水平。
當然,完全的使用可視化的軟件設計確實縱容了開發人員的惰性,大量的沒有鉆研精神的軟件開發人員只利用了可視化軟件設計的功能而不去思考其掩蓋的技術細節,這不利于由低水平的軟件開發人員升級為高水平的軟件開發人員。筆者見過這類的開發人員,使用VS.NET從事開發工作若干年,只會拖拽生成DataSet,然后在窗體上放置若干個控件,直接綁定到數據源上,幾年下來都是干這樣的工作。對此少數開發人員覺得工作一段時期自己的水平沒有多大提高而有所焦慮并試圖改變;當然也有很多懶惰的開發人員對此麻木不仁,技術水平原地踏步,終難成大器。
因此有夢想的開發人員還需要大力發揚鉆研精神,不拘泥于可視化軟件設計帶來的便利,還需要深入理解相關技術細節,也是初級開發人員成長的必由之路。
有完美主義者認為[袁永福版權所有]讓初學者學習軟件開發,必須拋棄可視化軟件設計,一切用手工編寫代碼來實現功能,這樣做為得是讓學習者一開始就學習技術底層細節。筆者個人覺得不妥:
從軟件開發學習者的角度來說,一開始就學習技術底層細節就像讓小學生學習高難度的奧數一樣,對于少數天才這是提升能力的較好方式,但對于大多數普通人來說那是拔苗助長。過高的難道將較大的打擊學習者的信心,使得學習者喪失對軟件開發的興趣,容易導致其放棄學習。
持精英教育觀點的人士或者會說就是這樣才能大浪淘沙,能發現并培養出高水平的軟件開發人員。可是中國軟件行業需要幾十萬上百萬的軟件開發人員,若通過這種方式培養不知何年那月才能湊齊這個數字。
從企業的角度來說,一開始就讓初學者或者大學畢業生學習技術底層細節,則時間比較長,可能需要好幾個月甚至一年以上的時間,還得讓老員工花時間悉心指導才可能成功;若經過培訓發現初學者不是軟件開發的料則之前的工作全部浪費。這種培養方式對自負盈虧的企業來說成本太高了,得不償失。
若讓初學者首先學習可視化軟件設計,則學習難度低,速度快,而且能較快的投入實際的軟件開發過程中。因此能讓初學者或者大學畢業生盡快的投入實際工作,為企業帶來工作業績。而且能較快的看到自己能投入實際工作,這對大學畢業生來說是一種激勵,使其能較快的建立起職場自信心,形成對軟件開發工作的興趣,這對企業和個人來說都有好處。
綜上可以看到,可視化軟件設計確實較大的提高了開發人員的工作效率,降低軟件的開發成本。[袁永福版權所有]
posted on 2011-08-17 09:46 袁永福 電子病歷,醫療信息化 閱讀(4706) 評論(0) 收藏 舉報



浙公網安備 33010602011771號