コピー&ペーストはパッケージングの敵です

コピー&ペーストはパッケージングの敵です
OO、デザイン パターン、および多くのオブジェクト指向の原則について話す前に、まず 1 つのことを習得する必要があります。それは、カプセル化です。カプセル化の原理と技術を習得すると、OO 言語を使用していなくても美しいフレームワークを持つプログラムを構築できるようになります。これらの原則をプログラム外に適用すると、驚くべき結果が得られることもあります。 「設計ルール - モジュール化の力」(http://www.douban.com/subject/1737636/) では、カプセル化とモジュール化を重視しており、この位置づけにふさわしいものです。これは、複雑な問題を解決するために使用する最も基本的な方法です(他にはありません)。

プログラムは複雑なシステムです。 「道は一つを生み、一つは二つを生み、二つは三つを生み、三つは(四つ、四つは…)万物を生む。」複雑さの源泉が「道」の変容であると考えられるならば、この「一つ」はカプセル化であるに違いありません。さまざまなプログラミング言語と、これらのプログラミング言語から派生したメソッドは、「2 番目」の位置にあり、たとえば、OO 設計パラダイム、FP (関数型プログラミング) パラダイム、階層化の原則などがあります。リスコフの置換原則や継承よりも優先される合成などのオブジェクト指向設計原則は「3 番目」の位置にあり、特定の設計パターンなどは「3 番目」の後の「4 番目」の位置にあります。

私は愚かなので、リスコフの置換原則とは何か、このモデルやあのモデルをどのように実装するかなど、それらの原則をまだ思い出せません。デザインパターンの中では戦略パターンにのみ興味があり、他のパターンにはあまり興味がありません。本質的には、これらのパターンや原則は、カプセル化をより適切に実装するための方法とツールを提供するだけです。

コピー アンド ペーストはカプセル化の敵であり、醜いコードの最大の悪臭です。 1 回コピーすることは、少なくとも 1 つの変数ポイントを追加することと同じであり、2 回コピーすることは、少なくとも 2 つの変数ポイントを追加することと同じです。なぜ「少なくとも」と言うのでしょうか? モジュール間には関連性があるため、1 か所の変更によって他の複数の場所でも変更が発生します。 S がシステム自体、M がシステム自体の測定値、C がシステム S 内のモジュールのコピーの平均数 (C>1) であると仮定すると、M と C の関係は指数関係になるはずです。つまり、M は C の N 乗 (N>1) に比例します。

指数関数的な関係だけでも十分恐ろしいのですが、さらに恐ろしいのは、システム内のモジュールが変更されたときに、そのモジュールがシステム内に複数のコピーを持っている場合、私たちが怠惰になり、すべてのコピーを変更するのではなく、コピーの 1 つだけを変更する可能性があることです。これにより、モジュールが 1 つのモジュールから複数の類似しているが異なるモジュールに分割され、システムの複雑さが大幅に増加し、最終的にはシステムが腐敗することになります。直感的に言えば、設計が不十分なシステムの複雑さは、モジュールの数の階乗関係、あるいはべき乗関係にほぼ相当し、指数関係よりも恐ろしい関係です。

したがって、コピー&ペーストは非常に邪悪なコーディング方法です。コーディングするときは、コピーと貼り付けを減らす方法を見つける必要があります。これは、リファクタリング フェーズ中に行うものではなく、コーディング中に考慮する必要があるものです。どのような方法、手段、モデルを使用するかは、すべて細かい問題です。

コピー&ペーストをせず、それを貫くと、大きなメリットが得られ、作成するコードは高品質で価値の高いものになります。他の人のシステムを見ると、そのシステムの利点と欠点がすぐにわかります。デザインパターン、インターフェースの直交性、デザイン原則など、これまで意識的に勉強したことがないかもしれませんが、最終的にはすべてが同じ目的地につながることがわかり、海外の専門家とのつながりを感じることができます。私たちは、これらの専門家のアイデアや方法を自発的に組み合わせて改善し、さらには新しい方法や手段を生み出していきます。 3 と 4 を教条的かつ崇拝的な方法で学ぶのではなく、1 から直接始め、1 が 2 を生み、2 が 3 を生み、3 が 4 を生むようにします。おそらく、その時点では、オブジェクトが何であるかを忘れているでしょう。

私が文句を言っている理由は、昨日から今日にかけて、モジュールをリファクタリングしているからです。このモジュール M1 のコア コンポーネントは、RTF からラップされたレイアウト ルール エディターです。このコア コンポーネントを設計した人は、RichTextBox を中心としたコントロール A を設計し、このコントロールのルール ロジックの一部を抽出して、クラス B とクラス C の静的メソッドに配置しました。さらに驚くべきことは、クラス B は別のモジュール M2 にあり、クラス C はモジュール M1 にあることです。このコントロールは、M1 の 3 つの場所 (D、E、F) で使用されます。D、E、F のそれぞれで、このスペース A に対して 7 つまたは 8 つのイベントを登録し、イベント コールバック関数でモジュール M2 のクラス B の静的メソッドとモジュール M1 のクラス C の静的メソッドを呼び出して、何らかのロジックを実装する必要があります。ここで、コントロール G を記述したいのですが、この G にはコントロール A も必要です。この場合、G の A のイベントとコールバック関数を多数登録し、コールバック関数に一連のロジックを配置する必要があります。これには少なくとも 200 行のコードが必要になります。これらのコールバック関数を記述するには、コントロール A とクラス B および C の内部動作メカニズムを理解する必要があります。つまり、豚肉を食べるためには、自分で豚を殺さなければならないのです。もちろん、時間を節約するために、D、E、または F からコードをコピーして変更することもできます。

深刻な問題は、制御 A 自体に論理エラーと不完全な機能があり、修復する必要があることです。あらゆる場所に複製されるため、1 回の動作が全身に影響します。A に手術を行う場合は、B、C、D、E、F にも手術を行う必要があります。 A を整形する際に、コンパイルするために、B、C、D、E、F の A に関係するコードをすべてコメントアウトし、合計で約 1,500 行のコードをコメントアウトしました。実際、この 1500 行のコードのうち、本当に価値のあるコードは 200 行程度しかなく、残りのコードはすべてコピー、貼り付け、変数名の変更によって完成しています。

なぜこの問題が発生するのでしょうか?コピー&ペーストのためです。コピー&ペーストは簡単です。パッケージングについて考える時間を費やすことなく、いくつかの単語をコピーして変更するだけで使用できます。実際の状況は、コントロール A を参照するために、200 行から 300 行のコードを書かなければなりません。複数の場所で参照する場合は、1,000 行以上のコードを書かなければなりません。コピー アンド ペーストは面倒ではありませんが、A にエラーがあることがわかった場合、または拡張する必要がある場合、A を変更するときに、この 1,000 行のコードも移動する必要があります。この 1,000 行のコードには、さらに多くのコードが含まれる可能性があり、最終的にはさらに多くのコードを修正する必要が生じます。これがコードの腐敗です。

実際、この A は非常にうまくカプセル化されています。他のクラスが入力データを入力する必要はありません。他のクラスは、A コントロールから最終的なルール結果であるリストを取得するだけで済みます。カプセル化が適切であれば、A を呼び出して結果を取得することは 2 行または 3 行のコードで実現できます。

カプセル化しない理由は、コピー&ペーストに慣れているから、カプセル化するのが面倒だから、あるいはカプセル化するという考えがまったくないからです。

多くの新人プログラマー、あるいはそれほど新人ではないプログラマー、特に Web 開発プログラマーは、自分の仕事の技術的内容が低いことに常に不満を抱いており、常にもっと学びたいと考えています。本質的に、彼らが行う仕事は非常に技術的であり、それはすべてあなたがそれをどのように見るかによって決まります。

自分の作品を単なるコピー、貼り付け、盗作、コード改変としか捉えていない場合、技術的な内容は当然低くなります。いかにしてコピー&ペーストを排除し、品質と進捗を向上させ、作業において不要なものを排除し、あらゆる無駄を排除するかが仕事だと捉えれば、この仕事の技術的内容は極めて高いと言えます。主人を崇拝してはいけません。そうすると、主人の仕事をしていることになります。新しいテクノロジーを崇拝しないでください。崇拝すると、あなたの仕事が新世代のテクノロジーの萌芽となる可能性があります。あらゆるもの、あらゆる色、あらゆる香り、すべてが私の心の中にあります。緑の竹はすべて法身であり、青々とした黄色い花はすべて般若です。

<<:  複数の Tomcat を展開して起動し、プロジェクトを移行する方法を 1 つの記事で学習します。

>>:  Vue3コンポーネントの開発詳細

推薦する

MySQL 8.0.19 インストールチュートリアル

公式サイトからインストールパッケージをダウンロードします: mysql-8.0.19-linux-g...

Nginx リバース プロキシを使用してクロスドメイン問題を解決する方法の詳細な説明

質問前回のクロスドメイン リソース共有に関する記事では、ドメイン間で Cookie を送信する場合、...

MySQLのマスタースレーブ構成を使用して、読み取りと書き込みの分離を実現し、データベースの負荷を軽減します。

大規模な Web サイトでは、多数の同時アクセスを処理するために、Web サイト上の分散負荷分散以上...

MySQL 8.0.14 のインストールと設定方法のグラフィックチュートリアル (一般)

MySQLサービス8.0.14のインストール(一般)の参考までに、具体的な内容は次のとおりです。イ...

Vue3における7種類のコンポーネント通信の詳細

目次1. Vue3コンポーネント通信方式2. Vue3通信の使い方2.1 小道具2.2 $エミット2...

Linuxで現在のスクリプトの実際のパスを取得する方法

1. 現在のスクリプトの実際のパスを取得します。 #!/bin/bash if [[ $0 =~ ^...

血の写輪眼と輪廻眼の特殊効果コードを実現するためのHTML+CSS

結果 (完全なコードは下部にあります): 実装は難しくありませんが、繰り返しコードが多くなります。実...

Mysql general_log をクリーンアップする方法の概要

方法1: グローバル general_log を 'OFF' に設定します。 テーブ...

jQueryはドロップダウンメニューのスライド効果を実現します

Web ページを作成するときに、クールでスムーズなドロップダウン メニューが必要になることがあります...

iframeフレームはIEブラウザで白い背景を透明に設定します

最近、プロジェクトを進める過程で、ページの階層構造を描画するために iframe を頻繁に使用する必...

Vue はシームレスなカルーセル効果 (マーキー) を実現します

この記事では、シームレスなカルーセル効果を実現するためのVueの具体的なコードを例として紹介します。...

DockerにRedisをインストールし、設定ファイルとして起動する詳細な説明

更新: 最近、サーバーがマイニング ウイルスによってハッキングされたことが判明しました。これは、おそ...

手の動きをリアルタイムで監視するための Handtrack.js ライブラリ (推奨)

【はじめに】: Handtrack.jsは、ブラウザ上で直接リアルタイムの手の動きの追跡と検出を実...

JSで画面録画機能を作成する

OBS studioかっこいいですが、 JavaScriptもっとかっこいいです。では、 JavaS...