第7回社内勉強会「code sucks - 人の振り見て我が振り直せ」
DESCRIPTION
世間や社内で見かけた困ったコードをdisることでコードレビューの必要性をアピールするTRANSCRIPT
Code sucks人の振り見て我が振り直せ
第 7 回社内勉強会
テーマ巷にあふれる困ったコードを晒して dis る
身に覚えがあったら反省する
自信をつける
お約束 自分のコードが出てきたら
一緒に笑う こっそり反省する 次から気をつける
異論があったら ガンガンツッコむ
他にも suck なコードを見つけたら 社内 wiki に投稿する
その1
終わらない二月、永遠の閏年
月の最終日を取得したいらしい// 検索月の末日を取得switch( $s_month ) {case 2: $last_day = 28; if ( ( $year % 4 ) == 0 ) { $last_day = 29; } break;
閏年 (via Wikipedia)http://ja.wikipedia.org/wiki/%E9%96%8F%E5%B9%B4
グレゴリオ暦( 略 )次の規則に従って 400 年に 97 回の閏年が設けられる。 ( 略 )
1. 西暦年が 4 で割り切れる年は閏年 2. ただし、西暦年が 100 で割り切れる年は平年 3. ただし、西暦年が 400 で割り切れる年は閏年
ポイントをもう一度1. 西暦年が
4 で割り切れる年は閏年2. ただし、西暦年が
100 で割り切れる年は平年3. ただし、西暦年が
400 で割り切れる年は閏年
コードをもう一度// 検索月の末日を取得switch( $s_month ) {case 2: $last_day = 28; if ( ( $year % 4 ) == 0 ) { $last_day = 29; } break;
コンピュータシステムと閏年コンピュータシステムにおいて閏年を判定するアルゴリズムの記述には問題がある場合が多く、しばしばこれが原因でシステムは重大な障害を起こす。これは例えば、「 4 で割り切れる年」としかしていなかったり year==2000||year==2004のようにある程度先の閏年しかコードしていないなどが挙げられる。
二段オチ$today = time();$s_year = date( "Y", $today);$s_month = date( "m", $today);$s_day = 1;$e_year = date( "Y", $today);$e_month = date( "m", $today);// 検索月の末日を取得switch( $s_month ) {case 2: $last_day = 28; if ( ( $year % 4 ) == 0 ) { $last_day = 29; } break;}
$ php -r "var_dump($year) ; "NULL
$ php -r "echo NULL % 4 ; "0
↓毎年閏年になるじゃん
正解は
$last_day = date("t") ;
http://jp2.php.net/manual/ja/function.date.php
その2
あなたが見ている世界は
ほんものか?
こんなリストがありました よくある商品リスト Web に表示したい
ソースをチェックしてみた$column_names = array(
'商品名 ','商品種別 ','重量 ','備考 ',
) ;
イヤな予感!!
テーブルをチェックしてみたmysql> describe item_master ;
+--------------+---------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+--------------+---------+------+-----+---------+-------+| item_id | int(11) | NO | | NULL | || column_type | int(11) | NO | | NULL | || column_value | text | YES | | NULL | |+--------------+---------+------+-----+---------+-------+
_, ._(;゚ Д ゚)
データをチェックしてみたmysql> SELECT * FROM item_master ;
( ゚ д ゚ )
( つ д⊂) ゴシゴシ
( ;゚ д ゚ )
( つ д⊂) ゴシゴシ _, ._(;゚ Д ゚) …? !
( つ д⊂) ゴシゴシゴシゴシゴシ
( ; Д ) !!
まあ落ち着け カラムの追加に強い、という
メリットがあるかもしれないじゃないか プライマリキーに縛られないので、
データスキーマに自由があるじゃないか なにかオトナの理由で、正規化できない
事情があったのかもしれないじゃないか
ロジックをチェックしてみた// $resultには表示対象の商品コードが入っているwhile ($data = mysql_fetch_array($result)){ for ($i = 0 ; $i < count($column_names) ; $i ++) { $sql = "SELECT * FROM item_master" . " WHERE item_id = {$data['item_id']}" . " AND column_type = {$i}" ; $ret = mysql_query($sql) ; $item = mysql_fetch_array($ret) ;
echo "<td>{$column_names[$item['column_type']]}</td>\n" ; echo "<td>{$item['column_value']}</td>\n" ; }}
正解は
正規化しようhttp://www.kogures.com/hitoshi/webtext/db-seikika/index.html
補足 あえて正規化しない、という選択肢
トランザクションロックの範囲を小さくする どっちにしても「正規化してから」非正規化を検討
重複項目も同様 「計算で出る要素」「他のテーブルにある要素」を
あえて持つ 処理速度と記憶容量、保守性のトレードオフ
データベースは奥が深いね! 技術者に敬意を
その3
できるだけコネタです
コネタその1if( $order == _SER_ORDER_LAST_ ) { // 前日閲覧数順} elseif( $order == _SER_ORDER_NEW_ ) { // 新着順} elseif( $order == _SER_ORDER_FAV_ ) { // 登録数順} else { // 更新順}
switch – case を使え!!
コネタその2// $iRecCnt(レコード数 )が1以外なら// 不正アクセスらしい。
if($iRecCnt>1){ $strAttentMessage = "不正なアクセスです。 ";}if($iRecCnt==0){ $strAttentMessage = "不正なアクセスです。 ";}
$iRecCnt != 1じゃ
ダメなの?
コネタその3// 取ってきたレコードを変数展開したいらしい。$sorter = $aRecData[0][c_sorter];$page_title = $aRecData[0][c_page_title];$page_content = $aRecData[0][c_page_content];$mailflg = $aRecData[0][c_mail];$signflg = $aRecData[0][c_sign];$backlink = $aRecData[0][c_backlink];$name = $aRecData[0][tname];$cl_bg = $aRecData[0][color_bg];$cl_text = $aRecData[0][color_text];$cl_link = $aRecData[0][color_link];$cl_vlink = $aRecData[0][color_vlink];$cl_hr = $aRecData[0][color_hr];$cl_title = $aRecData[0][color_title];
extract($aRecData[0]) ;
じゃダメなの?
コネタその4 (1/3)// なんだかいろんなコネクションがある。// INSERT祭りが始まるようだ。
$conn->begin_trans();$conn_sub->begin_trans();$conn_s->begin_trans();$conn_msg->begin_trans();$conn_ad->begin_trans();$conn_foo->begin_trans() ;$conn_bar->begin_trans() ;
コネタその4 (2/3)// ちょっと行数が多くて心が折れそうだが、// 処理にしくじったらロールバックさせたいようだ。if(!$conn->execute($strQue)) { $conn->rollback(); $conn_sub->rollback(); $conn_s->rollback(); $conn_msg->rollback(); $conn_ad->rollback(); $conn_foo->rollback() ; $conn_bar->rollback() ; db_regist_error($conn);}
コネタその4 (3/3) 一連の処理でロールバックしている箇所を
数えてみた。$ grep \$conn-\>rollback hoge.php | wc -l
29全部、手で
保守する気?
まとめ 人の振り見て我が振り直せ
あなたのコードもどこかで dis られてる…かも。
恐れる必要はない 勇気とは恐怖を克服すること
具体的には… たくさん書こう 人に見せよう
レビュー重要 今回は「 dis る」という形式だった 次回は「ライブレビュー」を予定
「にこにこ力」「ほめ力」「自画自賛力」重要
おしまい
ご清聴ありがとうございました