Applying the principle of single liability in methods using subscribe

Asked

Viewed 52 times

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
                }
            });
    }
}

Note that the methods checkA, checkB and checkC perform a service that returns a Obervable (we can see this through .subscribe) which in turn is responsible for consuming a REST API (not explicit, but only that the service is asynchronous).

The chain of events begins with the method checkA and when it is completed executes the method checkB, which in turn executes the checkC.

The point is that the 3 methods have well defined functions, but when completing the task the method performs another method that has a completely different responsibility, breaking the principle of single responsibility.

For example, when I get a car running, I don’t expect it to start accelerating on its own after putting on the seat belt; that’s basically what I’m doing when performing methods with different responsibilities.

I think it would be right for there to be a controlling element responsible for deciding which flow to follow (just as I decide what to do next after putting on my seat belt), but since each method is asynchronous, I don’t know how to solve the problem with Angular 5.

How to solve this problem?

1 answer

0

I solved the problem by creating a control 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 the reading of the code.
  • The methods checkA, checkB and checkC have a single responsibility.
  • As the above methods have become a single liability, they can be reused in other cases.
  • The methods are not responsible for invoking another method, this has become the responsibility of the method invokeChain. This method is responsible for manipulating the flow according to the request previous.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.