読者です 読者をやめる 読者になる 読者になる

プログラミングの魔物

エラー、バグ、仕様変更と戦うブログ

無題

どこかで区切りを見つけないといつまでも本読みを再開できそうにない。
とりあえず一段落したら再開しよう。

PHP Simple HTML DOM Parser

PHP Simple HTML DOM Parserはその名の通りHTMLのパーサー。
スクレイピングするために使用している。
比較検討したわけではないのでひょっとしたらもっと優れたものがあるかも知れないけど、今のところ満足している。

マニュアル

http://simplehtmldom.sourceforge.net/manual.htm
Quick Startを読むと大体分かる。
jQuery風の要素指定が可能。

文字列からオブジェクトを作れるので文字コード変換等の対応はそれで。

APIヘルプ

http://simplehtmldom.sourceforge.net/manual_api.htm

書き換えや保存も可能な様子。
外部HTMLを取得した後、書き換えて保存するといった用途に使えるかもしれない。

近況

なんだかんだで3月中に終わらせようと思っていた作業が結構な時間を食っている。
一番難しいのは作業に対するモチベーションを上げることだったりする。

一日ごとに目標を決めて進めているが、最近はそのハードルを低くしすぎているため遅々として進まない。
とはいえ、ハードルを上げすぎて完全にモチベーションが死んでしまっても元も子もない。
怠惰な自分を飼い慣らす方法を手探りで探していこう。うん。

未知の技術を使う場面においては、目標とする内容がそもそも実現可能かどうかを検討する必要があり、目標の設定が困難である。
となるとたとえば「この作業にどの程度従事したか」というのを目標にしたりするわけだ。
・・・なにやらいつ終わるのかわからない危険な香りがして来た。

まあ、とりあえず、コードで遊びながら頑張ろう。
必要のないものを作っている時が一番楽しいとか言うあるある。


リファクタリングの本を読み始めてから、気の利いたソースの書き方ができるようになった気がする。
後々の自分が苦労しないための組み方というかなんというか。
他人のソースをリファクタリングしながら読むのはとても良い。

追記

jQuery 2.0リリース、IE8/7/6は非サポート http://dlvr.it/3GPR5v

https://twitter.com/codezine/status/326168173760110593

ワーオ。
これバージョン上げるのためらってしまう。

1.x系は継続してサポートするということならそこまで深刻でもないか。

ブラウザシェアグラフ

http://lhsp.s206.xrea.com/misc/browser-share-version.html
Last Update4/1ってなんかやだな。混乱する。
IE8はまだまだ現役の人が多い様子。

それにしてもChromeすごいな。最近はFirefoxも起動が早くなってきたけど、昔はモッサリしてたからそれで人を逃したのかな?
あとFirefoxのプラグイン、バージョンアップすると使えなくなったりするし。
Chromeは共有が便利だからそれもあるかな。

メソッド呼び出しの単純化

リファクタリング 10章

インターフェースをより直接的にするためのリファクタリング

メソッド名の変更

メソッドの名前がその目的を正しく表現できていない → メソッドの名前を変更する

  • メソッドにつけるコメントを考え、それをメソッド名にする
  • 良い名前を思いついたら何度でも変更する
  • 同じ事がシグニチャにも言える。引数の順序を変更することで意味を明らかにできるならそうする

引数の追加

あるメソッドが呼び出し元からより多くの情報を必要としている → その情報を渡すために引数を追加する

  • 足りない情報を見つけたら引数として追加する
  • 追加時には「引数オブジェクトの導入」を検討する

引数の削除

ある引数が、もはやメソッド本体から使われていない → 引数を削除する

問い合わせと更新の分離

1つのメソッドが値を返すと同時にオブジェクトの状態を変更している → 問い合わせ用と更新用の2つのメソッドをそれぞれ作成する

  • 値を返す関数は観測可能な副作用がなければ価値がある。観測可能な副作用とは内部的なキャッシュなどの他にも影響を与えるメソッド
  • 値を返すと同時に副作用も伴うメソッドは分離すべき

メソッドのパラメーター化

複数のメソッドが、異なる値に対してよく似た振る舞いをしている → その異なる値を1つの引数として受け取るメソッドを作成する

  • よく似た振る舞いをするものの内部的な値に依存して異なる複数のメソッドを一元化する

明示的なメソッド群による引数の置き換え

引数の特定の値によって異なるコードが実行されるメソッドがある → 引数の値に対応する別々のメソッドを作成する

  • 「メソッドのパラメーター化」の裏返し
  • 条件に依存する振る舞いを減らす。コンパイル時にチェックされる

オブジェクトそのものの受け渡し

あるオブジェクトから複数の値を取得し、それらの値をメソッド呼び出しの引数として渡している → 代わりにオブジェクトそのものを渡す

  • オブジェクトから得られる情報量を増やすことができる
  • 副作用としてオブジェクトへの依存関係ができる

メソッドによる引数の置き換え

あるオブジェクトがメソッドを呼び出し、その戻り値を別のメソッドの引数として渡している。受信側はそのメソッドを呼出可能である → 引数を削除し、受信側にそのメソッドを呼び出させる

  • 引数で与えられる情報を別の方法で取得できるならそうする

引数オブジェクトの導入

本来まとめて扱うべき一連の引数がある → それらをオブジェクトに置き換える

  • いつも一緒に渡される引数グループはオブジェクト化を検討する

setメソッドの削除

フィールドの値が生成時に設定され、決して変更されない → そのフィールドに対するすべてのsetメソッドを削除する

  • 外から変更されない場合は必要ない

メソッドの隠蔽

メソッドが自分の定義されているクラス以外から全く使用されていない → そのメソッドを非公開にする

  • リファクタリングによりメソッドの可視性に関する決定が変わることがある
  • 定期的にチェックして公開する必要のないメソッドはプライベートにする

FactoryMethodによるコンストラクタの置き換え

オブジェクトを生成する前に、単純な生成以上のことをしたい → ファクトリメソッドを使ってコンストラクタを置き換える

  • 最もわかりやすい動機はタイプコードを置き換えたい場合
  • コンストラクタが制約されているような場合にも利用できる

ダウンキャストのカプセル化

メソッドが返すオブジェクトが、呼び出し側によってダウンキャストされる必要がある → そのダウンキャストをメソッド内に移動する

  • ダウンキャストを隠す

例外によるエラーコードの置き換え

メソッドがエラーを示す特別なコードをリターンしている → 代わりに例外を発生させる

  • エラーが発生した時に呼び出し元で処理する場合は例外を使う

条件判定による例外の置き換え

例外を発生させているが、本来は呼び出し側が先にチェックすべきである → 最初に条件判定をするように呼び出し側を修正する

  • 例外の使いすぎにより、本来条件で処理する部分まで例外を使用しているならそれを改善する

この記事で読み進めている本

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

  • 作者: マーチンファウラー,Martin Fowler,児玉公信,平澤章,友野晶夫,梅沢真史
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/05
  • メディア: 単行本
  • 購入: 94人 クリック: 3,091回
  • この商品を含むブログ (295件) を見る

条件記述の単純化

リファクタリング 9章

条件ロジックは分かりにくくなる宿命にあり、それを単純化するリファクタリングが多数存在する。

条件記述の分解

複雑な条件記述がある → その条件記述部とthen部およびelse部から、メソッドを抽出する

  • 条件の中の式あるいはコードブロックをメソッド化し明確化する
  • 分岐の理由をハッキリさせる

条件記述の統合

同じ結果を持つ一連の条件判定がある → それらを1つの条件記述にまとめてから抽出する

  • 複数の条件の結果が同一の処理になる場合に、条件をorでつなげたりメソッド化したりすることで統合する
  • 条件判定が本当に独立していて意図がある場合は統合する必要はない

重複した条件記述の断片の統合

条件式のすべての分岐に同じコードが存在する → それを式の外側に移動する

  • 各分岐の内部のコードに重複している部分があれば、それを前部または後部に寄せムダを省く
  • コードがメソッド化出来れば「メソッドの抽出」をする

制御フラグの削除

一連の論理型の式に対して制御フラグとして機能する1つの変数がある → 代わりにbreakかreturnを使う

  • 制御フラグは大抵break,continueで除去できるので無くす
  • breakやcontinueがない言語ではメソッド化してreturnを使う

ガード節による入れ子条件記述の置き換え

メソッドに正常ルートが不明確な条件付き振る舞いがある → 特殊ケースすべてに対してガード節を使う

  • 条件は次の2つの形式に分類される。1つはいずれも正常、もう1つは片方が正常でもう片方が特殊条件
  • 両方が正常ならif-then-else
  • 特殊条件は条件が真ならリターン(ガード節)
  • 入れ子になって読みにくくなった条件記述を、特殊条件としてreturnするガード節に置き換えることで可読性を高める

ポリモーフィズムによる条件記述の置き換え

オブジェクトのタイプによって異なる振る舞いを選択する条件記述がある → 条件記述の各アクション部をサブクラスのオーバライドメソッドに移動する。元のメソッドはabstractにする

ヌルオブジェクトの導入

null値のチェックが繰り返し現れる → そのnull値をヌルオブジェクトで置き換える

  • オブジェクトがヌルかどうかを判定して処理を分ける→条件式が増える
  • ヌルオブジェクトを導入する→正解

表明の導入

コードのある部分が、そのプログラムの状態について何らかの仮定を持っている → その仮定を、表明を使って明示する

  • 前提条件があるならassertする
  • 偽になったらプログラマのエラー。通常、本番コードでは取り除かれる(ライブラリ等は別)

この記事で読み進めている本

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

  • 作者: マーチンファウラー,Martin Fowler,児玉公信,平澤章,友野晶夫,梅沢真史
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/05
  • メディア: 単行本
  • 購入: 94人 クリック: 3,091回
  • この商品を含むブログ (295件) を見る

データの再編成

リファクタリング 8章

本読みの再開。作業と交互に読みすすめるので、今までよりペースは落ちると思う。

自己カプセル化フィールド

フィールドを直接アクセスしているが、結合関係が煩わしくなってきた → フィールドに対するget,setを作ってそれだけでアクセス

  • フィールドのアクセス方法は2種類。1つはクラス内部であれば直接アクセスできる、もう1つはクラス内部であってもアクセサを使う
  • 間接アクセスの利点はサブクラスがオーバーライドできることと遅延初期化のようにデータ管理面での柔軟性を持てること
  • 直接アクセスの利点はコードが読みやすくなること
  • このリファクタリングは、最初は直接アクセスで作り、必要になった時点で間接アクセスにするという考え方
  • 適切なタイミングは、変数をサブクラス内の計算値を置き換えたくなった時に適用する

オブジェクトによるデータ値の置き換え

追加のデータや振る舞いが必要なデータ項目がある → そのデータ項目をオブジェクトに変える

  • 最初は単純なデータ項目だったが、後に振る舞いを追加する必要が出てきた場合にオブジェクト化する

値から参照への変更

同じインスタンスが多数存在するクラスがある。それらを1つのオブジェクトに置き換えたい → そのオブジェクトを参照オブジェクトに変える

  • 参照に置き換えることによってメモリの消費量を減らしたり、値の比較をしやすくしたりする

参照から値への変更

小さくて、普遍で、コントロールが煩わしい参照オブジェクト → 値オブジェクトに変更

  • 値から参照への変更の逆
  • 参照によるアクセスが煩わしくなってきたら値へと変更する
  • 値オブジェクトは特に分散並列処理システムで有効
  • 値オブジェクトは不変

オブジェクトによる配列の置き換え

配列の各要素が、それぞれ異なる意味を持つ → その配列を、要素ごとに対応したフィールドを持つオブジェクトに置き換える

  • 配列は同種のオブジェクトのコレクションを保持するために使用するべき
  • たとえば配列の先頭のデータに特別な意味を持たせて管理している場合はオブジェクト化する

観察されるデータの複製

あるGUIコントロールでのみ有効なドメインデータが有り、ドメインメソッドからもアクセスする必要がある → そのデータをドメインオブジェクトにコピーして、それらを同期させるためのオブザーバを設ける

  • 振る舞いを階層ごとに分離するのは容易だが、データはそうは行かない。そこで、複製して同期をとるメカニズムを用意する
  • Observer/Observableの代わりにイベントリスナー使うときにもこのリファクタリングが適用出来る

単方向関連の双方向への変更

2つのクラスが互いにその特性を使う必要があるが、単方向のリンクしかない → 逆ポインタを加えて、両方の集合を更新するように更新操作を変更する

  • 逆ポインタを用いて双方向性をもたせる

双方向関連の単方向への変更

双方向関連があるが、一方のクラスはもはや他方の特性を必要としていない → 不要になった関連の一方を削除する

  • 双方向はコストが掛かり、ゾンビも生まれやすくなる。また、相互依存性を強制するのでどちらかの変更がも一方にも影響を与える
  • 双方向関連が不要になったらやめる

シンボリック定数によるマジックナンバーの置き換え

特別な意味を持った数字のリテラルがある → 定数を作り、それにふさわしい名前をつけて、そのリテラルを置き換える

フィールドのカプセル化

公開フィールドがある → 非公開にしてアクセサを用意

  • データを公開するとオブジェクトにとって未定義の動作が引き起こされる可能性が出る
  • これはリファクタリングの手順の中の1つであり、その後、このメソッドを利用しているメソッドを探し、「メソッドの移動」により適切なオブジェクトへの配置が可能かどうかなどを検討する

コレクションのカプセル化

メソッドがコレクションを返す → 読み取り専用のビューを返して、追加と削除のメソッドを提供する

  • クライアントに直接コレクションを操作させるのではなく、追加・削除をクラスによって管理する
  • コレクションに対するクライアント側での未定義の動作を回避できる
  • 結合度を低下できる

データクラスによるレコードの置き換え

古いプログラミング環境のレコード構造とインターフェースを取る必要がある → そのレコード用に、振る舞いを持たないデータオブジェクトを作る

  • 従来のAPIやデータベースとのやり取りを行うための専用クラス

クラスによるタイプコードの置き換え

振る舞いに影響しない数字のタイプコードを持つクラスがある → その数字を新しいクラスで置き換える

  • シンボリック名は可読性を高められるが別名でしかない
  • 数字をクラスに置き換えると静的な型チェックができる
  • これを行う前に他のタイプコードの置き換えについて検討する
  • タイプコードが純粋なデータである時だけタイプコードをクラスで置き換える
  • すべてのswitchはいずれ「ポリモーフィズムによる条件記述の置き換え」により取り除かれる。そのために「サブクラスによるタイプコードの置き換え」、または「State/Strategyによるタイプコードの置き換え」で対処されている必要がある

サブクラスによるタイプコードの置き換え

クラスの振る舞いに影響を与える不変のタイプコードが有る → そのタイプコードをサブクラスに置き換える

  • タイプコードが振る舞いに関係しないなら「クラスによるタイプコードの置き換え」が適用出来る
  • タイプコードが振る舞いに影響を与える時、ポリモーフィズムを利用する(switchやif)「ポリモーフィズムによる条件記述の置き換え」
  • 出来ないケースはオブジェクトが生成された後にタイプコードが変わる場合、またはタイプコードを持つクラスがすでに別の処理でサブクラス化されている場合。その場合には「State/Strategyによるタイプコードの置き換え」
  • ポリモーフィズムによる条件記述の置き換え」の土台。きっかけは条件文により処理が分岐する場合。条件文がなければ「クラスによるタイプコードの置き換え」が有効
  • このリファクタリングを使うもう一つの理由は、あるタイプコードを持つオブジェクトにだけ関連する特性が存在する場合。このリファクタリングが終われば「メソッドの引き下げ」や「フィールドの引き下げ」を行なって、サブクラスをより特化できる
  • サブタイプによる振る舞いの差異をクラス自身で持つことが可能になる。新たなバリエーションにサブクラスの追加だけで対応できる
  • バリエーションが発生し続ける場合に特に有効

State/Strategyによるタイプコードの置き換え

クラスの振る舞いに影響するタイプコードがあるが、サブクラス化は出来ない → 状態オブジェクトでタイプコードを置き換える

  • タイプコードがオブジェクトの生存期間中に変化するか、サブクラス化が不都合な理由が別にあるときに適用出来る
  • ポリモーフィズムによる条件記述の置き換え」を使うならStrategy、状態に特有なデータを移動しようとしており、オブジェクトの状態が変わる場合はState

フィールドによるサブクラスの置き換え

定数データを返すメソッドだけが異なるサブクラスがある → そのメソッドをサブクラスのフィールドに変更して、サブクラスを削除する

  • 特性や振る舞いを変えるためにサブクラスが作られる
  • 定数データだけが異なるサブクラスはスーパークラスにフィールドを追加するだけで削除できる

この記事で読み進めている本

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

  • 作者: マーチンファウラー,Martin Fowler,児玉公信,平澤章,友野晶夫,梅沢真史
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/05
  • メディア: 単行本
  • 購入: 94人 クリック: 3,091回
  • この商品を含むブログ (295件) を見る

無題

今月は別の作業に集中するので、本読みは4月頃再開予定。
まあ3月中に終わらなければ伸びる可能性もあるけど、とりあえず3月中を目処に作業中。

あと暇な時にでも次に作成するプログラムの資料用に構文解析のアルゴリズムなどを調べて載せるかも知れない。
効率よく解析できればもっと複雑なDSLを組めるようになる。

MetaluaというLuaにマクロを追加するものがあるが、それは出力がバイトコードなのでクロスプラットフォームを意識した場合にエンディアン等が鬼門になる。
MetaluaがLuaファイルを吐いてくれるなら内部DSLも記述しやすくなるが、その辺は面倒くさそうなのであまり詳しく調べていない。