發表文章

[C#] 初探 XUnits

Unit Testing with xUnit 單元測試以前都沒寫過,上次去外面上課,稍微接觸一下。由於最近在網路上買了一本 .Net Core 來看,感覺 Unit Test 是一個好東西。 所以,我得做一點筆記,紀錄一下,不然哪天又忘了。 Unit Test 在軟體工程中,有一個 SRP Pattern ,大意是盡量讓一個類別維持單一原則,不要做太多事。這時候,我們就可以透過單元測試,來個別驗證這些類別與功能。 單元測試可以提高軟體的可靠度,減少將來軟體釋出時,帶來的一些臭蟲。 Business day Calculator Example 書上給了一些範例,就套用這範例,紀錄下去吧! 透過 VS 建立一個空方案(BusinessDays),接著新增一個 Lib 專案(BizDayCal),在新增一個 xUnit 專案(BizDayCalTests)。 BizDayCal namespace BizDayCal { using System; using System.Collections.Generic; public class Calculator { private List<IRule> rules = new List<IRule>(); public void AddRule(IRule rule) { this.rules.Add(rule); } public bool IsBusinessDay(DateTime date) { foreach (var rule in rules) if (!rule.CheckDate(date)) return false; return true; } } } namespace BizDayCal { using System; public Interface IRule { bool CheckDate...

[C#] API 設計規則

API 設計規則 先前看了一篇文章,在講述 API 的設計理念,方法與規則,分為三個階段。算是一篇不錯的文章,很實用的,於是就做了點筆記,把重要的內容記錄下來,提醒自己將來好遵守。 基礎 : 考慮用詞與語法一致 API 的命名拼寫要正確。 準確的用詞。(正反義詞不可混用。) 注意單複數。 不要誤用詞性。 (例如 : Success/Failure<名詞>,Succeed/Fail<動詞>,Successful/Failed<形容詞>) 處理縮寫。(Pascal 與 Camel 命名方式) 用對時態和語句。(盡量避免使用被動語句) 進階 : 多思考語義與可用性 單一職責原理。(SRP,一個類別或是方法,只專職做一件事就好) 避免副作用。(Expected 與 OCP,當類別擴充時,不會影響到原生的系統結構,要與預期的結果相符。) 合理的設計函數參數。(相關性越高的參數,越要將參數前置,或是將同類型的參數整合到所傳遞的物件中。) 合理的運用函數多載。(Overload。Hint : 當傳入的參數,無法進行有效區分時,建議不要選擇多載) 一致性的術語表 遵循一致性的 API 風格 Note : 一致性可以最大化程度的降低 訊息熵 一致性範例 -------------------------------------- pic | 圖片 | image, picture -------------------------------------- path | 路徑 | URL,url, uri -------------------------------------- on | 事件綁定| bind, addEventListener -------------------------------------- off | 解除綁定| unbind, removeEventListener ------------------------------------------- emit | 觸發事件| fire, trigger -------------------------------------- module| 模組 ...

[C#]C# Coding 規則

C# Coding 規則 標示符命名規則 標示符是指變數,類別或是結構,和類別與結構的成員的變數名稱。 必須以字母或底線開頭。 不能將關鍵字作為標示符用,如果需要,則須在標示符號前,加上前綴字符 @ 。 標示符也可以包含 Unicode。 命名規則 一般對於變數或是類別方法名稱的宣告,或將該宣告的變數,以有意圖的方式來命名。(單字組合) 一般命名的規則可分為兩類,一個是 Pascal ,另外一個則是 Camel。 Pascal : 大小寫形式,每個單字開頭皆為大寫,一般 Pascal 大都使用在 非參數 的宣告,即類別名稱、方法,屬性等。 例如 : class Person。 ToDoSomething()。 public int Age {get;set;}。 Camel : 開頭的單字為小寫,而後整個單字組開頭皆為大寫,一般用在傳遞參數或是宣告變數上使用。有時候,有些人的宣告的變數前面會加上底線。 一般都是私有成員使用 Camel 傳遞給方法的所有名稱都應該是以 Camel 形式 透過 Camel 也可以使用大小寫來區分兩個不同的對象。 例如: private string name; private string firstName; private string lastName; private string _name; ... class Person { private int _name; public Person(string name) { this._name = name; } } ... private int _age; public int Age { get {return _age;} set { _age = value;} } 命名風格 命名的風格名稱最好要一致。例如 : ShowConfig(),EditConfig()。 命名空間的名稱 MS 有建議命名空間的法則,即 . 。 命名名稱和關鍵字 兩者不應該互相衝突。

[Design-Pattern] Observer Pattern

Observer Pattern - 觀察者模式 目的 : 處理一個物件對應多個物件之間的連動關係。類似 Mqtt sub/pub 當一個觀察者物件(Subject)改變時,其他的觀察者物件(Observer)都會收到通知,並執行對應的動作。 善用抽象類別 Subject public abstract class Subject { protected List<Adventurer> adventurers = new List<Adventurer>(); public void add(Adventurer adventurer) { Console.WriteLine($"{adventurer.Name} subscribe the topic!"); adventurers.Add(adventurer); } public void remove(Adventurer adventurer) { adventurers.Remove(adventurer); } public abstract void sendQuestion(string msg); } Association public class Association : Subject { public override void sendQuestion(string msg) { foreach (var adventurer in adventurers) { adventurer.getQuestions(msg); } } } Adventurer public abstract class Adventurer { public string Name; public ...

[Design-Pattern] Decorator Pattern

Decorator Pattern - 裝飾模型 Decorator Pattern 也可以稱作 Wrapper Patter。 優點 1. 動態新增功能至已存在的類別 2. 另一種子類別(抽象類別) 3. 支援開閉原則 何時去使用 1. 大型系統(Legacy System) 2. 控制項(Controller) 3. Sealed Class 介面 public interface ICar { double GetCost(); string GetName(); } 被裝飾者類別 (Component) public class Car:ICar { public double GetCost() { return 600000; } public string GetName() { return "Car"; } } 抽象類別 public abstract class DecoratorAccessoryCar : ICar { private readonly ICar _car; public DecoratorAccessoryCar(ICar car) { this._car = car; } public virtual double GetCost() { return this._car.GetCost(); } public virtual string GetName() { return this._car.GetName(); } } 裝飾類別 (Decorator) public class BasicAccessories : DecoratorAccessoryCar { ...

[Design-Pattern] Strategy

策略模式 - Strategy Pattern 目的 : 將各種可以互換的演算法(策略)包裝成一個類別 排序策略 父類別 先宣告一個父類別 public enum Color { Black, White, Blue, Gray, Red } public class Car { public readonly int Price; public readonly Color CarColor; public Car(int price, Color color) { this.Price = price; this.CarColor = color; } public override string ToString() { return $"Price : {Price}, Color : {CarColor}"; } } 繼承 Comparer 透過繼承範型的 Comparer ,來實作排序演算法。 public class SortByColor : Comparer<Car> { public override int Compare(Car o1, Car o2) { if (o1 == null || o2 == null) throw new ArgumentNullException(); return (o1.CarColor > o2.CarColor) ? 1 : (o1.CarColor == o2.CarColor) ? 0 : -1; } } public class SortCarByPrice : Comparer<Car> { public ove...

[Design-Pattern] Abstract Factory Pattern

抽象工廠 - Abstract Factory 目的 : 用一個工廠介面來生產一系列相關的產物,但實際建立那些物件由實作工廠的子類別來實現 建立抽象工廠(抽象類別) public enum CarColor { White, Black, Blue, Gray } public enum CarType { Sedan, Coupe, Wagon, Suv, Convertible, HatchBack, Limousine, Van } public abstract class Car { private CarColor _carColor; private CarType _carType; public abstract void Display(); public abstract void SetCarColor(CarColor color); public abstract void SetCarType(CarType type); public CarColor Color { get => this._carColor; set => this._carColor = value; } public CarType CTYPE { set => this._carType = value; get => this._carType; } } 實作抽象工廠 public class Honda : Car { private static string Vendor = "Honda"; public Honda() ...