У меня есть приложение-служба 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
как следовать принципу единой ответственности?
Если 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
класса.
Я думаю, что это большой вопрос, который беспокоил меня время от времени, так что вот мои 2 цента
Действия, такие как DoMyAction, которые должны выполнять некоторую согласованность между многими службами, являются общими, и не существует простого способа их обойти. Тем не менее, очень легко забыть их истинное назначение и добавить дополнительные вещи, которые в идеале должны быть в другом месте. Итак, в духе единоличной ответственности:
DoMyAction
.