PHP Manual
/
セキュリティ

レガシーPHPプロジェクトのリファクタリング - 技術的負債を取り戻す方法

11. 05. 2021

Obsah článku

知識や経験の豊富なプロジェクトオーナーとコンサルティングをしていると、デジタルプロジェクトの長期的な持続可能性についての問題によく出くわします。多くの大規模プロジェクトは、開発期間が3年を超えると、内部的に陳腐化し、持続不可能になります。ここで、さまざまなレベルの知識、経験、そして最も重要な勤勉さを持つ開発者のチームを想像してみてください。

デジタルプロジェクトを技術的にTOPレベルに維持するために、必要なこと。

  • 有能な開発者とプロジェクトマネージャー**は、素晴らしいコミュニケーションをとり、誰もが自分のしていることと、それが他の人にどのような影響を与えるかを理解しています。
  • チーム全体が知っている機能的なツールやワークフローは、それに応じて他の人に仕事を適応させる。
  • 忘れがちな日々のルーティンを提供する自動化されたタスクは、非常に重要です。

大規模なプロジェクトを開発する場合、単純に簡単にはいきません。正しいことをするのも大事ですが、もっと大事なことがあるんです。

リファクタリングとは何か、なぜ必要なのか

リファクタリングの概念は、周辺環境に影響を与えることなく、プログラムのコードの外観や内部ロジックを修正する一連の活動を包含しています。リファクタリングのプロセスは、クリスマスの大掃除と考えることができます。同じままですが、より整理され、不要なものは捨てられます。また、リファクタリングでは、一回きりのイベントではなく、一定のサイクルで繰り返す長期的なプロセスであることを念頭に置くことが重要です。これをやらないと、いろいろな変なミスや金銭的な損失、オンボーディングの問題、泣き寝入りすることになる。

プロジェクトを安定させ、最新の状態に保つことができれば、大きな利益を得ることができます。

  • プロジェクトは、より安全なものになります。お客様が使用するライブラリには、バグやセキュリティ上の脆弱性を修正するパッチが定期的にリリースされています。セキュリティは健全なプロジェクトの基本的な生命機能の1つです。
  • コードや内部アーキテクチャがよりシンプルになり、よりよく考え抜かれるようになります。バグを発見しやすくなり、多くのバグは未然に防ぐこともできます。
  • コードが単純化されていれば、ジュニア開発者を連れてきて、全体の予算を大幅に削減することも可能です。
  • いくつかのことを複雑にしすぎて、複雑にしすぎていることに気づくかもしれません。プロジェクトは全体的にシンプルになります。

大規模なデジタルプロジェクトで軌道に乗るためには、走らなければなりません。でも、成長したいんですよね。

安全なリファクタリングの方法

リファクタリングのたびに大きな賭けに出て、報われないかもしれない。

私は、リファクタリングに着手するずっと前に、必ず安定した環境を確保するようにしています。

安定性を確保するためには、特に機能的なエラーログが必要です。単純なプロジェクトであれば、エラーを HTML ファイルに記録する Tracy があればよいでしょう。より高度なプロジェクトでは、SentryRollbar といったツールが登場します。私自身は、すべてのプロジェクトでTracyを使用し、プロジェクトの種類に応じて他のツールを使用しています。

リファクタリングの約1ヶ月前からバグの追跡を開始し、後で重点的に取り組む既知のバグのスプレッドシートを作成します。リファクタリングによって発生したバグと、過去にプロジェクトが持っていたバグを知ることは、常に重要なことです。そうすることで、クライアントに対して仕事の成果をよりよく説明することができるのです。

ログを見ることで、比較的安定した環境で作業していることがわかれば、あとは本題に入るだけです。その他に、リスクの大きさによって方法を分類しています。

コーディングスタイルとコーディングスタンダードの修正

ほとんどのプロジェクトでは、コードの書式が統一されていません。これは大きな間違いです。よくできたプロジェクトは、すべてのことが同じように書かれている、一人の人間のプロジェクトのように見えるのです。

基本的なフォーマットのエラーは、プロジェクト全体に定期的にかけているNetteコードチェッカーというツールでしっかり修正しています。

一方、コーディングスタイルは、コードの書式や個々の言語表現のインデントなどを扱う。PSR-12 規格は、PHPの世界で多く使われており、他の非常に多くの規格がこれに基づいています。使うことをおすすめします。

プロジェクトによっては、タブとスペースを不格好に組み合わせているものがあります。空白の規約違反(およびその他のエラー)を効果的に防ぐには、プロジェクトルートに .editorconfig ファイルを作成して、新しく書かれたコードをどのようにフォーマットするかをエディタに指示します。

私自身はこの構成で使っています。

root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{php,phpt}]
indent_style = tab
indent_size = 4

また、すべてのcarriage-notesをアポストロフィに修正します。自動的に行うことができます。

また、コードの書式を自動的にチェックすることもできます。これについては、GitHubに十分に機能するデモを用意しました。コードの自動修正も必要な場合は、同じツールで行うことができます。また、PhpStormは、プロジェクト全体にわたって一括してでも、コードを直接自動修正することに非常に優れています。

大規模プロジェクトにおけるCoding Styleの修正方法

大規模なプロジェクトでは、自動コード整形を1モジュールずつ行うことをお勧めします。これは、Gitに膨大な数のコンフリクトを発生させる可能性があるからです。したがって、最良の戦略は、ひとつの大きなコミットでできるだけ多くの行を修正し、そのコミットを直接マスターにプッシュし、それから他のブランチに変更を分散させることです。

コンフリクトが大きすぎる場合、まずmasterでコードをフォーマットし、その後、変更の多い大きなブランチごとに再度フォーマットすることは理にかなっています。非常に多くの変更されたラインが互いに相殺される(早送りをする)ので、非常に少ないコンフリクトを解決することができ、時にはコンフリクトが発生しないこともあります。

何もしなければ、コードが悪いままです。なぜなら、マージするたびに、実際には何も変更されていない何十行もの行を修正する必要が生じ、コードレビューと変更の差し戻しの両方を不必要に複雑化させるからです。

PhpStan - 静的コード解析と型エラー修正

大規模なロジックの修正に着手する前に、プロジェクトのライフサイクルの基本的な機能を見直し、修正することが非常に重要です。この中には、どんなプロジェクトでも期待するような当たり前のことが含まれていますが、それでも満たされないことがあります。

例えば、こんな感じです。

  • すべてのクラス、メソッド、関数が存在すること
  • クラス継承を壊してはならない
  • クラスは、使用されるインタフェースまたは祖先のインタフェースを実装しなければならない。同時に、final クラスを継承してはいけません。
  • eval()shell_exec()var_dump()` などの安全でない関数を呼び出してはいけません。また、どうせ呼ぶなら、コメントで明示する必要がある
  • 常に例外をキャッチし、アプリケーション全体をクラッシュさせないようにしなければならない

この問題の解決策は、PhpStanをプロジェクトにインストールし、少なくともレベル1に修正することです。そう、大変なんです、そう、大変なんです。しかし、もしそれをしなければ、すべてのリファクタリングがロシアンルーレットとなり、開発者は被害ができるだけ少なくなることを願うだけです。

PhpStanの基本レベルでは、例えばデータ型などの形式的なものがどこにでも存在する必要はないのですが、これは将来的に対応する予定です。一方、ある関数やメソッドがあるデータ型を返すが、typehintで他のデータ型をアサートするということはないかもしれない。

レクター - 安全な繰り返し修理

よく知られたプログラミングの格言に、システムに新しいエラー(例外を投げるなど)を追加する前に、まずそのエラーを警告として追加し、長い間現れなかった場合にのみ致命的なエラーにするべきだというものがある。

データ型も同じです。未知のコードをリファクタリングするときは、Rectorのような自動ツールに、まずコードにコメント注釈を追加させます。これは何も壊さないのですが、何がどこにあるのかを後で明確にするのに役立ちます。これらのコメントはPhpStanによって聞かれ、何も壊していないこと、安全な改造であることを安全に確認するために使用することができます。

私は大体1回のコミットでプロパティや引数にコメントを追加し、その後1ヶ月くらい待って、長期的に全てがうまくいったところで、長期的に問題がなかったところを固定データ型に書き換えるという手段をとっています。

How we Completed Thousands of Missing @var Annotations in a Day の記事をご覧ください。

Rectorについては、GitHubを参照してください。

依存関係を更新する

パッケージの依存関係やPHPのバージョンの更新に入る前に、自動テストの使い方を研究し学ぶことが重要です。

テストがうまくいっていれば、Composerツールで更新を実行できます。もし可能なら、プロジェクトの composer.json を自動的に更新し、互換性の変更をチェックできる Dependabot ロボットの助けを借りてください。

もし、大きな変更がある場合は、常にゆっくりと変更を加え、バージョンごとにインクリメントしてください。一度に多くのパッケージをアップデートしないでください。アップデートのたびに、PhpStanでプロジェクト全体をスキャンし、バグを修正する。数時間かかる長丁場だが、その分、苦労も多い。

次に進むべき道

次のステップは、プロジェクトの種類と状況によって個別になります。一般的に、ウェブ開発を副業としているメディアエージェンシーに勤める若手から安く買ったコードよりも、シニア開発者によって書かれた優れたデザインのコードの方が、メンテナンス性は桁違いに高いのです。

祈っています。大変だろうけど、きっと乗り越えられるよ。

Jan Barášek   Více o autorovi

Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.

Rád vám pomůžu:

Související články

1.
10.
Status:
All systems normal.
2024