はてなキーワード: リファクタリングとは
「この関数にこういうパラメータを使ったこういう処理を追加してくれ」などと言われたら、コードは複雑化するのは当然だろう。
かといってこういう要求が来た時に、コード全体を一から作り直して簡潔にしようと思うのはナンセンスだ。
コードの量にもよるが、一定程度の量のコードがそこにあるときは、やはりリファクタリングの方が効率よく進められる。
「僕はリファクタリングなんてしませぇん、一から書いた方がいいでぇす」というのは、特定の現場・状況だけにあてはまるものだと認識しておこう。
確かに「コード全体をリファクタリング」なんてしようと思ったら大変すぎるが、通常は「修正を担当する部分をついでにリファクタリングする」でOKだ。
ユニットテストさえかけていれば、そのリファクタリングによって、バグが見つかりやすくなるだろうし、保守性も上がるのである。
なお、本当にコードベースが酷いカオス状態で、ゴッドオブジェクトを使っているような状況になったら、「書き直す」という利点が少しはあるかもしれないが、そういう場合は関係各位に同意を取らなければやってはいけない。
そういったカオスな状況でさえ、平均的なプログラマーは「良いコード」よりも「慣れているコード」に愛着を持つ傾向にある。
もしあなたが「コードを綺麗にするためにすべてを一から書き直そう」と、無断でそのようなことをやったら、彼らが慣れていないという理由で批判の嵐が殺到するだろう。
プログラマーの三代美徳は、怠惰でもなければ傲慢でもない。本能、感情、混乱である。
本能とは、モチベーションの本質的部分である。エロいdeepfakeを作りたい、頭よく見られたい、金儲けしたいといった動機によってプログラマーは手を動かす。
本能がなければドーパミンも存在しない。コードを書く誘因は本能的衝動によって生み出されている。
感情とは、要するに好き嫌いのことだ。たくさんの経験を積み重ねてセンスを獲得するには、好き嫌いに敏感でなければならない。
なぜvscodeがクソで、emacsが素晴らしいのか。なぜマイクロサービスアーキテクチャに強い疑念があるのか。なぜベンダーロックインが金の浪費に繋がるのか。
そういったことは、経験から学び、そして感情という次元に落とし込まれる。感情は少数の次元で美的感覚を得るための優れたセンサーである。
混乱とは、人生である。混乱したことのないものはエントロピーを操ることはできない。
コードは常にエントロピー増大の法則に晒されている。高エントロピーの乱雑的コードを読んで混乱したことがなければ、リファクタリングもできないだろう。
誰にも相談せずに
コードを書く上で重要なことは?という質問に対して、アスペならば「実行できること」と答えるだろう。
当たり前なことしか言っていない。「実行できること」という文からは全く有益な知見を得られない。
実行できることは重要性ではなく、必要性である。重要性とは、必要なことをすべてやった上でなおやる価値のあることを意味する。
そう考えた時に私がよく思うのは「最短時間で理解可能」であることが重要であると思うわけである。
しかしここに宗教がある。そもそも、人間が物事を理解するプロセスは人それぞれである。
私は一度、関数やモジュールで適切に分離するためのリファクタリングというものを行ったことがある。
というのも、一つの関数に万を超える行が書かれていたため、上司がリファクタリングを命令したためである。
具体的詳細はprivateメソッドに、公開する必要のあるものはpublicメソッドに移した。
そして当初働いていた職場での反応はどうだったかというと、「スパゲッティコード」だというのだ。
スパゲッティコード?一つの関数に万を超える行があるほうがスパゲッティだと普通は思うだろう。
ところが、彼らの脳内では、「常にコードの詳細が見えていなければ気がすまない」という、カプセル化を無視する思想で動いていたため、関数化すると関数の最下層まで辿らないと気がすまないらしかったのである。
このようにして、教育の無い人間はコードの読み方もカプセル化も知らないので、非生産的な方法が最短の方法になってしまうのである。
コードを最短で理解するためにはどうするのか。基礎知識を教育された集団の中に身を置くのがまず先決である。
例えばcalc_monthly_salary_yen(Person p)という行が存在した時、いちいちcalc_monthly_salary_yenの中身を常に見に行くような人たちはダメだ。
「人間のデータを入力すれば円単位で月の給料を計算してくれるんだろう」とざっくりと自然言語的に読み進められる人たちでなければ「最短理解」は難しい。
開発手法でしっくり来てるのがAndy HuntさんのTracer Bullet Developmentで、開発の方向性を示すのに試作を作る方法。
1. 主要なシステム オブジェクトを定義。UI、サーバー、ロジックビット、データベース抽象化レイヤー等。
3. データフローを実現するために API とその戻り値をコーディング。
4. 単体テストを使用して API の予想される使用法を文書化。
5. 各 API に必要な量の既定のデータ (別名、ダミー データ、偽のデータ、ハードコーディングされたデータ) を追加して、API が「実行」されるようにする。
6. あらかじめ用意されたデータを実際の機能に段階的に置き換える。
プログラミングの話題と相性がいいんじゃないかと思って、昔読んだことがある達人プログラマー (1999年に出版された第1版の方、2019年に出版された第2版ではない) をぱらぱら見返してみた。プログラマーとしての姿勢やプラクティスなどは一般に普及したかどうかの判断が難しい。間違いなく一般的になったなと思えるものに絞って書く。インフラ面の進化が大きいと言えそう。
フリーレン「わずか数年で人類の開発方法論に組み込まれ、新しいインフラによってシステム開発の生産性を向上させた。」
でも今のチームはソースコード管理システムを使っていないんだけど……
恥ずかしいと思ってください! そして、これが伝道師となる機会だと受け止めてほしいのです。しかし、彼らが自ら進むべき道を見つける時まで、あなた一人ぼっちであってもソース管理を使うようにしてください。
フェルン「いまのはバージョン管理システムです。」
いつリファクタリングを行うべきなのか?
コードがうまくなじんでいないと感じたり、まとめるべき 2 つの事柄を見つけたりといった何か「おかしなもの」に遭遇した場合、手を入れることを躊躇してはいけません。
テストの文化
あなたの記述したソフトウェアはすべてテストの対象になります。あなたやあなたのチームの人間がテストをしなければ、最終的にユーザーがテストを強いられるのです。このため、テスト計画を徹底的に練る必要があります。しかし、事前にものごとを少し考えるだけでメンテナンス費とヘルプデスクへの呼び出しを大幅に削減できます。
(中略)
テストは技術というよりは文化なのです。こういったテスト文化は、使用する言語に関係なくプロジェクトに植え付けることが可能なのです。
フェルン「いまのはテスト駆動開発です。」
多くのプロジェクトでは、こういったレベルのビルドは毎晩自動的に実行されています。つまり、プロジェクトの特定部分を夜間ビルドで作成すると同時に、個別のテストよりも完全なテストを実行できるのです。これによって、完全なビルド実行時に行うテストをすべて実行させることも可能になります。結果として、その日のうちに回帰テストの問題を見つけられるようになるわけです。ソースの変更後、できるだけ早い時点で問題を検出できれば、バグの検出と修正を円滑に進められるようになるはずです。
この期間に、様々なプロジェクトに関わり、多くのことを学びました。
今回は、私が経験した技術的な話を中心に、はてなでの仕事について振り返りたいと思います。
はてなでは、主にRuby on Railsを使ってWebアプリケーションを開発していました。
はてなブログやはてなブックマークなどの有名なサービスはもちろん、社内向けのツールや新規事業のプロトタイプもRailsで作っていました。
Railsは、高速に開発できるというメリットがありますが、それと同時にコードの品質やパフォーマンスにも気を配る必要があります。
私は、テストやリファクタリング、コードレビューなどの技術的なプラクティスを積極的に取り入れることで、Railsの開発をより効率的で安全に行う方法を学びました。
例えば、私が担当したプロジェクトでは、RSpecやRuboCopといったツールを使ってテストカバレッジやコード規約をチェックし、GitHub ActionsやCircleCIといったサービスを使って自動化しました。
また、Pull RequestやPair Programmingといった方法を使ってコードのレビューを行い、バグや改善点を見つけたり、知識やノウハウを共有したりしました。
また、はてなでは、AWSやGCPなどのクラウドサービスを活用してインフラを構築していました。
私は、DockerやKubernetes、Terraformなどのツールを使って、コンテナ化やオーケストレーション、インフラストラクチャ・アズ・コードなどの技術を実践しました。
これらの技術は、開発環境と本番環境の差異を減らし、デプロイやスケーリングを容易にするという利点がありますが、それと同時に複雑さやトラブルシューティングの難しさも増します。
私は、モニタリングやロギング、アラートなどの技術的な仕組みを整備することで、インフラの運用をより安定的で信頼性の高いものにする方法を学びました。
例えば、私が関わったプロジェクトでは、DatadogやCloudWatchといったサービスを使ってシステムの状態やパフォーマンスを監視し、SlackやPagerDutyといったサービスを使って異常や警告を通知しました。
また、ElasticsearchやFluentdといったツールを使ってログの収集や分析を行い、原因究明や改善策の検討に役立てました。
## チームでの協働
はてなでエンジニアとして働くことで、私は多くの技術的なスキルや知識を身につけることができました。
しかし、それ以上に大切だったのは、チームで協力して問題を解決することでした。
はてなでは、エンジニアだけでなくデザイナーやプロダクトマネージャーなどの他職種とも連携してプロジェクトを進めることが多かったです。
私は、コミュニケーションやフィードバック、ドキュメンテーションなどの技術的ではないスキルも重要だと感じました。
私は、自分の意見や提案を積極的に発信することで、プロダクトやサービスの品質や価値を高める方法を学びました。
例えば、私が参加したプロジェクトでは、SlackやZoomといったツールを使って日常的に情報交換や相談を行い、BacklogやJiraといったツールを使ってタスク管理や進捗報告を行いました。
また、FigmaやMiroといったツールを使ってデザインやアイデアの共有やフィードバックを行いました。
私は、はてなでエンジニアとして働くことがとても楽しく充実していました。
しかし、私は自分のキャリアについて考える中で、新しい挑戦をしたいという気持ちが強くなりました。
私は、自分の興味や関心のある分野にもっと深く没頭したいと思いました。
## おわりに
彼らに感謝する気持ちを込めて、このエントリーを書き終えたいと思います。
そもそも高い賃金が欲しくてプログラマーになったようなやつは勘違いしているようだけど
なぜなら経済として会社を支えているのはどんなときでも営業だからだ
現に9割9分の会社は技術などないが営業が優秀なので存続している
(ちなみにここでいう営業というのはプロモーションや戦略系も含まれる)
例えば流行の機械学習を生業としているようなベンチャー企業であっても
最新のトレーニング手法やパラメータ定義なんかを使っても得られる利益はほとんど無いのだ
Web系でもAngularだろうがReactだろうがVueだろうがどうでもよくて
とにかくデザイナーの出したものを忠実、もしくはそれ以上のものを生み出せれば技術などどうでも良いのである
という人もいるが、残念ながら全ての技術は5年後に負債になっている可能性が等しくあるということを理解していただきたい
そんな中で日本での人材流動性の高まりであるとかプログラマー育成問題なんかもあって
技術系(プログラマー)の市場価値が高まり、たまたま今だけ高給になっているわけである
卵が少なくなって卵の値段が上がったとしても
その卵が美味しいかと言われるとそんなわけはないのだ
どちらかと言うと腐った卵まで流通するのが恐ろしいところである
私が見てきたベンチャーの腐った卵には下記のようなジャンルがある
メガベンチャーや伸び盛りのベンチャー系に多く、特に旧帝大出身(特に東大)に多いのがこのパワハラ系
とにかく(自分の)理論が正しいということを前提に自覚無くパワハラを繰り返す
これが雇われ社員ならそれほど問題でもないのだが、経営者側のCTOなどだった場合は目も当てられない
テックだろうがベンチャーだろうが雇用主と雇用者という関係性は変わらないのに平気でゴリゴリパワハラを行う
雇用主側に主張されると組合も無い弱い立場の雇用者は何も言えない
その状況を理解していないのか雇用主側のパワハラはエスカレートしていく傾向にあり
社員は退職するが新しい人材は集まらずたいていの場合は逆に雇用主側が病む
この手のテックマウントパワハラ系の特徴は、ドメイン駆動や過度の抽象化、もしくは無駄な高速化や機械語への執念などが挙げられる
例示するのは難しいが、PRを上げてきた新人社員をSlack上で公開にボコボコに論破した上に
「社会人としてできて当たり前」
みたいなことまで説教を始める人を何人か知ってる
小さめで大きくなってきているベンチャーに多いのが、この結局全部自分でやる系
締め切りの前日もしくは当日、もしくは過ぎた後に自分で全部やり直す人
それまで部下や関係者が相談しつつ進めていても結局は全部ぶち壊して全部自分でやる
などというのは完全な素人で、単に他者に業務依頼できない人である
「言ってくれればもっと早く出来たのに」
ということしかない
そんな調子で依頼することができないので結局は自分で実装を繰り返し更に時間がなくなる
「俺ほどの技術力を持った人がいなくて困る」
みたいな自己肯定感を醸成しているのでそのうち上のパワハラ系へと移行していく
特徴としてはSlackにしろPRにしろ話が抽象的すぎて文章力が無い人である
「1を聞いたら10を知るのが当たり前だろ!」
と言う人が多く(1と10から100は分かるけど1だけで10を知ったら変態ですよ)
ヒドイ人になるとIssueやPRの管理も全然できず、ブランチも規則無く乱立してしまっていて
新しく入った人もいったい何をどうすればいいのかさっぱり分からない状況で放置してしまう
これも例示すると、新サービスの仕様だけは決まっていてページレイアウトが無い状態で
デザイナーの配属が難しいので実装側が考える、ということになったとき(割とある)
と言っても音信不通で渋々とこれまでのレイアウトを踏襲して3人できっちり作ったところ
リリース前日になってCTOが徹夜で全部作り直す、ということがあった
レイアウトも全然変わっていて、実はニュースリリースの段階から新規テーマになることが決まっていたらしく
それに合わせて全部作り替えたそうだ
新規テーマは1ヶ月も前から決まっていたのだから共有さえしてくれればそれに合わせて作ったのになぁ、という話をした
余談だがこういうときにこの手の人が「デザイン共有できず申し訳なかった」というような一言はほとんど無い
そういうコミュニケーションが取れる人は最初から業務依頼ができるのだ
最後が最近一番多いのだが、単に技術力が無くて頑張ってるだけの技術者
JavaScriptでリストの中に'apple'があるかどうかを調べる時に array.includes('apple')と書くとして、
10個のフルーツのリストがあってそれらが含まれているかを調べる時に10個のincludesを書いてしまうような人である
「せめてfor文で書こう」「そもそもデータ構造がおかしい」「というか本当にやりたい処理は?」
などなど様々な疑問が出てくるが、不思議なことにこれらを指摘しても絶対に直ることは無く、全く同じことを何度もやる
他にも例えば男性か女性かでメッセージを変えて出力しているコードがあったとする
if( gender === 'male') { ... } else { ... }
これに、20歳以下の場合は男女共通で違うメッセージを出す場合に
if( gender === 'male') { if ( age <= 20 ) { ... } else { ... } } else { if ( age <= 20 ) { ... } else { ... } }
みたいなコードを書いてしまう(20歳以下の部分は同じコードのコピペ)
メッセージ表示させるだけなら大したことないが、実際にはもっと複雑な処理をコピペで貼り付けるのである
そのため
「20歳以下の表示部分のバグについて、男性の場合は直ってるけど女性の場合に直ってない」
if ( gender === 'female' && age <=20 ) { ... }
これでもだいぶオブラートに包んでいて、実際にはもっと複雑なロジックをぐちゃぐちゃのまま整理せずに追加するのでとてもじゃないがメンテできない
(最近だとそういう部分はまとめてChatGPTに放り込むと綺麗にしてくれるので非常に助かっている)
こういう低レベルな技術者は結構いるのだが、大企業だと時間をかけて成長していくのに対して
ベンチャーになると自己肯定感が高いのか成長せずに偉そうである
「動いてるものは触らないで欲しい」
「Javaだとこういう書き方するんだよね」(そんなことはない)
みたいなことを言って、とにかく学習しない
曲がりなりにもそういう職に一度就いてしまうと指摘されることもないので学習しないんだと思う
特にCTOだとあくまで雇用主側の立場なので雇用者側から指摘されることも少ないし
同業他社のレビューなんてのもないからそこで時間が止まってしまうんだろうな、という感じ
こういう技術者のコードでも、見た目は動いているので営業側から見ると売るには問題ないのだ
なので営業が優秀だと下手に売れてしまって成功体験からますます自己肯定感が増して手が付けられないモンスターCTOの誕生である
「成功してから伸び悩んで大手企業が買収したけど技術的負債が凄まじ過ぎてリファクタリングだけで一大プロジェクトになる」
「リファクタリングが上手く行かずに仕様変更することになって『大手企業に買収されてダメになった』というレッテルが貼られる」
「当時のCTOは別の会社で新しい事業のCTOとして活躍している」
という流れはこうして生まれている