Apply the principle of sole responsibility in methods that use subscribe

0

Consider the following class:

export class TesteComponent {
    //...
    public onSubmit() {
        this.checkA();
    }

    private checkA(): void {
        this.service.checkA(value)
            .subscribe(response => {
                if(response) {
                    //regra de negócio
                    this.checkB();
                } else {
                    //error
                }
            });
    }

    private checkB(): void {
        this.service.checkB(value)
            .subscribe(response => {
                if(response) {
                    //regra de negócio
                    this.checkC();
                } else {
                    //error
                }
            });
    }

    private checkC(): void {
        this.service.checkC(value)
            .subscribe(response => {
                if(response) {
                    //regra de negócio
                    //fim
                } else {
                    //error
                }
            });
    }
}

Notice that the checkA , checkB , and checkC methods execute a service that returns a Obervable (we can see this through .subscribe ) which in turn is responsible for consuming a REST API is explicit, but it is only important to know that the service is asynchronous.)

The event chain begins with the checkA method, and when it completes it executes the checkB method, which in turn executes checkC .

The point is that the three methods have well-defined functions, but at the end of the task the method executes another method that has a completely different responsibility, hurting the principle of single responsibility.

For example, when I put a car running, I do not expect it to start accelerating on its own after putting the seat belt on; this is basically what I'm doing when running methods with different responsibilities.

I think the right thing would be to have a controller element in charge of deciding which flow to follow (as I decide what to do next after putting on a seatbelt), but since each method is asynchronous, I do not know how to solve the problem with Angular 5.

How to resolve this issue ?

    
asked by anonymous 16.04.2018 / 19:48

1 answer

0

I solved the problem by creating a controller function, for example:

export class TesteComponent {
    //...
    public onSubmit() {
        this.invokeChain('checkA');
    }

    private invokeChain(operation: string) {
        switch(operation) {
            case 'checkA':
                this.checkA(fakeParam).subscribe((response: boolean) => {
                    if(response) this.invokeChain('checkB');
                    else this.errorHandling();
                });
             break;

            case 'checkB':
                this.checkB(fakeParam).subscribe((response: boolean) => {
                    if(response) this.invokeChain('checkC');
                    else this.errorHandling();
                });
             break;

            case 'checkC':
                this.checkC(fakeParam).subscribe((response: boolean) => {
                    if(response) console.log('Fim');
                    else this.errorHandling();
                });
             break;
        }
    }

    private checkA(value: string): Observable<boolean> {
        return this.service.checkA(value)
            .map((response: boolean) => response);
    }

    private checkB(value: string): Observable<boolean> {
        return this.service.checkB(value)
            .map((response: boolean) => response);
    }

    private checkC(value: string): Observable<boolean> {
        return this.service.checkC(value)
            .map((response: boolean) => response);
    }
}

The names used are for example only.

I do not know if there is another solution or some standard to solve the problem, but I consider a reasonable solution for the following reasons:

  • Improves code reading.
  • The methods checkA , checkB and checkC have a single responsibility.
  • Since the methods mentioned above have a single responsibility, they can be reused in other cases.
  • Methods are not responsible for invoking another method, this has become the responsibility of the invokeChain method. This method is responsible for handling the flow according to the previous request response.
24.04.2018 / 16:48