目前分類:軟體開發 (12)

瀏覽方式: 標題列表 簡短摘要

部落格的第一篇文,就要玩這麼硬嗎? 我想是的,努力衝一波吧!

我希望透過實戰系列來撰寫技術學習文章,然後一邊打造免費版的機器視覺軟體,再把這個過程記錄下來。

開發軟體的人最希望的就是,自己創造的東西越多人用越好,因為那是最自由也最有成就感的時刻。 

接下來我會陸續把細節給慢慢補上,但基本上內容會包含:

1. 物件導向概述

2. 物件導向理論簡介

3. 物件導向方法

4. 物件導向技巧

5. 物件導向實戰:實戰案例為影像處理類別

6. 影像格式與檔案內容介紹

7. 影像處理演算法介紹

8. 機器學習演算法介紹

9. API 設計

10. 人機介面 GUI 設計 (C#, Python)

11. SIMD的加速指令集設計技巧

12. 系統移植 (PC to Embedded System)

以上的內容,我會盡量濃縮為 30 ~ 60 天的課程,這次課程結束後,之後的實戰系列就可以直接上案例分析了。

我希望未來可以設計一個又一個可以實際使用的軟體,並分享給大家使用。

考驗我的時刻到來,我會強迫自己完成目標的,加油!

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

終於完成物件導向的設計,包括用於指導撰寫程式的「類別模型」和「動態模型」。

以物件導向的方式進行設計,只是進攻的前奏,撰寫程式才是最終的目標。

雖然物件導向的理論、方法、技巧經過多年的發展後,業界已經形成基本統一的認知,但並未出現一種統一的「物件導向程式語言」。

 

程式語言的差異性


每種語言都會根據自己的需求、特徵,選擇支援或不支援物件導向,或者只支援部份物件導向的特性。

各種語言對物件導向支援的程度和方式,導致將其設計轉換為程式碼時,還需要做一次翻譯或轉換的過程。

因此,若想充分應用物件導向,除了掌握物件導向的概念、方法、技巧外,還得要精通程式語言與物件導向相關的特性。

本系列以 C/C++ 為主要程式語言,並詳細描述它們與物件導向相關的特性;在 GUI 的設計上,我們會採用 C# 及 Python 來說明。

這邊只是先擷取出 C++ 跟物件導向相關的資料,後續我們會再參考「API Design for C++」一書來了解更多的細節。

 

C++


C++是第一個廣泛流行的物件導向程式語言,至今依然佔據程式語言榜單的前幾名。

儘管 C++ 促進了物件導向程式設計的發展,但它的複雜性也伴隨著較大的爭議;尤其是與物件導向相關的特性,光是各式各樣的術語,就能把剛入門的程式開發者搞得頭昏眼花。

尤其 C++ 相容於 C 語言的特性,導致在程式中,一不留神就會出現「物件導向」和「程序導向」風格混雜的情況。

正因為 C++ 這種特性,當採用 C++ 進行物件導向程式設計時,就需要花費更多的時間和精力,以便瞭解 C++ 物件導向的特型。

 

類別


C++ 類別透過關鍵字 class  來標示。

類別的定義包含兩部分:類別標頭 (header, .h),由 class 和後面的類別名稱組成;類別實作(source, .cpp ),由一對大括弧包圍起來,裡面包含屬性和方法的宣告。

例如:

NImage.h

#ifndef		_NIMAGE_H
#define		_NIMAGE_H

#include <windows.h>

#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4) 

class NImage 
{
private:
	HBITMAP			hBitmap;
 	LPBYTE    		lpBits;

	int				nWidth;
	int				nHeight;
	int				nBitCount;
    int				nBytesPerLine;
	int				nBytesPerPixel;
	int				nNumColors;
	int				nSize;

	HDC				hMemDC;

public:
	NImage();
 	~NImage();
public:

// Overrides
 	virtual BOOL  BitBlt(HDC,int,int,int,int,int,int,DWORD);
 	virtual BOOL  MaskBlt(HDC,int,int,HBITMAP,DWORD);
  	virtual HDC   GetDC();
	virtual void  ReleaseDC();

	void  Create(int Width,int Height,int Bits,DWORD dwFlags=0);
 	BOOL  IsNull();
	void  Destroy();

	int   GetWidth();
	int   GetHeight();
	int   GetBPP();
	int	  GetPitch();
	int	  GetMaxColorTableEntries();
  
	BYTE* GetPixelAddress(int x,int y);
	COLORREF GetPixel(int x,int y );
	void  GetColorTable(int m, int n, RGBQUAD* ColorTab);
	void  SetColorTable(int m, int n, RGBQUAD* ColorTab);

	BOOL  LoadBMP(char* filename);
	BOOL  SaveBMP(char* filename);

	HBITMAP* GetBitmap();

};

#endif		//!_NIMAGE_H

在 C++ 中,宣告和定義是分開的,上述程式碼只是 NImage 類別的宣告,其方法需要在定義檔(source, .cpp)實作。

例如:

NImage.cpp

#include <stdio.h>
#include "NImage.h"

NImage::NImage()
{
	hBitmap=NULL;
	hMemDC=NULL;
}

NImage::~NImage()
{
	Destroy();
}

BOOL  NImage::IsNull()
{
	if (hBitmap==NULL)
		return(TRUE);
	else
		return(FALSE);
}

void  NImage::Destroy()
{
    if (hBitmap!=NULL) {
		DeleteObject(hBitmap);
   		hBitmap=NULL;
	}
}


存取控制


C++類別的屬性和方法,都可以指定三種存取控制方式:

1. public: 程式的任何地方都可以存取,例如類別本身、其他類別、其他函式等。

2. protected: 對子類別就像 public 一樣,對其他程式則表現得像 private。

3. private: 只能被該類別的成員函式和朋友類別(friend class)存取。

 

C++ 是分段的存取控制方式,每段的開始透過存取限定詞加上一個冒號 ( : ),直到另一個分段開始時結束,或者到類別定義結束。

一個類別允許包含多個存取控制段;如果沒有指定存取限定詞,則預設為 private。

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

動態模型


動態模型設計一般都是在類別模型設計完成後開始,此階段需要使用類別模型的類別。

動態模型設計不需要應用「設計原則」和「設計模式」,只需對照「使用案例模型」,並根據使用案例的特點,選一個適合的動態模型表述即可。

 

模型分類


參考 UML 標準,常見的動態模型如下:

* 狀態模型→主要描述物件生命週期的狀態變化。

* 活動模型→主要用來描述一個工作流程或計算流程。

* 序列模型→主要用來描述物件按照時間順序組織的訊息互動過程,其關鍵特徵是強調按照「時間順序」組織物件的互動。

* 協作模型→主要用來描述物件之間的關聯組知的訊息互動過程,其關鍵特徵是強調「物件關係」組織物件的互動。

 

建模實踐


基本上動態模型都可以從「使用案例模型」推導出來,但狀態模型會比其他模型複雜一些,因為需要綜合多個使用案例模型,從中提取出和某個物件狀態相關的內容,再統一設計狀態模型。

從使用案例模型推導出動態模型是一個「分解和分配」的過程。

 

建模技巧


在實際的專案進行過程中,其實每個子專案或功能,並不會都使用動態模型來描述,這主要是程式設計人員效率方面的考量。

設計動態模型主要是便於思考和理解實作過程;如果專案比較簡單,通常很容易理解,也就沒必要設計動態模型了。

考慮到效率和效果兩個因素,一般只需要針對一些關鍵、核心及複雜的專案或功能,進行動態模型設計即可。

但要注意,千萬不要直接按照動態模型撰寫程式碼,模型不等於虛擬碼、更不等於程式碼,模型的主要目的是指導程式碼的撰寫,但並非程式碼的文字敘述。

 

本章總結


1. 設計階段將輸出設計模型。

2. 物件導向設計更像是一門藝術。

3. 設計模型主要包含兩個部分:靜態模型、動態模型。

4. 從領域模型可以得到最初的設計類別。

5. 「設計原則」和「設計模式」可以指導做出更好的物件導向程式設計。

6. 設計原則主要是指 SOLID 原則。

7. 設計模式是指 GoF 提出的設計模式。

8. 根據框架或者規範的要求,拆分輔助類別。

9. 動態模型主要有 4 種:狀態模型、活動模型、序列模型、協作模型。

10. 動態建模不需要面面俱到。

11. 動態建模不等於程式碼。

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

經過領域模型的分析後,已經可以看出「物件導向」的雛型了,但領域類別無法直接拿來做程式設計,因為它只是從「使用案例模型」中萃取出來、映射業務領域的概念,而非真正意義上的軟體類別。

「設計模型」就是用來連結「領域類別」到「軟體類別」的轉換,這就是「物件導向設計階段」的主要任務。

設計階段是整個物件導向分析和設計的關鍵,它將輸出「設計模型」,並綜合各種方法與技巧。

設計並沒有一個量化的標準,這代表沒有標準答案,物件導向的設計更像是一門藝術,不過它也是有一定的規律和方法可尋。

 

設計模型總覽


設計模型主要包含:靜態模型和動態模型。

靜態模型又稱為「類別模型」,主要關注系統的「靜態」結構,描述系統包含的類別、類別的名稱、職責、屬性、方法,以及類別與類別之間的關係。

動態模型關注系統的「動態」行為,描述類別本身的一些動作,或者狀態變化,以及類別之間如何配合,才能完成最終的系統功能。

只有結合靜態與動態模型,才能真正描述清楚一個系統。

靜態模型:類別的宣告,包括類別、屬性、方法名稱。

動態模型:類別的實作,每個方法內部的實作過程。

因為動態模型是描述具體功能的實作過程,看起來會跟「程序導向」的分析方法類似,但它本質上還是「物件導向」,描述的是各個物件之間如何配合與協作。

動態模型必須在靜態模型的基礎上設計,靜態模型的變化也會影響到動態模型。

 

類別模型


「類別模型」是整個物件導向設計模型的核心。

進行物件導向類別設計,第一個要解決的問題是:類別從哪裡來?

領域模型中的「領域類別」,便是設計類別中「軟體類別」最好的來源;透過「領域類別」啟發設計最初的「軟體類別」,具有下列幾個明顯的優點:

*軟體類別來自領域類別,領域類別來自使用案例,使用案例來自客戶;一環扣一環,軟體類別的正確性得到保證,不用擔心主觀臆測所帶來的問題。

*領域類別到軟體類別的轉換非常簡單,只要掌握基本的物件導向知識就能完成。

*不需要參考其它系統,不用擔心沒有參考物時無法設計的問題。

 

1. 領域類別映射


-類別篩選

「軟體類別」是軟體系統內部的一個概念,而「領域類別」則是業務領域的概念,並不是每個領域類別最終都會體現在軟體系統中。

-名稱映射

篩選完成後,將每個領域類別都用一個軟體類別相對應,名稱保持一致即可,別擔心這樣的設計品質不高,目前只是一個開始工作。

-屬性映射

透過名稱映射得到軟體類別後,接下來就是設計類別的屬性;由於領域類別已經有屬性,因此照搬過來即可。

-提煉方法

軟體類別的屬性設計完成後,接下就是設計軟體類別的方法;類別方法的設計也是從已有的模型推導出來。

鎖定「使用案例模型」來找到類別方法,其重點就是「找動詞」。

我們之後會以「影像處理軟體」為例,說明如何透過「找動詞」這種技巧找到軟體類別的方法。

 

2. 應用設計原則和設計模式


物件導向領域經過幾十年的演進,已經發展出很多成熟的指導方針和方法,以利於評價和規範物件導向設計;其中最具代表性的就是「設計原則」和「設計模式」。

-設計原則

當提及物件導向領域的設計原則時,其實都是在談論 Robert C Martin 的 「SOLID 原則」。

設計原則也是一個判斷標準,應用設計原則的根本目的是要「保證可擴充性」。

設計模式的本質也是為了提高可擴充性;這也是為什麼透過領域類別映射後,還要繼續應用「設計原則」和「設計模式」的主要原因,根本上都是為了提高設計的可擴充性。

後續將以「影像處理軟體」為例,看看如何應用設計原則。

-設計模式

相較於設計原則,設計模式更加普及與流行;一般談到設計方法時,都會先想到設計模式。

通常談論設計模式時,其實都是指 GoF (Gang of Four) 所講的設計模式。

設計原則和設計模式是互補關係:設計原則主要規範「類別的定義」,而設計模式主要規範「類別的行為」。

設計原則:類別的靜態設計原則。

設計模式:類別的動態設計原則。

後續將同樣以「影像處理軟體」為例,說明如何應用設計模式來進行最佳化設計。

 

3. 拆分輔助類別


拆分類別的主要目的,是為了使撰寫類別時能夠滿足一些框架或規範的要求;例如常見的 MVC 模式,拆分成 ModelViewControl 三個元素等。

只要將設計出來的類別,按照規範要求,對應拆分即可;這僅是為了滿足框架或者規範的要求,本身並不是設計,而是實作的一個步驟,所以一般都不需要將拆分的輔助類別體現於類別模型中,只在設計程式時拆分即可。

 

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

什麼是領域模型?


需求分析和物件導向並無直接關係,需求分析階段不區分是物件導向還是程序導向,要從「領域建模」才真正開始物件導向的工作。

領域模型是完成從需求分析到物件導向設計的一座橋樑。

領域模型是對領域內的概念或現實世界中物件的視覺化表示,又稱「概念模型」、「領域物件模型」、「分析物件模型」。

 

該如何進行領域建模?


領域建模的方法概括起來就是「找名詞」,從需求模型中或是說「從使用案例中找名詞」。

找到名詞後,為了能夠更加符合物件導向的要求,還需要進一步完善這些名詞:加屬性、連關係。

領域建模的方法可以總結為:找名詞、加屬性、連關係。

另外,該注意的是領域建模無法關注使用案例的約束和限制,例如效能、可靠性等;但後面進行設計時還會回過頭來核對使用案例。

後續我們會使用一個「影像處理軟體」的使用案例來說明如何建立領域模型。

 

常見問題


1. 如果沒有使用案例,是否就無法得到領域模型?

對於經驗豐富的分析師來說,沒有使用案例同樣能夠分析出領域模型;但強烈建議使用案例分析,使用案例對於正確分析客戶需求非常有幫助。

2. 如果是程序導向,需要進行領域模型分析嗎?

基本上不需要,程序導向需要分析的是「工作流程」和「資料結構」。

 

本章總結


* 領域模型是「需求到物件導向的橋樑」。

* 領域建模的方法:找名詞、加屬性、連關係。

* 從使用案例中可以找到領域模型所需的名詞。

* 領域模型的類別不是軟體類別,只是用來描述領域的實體,不需要關注方法。

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

使用案例 (Use Case)是用來描述需求的流程,就是 5W1H 中的  How。

流程一般都是客戶根據自己的業務總結而來,看似只要將客戶描述的內容記錄下來即可,但現實與理想總是有差距,各式各樣的狀況都可能出現,因此我們也無法直接通過記錄客戶的描述,就能直接完成描述需求的流程。

 

NEA 三段法


只要掌握正確的方法,就可以完成良好的需求分析,例如使用案例方法三段法 (NEA 方法):

1. 正常處理 (Normal),通過和客戶溝通,分析需求的正常流程。

2. 異常處理 (Exception),在正常處理流程的步驟上,分析每一步的各種異常狀況和對應的處理。

3. 替代處理 ( Alternative),在正常處理流程的步驟上,分析每一步是否有其他替代方法,以及如何進行。

經過以上簡單的三段法後,可以說 How 就分析得差不多了。

後續我們會用一個完整的「影像處理軟體」使用案例來說明需求分析 5W1H8C 方法涉及的內容。

 

使用案例說明


一個完整的使用案例,應該包含下列幾個部分:

1. 使用案例名稱,即需求的名稱。

2. 場景,使用案例發生的環境,正好對應 5W 中的 3 個 W - Who, Where, When。

3. 使用案例描述,對應 5W 中的 What 和 How,亦即客戶應該怎樣做,以及每個步驟的輸出;不要求每個步驟都一定有輸出,可以有也可以沒有,或著有多個輸出。

4. 使用案例價值,描述使用案例對應的客戶價值,對應 5W 中的 Why。

5. 約束和限制,整個需求流程中相關的約束和限制條件,對應 8C。

 

常見問題與回答


1. 5W1H8C 分析方法是物件導向專用的嗎?

這方法適合軟體相關的所有領域、所有類型的產品與流程,其根本原因在於「需求的本質」都是一樣的,亦即「客戶的問題和價值」。

2. 瞭解客戶需求只能透過交談或是詢問進行嗎?

還有很多方法,例如問卷調查、自由發想、資料分析、資料探勘、競爭對手分析等,可以參考「需求分析理論」的相關書籍。但最常見、最有效以及最直接的方法還是和客戶交流。

3. 5W 和 8C 中的每個點,是否每次需求分析都一定要全部考慮?

實務上建議這樣做,即使某個點沒有涉及,就註明「沒有特別要求」。這個好處是,其他人不用擔心到底是忘記分析,或者是確實不涉及。

4. 是否每個需求都一定要寫一個使用案例?

不一定,只有那些關鍵、複雜、存在多個步驟或者互動的需求,才需要透過使用案例進行詳細分析。

 

總結


1. 「需求」是對客戶來說有價值的事情,功能是系統為了實現「需求」而具備的能力。

2.   修復「需求」錯誤的成本非常高。

3. 「需求分析」的目的是挖掘客戶的問題,實現客戶價值。

4. 「需求分析」方法:5W1H8C。

5. 「需求分析」階段不區分是物件導向還是程序導向。

6. 「使用案例方法」用於詳細分析 5W1H8C 中的 1H。

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

功能屬性:需求產生的環境要素

我們必須關注產生需求時的環境,因為環境會影響需求;所以要針對 5W 進行分析,這些都是需求產生時的關聯性因子。

When:和時間相關的環境資訊。

Where:和地點相關的環境資訊。

Who:和參與者相關的資訊,很多外部的參與者不一定是「人」,例如外部系統、動物等都包含在裡面。

常見的參與者資訊有:

  • *投資者、管理者;
  • *使用者、維護者;
  • *監督者、評估者,例如政府機構、監管機構等;

What:客戶最終想要的輸出。例如一個檔案、一份報告、一張圖片、一套系統等。

Why:客戶遇到的問題、困難與阻礙等,也是客戶提出需求的驅動力;只要是客戶覺得不爽,都屬於 Why 的範圍。

最關鍵的 W 就是 Why,只有真正瞭解客戶的需求驅動力,才能解決他們的問題;而只有解決客戶的問題,他們才會真正的滿意。

需要分析的終極目標就是「挖掘客戶的問題,實現客戶的價值!」

5W 分析沒有什麼具體的指導方法,主要依靠分析人員的經驗與水準。

 

功能屬性:需求的流程運作

1H代表 How,需求分析階段的 How 不是指如何實現需求,而是指需求本身的流程,如何實現是「設計階段」的事。

How 就是用來描述整個流程如何運作。

How 分析的結果是需求分析的主要輸出,其品質直接影響最後需求實作的品質。

How 分析有一套成熟的方法,就是「使用案例方法」。

 

品質屬性:8個約束與限制

8C 指的是 8 個約束和限制,具體如下:

「效能」是指系統提供對應服務的效率,包括回應時間和處理數量;效能是很多系統架構設計的關鍵約束之一。

「成本」是指為了實作系統而需付出的代價;例如客戶只願意付 20 萬購買這個系統,但我們卻設計一個耗費 50 萬的系統,客戶是不會買單的。

「時間」是指客戶要求系統何時交付。

「可靠性」是指系統長時間正確運行的能力,工業上對當機時間的要求十分嚴格。

「安全性」是指對資訊安全的保護能力。

「合規性」是指滿足各種行業標準、法規或規範等。

「技術性」是指客戶可能會要求在不同的軟體或硬體平台上開發,例如在 Windows 或 Linux 上開發,那就要依據客戶需求使用不同的平台技術。

「相容性」是指產品或系統與客戶既有的產品或系統的相容能力;新的系統必須能和已有的系統配合,否則將無法運行。

 

總結

需求分為「功能屬性」和「品質屬性」, 5W + 1H 屬於功能屬性,8C 屬於品質屬性。

能否正確地實現一個需求,既要看功能屬性是否正確,也要看品質屬性是否正確,兩者缺一不可。

例如:設計了一個功能強大的機器視覺系統,但動不動就當機,你覺得客戶會使用這樣的系統嗎?

 

 

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

需求詳解

對軟體專案來說,需求就是專案最一開始的輸入。

  • *需求:對客戶來說有價值的事情。
  • *功能:系統為了滿足客戶價值而提供的能力。

區別是需求還是功能的方式很簡單,只要判斷是否對客戶有價值。

舉例來說:影像處理軟體:「顯示影像」是需求,「讀取檔案」、「取得影像長寬」、「取得色彩位元」等是功能。


需求的重要性

很多專案開發都不怎麼重視需求!

一般可以經常看到這樣的場景:

  • *業務人員和客戶溝通,把客戶的要求簡單整理後,就交給研發人員了。
  • *專案時程比較緊湊,那就減少需求分析的階段吧。
  • *產品人員提出一個簡單的需求,為了能夠快速完成,沒有怎麼做分析就開始設計程式。

雖然看起來專案進度加快了,然而大多數的結果都是令人失望的;根據統計,有接近 1/3 的專案失敗或陷入困境,都是由於需求分析階段沒執行到位所導致。

如果最開始的輸入錯誤,不管中間的過程完成度再高,最終都會輸出垃圾產品,「Garbage in, garbage out」。

而且,修復需求錯誤的成本非常地高;假設在撰寫程式階段,發現和修復一個錯誤的人力是一個單位,那麼在測試階段修復需求錯誤的成本是 5 ~ 10個單位。

在維護階段 (產品正式上線後),修復需求錯誤的成本是 20 個單位;但如果在需求階段修復需求錯誤的話,成本只需要 0.1 ~ 0.2 個單位即可。

如果需求分析有錯,那麼幾乎要把軟體專案重做一次,因此修復成本非常昂貴。


需求分析

客戶會說他們的「需求」,但在大部份情況下都不會告知「需求」背後的問題。

需求分析的目的就是要「挖掘客戶的問題,然後實現客戶價值」;只有提供的東西能夠解決客戶的問題,客戶才會滿意。

客戶不會直接告訴我們「問題在哪」,例如客戶不會告訴我們「他想要顯示照片」,因為這是他的問題,不是他的需求。

「我需要一個影像處理軟體」才是需求,只是這個需求是用來解決客戶的問題的。

由於大部份客戶都會根據自己的經驗、知識、閱歷等,設計一個解決方案,然後作為需求提出來,因此深入了解客戶問題,才有助於更完善地實現需求。

需求分析有三重境界:「記錄員」、「分析員」、「引導員」。

記錄員:記錄客戶的需求。

分析員:和客戶一起分析問題,完善需求。

引導員:能夠引導客戶的需求。

 

要能發現客戶的問題,並引導客戶將需求調整為更合理的要求。

若想要做好「需求分析」,必須隨時抓住「客戶的問題和價值」這個指導原則。


需求分析的方法

在大多數公司裡,需求分析都是由經驗豐富的資深人員或是對系統很熟悉的資深開發人員擔任。

實際上只要掌握正確的方法,大部分的人都能做好「需求分析」。

總結起來就是「需求分析 518 方法」, 5W 1H 8C
 

  • *5W:When, Where, Who, What, Why.
  • *1H:How
  • *8C:8個 Constraint, 效能 (Performance)、成本 (Cost)、時間(Time)、可靠性(Reliability)、安全性(Security)、合規性(Compliance)、技術性(Technology)及相容性 (Compatibility)。

 

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

專案管理的流程主要指導專案經理如何管理專案,但對於指導開發人員如何開發專案,並無多大用處。

剛畢業的學生或許對「軟體工程」很熟悉,對各個開發階段應該做什麼,不同的開發流程有什麼優缺點,說的頭頭是道。

可是一旦參與專案開發後,便會有一種無從下手的感覺。

 

舉例來說:

  • 1. 需求分析階段要分析需求,但具體怎麼分析?
  • 2. 客戶的需求是描述語句,例如「我們需要一個影像處理的軟體」,而程式碼則是一個具體的類別和函式。那怎麼從描述語句轉化成具體的類別和函式呢?
  • 3. 具體的語言特性,例如 C++private, protected, public 等屬性是來自哪裡?該如何設計?
  • 4. 物件導向的類別、屬性、方法等,是怎麼設計出來的?

 

相信以上的問題都曾困擾著你我,但軟體工程並未給出答案,導致我們在實際開發過程中,只能在別人的設計與指導下工作,或是亂湊出能滿足需求的想法,至於效果,就得靠上天眷顧了。

有慧根的人,經過一段時間的磨練後,可能就漸漸掌握門道,但大多數的人可能就一直原地踏步,不斷地執行別人分配的工作內容。

其實,就像「專案管理」有一套完整的流程一樣,「專案開發」也有一套完整的程序。

對於物件導向來說,整個開發流程實際上非常清晰,底下我們將「瀑布模型」、「敏捷開發」等稱為『管理流程』;物件導向流程開發稱為『技術流程』。

 

物件導向的技術流程可以概括如下:

需求模型 → 領域模型 → 設計模型 → 實作模型

  1. 1. 需求模型:透過和客戶溝通,結合產業經驗和知識,明確地闡述客戶的需求。
  2. 2. 領域模型:根據需求模型,擷取出領域相關概念,為後面的物件導向設計打下基礎。
  3. 3. 設計模型:以領域模型為基礎,綜合物件導向的各種設計技巧,完成類別的設計。
  4. 4. 實作模型:以設計模型為基礎,將設計轉譯為具體的程式語言實作,完成程式碼撰寫。

 

技術流程環環相扣,上一步流程的輸入就是下一步流程的輸入。藉由這種 step by step 的方式,可以完成從需求到最後實作的相關工作。

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

類別


類別是物件導向領域裡最基礎的概念,也是物件導向分析和設計的基石。

所謂類別,就是站在個人的觀察角度,具有相似點的事物,就是同一類。


 

物件導向類別


物件導向的類別由兩部份組成:屬性方法

屬性:類別具有的特性
方法:類別具有的功能

實際設計程式時,可以用『屬性是名詞,方法是動詞』來判斷。

舉例來說:
這張數位影像的長度為 100 像素,寬度為 50 像素,色彩深度為 24 位元,這裡的長寬及色彩深度就是『數位影像』的屬性;

想獲取點位置在 X 50 像素,Y 在 20 像素的 RGB 彩色值,這裡的『獲取彩色值』就是『數位影像』的方法。

設計屬性的一個基本原則:屬性最小化原則,即『屬性不可再分』。

設計方法看似簡單,看到動詞就是一個方法,但實際操作遠沒這麼簡單。舉例來說:獲取彩色值用在 24 位元影像、32 位元影像跟 8 位元影像,都是同一個方法嗎?

如果都在同一個方法內,這個方法如何區分要獲取多少位元的數位影像呢? 只能增加一堆 if-else 來區分。 如果後續要新增獲取不同彩色空間的彩色值時,不就只能一直增加判斷式,變成大雜燴。

這裡引出設計方法的一個基本原則:方法單一化原則,即『一個方法只做一件事』。

範例程式碼:

 


 

物件


物件就是一個真實存在的類別,物件導向是對現實世界的模擬,那物件就是現實世界存在的『物體』。

真正在軟體運行過程的是『物件』,而不是『類別』。

『類別』是程式撰寫時,由程式人員分析歸納而來。

軟體類別:軟體設計過程中歸納總結出來的分類

軟體物件:軟體實際運行過程中存在的物件。

軟體類別是對現實類別的模擬,但不是簡單的等同。除了實作現實類別相對應的功能,還會創造出許多現實中不存在的類別。

這個創造過程正是各種設計方法設計模式設計原則大顯身手的地方。


 

抽象類別


抽象類別是一種特殊的類別,它只能用於繼承,不能用來產生實體為具體的物件。

為什麼需要抽象類別? 為何要設計一種只能繼承,而不能產生實體的類別?

設計的角度來看,抽象類別是根據類別抽象出來的,例如從鳳梨、芭樂、柳丁幾個普通類別,抽象出水果這個類別。但真的吃的時候,並沒有辦法吃的一個名為水果的東西。

實作的角度來看,抽象類別與實作類別的不同之處在於:有的抽象類別擁有抽象方法(方法只有宣告,沒有定義),子類別必須自己定義這些抽象方法,而不能像普通的方法一樣,透過繼承就能獲得父類別的方法。


 

物件導向的三大核心特徵


封裝繼承多型是物件導向的三大核心特徵,判斷一種程式語言是否為物件導向的程式語言,就看其是否支援這三大核心特徵。

封裝資料的主要原因是『保護隱私』。在程序導向的設計中,資料結構公開的,任何能取得資料的人都可以隨意修改,也允許以不同的方式修改。

如果資料被改錯了,那麼其他依賴此資料的函式會受到影響,甚至造成程式崩潰

物件導向的類別封裝屬性後,對屬性的修改只能透過類別的方法進行,一來不會曝露內部的具體屬性;二來對屬性都是統一的操作,不會出現亂修改的情況。

封裝方法的主要原因是『隔離複雜度』。每個類別只需要關注自己負責的功能如何完成即可,如果需要其他類別配合,僅需呼叫類別的方法,而不用瞭解其內部的具體實作

在現實世界中也常看到『隔離複雜度』的例子。例如想看電視只要輕輕一按搖控器按鈕,就可以看到電視節目的影像了,究竟電視機怎麼運作的,大多數人不知道也不關心。

讓我們用封裝範例來解釋『無封裝』的程序導向和『有封裝』的物件導向差在哪裡。

程序導向 = 演算法 + 資料結構

這裡的資料結構是公開的,每個地方都能看到和引用,否則程序導向中的各個處理流程就沒辦法處理。

實作程式碼如下:


物件導向 = 物件 + 互動

實作程式碼如下:

 



物件導向的封裝有三種方式


public
這種方式就是不封裝,直接對外公開

protected
這種封裝方式對外不公開,但對朋友(friend)子類別公開。

private
這種封裝方式對誰都不公開。


 

繼承


繼承是物件導向語言最基本的特徵,如果一種語言沒有繼承機制,就說不上是真正的物件導向語言。

在物件導向中,繼承的實際意義可以用遺傳來形容,程式設計師決定父類別遺傳什麼給子類別。


 

多型


在物件導向領域中,多型的真正涵意是:使用指向父類別指標參照,便能呼叫子類別物件

以下用實作程式碼來說明:


多型的特性,在物件導向程式設計領域具有十分重要的作用。多型遮罩了子類別物件的差異,允許呼叫者寫出通用的程式碼,而無須針對每個子類別撰寫不同的程式碼。

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

常見的 C 語言是屬於程序導向結構化程式設計的概念,採取『自上而下逐步細化模組化』的方法,將軟體的複雜度控制在一個範圍內,從而降低軟體發展的複雜度,因此 C 語言成為 20 世紀 70 年代軟體發展的潮流。

隨著硬體的快速發展,業務要求越來越複雜,而且程式設計應用領域越來越廣泛,結構化程式設計的軟體生產力遠跟不上硬體和業務的發展。

因為結構化程式設計的方式無法滿足軟體『可擴充性』和『可維護性』的需求,因此物件導向的概念才開始普及。從 C++ 到後來的 JavaC# 把物件導向推向巔峰。

和程序導向相比,物件導向的概念更加貼近人類思維的特點,這也是軟體設計的一次重大突破。


 

程序導向簡介


程序導向是一種以『程序』為中心的程式流水線設計概念,其中最中要的就是『完成一件事情的步驟』。這是一種機械式的邏輯,每個階段都有自己的輸入資料處理單元輸出資料

在程序導向中,我們需要將程式分成不同的處理單元,然後設計不同單元該如何銜接,並定義每個單元的輸入及輸出資料類型。

程式設計人員應該都聽過「程式設計 = 演算法 + 資料結構」,這其實就是程序導向的概念,而這種特徵其實和電腦的本質相關,其核心 CPU 處理指令的方式就如同流水線一樣,所以電腦是以程序導向為基石來進行處理。

即使我們使用物件導向語言來進行程式開發,但它最後還是要轉換成 CPU 能執行的指令,依舊屬於程序導向。


 

物件導向簡介


物件導向是一種以『物件』作為中心的程式設計概念,著重在對現實世界的模擬

跟程序導向不同,物件導向的方法中沒有主要控制的角色,也不需要指定嚴謹的操作順序,而是以物件為主體,指定這些物件完成任務,以及這些物件如何對外界的刺激做出反應。

人們大多是按照物件導向的方式進行思考,所以物件導向更加符合人類的思維習慣。

在物件導向的程式設計中,「程式設計 = 物件 + 互動


 

為什麼需要物件導向?


由於程序導向是電腦運行的基石,因此目前 C 語言作業系統協定堆疊驅動程式,依然還是程序導向的天下。

但程序導向有著先天性的不足,那就是流程結構相對固定,雖有效率但其擴充比較麻煩。每次需求的變更,都要對流程的每個步驟、中間的進出的資料結構進行修改。

物件導向是為了解決程序導向的『擴充性』問題而誕生的,因此物件導向的最大特徵就是『可擴充性』。要將變化帶來的影響控制在有限的範圍內,避免產生全流程或大範圍的影響,降低開發上的風險

因此,經常發生變化的地方就是物件導向的發威之處,常見及可變的主要集中在客戶需求部份,不變的一般都屬於電腦系統的基礎

作業系統、資料庫及協定等,相對穩定而且要求高效率,因此較適合程序導向;而企業應用、網際網路或遊戲等應用,需求經常變更且功能不斷擴展,適用物件導向的概念。

效能要求很高的系統軟體,基本上都是利用 C 語言寫的,例如作業系統、驅動程式、嵌入式軟體及網路設備等。


 

物件導向語言不等於物件導向程式設計


C 語言是純粹的程序導向的程式語言,但不代表用 C 語言撰寫程式就是程式導向程式設計,利用 C 語言一樣可以寫出物件導向的程式。

同理, Java 是純粹的物件導向程式語言,但也可以用 Java 寫出程序導向的程式。

程序導向和物件導向都是一種思維方式,它是一種思考問題的方法,和具體的語言沒有必然的關係。

舉例來說,在 Java 中寫程序導向的程式碼,最簡單的方式是撰寫一個大類別,內含很多方法,然後在 main 函式裡面按照程式導向的方式呼叫即可。


 

重點摘要:


1. 程序導向是一種「機械的思維」。
2. 物件導向是一種「人類的思維」。
3. 物件導向適合解決軟體的「可擴充性」問題。
4. 物件導向程式語言不等於物件導向程式設計。

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()

在開始寫實戰系列之前,先說明一下主要用到的參考書籍

1. 如何用物件導向實作複雜的業務需求

2. C++ API 設計

3. 自行編寫的講義

我們常常使用別人設計好的 API 來使用,這符合現代軟體設計的概念,利用軟體元件拼湊組合出新的功能,不做重覆的事。

在實務上,為了求快,工程師們常知其然不知所以然,反正呼叫 API 能動或能給出想要的結果就好。但這樣的想法到底是讓軟體設計變的更輕鬆,還是入門容易熟練難呢?

我游走教育的第一線時,其實也碰到類似的問題,當學校在教理論課程時,實作部份是直接呼叫別人已經設計好的函式庫,這中間會有個很大的學用落差,那就是學這麼多幹嘛?會呼叫函式庫就好。

但真的這樣就夠了嗎?中間跳過了甚麼?那就是這個軟體元件為何要這樣設計,它隱含的分析及設計流程全部跳過,如果一昧地只會用別人設計好的東西,那當遇到的非典型情況時,自己又該怎麼處理呢?等待別人出手救援?

倒也不是說甚麼東西都要自己重新設計,這樣太沒效率也不符合現代軟體設計原則,但最起碼還有機會當學生上課或自己下班進修時,能多一點耐心去了解常用到的工具軟體從何而來。

當你邊上理論課程,然後自己又有能力設計出基於理論的實用軟體工具,並分享給其他人使用時,豈不是更滿足也更有成就感!

上面講的扯遠了,很像老學究在講的話,事實上以我的話來說,撇開實用性的問題,能自己設計軟體就是

人在兩種情況下會特別開心,一是自己在創造東西、二是自己有在成長進步。

當我在設計軟體,學習新技術時,特別開心,因為同時滿足前面說的兩種情況,所以就是爽。

話說回來,如果又爽又能夠幫到別人的忙,然後自己也能有正向回饋,那就是爽上加爽,這種事為何不做?

所以呢? 開這個實戰系列,或許短期看起來是有點浪費自己的時間,然後壓力大又累,但長遠來看絕對是利大於弊

如果有聽過費曼學習法的人,一定對我現在的所做所為不陌生,要怎麼自主學習,設定目標並想辦法提升自己的能力到可以教人為止。

自主學習難就難在怎麼幫自己設定目標,跟工作或唸書不同,不管是工作或唸書都是在別人設定的框架下被動學習,但要主動去學習就得有很強烈的動機,我寫實戰系列就是希望幫自己創造動機,讓我有機會能夠主動學習

對我來說是如此,希望對在讀這些文章的同學們,也能有一樣的感受。

一起加油!

 

文章標籤

OtakuYeh 發表在 痞客邦 留言(0) 人氣()