Расширение класса внешними методами и переменными

Adelf

Administrator
Команда форума
@fixxxer ты разве не знал, что open в этом принципе означает "класс должен быть открыт для наследования"?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
запретить нарушения SOLID невозможно и не нужно, но мы можем прямо назвать нарушения нарушениями, и обозначить проблемы, которые последуют в будущем, если оно наступит
 

fixxxer

К.О.
Партнер клуба
@fixxxer ты разве не знал, что open в этом принципе означает "класс должен быть открыт для наследования"?
В том-то и дело, что не означает. Есть такая трактовка, она самая популярная, но крайне неудачная, поскольку смешивает принцип и способ его реализации. Ну написал Мейер в 88-м году про наследование, что теперь, обосраться и не жить?

Есть более вменяема формулировка, которая называется Polymorphic Open/Closed Principle.
 
Последнее редактирование:

Adelf

Administrator
Команда форума
В том-то и дело, что не означает. Есть такая трактовка, она самая популярная, но крайне неудачная, поскольку смешивает принцип и способ его реализации. Ну написал Мейер в 88-м году про наследование, что теперь, обосраться и не жить?

Более вменяема формулировка, которая называется Polymorphic Open/Closed Principle.
эх. я думал сарказм зайдёт :) а оказалось, что люди реально так думали.
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Сложно распознать сарказм, когда в изначальной публикации про OCP написано про наследование. :)
 

whirlwind

TDD infected, paranoid
😅

Если ты не троллишь, то это какое-то понимание OCP из 80-х
Не троллю. А что расширение OCP до POCP меняет в данном аспекте? Или наследование уже уволили из триады основных принципов ООП? Если нет, то претензии к final обоснованы. Если класс нормальный и пригоден для широкого reuse, то разработчик не может и не должен ограничивать круг его обязанностей. Проблемы чужого дизайна этого разработчика вообще волновать не должны. По поводу POCP я сильно могу потроллить. Представь, что ты взял некую стороннюю либу, которая торчит наружу фасадом за которым скрыта жыырная реализация. Если эта либа не предусматривает расширения по типу DI, то единственный вменяемый вариант - наследование. Я уже не говорю, что во многих случаях, чтобы внедрить нечно стороннее в проект с тестами, без mocking и partial mocking обойтись невозможно. Но когда мы говорим о модульных тестах все остальные разговоры это все про экономию на спичках.
 
Последнее редактирование:

флоппик

promotor fidei
Команда форума
Партнер клуба
Представь, что ты взял некую стороннюю либу, которая торчит наружу фасадом за которым скрыта жыырная реализация. Если эта либа не предусматривает расширения по типу DI, то единственный вменяемый вариант - наследование.
Прости, но это реально звучит как "Представьте, что вот вы взяли говно, а там ваше расширение вместо наследования - не работает! поэтому ваш файнал - говно!"
 

WMix

герр M:)ller
Партнер клуба
Например, final противоречит Open/Close.
ты думешь Open означает наследование обьектов?
тут читать
Или наследование уже уволили из триады основных принципов ООП?
да нет же, просто наевшись кактусов, наследуем только абстракцию
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Или наследование уже уволили из триады основных принципов ООП?
Да лажа полная эта триада, это C++-ное понимание ООП (ну ок, ноги растут из Simula, но что это меняет)? ООП прекрасно реализуется без наследования вообще. Как и без концепции класса. Вот понятия интерфейса (в широком смысле, как множество контрактов) и объекта (как черного ящика, поддерживающего контракты) - ключевые.
 

whirlwind

TDD infected, paranoid
ты думешь Open означает наследование обьектов?
Open означает ровно то, как переводится - открыт. Вы упорно не хотите видеть окончание формулировки - для расширения. Каким образом - дело двадцатьпятое. Декорирование-же никого из вас не смущает?

Где я спорил, что ООП не реализуется без наследования? Цена вопроса? Возьми свой распрекрасный final класс, у которого нет интерфейса, и попробуй сделать unit test на другой класс, который использует этот первый в качестве зависимости. Приватный конструктор или package visible конструктор - те же самые яйца. Способов выстрелить себе в ногу существует множество. Стоимость становится видна не там где программы уровня hello world, а где активный code reuse и абстрагирование от сложной логики.

По поводу говна, откройте любимую, эталонную ООП-эшную, с годами обсосанными rfc-хами java core и объясните мне где там DI? Там миллион примеров, где наследование вместо возможного DI, DI или просто нет или наследование более чем оправдано (пример навскидку MouseListener + MouseAdapter).
 

Вурдалак

Продвинутый новичок
Как в этой, так и в одной старой теме, ты пытаешься сказать, что OCP требует non-final класс, потому что существуют плохие non-final классы. Или что нельзя unit-тест написать. Ты совершаешь ошибки в рассуждениях.
 

whirlwind

TDD infected, paranoid
Как в этой, так и в одной старой теме, ты пытаешься сказать, что OCP требует non-final класс, потому что существуют плохие non-final классы. Или что нельзя unit-тест написать. Ты совершаешь ошибки в рассуждениях.
Это одно и то же. Современные фреймворки тестирования (и многие IoC контейнеры) работают по одному принципу. final метод или класс становится невозможно переопределить (что в вашем понимании = невозможно или не нужно унаследовать). Если его невозможно переопределить, то невозможно создать проксю для навеса AOP, мокнуть, автоматически сделать lazy init/load, и т.п. Но, бесспорно, написать программу без наследования как и без ООП и даже без любого высокоуровневого ЯП определенно возможно. Для этого понадобится какая нибудь програмка для побайтного ввода и справочник Гука.

Все прелести всех трех принципов ООП можно увидеть разбирая как реализованы IoC+DI в разных языках. Там сразу видны все проблемы при отклонении от умеренного понимания инкапсуляции: паблик проперти - отклонение в сторону нарушения инкапсуляции, ваше отсутствие наследование - отклонение в сторону параноидальной инкапсуляции. Приватные конструкторы, публичные проперти, final - все что закрывает для расширение или диктует нефункциональные требования (hello, singleton!) все это мешает повторному использованию и стоит времени. Кое что решается наличием рефлексии. Но это из разряда грязных хаков и не делает проблему несуществующей.
 

Вурдалак

Продвинутый новичок
Я еще раз сформулирую мысль: ты пытаешься сказать, что final не нужен, потому что кто-то не умеет им пользоваться. Это логическая ошибка.
 

whirlwind

TDD infected, paranoid
Я еще раз сформулирую мысль: ты пытаешься сказать, что final не нужен, потому что кто-то не умеет им пользоваться. Это логическая ошибка.
Нет не так. final не нужен потому, что мне не известен кейс, где его использование будет оправдано. Приведите пример.
 

Вурдалак

Продвинутый новичок
Нет не так. final не нужен потому, что мне не известен кейс, где его использование будет оправдано. Приведите пример.
Если бы в языке по умолчанию был final и требовалось бы писать open к тем классам, где наследование разрешено (Kotlin, например), то такой формулировки («где его использование будет оправдано»), наверное, бы не было. Я ищу не места, где нужен final, а где его можно убрать.

Я могу привести в пример, допустим, любой value object. Или класс с одним методом, который реализует интерфейс. Там наследование при всём желании не имеет смысла, там нечего будет наследовать, даже притянуть его за уши не получится.
 

Adelf

Administrator
Команда форума
Нет не так. final не нужен потому, что мне не известен кейс, где его использование будет оправдано. Приведите пример.
https://github.com/adelf/acwa_book_ru/blob/master/manuscript/2-di.md#наследование. Вот здесь я попытался придумать проблему. Вполне вероятную кстати.
 

Yoskaldyr

"Спамер"
Партнер клуба
@Adelf пример с одной стороны неплохой, но с другой показывает что против лома нет приема, т.е. против говнокода не устоит ни одна абстракция (и говнокод в данном случае это кусок ларавеля и как он рефакторился)
 

Adelf

Administrator
Команда форума
@Adelf пример с одной стороны неплохой, но с другой показывает что против лома нет приема, т.е. против говнокода не устоит ни одна абстракция (и говнокод в данном случае это кусок ларавеля и как он рефакторился)
Да нормально рефакторился. Контракт соблюдён был всегда. Во многих случаях делать декоратор намного безопаснее.
 

Yoskaldyr

"Спамер"
Партнер клуба
Да нормально рефакторился
Ну блин, где нормально??? добавление метода PushOn это не нарушение контракта? Я уверен что провернули все это в минорных версиях. Т.е. говнокодить начали значительно раньше чем вынесли в интерфейс и стали использовать еще один общий метод, но там уже претензий нет. Накосячили значительно раньше, а ошибка это следствие этого и следствие отстутствия тестов.

А вообще в примере все прекрасно и кто расширял и разработчики фреймворка. В текущей разработке надо бы уже привыкнуть, что даже в минорных версиях сторонних библиотек все может поломаться и тесты обязаны быть как раз для любого вызова сторонних библиотек и для всего связанного с работой с фреймворком (кстати как раз это часто не тестируют, считают что фреймворк написан идеально, что лол)
 
Сверху