简体   繁体   中英

Refactoring and avoiding code duplication

I've ran into a problem that is new for me. Basically, someone else has already written a class A. The important parts looks like this

class A{

 // some instance variables

 public A(){
  // Calls methods
  build();
  // Calls more methods
 }

 private build(){
  item = makeItem();
  anotherItem = makeAnotherItem();
  // more code
 }

 private makeItem(){
  // Does some things and calls updateItem()
 }

 private updateItem(){
  // Does some things with instance variables of class A
  // and calls yet another method in class A.
 }

My problem is that build() does exactly what I need, but I need it in another class. Now here are the problems:

  1. class A does a whole lot more than the things I've written, and so I cannot create an object of it. It would be pointless.
  2. I've tried copying the build() method for my class B. However, build() uses other methods. And so I have to copy them as well and of course they call other methods and use instance variables declared in some other methods. Basically, I would have to copy 200 rows of code.

I'm guessing this problem actually has a name but I do not know what it's called and have therefore searched some basic terms only. What can I do to use build() in my class B?

You use the code of the build method in two classes but inheritance is not useful? Then you can reuse the code of the build method with composition. (hint Favor Composition over Inheritance ) Create a new class C, which contains the build method. The class C is used by the classes A and B via composition. They delegate to the build method of the class C.

See the refactoring method of Martin Fowler.

https://sourcemaking.com/refactoring/smells/duplicate-code also see https://sourcemaking.com/refactoring/replace-inheritance-with-delegation

Always refactor in small steps. eg Put stuff together that belongs together, perhaps there is a neccessity for another class C which contains makeItem, makeAnotherItem and the corresponding instance variables. There is no general answer and it depends on how your code exactly looks like

first of all if build() in class A is using other private methods of A, that smells like you will need class A itself.

One option could be to create abstract class containing the common methods (including the build method), and extend this abstract class by class A and B. that way you will not have duplicate code

If for some reason you don't want to touch class A, I suggest you create an interface like :

public interface Builder{
    void build()
}

and then implement this interface by your class B, and also extend class A so that you have implementation of the build method.

public class B extends A implements Builder{
    // build() of class A will be used
    // do other staff
}

In doing so, there is no change to class A at all (this might be desired if it is legacy code or something) + Builder can be used as a type in API you want to expose.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM