自分のブログ名

sheephumanのブログ

ひつじ好きな人間のブログ。

C# ドメイン駆動設計(DDD)とは何か

21/03/11 表示がおかしかったのを手直し。ソースファイルを上げた。MarkDownは編集しにくい。



 ドメイン駆動開発とも言われている、ソフトウェア開発手法の僕なりの理解です。 以下の講座を履修して学びました。

C#でドメイン駆動開発パート1【C#でドメイン駆動開発とテスト駆動開発を使って保守性の高いプログラミングをする方法】 | Udemy



自分で作成したソースプロジェクト

※1 全く同じではありません。かなり手抜きをしてる。一応動きます。
※2 DbはPupsSQLite(http://www.eonet.ne.jp/~pup/software.html)で作りました。
※3 どうしても動かないという方は参考にするのもいいかもしれません。自力で組んだ方がいいけどね。
※4 ファイル内に同梱しているDDD2.dbをデスクトップに置かないと動作しません。

f:id:sheephuman:20210311193420p:plain


drive.google.com


















 具体的な構成

大まかな説明です。

f:id:sheephuman:20201027111039p:plain
DDDの層構造

View(UI)

普通にフォームですね。WeatherLatestViewとしています。
f:id:sheephuman:20201027102721p:plain

ViewModels 



public partial class WeatherListView : Form
{
 private WeatheListViewModel _viewModel = new WeatheListViewModel();
 public WeatherListView()
{
  InitializeComponent();

  WeathersDataGrid.DataBindings.Add("DataSource", viewModel,nameof(viewModel.Weathrs));
   //DataGridViewです。
}
}



そうですね!

www.youtube.com



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上でプロジェクトファイルを作り、フォルダ分けして管理していく事でコーディングルール・プログラミングの方針を確定させ、円滑な作業を行っていくという事を可能にします。