Как следовать принципу единой ответственности в совокупности действий

2

У меня есть приложение-служба Windows, которое читает некоторые файлы, выполняет некоторые изменения и загружает их в веб-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 новый класс как DoMyActions и создаю объекты вышеупомянутого класса и вызываю методы theres для выполнения этой задачи, является ли это нарушением принципа единой ответственности? Для разъяснения моего вопроса я стараюсь сделать что-то вроде ниже.

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 как следовать принципу единой ответственности?

Теги:
oop
solid-principles
single-responsibility-principle

2 ответа

2

Если DoAction класса 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
}

Тогда я бы использовал инъекцию конструктора для внедрения продолжения, класс позволил коду быть более гибким.

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

Вы можете настроить выполнение логики в excuteAPI методом из DoMyAction класса.

  • 0
    Не могли бы вы объяснить, в чем преимущество вашего 3-го блока кода или в чем причина его использования?
  • 0
    @NoughT 3-й блок кода может позволить пользователю решить, какой экземпляр пользователь хочет использовать вместо жесткого кода в классе DoMyAction .
Показать ещё 1 комментарий
1

Я думаю, что это большой вопрос, который беспокоил меня время от времени, так что вот мои 2 цента

Действия, такие как DoMyAction, которые должны выполнять некоторую согласованность между многими службами, являются общими, и не существует простого способа их обойти. Тем не менее, очень легко забыть их истинное назначение и добавить дополнительные вещи, которые в идеале должны быть в другом месте. Итак, в духе единоличной ответственности:

  • Не инкапсулируйте построение зависимостей. Это отдельная ответственность сама по себе. Вы можете получить все зависимости от конструктора посредством внедрения, как показано в этом ответе.
  • Следуйте закону Деметры и придерживайтесь ваших непосредственных зависимостей. Это сведет к минимуму связь вашего действия с его зависимостями. Например, не делайте: getFileContent(). GetRelevantSections(). FormatProperly()
  • Действие должно работать на абстрактных интерфейсах, чтобы обслуживать файлы различных типов, процессоры и службы загрузки.
  • В общем, напомните себе о масштабах своего действия и уберите что-нибудь кроме оркестровки или что-то еще, что он должен делать

Ещё вопросы

Сообщество Overcoder
Наверх
Меню