11月3日に「PHPカンファレンス2016に行ってきた」
のつづき。
PHPで堅牢なコードを書く
例外処理、表明プログラミング、契約による設計
をメモメモ
・自己紹介
・今日の講演:コードたくさん
例:SQLアンチパターンのひどいコード例をアレンジして
バグトラッキングシステムの検索
正常に動いているときはいい
・例野中でエラーになるのは・・
グローバル変数、データベース接続エラー
テーブル名が変わった場合
パラメーターがNULL、暗黙のキャスト失敗、データベース接続失敗
Bug暮らす未設定、データベース接続エラー
6行中、5行で
・失敗された中で、一番きつい
$paramsのキー
裏でこっそりワーニング:正常系と見分けがつかない
→不具合の発見が遅れるほど、傷は深くなる
・賢明なソフトウェア技術者になるための第一歩は、
動くプログラムを書くことと正しいプログラムを適切に作成することの
違いを認識すること まいけるじゃくそん
→50%がエラーハンドリング
・上手く動かなかったコードたち
データベース接続失敗→どんないいコードかいても
テーブル名やカラム名がだれかに変更された
使い方が間違えている
・予防的プログラミング 対処 <<< 予防
防御的プログラミング
そうなるはずだと決め付けないこと
誤解:入力をチェックする
ドキュメントを書く→よいことといわれるが、問題解決しているか
防御的プログラミングとは
悪いことにばんそこうを貼ることではない
→問題発生を事前に防ごうというコーディングスタイル
よいインターフェース
正しく使用するほうが操作ミスをするより簡単
謝った使い方をするほうが困難
型宣言
できていいことだけを出来るようにする
値の制限→Enum
関数のサイズを小さくする
問題領域の知識を活用して、固有の型を作る
列挙型をPHPで使える
知りすぎている→間違い発生しやすくなる
知り過ぎない、やり過ぎない
・第一部まとめ 予防に勝る防御なし
・攻撃的プログラミング
fail first
おかしいことが起こったら、速やかに停止させる
障害を抱えて中途半端に動いているプログラムより
→そんなに気楽にシステムを落としていいの?
・正当性と堅牢性
両立難しい
→個々のプログラムは正当性:エラーをみつけて、
アーキテクチャで堅牢せい:穏当な方向へ
・暗黙の前提を明示し、バグをあぶりだす表明プログラミング
起こるはずがないと思っていることがあれば、
チェックする→表明する
・PHP7のassert
評価式が真かどうか→じゃなかったら・・・、
PHP5では、アサーション警告→7も警告
php.iniでassert.exception =1に→落ちる
表明のメリット
書き手は、前提を書いている
例外と表明の使い分け
・本来のエラー処理に表明を使ってhがいけない
・発生してはならない状況にアサーション
・遅くならない?
そこでPHP7 assertは言語構造:実行段階でassertion off
zend.assertionsで制御できる
表明で引き渡す条件には副作用があってはいけない
・かもしれない例外的状況に対処する
エラーを無視するな
PDO:falseをチェック
戻り値の弱点
コードが肥大化しがち
無視されやすい
戻り値だけでは伝わりにくい
PDOを例外モードにしよう
→暗黙の前提:assertに落とす
・例外の利点
握りつぶしているのは書き手の姿勢に問題があることがすぐに分かる
第二部まとめ:fail first
・契約プログラミング
誰の責務かはっきりさせる契約による設計
バートランドメイヤー
要求された以上のことも以下のことも行わない
{P}A{Q}
事前条件を満たした条件で呼ぶなら
事後条件を満たす状態を実現する
処理
成功
失敗
バグ:必ず落ちる
例外:失敗することもある
実行時の表明違反やバグを示すための例外は、そのソフトウェアに
バグがある証拠である
Throwable
Error:エラー 処理系→バグ
Exception:ロジックエクセプション→バグ:必ず落ちるので直すこと
RuntimeException:例外
・コンストラクタの契約
アサーションで書く
・findallの契約
自分で例外とバグを切り分けて書く
ロジックエクセプション、第三引数でeを投げる
・まとめ
第一部:予防に勝る防御なし
第二部:fail first
第三部:バグと例外を区別、見分けられるように
テストコード
外から調べる:はさみうちになる
のつづき。
PHPで堅牢なコードを書く
例外処理、表明プログラミング、契約による設計
をメモメモ
・自己紹介
・今日の講演:コードたくさん
例:SQLアンチパターンのひどいコード例をアレンジして
バグトラッキングシステムの検索
正常に動いているときはいい
・例野中でエラーになるのは・・
グローバル変数、データベース接続エラー
テーブル名が変わった場合
パラメーターがNULL、暗黙のキャスト失敗、データベース接続失敗
Bug暮らす未設定、データベース接続エラー
6行中、5行で
・失敗された中で、一番きつい
$paramsのキー
裏でこっそりワーニング:正常系と見分けがつかない
→不具合の発見が遅れるほど、傷は深くなる
・賢明なソフトウェア技術者になるための第一歩は、
動くプログラムを書くことと正しいプログラムを適切に作成することの
違いを認識すること まいけるじゃくそん
→50%がエラーハンドリング
・上手く動かなかったコードたち
データベース接続失敗→どんないいコードかいても
テーブル名やカラム名がだれかに変更された
使い方が間違えている
・予防的プログラミング 対処 <<< 予防
防御的プログラミング
そうなるはずだと決め付けないこと
誤解:入力をチェックする
ドキュメントを書く→よいことといわれるが、問題解決しているか
防御的プログラミングとは
悪いことにばんそこうを貼ることではない
→問題発生を事前に防ごうというコーディングスタイル
よいインターフェース
正しく使用するほうが操作ミスをするより簡単
謝った使い方をするほうが困難
型宣言
できていいことだけを出来るようにする
値の制限→Enum
関数のサイズを小さくする
問題領域の知識を活用して、固有の型を作る
列挙型をPHPで使える
知りすぎている→間違い発生しやすくなる
知り過ぎない、やり過ぎない
・第一部まとめ 予防に勝る防御なし
・攻撃的プログラミング
fail first
おかしいことが起こったら、速やかに停止させる
障害を抱えて中途半端に動いているプログラムより
→そんなに気楽にシステムを落としていいの?
・正当性と堅牢性
両立難しい
→個々のプログラムは正当性:エラーをみつけて、
アーキテクチャで堅牢せい:穏当な方向へ
・暗黙の前提を明示し、バグをあぶりだす表明プログラミング
起こるはずがないと思っていることがあれば、
チェックする→表明する
・PHP7のassert
評価式が真かどうか→じゃなかったら・・・、
PHP5では、アサーション警告→7も警告
php.iniでassert.exception =1に→落ちる
表明のメリット
書き手は、前提を書いている
例外と表明の使い分け
・本来のエラー処理に表明を使ってhがいけない
・発生してはならない状況にアサーション
・遅くならない?
そこでPHP7 assertは言語構造:実行段階でassertion off
zend.assertionsで制御できる
表明で引き渡す条件には副作用があってはいけない
・かもしれない例外的状況に対処する
エラーを無視するな
PDO:falseをチェック
戻り値の弱点
コードが肥大化しがち
無視されやすい
戻り値だけでは伝わりにくい
PDOを例外モードにしよう
→暗黙の前提:assertに落とす
・例外の利点
握りつぶしているのは書き手の姿勢に問題があることがすぐに分かる
第二部まとめ:fail first
・契約プログラミング
誰の責務かはっきりさせる契約による設計
バートランドメイヤー
要求された以上のことも以下のことも行わない
{P}A{Q}
事前条件を満たした条件で呼ぶなら
事後条件を満たす状態を実現する
処理
成功
失敗
バグ:必ず落ちる
例外:失敗することもある
実行時の表明違反やバグを示すための例外は、そのソフトウェアに
バグがある証拠である
Throwable
Error:エラー 処理系→バグ
Exception:ロジックエクセプション→バグ:必ず落ちるので直すこと
RuntimeException:例外
・コンストラクタの契約
アサーションで書く
・findallの契約
自分で例外とバグを切り分けて書く
ロジックエクセプション、第三引数でeを投げる
・まとめ
第一部:予防に勝る防御なし
第二部:fail first
第三部:バグと例外を区別、見分けられるように
テストコード
外から調べる:はさみうちになる