Как стать автором
Обновить
8
0
Basim Al-Jawahery @Basim108

.Net Backend Developer

Отправить сообщение
Тип 0 используется в Event Sourcing (ES). Может сложиться ощущение что ES это Тип 2, но это не так. Потому что, ES разделяет понятие события и агрегат. Агрегат это искомая бизнес сущность, например документ. Событие же это то что произошло с документом и оно не изменно. Этьо уже произошло и не должно никогда меняться. Если хотим изменить просто создаем новое событие «А теперь хотим изменить поле на какое-то значение».
Сам факт наличие событий является историей данного документа. ES гораздо больше чем версионность, т.к. события могут говорить не только об изменениях в документе, но и других процессах (документ без изменений был согласован; документ без изменений перешел в архив и т.п.).
Поэтому Тип 0 во всю используется в современном стеке технологий.
Но это так дополнение, спасибо за статью :)
Спасибо за статью, полностью согласен с автором и с принципом SRP. Однако размышляя о SRP и ища в коде хорошие и наглядные примеры когда SRP помогает а когда усложняет, я наткнулся на класс List и у него полно методов и полный набор CRUD и кучу перегрузок по каждой букве из CRUD.
И вот вопрос, нужно что делать отдельный класс структура данных и отдельные классы реализациий каждого метода?
Это же будет дико не удобно:
public class MyClass{
  public MyClass(IListAdder adder, IListRemover remover)
  public void MyMethod(IEnumerable<int> list){
       remover.Remove(10, list);
       adder.Add(12, list);
  }
}
Однако не всегда получается красиво так выделить функционал в отдельный класс. Иногда, бывает так, что приватный метод, который нужно сделать protected сильно завязан на члены класса Base.

И ладно еще если метод зависит от публичных членов класса Base, тогда можно было бы вызывать метод в контексте Base, таким образом
function SomeSpeciaFunctionality(){
    this.method = function (){ // useful code 
    }
}
function Base(){
     var _self = this;
     var _compositionInstance = new SomeSpeciaFunctionality();
     function myPrivateFunction(){
        _compositionInstance.method.call(_self);
     }
}

хуже, когда защищаемый метод зависит от приватных, т.е. замкнутых членов класса Base.
Хотя и это не смертельно, можно отказаться от реализации приватных членов через замыкание и использовать замкнутый приватный контекст и на нем уже вызывать:
function SomeSpeciaFunctionality(privateMembers){
    this.method = function (){ // useful code 
    }
}
function Base(){
     var _self = this;
     var _privateMembers ={
           myPrivateVariable: 12
     }
     var _compositionInstance = new SomeSpeciaFunctionality(_privateMembers);
     function myPrivateFunction(){
        _compositionInstance.method.call(_self);
     }
}
Из долгих дебатов на тему нужны ли в классах члены с protected-доступом мне показалось разумным аргумент, что вместо того, чтобы разделять приватные члены с производными классами (а ведь protected-доступ, по сути, именно это и означает), нужно создавать новые классы и использовать композицию. И эти новые классы, можно было бы разделять между производными классами.
т.е. вместо
function Base(){
    //@protected как бы делаем метод защищенным и разделяем его с производными классами
    function protectedMethod(){}
}

разумно сделать
function SomeSpeciaFunctionality(){
    this.method = function (){ // useful code 
    }
}
function Base(){
     var _compositionInstance = new SomeSpeciaFunctionality();
     function myPrivateFunction(){
        _compositionInstance.method();
     }
}
function DerivedClass(){
     var _compositionInstance = new SomeSpeciaFunctionality();
     function anotherPrivateFunction(){
        _compositionInstance.method();
     }
}
Спасибо за комментарий, но позволю себе не согласиться с Вами относительно
и больше относится к интерфейсной части приложения, нежели к данным.
Согласен! И т.к. нарастание копи-пастов не происходит организованно, комментари о том откуда/куда скопированно будет уместен, чтобы понимать сколько раз копировали. И если возникает надобность третий раз коппировать, то нужно помечать код опасным и кондидатом на рефакторинг.
Мне кажется, если DRY не стыкуется с SOLID, то стоит посоветоваться с GoF.
Точно!!! :)
Спасибо! Почитал, полезная и очень интересная ссылка :)
Это повод провести дополнительное тестирование и четко определить как именно должна работать данная логика для срочных посылок

Это правда, так нужно делать обязательно. Однако набор тестов (тест-кейсов) будет зависить от того кода который тестируем, и я думаю комментарии c пометкой какие классы вовлечены в копи-пасту помогли бы как-раз определить этот набор тестов. Да и вообще подобные комментарий откуда/куда копировалось, помогают держать копи-паст под контролем.

В описываемом вами случае можно ввести некий GenericParcel: IParcel, куда сложить всю логику, которая не зависит от типа посылок и затем уже наследовать Parcel и UrgentParcel от него
В случаи, когда мы знаем что надо проектировать одновремено обычные посылки и срочные, то согласен. Но в случаи когда срочные посылки появились позже, рефакторить и как либо менять класс Parcel было бы не разумным риском обрушить модули работы обычных посылок.

P.S. Представьте микросервисную архитектуру, в случаи когда обычные посылки работают в своем микросервисе, мы реализовываем работу срочных посылок в отдельном своем микросервисе и что делать с кодом ела копировать? я думаю это было бы разумнее, чем менять микросервис обычных посылок.

Спасибо Вам за комментарий,

Т е формальные аргументы и возвращаемое значение не меняются, но при этом меняется семантика, так что клиенты IParcel более не могут работать с этим новым классом.
Тут Вы скорее описываете нарушение принципа замещения Лисков.

P.S. Я не хотел описывать сразу весь интерфейс IParcel со всеми его свойствами и методами, дабы читателю было проще читать. Метод ArrivedToRecipient был добавлен не только в класс, он, как я предполагал, но не описал в статье, был изначально у IParcel и его реализация есть в классе Parcel. Так вот вопрос обсуждался стоит ли копи/пастить тело метода в класс UrgentParcel.

Информация

В рейтинге
Не участвует
Дата рождения
Зарегистрирован
Активность