Mixed Entity and Business classes - Refactor help needed

101 views Asked by At

I have a project where Entity Classes and Business classes are mixed up. The entity beans are part of the business and all is used through the whole project.

How can I best refactor those classes to separate those layers. I also want to keep the changes to the implementers as minimal as possible. Preferable no changes, otherwise hundreds of references need to be updated. How should I rename the classes and work through this?

Example of mixed code:

// Mixed business-entity class
public final class Language {
    private final Long id;
    private final String code;
    private final String description;

    //Constructor
    public Language() {
    }

    //getters and setters
    public String getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    ...

    //Business is a part of this class
    public static Language findByUser(User user) {
        Language language;
        ...implementation to find user language...
        return language;
    }

    ....
}

// Implementing class
public class Messenger {
    public Messenger() {
    }

    public static void sendEmail() {
        ...
        Language emailLanguage = Language.findByUser(user):
        ...
    }
}

I want to separte those layers in:

// Entity Class
public final class Language {
    private final Long id;
    private final String code;
    private final String description;

    //Constructor
    public Language() {
    }

    //getters and setters
    public String getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }
    ...
}

// Business Class

public final class LanguageImpl {
    public LanguageImpl() {
    }
    public static Language findByUser(User user) {
        Language language;
        ...implementation to find user language...
        return language;
    }
    ....
}

Provide minimal changes to implementation classes, preferable no changes. Otherwise a lot of work will come because of the references all over the code-base.

// Implementing class
public class Messenger {

    public Messenger() {
    }

    public static void sendEmail() {
        ...
        Language emailLanguage = Language.findByUser(user);
        ...
    }
}

How do I work through this refactoring? How should I rename my classes?

Any thoughts would be very helpful! Thanks!

1

There are 1 answers

0
Dimitri Dewaele On BEST ANSWER

This is my solution. Please review and accept this if it looks good. Thanks!

The mixed business-entity class is re-used as a wrapper class. This makes it possible to re-use this in all implementing classes where no changes are needed.

public final class Language Extends LanguageImpl{
    private final LanguageEntity languageEntity;
    //Constructor
    public Language(LanguageEntity le) {
        languageEntity = le;
    }

    //Wrapper method
    public static Language findByUser(User user) {
        LanguageEntity le = findEntityByUser(user);
        Language language = new Language(le);
        return language;
    }
    ....
}

A new Entity class is created (LanguageEntity) in a new package. This avoids package and naming conflicts with the original mixed class (Language). All entity fields and methods from the mixed class are moved here.

package com.test.entity;
public final class LanguageEntity {
    private final Long id;
    private final String code;
    private final String description;
    //Constructor
    public LanguageEntity() {    }
    //getters and setters
    public String getId() { return this.id;  }
    public void setId(Long id) {  this.id = id;    }
    ...
}

A new business class is created (LanguageImpl) in a new package. All business methods are moved here. The original mixed class will extend this new business class.

package com.test.impl
public final class LanguageImpl {
    //Constructor
    public LanguageImpl() {     }
    //Business is a part of this class
    public static LanguageEntity findEntityByUser(User user) {
        LanguageEntity language;
        ...implementation to find user language...
        return language;
    }
    ....
}

This is an implementing class that does not need changes. Hundreds of implementation locations remain unchanged, which saves a lot of work. Hurray!

public class Messenger {
    public Messenger() {    }
    public static void sendEmail() {
        ...
        Language emailLanguage = Language.findByUser(user):
        ...
    }
}

And for future development, the new combination LanguageEntity and LanguageImpl will be used. The original Language will be deprecated.

Please leave comments on this solution. Other solutions are more than welcome!