<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>はらぺこ日誌 &#187; 設計</title>
	<atom:link href="https://blog.harapeko.jp/tag/%e8%a8%ad%e8%a8%88/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.harapeko.jp</link>
	<description>株式会社はらぺこ 公式ブログ</description>
	<lastBuildDate>Mon, 30 Oct 2017 14:32:56 +0000</lastBuildDate>
	<language>ja</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.2</generator>
	<item>
		<title>API 開発における要件分析 &#8211; C++ のための API デザイン</title>
		<link>https://blog.harapeko.jp/2014/08/10/apides-requirements/</link>
		<comments>https://blog.harapeko.jp/2014/08/10/apides-requirements/#comments</comments>
		<pubDate>Sun, 10 Aug 2014 13:10:03 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[ユースケース]]></category>
		<category><![CDATA[要件分析]]></category>
		<category><![CDATA[設計]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=346</guid>
		<description><![CDATA[ライブラリ API の設計手法を学ぼうシリーズの第3弾です。前回の記事はこちら。以下の教材を利用しています。  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>ライブラリ API の設計手法を学ぼうシリーズの第3弾です。<a href="http://blog.harapeko.jp/2014/08/06/observer-apides/" title="はらぺこ日誌≫ ブログアーカイブ ≫ Observer パターンでコンソール MVC っぽいことをやってみる - C++ のための API デザイン">前回の記事はこちら</a>。以下の教材を利用しています。</p>
<ul>
<li><a href ='http://www.amazon.co.jp/gp/search/ref=as_li_qf_sp_sr_il?ie=UTF8&#038;camp=247&#038;creative=1211&#038;index=aps&#038;keywords=C%2B%2B%20API%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3&#038;linkCode=as2&#038;tag=harapekoinc-22'>C++ APIデザイン<br />
<img src='http://ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&#038;ASIN=B00EYXMA6Q&#038;Format=_SL250_&#038;ID=AsinImage&#038;MarketPlace=JP&#038;ServiceVersion=20070822&#038;WS=1&#038;tag=harapekoinc-22' border='0' /></a></li>
</ul>
<p>今回から第4章に入ります。4章は C++ での実装の話はなく、設計に入るまでの情報の収集や整理 (要するに要件分析)、および様々なレイヤーでの設計に関する議論となっています。プログラミング実習をするような内容でもないので、要点をまとめながら解釈したり考えたりしたことをレポートしたいと思います。</p>
<p>今回はその中でも、 4.1～4.3節の、要件分析までの内容について見ていきます。</p>
<h3>大原則</h3>
<p>最初のセクションに入る前の書き出しで、以下のように書かれています。これはもう、大原則ですよね… (強調は拙引用者によるものです)。<br />
<span id="more-346"></span></p>
<blockquote title="C++ のための API デザイン - 第4章 デザイン"><p>
…こうしたさまざまな分析テクニックは個別に使っても組み合わせて使っても有用である。とはいえ、<strong>「自分で理解できないことは設計できない」</strong>という原則を常に頭に入れて設計してもらいたい。
</p></blockquote>
<p>このことは、この後に説明されるさまざまな場面において重要な事柄です。システムの構成をうまく分解・整理できない、クラスや関数に適切な名前を付けられない、などといったことは、当該事項に対する理解が不足している証拠であり、そのために情報の収集や議論を重ね、要件を整理するということの繰り返しが必要不可欠になるわけなんですね。(あーしんどい)</p>
<h3>優れた設計の必要性</h3>
<p>4.1節では、優れた設計がなぜ必要なのかを、怖い話を交えて説いています。</p>
<p>…ちょっとだけ愚痴を (強調は拙引用者による)。</p>
<blockquote title="C++ のための API デザイン - 第4章 デザイン - 4.1.3 長期的な設計"><p>
この問題にはもう1つの側面がある。コードの品質を高く保っていかないと、コードの進展とともに当初の設計がしだいに退化していくことだ。デッドラインに間に合わせるための手抜きは、後で戻って修正する限り許される。とにかく、<strong>自分の技術的な負債は必ず後で支払わされることを肝に銘じることだ</strong>。コードというものは、当初開発者が思ったより長く存続するものだ。APIを弱体化するときはこの事実を思い出して欲しい。このつけを長期的にサポートするはめになるのは本人だ。だからこそ、API設計に対する新規要件のインパクトをしっかりと把握し、(…以下略)
</p></blockquote>
<p>…このツケを踏み倒していく技術者のなんと多いことか＿|￣|&#8230;&#8230;&#8230;&#8230;◎ (←お前が言うな)</p>
<h3>機能要件の収集</h3>
<p>4.2節は機能要件について書かれています。まず、ソフトウェア業界における要件の種類を以下の 3つに整理しています (強調は原文ママ)。</p>
<blockquote title="C++ のための API デザイン - 第4章 デザイン - 4.2 機能要件の収集">
<ul>
<li><strong>ビジネス要件</strong>: 事業という意味でのソフトウェアの価値。会社のニーズにどう応えられるか。</li>
<li><strong>機能要件</strong>: ソフトウェアの動作や振る舞い。ソフトウェアが遂行すべき内容。</li>
<li><strong>非機能要件</strong>: ソフトウェアが達成すべき質的水準。ユーザにとってうまく機能する度合い。</li>
</ul>
</blockquote>
<p>そのうえで、 API 開発に際して、上記のうちの機能要件、および (ついでに) 非機能要件について、 API のターゲットユーザーや専門家などからどういった要点で質問し、情報を引き出すべきか、そしてそれらについてどのように整理してまとめ、保守してゆくべきかが説かれています。</p>
<p>ちょっとショッキングな (だけど実感として納得できてしまう) 記述を以下に引用します…。</p>
<blockquote title="C++ のための API デザイン - 第4章 デザイン - 4.2.3 要件の保守"><p>
平均すると、あるプロジェクトで開発期間中に変更する機能要件は 25% あり、そのために書き換えるコードは 70～85% に上るという[52]。クライアントの変化するニーズをしっかり受け止めることは大事なことだが、要件の変更に伴うコストを関係者全員に理解させることも重要である。(…以下略)</p>
<p>(参考文献)<br />
[52] S. McConnell, Code Complete: A Practical Handbook of Software Construction, second ed., Microsoft Press, 2004. ISBN 0735619670. (『Code Complete 第2版〈上〉〈下〉&mdash; 完全なプログラミングを目指して』、スティーブ・マコネル著、クイープ訳、日経BPソフトプレス、2005年)
</p></blockquote>
<p>…この場合、書き換えが発生すると予想できる分だけ余裕を持って見積もるべきなのか、要件の管理を徹底した上で、要件の変更が発生する度に追加の見積もりを計上すべきなのか、どっちなんでしょうかね…。アジャイルなやり方を採用している現場ならもう少し融通も利くのでしょうが、そもそもエンドが動かせないプロジェクトの場合、開発側代表者 (多くの場合、PM?) の交渉手腕、企業の人的リソース配分なども意味を持ってくることに… (考えたくない)</p>
<p># マコネル読め&gt;ヲレ</p>
<h3>ユースケースの作成</h3>
<div class="ad">
<a href="http://www.amazon.co.jp/gp/product/4798101273/ref=as_li_qf_sp_asin_il?ie=UTF8&#038;camp=247&#038;creative=1211&#038;creativeASIN=4798101273&#038;linkCode=as2&#038;tag=harapekoinc-22"><img border="0" src="http://ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&#038;ASIN=4798101273&#038;Format=_SL250_&#038;ID=AsinImage&#038;MarketPlace=JP&#038;ServiceVersion=20070822&#038;WS=1&#038;tag=harapekoinc-22" ><br />
ユースケース実践ガイド &mdash; 効果的なユースケースの書き方<br />
(OOP Foundations)</a>
</div>
<p>4.3節はユースケースについて書かれています。ユースケースの様式 (フォーマットであったり、 UML であったり) よりも、概念や存在意義を始め、書くべき内容やボリューム感、粒度、使うべき言葉、それから向き合い方や取り扱いなどといった実践的な部分について書かれています。</p>
<p>4章で書かれていること全般的に言えることですが、ユースケースについてもあくまで概要レベルで触れられています。ここに書いてあることを読んだだけでも割といい感じで書けそうですが (それだけ要点よくまとまっています)、より深く学びたい人はアリスター・コーバーン著「ユースケース実践ガイド」がお勧めです。</p>
<p>それから、関連する事柄として、 4.3.4 でアジャイル開発での要件の取り扱いとユーザーストーリーについて論じられています。ユーザーストーリーについては以下の部分の引用が端的で分かりやすいのではないでしょうか。</p>
<blockquote title="C++ のための API デザイン - 第4章 デザイン - 4.3.4 要件とアジャイル開発"><p>
(…前略)マイク・コーンはユーザーストーリーについてシンプルな形式を提案している[19]。</p>
<blockquote><p>
私は、 [役割] として [利点] のために [目的物] がほしい。
</p></blockquote>
<p>(参考文献)<br />
[19] M.Cohn, User Stories Applied: For Agile Software Development, Addison-Wesley Professional, 2004. ISBN 0321205685.
</p></blockquote>
<p>私は、プログラマーとして Unicode を内部表現として安全に取り扱える C++ コンパイラと正規表現ライブラリが欲しいです…。</p>
<h3><q>膨大な量の正式な要件文書を維持管理することは迅速《アジャイル》ではない</q></h3>
<p>要件分析について述べられた内容は以上で終わりです。結局本書では、要件を分析する方法論として、機能要件の収集、ユースケース、ユーザーストーリーの 3種類しか挙げていません。しかも、必ずしもそれらをすべて揃えろという話ではなく、プロジェクトの性質に応じて、ユースケースのみを作成する、ユースケースから機能要件を引き出す (もしくはその逆)、ユースケースよりも迅速かつ簡潔な方法としてユーザーストーリーを用いる、などの選択肢がありうることを示唆しています。</p>
<p>要件定義の文書に盛り込むべき内容としてはさまざまなものが要求されることが多いです。入出力要求であるとか、業務フローであるとか…。そして、割と多くの企業や現場で、主に Excel や Excel、それから Excel などを使ってきっちりとした体裁の文書を作成し (悪意が滲み出てるって? きっと気のせいですよ…)、用語の解釈に誤りがないかとか、誤字・脱字はないかとかいったことで延々とレビューを繰り返すという光景が繰り広げられているのではないでしょうか。</p>
<p>もちろん、要件として残すべき資料がこの程度しか考えられないのは開発対象があくまで C++ で実装するような API の開発であり、それは開発者が使うためにリリースされるものであるからそんなもんで充分なんだろうという考え方もできると思います。なにはともあれ、振る舞い要求を分析する方法であるユースケースの説明を行う節の最後にアジャイル手法とユーザーストーリーの説明を交えてくる点も含めて、著者であるマーティン・レディが要件分析に対してどちらを志向しているのかが垣間見れるようにも思えます…。</p>
<p>当然のことながら、ウォーターフォールモデルを悪しき風習であると断じるつもりは (少なくとも私には) 毛頭ありません。それよりは、どんな手法や枠組みを用いるにせよ、形式に従うこと自体を目的にして費やされるコストに、もう少し懐疑的であっても良いのではないか、ということなのだと思います。箇条書きで済む内容だったら Wiki を使うんだっていいわけですし、図だって手書きのものをスキャンしたものを共有とかでもいいわけですし、履歴管理を重視したいなら図も GraphViz で書くという手だってあるわけですし、納品物という形を得たいなら印刷しなくても CD に焼いて納品という手だってあるわけですし…。</p>
<p>最後もなんだか愚痴っぽくなっちゃいましたね <tt>(^_^;</tt>。次回は 4.4節以降、設計の部分についてレポートする予定です。それではまた…。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2014/08/10/apides-requirements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Observer パターンでコンソール MVC っぽいことをやってみる &#8211; C++ のための API デザイン</title>
		<link>https://blog.harapeko.jp/2014/08/06/observer-apides/</link>
		<comments>https://blog.harapeko.jp/2014/08/06/observer-apides/#comments</comments>
		<pubDate>Wed, 06 Aug 2014 09:06:45 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++11]]></category>
		<category><![CDATA[設計]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=319</guid>
		<description><![CDATA[ライブラリ API の設計手法を学ぼうシリーズの第2弾です。前回の記事はこちら。以下の教材を利用しています。  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>ライブラリ API の設計手法を学ぼうシリーズの第2弾です。<a href="http://blog.harapeko.jp/2014/06/19/pimpl-factory-apides/">前回の記事はこちら</a>。以下の教材を利用しています。</p>
<ul>
<li><a href ='http://www.amazon.co.jp/gp/search/ref=as_li_qf_sp_sr_il?ie=UTF8&#038;camp=247&#038;creative=1211&#038;index=aps&#038;keywords=C%2B%2B%20API%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3&#038;linkCode=as2&#038;tag=harapekoinc-22'>C++ APIデザイン<br />
<img src='http://ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&#038;ASIN=B00EYXMA6Q&#038;Format=_SL250_&#038;ID=AsinImage&#038;MarketPlace=JP&#038;ServiceVersion=20070822&#038;WS=1&#038;tag=harapekoinc-22' border='0' /></a></li>
</ul>
<p>さて、API のラッピングパターンについてはざっと読むだけで終了とし、今回は Observer パターンについてさらってみました。</p>
<h3>MVC っぽいことをやってみたい。</h3>
<p>本書では、オブザーバーパターンの説明に入る前に、 MVC アーキテクチャについての説明がありました。</p>
<blockquote cite="http://www.amazon.co.jp/gp/search/ref=as_li_qf_sp_sr_il?ie=UTF8&#038;camp=247&#038;creative=1211&#038;index=aps&#038;keywords=C%2B%2B%20API%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3&#038;linkCode=as2&#038;tag=harapekoinc-22" title="C++ APIデザイン - 3.5.1 モデル/ビュー/コントローラ (p.120)"><p>
シンプルなアプリケーションでは、コントローラはユーザ入力に基づいてモデルへの変更に影響を与え、こうした変更をビューに通信して、UIを更新できるようにする。しかし、実際のアプリケーションでは、通常、水面下のモデルへの追加変更を反映するために、ビューも更新する必要がある。(…中略…)とはいえ、先ほど述べたように、モデルコードはビューコードを静的にバインディングして呼び出すことはできない。そこでオブザーバーが必要になるのだ。
</p></blockquote>
<p>なるほどなるほど。とまぁ、こんな説明の後に Observer パターンの実装例とその説明に入っていくのを見せられたら、そりゃあまぁ、 MVC っぽいことをやってみたい、って普通思いますよね…??</p>
<p>ただ、上記にあるようにモデルがビューを監視できるようにする必要があるという話であるにもかかわらず、多くの MVC フレームワーク実装を見るに、ビューからのメッセージを受け取って何らかの制御を行うコードは通常コントローラに書かれているように見えます。現実的には、ビジネスロジックはフレームワークを差し替えても流用可能であることが望ましく、オブザーバーにするための抽象クラスの継承でさえ避けたいというのが実情なのではないかと思います。<br />
<span id="more-319"></span><br />
そこで、コントローラをビューに対するオブザーバーとする設計とし、ビューが提供するいくつかのメッセージに対して、メッセージハンドラのような感じでコントローラを登録し、実装できるようにする、という考え方でやってみることにしました。ビューはよく使いそうなパターンのものを幾つか用意しておけば、あとは必要に応じてたまーに新しいものを追加する程度の変更で事足りるでしょうが、コントローラは新しい機能を追加するたびに必ず実装を追加することになります。テキスト p.120 の図にも示されている通り、ビューはコントローラの実装を知らないほうが良いのです。モデルはコントローラが掴んで (もしくは生成して)、ビューから呼び出されるハンドラメソッド内で操作するようにすればよいでしょう。</p>
<h3>コンソール画面で動くものを作ってみる。</h3>
<p>MVC アーキテクチャっぽいものを、といっても、具体的に何を作ろうか、というのは悩みどころです。 GUI のものを作るにしても、 Web アプリケーションを作るにしても、結構大掛かりなシステムになってしまうのではないかという不安があります。お試しで作るんですから、簡単なものがいいんですよね…。</p>
<p>というわけで、コンソール画面で動くものを作ることにしよう、ということでプログラムを書いてみることにしました。それも内容的にもごく簡単なものをということで、お題はズバリ、<strong>時計</strong>です。コンソール画面の真ん中らへんで、現在時刻を表示し続けるというだけの、ごくごく簡単なプログラムです。</p>
<h3>作ってみた。</h3>
<p>そんなわけで、作ってみました。ソースコードは以下の場所にて公開しています。</p>
<ul>
<li><a href="https://github.com/murachi/samples-for-blog/tree/master/c%2B%2B/api-design-for-c%2B%2B/ch03-pattern/observer">samples-for-blog/c++/api-design-for-c++/ch03-pattern/observer at master · murachi/samples-for-blog</a></li>
</ul>
<p>このプログラムは <code>std::thread</code> を使ったマルチスレッドプログラムなので、 gcc でコンパイルするときは以下のように、必ず <code>-pthread</code> オプションを付けてあげて下さい。</p>
<pre>
$ g++ -std=c++11 -pthread -o watch *.cpp
$ ./watch
</pre>
<p>プログラムを実行すると、コンソール画面がクリアーされて、画面の真ん中らへんに現在日時がリアルタイムで表示されます。また、画面の下の方に「Hit any key to finish.」と表示されるとおり、なにか適当なキーを押すとプログラムは終了します。<br />
<a href="http://blog.harapeko.jp/wp-content/uploads/2014/08/fig-run-ubuntu.png"><img src="http://blog.harapeko.jp/wp-content/uploads/2014/08/fig-run-ubuntu.png" alt="Ubuntu で実行" title="observer パターン練習プログラムを Ubuntu 環境で実行してみたところ" width="410" height="303" class="alignnone size-full wp-image-334" /></a><br />
<a href="http://blog.harapeko.jp/wp-content/uploads/2014/08/fig-run-windows.png"><img src="http://blog.harapeko.jp/wp-content/uploads/2014/08/fig-run-windows.png" alt="Windows で実行" title="observer パターン練習プログラムを Windows 環境で実行してみたところ" width="338" height="246" class="alignnone size-full wp-image-338" /></a><br />
なお、動作確認は以下の環境にて行いました。</p>
<ul>
<li>Ubuntu Linux 14.04 LTS x86_64/GCC 4.8.2/bash 4.3.11/kernel 3.13.0</li>
<li>Windows7 Professional SP1 x86_64/Mingw_w64 GCC 4.8.2 (powerd by <a href="http://win-builds.org/">Win-builds</a>)/コマンドプロンプト</li>
</ul>
<h3>プログラムの解説など。</h3>
<h4>モデル</h4>
<p>日時の保持と現在日時への更新、といった辺りをビジネスロジックとして実装しています。 datetime.h と datetime.cpp がそれです。</p>
<p>ここはまぁ、日時の取り扱いに Boost.DateTime を使っているという点以外は特筆すべき点も無いんじゃないかと思います。</p>
<h4>ビュー</h4>
<p>コンソール上で動作するビュー全般、ということで console-view.h と console-view.cpp 、より具体的に静的に文字列を表示するだけのビューということで static-text.h と static-text.cpp を、そしてキー入力を待ち受けるためのビューとして key-listener.h と keylistener.cpp を実装しました。また、ビューはオブザーバーを登録して通知を投げるサブジェクトとして実装しています (subject.h 、 subject.cpp)。</p>
<pre>
class SubjectBase : private boost::noncopyable {
    // ...
};

class ConsoleView : public SubjectBase {
    // ...
};

class StaticText : public ConsoleView {
    // ...
};

class KeyListener : public ConsoleView {
    // ...
};
</pre>
<p>SubjectBase クラスについては、これはもう概ね教科書どおりの実装です。 <code>subscribe()</code> メソッドにてメッセージ ID を指定しつつ observer を登録し、何らかのイベントに応じて、そのイベントに対応するメッセージ ID に指定登録されたすべてのオブザーバーに通知を投げる、ということができる仕組みになっています。派生クラスは自身の <code>notifyObserver()</code> メソッドを呼べば、 observer として登録されているコントローラを呼び出すことができるというわけです。</p>
<p>なお、オブザーバーの登録・削除はスレッドセーフになるよう、 Mutex を使ってロックをかけています。オブザーバーへの通知の際にもロックをかけていますが、通知対象となるオブザーバーの配列をコピーするまででロックを解除し、コピーを見て通知を行うようにしています (通知の実行までロックした状態でやるとデッドロックを起こすことがあったので…<tt>^^;</tt>)。</p>
<p>ConsoleView クラスはコンソール上で動作するビューとしての一通りの機能を持つクラス… であるべきなのですが、考えられるすべての機能を盛り込みまくる動機付けもなかったので、とりあえず以下の機能だけ実装しました。</p>
<ul>
<li>以下のステータスの保持と、それに基づく表示
<ul>
<li>表示文字列</li>
<li>表示位置 (コンソール座標)</li>
<li>色番号 (0～7)</li>
</ul>
</li>
<li>上記のステータスを変更すると、それに応じて表示を更新する</li>
<li>タイマー、およびインターバルタイマー</li>
<li>コンソール画面のサイズの取得</li>
</ul>
<p>ステータスの変更は <code>setStatus()</code> メソッドにて行います。ステータスを変更すると即座に表示に反映される、ようにしたかったのですが、例えばテキストも表示位置も色も変更するよ、という場合に、それぞれの値を個別に受け取るようにメソッドを分けてしまうと、一度の変更で再描画が最大 3回も走ってしまう、というのでは激しくダサいなと思ったので、現在のステータスを構造体として受け取って、その内容を書き換えるコールバック関数を受け取るようにしてあります。このコールバック関数は <code>std::function</code> として受け取るようにしてあるので、キャプチャ付きのラムダを指定することも可能です (<a href="http://blog.harapeko.jp/2014/07/25/lambda-ref-captured-constant/" title="はらぺこ日誌» ブログアーカイブ » C++: lambda の参照キャプチャは const 性を損なわない?">こちらの記事</a>でやろうとしていたやつですね<tt>^^;</tt>)。</p>
<p>タイマーとインターバルタイマーは、それぞれ <code>setTimer()</code> と <code>setInterval()</code> 各メソッドを呼ぶことで発動します。どちらも指定した時間が来ると <code>vm_Timer</code> メッセージの通知を observer に投げます。インターバルタイマーの方はこれを <code>stopInterval()</code> を呼ぶまで何度でも繰り返します。今回のプログラムではインターバルタイマーの方だけ使っています。</p>
<p>StaticText クラスはコンソール上の固定の位置に、指定した色で指定したテキストをただ表示するだけのビューとして実装しました。 <code>changeText()</code> メソッドを使うことで、表示するテキストの内容だけ変更することができるようになっています。もっとも、<code>ConsoleView::setStatus()</code> メソッドが public なので、やろうと思えば表示位置や色も変更できてしまうのですが…。</p>
<p>KeyListener クラスは、キー入力を待ち受けし、入力値を取得することができる入力用のビューです。あまりコメントを尽くしていないのでわかりにくいのですが、 <code>initialize()</code> メソッドをオーバーライドしており、オブザーバーに初期化メッセージを投げる前に、この中でキー待受を行うスレッドを生成します。このスレッドがキーの入力を取得すると、今度はオブザーバーにそのことを伝えるメッセージを投げ、オブザーバー側で <code>getKeyChar()</code> メソッドを呼んで入力値を得ることができるようになっています。</p>
<h4>コンソールマネージャ</h4>
<p>コンソール制御は複数存在しうるビューとは切り離して実装する必要があると判断し、コンソールマネージャとして別途実装しています (console-manager.h 、 console-manager.cpp)。内容的にはシングルトンにしたいところなのですが、今回はビューに対して依存性を注入することを前提とした設計ということにしてみました (<code>main()</code> 関数の中で 1つだけインスタンスを生成するイメージ)。</p>
<p>実際に実装した機能は以下のとおりです。</p>
<ul>
<li>インスタンス生成時に画面をクリアする。</li>
<li>インスタンス破棄時にカーソルの現在の文字の色を元に戻す (Windows では白で決め打ちにしちゃってます…)。</li>
<li>コンソール画面のサイズの取得 (<code>getSize()</code>)。</li>
<li>指定したカーソル位置及び色でコンソールに文字列を出力する (<code>output()</code>)。</li>
<li>エコーバックせずにキー入力を受け付ける (<code>waitKeyInput()</code>)。</li>
</ul>
<p>ConsoleView クラスやその派生クラスが提供する機能の具体的な実装は全てここにあります。</p>
<p>最後の <code>waitKeyInput()</code> は、要するに DOS の <code>getch()</code> 関数です (実際、 Windows では <a href="http://msdn.microsoft.com/ja-jp/library/078sfkak.aspx">_getch()</a> 関数を呼んでいます)。当然ブロックします (なので、 KeyListener クラスはスレッドを咬ましてこいつを呼びに行っています)。</p>
<h4>コントローラ</h4>
<p>時計のリアルタイム表示処理を行うコントローラとして watch-controller.h と watch-controller.cpp 、キーが入力されるまでプログラムを実行させ続けるためのコントローラとして wait-controller.h と wait-controller.cpp を実装しました。これらはサブジェクトであるビューから通知を受け取るオブザーバーとして実装しています (observer.h)。</p>
<pre>
class ObserverBase : private boost::noncopyable {
public:
    virtual ~ObserverBase() = default;
    virtual void notify(int message) = 0;
};

class WatchController : public ObserverBase {
    // ...
};

class WaitController : public ObserverBase {
    // ...
};
</pre>
<p>ObserverBase クラスも SubjectBase クラスと同様、教科書通りの実装となっております。通知を受け取る純粋仮想関数 <code>notify()</code> があるだけの簡単なインタフェースです。</p>
<p>WatchController クラスは時計のリアルタイム表示処理を行います。コンストラクタに StaticText インスタンスの参照を受け取り、コンストラクタの中で初期化メッセージとインターバルタイマメッセージ用に自身を登録します。で、初期化メッセージを受け取ったタイミングで StaticText のインターバルタイマ (これは ConsoleView から継承されている機能ですね) を開始し、インターバルタイマメッセージを受け取ったタイミングで、自身がメンバに持つ DateTime オブジェクトの現在時刻更新を行いつつ、 StaticText の表示に反映させる、という仕組みです。</p>
<p>WaitController クラスはキー入力を受け取るまでひたすら待ち続けるという処理を行います。 WatchController だけだと、 インスタンスを生成したはいいけど main 関数が処理から抜けてしまってプログラムがあっという間に終わっちゃうという物悲しい現象が起こってしまうので、何もしないでただ待つだけのスレッドを用意してそれに同期 (join) することで main 関数から抜けないようにして上げる必要があり、その役目を果たすのがこのクラスというわけです。</p>
<p>作りは WatchController に割と似通っていまして、まずコンストラクタに KeyListener インスタンスの参照を受け取り、コンストラクタの中で初期化メッセージとキー入力メッセージ用に自身を登録します。で、初期化メッセージを受け取ったタイミングでコンソールに「Hit any key to finish.」などと表示しつつ、フラグが立つまでひたすら待ち続けるだけのスレッドを作って join します (このため、 <code>KeyListener::initialize()</code> メソッドの呼び出し元がブロックされる)。その直前に KeyListener が生成していたキー入力待ち受けスレッドがキー入力を受け付け、そのメッセージをこのコントローラに投げると、そこで先ほど処理をブロックするためだけに作ったスレッドを終了させるフラグを立て、めでたくブロックされていた処理が開通する、という仕組みです。</p>
<p>両方のコントローラで共通する話なのですが、ビューへのオブザーバー登録はどちらもオブザーバーであるコントローラのコンストラクタの中で行っています。 WatchController での記述を以下に示しますが、</p>
<pre>
WatchController::WatchController(StaticText &amp; text_view)
    : impl{new WatchController::Impl{text_view}}
{
    text_view.subscribe(ConsoleView::vm_Init,
        std::shared_ptr&lt;ObserverBase&gt;{this, [](ObserverBase *){}});
    text_view.subscribe(ConsoleView::vm_Timer,
        std::shared_ptr&lt;ObserverBase&gt;{this, [](ObserverBase *){}});
}
</pre>
<p><code>std::shared_ptr</code> のコンストラクタの第2引数に何もしないラムダを渡すというなんだか気持ちの悪いことをやっていますよね。何でこんなことをやっているのか。サブジェクト側ではオブザーバーインスタンスを shared_ptr でメモリー管理していますが、これはサブジェクトがどのように生成されるかわからないという前提では妥当な設計だと思うのですが、その一方で実際に登録を行うときに、これをオブザーバーのコンストラクタの中でやってしまおう、そうした方がなんだかスマートに書けそうだという場合に、 <code>this</code> ポインタをそのまま shared_ptr に包んでしまうのは非常に危険です。なぜならそのオブザーバーインスタンスはどのように生成されるかわからないし、生成した側がどのような形で管理するかもわからないので、例えばスタック変数として生成した場合や、生成した側でも unique_ptr や shared_ptr に包んで適切に破棄しようとしていた場合には、どちらかの破棄のタイミングで例外が送出される (おそらくは、アプリケーションエラーになる) ことになってしまいます。そうならないように、何もしない deleter を shared_ptr に渡し、 <code>delete</code> が呼ばれるのを防いでいるわけです。メモリーの管理責任の所在については色々と議論もあるでしょうが、私はインスタンスの生成を行った側が、そのインスタンスの破棄についても責任をもつべきだと考えています。</p>
<h4>main関数</h4>
<p>main関数はわかりやすいように main.cpp ファイルに記述しました。まず ConsoleManager インスタンスを生成し、次に日時の表示を行うビュー StaticText とコントローラ WatchController を生成して、ビューの <code>initialize()</code> メソッドを呼ぶ。同様にキー入力待受を行うビュー KeyListener とコントローラ WaitController を生成して、同じくビューの <code>initialize()</code> メソッドを呼ぶ。ただこれだけです。これだけで何でよしなに動いてくれるのか、といった辺りは、ここまでで色々と説明したとおりです… (分かんないかなぁ<tt>^^;</tt>)。</p>
<h3>作ってみた感想など</h3>
<p>前回 Pimpl をさらった時に、テキストに示されていた以外にプラットフォーム依存のコードを各状況というのがなかなか思いつかなくて try 出来なかったのですが、今回 ConsoleManager という形で <code>#ifdef</code> 書きまくることが出来たのはちょっと幸運でした。こういうのは自分で書いてみないと、他人が書いたコードを読むだけではなんだかビビってしまうばかりなので… プラットフォームごとに違うことをやるようなコードを書いて、どっちのプラットフォームでも動くのを確認するのはなかなか爽快ですよ。</p>
<p>KeyListener みたいな仕組みは、本当はビューではなく全く別の枠組みで用意すべきだったのかもしれません。 Windows のメッセージループみたいに書けるのが本当は理想的… なのかなぁ?? (よくわからん)</p>
<p>Windows の方は実際一応動くのですが、キー入力時に時々よく分からんエラーを吐いて終わることがあります (2014/8/6 時点)。何かがツメが甘いのかも…。</p>
<p>より MVC フレームワークチックにやりたいということであれば、他にも色々と改良の余地はあるんじゃないかと思います。埋め込みリソースからビューを生成とか…。</p>
<p>こちらからは以上です。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2014/08/06/observer-apides/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Pimpl とかファクトリとか &#8211; C++ のための API デザイン</title>
		<link>https://blog.harapeko.jp/2014/06/19/pimpl-factory-apides/</link>
		<comments>https://blog.harapeko.jp/2014/06/19/pimpl-factory-apides/#comments</comments>
		<pubDate>Thu, 19 Jun 2014 05:53:55 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[活動記録]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++11]]></category>
		<category><![CDATA[設計]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=304</guid>
		<description><![CDATA[otoco プロジェクトの開発に着手するにあたって、私はまだ C++ でのライブラリ開発を 1 からコーディネ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a href="http://developer.harapeko.jp/trac/original/otoco">otoco プロジェクト</a>の開発に着手するにあたって、私はまだ C++ でのライブラリ開発を 1 からコーディネートした経験がなかったので、クロスプラットフォームに対応したライブラリ API の開発手法を学ぶ必要があると感じました。ちょうどいい感じの教材が割りと最近出ていたようで、早速購入し、勉強を進めています。</p>
<ul>
<li><a href ='http://www.amazon.co.jp/gp/search/ref=as_li_qf_sp_sr_il?ie=UTF8&#038;camp=247&#038;creative=1211&#038;index=aps&#038;keywords=C%2B%2B%20API%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3&#038;linkCode=as2&#038;tag=harapekoinc-22'>C++ APIデザイン<br />
<img src='http://ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&#038;ASIN=B00EYXMA6Q&#038;Format=_SL250_&#038;ID=AsinImage&#038;MarketPlace=JP&#038;ServiceVersion=20070822&#038;WS=1&#038;tag=harapekoinc-22' border='0' /></a></li>
</ul>
<p>C++11 についても若干触れられているようで (原著執筆当時はまだ C++0x と呼ばれていた模様…)、この手の教材の中では比較的情報が新しい方なんではないかと思われます。</p>
<p>実はこの本を買って勉強し始めたのはもう結構前 (確か前原にいた頃… 昨年の暮れ頃?) なのですが、ここしばらく本業やら引っ越しやらが忙しくてなかなか手を回せずにいたので、久しぶりの着手ということで、すでに履修していた第3章の、 Pimpl イディオムとファクトリメソッド辺りを復習してみました。<br />
<span id="more-304"></span><br />
今度こそ本腰を入れてちゃんとやろう、ということで、<a href="https://github.com/murachi/samples-for-blog/tree/master/c%2B%2B/api-design-for-c%2B%2B" title="samples-for-blog/c++/api-design-for-c++ at master · murachi/samples-for-blog">練習用に書いたサンプルプログラムは github に up しております</a>。 git の練習も兼ねているのですが…。</p>
<h3>Pimpl イディオム</h3>
<p>C++ でライブラリを実装するのに際して最も基本的とも言うべきテクニックです。 2章の中で、優れた API の特徴について議論されていますが、その中でも Pimpl イディオムは、プラットフォーム独立性を高める働きと、結合度を削減する働きを担っています。本書のサンプルではタイマーを取り上げ、 Unix の getTimeOfDay(2) システムコールと Win32 の <code>GetTickCount()</code> API の両方に対応する場合に、 Pimpl イディオムを用いて実装の詳細をヘッダーファイルから <code>.cpp</code> ファイルへ隠すというものでした。</p>
<ul>
<li><a href="https://github.com/murachi/samples-for-blog/tree/master/c%2B%2B/api-design-for-c%2B%2B/ch03-pattern/pimpl" title="samples-for-blog/c++/api-design-for-c++/ch03-pattern/pimpl at master · murachi/samples-for-blog">Pimpl イディオムのサンプルプログラム</a></li>
</ul>
<p>私が書いたサンプルもほぼ同内容です (メインルーチンはお馴染みの? あほプログラムでやんす)。強いて違いを言えば、 Pimpl を <code>std::unique_ptr</code> に突っ込んでいること (本書では <code>boost::scoped_ptr</code> を採用していました) ぐらいでしょうか。</p>
<h3>ファクトリメソッド</h3>
<p>本書では Pimpl イディオムの次にシングルトンパターンを解説していますが、今回はここは一旦飛ばして (書かれていることは有用なので、目を通すことはおすすめします)、ファクトリメソッドの方をさらってみました。</p>
<p>本書で紹介されているファクトリメソッドは、 GoF のファクトリメソッドパターンとは若干異なるようで、 Creator の継承と Product の継承を連動させて云々、というものではなく、単に値による指定で生成するオブジェクトの種類を切り替えるという類のもののようでした。これはこれで、例えばプラグインの実装なんかでは役に立ちそうなテクニックだとは思います。</p>
<ul>
<li><a href="https://github.com/murachi/samples-for-blog/tree/master/c%2B%2B/api-design-for-c%2B%2B/ch03-pattern/factory" title="samples-for-blog/c++/api-design-for-c++/ch03-pattern/factory at master · murachi/samples-for-blog">ファクトリメソッドのサンプルプログラム</a></li>
</ul>
<p>拡張可能なファクトリの応用として、ファクトリ登録を生成されるオブジェクトのクラス毎に行うようにし、 Product の追加が行いやすいような設計にしてみました。この用途に限れば登録解除は不要だろうということで、登録用のメソッドのみ用意。ファクトリ名とコールバックの保存には、グローバル変数<strong>ではなく</strong>、関数内 <code>static</code> 変数として用意した <code>std::unordered_map</code> に格納することで、コンパイル単位をまたいだ非ローカル静的オブジェクトの初期化順に伴うSEGVりを回避しています (この辺のことはそれこそ本書のシングルトンの項にて、 Scott Meyers の言葉を引用しつつ説明されています)。</p>
<p>また、せっかくなので極力 Pimpl を用いるようにしてみました。プラットフォーム独立性も重要ですが、それを考慮する必要のない場面でも、 <code>private</code> メソッドの追加・変更に伴う再コンパイルを気にする必要がなくなることによるメンテナンス性の向上 (修正・改変・リファクタリングのやりやすさ) は非常に重要です。今回作った中では、特に <code>Base64Converter</code> クラスの実装がまぁまぁいいサンプルになったんじゃないかと思います (…<code>Base64Map</code>クラスも <code>.cpp</code> ファイルの中に隠しちゃってもよかったかもなぁ…)。</p>
<p>今回はここまで。次回があれば、今度はラッピングパターン、オブザーバーパターンあたりをさらえればと思います。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2014/06/19/pimpl-factory-apides/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>システム構成仕様がとりあえず完成。</title>
		<link>https://blog.harapeko.jp/2009/07/07/system-structure-spec-completed/</link>
		<comments>https://blog.harapeko.jp/2009/07/07/system-structure-spec-completed/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 23:52:19 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[活動記録]]></category>
		<category><![CDATA[otoco]]></category>
		<category><![CDATA[設計]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=83</guid>
		<description><![CDATA[こんなんできました～。 …なんか、UI と I/O の関係図にデータの流れも含まれてるなぁ。これだったらデータ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a href="http://developer.harapeko.jp/trac/original/otoco/wiki/%E5%A4%96%E9%83%A8%E4%BB%95%E6%A7%98/%E5%9F%BA%E6%9C%AC%E4%BB%95%E6%A7%98/%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A7%8B%E6%88%90%E4%BB%95%E6%A7%98">こんなんできました～</a>。</p>
<p>…なんか、UI と I/O の関係図にデータの流れも含まれてるなぁ。これだったらデータの流れ図要らなかったかも…。ていうか、基本的にはここでやりたかったのは必要な UI の可視化なので、実行時オプション、設定ファイル、警告出力、そして各種操作が、各処理とどう関係するか、という部分だけ書いて、データの流れは含めるべきではなかったかも…。あと端子で書いた 3つの出力もデータの流れ図で示すべきだったかも…。データの流れ図ではファイルと見分けが付かないしなぁ…。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2009/07/07/system-structure-spec-completed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UI と I/O の関係図を作成中…</title>
		<link>https://blog.harapeko.jp/2009/07/06/editing-ui-to-io-spec/</link>
		<comments>https://blog.harapeko.jp/2009/07/06/editing-ui-to-io-spec/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 00:56:06 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[活動記録]]></category>
		<category><![CDATA[otoco]]></category>
		<category><![CDATA[設計]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=80</guid>
		<description><![CDATA[なんだけど、いまいちしっくりこないので、まだ未公開です…。ちょっと時間をかけすぎてしまった (1時間以上オーバ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>なんだけど、いまいちしっくりこないので、まだ未公開です…。ちょっと時間をかけすぎてしまった (1時間以上オーバー^_^;)。</p>
<p>…操作と入出力がごっちゃになっちゃってるなぁ。入力はファイルを規定しているのに出力はそれを規定しないからアンバランスになってるんだろうな。操作が処理を呼び出す関係と処理による入出力の関係は切り離さないとな。出力はどうやって示そう? コネクタが良いのかなぁ… (以上独り言)</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2009/07/06/editing-ui-to-io-spec/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>データの流れを設計してみた。</title>
		<link>https://blog.harapeko.jp/2009/07/05/data-flow-spec/</link>
		<comments>https://blog.harapeko.jp/2009/07/05/data-flow-spec/#comments</comments>
		<pubDate>Sun, 05 Jul 2009 03:47:59 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[活動記録]]></category>
		<category><![CDATA[otoco]]></category>
		<category><![CDATA[設計]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=76</guid>
		<description><![CDATA[otoco の処理におけるデータの流れを書いてみました。この奇っ怪な図の作図には OpenOffice.org [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a href="http://developer.harapeko.jp/trac/original/otoco/wiki/%E5%A4%96%E9%83%A8%E4%BB%95%E6%A7%98/%E5%9F%BA%E6%9C%AC%E4%BB%95%E6%A7%98/%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A7%8B%E6%88%90%E4%BB%95%E6%A7%98#data-flow">otoco の処理におけるデータの流れ</a>を書いてみました。この奇っ怪な図の作図には OpenOffice.org の Draw を利用しています。</p>
<p>この手のツールの場合、データの流れはそのまま必要な処理を浮き彫りにするので、システムの構成を表現する情報の一つとして重要な資料になります。そして、実際のモジュール構成をもろに規定する仕様とはならないので、あくまで外部仕様として扱うことができるのも大きな利点です。</p>
<p>明日以降はこれに加えて、UI と処理との関係を設計します。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2009/07/05/data-flow-spec/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
