- 投稿日:2019-07-01T23:34:27+09:00
オブジェクト指向分析によるモジュール分割のイメージ
伝えたいこと
モデリングとプログラミングが関係ないと思っている人向けです。
オブジェクト指向分析モデリングの結果を実装すると、コードが読みやすくなります。
実際には、「オブジェクト指向分析」がモジュール分割の非常に有効な手段である、ということです。
今回は、「顧客がクリーニング店に洗濯物を出す」という内容を、分析モデリングし、その後コードに変換しています。分析のクラス図
話を分かりやすくするために、クラス図はかなり小さなネタにしています。
クリーニング店と顧客の関係で、特に、顧客が衣服を行きつけのクリーニング店にクリーニングしてもらうという関係性だけを表しています。
見て分かるように、非常に素直に伝えたい人間関係やモノの関係を、ポンチ絵的に表した(クラス)図です。
これならば、プログラミングと関係なく、人と人が共有して話し合っても、話しやすい図になっているのではないでしょうか。分析のシーケンス図
とても単純ですが、顧客がクリーニング店に行って、クリーニングしてもらう流れを描きました。
単純化するために、クリーニングは同期で書いてあります(つまり、クリーニングが終わるまでそこで待っている)ので、そこは突っ込まないでください(^^)。
そのモデルを、そのままコード
Program.csは、
クリーニング店と顧客のインスタンスを生成して、
顧客に、クリーニングの回数券を買わせ、
顧客に、服を汚させて、
次に、
顧客に、クリーニング店に行かせています。 // シーケンス図は、ここだけ描いてある。Program.csusing 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.csusing 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.csusing 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; } } }分析モデルとコードを見て
クラス図、シーケンス図、コードを見て、
分析モデルで特定したクラスが、そのままモジュール分割に利用されているのが分かりますよね。
つまり、逆に言えば、モジュールがポンチ絵的な構造をしている、とも言えます。
ポンチ絵的な構造だったら、人間にとって、より分かりやすいですよね。より素直なコードに見えると思うのです。
これが、オブジェクト指向分析が、モジュール分割に有効な手段の一つだということです。
もしよかったら、参考にしてください。
- 投稿日:2019-07-01T13:37:55+09:00
C#でPollyを使ったリトライ処理
nugetでPollyをインストールしたら後は下記のように実装するだけです。
今回はAzureSQLDatabaseを使用するため、シンプルに指定したエラーの際にリトライするよう実装しました。RetryHelper.csusing 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 }; } }
- 投稿日:2019-07-01T00:17:35+09:00
【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のインストーラをダウンロード
画面の指示に従って操作を行えばインストールできました。
.NET Core 3.0がインストールされたことを確認。
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#開発を行うときは必須なので入れておきます。
プロジェクト作成
bashdotnet new blazor -o WebApplication1 code -r WebApplication1 #WebApplication1のフォルダをルートのフォルダにしてVSCodeを開き直す dotnet runhttp://localhost:5000/ を開くとBlazorのプロジェクトを確認することができます。
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
の更新を確認できました。3-3. コードを変更してみる
Pages/Counter.razor
に[Parameter]
属性を指定してIncrementAmount
のプロパティを追加し、currentCount
にIncrementAmount
を足すように変更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
として起動し直すと変更が反映されます。4. 監視モードで実行する
dotnet watch run
とすることで、ファイルが変更されると自動で再コンパイルしてサーバー起動してくれます。
一回一回Ctrl+Cとする手間がはぶけます。ただ私の環境ですと自動とはいえ、ファイルを更新 -> サーバリロード で5〜6秒ぐらいかかってしまいました。
もう少しやりやすい方法などありましたら、教えていただきたいです。m(_ _)m5. chromeでステップ実行
試してみるとおそらくうまくいったので自分が行ったことを書かせていただきます。
参考
- Debug ASP.NET Core Blazor | Microsoft Docs
- Compiling C# to WASM with Mono and Blazor then Debugging .NET Source with Remote Debugging in Chrome DevTools - Scott Hanselman
- macos - Start Google Chrome on Mac with command line switches - Super User
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:50003 開いた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++; } }chromeからステップ実行することができました、スンバラシ…
最後まで読んでいただいてありがとうございました。