No more Death March

あるSEのチラシの裏 C# WPF

c# リフレクションの使いどころを考える

ソフト全体で使いたいインターフェースがある時、
インターフェースとその実装を同じプロジェクトに入れると実装部分をメンテナンスする度に大規模なビルドが必要になる。

そもそも抽象(インターフェース)に依存して処理を標準化するのに実装を直す度にビルドが走るのはおかしな話。

それを回避する方法として、インターフェースと実装を分離し、UnityなどのDIを使うのも良いのだけど、
粒度の小さく凝集度の高いものを毎回DIで実現しようとするとDIのためのコーディングだけで手間がかかってしまう。

そこでリフレクションを使ってインターフェースが宣言されているプロジェクト内でリフレクションを使って実装クラスのアセンブリを読み込んでしまう。

プロジェクトの依存関係は実装⇒インターフェースの向きなので依存関係に逆転した読み込みが行われることになる。

一見するとおかしな考え方に思えるが、こうすることによって実装以外のインターフェースに依存するプロジェクトから
インターフェースの実装プロジェクトに対する依存を完全に排除することが出来るし、実装をチューニングしたりリファクタリングしても、
クライアントプロジェクトのビルドが実行されることはなくなる。

ステートソーシングな設計をイベントソーシングな設計に

ステートソーシングな設計の「商品テーブル」をイベントソーシングな設計に置き換える時のイメージをメモ

「商品テーブル」
・ID
・コード
・名称
・登録担当者ID
・登録日時
・更新担当者ID
・更新日時
・削除担当者ID
・削除日時

手順1)ドメインに関する出来事を箇条書きにする

・新しい商品を登録した。
・商品の名前を変えた。
・商品のコードを変えた。
・商品を削除した。

手順2)出来事をテーブルに置き換える

・「商品が登録されましたテーブル」
・「商品の名前が変わりましたテーブル」
・「商品のコードが変わりましたテーブル」
・「商品を削除しましたテーブル」

手順3)各テーブルの列構成を考える。

「商品」
・ID

「商品登録されましたテーブル」
・ID
・商品ID
・担当者ID
・発生日時

「商品の名前が変わりましたテーブル」
・ID
・商品ID
・新しい商品名
・担当者ID
・発生日時

「商品のコードが変わりましたテーブル」
・ID
・商品ID
・新しいコード
・担当者ID
・発生日時

「商品を削除しましたテーブル」
・ID
・商品ID
・担当者ID
・発生日時

C# プロパティとメソッドの違い

プロパティとメソッドとの違いについておさらいします。

MSDNに掲載されている説明は以下の通り。

プロパティとメソッドの選択

一般的に、メソッドは操作を表し、プロパティはデータを表します。

例えば「人」オブジェクトがあれば、
「名前」や「性別」はデータで、
「歩け」や「走れ」といった操作(動作)はメソッドですよ。
ということだと。

お仕事プログラミングはVB6から入った身なので、
当時は疑うこともなくプロパティを使っていたけど、
オブジェクト指向設計の面で考えるとこのメソッドなのかプロパティなのかっていうのが、
返って話をややこしくしていると思う。

そもそもJavaだとかRubyだとか、C#で言うプロパティというのは無いわけで、
Microsoft系言語のガラパゴスな仕組みだと認識しています。

少しでも脳みその負担を減らすために、いっそプロパティを使わずにプログラミングした方がいいんじゃないかとすら思う。

Javaからプログラミングに入った人だとJavaC#と移った時に
プロパティ?なにそれ?プロパティファイルじゃなくて?ってなるんでしょうかね。

書籍「現場で役立つシステム設計の原則」を読んでみて。

7月5日に発売されたのでさっそく購入しました。

この本の著者の増田さんという方、
DDDやOOPに関する資料をSlideShareに公開していて何度も目にしていました。

流し読みしてみての感想ですが、
SlideShareの内容を書籍にまとめ、より詳しく解説を加えたものという具合です。

↓↓↓増田さんが公開している資料↓↓↓
www.slideshare.net

個人的にはとても良い本だと思う。
これから何度も読み返して頭に馴染ませて行きます。

オブジェクト指向設計を勉強しよう!」ってなって、実践DDD本やリファクタリング本を読み漁りましたが、
この本を最初に読んだ方が分かりやすかっただろうなぁ・・・

文字列からプリンタを取得

using System;
using System.Printing;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var queueByFullName = new PrintQueue(new LocalPrintServer(), LocalPrintServer.GetDefaultPrintQueue().FullName);
            Console.WriteLine(queueByFullName.FullName);
            Console.ReadKey();
        }
    }
}

PrintQueueクラスのコンストラクタにPrintServerクラスのインスタンスとプリンタの完全名(文字列)を渡すと取得出来る。


以下のようにインストールされていないプリンタ名を指定するとSystem.Printing.PrintQueueExceptionが発生する。

using System;
using System.Printing;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //var queueByFullName = new PrintQueue(new LocalPrintServer(), LocalPrintServer.GetDefaultPrintQueue().FullName);
            var queueByFullName = new PrintQueue(new LocalPrintServer(), "Hoge");
            Console.WriteLine(queueByFullName.FullName);
            Console.ReadKey();
        }
    }
}

インストールされているプリンターの一覧を取得する。

using System;
using System.Printing;

namespace LocalPrintersName
{
    class Program
    {
        static void Main(string[] args)
        {

            foreach(var queue in new LocalPrintServer().GetPrintQueues())
            {
                Console.WriteLine(queue.FullName);
            }
            Console.ReadLine();
        }
    }
}

LocalPrintServerのインスタンスメソッドGetPrintQueuesを実行
実行した端末のPrintQueueクラスのコレクションが返る。

後はPrintQueueクラスのプロパティを出力

既定のプリンター名を取得する。

using System;
using System.Printing;

namespace DefaultPrinterName
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("既定のプリンタは{0}です。", LocalPrintServer.GetDefaultPrintQueue().FullName);

            Console.ReadKey();
        }
    }
}

system.printingを参照設定に追加
LocalPrintServerクラスのstaticメソッドGetDefaultPrintQueueでプリンタ設定のインスタンスを取得
FullNameプロパティでプリンタ名を取得