巨大な接着方法を避ける方法は?


21

私の現在の仕事では、古いコードを数回クリーンアップする仕事をしました。多くの場合、コードは迷路であり、その背後のデータはさらに複雑です。私は物事をすてきな、きちんとした、モジュール式の方法にまとめると思います。各メソッドは1つのことを行い、それをうまく行います。それは物事が南に行き始めるときです...

常に、私はきれいなAPIになり、それをすべて結びつける実際の方法はありません。解決策は、最終的にすべての「クリーン」メソッドを呼び出す、大きない「グルー」メソッド(通常は条件ステートメントでいっぱい)を記述することです。

通常、glueメソッドは、クリーンアップしようとしたコード/データのもつれの簡潔なバージョンになります。一般的に読みやすいですが、それでもいらいらします。

そのような方法を避けるにはどうすればよいですか?これはもつれたデータの症状なのでしょうか、それとも私が間違っていることを反映しているのでしょうか?


3
APIは使用するためのものです。もつれた混乱から、APIを作成してから、再びもつれさせました。たぶんそれは単なるビジネス要件です。しかし、他の誰かが来て、APIを使用して別の接着機能を簡単に作成できるため、付加価値があります。手を絞る必要はありません...
アディティアMP

1
ここでオブジェクトについて話しているのでしょうか、それともあちこちでファンクなのですか?
エリックReppen

3
私はこれがその質問の複製だとは思わない、私はもう少し一般的に(そして単一の機能よりも大規模に)話している。
cmhobbs

1
erik-私はここでオブジェクトとメソッドについて話しています。いくつかの条件付き混乱を取り、それらをAPIに変えました。問題は、APIを呼び出すときです。ここでの最初の答えは、まさに私が探しているものかもしれません。
cmhobbs

2
いったいどういうことですか?
MattDavey

回答:


12

LedgerSMBのリファクタリングの経験をお伝えします。私たちは早い段階で物事を別の方法で行うことを決定しましたが、まだあなたが説明したとおりにしていますが、多くの接着方法はありません(いくつかの接着方法がありますが、多くはありません)。

2つのコードベースのある生活

LedgerSMBは2つのコードベースで約5年間存続しましたが、古いコードベースが削除されるまでにさらに数年かかります。古いコードベースは、見るべき本当の恐怖です。悪いdb設計、Perl IS->some_func(\%$some_object);は、スパゲッティメタファーがときどき使用される理由を正確に示すコードと同様に構築します(実行パスは、モジュール間で、また言語間で、韻も理由もなく蛇行しています)。新しいコードベースでは、dbクエリをストアドプロシージャに移動したり、要求を処理するためのよりクリーンなフレームワークを使用するなどして、これを回避しています。

私たちが最初に決めたのは、モジュールごとにモジュールをリファクタリングすることでした。これは、特定の領域のすべての機能を新しいモジュールに移動し、古いコードを新しいモジュールにフックすることを意味します。新しいAPIがクリーンであれば、これは大した問題ではありません。新しいAPIが毛深いものではない場合、それは新しいAPIで少し一生懸命働くことへの招待です。

2つ目は、新しいコードが古いコードのロジックにアクセスしなければならない場合が多いことです。これは、extentい接着剤メソッドにつながるため、可能な限り回避する必要がありますが、常に回避できるとは限りません。この場合、接着方法は最小限に抑え、可能な限り回避する必要がありますが、必要に応じて使用します。

これを機能させるには、特定の領域のすべての機能の書き換えをコミットする必要があります。たとえば、すべての顧客情報追跡コードを一度に書き換えることができる場合、つまり、古いコードからこれを呼び出すコードは扱いにくくなり、新しいコードから古いコードへのディスパッチは最小限に抑えられます。

2つ目のことは、適切な抽象化を自分の場所に持っている場合、呼び出すAPIのレベルとそのクリーンな状態を維持する方法を選択できる必要があるということです。ただし、APIを呼び出している部分を書き直して、かなりきれいになるように検討する必要があります。

ビジネスツールには、還元できないほど複雑な領域が数多くあります。すべての複雑さを取り除くことはできません。ただし、特に必要なことを実行するクリーンなAPIと、そのAPIを建設的に利用するモジュールに焦点を当てることで管理できます。Glueは、残りの呼び出しコードの書き換えが高速になる可能性があることを考慮した場合にのみ、最後の手段となるはずです。


頭に釘を打ったのではないかと思います。グルーが存在する理由は、作成したインターフェイスを呼び出すコードが原因である可能性があります。私たちが何かを逃していないかどうかを確認するために、さらにいくつかの応答を待ちますが、これは非常にうまくまとめていると思います。
cmhobbs

1
「韻律や理由もなく、モジュール間および言語間で、また言語間で蛇行する実行パス」-これは、現代のオブジェクト指向のプラクティスも思い出させます。
user253751

8

あなたがやったことは、手続き型コードベースのもつれた混乱を取り、素敵なモジュール式の手続き型コードベースを作成したように聞こえます。

常に、私はきれいなAPIになり、それをすべて結びつける実際の方法はありません。解決策は、最終的にすべての「クリーン」メソッドを呼び出す、大きない「グルー」メソッド(通常は条件ステートメントでいっぱい)を記述することです。

手続き型コード(OOに変装していても)を使用すると、常にどこかで定義されたシーケンシャルワークフローが発生します。何かがおかしいと感じさせるのは、このコードの手続き的な性質だと思います。これは必ずしも悪いことではなく、レガシーコードを使用する場合は完全に避けられない場合があります


6

元のコードベースをクリーンアップしたのと同じ方法で、大きないグルーメソッドをクリーンアップする必要があります。きちんとしたモジュール方式で分割します。おそらく、いくつかのタスクを実行するコード行のグループがこれらの行をメソッドに分割します。変数を共有する場合、共有変数と新しいメソッドを1つのクラスに入れることを検討できます。


2
その場合、グルーツリーを取得しませんか?
ピーターB

3
@PieterBかもしれませんが、さまざまな方法でさまざまなタスクがある場合、さまざまな依存関係を抽出する方が簡単です。新しいメソッドを抽出した後、別のリファクタリングパスを実行できます。
パリング

1

基本的に、抽象レイヤーを追加し続けます。それは、各レイヤーが単独で使用されるようになるまで続きます。抽象化に関する逆説的なことは、複雑さを追加して軽減することです。なぜなら、抽象化されたコードを読むときは、一度に1つのレイヤーだけに関心があるからです。各レイヤーが簡単に理解できるほど小さい場合、そのレイヤーがいくつあるかは関係ありません。

それも抽象化を書くのを難しくするものです。鉛筆のような単純なものでも、抽象化のすべてのレイヤーを一度に頭の中に収めようとすると、頭が曲がります。重要なのは、1つのレイヤーを好きな方法で取得し、そのレイヤーの基礎となる複雑さをすべて忘れて、次のレベルで同じことを行うことです。


0

APIの実装について考えるだけでAPIをリファクタリングしているように聞こえますが、APIを使用するコード、つまり、あなたが話している「グルーコード」について十分に考える必要はありません。

それが本当なら、反対側から始めようとするかもしれません。最初にyourいグルーコードになる恐れがあるものを書き直し、そのプロセスでAPIになるいくつかのまだ実装されていないインターフェイスを作成します。このAPIの実際の実装については、あまり考えすぎないでください。それができるという直感があれば大丈夫です。そして、そのAPIに適合するようにコードラビリンスを書き直してください。もちろん、このプロセスではAPIと接着剤コードにいくつかの変更がありますが、よりうまく適合するはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.