jeudi 22 juin 2017

Refactore really complicated method (Spring)

I made this kind of thing :

@Service
public class MyService {

    @Autowired
    private AnotherService anotherService;

    public void reallyComplicatedMethod(A a, B b, C c, D d, E e, F f){
        // over 9000 lines of code that use anotherService
    }
}

This seem beautiful but lines contains a magic tree of nested "if" "else" everywhere

So I refactore it to separate different parts :

@Service
public class MyService {

    @Autowired
    private AnotherService anotherService;

    public void reallyComplicatedMethod(A a, B b, C c, D d, E e, F f){
        part1(a, b, c);
        part2(a, b, c, d, e, f);
        part3(a);
        // ...
    }

    private void part1(A a, B b, C c){...}
    private void part2(A a, B b, C c, D d, E e, F f){
        // imagine a lot of if else for ...
        part2_1(a, b, c);
        part2_2(d, e, f);
    }
    private void part2_1(A a, B b, C c){...}
    private void part2_2(D d, E e, F f){...}

    private void part3(A a){...}
    // other parts

}

Classic. But I have a lot more arguments (A, B, C, D ...), with complicate names that are really invasive in my "partX" methods.

So I add it into an object that contains all those arguments. I use this object to launch the process instead of pass it in every method.

@Service
public class MyService {

    @Autowired
    private AnotherService anotherService;

    public void reallyComplicatedMethod(A a, B b, C c, D d, E e, F f){
        new DoMyMethod(a, b, c, d, e, f).run();
    }

    class DoMyMethod {
        A a, B b, C c, D d, E e, F f;

        // It can also be a Builder (if there are too many parameters)
        DoMyMethod(A a, B b, C c, D d, E e, F f){
            // el famoso constructor with this.x = x;
        }

        void run() {
            part1();
            part2();
            part3();
            // ...
        }

        private void part1(){...}
        private void part2(){...}
        // sub part2
        private void part3(){...}
        // other parts
    }
}

At the end, I find the "partX" method really cool to read but the architecture feels like "wtf are you doing bruh ?!"

Add other classes that do the job is a convenient way to do this, but Spring @Autowired services and arguments have to be exchange everywhere.

Can you please give me some advices ? like some kind of design pattern for example :)

Aucun commentaire:

Enregistrer un commentaire