Delegating objects creates duplicate code: (inheritance versus delegates)

I ran into a situation in the Java OOP world that prompted me to figure out what the ideal way to structure my code for "test ability" is. The research I've done has mostly pointed to delegates, which is a simple, straightforward pattern , however, I find it leads to a ton of duplicate code.

In conclusion, I have a class with some long methods. I have a second class that "extends" the aforementioned long class and overrides some of the above methods. The second class calls the super method when overriding the original (thus the first class is completely needed to shorten the code).

Example: Stripped down parent:

public class ParentClass {

  public void methodX(final int source, final int target) {
   ++++
   ++++
   ++++
  }
}

      

Stripped down child:

public class ChildClass extends ParentClass {

  @Override
  public void methodX(final int source, final int target) {
    super.methodX(source, target)
    ****
    ****
    **** // extra logic
  }
}

      

My thoughts and concerns:

Writing a test class for ChildClass (a class that extends and overrides the methods of its parents) is incredibly tricky because we call it a super method! The super method is critical to prevent duplicate test code, that is, the code to test the ParentClass must be used in the ChildClass. I can mock many of these internal methods manually with Mockito, but it definitely seems like a terrible practice.

My questions:

Is this a fair way to use a super-method, or extend such a class altogether (child classes should be avoided - composition> inheritance)? Do I need to test ParentClass when testing child classes? What design patterns will you use to properly refactor your code to avoid this situation?

+3


source to share


2 answers


I think there are different "smells" in your input:

  • You start by breaking the java coding rules. Class names run UpperCase; but that's just a side note.
  • The first real problem I see is: multiple implementations methodX()

    ; and making this call to the super-implementation part of the essential in your subclass override. This creates a very tight connection between your classes.


I would start at this point - and try to get rid of it; but in case you can't or don't want to; it is absolutely imperative that you do not "ridicule" this super challenge. You want your tests for your subclass to execute the code they depend on.

On the contrary: if you find that you cannot reasonably test your child classes without these mocking tricks; then this is another indication that something is wrong in your codebase.

+1


source


Yes, that's fair.

Extension means defining the relationship "is".

And Mazda IS A Car.



So it's fair (and necessary) to check that Mazda can really do everything that a car does, and it's more than normal that Mazda reuses everything it can from a Car.

To avoid (or minimize) duplication of code between CarTest

and MazdaTest

, you can use CarTestHelper

and place all test code that you want to reuse in static helper methods.

+1


source







All Articles