必ず失敗するひどい実装を晒してみる
年の瀬ですが、みなさま今年の振り返りはできていますでしょうか?この記事では今年に限らず、今までわたくしが犯した罪のある実装を晒していきたいと思います。
「愚者は経験に学び、賢者は歴史に学ぶ。」という言葉にあるように、この記事が少しでも多くの方の助けになるように、思いつき限りイケてない実装を晒してみようと思います。
関数やクラスがない
思いつく限り、これが最もひどい実装だと思います。プログラミング始めて間もないころ、動かすのが精一杯で、構成など考えたことがありませんでした。
手続き型とも言いますが、要は上からひたすら実行していって、終了する書き方です。
オブジェクト思考とか、テストのしやすさなんてものは存在しません。
こんな感じ。
# 定数設定 db_server = "192.168.1.1" # DBアクセス conn = db.con.hogehoge() # データ取得 sql = 'SELECT * FROM user' data = conn.fetch(sql) # データ加工 trim_data = trim(data) # 表示 print(trim_data)
ちゃんとDBクラスを用意したり、加工用メソッドを作るなど役割を分けましょう。そうやって関数・クラスとかで切り出せば、テストがしやすくなります。
毎回すべて目視で動作確認とか、不安定すぎるのでやめましょう。
ShellScriptで頑張る
関数が20, 30になりそうな規模なのに、シェルスクリプトで頑張っちゃうパターン。
インフラ系ですと、ShellScript読める人も多いので、保守性考えて、カジュアルにまぁShellScriptでいいかと作ってみるわけです。
しかしながら、ShellScriptの大きな弱点として、例外処理が非常にしにくいという問題があります。キャッチを全部自分でしていくか、-eですべてエラー扱いにしないといけないわけです。
そこそこの規模のコードですと、大事な場面で使われるものが多く、簡単に置き換えがきかないものであることが多いと思うのですが、その実装で例外に対する処理が甘いと、処理こけているのに気づかないという。
しかも保守している人がもう退社しているとか、違う部署に行っているとか、下手に手を付けられないレベルになっていたり。闇になりやすいので、気をつけたほうがよいかと。
他APIに依存する(密になっている)設計
便利だろうと思って、逆に不都合を招くパターン。
たとえば、ロガーの実装にESにもデータを送る実装をいれてしまったりする。他にも、何かの確認のために、他サービスに依存する設計となる。
他サービスなり他APIがこけただけで全てエラーになってしまうのに、それに気づかない。イケてないのやめましょう。ロガーならファイルに吐いて、td-agentで送る、他APIが503などのときも動くようにするなどケアをしましょう。
インフラの設計でも同じですが、疎な設計にしておけば、あと置き換えたり、何か発展したものを作るときでも、すごく楽になります。
疎は神、密は悪と覚えておきましょう。
マジックナンバー
消費税なりIPなり、なんらかの値をコード内に直接埋め込んでしまっているパターン。
そこに修正が入ったときにfgrep & xargsで全検索して全部置換しないといけないようなパターンです。
他の人がその部分を読んでもすぐ理解できませんし、修正コストが半端ないです。1ファイル修正するだけで済むのと、数十修正しないといけない場合の精神的負荷はかなりの差があります。
Pythonであれば、拙作constants_managerを使いましょう。
巨大なutil
utilってでかくなります。気づくとでかくなります。
ちゃんとuserc_util, file_utilなど役割ごとに分けましょう。fatな実装にせず、影響すべき範囲を限定しましょう。
ログ出力が少ない
障害が起きたときに、原因をすぐ追うことができなくなります。開発環境ではDEBUG、本番ではINFOみたくわけられるとなおよいですね。
misc
他にもバージョン管理されていない、タグ切りされてない、オプションや引数が多い、ファイル名・関数名がイケない、設計レビューやテストがない、パフォーマンスを考慮してないなどあげればキリがないですが、この辺にしておきましょう。
終わりに
色々経験をさせて頂いているのに、なかなかひどいことが多いですね。申し訳ないです。
読者のみなさまは同じ失敗を繰り返さないよう、2016年良い実装をして頂ければと思います。ということで、お互いがんばりましょう!ではでは!