假設今天要設計一個貼文的系統,一則貼文有內容跟作者,具有草稿狀態與發布狀態,並且有修改與確定內容的功能
物件導向建模
我們會建立一個貼文的物件,這個物件中具有一些欄位可以儲存貼文需要的資料,並且本身具有一些對這些內容編輯的方法,我們會把相關的資料與邏輯放到單一的物件中。
public class Post
{
// 貼文具有一些欄位
public string Author { get; set; }
public string Content { get; set; }
public string Status { get; set; }
// 貼文可以編輯自身的內容
public void Edit(string text) => // 編輯內容
public void Confirm() => // 確認內容
public void Release() => // 發布內容
}
函數導向建模
我們可以針對Post寫擴充方法,要注意的是前面的方法使用void直接修改內容,而這邊使用record,並且方法會回傳一個修改過後的貼文。
public record Post(string Author, string Content, string Atatus)
// 針對record型別寫擴充方法
public static class PostExtension
{
public static Post Edit(this Post post, string text) => post with { Content = text };
// 省略其他方法
}
在FP裡面,我們可以將方法作為靜態類別的成員,實現模組的功能,像是C#中的Math
類別就可以視為一個模組,當需要使用的時候用using載入,接下來介紹兩個C#的功能
using static :
應該很多人已經知道,但實際上不常使用,當我們使用using static陳述式時,就可以將靜態類別的成員載入,這個功能對於FP來說能夠更方便使用模組的內容。
Interface Properties:
C# 8.0開始,介面可以有屬性,這個功能也可以解讀成對FP的支援,我們希望能夠將資料與函數模組分開,而介面屬性定義了資料的特徵,並且保留了型別的彈性。舉例來說,我可以將具有發布的功能交由IRelease
的介面達成,只要資料中具有表示狀態的status欄位,就可以擁有發布的功能,而後續如果希望有發布相本的功能,也可以用模組中相同的方法。
public interface IRelease { public string status { get; set; } }
public class Post : IRelease
{
string Author { get; set; }
string Content { get; set; }
string Status { get; set; }
}
public class Album : IRelease
{
string Author { get; set; }
Photo Photo { get; set; }
string Status { get; set; }
}