<?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/category/tech/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>Python 習得中 &#8211; その 6</title>
		<link>https://blog.harapeko.jp/2017/04/09/python-learning-6/</link>
		<comments>https://blog.harapeko.jp/2017/04/09/python-learning-6/#comments</comments>
		<pubDate>Sun, 09 Apr 2017 06:13:53 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=401</guid>
		<description><![CDATA[今回は 5章、モジュールの import の仕方やモジュールの書き方、あとはいくつかの標準ライブラリの紹介です [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>今回は 5章、モジュールの import の仕方やモジュールの書き方、あとはいくつかの標準ライブラリの紹介です。</p>
<p>手元ではもう概ね読了しています。ブログに書くのは一旦ここまでで終了しようかなと思っています… こうやって書き出すよりいろいろ作って実践していったほうが身につくのは早そうなので…。</p>
<p><span id="more-401"></span></p>
<h3>モジュールのパッケージ</h3>
<ol>
<li>ライブラリパスの通ったディレクトリ下にディレクトリを作成</li>
<li>その下に Python モジュールとして読み込ませるクラスや関数を書いた <code>.py</code> ファイルを作成</li>
<li>↑と同じ場所に <code>__init__.py</code> という名前の空のファイルを作成</li>
</ol>
<p>ロードするときは、ディレクトリ名が <code>package_dir</code> で、その配下にある <code>hoge.py</code> ファイルに定義されたクラスや関数をすべてロードする場合、以下の通りとなる。</p>
<pre>
from package_dir import hoge

# MyHogeHoge クラスのコンストラクタを呼ぶ場合
x = hoge.MyHogeHoge('params', '...')
</pre>
<p>名前空間はディレクトリ名、ファイル名にがっつり依存するので、ファイル構成は結構気をつけたほうが良さそうです…。</p>
<h3><code>defaultdict</code></h3>
<p>Python の辞書は存在しないキーを指定して参照しようとするとエラーになるので、キーが存在しない可能性がある場合は <code>in</code> でテストするか <code>get()</code> メソッド (存在しない場合はデフォルト値が返される) を介する必要があります。これは存在しないキーを指定してもデフォルトでエラーにならない Perl の連想配列の実装に比べて利点だと思うのですが (この挙動のおかげでバグを作りこんでしまうことが Perl の場合は本当に多い)、 <code>defaultdict()</code> はこの悪しき Perl の連想配列に似た挙動がデフォルトである上に、一度参照してしまうとそのキーにデフォルト値が割り当てられてしまうという最悪な動きをする代物です。</p>
<p>こんなの使うことあるんでしょうか…(´･_･`)</p>
<p>組み込みの辞書よりもスクリプト然としたコードを書くのに向いているのかもしれませんが (本書に示されている独自カウンタのサンプルのような… それもその直後に <code>Counter</code> を用いたずっと簡潔な書き方を示すことでくつがえ)、その割には冒頭で割と覚えにくい名前のパッケージ名からロードしてあげないといけないのも使い勝手としてはいまいちです。</p>
<h3><code>Counter</code></h3>
<p>積集合、和集合が取れるのがいいですね。</p>
<h3><code>OrderedDict</code></h3>
<p>Perl では古の pseudo hash を思い出しました…(&#8216;A`)</p>
<h3>その他</h3>
<p>いろいろあるみたいですが、<a href="http://docs.python.jp/3/library/" title="Python 標準ライブラリ — Python 3.6.1 ドキュメント">必要に応じて探してくれば良いのかなと思います</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2017/04/09/python-learning-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python 習得中 &#8211; その5</title>
		<link>https://blog.harapeko.jp/2017/03/22/python-learning-5/</link>
		<comments>https://blog.harapeko.jp/2017/03/22/python-learning-5/#comments</comments>
		<pubDate>Tue, 21 Mar 2017 21:02:31 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[O'reilly]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=398</guid>
		<description><![CDATA[業務が始まったこともあり、間が空いてしまいました。余談ですが、業務でもすでに段階的に Python を使い始め [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>業務が始まったこともあり、間が空いてしまいました。余談ですが、業務でもすでに段階的に Python を使い始めておりまして、 selenium と BeautifulSoup を使って Web スクレイピングでクローリングする script kiddy な感じのツールをメンテする準備を進めたりしています。</p>
<p>「<a href="https://www.oreilly.co.jp/books/9784873117386/">入門Python3</a>」は電子版を購入したのですが、 O&#8217;reilly の電子書籍は一度購入してしまえば O&#8217;reilly のサイトからいつでもどこでもダウンロードできます。閲覧規制が若干厳しい職場の環境でもダウンロードできたので何気に便利で快適です<tt>^^</tt>。</p>
<p>今回は 4章の 4.6節から。手元ではすでに 8章の途中ぐらいまで概ね読み終わっているのですが、今回は 4章までの内容について記述します。</p>
<p><span id="more-398"></span></p>
<h3>内包表記</h3>
<p>Python をして、もっともスクリプト言語らしい機能のひとつであるように思います。ザ・構文糖衣。</p>
<pre>
number_list = [n for n in range(0, 10)]
</pre>
<p>ちなみにこれ、Perl で書くとこうなります。</p>
<pre>
@number_list = (0..9)
</pre>
<p>他の LL を学べば学ぶほど、 Perl が如何にスクリプト然としているかがよく分かるという一例です…。</p>
<p>なお、 Python は <code>range</code> にしてもスライスにしても、終端値は含まれないことに注意する必要があります。</p>
<p><code>range</code> 自体にも step が指定できますが、内包表記の後ろに <code>if</code> 文を入れることでデータに含める値の条件を指定することもできます。下は凡庸な例ですが、既存のリストから条件を指定して値を抽出したいケースは多々あります。</p>
<pre>
even_list = [num for num in range(0, 6) if num % 2 == 0]  # 0, 2, 4
</pre>
<p>C# の Linq みたいなことをやりたい場合はジェネレータ内包表記でいろいろとできそうです… (例が思いつかないですが</p>
<h3>可変長引数</h3>
<p><q><code>*</code></q> で始まる仮引数は位置引数のタプル、<q><code>**</code></q> で始まる仮引数はキーワード引数の辞書になる、というもの。</p>
<p>python の性質として面白いなと思うのは、位置引数とキーワード引数がこの仕組みによって完全に分離しうるということ。キーワード引数として指定しないと有効にならないパラメータ、なんてのも書こうと思えば書けてしまえるわけです。実際使うかは別として。</p>
<h3>ラムダ</h3>
<pre>
lambda a, b: b - a
</pre>
<p>のような構文で書けるみたいです。 (ソートの比較条件を指定する場面ってあるのかしら…?)</p>
<h3>ジェネレータ</h3>
<p>C# でいうところの <code>IEnumerable</code> みたいなもんですね。 <code>yield</code> キーワードは他の言語でもよく使われていてまぁまぁありふれた存在となりつつあります…。</p>
<h3>デコレータ</h3>
<p>可変長引数が最も活躍するやつです。 C# の Attribute みたいなもんですかね。</p>
<h3>スコープと <code>global</code> 宣言</h3>
<p>関数内で変数を使用する際、同じ名前の変数がすでにグローバル名前空間に存在するときの挙動が、最初に値を代入するのか、値を参照するのかで変わるという、実に気持ち悪い内容に困惑するなど。</p>
<p>グローバル変数にアクセスしたい場合は <code>global</code> 宣言を使え、はいいんですが、関数内で閉じたスコープで使いたい場合に特別な宣言が必要ないというのがどうにもしっくりこないですね。</p>
<h3>例外</h3>
<p>…については、 <code>catch</code> ではなく <code>except</code> であることと、 <code>throw</code> ではなく <code>raise</code> であること以外は普通だと思います。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2017/03/22/python-learning-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python 習得中 &#8211; その 4</title>
		<link>https://blog.harapeko.jp/2017/02/25/python-learning-4/</link>
		<comments>https://blog.harapeko.jp/2017/02/25/python-learning-4/#comments</comments>
		<pubDate>Sat, 25 Feb 2017 07:29:28 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=395</guid>
		<description><![CDATA[今日は 4章の 4.5節まで。 複数の不等号を含む評価式が書ける 変数が取りうる値の範囲を調べる場合、その変数 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>今日は 4章の 4.5節まで。</p>
<p><span id="more-395"></span></p>
<h3>複数の不等号を含む評価式が書ける</h3>
<p>変数が取りうる値の範囲を調べる場合、その変数を <code>and</code> を挟んで 2回書く代わりに、複数の不等号を含む単一の評価式として書くことができる。</p>
<pre>
&gt;&gt;&gt; x = 7
&gt;&gt;&gt; 5 &lt; x &lt; 10
True
&gt;&gt;&gt; x = 2
&gt;&gt;&gt; 5 &lt; x &lt; 10
False
&gt;&gt;&gt; y = 200
&gt;&gt;&gt; 0 &lt; x &lt; 100 &lt; y &lt; 1000
True
</pre>
<p>こういう書き方できればいいのになぁと思うことは多々あったが、実際できる言語が存在するんですなぁ…。</p>
<h3>ループブロックの <code>else</code> 節</h3>
<p>ループブロックに <code>else</code> 節をつけると、 <code>break</code> 等による中断以外でループ終了する時に呼ばれるようです。</p>
<pre>
&gt;&gt;&gt; numbers = []
&gt;&gt;&gt; count = 0
&gt;&gt;&gt; while count &lt; 5:
...     val = input(str(count + 1) + "番目の整数を入力: ")
...     if val == 'q':
...             break
...     numbers.append(int(val))
...     count += 1
... else:
...     print(numbers, "の合計: ", sum(numbers))
... 
1番目の整数を入力: 1
2番目の整数を入力: 2
3番目の整数を入力: 3
4番目の整数を入力: 5
5番目の整数を入力: 7
[1, 2, 3, 5, 7] の合計:  18
</pre>
<p>使いどころはそれなりにあると思うのですが、これに <code>else</code> の名を冠するのは正直わかりにくい気もします…。</p>
<h3>いろいろと便利な <code>zip()</code> 関数</h3>
<p>複数のシーケンスを並列的に反復処理できる。</p>
<pre>
&gt;&gt;&gt; pythonObj = 'tuple', 'list', 'dict', 'set'
&gt;&gt;&gt; perlObj = 'list', 'list', 'hash', 'hash'
&gt;&gt;&gt; cppObj = 'tuple', 'vector', 'unordered_map', 'unordered_set'
&gt;&gt;&gt; mean = 'タプル', 'リスト (配列)', '辞書 (連想配列)', '集合'
&gt;&gt;&gt; for py, pl, cpp, jp in zip(pythonObj, perlObj, cppObj, mean):
...     print('Python: ' + py + ', Perl: ' + pl + ', C++: ' + cpp + \
...     '\nこれは何? - ' + jp)
... 
Python: tuple, Perl: list, C++: tuple
これは何? - タプル
Python: list, Perl: list, C++: vector
これは何? - リスト (配列)
Python: dict, Perl: hash, C++: unordered_map
これは何? - 辞書 (連想配列)
Python: set, Perl: hash, C++: unordered_set
これは何? - 集合
</pre>
<p>また、2つのシーケンスを <code>zip()</code> したものを <code>dict()</code> に食わせることで、一方をキー、他方を値とする辞書が作れる。</p>
<pre>
&gt;&gt;&gt; py2pl = dict(zip(pythonObj, perlObj))
&gt;&gt;&gt; py2pl
{'tuple': 'list', 'set': 'hash', 'dict': 'hash', 'list': 'list'}
</pre>
<h3>数列を作る <code>range()</code> 関数</h3>
<p>リストのスライスが欲しいのではなく、数の並びそのものが欲しい場合は、 <code>range()</code> 関数を使えばいい。 Perl でいうところの範囲演算子 <q><code>..</code></q> のようなもので、スライスと同様に step も指定できます。</p>
<pre>
&gt;&gt;&gt; for x, y in zip(range(0, 3), range(3, 0, -1)):
...     print("x:", x, "/ y:", y)
... 
x: 0 / y: 3
x: 1 / y: 2
x: 2 / y: 1
</pre>
<p><code>range(x, y)</code> で得られる数列の逆順が欲しい場合は、 <code>range(y, x, -1)</code> ではなく、 <code>range(y-1, x-1, -1)</code> とするか、または <code>range(x, y)[::-1]</code> とする必要があります。</p>
<pre>
&gt;&gt;&gt; list(range(0, 3))
[0, 1, 2]
&gt;&gt;&gt; list(range(3, 0, -1))
[3, 2, 1]
&gt;&gt;&gt; list(range(2, -1, -1))
[2, 1, 0]
&gt;&gt;&gt; range(0, 3)[::-1]
range(2, -1, -1)
</pre>
<p>range にスライスを指定するとリストではなく新たな range を生成するのは面白い特性ですね。</p>
<pre>
&gt;&gt;&gt; range(0 ,100, 3)[10:20]
range(30, 60, 3)
&gt;&gt;&gt; range(0 ,100, 3)[30:10:-5]
range(90, 30, -15)
&gt;&gt;&gt; range(0 ,10, 3)[30:10:-5]
range(9, 9, -15)
&gt;&gt;&gt; range(0 ,50, 3)[30:10:-5]
range(48, 30, -15)
</pre>
<p>…といった感じになるらしいです。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2017/02/25/python-learning-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python習得中 &#8211; その3</title>
		<link>https://blog.harapeko.jp/2017/02/24/python-learning-3/</link>
		<comments>https://blog.harapeko.jp/2017/02/24/python-learning-3/#comments</comments>
		<pubDate>Thu, 23 Feb 2017 15:48:26 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=391</guid>
		<description><![CDATA[3章まで読了。データ構造を表す型が何気に豊富ですね…。 リストをコピーする方法が 3通りもある 意外と自由度高 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>3章まで読了。データ構造を表す型が何気に豊富ですね…。</p>
<p><span id="more-391"></span></p>
<h3>リストをコピーする方法が 3通りもある</h3>
<p>意外と自由度高いな…。</p>
<pre>
&gt;&gt;&gt; a = [1, 2, 3]
&gt;&gt;&gt; b = a.copy()
&gt;&gt;&gt; c = list(a)
&gt;&gt;&gt; d = a[:]
&gt;&gt;&gt; a[0] = 'hoge'
&gt;&gt;&gt; a
['hoge', 2, 3]
&gt;&gt;&gt; b
[1, 2, 3]
&gt;&gt;&gt; c
[1, 2, 3]
&gt;&gt;&gt; d
[1, 2, 3]
</pre>
<p>見た目だけなら <code>d</code> のやり方が一番好きだけど、パフォーマンス的にはどれが一番マシなんだろう…?</p>
<p>ちなみに辞書のコピーは 3.4.12 節では <code>copy()</code> メソッドによる方法しか示されていなかったが、少なくとも <code>dict()</code> コンストラクタを使う方法は同様にイケるっぽい。</p>
<h3>Python ではリストとタプルは別物である</h3>
<p>Perl で慣れてるのでこういう表現になります。</p>
<p>Perl では値をカンマで区切ったものは何でもリストになります。 Python では値をカンマで区切ったものはタプルとなり、要素の追加・削除・変更ができません。</p>
<p>局面に応じて値の並びをミュータブルに扱いたいかイミュータブルに扱いたいかを選べるようになっているのは良いことだと思います。そうなっていることで不便を感じることも多分無いと思います。 Perl のリストの仕組みに不便を感じたことはありませんが。</p>
<p>強いて言えば値 1個だけのタプルの書き方がちょっとキモイですね…。</p>
<pre>
&gt;&gt;&gt; (1)
1
&gt;&gt;&gt; 1,
(1,)
</pre>
<p>Perl みたいに丸かっこで括ったらリスト、じゃないやタプルとして扱われる、でも良かった気もしますが…</p>
<p>ただ、C++ や C# などでライブラリに存在するタプルオブジェクトなんかに比べれば、これが本来タプルに求められるべき使い勝手なんだろうな、という気はします…(´・ω・`)。</p>
<h3><code>dict</code> コンストラクタ</h3>
<p>2要素のタプルのタプルからでも生成できるみたいだけど、引数にタプルのリテラルを指定する場合はカッコをいっぱい挟まないといけない模様…(´・ω・`)</p>
<pre>
&gt;&gt;&gt; dict(1, 2, 3, 4, 5, 6)
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: dict expected at most 1 arguments, got 6
&gt;&gt;&gt; dict((1, 2), (3, 4), (5, 6))
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: dict expected at most 1 arguments, got 3
&gt;&gt;&gt; dict(((1, 2), (3, 4), (5, 6)))
{1: 2, 3: 4, 5: 6}
</pre>
<p><code>dict</code> コンストラクタに指定できる引数の数が 1つだけなので、まぁ当然っちゃ当然ですが… 素直に <q><code>{</code> 〜 <code>}</code></q> 使えってことですね。</p>
<h3><code>dict_keys</code> はそのまま <code>sorted</code> に渡せる</h3>
<p>辞書の <code>keys()</code> メソッドは <code>dict_keys</code> オブジェクトを返す。リストとして扱うには <code>list()</code> コンストラクタに渡す必要があるが、ソートしたキーの一覧が必要な場合はそのまま <code>sorted()</code> 関数に渡せばいいっぽい。</p>
<pre>
&gt;&gt;&gt; da = { 'hoge': 'foo', 'fuga': 'bar', 'piyo': 'baz', 'piyopiyo': 'qux' }
&gt;&gt;&gt; da.keys()
dict_keys(['hoge', 'piyo', 'piyopiyo', 'fuga'])
&gt;&gt;&gt; list(da.keys())
['hoge', 'piyo', 'piyopiyo', 'fuga']
&gt;&gt;&gt; sorted(da.keys())
['fuga', 'hoge', 'piyo', 'piyopiyo']
</pre>
<h3>辞書のキーの集合を得るなら <code>keys()</code> メソッドの呼び出しも不要</h3>
<p>これは 3.5.2 節に記載の通り。集合は <code>for</code> ループで回すこともできるので、普通の用途ならそもそもリストにする必要はないってことだやね。</p>
<pre>
&gt;&gt;&gt; da = {'hoge': 'foo', 'fuga': 'bar', 'piyo': 'baz', 'piyopiyo': 'qux'}
&gt;&gt;&gt; set(da)
{'hoge', 'piyopiyo', 'fuga', 'piyo'}
&gt;&gt;&gt; for a in set(da):
...     print(a)
... 
hoge
piyopiyo
fuga
piyo
</pre>
<p>本当に <code>for</code> ループで回すだけなら <code>keys()</code> が返す <code>dict_keys</code> でもイケるようですが。</p>
<pre>
&gt;&gt;&gt; for a in da.keys():
...     print(a)
... 
hoge
piyo
piyopiyo
fuga
</pre>
<p>集合の使い勝手はむしろ集合同士の比較演算にあるようです。 (3.5.4 節)</p>
<h3>辞書はキーにタプルが使える</h3>
<p>タプルとそれ以外との混在も可能っぽい。</p>
<pre>
&gt;&gt;&gt; da = {'foo': 1, 'bar': 2, ('foo', 'bar'): 3, 'baz': 4, ('foo', 'baz'): 5}
&gt;&gt;&gt; da
{'bar': 2, 'baz': 4, ('foo', 'bar'): 3, 'foo': 1, ('foo', 'baz'): 5}
&gt;&gt;&gt; da['foo', 'bar']
3
</pre>
<p>DBMS でも 2つのカラムが PK になる場合とかありうるので、データ構造が無駄に複雑にならなくて済む場合もあってよさそう。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2017/02/24/python-learning-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python習得中 &#8211; その2</title>
		<link>https://blog.harapeko.jp/2017/02/22/python-learning-2/</link>
		<comments>https://blog.harapeko.jp/2017/02/22/python-learning-2/#comments</comments>
		<pubDate>Wed, 22 Feb 2017 03:11:49 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=389</guid>
		<description><![CDATA[Python 習得中です。今日は 3章の 3.2.16 まで。 list コンストラクタに文字列を渡すと一文字 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Python 習得中です。今日は 3章の 3.2.16 まで。</p>
<p><span id="more-389"></span></p>
<h3><code>list</code> コンストラクタに文字列を渡すと一文字ずつに分解してリスト化する</h3>
<pre>
&gt;&gt;&gt; list('cat')
['c', 'a', 't']
</pre>
<p>率直に言って気持ち悪いですね(´・ω・`)</p>
<p>タプルも同じですか。</p>
<pre>
&gt;&gt;&gt; tuple('cat')
('c', 'a', 't')
</pre>
<p>素直に <q><code>[</code>〜<code>]</code></q> とか <q><code>(</code>〜<code>)</code></q> とか使えって話ですね。</p>
<h3><code>[0]</code> はいくつでも重ねられる</h3>
<p>リストのリストをいじっていて気づいたのですが、</p>
<pre>
&gt;&gt;&gt; arr = [['foo', 'bar', 'baz'], ['hoge', 'fuga', 'piyo'], [1, 2, 3]]
&gt;&gt;&gt; arr[0]
['foo', 'bar', 'baz']
&gt;&gt;&gt; arr[0][0]
'foo'
&gt;&gt;&gt; arr[0][0][0]
'f'
</pre>
<p>ここまではわかるのですが、</p>
<pre>
&gt;&gt;&gt; arr[0][0][0][0]
'f'
</pre>
<p>あ、これできちゃうんだ、と。</p>
<p>確かに、文字列のオフセット位置を指定して抽出した文字も型としては同じ <code>str</code> 型なので当然と言えば当然なのですが、なんだかもにょる…(´・ω・`)</p>
<h3>リストから同値の要素を除去する <code>remove()</code> メソッドの挙動</h3>
<p>リストの先頭から検索して最初に hit した要素を削除する。 hit するものがないと<strong>エラーになる</strong>。</p>
<pre>
&gt;&gt;&gt; arr = ['foo', 'bar', 'baz', 'bar', 'qux', 'quux']
&gt;&gt;&gt; arr
['foo', 'bar', 'baz', 'bar', 'qux', 'quux']
&gt;&gt;&gt; arr.remove('bar')
&gt;&gt;&gt; arr
['foo', 'baz', 'bar', 'qux', 'quux']
&gt;&gt;&gt; arr.remove('bar')
&gt;&gt;&gt; arr
['foo', 'baz', 'qux', 'quux']
&gt;&gt;&gt; arr.remove('bar')
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
ValueError: list.remove(x): x not in list
</pre>
<p>…使いみちあるの? これ(´・ω・`)</p>
<p><code>index()</code> メソッドも hit しないとエラーになる。先に <code>in</code> 演算子でテストしておかないとダメってことやね。</p>
<pre>
&gt;&gt;&gt; arr = ['foo', 'bar', 'baz', 'bar', 'qux', 'quux']
&gt;&gt;&gt; arr.index('bar')
1
&gt;&gt;&gt; arr.remove('bar')
&gt;&gt;&gt; arr
['foo', 'baz', 'bar', 'qux', 'quux']
&gt;&gt;&gt; arr.index('bar')
2
&gt;&gt;&gt; arr.remove('bar')
&gt;&gt;&gt; arr
['foo', 'baz', 'qux', 'quux']
&gt;&gt;&gt; arr.index('bar')
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
ValueError: 'bar' is not in list
</pre>
<h3><code>==</code> 演算子でリストの内容を比較できちゃう?</h3>
<p><code>join()</code> メソッドに関するサンプルを試していて思ったのですが…</p>
<pre>
&gt;&gt;&gt; arr = ['foo', 'bar', 'baz']
&gt;&gt;&gt; sep = ':'
&gt;&gt;&gt; joined = sep.join(arr)
&gt;&gt;&gt; joined
'foo:bar:baz'
&gt;&gt;&gt; separated = joined.split(sep)
&gt;&gt;&gt; separated
['foo', 'bar', 'baz']
&gt;&gt;&gt; separated == arr
True
</pre>
<p>ものすごく当たり前のことのように配列同士で比較が行われていてすげぇーってなりました…。</p>
<pre>
&gt;&gt;&gt; arr1 = ['foo', 'bar', 'baz']
&gt;&gt;&gt; arr2 = ['foo', 'bar', 'baz']
&gt;&gt;&gt; arr1 == arr2
True
&gt;&gt;&gt; arr1 = [['foo', 'bar', 'baz'], ['hoge', 'fuga', 'piyo']]
&gt;&gt;&gt; arr2 = [['foo', 'bar', 'baz'], ['hoge', 'fuga', 'piyo']]
&gt;&gt;&gt; arr1 == arr2
True
&gt;&gt;&gt; arr3 = [['foo', 'bar', 'baz'], ['hoge', 'fuga', 'poyo']] #ちょこっと違う
&gt;&gt;&gt; arr1 == arr3
False
</pre>
<p>階層深くしてもちゃんと比較してくれてますね…。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2017/02/22/python-learning-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python 習得中 &#8211; その1</title>
		<link>https://blog.harapeko.jp/2017/02/21/python-learning/</link>
		<comments>https://blog.harapeko.jp/2017/02/21/python-learning/#comments</comments>
		<pubDate>Tue, 21 Feb 2017 14:33:28 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=386</guid>
		<description><![CDATA[新しい現場で Python を使う仕事があるということなので、オライリーの入門 Python 3 の電子書籍版 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>新しい現場で Python を使う仕事があるということなので、オライリーの<a href="https://www.oreilly.co.jp/books/9784873117386/">入門 Python 3</a> の電子書籍版を購入して予習しています。とりあえず 2章まで読みました。</p>
<p>履修した中で気づいたことなどをちらほらとメモってみることにします。</p>
<p><span id="more-386"></span></p>
<h3><code>/</code> は浮動小数点数の演算になる</h3>
<p>演算子の左右が整数であっても、評価結果は必ず浮動小数点数になる。</p>
<p>整数の割り算を行いたい場合は <code>//</code> を使用する。</p>
<pre>
&gt;&gt;&gt; 9 / 4
2.25
&gt;&gt;&gt; 9 // 4
2
</pre>
<h3>整数型はサイズの制限がない</h3>
<p>Python3 では <code>long</code> 型が廃止され、 <code>int</code> 型は際限なく大きい値を取り扱えるようになっている。オーバーフロー例外は起こりえない。</p>
<p>面白いけど、 DBMS で取り扱われる整数だってサイズ制限はあるし、そこまでメリットあるのかなぁ…? 効率面との兼ね合いとかもどう折り合いをつけているんだろう? (ソースコード嫁&gt;ヲレ)</p>
<h3>スライスはステップも指定できる</h3>
<p><q><i>begin</i><code>:</code><i>end</i><code>:</code><i>step</i></q>、という構文。</p>
<p>文字列に対してもスライスを適用することができて、文字列を逆さにしたい場合はステップを -1 にしてやればいい。</p>
<pre>
&gt;&gt;&gt; alpha = 'abcdefghijklmnopqrstuvwxyz'
&gt;&gt;&gt; alpha[::-1]
'zyxwvutsrqponmlkjihgfedcba'
</pre>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2017/02/21/python-learning/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++11用のクラスひな形生成スクリプトを作ってみた</title>
		<link>https://blog.harapeko.jp/2014/08/20/cppgen/</link>
		<comments>https://blog.harapeko.jp/2014/08/20/cppgen/#comments</comments>
		<pubDate>Wed, 20 Aug 2014 08:10:44 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++11]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[ツール]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=357</guid>
		<description><![CDATA[C++ で開発する上で、クラスを一つ一つ実装するたびに毎回同じようなことを書かされるのは冗長なので、だいたいこ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>C++ で開発する上で、クラスを一つ一つ実装するたびに毎回同じようなことを書かされるのは冗長なので、だいたいこんな感じになるよねという範囲のひな形を生成するスクリプトを perl で記述してみました。</p>
<ul>
<li><a href="https://github.com/murachi/samples-for-blog/tree/master/perl/cppgen">cppgen.pl</a></li>
</ul>
<p><a href="http://search.cpan.org/~asw/Getopt-Compact-0.04/lib/Getopt/Compact.pm">Getopt::Compact</a> モジュールを使用しています。ご利用の際にはそちらも合わせてインストールしてあげてください。<br />
<span id="more-357"></span><br />
ツールの特徴としては以下のとおりです。</p>
<ul>
<li>名前空間とクラス名を指定すると、それらから類推される名前でファイル名や include guard シンボル名を設定し、ひな形を生成する。これらの指定は必須。
<ul>
<li>名前空間は 1階層にしか対応してません…。</li>
</ul>
</li>
<li>doxygen フォーマット (javadoc 風) でコメントを付加。
<ul>
<li>-s オプションでクラスの概要 (<code>@brief</code>) を指定可能。省略した場合はクラス名を使用。</li>
</ul>
</li>
<li>クラスの public 継承、仮想クラス、インタフェースクラスに対応。</li>
<li>Pimpl に対応 (構造体及びメンバ変数名は固定です…)。</li>
<li>Boost.noncopyable に対応。</li>
<li>コピーコンストラクタ、ムーブコンストラクタを自力実装するようにプレースホルダを設ける機能に対応。</li>
</ul>
<p>使い方ですが、例えば以下のようにすると、</p>
<pre>
$ perl cppgen.pl -c Observer -d hoge -s 'オブザーバーインタフェース' -in
$ perl cppgen.pl -c Subject -d hoge -s 'サブジェクト抽象クラス' -vpn
$ perl cppgen.pl -c ConsoleView -d hoge -s 'コンソールビュー抽象クラス' -e Subject -p
$ perl cppgen.pl -c StaticText -d hoge -s 'コンソールに静的にテキストを表示するビュークラス' -e ConsoleView -p
$ perl cppgen.pl -c DateTime -d hoge -s '日時を扱うクラス' -pCM
$ perl cppgen.pl -c WatchController -d hoge -s '時計コントローラ' -e Observer -p
$ perl cppgen.pl -c ConsoleManager -d hoge -s 'コンソール操作管理クラス' -pn
$ ls
console-manager.cpp  console-view.h  date-time.h      static-text.h  watch-controller.cpp
console-manager.h    cppgen.pl       observer.h       subject.cpp    watch-controller.h
console-view.cpp     date-time.cpp   static-text.cpp  subject.h
</pre>
<p>以下のような構成でファイルが生成されます。</p>
<ul>
<li>Observer クラス &#8230; noncopyable なインタフェースクラス (observer.h のみ)</li>
<li>Subject クラス &#8230; Pimpl を持つ noncopyable な抽象クラス (subject.h, subject.cpp)</li>
<li>ConsoleView クラス &#8230; Subject を継承し、 Pimpl を持つ抽象クラス (console-view.h, console-view.cpp)
<ul>
<li>他のクラスを継承するクラスは強制的に抽象クラスになります (デストラクタが virtual になる)。当たり前ですが…。</li>
</ul>
</li>
<li>StaticText クラス &#8230; ConsoleView クラスを継承し、 Pimpl を持つ抽象クラス (static-text.h, static-text.cpp)</li>
<li>DateTime クラス &#8230; Pimpl を持ち、コピーコンストラクタ、ムーブコンストラクタのプレースホルダを持つクラス (date-time.h, date-time.cpp)</li>
<li>WatchController クラス &#8230; Observer クラスを継承し、 Pimpl を持つ抽象クラス (watch-controller.h, watch-controller.cpp)</li>
<li>ConsoleManager クラス &#8230; Pimpl を持つ noncopyable なクラス (console-manager.h, console-manager.cpp)</li>
</ul>
<p>詳しくは <code>-h</code> オプションでヘルプを見るか、ソースを参照してください <tt>(^_^;</tt> 。</p>
<hr />
2014/8/22 &#8211; <strong>追記</strong><br />
テンプレートクラスに対応しました。</p>
<pre>
$ perl gencpp.pl -c DomNodeFromId -d hoge <strong style="color: red;">-t 'class NodeType'</strong> -ns 'ID を指定して DOM ノードを検索するラッパーオブジェクトクラス'
</pre>
<p>とかやると、以下の内容のヘッダファイル dom-node-from-id.h のみが生成されます。</p>
<pre>
/**
    @file   dom-node-from-id.h
    @brief  ID を指定して DOM ノードを検索するラッパーオブジェクトクラス定義  
*/
#ifndef HOGE_DOM_NODE_FROM_ID_H
#define HOGE_DOM_NODE_FROM_ID_H


namespace hoge {

/**
    @brief  ID を指定して DOM ノードを検索するラッパーオブジェクトクラス  
*/
template <strong style="color: red;">&lt;class NodeType&gt;</strong>
class DomNodeFromId {
    /// コピーコンストラクタ (使用禁止)
    DomNodeFromId(DomNodeFromId const&amp;) = delete;
    /// コピー代入演算子 (使用禁止)
    DomNodeFromId &amp; operator=(DomNodeFromId const&amp;) = delete;
    /// ムーブコンストラクタ (使用禁止)
    DomNodeFromId(DomNodeFromId &amp;&amp;) = delete;
    /// ムーブ代入演算子 (使用禁止)
    DomNodeFromId &amp; operator=(DomNodeFromId &amp;&amp;) = delete;

public:
    /**
        @brief  デフォルトコンストラクタ  
    */
    DomNodeFromId()
    {
        //TODO: デフォルト生成を行う処理の詳細をここに記述
    }
    /**
        @brief  デストラクタ  
    */
    ~DomNodeFromId() = default;
};

}   //namespace hoge

#endif  //HOGE_DOM_NODE_FROM_ID_H
</pre>
<p>見ての通り、 -n オプションと併用すると Boost.noncopyable を使用する代わりに、コピーやらムーブやらのあれこれを <code>= delete</code> しまくるコードが挿入されます。それから、デフォルトコンストラクタのプレースホルダはクラス定義内に確保され、デストラクタは <code>= default</code> で定義されます。</p>
<p>この他、 -CM オプションあたりが併用可能となっていますが、抽象クラスになるようなオプション (-vie) や、 Pimpl モード (-p) との併用はできません。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2014/08/20/cppgen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>shared_ptr にヒープ以外のものを掴ませたいなら何もしない Deleter も一緒に指定してあげればいい</title>
		<link>https://blog.harapeko.jp/2014/07/27/shared_ptr-nop-deleter/</link>
		<comments>https://blog.harapeko.jp/2014/07/27/shared_ptr-nop-deleter/#comments</comments>
		<pubDate>Sun, 27 Jul 2014 06:57:15 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++11]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=314</guid>
		<description><![CDATA[これまた非常に初歩的な話なのですが… STL のコンテナ (std::vector とか) には基本的にオブジ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>これまた非常に初歩的な話なのですが…</p>
<ul>
<li>STL のコンテナ (<code>std::vector</code> とか) には基本的にオブジェクトへの参照を掴ませることはできない (領域確保の効率の問題とかでデフォルトコンストラクタが必須だから)。</li>
<li>かといって、ナマポを掴ませるのは色々と危険 (意図せず寿命が切れて無効なポインタ掴まされた状態になったりとか)。</li>
<li>そも non-copyable なオブジェクトを扱いたかったりと言った理由で値そのものを掴ませるのは却下したい (まぁ、いろいろあるんだよ…)。</li>
<li>となると <code>std::shared_ptr</code> を噛ますのが順当かと思いきや…</li>
<li>必ずしもヒープに確保した (つまり、 new した) インスタンスだけを扱うとは限らないかもしれない。十分に寿命が長いことがわかっている自動変数やメンバ変数として確保したインスタンスのポインタをこのコンテナに突っ込んであげたい場合もあるかもしれない。</li>
<li>そういう場合に <code>std::shared_ptr</code> 使っちゃって大丈夫なのか…??</li>
</ul>
<p><span id="more-314"></span></p>
<h3>Deleter を指定してあげれば大丈夫</h3>
<ul>
<li><a href="https://github.com/murachi/samples-for-blog/tree/master/c%2B%2B/minimal-cases/shared-pointer-deleter">今回のサンプルコード</a></li>
</ul>
<p><code>std::shared_ptr</code> の Deleter って、 Win32 の <code>HANDLE</code> みたいに <code>delete</code> 以外の方法で開放するリソースを扱う方法として紹介されることが多いと思うんだけど、単純に、リソース開放の責任はここにはないよ、ということを明示する方法としてももちろん使えるよという、ただそれだけの話なんですね。</p>
<pre>
#include &lt;memory&gt;
#include &lt;vector&gt;
#include &lt;iostream&gt;

class Hoge {
    int number;
public:
    explicit Hoge(int num) : number{num}
    { std::cout &lt;&lt; &quot;Hoge &quot; &lt;&lt; number &lt;&lt; &quot; constructed.&quot; &lt;&lt; std::endl; }
    ~Hoge() { std::cout &lt;&lt; &quot;Hoge &quot; &lt;&lt; number &lt;&lt; &quot; destructed.&quot; &lt;&lt; std::endl; }
};

int main()
{
    std::vector&lt;std::shared_ptr&lt;Hoge&gt;&gt; hogehoge;
    hogehoge.push_back(std::shared_ptr&lt;Hoge&gt;{new Hoge(1)});    // まぁ普通…
    Hoge fuga{2};
    hogehoge.push_back(std::shared_ptr&lt;Hoge&gt;{&amp;fuga, [](Hoge *){}});    // を、行けるやん!!
    Hoge piyo{3};
    hogehoge.push_back(std::shared_ptr&lt;Hoge&gt;{&amp;piyo});    //(アカン)

    return 0;
}
</pre>
<p>実行結果:</p>
<pre>
murachi@erueru:~/github/samples-for-blog/c++/minimal-cases/shared-pointer-deleter$ g++ -std=c++11 -o hoge hoge.cpp
murachi@erueru:~/github/samples-for-blog/c++/minimal-cases/shared-pointer-deleter$ ./hoge
Hoge 1 constructed.
Hoge 2 constructed.
Hoge 3 constructed.
Hoge 3 destructed.
Hoge 2 destructed.
Hoge 1 destructed.
Hoge 3 destructed.
*** Error in `./hoge': double free or corruption (out): 0x00007fff8a6192a0 ***
中止 (コアダンプ)
murachi@erueru:~/github/samples-for-blog/c++/minimal-cases/shared-pointer-deleter$ 
</pre>
<p>何もしない Deleter を指定しなかった場合、 <code>std::vector</code> が開放される際に <code>std::shared_ptr</code> が <code>delete</code> を呼ぼうとするんだけど、出自が自動変数だった当該インスタンスはスコープ抜けるときに vector より先に破棄されちゃっていたので、結果コアダンプしてしまうわけですが、 Deleter を指定してあげた方は <code>std::vector</code> 開放時には何もしないので、結果開放処理が重複することなく済むわけです。 Deleter が lambda で書けちゃうのもいいですね。</p>
<p>ただ、この方法は<strong> <code>std::shared_ptr</code> でメモリー管理する領域よりも、生成元での寿命のほうが確実に長いことがわかっている場合以外は使えません</strong>。そういう意味では、プログラマーがメモリーの管理責任から開放されるための仕組みとして <code>std::shared_ptr</code> やガーベジコレクションのようなものを採用していることとは矛盾するやり方だと言えるでしょう。基本的には、 <code>std::shared_ptr</code> で扱うべきものは、プログラム全体で <code>std::shared_ptr</code> を介してのみ扱うよう徹底するのが正しいやり方なのかもしれません。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2014/07/27/shared_ptr-nop-deleter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
