メソッドを呼び出すためだけにオブジェクトを頻繁に作成している場合、コードのにおいですか


14

次のようなコードがたくさんあるコードベースを継承しました。

SomeDataAdapter sda = new SomeDataAdapter();
sda.UpdateData(DataTable updateData);

そして、sdaは二度と使用されません。

これらのメソッドは、実際には静的クラスメソッドである必要があることを示すコードの匂いですか?


これらのクラスはインターフェースを実装していますか?
Reactgular

7
静的メソッドにリファクタリングした翌日は、モックバージョンのデータアダプターを使用して単体テストを実行する日です。
マイク14年

22
@マイク:静的メソッドをモックする必要があるのはなぜですか?私は、静的メソッドはテスト可能ではないというこの誤った議論にうんざりしています。あなたの静的メソッドは、状態を保持するか、副作用を作成している場合、つまり、あなたの障害ではなく、あなたのテスト方法論の障害。
ロバートハーヴェイ14年

9
私の意見では、これは「すべてがクラスでなければならない」分析の弱点を示す言語の匂いです。
ベン14年

7
@RobertHarvey:他のメソッドをモックするのと同じ理由で、静的メソッドをモックする必要がある場合があります。単体テスト中に呼び出すにはコストが高すぎます。
ケビンクライン14年

回答:


1

UpdateDataはおそらく「サービス」クラスに属している必要があるため、これはアーキテクチャの匂いだと思います。

データがAppleである場合。AppleAdapterはservice / business-intelligenceクラスです。AppleServiceは、現在のメソッドの外部に存在するAppleAdapterへのシングルトン参照です。

private static volatile AppleAdapter _appleService = null;
private static object _appleServiceLock = new object();
private AppleAdapter AppleService
{
    get
    {
        if (_appleService == null)
        {
            lock (_appleServiceLock)
            {
                if (_appleService == null)
                    _appleService = new AppleAdapter();
            }
        }
        return _appleService;
    }
}

public SomeAppleRelatedMethod(Apple apple)
{
    AppleService.UpdateData(apple);
}

あなたがしていることは必ずしも間違っているとは思いませんが、SomeDataAdapterが何らかのステートレスビジネスサービスを実際に表している場合、シングルトンがベストプラクティスになります。お役に立てば幸いです!提供されている例は、_appleServiceがnullであり、2つ以上のスレッドによってまったく同時にアクセスされた場合に、_appleServiceの競合が発生しないようにする便利な方法です。

あのね?SomeDataAdapterがADO IDbDataAdapter(ほぼ確実にそうです)である場合、この応答全体を無視してください!

:P

元の質問にコメントを追加する権限はありませんが、このコードが存在する場所を指定できる場合。

このコードがIDbDataAdapterのカスタム実装を表し、UpdateDataがIDbConnection、IDbCommandを作成し、それらをすべて舞台裏で接続している場合、コードの臭いは考えられません。使い終わったときに処分する必要があるもの。


12
助けて!私はソフトウェアパターンにdrれています。
ロバートハーヴェイ14年

4
...または依存関係として注入されます。;)
ロブ14年

12
シングルトンとダブルチェックロックをいじって、単純な関数/手順に相当するものを取得することは、私にとってはるかに大きなコードのにおいです!
ベン14年

3

この問題はそれよりもさらに深くなると思います。それを静的メソッドにリファクタリングしたとしても、どこでも単一の静的メソッドを呼び出すコードを取得できます。私の意見では、それ自体がコードの匂いです。重要な抽象化が欠落していることを示している可能性があります。たぶん、前処理と後処理を行いながら、その間に起こることを変更できるコードを作成したいかもしれません。その前処理と後処理には共通の呼び出しが含まれ、中間の呼び出しは具体的な実装に依存します。


もっと深い問題があることに同意します。完全なアーキテクチャの再設計をせずに段階的に改善しようとしていますが、私が考えていたことはそれを行うには良い方法ではないようです。
シェーンWealti 14年

1

やや。それは通常、関数を渡したいと思っていることを意味し、あなたの選択した言語はあなたを許しません。それはちょっと不器用で洗練されていませんが、一流の機能を持たない言語にこだわっている場合、できることはあまりありません。

これらのオブジェクトのいずれも他の関数への引数として渡されていない場合、それらを静的メソッドに変更することができ、何も変更されません。


また、静的メソッドに、渡されるオブジェクトの修正バージョン(または修正コピー)を返すことを意味する場合もあります。
ロバートハーヴェイ14年

2
「ファーストクラス関数のない言語で立ち往生している場合」:メソッドが1つしかないオブジェクトとファーストクラス関数(またはファーストクラスクロージャー)の間に違いはありません:これらは同じものの2つの異なるビューです事。
ジョルジオ14年

4
@Giorgio理論的にはありません。実際には、あなたの言語が少なくともそのための構文糖を持っていない場合、それはいくつかのハードコードされた狭く有用な関数の違いでfn x => x + 1あり、new Function<Integer, Integer>() { public Integer eval(Integer x) { return x + 1; }};またはそれを制限します。
ドーバル14年

なぜfn x => x + 1シンタックスシュガーになれないのnew Function<Integer, Integer>() { public Integer eval(Integer x) { return x + 1; }}ですか?OK、多分あなたは、この種の構文糖のない言語で立ち往生している場合を意味します。
ジョルジオ14年

@Giorgio Oracleに尋ねる必要があります。(確かに、それはついにJava 8で変わりました)。本当に便利であるためには、それよりも多くの構文シュガーが必要であることに注意してください-また、事前に宣言されたメソッドを名前で渡すことができるようにしたいでしょう。カレーも便利です。ある時点で、関数を最初の市民として扱うのではなく、これらすべてのハックをする価値があるかどうか疑問に思う必要があります。しかし、今私は話題から外れています。
ドーバル14年

0

状態を保持することで、特定のクラスがより実用的で機能的になり、再利用可能になった場合、いいえ。何らかの理由で、コマンド設計パターンが思い浮かびます。その理由は確かにロバート・ハーヴェイをhaveれさせたいという願望ではない。


0

「頻繁に」を定義します。オブジェクトをどのくらいの頻度でインスタンス化しますか?たくさん-おそらくない?

システムには、より大きな問題があります。静的にすることで、オブジェクトの内部状態が変わらないことをプログラマに明確に伝えることができます。

状態が混乱している場合、最初のものを静的にするために他のものを静的にする必要がある場合は、どの部分を静的にする必要があり、どの部分を静的にしないかを尋ねる必要があります。

はい、それはコードの匂いです、ほんの小さなものです。


0

静的メソッドにして、次に進みます。静的メソッドには何も問題はありません。使用パターンが現れると、パターンの抽象化について心配することができます。


0

ここでの臭いは、これがオブジェクトに(最小限)ラップされた手続き型コードであるということです。

データテーブルでその操作を実行する理由がなければなりませんが、いくつかのセマンティクスを共有する(つまり、共通の意味を持つ)他の関連する操作でその操作をモデリングするのではなく、作成者は新しいプロシージャ内で新しいプロシージャを作成しましたクラスと呼ばれます。

関数型言語では、それがあなたのやり方です;)が、オブジェクト指向のパラダイムでは、その操作を含むいくつかの抽象化をモデル化します。次に、オブジェクト指向技術を使用してそのモデルを具体化し、いくつかのセマンティクスを保持する関連操作のセットを提供します。

したがって、ここでの主な臭いは、おそらくコンパイラーがクラスを必要としているために、作者がクラスを使用していることです。操作を概念モデルに編成することはありません。

ところで、問題空間の代わりにモデル化されているプログラムを見るときはいつでも注意してください。これは、デザインがより多くの思考から利益を得ることができることを示しています。つまり、クラスがすべて「xAdaptor」、「xHandler」、および「xUtility」であり、通常は貧弱なドメインモデルに結び付けられていることに注意してください。実装したいコンセプトを実際にモデリングするのではなく、誰かが便宜上コードを束ねているだけです。

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