【问题标题】:How to follow Single Responsibility Principle in set of actions如何在一组行动中遵循单一职责原则
【发布时间】:2019-04-27 16:33:12
【问题描述】:

我有一个 Windows 服务应用程序,它读取一些文件并进行一些修改并上传到 Web API。

在这里我尽可能地遵循单一责任原则。

在这个应用程序中,我有 3 个类来读取文件的内容、应用业务逻辑并将修改后的内容上传到服务器。

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
}

现在我的问题是,如果我添加了一个新类 DoMyActions 并创建上述类的对象并调用执行这些任务的方法,这是否违反了单一责任原则?为了弄清楚我的问题,我正在尝试执行以下操作。

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
}

有没有更好的方法?

如果我一直想使用DoMyAction 类如何遵循单一职责原则?

【问题讨论】:

    标签: c# .net oop solid-principles single-responsibility-principle


    【解决方案1】:

    如果DoAction类流程不变,可以直接将GetFileContent,ApplyBusinessLogic,UploadContent封装到DoAction类中。

    但我会为每个类创建接口,让代码更灵活。

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

    然后每个类实现每个接口,与它的动作相匹配。

    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
    }
    

    然后我会使用构造函数注入来注入procedure,class让代码更灵活。

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

    你可以在DoMyAction类的excuteAPI方法中设置你的执行逻辑。

    【讨论】:

    • 您能否解释一下您的第三个代码块的优势是什么或使用它的原因是什么?
    • @NoughT 第三个代码块可以让用户决定用户想要使用哪个实例而不是DoMyAction类中的硬代码。
    • 能否请您看一下这个问题,因为我对 SRP 有疑问:stackoverflow.com/questions/56017036/…
    【解决方案2】:

    我认为这是一个时常困扰我的好问题,所以这是我的 2 美分

    动作,例如 DoMyAction,必须在许多服务之间进行一些编排,这是很常见的,并且没有简单的方法可以绕过它们。但是,很容易忘记它们的真正目的并添加理想情况下应该在其他地方的额外内容。因此,本着单一责任的精神:

    • 不要封装依赖项的构造。这本身就是一项单独的责任。您可以通过注入从构造函数中获取所有依赖项,如this answer 所示
    • 遵循Law of Demeter 并坚持您的直接依赖关系。这将最大限度地减少您的操作与其依赖项的耦合。例如,不要这样做:getFileContent().getRelevantSections().formatProperly()
    • 该操作应在抽象接口上运行,以适应多种类型的文件、处理器和上传服务
    • 一般来说,提醒自己注意行动的范围,并移出除编排内容或应做的任何事情之外的任何事情

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-21
      相关资源
      最近更新 更多