21/03/11 表示がおかしかったのを手直し。ソースファイルを上げた。MarkDownは編集しにくい。
ドメイン駆動開発とも言われている、ソフトウェア開発手法の僕なりの理解です。
以下の講座を履修して学びました。
C#でドメイン駆動開発パート1【C#でドメイン駆動開発とテスト駆動開発を使って保守性の高いプログラミングをする方法】 | Udemy
自分で作成したソースプロジェクト
※1 全く同じではありません。かなり手抜きをしてる。一応動きます。
※2 DbはPupsSQLite(http://www.eonet.ne.jp/~pup/software.html)で作りました。
※3 どうしても動かないという方は参考にするのもいいかもしれません。自力で組んだ方がいいけどね。
※4 ファイル内に同梱しているDDD2.dbをデスクトップに置かないと動作しません。
ドメイン駆動開発は細分化。
TempはTemperture型のメンバ変数で、そこからTempertureクラス内にあるDisplayValueを呼ぶ。 pic.twitter.com/fxIyT7v6Am — ひつじ人間 (@sheephuman) 2020年10月13日
ドメイン駆動開発(設計)
読んで字のごとく、プロジェクト内にドメインを作る事。ドメインとはエリア(区分)みたいなもので
・ViewModel とか ・updateHelperとかで名前空間、フォルダ分けを徹底して、依存関係を明確にするという開発手法.....だと思う。 作るとこんな感じになるよ(Csharp) pic.twitter.com/V49En5n0Js — ひつじ人間 (@sheephuman) 2020年10月11日
これにはテスト開発の手法も含まれていて
超絶めんどくさがりの初心者(自分)は、いちいち別の書き方を試してはコメントアウトしてってのを繰り返して可読性を落としていくけど、それをMoq(ダミーデータ)をちゃんと用意して一つ一つテストしていく事で、最終的に効率も上げていく手法なんだね(多分 — ひつじ人間 (@sheephuman) 2020年10月11日
具体的な構成
大まかな説明です。
View(UI)
普通にフォームですね。WeatherLatestViewとしています。
ViewModels
public partial class WeatherListView : Form { private WeatheListViewModel _viewModel = new WeatheListViewModel(); public WeatherListView() { InitializeComponent(); WeathersDataGrid.DataBindings.Add("DataSource", viewModel,nameof(viewModel.Weathrs)); //DataGridViewです。 } }
そうですね!
Entityクラス
Entityとはクラスに渡す変数の集まりで、完全コンストラクタパターンで定義しておきます。
public sealed class AreaEntity { public AreaEntity(int areaId,string areaName) { AreaId = areaId; AreaName = areaName; } public int AreaId { get; } public string AreaName { get; } }
笑う所
www.youtube.com
明確に変数の役割が決まっている場合は、新しく専用のクラスを作り、そこにまとめて変数を格納しておきます
public AreaId AreaId{ get; } public DateTime Date { get; } public Condition Condition { get; } public Temperture Temp { get; } public string AreaName { get; set; }
また、ValueObjectクラスを作り、各Entityクラスに継承させておきます。
public abstract class ValueObject<T> where T : ValueObject<T> { public override bool Equals(object obj) { var vo = obj as T; if (vo == null) { return false; } return EqualsCore(vo) ; } public static bool operator ==(ValueObject<T> vo1, ValueObject<T> vo2) { return Equals(vo1, vo2); } public static bool operator !=(ValueObject<T> vo1, ValueObject<T> vo2) { return !Equals(vo1, vo2); } protected abstract bool EqualsCore(T other); public override int GetHashCode() { return base.GetHashCode(); } public override string ToString() { return base.ToString(); } }
この実装により、変数を渡した際の同一性が保証されます。
↓Temperatureクラスの操作はUI側では行わず、クラス側のみで行います
クラス内部でさらにFloatHelperを呼び出し、とにかくEditする層の細分化を図っています
public class Temperture : ValueObject<Temperture> { public const string UnitName = "℃"; public const int TemperatureDecimalPoint = 2; public Temperture(float value) { Vaiue = value; } public float Vaiue { get; } public string DisplayVaiue { get { return FloatHelepr.RoundString(Vaiue,TemperatureDecimalPoint); } } public string DisplayVaiueWithUnit { get { return FloatHelepr.RoundString(Vaiue, TemperatureDecimalPoint) + UnitName; } } public string DisplayValueWithUnitSpace { get { return FloatHelepr.RoundString(Vaiue, TemperatureDecimalPoint) +" "+ UnitName; } } public string DisplayValue { get; set; } public int DecimalPoint { get; private set; } protected override bool EqualsCore(Temperture other) { return Vaiue == other.Vaiue; }
まとめ
このように細分化を行っていくと、やや手間がかかるものの、バグの少ないCodingを自ずと強制することになります。
初心者は全てViewModel側(Form側)でコーディングするという事をやりがちですが、Visual Studio上でプロジェクトファイルを作り、フォルダ分けして管理していく事でコーディングルール・プログラミングの方針を確定させ、円滑な作業を行っていくという事を可能にします。