Search on the blog

2012年7月29日日曜日

デザインパターン(4) Factory Method

まえおき
今日はFactory Methodパターンについて。去年読んだときは理解できなくて、いろいろなサイトを見て回った。今日改めて読んでみてもメリットがよくわからなかった。この本で強調されているポイントがちょっと違うのではないかという疑問を持った。分かりやすいサイトを見つけたのでそこを読んで理解度を補強した。


まとめ
  • インスタンスの生成のための枠組みと実際の生成を切り離すためのパターン
  • FactoryクラスでTemplate Methodパターンが使われている
  • 使用者クラスから生成するクラスの依存性を排除する

疑問点
  • メリットが「CreatorクラスがConcreteProductに依存しないこと」と書かれているけど、「ConcreteProductの使用者クラスがConcreteProductに依存しないこと」の方がうれしい部分だと思うけど。。
  • 使用するクラスを直接newするのは悪だと言うのは知っていて、それをしないために単純なインスタンス生成メソッドを使うことと、Factory Methodを使うことの違いがよく分からなかった。参考サイトを見て解決した。

その他
  • Factory Methodパターンでインスタンス生成して欲しいことを明示するために、コンストラクタをpublicにしないというテクニックはおもしろいと思った。

参考サイト


Factory Methodパターンを使わないと、以下の3つのデメリットがあることを示し、
  1. クライアントクラスと具象クラスの結合度が高い
  2. 同等の生成処理の実装が各クライアントクラスに散在している
  3. 生成処理の中に変動しやすい if 文が存在している
単純なファクトリクラスを利用することで、1.2.を解決できることを示し、さらに3.を解決するためにファクトリクラスを抽象化し、Factory Methodパターンへと導くという説明が素晴らしかった。

2012年7月28日土曜日

デザインパターン(3) Template Method

まえおき
今日はTemplate Methodパターンについて。フレームワークと関連の深いパターン。

まとめ
  • 大まかな処理の流れをテンプレート可する。
  • 処理の大きな流れをスーパークラス側で定義し、各処理の詳細な処理はサブクラス側で定義する。

疑問点
  • メリットの説明が分かりづらかった。自分なりに考えてみたがメリットは大きく2つあると思う。処理の大まかな流れをテンプレート可することで、ソースコード量が減り、機能変更(各詳細処理を呼び出す順番や呼び出す処理の追加)にも強くなるというのが一つ。もう一つは決まった処理を決まった場所に書かせることで保守性が上がるということ。

その他
  • これは完全にフレームワーク内部で使われているパターンだなと思った。処理の流れはフレームワーク側で定義するから、利用者は○○にこういう処理を、△△にはああいう処理を書いてくれ。という感じ。
  • 「Liskov substitution principle」、「Hollywood principle」といった関連キーワードを学習した。こういう横文字のテクニカルタームをさらっと言えると、何となく出来るヤツに見えるので積極的に覚えていきたい。


2012年7月26日木曜日

デザインパターン(2) Adaptor

まえおき
今日はAdaptorパターンについて。Wrapperパターンとも呼ばれるらしい。このパターンはごくごくあたり前のことを言っているだけのような気がするんだけど。保守のプログラミングをやる場合は無意識のうちに使っていることが多いと思う。

まとめ
  • 既存機能と必要機能の「ずれ」を埋める。
  • 実績のあるクラスを効率的に利用することでテスト工数を減らすことができる。

疑問点
  • 継承を利用した方法と、移譲を利用した方法の使い分けがよく分からない。この本ではAdapteeが一つのクラスの場合しか説明されていないが、Adapteeが複数個あった場合は移譲を利用した方法しか使えない。Adapteeが一つのクラスなら継承、複数個のクラスなら移譲という使い分けでいいのだろうか?

その他
  • 「無意識のうちに使っている」と冒頭で書いたけど、よく考えるとAdapteeをAdapterでラッピングしてClientが使うという実装しかしたことがない。これでもテスト工数を減らすという目的は果たせるけれど、設計上よろしくない。Clientが知るべきは使いたい機能だけなのでそれをTargetとして明示的に示してあげる必要がある。そうすることで開発者の意図が伝わりやすいソースコードができる。というか、ここまでやって初めてAdaptorパターンと呼べるのかな・・。

関連情報
  • Adapterパターンを使い利用コンポーネントを切り替える インターフェースの差異を吸収することで、ソースの改修を少なくすることができるということをうまく説明しています。また、クラスの生成をメソッド化するとさらに改修量が減るという説明もとても分かりやすいです。


2012年7月25日水曜日

デザインパターン(1) Iterator

まえおき
社内のプログラミング講師になったから、デザインパターンくらいは知っとかないとまずい。ということでもう一度復習することにした。去年の夏読んでいた『Java言語で学ぶデザインパターン入門』という本を最初から読み直していこうと思う。まずは、Iteratorパターンから。

まとめ
  • 集合体の要素を一つ一つ指し示し、全体をスキャンするときに使う。
  • 集合体のスキャン機能を集合体の実装から独立させることができる。

疑問点
  • Aggregate インターフェースにIteratorインターフェースで定義されている抽象メソッドを定義すれば同じような保守性(使用者側で変更が発生しない)は担保できるのでは?と思ったが、一つの集合体を異なる方法で数え上げたいときは別にIteratorとしてスキャン役を持っておいた方が便利か。Mapのスキャンとかだと、keyをスキャンしたい場合も、valueをスキャンしたい場合があるしね。コンポーネントの独立性という意味でAggregateとIteratorを別々に用意することには大きな利便性があると思う。と中盤くらいで考えていたら、最後の方の節の「複数のイテレータ」で似たような話が言及されていた。

その他
この本で強調されている「具体的なクラスを定義する前に、インターフェースを定義する。」というのはすごく大切だと思う。機能と実装を切り離すことで、クラスの使用者がクラスの実装を意識せずに済むというのは非常に大事。

2012年7月23日月曜日

サーバー奮闘記(23) MySQLのNOT NULL制約設定

NOT NULL制約が効かない!?
NOT NULL制約をつけたカラムに値を指定せずに、insert文を発行してもerrorが出なかった。warningは出るんだけど、errorにはならない(NOT NULL制約を課したカラムにはそのカラムの型のデフォルト値が入る)。ちゃんとerror出して欲しかったので、設定を変えた。

やったこと
/etc/mysql/my.cnfに以下を追記。
[mysqld]
#
# * Basic Settings
#
sql-mode="STRICT_ALL_TABLES"
my.cnfを編集した後、MySQLを再起動。
sudo /etc/init.d/mysql restart
これで、NOT NULL制約が機能するようになった。

2012年7月14日土曜日

読書「1Q84 BOOK5,6」

1Q84の5巻と6巻を読んだ。友人曰く、終盤は難しくなるということだったが、まったく難しいとは感じなかった。おそらく自分の読み方が浅いのだろう。

「リトル・ピープル」とは結局何だったのか?
我々が暮らす現実の世界において何を指しているものなのか?
そして作者が伝えたかったことは何なのか?

 そこまで考えて読むと読書の楽しみが増すのかもしれない。自分は単なるファンタジー小説として読んだだけなので、そこまで深い考察はしなかったが、それでも充分楽しめた。


phpでOAuthしてみた

作ったもの
twitterで"ぽいぽい"しましょう。リンクをクリックすると、"ぽいぽい"できます。
http://goodpreparations.co.cc/test/twitter/sample1/auth.php

前準備
PEARライブラリのインストール
$ pear install Net_URL2-0.3.0
$ pear install HTTP_Request2-0.5.1
$ pear install HTTP_OAuth-0.1.6
php.iniの編集
CLI版はインクルードパスの設定していたけど、CGI版の方はやってなかったので追記。
(php.ini)
include_path = ".:PEARライブラリのパス"
そのあとサーバー再起動。
sudo apache2ctl stop
sudo apache2ctl start

ソースコード
<?php
require_once("HTTP/OAuth/Consumer.php");

// start a session
session_start();

// create a consumer object
$ini_array = parse_ini_file("/home/kenji/config/twitterapp.ini", true);
$consumer_key = $ini_array['test1']['key'];
$consumer_secret = $ini_array['test1']['secret'];
$consumer = new HTTP_OAuth_Consumer($consumer_key, $consumer_secret);

if ($_GET['oauth_verifier'] == "") {
    // get a request token
    $callback = 'http://goodpreparations.co.cc/test/twitter/sample1/auth.php';
    $consumer->getRequestToken('http://twitter.com/oauth/request_token', $callback);
    $_SESSION['request_token'] = $consumer->getToken();
    $_SESSION['request_secret'] = $consumer->getTokenSecret();
    
    // make an authorization page URL
    // $auth_url = $consumer->getAuthorizeUrl('http://twitter.com/oauth/authorize');
    $auth_url = $consumer->getAuthorizeUrl('http://twitter.com/oauth/authenticate');
    print "<a href=\"$auth_url\">Poi Poi on Twitter!</a>";
}
else {
    // get an access token
    $verifier = $_GET['oauth_verifier'];
    $consumer->setToken($_SESSION['request_token']);
    $consumer->setTokenSecret($_SESSION['request_secret']);
    $consumer->getAccessToken('http://twitter.com/oauth/access_token', $verifier);
    
    // tweet some mysterious message
    $status = 'ぽいぽいぽいぽぽいぽいぽぴーーー!! ' . date('jS F Y h:i:s A');;
    $response = $consumer->sendRequest("http://twitter.com/statuses/update.xml", array('status' => $status), "POST");
    print "See your <a href='https://twitter.com/' target='twitter'>twitter</a> page!<br />";
}
?>
ソースコード解説
  1. 2行目でOAuthを使うためのPEARのライブラリをインポート。
  2. 7-11行目で、 consumer keyとconsumer secretを指定してHTTP_OAuth_Consumer型のインスタンスを生成。consumer keyとconsumer secretはセキュリティを考慮して設定ファイルで指定。
  3. 13-24行目はverifierが空のとき、つまりユーザー認証がまだ行われていないときの処理。(ここの分岐もっとかっこよく書けないだろうか・・・)
  4. 15-18行目でrequest token、request secretを生成。getRequestToken()でproviderにHTTPリクエストを投げてこれらの値を取得している。
  5. 22行目でユーザーに踏ませるURLを生成する。GETパラメータでrequest tokenを指定。
  6. 25-36行目は、providerから戻ってきたときの処理。
  7. 30行目でaccess token、access secretを取得している($consumerのtoken、tokenSecretフィールドに格納される)。getAccessToken()の中を見れば分かるが、access token、access secretの取得にはconsumer key、consumer secret、request token、request secret、verifierが必要。
OAuthの概念図と照らし合わせてみると、なるほどーという感じ。仕組みはだいたい分かったけど、それぞれのトークンがprovider内部でどのように生成されるのかが分かっていないので時間があるとき調べてみよう。


参考ページ
PHPでTwitter APIのOAuthを使う方法まとめ - とても分かりやすかったです。

2012年7月12日木曜日

サーバー奮闘記(23) PEAR HTTP_Request

このパッケージ使うと、httpリクエストが簡単に投げられるらしい。非常に便利ですねー。やったことを書き残しておきます。

設定
PEARがなかったのでパッケージマネージャを再インストール。
$ wget http://pear.php.net/go-pear.phar
$ php go-pear.phar
include pathを設定する。php.iniの該当部分を以下のように変更。
include_path = ".:/xxxxxx"
xxxxxxは、PEARのphpソースが格納されているディレクトリ。以下のコマンドで表示される場所を設定。
$ pear config-get php_dir
パッケージのインストール
$ pear install HTTP_Request


遊んでみる
Manualページにあるサンプルで一通り遊んでみようと思います。

2012年7月8日日曜日

サーバー奮闘記(22) Basic認証の設定

やったこと
Apacheの.htaccessを使ってBasic認証をやってみた。やったことをメモしておく。サンプルで作ったページはここ。ユーザー名=usr、パスワード=passで入れます。
以下に設定すべき2つのポイントを纏めています。

htpasswdでユーザリストを作成
まず、htpasswdというコマンドを使って、認証するユーザ&パスワードを格納したファイルを作ります。
>htpasswd -c passwd.dat usr

パスワードの入力が求められるので、usrに付与するパスワードを入力します。ユーザを追加する場合は-cオプションなしでコマンドを実行します。例えば、usr2を追加したければ

>htpasswd passwd.dat usr2


.htaccessの設定
次に、Basic認証を行いたいディレクトリに.htaccessファイルを作成します。中身は以下のとおり。

AuthType Basic
AuthName "Input your ID and Password." (ユーザ入力画面で表示させたいメッセージ)
AuthUserFile /home/taro/passwd.dat(ユーザ&パスワード情報が格納されているファイルのフルパス)
require valid-user

これだけで、Basic認証ができます。簡単!

参考にしたページ
基本認証でアクセス制限をかける方法