〜JUnitでのテスト駆動型開発1〜ツイート今回はJUnitを使用して開発を行います。言っても今まで作成していたクラスの実装を行うというだけです。テスト仕様を作成するのですが、これは前回作成したので割愛します。JUnit前回、JUnitが動くことを確認するプログラムを作成しました。今回は、設計部分から。早い話が「どー動けば良いか?」を考えることから実装を始めたいと思います。テスト駆動テストケース(どう動くか?)を作成することから初めていきます。<仕様部分>指定のファイルが存在すれば、ファイルを参照することができ、ファイルが存在しなけでば、ファイルを作成する。今回はこの部分のみを実装します。初めにテストクラスの構成ですが、書くテストケースを実行する前にテスト対象クラスのインスタンスを新規で作成します。@Beforeアノテーションをつけてやるとそのメソッドはテストケースの実行前に起動します。KozaManager();}そして、問題のテストケースですが、プログラムレベルでまずは、ファイルの読み書き用クラスのインスタンスが取得できないと話にならないのでその起動確認を行います。assertを使用できることがJUnitの魅力でもあります。AssertとはJUnitのフレームワークで使用できる想定通りに動いたか確認するためのメソッドです。使い方は以下の通りです。import」して使用しています。メソッドを直接呼ぶことができます。assertNotNullなどの確認用メソッドです、上の場合だとtargetがNullの時にエラーを吐きます。"aaa");の様に使用し値が等しくない時にエラーを吐きます。メソッドの中で完結しないのですが、@Beforeでコンストラクタを起動しているので、テストケースとしては実行済みになりますので、インスタンスがtargetの中に入っているかどうかの確認を行います。問題の「ファイルを読み込むためのクラス」は以下の様に処理を行っています。下のクラスはテスト対象クラスです。System.out.println("ファイルオープンに失敗しました。}}とりあえずは、このテストがうまくいく様に作成します。今回のはコンストラクタを起動するだけ、しかもテストケースと呼べる様なものではないのでよろしくはないのですが、コンストラクタで必要なインスタンスなどを作成しないことには何も始まらないのでこの様になりました。ポイントテストケースを作成する前の準備コンストラクタでテストケースに関連する部分を含むがテストを行ったことにはしないとりあえずはここまでにします。〜テスト駆動型開発を行う〜ツイート今回は、JUnitを使用して以下のことを実行します。世間ではいろいろなことが言われていますが、シンプルに「テスト仕様から作成する方法」という意味で記載しています。シンプルに「テスト仕様から作成する」ということはどいうことかに関して、ちょいと記載します。早い話が、「このクラスはどう動けば良いの?」から考える実装方法だと思っています。「テスト駆動型開発」という言葉を作った人間ではないので、この様な書き方になります。ちなみに、JUnitが使用できるかどうかに関しては下の様に「JUnit」がワークスペース上に表示されていれば大丈夫です。例外として、存在するけど動かないということもありますが、それはエラーが出力され、コンソールに「XXXException」と表示されるのでそれをインターネットで調べてみると解決します。ちなみに、自分の場合は以下の様にアノテーションをつけてやると動きました。Springなどのフレームワークを使用している場合は、それぞれのテストさ癖方法があるのでそちらを参照されたし。{テストケース}テスト仕様を考える前回作成した、仕様と設計より「口座管理クラス」を作成することにしました。この口座管理クラスはファイルを使用してデータを保存したり、更新したりします。本番で使用するクラスとテストクラスを分けるために以下の様に完全クラス名は同じだけどルートフォルダが違う形で作成します。今回作成するクラスは、KozaManagerクラスです。テストクラスは下の様に「test」フォルダいかに作成します。テスト仕様テスト仕様というと堅苦しい感じがしますが、早い話が「どう動けば良いか?」を決めるところです。今回はファイルに出力するだけなので深く考えません。CSVファイルを作成CSVファイルはカンマ区切りのテキストファイルです。...この様な形で、データを保存します。今回は、口座情報なのと最小限度の情報を登録するので、ユーザーとパスワード、預金額をデータとして保存します。テストが動くか確認します。}}ちなみに、コンストラクタを動かしたくないので今はコメントアウトしています。テストが動くか確認します。動かしてみた結果です。今日はこの辺で失礼します。〜オブジェクト指向的分析、アプリ拡張の実装とテスト〜ツイート今回は、作成した仕様、設計した機能に関して実装していこうと思います。前回作成した仕様、機能に関しては以下にまとめておきます。口座の預金額と口座を持っている人を一意にするそして、上の仕様をいっぺんに実装するのは自分の頭では追いつかないので諦めて、1つずつ考えていこうと思います。仕様1「口座を開設している人の情報を保存する」に関して、ますは「口座を開設する」機能が必要です。いうかこれがないとこれ以降の機能が実装できません。?口座が作成されないと口座を開設している人が追加できない、つまり口座を持っている人が0人のまま。いうことになるからです。ファイルには、カンマ区切りの「CSV」形式でデータを登録するファイル入出力の実装やっと実装にたどり着きました。ここまで来た方おめでとうございます。このページに来た方、ブログなのでいつでもこれ以前の記事を参照できます。下のリンクで一覧が見れます。よかったらチャレンジしてみてください。学習フロー」java.io.Fileクラスこのクラスを使用してファイルの操作を行います。ここで注意して欲しいのは「Fileクラス」はファイル、ディレクトリ(フォルダ)を表現するクラスであり、「入出力」は別のクラスを使用する必要があるというところです。java.io.BufferedWriterクラス上のFileクラスと併用してこのクラスでファイルへの書き出しを行います。四の五の言っても意味がないので、コードから見ていきます。上の2クラスの作成(生成)を行います。口座を操作、管理するクラスは「KozaManager」と名付けました。System.out.println("ファイルオープンに失敗しました。}}コンストラクタで、ファイルの書き出し、読み込みクラスを作成(生成)しています。{...}」リーダー(BufferedReader)を作成しています。}で例外処理を作成しています。私事ではありますが、「テスト」に対しての認識を共有したく思い「テスト駆動開発」でやっていきたいと思っています。このテスト駆動型開発は「仕様を明確にする」のが至上命令で、「どーゆー風に動けば良いか?」を一番に考えます。なんか当たり前な話に聞こえますが、「当たり前」はできていなくてはならない(実際難しい。頑張りましょう(笑)というわけで、テストケースから作成していきます。詳細に関してはこちらを参照してくださいwwww。余談テスト駆動型開発がオススメな理由、というか自分の考えですが、テストケースがちゃんとできていれば「テストが通れば、実装内容はほぼ自由」で良いことになります。リファクタリングをするにも「テストが通ればデグレートの心配はない」ということになります。テストは自動で実行できるツール(Mavenなど)があるので、テスト処理を流して帰宅するのもおっけーです(作業時間に余裕が必要ですが。今回のテストはファイルの読み込みと書き出しができることを確認するためのケースを作成します。このテストケースを通る(エラーが出ない)のであれば実装は完了になります。考えなくてはいけないのがいかになります。操作するファイルが存在しなければ、作成し、存在すればそのまま参照する同様にファイルへ(口座の)ユーザー情報をファイル(CSV形式)への出力、保存ができること同様にファイルの読み込みができること読み込んだファイルのデータをユーザー情報クラスで取得できること(同様にファイルへ出力できること)上の4項目を満たすようなクラスができれば、現状はおっけーです。今回は、ここまでにします。〜オブジェクト指向的分析、アプリの拡張をする〜ツイート今回は、コーダー銀行(コンソールアプリ)の拡張をします。今までに、以下の内容を実施(記載)してきました。現状の処理としては、コーダー銀行への「入金」と「引き出し」ができるだけであまり役に立たなそうです。今度はもっと銀行らしく口座の開設機能を作る方向へ向けて機能拡張を考えて見たいと思います。するときには「どこを拡張するか?」つまり「コードのどの部分をどのように修正するか?」という疑問に答える必要があります。そこで、今までの作成したものを、確認がてらに見直して「修正ポイント」を探し、拡張するための設計を行いたいと思います。「どのようなことを実現するか?」を初めに考える必要があります。今回の場合は「コーダー銀行の口座開設」が実現したいことなので、口座の開設のために必要なことを考えます。大まかにこんな感じだと思います。細かいと複雑になりクラス設計がややこしくなるので、今回は学習目的なのでこの程度の仕様にしておきます。今動いているアプリは下のような感じで動きます。チェック処理」を担当するクラスになっています。※実際のソースはGitにアップしています。ちなみに、パッケージは下のようになっています。「jp/zenryoku/apps/atm」/atm/MainBank.java(メイン処理)/atm/Calcuration.java(預金額管理)/atm/checker/InputChecker.java(チェック処理)実装ポイント口座の開設処理を行う前に、現状では「入金」と「引き出し」の機能しかありません。この場合だとコーダー銀行の口座は一人だけで誰でも引き出しができてしまうので安全ではありません(学習ようなので。1つずつ問題を解消していきますが、まずは口座を開設する機能が必要です。ユーザー(口座保持者)と口座を結びつける処理などは、後で考えます。業務アプリ(〜銀行さんとかで使用しているもの)は、ものすごい人数が利用できるように「データベース(DB)」を使用しています。DBを使用する前に、「ファイル操作」に関して理解する必要があるのでそのように実装いたします。ファイルに口座情報を保存する今回作成する「コーダー銀行アプリ」は学習ようなので本物のように個人情報をてんこ盛りにしたような実装はしません。単純に作成するため必要最低限の項目のみを使用します。それは以下に示します。名前(ヘボン式のローマ字)パスワードそして、今回実装する処理としては。ファイルにデータを登録する処理この機能を実装するのには、今までのやり方からすると「ファイルにデータを登録する役割」のあるクラスを作成し、そのクラスに処理を実装する、ということになります。これもオブジェクト指向の基本になります。くどいようですが、「役割分担をちゃんとやりましょう」ということです。設計を行うここまできたら、察しの良い人は「ファイル操作クラスを作るんでしょ?」と思うかもしれません。その通りでございます。実装する内容は以下のようになります。自分で作成したものは「自分で好きなように改造できる」ので、想像を膨らませて「面白いもの」を作ってみるのも良い学習になります。まとめ上記の内容をまとめると以下のようになりました。ファイルには、カンマ区切りの「CSV」形式でデータを登録する次回は、ここで作成した仕様に基づき実際にコードを作成(実装)してみようと思います。〜チェック処理クラスを作る〜ツイート今回も、下のような作成したクラスをカスタムして、入力チェック処理を作成します。コーダー銀行の入力チェック処理を作成してみようと思います。なんども、同じようなことを記載しますが、オブジェクト指向プログラミングでは「役割分担」が大切です。大雑把に以下のような形(イメージ)で実装します。「〜担当のクラス」という役割を割り当てやるメイン処理で呼び出してやる。コードで書くと下のような感じです。A.処理のはじめ「いらっしゃいませ」という挨拶部分。");System.out.println("入金の時は「in」、引き出しの時は「out」を、終了する時は「bye」を入力してください。System.out.println("入金処理を行います。System.out.println("引出し処理を行います。System.out.println("「in」か「out」を入力してください。}}処理の終わりSystem.out.println("ATM処理を終了します。ご利用ありがとうございました。");こんな感じ(イメージ)です。「なんだ、処理を区分けして説明しただけぢゃねぇか。」と思った方、その通りでございます。「処理を区分け」することがはじめの一歩目になります。アプリを起動してコンソールから「引き出す」「入金」を選択するそれぞれの処理に対して「預金額」から足し算、引き算を行いその結果を表示するこのアプリを作成するために作った「部品」は以下の通りです。メインメソッドを持ち、入力の受付も行うクラス入金、引き出しを行う計算処理クラス早い話が、以下のようなクラスを作成するということです。今回のミッションは「入力チェック処理」を作成することです。「入力処理」を担当するクラスを確認します。上記より、1のメイン処理を作成するクラスがそのクラスになります。入力処理ズバリ、Scannerクラスを使用しているところです。input.nextLine();の部分が入力を受け取っている処理です。このScannerクラスは、java.utilパッケージにあります。入力された値をStringクラスで受け取ります。入力された値が妥当かチェックしようという分けです。チェック処理チェック処理は、以下のようなものを作成しようと思います。入力チェック「in」か「out」「bye」の入力以外はエラーにするそして、入力チェック処理(クラス)を作成したら、ソースの整理をします。入力チェック処理は、今回の目玉なので処理内容を記載しません。その代わり、チェック処理を作成した後の整理(リファクタリング)部分について記載します。現在の入力部分は以下のようになっています。※他にもありますが、今回はこの部分を対象とします。System.out.println("入金処理を行います。System.out.println("引出し処理を行います。System.out.println("「in」か「out」を入力してください。}}無限ループする処理の中です。入力チェックと無限ループは関係ありません。(オブジェクト間の依存関係がないということです)ただし、コード上ではループの中で入力チェックを行うので関連性があります。input.nextLine();をはっきりと分けて考えるために記載しました。以下のようにチェック処理を独立させたいということです。入力チェック処理を担当するクラスを作成し、そのクラスが入力チェックを行うようにするこうすることで何が変わるか?ということなのですが、これはチェック処理の内容のみを変更したいときにすぐに追加・変更が可能なようにするということです。チェック処理を独立させるズバリ、チェッククラスを作成します。名前は「InputChecker」にします。以下のような実装にします。System.out.println("入金処理を行います。System.out.println("引出し処理を行います。}}これで、処理中にエラーがあった場合、は上のコードの一部のみを実行するだけで良いので、無駄な処理を行わなくて済見ます。下のコードのみを実行するだけになります。}今回は、ここまでにしておきます。〜コンストラクタの役割を見る〜ツイート今回は、以前作成したアプリ=「コーダー銀行ATMアプリ」をカスタムしながら、javaで提供されているAPIの使い方を何個か見てみようと思います。Stringすでに使用しているクラスです。文字列として使用します。文字列の比較もします。編集、切り出しなどいろいろなメソッドがあるので、一部抜粋して見ます。equals()メソッドsubstring()メソッドvalueOf()メソッドこれらのメソッドはよく使うと思われるので、紹介いたします。System.out.println("テストです。「1」3番目は「int型」から「文字列(String)型」へ変換しています。コンストラクタで預金額を1000に設定しています。これをコンストラクタに渡した値で預金額を初期化できるように修正するにはどうしたら良いでしょうか?」ヒント;ソースのダウンロードはこちらからできますどこを修正すれば良いか?初めに考えるのは上記の疑問に答えるための答えを考えます。問題にある「コンストラクタで。」という部分に着目します。コードを見てみると下のようになっています。Calcuration();}これでCalcurationクラスを初期化しています。1000;}上のようになっています。コンストラクタは引数なしなので、預金額に直接「1000」を代入しています。ここまで記載すれば、答えは見えてくると思います。【問題2】このアプリにはバグがあります。それを見つけて修正してください。今のところ自分が認識しているのは入力したときにあるバグなのですが、そのほかにもあるかもしれません。いうと、テストをしていないからです。本番環境(サーバー)にリリースしようと考えている人は絶対に真似しないようにしてください。テストはちゃんとやりましょう。この問題の答えは書きません。見つけて見てください。〜設計後の部品を実装する2〜ツイート今回は、部品の設計を行った後の、実装を行います。(設計で)作成したクラスは以下の通りです。MainBankクラスCalcurationクラスオブジェクト指向Lv1オブジェクト指向で作り始めるとだんだん話が大きくなってしまうので、ここでは小さく、わかりやすく実装しようと思います。作成するクラスは上記の通りですので、これらをシンプルに実装します。MainBakクラスメインメソッドは、以下になります。main.atm();}2行で終わりました。いうのは冗談として、最終的なソースはGitにコミットしておきます。(本当はPUSHですが。)ここまできたら、あとは創意工夫がモノを言うので、ここでは実装した結果を記載したいと思います。一覧と言っても、2つのクラスしかないので、大したことはないのですが、簡単に説明だけつけておきます。このクラスのatm()メソッドを呼び出します。コンソール表示を行い、入金、引き出しのどちらかの処理を呼び出す。第二引数のbooleanで入金か引き出しか判定する。あとは入金なら足し算、引き出しなら引き算を行う。他のメソッドは細かい入力チェック、計算処理これらのクラス関係MainBankクラスはフィールドにCalcurationクラスを持っている。このクラスがアプリケーションのメインを担当する。これに対して、Calcurationクラスは、入金、引き出し処理の担当を行い。フィールドには預金額を保持するようにしている。入金、引き出しの処理で預金額が加算されたり、減算される。コンストラクタについてコンストラクタはクラスのインスタンスを作るときに通るメソッドのようなものでクラスの初期化を行う。引数のあるなしによりコンストラクタは区別される。}上の2つのコンストラクタはJVMによって区別されます。メインメソッドでコンストラクタを呼び出したときに処理が走る場所が変わります。サンプルコードをいかに記載しいます。MainBank(1008);このようにコンストラクタを複数作るのは、初期化するパターンを何個か作成したいからです。「パターンはいらんな。」という場合はこのようにコンストラクタを複数作らなければ良いのです。上のように「引数あり」と「引数なし」のコンストラクタ(メソッド)を作成することを「オーバーロード」と言いいます。のちに、「オーバーライド」という言葉も出てくるので混同しないようにしましょう。〜クラス設計から実装〜ツイート今回は、クラスの設計〜実装までの簡単な流れを記載したいと思います。オブジェクト指向プログラミングの始まりです。オブジェクト指向よく世間巷では「オブジェクト指向言語」などという言葉が使われていますが、これは「オブジェクト指向で作りやすい」という意味です。オブジェクト指向言語(今回はJava)で非オブジェクト指向プログラミングをすると下のようになります。}}ポイントとしては、以下の部分がオブジェクト指向プログラミングではありません。プログラムのほとんどを1つのメソッドに書いているので、変更を加えようとすると必ずこのファイルを修正しないといけません。処理の内容が少ないので問題ありませんが、処理が分割されておらず「〜の処理はXXXにまとめる」というように処理が分割されていない。結局は小さなプログラムではあまり効果がないのですが、何かのアプリケーションを作成しようとした時に威力を発揮します。簡単なアプリを作るコンソールアプリになりますが、簡単に作成して行こう思います。詳細部分に関しては上記のリンク先を参照していただきたく思います。簡単に「ATMのようなアプリケーション」を作成してみようと思います。全体の流れ(ユースケース)「全体の流れ」と記載しましたが、「人が使うときの流れ=ユースケース」になります。実際のATMとはかけ離れてしまいますが。<ユースケース>【前提】コンソール画面のATMとします。ユーザー認証は行いません。単純に金額を入金、引き出しができるものを作ります。【仕様】アプリを起動してコンソールから「引き出す」「入金」を選択するそれぞれの処理に対して「預金額」から足し算、引き算を行いその結果を表示する仕様としては単純なものです。これをサンプルとして作成することを考えます。必要な機能を考えるはっきり言ってこの部分には「正解」というものがありません。ある意味「なんでも良い」のかもしれませんが、なるべく効率の良いものを作りたいと思うのが人情です。そのために必要なことは以下のようになります。無駄な処理を行わないということです。そのためにクラスを作成し役割分担を行います。上のケースで行くと、以下の要件が出てきます。大雑把に3つの要件が出てきます。要件を満たす部品を考える【前提】コンソールアプリなのでメインメソッドを動かす中で全ての作業(入金、引き出しなど)を表現します。<部品候補>メインメソッドを持ち、入力の受付も行うクラス入金、引き出しを行う計算処理クラス大雑把に2つの部品を作る事で、役割を分担し、要件を満たすことができそうです。今回はここまでにします。〜クラス型変数の使い方〜ツイートJavaで作成したクラスを使う方法を記載します。クラスの作成は、以下のようにコードを書くと作れます。null;のように使用するときの使用するときの話です。今回は、作成したクラスの中にメインメソッドを作り、自分のクラスを変数に代入して使用します。下にサンプルコードを示します。}}シンプルにこんな形でコードを作成しました。「書き方」と同じ構成なのでわかりやすいと思いますが、いかがでしょうか?細かい説明は省きますが、メインメソッドの場合は、クラスをnewして使用しないとクラス内のメソッドを使用することができません。クラスからクラスを呼ぶ上のコードともう1つ作成して見ます。}}はじめのクラスに「メインメソッド」がないだけの同じうようなクラスです。はじめのクラスをちょっと修正します。}}このような形でメインメソッドから他の作成したクラスを呼び出します。java.lang.XXXのようなクラスもこれと同じようにメソッドを呼び出し使用することができます。いいかのコードはjava.lang.Stringクラスの「equals()」を使用しています。}}「"(ダブルクォーテーション)」で囲った文字はStringクラスとみなされます。こんな感じでしょうか?でわでわ。〜クラスの作り方〜ツイート今回は、クラスの作り方をやります。以前似たようなことをやっていますが、違う視点で記載します。クラスの作り方とりあえずは、構文(書き方)を記載します。}}簡単に書くと、上のように書きます。単純に「new」することです。この「new」を行うとクラスの中の「メンバ」が使用可能になります。具体的には、以下の通りです。上のコードを参考に記載します。インスタンス化不要メインメソッドがインスタンス化しなくても使用できます。本当は「static」がついているので「静的メソッド」とか呼ばれるメソッドですが、後々にこの部分は記載します。インスタンス化必要メンバXXXはインスタンス化が必要です。具体的には上のフィールド変数、メンバーメソッドはインスタンス化しないと使用できません。「なんでか」って?インスタンス化することで、クラスがただの「型」だったのがインスタンス(メモリ領域を確保)して、フィールド変数、メンバメソッドを使用するためのメモリ領域を確保、インスタンスとしてクラスを1つ生成するので、使用可能になります、。わかりやすくあるウェブサーバーでユーザーがログインする時のケースで考えます。この時に、ユーザークラスは「ログイン」する前はインスタンスがありませんが、ログインする時に、ユーザーの情報をDBから取得し、インスタン化してデータをクラスにセットします。これは、ユーザーがログインした文だけ(つまりユーザーの数だけ)インスタンスが生成されます。World」をコンソールに出力するクラスを作成してください。上で作成したクラスに「kogeki()」メソッドを追加して、同様にコンソールに「勇者の攻撃!はぐれプログラマに8のダメージ。」と出力してください。