11

私は Java で多くのコードを開発し、Groovy と Haskell に手を出しました。それが今では Scala につながっています。

私は Scala の機能面には比較的慣れていますが、Scala のオブジェクト指向設計については、特にトレイト/ミックスインが原因で、Java とは少し異なるように感じられるため、少し不安定です。

私はできる限りテストしやすいコードを書くことを目指しています。

  • 可能な場合の不変性
  • コンストラクターによる状態の注入を優先する
  • 常に継承ではなく構成を使用してください ( SO に関するこの投稿の影響を強く受けており、おそらく過剰反応です) 。

今、私はこの新しい Scala テリトリーに足を踏み入れようとしていますが、ここでどのアプローチを採用すべきか、特に何らかの目的で継承を使用する必要があるかどうかを判断するのに苦労しています。

Programming Scala (Wampler and Payne; O'Reilly、第 2 版) には考慮事項のセクション (「優れたオブジェクト指向設計: 余談」) があり、SO に関する多くの投稿を読みましたが、見たことはありません。テスト容易性の設計上の考慮事項についての明示的な言及。この本は、継承の使用に関する次のアドバイスを提供しています。

  1. 抽象基本クラスまたは特性は、ケース クラスを含む具象クラスによって 1 レベル サブクラス化されます。
  2. 次の 2 つの場合を除いて、具象クラスはサブクラス化されません。
    • 特性で定義された他の動作を混在させるクラス (...)
    • 自動化されたユニットテストを促進するためのテスト専用バージョン。
  3. サブクラス化が適切なアプローチのように思われる場合は、動作を特性に分割し、代わりにそれらの特性を混合することを検討してください。
  4. 親子型の境界を越えて論理状態を分割しないでください。

SO を掘り下げてみると、ミックスインが合成よりも望ましい場合があることも示唆されています。

本質的に、私は2つの質問があります:

  1. テスト容易性を考慮しても、継承を使用した方がよい一般的なケースはありますか?

  2. ミックスインは、コードのテスト容易性を向上させる良い方法を提供しますか?

4

2 に答える 2

11

あなたが参照した Q/A での特性の使用法は、特性を混合することによって提供される柔軟性を実際に扱っていました。

たとえば、特性を明示的に拡張すると、コンパイラはコンパイル時にクラスとスーパークラスの型をロックします。この例では、MyService はLockingFlavorA

trait Locking { // ... }

class LockingFlavorA extends Locking { //... }

class MyService extends LockingFlavorA {

}

型付き自己参照を使用した場合 (指摘した Q/A に示されているように):

class MyService {
   this: Locking =>
}

.. はそれ自体、または の有効なサブクラスをLocking参照できます。次に、作成者は、その目的で新しいクラスを明示的に作成せずに、呼び出しサイトでロックの実装を混ぜます。LockingLocking

val myService: MyService = new MyService with JDK15Locking

テストを容易にすることができると彼らが言うとき、彼らは実際にはこの機能を使用して、私たち Java 開発者がコンポジションとモック オブジェクトで通常行うことをエミュレートすることについて話していると思います。モックLocking実装を作成し、テスト中にそれを混ぜて、ランタイム用の実際の実装を作成するだけです。

あなたの質問に対して: これは、モッキング ライブラリと依存性注入を使用するよりも良いですか、悪いですか? 言うのは難しいですが、最終的には、どちらかの手法が残りのコードベースとどれだけうまく機能するかにかかっていると思います。

すでにコンポジションと依存関係の注入を効果的に使用している場合は、そのパターンを継続することをお勧めします。

あなたが始めたばかりで、まだ大砲を必要としていない場合、または依存性注入が適切であると哲学的に判断していない場合は、ミックスインから非常にわずかなコストで多くのマイレージを得ることができます。実行時の複雑さ。

真の答えは非常に状況に応じたものになると思います。

TL;DR 以下

質問 1) コンポジション/dep-inj に代わる状況に応じた有用な代替手段だと思いますが、おそらく単純さ以外に大きな利点はないと思います。

質問 2) はい、主にトレイト実装を介してモック オブジェクトをエミュレートすることにより、テスト容易性を向上させることができます。

于 2015-02-17T19:01:38.340 に答える