20190701のC#に関する記事は3件です。

オブジェクト指向分析によるモジュール分割のイメージ

伝えたいこと

モデリングとプログラミングが関係ないと思っている人向けです。
オブジェクト指向分析モデリングの結果を実装すると、コードが読みやすくなります。
実際には、「オブジェクト指向分析」がモジュール分割の非常に有効な手段である、ということです。
今回は、「顧客がクリーニング店に洗濯物を出す」という内容を、分析モデリングし、その後コードに変換しています。

分析のクラス図

話を分かりやすくするために、クラス図はかなり小さなネタにしています。
クリーニング店と顧客の関係で、特に、顧客が衣服を行きつけのクリーニング店にクリーニングしてもらうという関係性だけを表しています。
クリーニング店のクラス図.jpg
見て分かるように、非常に素直に伝えたい人間関係やモノの関係を、ポンチ絵的に表した(クラス)図です。
これならば、プログラミングと関係なく、人と人が共有して話し合っても、話しやすい図になっているのではないでしょうか。

分析のシーケンス図

とても単純ですが、顧客がクリーニング店に行って、クリーニングしてもらう流れを描きました。
単純化するために、クリーニングは同期で書いてあります(つまり、クリーニングが終わるまでそこで待っている)ので、そこは突っ込まないでください(^^)。
クリーニング店のシーケンス図.jpg

そのモデルを、そのままコード

Program.csは、
クリーニング店と顧客のインスタンスを生成して、
顧客に、クリーニングの回数券を買わせ、
顧客に、服を汚させて、
次に、
顧客に、クリーニング店に行かせています。 // シーケンス図は、ここだけ描いてある。

Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Cleaners
{
    class Program
    {
        static void Main(string[] args)
        {
            // クリーニング店
            Cleaners cleaners = new Cleaners();
            // 行きつけのクリーニング店のある顧客
            Customer custmer = new Customer(cleaners);

            // 回数券を買う
            custmer.BuyCouponTicket();

            // 服を汚す
            custmer.StockDirtyLaundry();

            // クリーニング店に行く
            custmer.GoCleaners();
        }
    }
}

Custmer.csは、「顧客」クラスです。
クラス図を、まんま、コードに落としています。
サンプルプログラムなので、コンストラクタで、洋服を持たせてしまいましたが、ご愛敬としてください。
最後の関数「クリーニング店に行く」がシーケンス図で示したものです。
シーケンス図と比べると対応していると思います。

Custmer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Cleaners
{
    // 顧客
    class Customer
    {
        // 行きつけのクリーニング店のある顧客
        public Customer(Cleaners regularCleaners)
        {
            RegularCleaners = regularCleaners;
            CleanLaundry.Add(new Clothes("T-Shirt"));
            CleanLaundry.Add(new Clothes("Jacket"));
        }

        // 汚れた洗濯物
        public List<Clothes> DirtyLaundry { get; } = new List<Clothes>();

        // 回数券
        private Queue<Coupon> CouponTicket { get; } = new Queue<Coupon>();

        // 行きつけのクリーニング店
        private Cleaners RegularCleaners = null;

        // きれいな洗濯物
        public List<Clothes> CleanLaundry { get; } = new List<Clothes>();

        // 汚れものを貯める
        public void StockDirtyLaundry()
        {
            // きれいな洗濯物をひとつ取り出して、
            Clothes clothes = CleanLaundry[0];
            CleanLaundry.RemoveAt(0);

            // その洗濯物を、汚れた洗濯物にする
            clothes.Dirty = true;
            DirtyLaundry.Add(clothes);
        }

        // 回数券を買う
        public void BuyCouponTicket()
        {
            // お金は払ってないけれど、省略しているだけ
            CouponTicket.Enqueue(new Coupon());
        }

        // クリーニング店に行く
        public void GoCleaners()
        {
            // 行きつけのクリーニング店.洗濯する(汚れた洗濯物,回数券);
            List<Clothes> clothes = RegularCleaners.Wash(DirtyLaundry, CouponTicket.Dequeue());
            // 仕上り品としてしまう
            CleanLaundry.AddRange(clothes); 
        }

    }
}

Cleaners.csは、「クリーニング店」クラスです。
洗濯する関数だけがありますので、これがシーケンス図内に描かれている部分です。

Cleaners.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Cleaners
{
    // クリーニング店
    class Cleaners
    {
        // 洗濯する
        public List<Clothes> Wash(List<Clothes> clothes,Coupon coupon)
        {
            // 回数券クーポンを破棄し
            // (略)

            // 洗濯する
            foreach(Clothes oneClothes in clothes)
            {
                oneClothes.Dirty = false;
            }

            // 返却する
            return clothes;
        }
    }
}

分析モデルとコードを見て

クラス図、シーケンス図、コードを見て、
分析モデルで特定したクラスが、そのままモジュール分割に利用されているのが分かりますよね。
つまり、逆に言えば、モジュールがポンチ絵的な構造をしている、とも言えます。
ポンチ絵的な構造だったら、人間にとって、より分かりやすいですよね。

より素直なコードに見えると思うのです。

これが、オブジェクト指向分析が、モジュール分割に有効な手段の一つだということです。
もしよかったら、参考にしてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#でPollyを使ったリトライ処理

nugetでPollyをインストールしたら後は下記のように実装するだけです。
今回はAzureSQLDatabaseを使用するため、シンプルに指定したエラーの際にリトライするよう実装しました。

RetryHelper.cs
using Polly;
using System.Collections.Generic;
using System.Data.SqlClient;

namespace Common
{

    public static class RetryHelper
    {
        public static void OpenWithRetry(this SqlConnection connection)
        {

            PolicyResult policyResult = Policy.Handle<SqlException>(ex => TransientErrorNumbers.Contains(ex.Number))
                .Retry(3)
                .ExecuteAndCapture(connection.Open);

            if (policyResult.Outcome == OutcomeType.Failure)
            {
                // 実行に失敗した
                if (policyResult.FinalException is SqlException)
                {
                    SqlConnection.ClearPool(connection);

                    throw policyResult.FinalException;
                    // FinalException に例外が格納されている
                }
            }
        }

        private static readonly HashSet<int> TransientErrorNumbers = new HashSet<int>
        {
            50000,
            40197,
            40501,
            10053,
            10054,
            10060,
            40613,
            40143,
            233,
            121,
            64,
            53,
            20,
             -2
        };

    }

}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【C#】macOSでBlazorの実行環境を作成してみた

BlazorとはJavaScriptの代わりに C# を使って、フロントエンド開発を行いSPAを作れるフレームワークです。
WebAssembly (wasm) によって、.NETのコードをブラウザで実行しています。

前からBlazorを勉強したいと思い、実行環境だけ作成してみたので投稿させていただきました。
C#初心者です。よろしくお願いします。


以下のGet startedの通りに行えば、特に問題なく実行環境を作成できました。

自分が試した環境

  • macOS Mojave
  • dotnet 3.0.100-preview6-012264
  • Google Chrome : 75.0.3770.100 (Official Build) (64-bit)

1. .NET Core 3.0 をインストールする

macOSのインストーラをダウンロード

Screen Shot 2019-06-30 at 3.png

画面の指示に従って操作を行えばインストールできました。

Screen Shot 2019-06-30 at 3.22.36.png

.NET Core 3.0がインストールされたことを確認。

Screen Shot 2019-06-30 at 3.24.33.png

2. コマンドを実行してBlazorテンプレートをインストール

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview6.19307.2

3. Blazorのプロジェクトを作成

VSCodeを使用してプロジェクト作成した手順を紹介させていただきます

3-1. C# for Visual Studio Code extension のインストール

VSCodeでC#開発を行うときは必須なので入れておきます。

プロジェクト作成

bash
dotnet new blazor -o WebApplication1
code -r WebApplication1 #WebApplication1のフォルダをルートのフォルダにしてVSCodeを開き直す
dotnet run

JUiS8Zt49a.gif

http://localhost:5000/ を開くとBlazorのプロジェクトを確認することができます。

Screen Shot 2019-06-30 at 3.47.59.png

3-2. カウンターの動きを確認

Pages/Counter.razor
@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="@IncrementCount">Click me</button>

@code {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

@page/counterと指定されているのでhttp://localhost:5000/counter とアクセスすると、Pages/Counter.razorの内容が実行されます。

@onclickでクリックイベントを指定し、@IncrementCountが実行され、@currentCountの更新を確認できました。

eQX9Wd6FU8.gif

3-3. コードを変更してみる

Pages/Counter.razor[Parameter]属性を指定してIncrementAmountのプロパティを追加し、currentCountIncrementAmountを足すように変更

Pages/Counter.razor
  @page "/counter"

  <h1>Counter</h1>

  <p>Current count: @currentCount</p>

  <button class="btn btn-primary" @onclick="@IncrementCount">Click me</button>

  @code {
      int currentCount = 0;

+     [Parameter]
+     private int IncrementAmount { get; set; } = 1;

      void IncrementCount()
      {
-         currentCount++;
+         currentCount += IncrementAmount;
      }
  }

ホーム画面に<Counter />エレメントを追加します。
先ほどCounterコンポーネントにIncrementAmountプロパティを追加したので、<Counter IncrementAmount="10" />とします。

Pages/Index.razor
  @page "/"

  <h1>Hello, world!</h1>

  Welcome to your new app.

  <SurveyPrompt Title="How is Blazor working for you?" />

+ <Counter IncrementAmount="10" />

コードを変更したので、Ctrl+Cで一度サーバーをシャットダウンし、dotnet runとして起動し直すと変更が反映されます。

zlOgB3KuZi.gif

4. 監視モードで実行する

dotnet watch runとすることで、ファイルが変更されると自動で再コンパイルしてサーバー起動してくれます。
一回一回Ctrl+Cとする手間がはぶけます。

ただ私の環境ですと自動とはいえ、ファイルを更新 -> サーバリロード で5〜6秒ぐらいかかってしまいました。
もう少しやりやすい方法などありましたら、教えていただきたいです。m(_ _)m

5. chromeでステップ実行

試してみるとおそらくうまくいったので自分が行ったことを書かせていただきます。

参考

5-1 デバッグモードで起動する

dotnet run --configuration Debug

5-2 chromeをコマンドから起動する

1 chromeを開いているのであれば閉じる
2 以下のコマンドでchromeを開く

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 http://localhost:5000

3 開いたchromeがアクティブウィンドウの状態でshift+option+D
4 dev toolが開くのでブレークポイントを設定する
5 ステップ実行してみる

こちらのコード↓をステップ実行してみます

Pages/Counter.razor
@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="@IncrementCount">Click me</button>

@code {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
        currentCount++;
        currentCount++;
        currentCount++;
        currentCount++;
    }
}

vCY6DJ7t2p.gif

chromeからステップ実行することができました、スンバラシ…

自分がはまった部分

5-3. dev toolをcommand+Rでリロードすると、なぜかファイルが見れなくなってしまう

command+Rではなく、左上のリロードをマウスでクリックするとファイルが見れるようになりました。↓
無事ソースが確認できました。

muy4CAoJux.gif


最後まで読んでいただいてありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む