简体   繁体   中英

How to follow Single Responsibility Principle in set of actions

I have a windows service application that read some files and does some modification and upload to a web API.

In here I followed the single responsibility principle as much as possible.

In this app, I have 3 classes that read files' content, apply business logic and upload that modified content to the server.

class GetFileContent { 
// in here there is a method to return the file content
}

class ApplyBusinessLogic { 
// in here there is a method to get that file content as param and apply business logic
}

class UploadContent {
// get the modified content and upload it
}

Now my question is if I added a new class as DoMyActions and create objects of above class and call theres methods for doing those task, is that violation of the Single Responsibility Principle? For make clear of my question I am tring to do something like below.

class DoMyAction { 

GetFileContent content = new GetFileContent();
// call the method in above class and get the content

ApplyBusinessLogic doMyThing = new ApplyBusinessLogic();
// do my stuff using that file content

UploadContent uploader = new UploadContent();
// upload the content
}

Is there a better approch on this?

If I continuously want to use DoMyAction class how to follow the Single Responsibility Principle?

If the DoAction class process does not change, you can directly encapsulation GetFileContent , ApplyBusinessLogic , UploadContent into the DoAction class.

But I would create interfaces for each class to let code more flexible.

public interface IFileContent{
    byte[] GetFileContent();
}
public interface IApplyBusinessLogic{
    void ApplyLogic();
}
public interface IUploadContent{
    void Upload();
}

Then every class implement each interface, which matches its action.

public class GetFileContent : IFileContent { 
    public  byte[] GetFileContent(){

    }
    // in here there is a method to return the file content
}

public class ApplyBusinessLogic : IApplyBusinessLogic { 
    public void ApplyLogic(){

    }
    // in here there is a method to get that file content as param and apply business logic
}

public class UploadContent : IUploadContent{
    public void Upload(){

    }
    // get the modified content and upload it
}

Then I would use constructor injection to inject the proceed, class let the code more flexible.

public class DoMyAction { 

    IFileContent _content;
    // call the method in above class and get the content

    IApplyBusinessLogic _doMyThing;
    // do my stuff using that file content

    IUploadContent _uploader;
    // upload the content


    public DoMyAction(IFileContent content,IApplyBusinessLogic doMyThing,IUploadContent uploader){
        _content  = content;
        _doMyThing = doMyThing;
        _uploader = uploader;
    }

    public void excuteAPI(){
      //doing something here
    }
}

You can set your execute logic in excuteAPI method from DoMyAction class.

I think this is a great question that has troubled me every now and then so here are my 2 cents

Actions, like DoMyAction , that must do some orchestration between many services are common and there is no simple way around them. However, it is very easy to forget their true purpose and add extra stuff that should ideally be elsewhere. So, in the spirit of single responsibility:

  • Don't encapsulate construction of dependencies. That is a separate responsibility in itself. You can get all dependencies from the constructor through injection as this answer has illustrated
  • Follow the Law of Demeter and stick to your immediate dependencies. This will minimize the coupling of your action to its dependencies. For example, don't do: getFileContent().getRelevantSections().formatProperly()
  • The action should operate on abstract interfaces so that it caters to multiple types of files, processors and uploading services
  • In general, remind yourself about the scope of your action and move out anything other than orchestration stuff or whatever its supposed to do

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