C# オブジェクト初期化子でプロパティのプロパティを初期化

C#でオブジェクト初期化子という構文があります。
オブジェクトの作成時にアクセス可能なプロパティやフィールドに値を割り当てるもので、
例えば次のように書きます。

var person = new Person() {
    Name = "Taro",
    Id = 1,
};

これは以下と同等です。

var person = new Person();
person.Name = "Taro";
person.Id = 1;

メリットは初期化の内容が1箇所に集まることで、
初期化中に間違って別の処理が混入することが無いことです。
なので積極的に利用すべきですね。

初期化できるのはアクセス可能なメンバーに限定されるので、
例えば以下のケースはコンパイルエラーとなります。

var parent = new Parent() {
    Person = new Person(),  //Person プロパティはsetできないのでコンパイルエラー
};
class Parent {
    public Person Person { get; } = new Person();
}

class Person {
    public string Name { get; set; }  //プロパティ
    public int Id;  //フィールド
    public List<int> RelatedId { get; }

    //コンストラクタ
    public Person() {
       RelatedId = new List<int>() { 1 }; //要素"1"で初期化
    }
}

Parentオブジェクト初期化子内で、
Personプロパティのプロパティを設定したい場合は以下のように書きます。

var parent = new Parent() {
    Person = { Name = "Taro", Id = 1 }
};

ではList<int>に値を指定した場合はどうなるでしょうか?

var parent = new Parent() {
    Person = { Name = "Taro", Id = 1, RelatedId = {10, 20}}
};

RelatedIdはコンストラクタで初期化された値に値が追加され、
この場合、要素が{1, 10, 20}の要素数3のコレクションとなるようです。
あまり使いどころは無いかもしれませんが、覚えておくとどこかで役に立つかもしれません。

ソフトウェアの完成

製作しているソフトウェアが完成すると嬉しいものです。
でも完成のタイミングとはいつなのでしょうか?
実装が全て完了して、
仕様を満たしているか、動作は問題無いか等の確認を行い、
全て合格した場合に完成となります。

ただ動作テストの時にいろいろ気付くこともあり、
そのときに「この部分は使い勝手が悪い」「もっとこうしたほうが良い」など、
特にUI(ユーザーインターフェース)周りで改善案が浮上します。
私の場合はこの時点で挙がった改善案をtodoとして、
それらを解決した時点で完成としています。

デザインやUIの部分は、想定する使い方が変わると、
「使いやすさ」を実現する方法も変わってしまいます。
これらの全て実装すると開発期間やコストをオーバーしてしまいますので、
まずは普通の使い方で不便を感じない実装が重要だと考えています。

それでも「期待以上だった」とお客様に言って頂けるような、
そんなソフトウェアを目指しています。

C# のコーディング規則

C# のコーディング規則
Microsoft公式ドキュメントに「C# のコーディング規則」が追加されました。
2021/5/14 の新しい内容です。

この記事のガイドラインは、サンプルおよびドキュメントを開発するために Microsoft によって使用されます。これらは、.NET ランタイムの C# コーディング スタイル ガイドラインから採用されました。それらを使用することも、ニーズに合わせて調整することもできます。 主な目的は、プロジェクト、チーム、組織、または会社のソース コード内での一貫性と読みやすさです。

とあるように、Microsoftでも使用される内容なので、
コーディング規則はこれをベースにするのが良さそうです。
フィールドはキャメルケースに_プレフィクスを付ける事が明文化されています。

  • private または internal のフィールドに名前を付ける場合は、キャメルケースを使用し、_を使用してプレフィックスを付けます。
  • ステートメント補完をサポートする IDE でこれらの名前付け規則に従う C# コードを編集するときは、「_」と入力すると、オブジェクト スコープのすべてのメンバーが表示されます。
  • なので自動実装ではないプロパティを使用する場合、
    バッキングフィールド名はプロパティ名の先頭を小文字にして_プレフィックスを付けたものになります。

    あと気になった点は、次のような点でしょうか。
    コメントは文章で書くようにという事ですね。

  • private または internal である static フィールドを使用する場合は、s_プレフィックスを使用し、スレッド静的には t_を使用します。
  • コメントのテキストはピリオドで終了します。
  • もちろん最初に書いてあるように、この規則はニーズに合わせて調整することもできますが、
    基本の規則として知っておくと良いと思います。

    PlantUML を試してみました。

    5月の連休を利用して、UML図の作成にPlantUMLを試してみました。
    VSCode + 拡張機能の流行りの組み合わせです。
    普段は別の専用ソフトを使っているので、
    テキストベースで図を作成するのは、個人的には初めてです。

    練習に社内の研修用ソフトのシーケンス図を作成してみると、
    予想以上に簡単に作成することができました。
    テキストベースなので要素の配置などレイアウトを考える必要もなく、
    シンプルに書きたい事を書くことができる印象です。

    ほんの些細な事でも考える事が少なくなると、
    やりたい事がよりはっきり見えてくるのを実感しました。
    プログラムのソースコードを書くときでも、
    スコープは狭くする、ネストを深くしない、メソッドは小さく分ける…など、
    余計な事を考える余地が少なくなるよう工夫したいと思います。

    読みやすいコード

    コードは理解しやすくなければならない。
    「リーダブルコード」にもそう書かれています。

    他の人が読みやすいかどうかというのはとても重要な事だと思います。
    適切な変数名やメソッド名は理解を助けますし、
    説明変数なども積極的に利用するようにしています。
    書き方ひとつとっても、
    例えば変数を宣言して anotherClass のみ遅延した初期化が必要な場合、

    var myClass = new MyClass();
    var yourClass = new YourClass();
    AnotherClass anotherClass;

    と書くよりは、

    var myClass = new MyClass();
    var yourClass = new YourClass();
    var anotherClass = default(AnotherClass);

    と書く方が、それぞれの変数の位置が揃っていて、
    読みやすいのではないでしょうか。
    気取らず、気の利いた美しいコードを目指したいと思います。

    C#9.0 record

    C#9.0でrecord型が追加されました。
    まだ実務では使用していませんが、
    今後C#でとても重要な機能になると思っています。

    最も活躍できるのが、DDDのValueObjectでしょうか。
    今まではそれらしい事をするには等値性を表現する為に、
    Equals()やGetHashCode()をoverrideする必要がありましたが、
    record型はコンパイラが自動で行ってくれます。

    そして定義がとても簡単に行えます。
    Microsoftの説明を引用すると、

    public record Person {
     public string LastName { get; }
     public string FirstName { get; }
     public Person(string first, string last) => (FirstName, LastName) = (first, last);
    }

    と同じことが、

    public record Person(string FirstName, string LastName) { }

    と書けます。とても簡潔ですね。

    リファクタリング

    既存のソースコードに新しい機能や変更を加えようとするとき、
    まず既存のコードをリファクタリングします。
    そして切り出したり共通化したクラスやインターフェースなどを、
    ソリューションやプロジェクト内のどこに記入するべきか考える必要があります。

    全体の設計思想や、選択したフレームワークによって、
    適切な場所があるはずですが、なかなか上手く収まらない事もあります。

    そのような場合は、自分が全体の設計思想に対する理解が足りていないか、
    ソリューションやプロジェクトが上手く構成できていない事がうかがえます。

    リファクタリングは基本的には必要な時に行いますが、
    例えばテストファースト開発のように、
    開発サイクルの中で常時行う方法もあります。

    年末の大掃除と同じように、まとめて後でやろうとすると大変です。
    普段から少しずつ行っていればリスクも少なく、
    ソリューションやプロジェクトの構成もより明確になってゆくものだと思います。

    リファクタリングであまり悩むことが無いよう、
    安心して開発できる環境を目指したいと思います。

    デザインパターン

    GoFの23のデザインパターンを学習しています。
    デザインパターンの多くは、
    抽象的な概念を抽象クラスやインタフェースで定義して、
    継承や実装により、実クラスで表現する手法を取ります。

    デザインパターンを知ると設計の幅が広がるとともに、
    ソースコードを読むときの理解の助けにもなると思いました。

    例えばiPhoneで使われるviewには、
    Observerパターンが使われているものがあります。
    Observerパターンを知っていればすぐに理解できますが、
    知らないと概念の理解に少し苦しみます。

    チームで開発を行う場合でも、
    「ここはSingletonパターンを使おう」など、
    言語を問わずに共通の概念を共有することができるので、
    連携がスムーズにできそうですね。

    Microsoft Code Analysis

    自宅で使用している Visual studio に、
    「Microsoft Code Analysis」を導入してみました。
    VSの拡張機能から簡単にインストールすることができます。
    コードの問題を検出して、改善・修正の提案を行ってくれるので、
    初学者の方にもおすすめです。

    例えば次のような冗長なコードを書いてしまった場合でも、
    if(isDebug == true){ ...
    コードを簡単にできる旨をヒントや警告で表示してくれて、
    クリックで修正する事ができます。
    if(isDebug){ ...
    他にも private にできるメンバーを教えてくれたりなど機能が豊富で、
    自然と Microsoft が推奨する、一般的なコードを書くことができるようになります。

    会社では ReSharper を使用しているので必要無いのですが、
    自宅でも同様の分析機能があると少し安心します。

    Xamarin の開発環境

    弊社では Xamarin を用いてモバイルアプリも開発をしております。
    Xamarin はC#で iOS/Android などのモバイルアプリが開発できる、
    モバイルアプリ向けのクロスプラットフォーム開発環境です。

    ただし例えばiOSアプリをWindowsで開発する場合でも必ずMacが必要で、
    Mono、Xcode、Visual Studio(Mac)、Visual Studio(Win)、Xamarin などの、
    使用するソフト間のバージョン関係がとてもシビアです。

    先日 Visual Studio(Win) Ver16.6 にアップデートした際に、
    ビルドができない状態となり、原因の特定に時間が掛かってしまいました。
    結局は Visual Studio の問題で Ver16.6.1 で修正されたのですが、
    これを機に Visual Studio(Mac) による専用の開発環境を整えて、
    開発時のソフトウェアバージョンをある程度固定する事にしました。

    Windows と Mac 間の通信が不要となり、
    ビルド速度が向上し、デバッグも安定するようになりました。
    普段は Visual Studio(Win) で開発を行っておりましたので、
    Visual Studio(Mac) やショートカットに慣れていこうと思います。