Niigata.NET 2.1を開催しました #ngtnet

Niigata.NET 2.1 テックトーク+ハンズオン & .NET開発お悩み相談室 – connpass
https://ngtnet.connpass.com/event/41607/

先週11/19(土)に今年2回目となるNiigata.NET勉強会を開催しました。今回は従来のテックトークに加え、参加者の皆さんにも手を動かしてもらおうと、ハンズオン形式のセッションも取り入れてみました。

(当日の様子はこちら

 

プログラミング初級講座 C#編 – 分岐 by @AILight

最初のセッションは、新潟が誇るMS MVPの石野さんによる、シリーズもの第3弾です。if、switchといった「分岐」を扱う言語機能についてフォーカスし、初歩的な内容から紹介していただきました。

その中で印象的だったのは「分岐がないことが分岐の良い条件である」といったような雰囲気の言葉でした。

ともすると、分岐というものはいわゆるスパゲティコードになってしまいがちなものです。特に初心者、初級者のうちは、いわゆる設計書に書かれたロジックをそのまま表現しようとして、様々な条件が入り組み、深くなったif分を書いてしまうものです。

こういったif文、switch文を「いかに減らすか」が、分岐を扱うキモだと石野さんは主張されました。

その為に、if文をどうやって減らすかということを、コード例を用いて説明しました。その方法は主に以下の通り。

  1. 配列等を使ったジャンプ
  2. 「条件」でなく「データ」に着目

配列等を使ったジャンプ

引数が0->5のような値だとして、それに対応する値を返すような場合、それは引数をインデックスとみなして配列を用いて目的の値を返すようにすることで、if文をなくすことができます。

変更前
int SomeMethod(int value)
{
  if (value == 0)
  {
    return 5;
  }
  else if(value == 1)
  {
    return 10;
  }
  else if (value == 2)
  {
    ...
  }
  ...
}
変更後
if SomeMethod(int value)
{
  return new [] { 5, 10, ... }[value];
}

何かしらの値のテーブルを使って対応する値を返すようなケースでは、案外使えるケースはありそうです。

「条件」でなく「データ」に着目

小規模なアプリでメニューを作る際、ユーザーの情報を条件にif文を連ねて必要なメニューを表示するようにすると、条件の追加、変更に弱くなってしまいます。それを解決するため、「ユーザー情報」側にどのメニューを表示するかの判断を委譲し、メニューを構築する側ではそれを利用するだけにします。

変更前
if (user.IsHoge)
{
  // A機能メニューに追加
}
else if (user.IsFuga)
{
  if (user.IsPiyo)
  {
    // B機能メニューに追加
  }
  else
  {
    // C機能メニューに追加
  }
}
変更後
if (user.UseA)
{
  // A機能メニューに追加
}
else if (user.UseB)
{
  // B機能メニューに追加
}
else if (user.UseC)
{
  // C機能メニューに追加
}

このように「データ」を主体に構築することで、条件の追加、変更に強くなります。

 

先日リリースされたC# 7では「型スイッチ」機能などでさらに分岐のパターンが増えます。こういったものを使うにも、基本的なif、switchは押えておいた方がよいでしょう。

 

ASP.NET MVC開発体験 by @masaru_b_cl

私のセッションです。asp.net/mvcからアクセスできるASP.NET 5のチュートリアルを、会場の皆さんとやりながら簡単にASP.NET MVCの説明を行いました。

一緒に進めていくので、それぞれ進み具合が違い、ある程度余裕を持って進めていたので、MVCのCとVまでしかできませんでした。それでも、Cでリクエストを受け取って処理して返す、VはRazorで書く、Vの編集と確認はリビルド不要、くらいは説明できたので良しとしましょう。

実際、今回のセッションの裏テーマは「公式チュートリアルやろうぜ」でした。

大抵のメジャーなプラットフォーム、フレームワークは公式がチュートリアル用意してあることが多いです。もちろん英語なわけですが、「うわっ、英語怖い!」を乗り越えて読んでみると、実際は中学英語範囲の構文で読めますし、重要なのはコードなので万国共通のため、あんまり問題ありません。

それを避けてわざわざどこの馬の骨ともわからない人が書いた日本語blogエントリを読んだり、公式以外のチュートリアルを見ても、情報が古かったり、環境構築が大変だったりして、すんなりいかないことが、個人的には多いと感じています。

その点、公式チュートリアルは必要十分な情報をコンパクトにまとめてあることが多いです。一例として、某レールに乗るフレームワークのチュートリアルは、環境の違いかうまくできなかったんですよねぇ。でも、公式のやつは引っかかることもなくできたという経験があります。

ぜひ、未知のプラットフォーム、フレームワーク、ライブラリは、まずは公式チュートリアルから入ってみることをお勧めします。

あと、今回@circled9さんが前日にリリースされたばかりのVisual Studio for Macでぶっこんできて、「強い」と思いました。(ありがとう!)

 

.NET開発相談室

Niigata.NETの恒例コーナーにしていこうと目論んでおりますw

前回主催側がしゃべりすぎたため、今回は参加者の皆さんに多くしゃべってもらおうと思ったのですが、なかなかうまくネタを引き出せないものですね。それでも、なんとか四苦八苦してネタを絞り出し、あーだこーだ言える機会が持てたのは良かったです。

ただ、イベント終了後に「string型の変数の初期化をnullでやるのと空も時でやるの、どっちがいいんですかね?」みたいなことを聞かれ、「それをさっきの相談室で言ってもらえたら!」って思ったので、次回は「こんなのでいいんですよ」ってのを、もっと言ってかないとなぁと思った次第です。

 

そんな感じで、第3回の勉強会を終えました。今後はなんとか最低でも年2回ペースで開けるよう、いろいろと動いていきたいと思います。あと、主催側じゃないスピーカーの確保もぜひ。

 

なお、Niigata.NETでは「中の人」も募集しております!別にスピーカーをやれというわけではなく、イベント運営に必要な会場設営、受付、懇親会の手配など、色んな雑事の一部をお手伝いしていただけたらと思います。やってもいいよという方は、この記事へのコメント、Twitterでのメンション、ハッシュタグ#ngtnetを付けたつぶやきなど、何らかの手段でお知らせください。

書評 | Amazon Web Servicesではじめる新米プログラマのためのクラウド超入門

http://www.shoeisha.co.jp/book/detail/9784798144696

WINGSプロジェクト様より献本御礼。

本書はAWSの多種多様なサービスの中から、S3、EC2、ELB、Route 53といった主要なサービスを中心に、その概念や役割、そしてGUIによる設定方法について述べた書籍です。また、ネットワーク等いわゆる「インフラ」に関わる基本的な知識についても解説がついており、初学者に対して非常にやさしい構成であると感じました。

GUIによるAWSの管理コンソール捜査については、ハードコピーがふんだんに使われており、書籍をなぞりながら実際にAWSを体験できるようになっています。その分ページ数がかさんでいるため、ある程度知識のある読者にとっては内容が薄いように感じる顔しれません。しかし、あくまで本書は「新米プログラマのための」と銘打ってありますので、そのあたりは差し引いて考えるべきでしょう。

本書で一点気になったこととしては、著者の前著でもそうだったのですが、説明図の中のLinuxコマンド例が

rm -rf /

なのですよね。これは図のもとにしたイメージ素材がそうだったのか、はたまた著者のお茶目心なのか判断に困るところです……

そういった些末なところを除けば、新米プログラマだけでなく、他のクラウド・プラットフォームユーザーがAWSについてざっと知りたいといった用途にも、個人的にお勧めできると思います。

tdd-in-net-1-638

テスト駆動開発(TDD) in .NET #ngtnet by @masaru_b_cl

はじめに

このエントリは2016/5/7に開催したNiigata.NET 2.0で行ったセッションを再構成したものです。

 

ライセンス

クリエイティブ・コモンズ・ライセンス
この 作品 は クリエイティブ・コモンズ 表示 – 継承 4.0 国際 ライセンスの下に提供されています。

 

Agenda

 

テスト駆動開発(TDD)とは

テスト駆動開発とは、Kent Beck(ケント・ベック)が提唱した開発手法です。彼の著書であり、「原典」とも呼ばれる「テスト駆動開発入門」(http://www.amazon.co.jp/dp/4894717115)(残念ながら絶版。再販望む!)にはこのように書いてあります。

「動作するきれいなコード」、ロン・ジェフリーズのこの簡潔な言葉は、TDD(テスト駆動開発)の目標である。動作するきれいなコードは、あらゆる理由で価値がある。

それでは、どのように「動作するきれいなコード」を目指していくのでしょう?

 

TDDの進み方

まず、「動作するきれいなコード」にたどり着くには2つの道があります。一つはきれいなコードを書きながら動作するように直していくもの。もう一つは動作するコードを書きながらきれいに直していくものです。

(図は日本におけるTDDの第一人者である「和田 卓人(@t_wada)」さんのスライド「TDDのこころ」より拝借しています。)

TDDはこのうち後者の「着実に一歩ずつ進む道」をとります。つまりまず動くようにしてからきれいにしていきます。なぜこの道かというと、何はともあれ「動作」していなければ、製品としての価値はないということが一つです。

他に、この「動かない」→「動く」の線を超えるときに多くの「気づき」が得られるということもあります。フィードバックは早ければ早いほど修正が容易ですので、まずは動くように書き、フィードバックを得て素早く修正していくのがTDDということになります。

 

TDDのサイクル

TDDはこの着実な道を次のようなサイクルで進んでいきます。

  1. 次の目標を考える
  2. その目標を示すテストを書く(テストファースト)
  3. そのテストを実行して失敗させる(Red)
  4. 目的のコードを書く
  5. 2で書いたテストを成功させる(Green)
  6. テストが通るままでリファクタリングを行う(Refactoring)
  7. 1~6を繰り返す

そしてこの手順を小さく回すことで、素早いフィードバックを得ることができます。

これをTDDの界隈では「黄金の回転」と呼んでいます。これはくるくると回りながらどんどんと高みを目指していくイメージから、荒木飛呂彦先生の「スティール・ボール・ラン」に出てくる「黄金の回転」が連想されるため、このように呼ぶようになったそうです。

(スティールボールラン、荒木飛呂彦著より)

 

動作するきれいなコード

では、「動作するきれいなコード」とは何でしょう?それは原典の該当箇所の原文を見ればわかります。

「動作するきれいなコード」は「Clean code that works」であり「Beautiful」ではないのです。つまりは整頓されたコードがきれいなコードであるということになります。

とはいえ、もう少し具体的な指針が欲しいところです。そこで、「きれい」なコードとは何かを知ることのできる書籍をいくつか紹介します。

まずは「リーダブルコード」です。サンプルコードはC#など.NET言語ではありませんが、「リーダブル≒読みやすい」コードを書くためのテクニックに「名前」を付けて完結にまとめているため、最初に読む1冊としては最適です。

次に「リファクタリング」です。コードの挙動を変えずに構成を直す「リファクタリング」のテクニックについて網羅的にまとまっています。「きれいなコード」にどのように直せばよいのかを学ぶのによいでしょう。なお、この本もTDD入門と同じく一度絶版になりましたが、オーム社により再販されています。

これまでの2冊は実際のコードに近い話でしたが、「きれいな」コードは「きれいな」設計から生まれます。そのため、オブジェクト指向プログラミング言語を使ったアプリケーションの「設計」に関する原則を学ぶことも重要です。それを学ぶための書籍を2つ紹介します。

まずは「C#実践開発手法」です。これはその名の通り、C#を使っていわゆる「SOLID原則」と呼ばれるような設計原則を、実際にどのように使えばよいのか実例とともに紹介しています。こういった分野の書籍には「アジャイルソフトウェア開発の奥義」がありましたが、コードがJava(もしくはC++、Smalltalk)だったので、C#でコードが読めるというだけでも本書はありがたいです。もちろん、内容もより新しいものになっています。

そして、オブジェクト指向プログラミング言語の設計原則について学ぶなら「Head First デザインパターン」がおすすめです。本書のタイトルは「デザインパターン」となっていますが、実際はSOLID原則やハリウッド原則といった基本原則を学ぶのに最適な本だと私は思っています。サンプルコードはJavaですが、C#を知っていればそれほど苦も無く翻訳して読めるでしょう。

また、きれいなコードは既存のライブラリ等との統一感も重要です。特に.NET Frameworkは標準ライブラリが巨大なので、勝手なルールでライブラリを作ってしまうと、利用者が混乱してしまいます。

そこで、標準ライブラリの設計ガイドラインを知るために、「.NETのクラスライブラリ設計」も強くお勧めします。この本は単にライブラリ設計のガイドラインが書いてあるだけでなく、過去の失敗についての.NETの中の人の議論が掲載されていることもおすすめポイントの一つです。

 

TDDの目的

さて、こういった書籍などを参考にしつつも「きれいなコード」を目指すことがTDDの目標であることはすでに述べたとおりです。では、目標のさらに先にある「TDDの目的」はなんでしょうか。それは、一言でいうと「健康」です。

TDDはテストを書きますが、それは大きな目的を実現するための手段でしかありません。TDDで目標とするのは「動作するきれいなコード」は、すなわち「変化に対応」しやすいコードであるともいえます。

変化に対応しやすいコードは、言い換えれば不安が少ないコードだともいえます。ユーザーの要望をかなえるためには、コードを変化させなければいけませんが、「動作するきれいなコード」ならば、安心して変更することができます。

そして、この「不安が少ない」状態を一言で表せば、それが「健康」であるということです。

そして、「健康」なコードは不安が少ないため、開発者自身の「健康」にもつながります。一人一人の開発者が健康なら、チーム全体も「健康」であり、ひいては開発、運用している製品、サービスとその開発者、ユーザーなど関係者全員の健康にもつながります。

この大きな目的のために、まずは目標として「動作するきれいなコード」を維持するよう、TDDを行っていきます。

 

.NETにおけるTDD

TDDがどういうものかわかりましたが、.NET開発においてTDDをどのように進めていけばよいのでしょうか?次の4つの項目に焦点を当て、順に説明していきます。

  • テスティングフレームワークおよびサポートツール
  • ソリューション構成
  • テストコード
  • テスト実行

 

テスティングフレームワーク

まずは、.NETで使える主なテスティングフレームワークをいくつか紹介します。

まず最初は「MSTest」です。MSTestはVisual Studioに標準搭載されたテスティングフレームワークで、現在はExpress Editionでも使用できるため、お手軽さはNo.1です。

次は「NUnit」です。JUnitをはじめとした、いわゆるxUnit系列の正統派オープンソーステスティングフレームワークで、MSTestがVSの下位エディションに搭載されるまでは、デファクトスタンダードでした。

最後は「xUnit.net」です。上記2つより新しく、テストコードの書き方等を一から見直したテスティングフレームワークで、MSのASP.NETチームなどでは、最近のオープンソースプロダクトのテストに使用されています。

ではどのテスティングワークを選べばよいのでしょうか?個人的にはMSTestかNUnitをお勧めします。

MSTestは何といってもVSを入れれば入っているというお手軽さが一番で、必要最小限の機能はあるので、入門には最適だといえるでしょう。また、NUnitは歴史があることもあり、Web上の日本語情報も多く、MSTestよりは高機能(パラメタライズド・テストなど)です。

サポートツール

次にサポートツールについて見ていきましょう。まずは「テストアダプター」です。

MSTestは標準でVS上からテストを実行することができますが、その他のテスティングフレームワークは、専用のテストランナーを使う必要がありました。それを改善し、VSからテストを実行できるようにするのが、「テストアダプター」です。

テストアダプターを導入すれば、NUnitやxUnit.netのテストコードも、VS上から実行して結果を確認できるようになります。

また、テストコードの書き味を改善するため、「Chaining Assertion」というライブラリもお勧めです。

Chaining Assertionはテストコードの書き方を、A.Is(B)の形式で書けるようにします。MSTestの他、NUnitやxUnit.netにも対応しています。後で実例を出すときに、Chaining Assertionを使ったコード例を使って説明します。

 

ソリューション構成

次にTDDを行うソリューションの構成を見ていきましょう。.NETでTDDする場合、テスト対象プロジェクトとテストプロジェクトの複数プロジェクト構成にするのが一般的です。

まずテスト対象プロジェクトは*.exe形式の実行ファイルや*.dllのクラスライブラリどちらでも大丈夫です。ただ、クラスライブラリにする方が一般的ではあります。

そして、テストプロジェクトが別になるため、テスト対象の型は原則publicとします。internalな型についても、テスト対象プロジェクトにアセンブリ属性InternalsVisibleToを使い、テストプロジェクトに対してのみ公開することもできます。

次にテストプロジェクトですが、MSTestを使う場合は「単体テストプロジェクト」を選択します。他のOSSテスティングフレームワークを使う場合は、クラスライブラリプロジェクトを作成した後、使用するテスティングフレームワークへの参照を追加します。

 

テストコード

次にテストコードの構成を見てみましょう。今回はMSTest+前述のChaining Assertionを使ったテストコードについて説明します。

まず、MSTestのテストクラスであることを示すため、TestClass属性をクラスに付けます。テストクラスはpublic出なければならないことに注意してください。

次に、実際のテストを行うメソッドにはTestMethod属性を付けます。テストメソッドもpublicとし、戻り値はvoid、引数はなしとします。テストメソッドは必要な数だけ複数個作ってかまいません。テストメソッド内では、実際の値と期待値が等しいことを、Isメソッドを使い検証します。

この他、それぞれのテストメソッドが実行される前に毎回実行したい処理、例えばテスト対象オブジェクトの初期化などは、TestInitialize属性のついた、いわゆるSetUpメソッドに書きます。同様に、テストメソッド実行後に毎回実行したい後処理は、TestCleanup属性のついた、いわゆるTearDownメソッドに書きます。

 

テスト実行

こうして作成したテストコードは、Visual Studio上から実行すると、「テストエクスプローラー」にテストメソッドごとに成功、失敗、そして失敗ならその失敗した箇所の情報が表示されます。

このようにして、VS上でテストを行っていきます。

 

TDDの実例

それでは、実際にTDDを行っている様子の実例を見せましょう。今回はFizzBuzzを題材として使用します。作成したコードは、GitHubにアップしているので、併せて参照してみてください。

 

設計

まず最初に行うのは「設計」です。作成するプログラムの仕様を元に、ざっと設計して必要と思われるタスクをToDoリストとして作成します。最初にこの工程を行うことで、事前の目標付けとともに、仕様であいまいな部分やどのようにテストを行うのかといった不安要素をなるべくなくします。

 

最初のテスト作成

ToDoリストを作成したら、その中から一つ選び最初の「失敗する」テストを作成します。今回は「正の整数の場合、その数値を文字列で返す」を選び、このことをテストするために「引数が1の場合、”1″を返す」ことを確認するテストコードを書きます。

この時、自分が「最初のユーザー」となり、使いやすいAPI設計を考えることが重要です。それには、型名やメソッド名、引数の名前や型、戻り値の型など、様々な観点があります。

今回はまずテスト対象プロジェクトFizzBuzzとテストプロジェクトFizzBuzz.Testを作成し、FizzBuzz.TestプロジェクトにFizzBuzzTest.csを追加してFizzBuzzTestクラスを作成しました。なお、テスティングフレームワークにはMSTestを使い、Chaining AssertionをNuGet経由でインストールしています。

PM> Install-Package ChainingAssertion

(https://github.com/masaru-b-cl/ngtnet2-fizzbuzz/blob/af2891d63f95b2ea60c88e643b335d0ca14159bd/FizzBuzz.Test/FizzBuzzTest.cs)

.NET開発で最初のテストコードを書く時のポイントは以下の通りです。

  • 戻り値の型を明示する
  • 引数の型を明示する
  • 名前付き引数で引数名を明示する

こうしておくことで、次のフェーズを行う際、VSの機能を使ってコードを自動生成できます。

またこの他、テストコードは適宜日本語で書くことで、その意図がわかりやすくなることもあります。特にC#はメソッド名に使える文字が限られているため、日本語の表現力に頼るのは理にかなっています。

 

最初のテスト失敗

テストコードを作成したら、テストを実行して失敗することを確認します。ここではテストの役割のうち「正しく失敗する」ことを確認することが重要です。

なお、「最初の失敗するテスト」の失敗にはコンパイルエラーも含めてよいです。この段階ではFizzBuzzerクラスは無いのでコンパイルエラーになるはずです。

 

仮実装(Fake It)

テストが正常に失敗することを確認したら、いよいよテスト対象コードの実装に入ります。まず最初に行うのは、「仮実装(Fake It)」です。仮実装とは「テストが成功する最速の実装」のことで、リテラル定数を使ってテストが成功するように書いてしまいます。最初に作成したテストコードであれば、戻り値として”1″を返せば、テストが成功するはずです。

一見意味がないようにも見えますが、この手順には失敗しようのない状態で「テストが正しく成功する」ことで、テストの妥当性を担保するという目的があります。もし仮実装でもテストが失敗するようなら、その後本当の実装にしてもテストが成功するわけはないのですから。

VSで仮実装を行う際、まずはテストコードからテスト対象クラスを生成します。コンパイルエラーとなっているFizzBuzzerクラスの箇所でCtrl+.キーを押し、「新しい型の生成…」を選択します。

generate-class

そして、表示された「型の生成」ダイアログにて、「種類」にclass、「場所」にFizzBuzzプロジェクト、そして「ファイル名」に”FizzBuzzer.cs”を指定して「OK」ボタンをクリックします。

generate-class-02

すると指定した通り、FizzBuzzerクラスがFizzBuzzプロジェクトのFizzBuzzer.csファイルに作成されます。

次に、FizzBuzzTest.csに戻り、コンパイルエラーとなっているSayメソッドの生成を行います。Ctrl+.を押し、「メソッド ‘FizzBuzzer.Say’ を生成します」を選択します。

generate-method

すると、未実装のメソッドSayが生成されます。

テストクラスで引数名、型、戻り値の型を明示していたことで、それに合わせたシグネチャでメソッドが生成されます。

最後に、Sayメソッドが1を返すように仮実装すれば終了です。

(https://github.com/masaru-b-cl/ngtnet2-fizzbuzz/blob/b89706c18621ab0302e3fe524539281e0a4cdd39/FizzBuzz/FizzBuzzer.cs)

この時、FizzBuzzTest.csファイルのSayメソッド呼び出しか所でAlt+F12を押すことで、「定義をここに表示」すると便利です。

peek-definition.jpg

 

最初のテストの成功

 

テストを実行し、成功することを確認します。Ctrl+R, Aキーを押すことで、すべてのテストを実行できます。

success-first-test.jpg

無事テストが成功しました。

 

リファクタリング

テストが成功したので、今度はリファクタリングです。テストが成功する状態を保ったまま、コードを整理します。言い換えれば、挙動を変えずに構造を改善するということです。

なお、テストコードを整えるのもリファクタリングの一つです。ここでは、テストコード内で明示した型や引数名を取り除いてみましょう。

(https://github.com/masaru-b-cl/ngtnet2-fizzbuzz/blob/42483eb7eaa217d80440a026572ffd211bb3ddab/FizzBuzz.Test/FizzBuzzTest.cs)

コードを変更したら、テストを実行して成功することを確認しておきましょう。

 

次の失敗するテストを追加する

先に進むため、「小さな一歩」となるような新たなテストを追加します。この時、先ほど仮実装したメソッドにて、同じ仕様を満たすもう一つのテストコードを追加することで、実装1点に対してテスト2点の「三角」で進めることを「三角測量」と呼びます。今回の例でいえば、「正の整数の場合、その整数を文字列にして返す」という仕様に対して、最初に作った1を”1″にして返すテストに加え、2を”2″にして返すかどうかを確認するテストを追加することで、三角測量を行います。

 

(https://github.com/masaru-b-cl/ngtnet2-fizzbuzz/blob/f21f34237754464babe6e6746a7f52df94295f4b/FizzBuzz.Test/FizzBuzzTest.cs)

 

すべてのテストを実行

テストを追加したらすべてのテストを再実行し、追加したテストだけが失敗することを確認します。もしこの時複数のテストが失敗するようであれば、それは良くない設計であることを示す臭いです。「良くない」とは仕様でなく内部実装に対してテストしている、責務分割が不十分で一つの変更があちこちに影響するような作りになっている可能性が高いのです。

failure-second-test

無事2つ目のテストだけが失敗しました。

 

テストが成功するまで修正

あとは、失敗した2つ目のテストについて、テストが成功するまで実装を行います。このとき、仮実装で使用した定数、リテラルを、引数や変数を使うように直します。サンプルでは、Sayメソッドの引数numberを文字列にして返すようにします。

(https://github.com/masaru-b-cl/ngtnet2-fizzbuzz/blob/f21f34237754464babe6e6746a7f52df94295f4b/FizzBuzz/FizzBuzzer.cs)

 

修正後にテストを実行し、2つのテスト両方が成功することを確認します。

success-second-test

 

再びリファクタリング

2つのテストで共通で使っているfizzBuzz変数をフィールドにしてSetUpメソッドで初期化したり、整数が整数の文字列を返すテストは一つあれば十分なので、一方を消したりします。

(https://github.com/masaru-b-cl/ngtnet2-fizzbuzz/blob/f3ffd123918d51a20a2e6cb8b4892097a9adccbe/FizzBuzz.Test/FizzBuzzTest.cs)

テストを実行し、成功することを確認します。

 

ToDoリストを更新する

ここまでで事前に作成したToDoリストの最初の仕様の実装が終わったので、完了したタスクを消してしまいます。

 

次のテストを追加する

今度は別の仕様について実装していこうと思うので、次のテストを作成し、追加します。3の倍数のテストを追加してみます。

(https://github.com/masaru-b-cl/ngtnet2-fizzbuzz/blob/f4b7c5a74d3ccada1787a583b96ab66d613705e4/FizzBuzz.Test/FizzBuzzTest.cs)

 

明白な実装

実装が自明である場合、仮実装をスキップしてしまっても構いません。これを「明白な実装」と呼び、イメージとしては開発スピードアップのため、ギアをあげるイメージです。今回は引数を3で割った余が0の時に”Fizz”を返すよう実装します。

(https://github.com/masaru-b-cl/ngtnet2-fizzbuzz/blob/da6c8c0288634b67789fcfa17965bf4ff761910c/FizzBuzz/FizzBuzzer.cs)

 

以上のような手順を繰り返して、ToDoリストの項目を全部消したら、実装が完了したということになります。

 

TDDの指針

最後に、TDDを行う上でのいくつかの指針を紹介します。

 

いつTDDを行うか

まず、「いつ」TDDを行えばよいのかというと、それは「不安」を感じたとき、ということになります。例えば、ライブラリの使い方に自信がなかったり、第三者の実装が信用できない時など、開発に関連する不安があれば、それをテストで保護してあげるのです。

ただし、今作成しているのが「使い捨て」のコードであれば、TDDを行わない方が良いこともあります。テストコードを作成しても、そのテストが数回しか実行されないようであれば、テストはただのコストでしかありません。

その他、GUIのコードについてはTDDを行いません。GUIの自動化テストを作成するには非常に手間がかかり高コストな作業です。しかし、GUIは一番ユーザーに近いところであることから、変更が頻繁に起こります。そうすると、せっかく作ったテストもすぐに変更しないといけなくなってしまいます。

また、トライ&エラーであれこれ試すような時もTDDは向いていません。ただし、あれこれ試した結果、確定した実装に対してテストを書いても問題ありません。「テストファースト」にはこだわらなくても大丈夫です。

 

どんなテストが良いテスト?

一般的に「良い」とされるテストの特徴に「F.I.R.S.T」と呼ばれるものがあります。

  • Fast(高速)
    テストの実行がすぐ終わること
  • Independent(独立している)
    他のテストへの影響がなく、任意のテストメソッド単体でも実行可能であること
  • Repeatable(繰り返し実行可能)
    何度実行しても同じ結果となること
  • Self-Validationg(手動での検証がない)
    テストコードのみでテストが完結していること。
  • Timely(テストファースト)
    最初にテストを書いていること

これら5つの特徴には優先度があり、特に重要なのはIとR、続いてF、S、Tです。少なくともIとRだけは考慮したテストを書きましょう。

 

どのようにテストを行うか

ToDoリストを元にどのようなテストを行えばよいのかについては、各種のテスト技法を参考としましょう。基本的なテスト技法として、同値クラス、境界値分析くらいは考慮したテストを書きましょう。

 

既存コードがある場合

「テストがないコードはレガシーコードだ!」のキャッチコピーでおなじみの「レガシーコード改善ガイド」を参考に、小さく初めて少しずつ範囲を広げていきましょう。

 

最後に

最後に大事なことですが、TDDはあくまで「センス」ではなく「スキル」です。訓練次第で誰でも習得画家のなものなのです。たまに「テストが書けるようになったらTDDをやってみよう」みたいなことを聞くことがありますが、「できるようになったら始める」というのは永遠に始めることはできません。まずは始めてみて、うまくいかなければ直せばよいのですから。

また、本来はチームを巻き込んだ形TDDができるのが理想ですが、まずはあなた一人でも始めることができます。やってみて、良いものであれば他の人に勧めて、徐々にTDD人口を増やしていきましょう。

そして、TDDによって安心を得て、「健康になりましょう」

 

参考資料

 

43037_normal_1460473877_相談-アニマル-イラスト

Niigata.NET 2.0を開催しました #ngtnet

Niigata.NET 2.0 | テックトーク&.NET開発お悩み相談室 – Niigata.NET | Doorkeeper

GWの終わりの5/7(土)にNiigata.NETの第2回勉強会を開催しました。

今回は前半は普段のテックトーク、後半は参加者の皆さんから普段の開発で困ったことなどについて、みんなで考えようなお悩み相談室としました。前回は初回ということで遠方よりご参加いただいたりと半ばお祭りでしたが、今回は地元参加者のみでの比較的少人数での会となりました。

テックトーク

考える、プログラミング初級講座 C#編 by @AILight

1つ目のテックトークは、越後が誇るMS MVPである@AILightさんによる、「変数」に絞ったC#入門でした(資料はアップされていないようです)。始めるまえに「時間が読めない」と公言していた通り、1時間半を超える大規模セッションになりましたf(^^;

ポイントを絞って振り返ってみます。

まず、C# ステップアップに大切なこととして次の3つを挙げています。

  1. 言語仕様を学ぶ
  2. ランタイムを学ぶ
  3. 短く書くようにする

C#の言語仕様については、最近はコードネームRoslynこと「.NET Compiler Platform」がオープンに開発が進んでいることもあり、ちょっと追うのが大変です。C# 5.0までくらいなら、VSのインストール先に入っているので、まずこちらで確認して、最新仕様は別途「C# によるプログラミング入門」などのサイトで確認するとよいと思います。

VS2015なら、言語仕様は以下のフォルダーにあります。

C:\Program Files\Microsoft Visual Studio 14.0\VC#\Specifications\1041\CSharp Language Specification.docx

次に変数の使い方として以下の3つを挙げています。

  1. 宣言
  2. 代入
  3. 参照

これらについて、実際の「自分のルール」含めて、変数名やvar使うか問題、多次元/ジャグ配列の宣言と初期化などについて語ってくれました。それらの中で、私も真似しようかなと思ったルールが一つあって、それは「変数名略すな」です。

よくこんなコードを書いてしまいがちです。


var client = new HttpClient();
client.~

ですが、ただの「client」ではもし今後HTTPSクライアントが増えたらどうするのか?といった視点から避けるべきという主張でした。その代わり、


var httpClient = new HttpClient();
client.~

のように、型名をcamelCaseにしたので良いのではということでした。

こんな感じで、「変数」だけでこれでもか、これでもかと大いに語ってくださいました。

テスト駆動開発(TDD) in .NET by @masaru_b_cl

私のセッションです。内容はスライドを参照ください。後日補足を加えて別途エントリにもまとめるつもりです。

私のセッションもデモ入れたりして少し長くなってしまいました。やはり資料をぎりぎりに作成するのはだめです……。

質疑応答は記憶している範囲ではこんな感じでした。

  • DB絡んだテストはどうするのか?
    • SetUp等でDB接続してデータをこしらえてテストしている
    • FastであることよりもIndependentでRepeatableな方が価値が高いので問題なし
  • いわゆる「単体テスト」に流用できないのか?
    • TDDのユニットテストは「開発者テスト」であり、品質保証を目的とするテストとは違うもの
      • 流用できる部分もあるかもしれないがそれほど多くない
    • 品証の単体テストは、単一コンポーネントというよりは各種コンポーネントを組み合わせて「ユースケース」を元に設計する
  • privateなメソッドのテストはやるのか?
    • privateなものはpublicなメソッドを通じて行う
      • privateなものは実装に近すぎて簡単にテストが壊れるため
    • そのためTDDもユースケースを考慮したテストを行う方がよい
    • もしprivateなメソッドをテストしたくなったら、単一責務の原則に従い責務分割のチャンス

 

.NET お悩み相談室

そして、今回のメインだったはずが、テックトークでだいぶ時間が押してしまい、30分くらいしかできませんでした。

出た話題としてはこんな感じだったかと。

  • 現在WinFormsのクラサバアプリを型付DataSet+TableAdapterを使って作っているが、EFにした方がよいのか?
    • MSのリソースはEFに集まっている
    • DataSetのように非接続型アクセスするには、ひと工夫必要
  • .NET関連の最新情報キャッチアップはみんなどうしているのか?
    • 最新情報を追っている人をSNS等でウォッチする
    • MSのドキュメント、チュートリアルを参考に手を動かす

時間がなかったので、正直消化不良気味でした。ぜひリベンジしたい。

 

全体を通じて

今回は参加者が地元の方だけということもあり、比較的おとなしい印象でした。また、TwitterをはじめとしたSNSのアカウントも持っていないような人が大半なのか、#ngtnetのTLは大変寂しいものになってしまいました。

今後に向けては、幹事の@AILightさん、@84taka0310さんとも相談していきますが、講師と生徒のような関係ではなく、もっと参加者の皆さんにガツガツ来てもらえるようなコミュニティにしていくため、何ができるか考えていかなくてはと思いました。地元の中小SIベンダーの一社員といった人に、どうやって動機づけしていくかは、地方コミュニティはどこでも同じ悩みを抱えているかもしれませんね。

 

次回について

少なくとも年2回の開催を目指すため、次回は10月あたりを予定しています。また日取り等決まったら告知します。

過去のバージョンのVisual Studioのライセンスを知る方法

Visual Studioのライセンスについては、Microsoftからライセンス・ホワイトペーパーが公開されています。

Visual StudioとMSDNのライセンス ホワイトペーパー
https://www.microsoft.com/ja-jp/download/details.aspx?id=13350

ただ、こちらからダウンロードできるのは最新バージョン(現時点ではVS2015)のものしかありません。それでは、諸事情で過去のバージョンのライセンスについて知りたい場合はどうすればよいのでしょう?

そんな時は、対象バージョンのCD、DVDメディアをエクスプローラーで開き、ルートにある、「license.htm」ファイルを開けば、おそらく望みのものが得られると思います。実際にメディアがなくとも、MSDNサブスクリプション契約していれば、過去のバージョンのISOファイルがダウンロードできるはずですので、そちらをマウントすればOKです。

DbDataAdapter.DisposeはDbCommandオブジェクトをDisposeしない

大量にDbDataAdapter使うコードで、途中でFillできなくなって調べた結果です。

System.Data.Common.DbDataAdapterにはSystem.Data.IDbDataAdapterインターフェースの実装であるSelect/Insert/Update/DeleteCommandプロパティがあり、これらのプロパティにはSystem.Data.IDbCommand型のオブジェクトの設定/取得が可能です。

そして、DbDataAdapter.Disposeメソッドを呼び出しても、この4つのコマンドオブジェクトはDisposeされず、nullが設定されるだけです。したがって、各プロパティに設定したコマンドオブジェクトは、そのコマンドオブジェクトを生成する側で、明示的にDisposeしてやらないといけません。

[参照]
https://github.com/Microsoft/referencesource/blob/master/System.Data%2FSystem%2FData%2FCommon%2FDbDataAdapter.cs#L236

override protected void Dispose(bool disposing) { // V1.0.3300, MDAC 69629
    if (disposing) { // release mananged objects
        IDbDataAdapter pthis = (IDbDataAdapter) this; // must cast to interface to obtain correct value
        pthis.SelectCommand = null;
        pthis.InsertCommand = null;
        pthis.UpdateCommand = null;
        pthis.DeleteCommand = null;
    }
    // release unmanaged objects
    base.Dispose(disposing); // notify base classes
}

最初、どうしてこうなってるのかなーと思ったのですが、DbDataAdapterはあくまでAdapterであって、Compositionではないからかと納得しました。どういうことかというと、DbDataAdapterへの各コマンドの付け外しは自由自在なので、DbDataAdapterがコマンドオブジェクトの死活管理を行うことはできないんですよね。

ハマりかけてなるほどなぁという話でした。

git | マージのタイミングで毎回gcが発生する際の対処例

gitリポジトリを使った開発中に、何故かマージ動作が起きるタイミングで毎回git gcが実行されてしまう状態になりました。環境は次の通り。


$ git --version
git version 2.6.2.windows.1

マージが発生するコマンド全部(merge、rebase、その他)なので非常にウザいです。で調べてみてもよくわかりません。

そこで試したのが以下の手順

  1. git gc –aggressive
    ガッツリGCやってゴミを減らす
  2. git prune
    自動gcの後に「warning: There are too many unreachable loose objects; run ‘git prune’ to remove them.」と表示されたので実行

これで毎回gcが発生しなくなりました!やったね!

同じ状況になった人は試してみてはいかがでしょうか?