Нарушаем принцип подстановки Лисков и смотрим, что получилось

  Рет қаралды 20,870

S0ER

S0ER

3 жыл бұрын

#soer #itubeteam
Основной канал для общения и публикации новых видео - Телегарм - t.me/softwareengineervlog
Спонсорство - donate.s0er.ru
Сайт платным контентом - soer.pro
Зеркало для видео Дзен Видео - zen.yandex.ru/id/5f578bdf22e2...
GitHub - github.com/soerdev
Чат для программистов - / discord
Группа ВК - codeartblog

Пікірлер: 162
@torburgmax
@torburgmax 3 жыл бұрын
это видео понравилось. я хорошо на него реагирую.
@darkfateinc7333
@darkfateinc7333 3 жыл бұрын
Соер, я думаю все что касается принципов ооп и паттернов проектирования сто процентов будет интересно смотреть, особенно от такого про. Пасиба)
@maximkurbanov
@maximkurbanov 3 жыл бұрын
Ты права.
@railsabbitovich408
@railsabbitovich408 3 жыл бұрын
Соер рассказывает настолько доходчиво , что я начинаю думать что я смогу стать программистом)
@user-po3id7ee7n
@user-po3id7ee7n 3 жыл бұрын
Стать программистом и быть программистом разные вещи)) Если ты не готов 2 дня искать баг в говнёвом коде твоих предыдущих коллег, до 6 утра сидеть латать дыры, потому что на релизе новой фичи ты обосрался и несколько десятков тысяч человек не смогли получить то, что им обещали и заказчик потерял уйму денег, учиться каждый день новому и не стоять на месте, а также всё прочее сопутствующее... ты конечно можешь попробовать) Если не горишь этим, а идешь только за деньгами или статусом или ещё чем-либо кроме личного интереса, разочарование не заставит себя долго ждать) А обучение будет мучительным) Говорю тебе как человек, свичнувшийся в бек-енд в 28 лет из вообще левой сферы деятельности)
@romanradchenko3569
@romanradchenko3569 3 жыл бұрын
Похожее вы и так уже программист.
@user-ot5kt1fi3v
@user-ot5kt1fi3v 3 жыл бұрын
@@romanradchenko3569 программист потому, что понимает лёгенький пример? Как-то странно)
@romanradchenko3569
@romanradchenko3569 3 жыл бұрын
@@user-ot5kt1fi3v начинающий программист :) я понял вас, согласен, подчеркнул то что многие так и спонтанно начинают увлекаться программированием.
@egorkurilko2995
@egorkurilko2995 Ай бұрын
@@user-po3id7ee7n Ну пи*дец, пойду умоюсь горькими слезами ))) в свои 43 годика. Программирование та же фабрика, где есть инженеры с мозгами и образованием, а есть "работяги", с образованием IT школы или курсов, которые и делают всю "черную" работу. Разделим же мух и котлеты! )
@user-lt2vd2ue2e
@user-lt2vd2ue2e 3 жыл бұрын
Важное дополнение. Как скорее всего рассуждал программист, когда наследовал квадрат от прямоугольника? Он изучил предметную область и определил, что квадрат ЯВЛЯЕТСЯ прямоугольником, а раз так, то можно наследовать один от другого. Но с точки зрения LSP отношение ЯВЛЯЕТСЯ не отражают отношения подтипов, что и приводит к ошибке. Об этом пишет Роберт Мартин в книге «Принципы, паттерны и методики гибкой разработки на C#»: «Термин ЯВЛЯЕТСЯ слишком широк, чтобы служить определением подтипа. Правильное определение подтипа - ЗАМЕСТИМ, где заместимость определяется явным или неявным контрактом.»
@0imax
@0imax 3 жыл бұрын
Ну так слово extends не просто так используется при объявлении наследования. Квадрат не расширяет прямоугольник :)
@max_du_cheshire
@max_du_cheshire 3 жыл бұрын
Простите великодушно, труд ваш уважаю, но на мой взгляд этот пример больше про неудачное наследование. Думаю помимо негативного кейса, было бы отлично рассмотреть исправление с использованием LSP.
@artemeelemann317
@artemeelemann317 3 жыл бұрын
Спасибо! За то, что раскрываете такие темы. В примерах, когда упоминается типизация, было бы, конечно здорово видеть примеры на TypeScript, потому что иначе получается мы говорим про интерфейсы, а в коде их нет И Рассматривать контрактное программирование без последних тоже, кажется недостаточным
@0imax
@0imax 3 жыл бұрын
Можно было просто на джаве/C# пример показать, нагляднее было бы.
@user-qv4hn6qq4n
@user-qv4hn6qq4n Жыл бұрын
Понятие интерфейса шире одноименной конструкции из TypeScript и прочих похожих. Интерфейс - это то, через что вы взаимодействуете с некоей частью приложения, например как здесь - конструктор. Вот и получается, что interface'а нет, а интерфейс есть :)
@ILICH1980
@ILICH1980 3 жыл бұрын
еще такого контента, на практических примерах смотреть интересно
@AlexeyGogots
@AlexeyGogots 3 жыл бұрын
Сделали наследование и поучили проблему, использовали мутательность и получили проблему, очередной вариант фактори и получили проблему. Вывод: оопшники всегда найдут способ отстрелить себе обе ноги. :)
@0imax
@0imax 3 жыл бұрын
Функциональщики всегда найдут повод потроллить ООПшников, даже если это очень толсто))
@igor_cojocaru
@igor_cojocaru 3 жыл бұрын
Спасибо. Доступно. Ждем контактное програмирование
@TalkerTube
@TalkerTube Жыл бұрын
Спасибо! Поучил ответы на все вопросы!
@shluhogon_42
@shluhogon_42 Жыл бұрын
Уже во втором примере хоть и начальный квадрат не поменялся, но посчитали мы площадь не квадрата. Нельзя увеличить только ширину и сказать, что это квадрат. Это можно объяснить доходчивее и не растягивать на 15 минут
@user-ic8zh9nw4m
@user-ic8zh9nw4m 3 жыл бұрын
С самого начала не хотелось наследовать квадрат от прямоугольника, но пример хороший вышел, понравилось.
@AleksandrRasskazov
@AleksandrRasskazov 3 жыл бұрын
Хорошее. Давай ещё про круг и овал :) Чтобы закрепить! Шутка.
@IGBasov
@IGBasov 3 жыл бұрын
Спасибо. Хорошо отреагировал на видео.
@TheNikki2009
@TheNikki2009 3 жыл бұрын
Спасибо за видео!
@fellainthewagon7166
@fellainthewagon7166 3 жыл бұрын
Спасибо, стало чуточку легче
@sovrinfo
@sovrinfo 3 жыл бұрын
Спасибо за видео.Коммент в поддержку!
@gennadiikhotovytskyi1579
@gennadiikhotovytskyi1579 3 жыл бұрын
Благодарю, интересно =)
@windxrunner
@windxrunner 3 жыл бұрын
Да здравствует Соер, наш просветитель!
@andreykhalepov8260
@andreykhalepov8260 3 жыл бұрын
Ждём с нетерпением продолжение!
@denisfrunza1040
@denisfrunza1040 3 жыл бұрын
Жду продолжения ✌️
@realmanproject7529
@realmanproject7529 Жыл бұрын
видео - класс, нужно еще
@Bunny-nr6qc
@Bunny-nr6qc 3 жыл бұрын
Только начал читать "Совершенный код", дочитал до LSP и выходит видео про LSP. Кто такой же удачливый? Спасибо С0ЕР
@lamer7905
@lamer7905 3 жыл бұрын
Круто, такие видео заходят прям. Продолжай в том же духе, будет четко.
@user-qv4hn6qq4n
@user-qv4hn6qq4n Жыл бұрын
То что вы сейчас сказали, одна из самых доходчивых вещей, которую я когда-либо слышал, каждый в этой комнате поумнел
@allepta9474
@allepta9474 3 жыл бұрын
Спасибо, стало понятнее)
@user-xh5mp4rc6g
@user-xh5mp4rc6g 3 жыл бұрын
Привет. Спасибо за видео. Было полезно. Можно еще таких примеров на другие принципы SOLID или паттернов GRUSP. Я бы посмотрел.
@OleguitoSwagbucks
@OleguitoSwagbucks 4 ай бұрын
Интеграл для площади - красиво
@AlexanderSavchenko91
@AlexanderSavchenko91 3 жыл бұрын
спасибо ) отличное видео )
@mikhailkh8560
@mikhailkh8560 3 жыл бұрын
Огонь! Наконец то я понял в чем же этот принцип заключается на самом деле.
@Shchyekinyanin
@Shchyekinyanin 3 жыл бұрын
Тогда второе видео про пост/предусловия и инварианты Вам просто жизненно необходимо
@user-vk2ws7dr1e
@user-vk2ws7dr1e 3 жыл бұрын
Круто, теперь у меня яснота появилась с Лиской👍
@goshiketerevskiy2603
@goshiketerevskiy2603 3 жыл бұрын
Не особо гуру в ооп и паттернах, но когда начались все эти пляски с методами и конструкторами, сразу пришел к выводу "а нафига вообще было наследовать квадрат от прямоугольника". как оказалось не зря сомневался. опыт
@hikkarion
@hikkarion 3 жыл бұрын
Офигенное объяснение!
@bigenough2122
@bigenough2122 3 жыл бұрын
Спасибо. Жду об контрактом)
@entropyass
@entropyass 3 жыл бұрын
Просто нужно было добавить сеттер и геттер на поле. Прямоугольник и квадрат различаются лишь тем, что у квадрата ширина и высота связаны(это одно и тоже). И методы для них как не масштабируй подходят. Пример: codepen. io/dkey26/pen/PoWvBRd
@user-li7sm7ux2q
@user-li7sm7ux2q 3 жыл бұрын
Самое крутое объяснение принципа подстановки! Так бы по всем принципам. Ещё хотелось бы увидеть видео про абстрактные методы и интерфейсы. Как правильно всем этим пользоваться
@fallenangel1395
@fallenangel1395 3 жыл бұрын
Как по мне, проблема в том, что мы, изменяя поле width напрямую, раскрываем состояние объекта. Только сам объект должен знать, как нужно работать с его данными. В классе Rectangle должен быть метод "изменить ширину". В Rectangle этот метод должен изменять только поле width, а в Square этот метод должен быть переопределен: вместе с width будет меняться и height. Или переопределение методов тоже нарушает принцип подстановки Барбары Лисков?
@0imax
@0imax 3 жыл бұрын
Я бы вообще не делал для квадрата отдельный класс, а пользовался везде rect-ом. Либо, если для квадрата нужно много уже готовых методов из прямоугольника, которые не хотелось бы копипастить - сделал бы композицию.
@archsapostle1stapostleofth738
@archsapostle1stapostleofth738 3 жыл бұрын
Комментарий для поднятия просвещения в топы
@vitiok78
@vitiok78 3 жыл бұрын
Классика)) Что бы было хорошо сделать так, чтобы отличалось от многих других: Не только рассказать о проблеме, а ещё и предложить решение. Ведь такое использование Прямоугольника и Квадрата это "сферический конь в вакууме". Так вот, чтобы отличаться от всех остальных, было бы неплохо, если бы Вы эту задачу представили как конкретную практическую задачу, потом бы показали, почему такой подход не работает (что и было сделано в этом видео), но после этого ещё бы и показали, как изменить сам подход для решения этой практической задачи. Ведь её надо решать, бизнес не будет смотреть, что у вас Лисков не работает, ему нужно решение. Так вот, начинающему было бы неплохо показать, как с этим бороться грамотно, чисто. Ведь явно видно, что эти два класса родственные, что у них будет куча одинаковых методов. Вот надо было бы подвести программиста к пониманию, как выйти из этой ситуации. Итого: видео отличное, но можно было бы и ещё лучше
@pavelkuprin5352
@pavelkuprin5352 3 жыл бұрын
Спасибо за раскрытие темы. Я бы решил проблему наследования квадрата от прямоугольника через внедрение свойства, которое будет хранить соотношение сторон при инициализации. Любые попытки изменить ширину или высоту будут учитывать начальное соотношение сторон (если реализовать через сеттеры).
@ilyasharkov8257
@ilyasharkov8257 3 жыл бұрын
Спасибо за видео. Хорошо расрыт принцип подстановки Барбары Лисков. Очень много коментариев про наследование: что нельзя было квадрат наследовать от прямоугольника. Мне кажется, если бы javascript на уровне языка имел более мощную поддержку принципов ООП (инкапсуляция в смысле сокрытия данных) + свойства, то проблем с использованием методов базового типа применительно к потомку не возникло бы.Но из-за ограничений языка получился отличный пример.
@Davie-gp2ej
@Davie-gp2ej 3 жыл бұрын
Это видео понравилось, я подписался
@VitaliyNET
@VitaliyNET 3 жыл бұрын
Согласен, не нужно нарушать принцип. А в c/c++, за такое линеечкой по пальчикам еще добавить можно) Потому что, если таких Square, будет отрисовываться на экране 15-25 тыс (для OpenGL пустяк), то по памяти это будет в 2 раза больше. Потому что одно поле height лишнее хранится в памяти.
@0imax
@0imax 3 жыл бұрын
И pragma pack не забыть :) правда, это уже совсем из другой оперы...
@user-mh2fc5rs9r
@user-mh2fc5rs9r 3 жыл бұрын
Даёшь контактное программирование!
@MIXEL3D3
@MIXEL3D3 3 жыл бұрын
Спасибо, мистер
@MrKelegorm
@MrKelegorm 2 жыл бұрын
Тут в первую очередь ошибка проектирования интерфейса класса Square. Он описывает модель квадрата, а позволяет (в итоге) редактировать поля так, что это уже не квадрат. Пример для описания принципа подстановки неудачный. Я думаю, стоит придумать пример лучше для объяснения принципа подстановки.
@asnow8423
@asnow8423 3 жыл бұрын
Интересное видео)
@OlegMavlyutov
@OlegMavlyutov 3 жыл бұрын
Эта серия роликов с объяснением SOLID на пальцах очень нравится! Куда более доходчиво чем в других источниках 😎👍
@orucqarayev4759
@orucqarayev4759 Жыл бұрын
спасибо
@ziroshibash7041
@ziroshibash7041 3 жыл бұрын
Офигенный видос, прям в тему, но немного не вовремя.
@ptand5350
@ptand5350 3 жыл бұрын
было бы интересно про все принципы солид, и как можно больше разнообразных примеров из жизни. Теорию много знают, но как их использовать когда код пишешь не все понимают. Именно интересно по анологии с этим видео, какие последствия могут быть, нарушая тот или иной принцип.
@hino2
@hino2 3 жыл бұрын
Ну я бы просто сделал класс для прямоугольника, где второй параметр в конструкторе был бы необязательным. И, если он отсутствует, то в высоту бы копировалась ширина.
@alexneo5458
@alexneo5458 3 жыл бұрын
Видео супер, полезное. Хотелось бы правда, чтобы примеров было больше, т.е. несколько показывать. И желательно, давать некоторые примеры приближенные к реальным вещам, которые встречаются на практике в js, а не таким абстрактным.
@sergeys4732
@sergeys4732 2 жыл бұрын
Создание кнопок разных, вот тебе пример
@artiomciobanu4689
@artiomciobanu4689 3 жыл бұрын
Классический пример)
@Michael_Sh
@Michael_Sh 3 жыл бұрын
Лайк не глядя.
@dann1kid
@dann1kid 3 жыл бұрын
Не досмотрев видево, мне кажется стоит закладывать в родительский класс возврат по количеству аргументов. Проблема наследования состоит в том, что если ты плохо спроектировал, то дальнейшие ветки зависят от рельс, на которые ты положил проект. А если ты поменял, то придется допиливать все наследование.
@alexg9188
@alexg9188 3 жыл бұрын
а так же, на мой взгляд важный момент, если способ расчета площади будет менять, то у нас получится две причины для изменения, потому что метод расчета площади используют два актора - квадрат и прямоугольник. Понятно, что это не относится к фигурам, но в бизнесе требования меняются. Правда это не к Лисков больше, а к SRP, наверное.
@itachinight
@itachinight 3 жыл бұрын
С билдером вообще странный пример, конструктор потомка не обязан быть таким же как как конструктор родителя, конструктор не обязан следовать принципу лисков, потому что мы создаём конкретный экземпляр. это задача билдера(фабрики) уже, если он принимает создаваемый класс через аргументы, проверять, что передано и создавать нужный инстанс и передавать те аргументы которые нужны конкретной реализации
@0imax
@0imax 3 жыл бұрын
Да, надо было просто сделать в базовом классе метод resize(w, h) и поломать голову над тем, как его переопределить в потомке.
@WGDev
@WGDev 3 жыл бұрын
* хорошо реагирует * интересно же ж
@phil2964
@phil2964 3 жыл бұрын
👍👍👍
@artkoorosawa6432
@artkoorosawa6432 3 жыл бұрын
Интересная тема. Чем больше вариантов видео о паттернах и принципах - тем больше будет осмысленности в этих вопросах. Очень хотелось бы избежать знания, наслышанности, заучивания и не использования.
@user-nl7lu9yj6w
@user-nl7lu9yj6w 3 жыл бұрын
Квадрат частный случай прямоугольника, Прямоугольник частный случай четырехугольника, четырехугольник частный случай многоугольника... иерархию вверх можно продолжить дальше)
@BigCrus
@BigCrus 3 жыл бұрын
го продолжение про контрактное программирование
@isidorob9901
@isidorob9901 3 жыл бұрын
На примере видео показано, что нарушив принцип мы не можем создать правильный builder и далее перекладываем возникающие проблемы (обработку ошибок) на других людей. Если мы не нарушим правило и создадим разные типы, то другим людям опять придется учитывать разные типы в своём алгоритме. Здесь вопрос - возможна ли какая-то генерализация чтобы не перекладывать проблемы далее? То есть как сделать универсальный билдер и рассчет площади для разных типов?
@ibl8587
@ibl8587 3 жыл бұрын
реагирую!
@vladhuz8423
@vladhuz8423 3 жыл бұрын
А большая проблема (я понимаю, что js, и мы ограничены в этом плане его реализацией с отсутствие private полей) не мутировать поля напрямую и сделать методы мутации внутри классов, после чего переопределить setWidth and setHeight для квадрата, в которых менять одновременно и то, и то? И на крайняк сделать expand method, который бы возвращал объект того или иного класса, в зависимости от того, равны стороны или нет?
@DjLeonSKennedy
@DjLeonSKennedy 3 жыл бұрын
Если у тебя есть два типа А и B с общим интерфейсом и ты меняешь тип А на тип B, и программа работает верно, значит принцип L не нарушен, все
@tgeor293
@tgeor293 3 жыл бұрын
Кстати, благодаря *_Public and private instance fields proposal_* в JS появятся приватные поля классов. А Chrome, Node и Babel уже поддерживают их.
@user-bl5qv3jy1l
@user-bl5qv3jy1l 3 жыл бұрын
Это тема относится к архитектуре, дизайну или проектированию? Т.е. как мне найти книги про это?
@yuriymusienko9351
@yuriymusienko9351 3 жыл бұрын
«Паттерны объектно-ориентированного проектирования» от банды четырёх
@Shchyekinyanin
@Shchyekinyanin 3 жыл бұрын
Это относится к проектированию. Читайте про SOLID
@Mike-hp3fh
@Mike-hp3fh 3 жыл бұрын
Этот пример кстати наглядно показывает сильные недостатки ООП. Я даже простой квадрат и прямоугольник не могу написать с использованием ООП. Да и опыт показывает, что в подавляющем большинстве случаев я не могу в принципе создать нормальное дерево наследования, не нарушающее никаких принципов. А при создании базового класса мне нужно думать о том какими будут ВСЕ его дочерние классы, не будет ли проблем в будущем, что просто невозможно. Как могу я догадаться что кроме прямоугольника у меня еще будет квадрат, а потом еще и параллелограмм, а в коде уже все завязано на прямоугольники. Проблема ООП в самом его фундаменте - в объединении данных и логики и в строгом наследовании.
@johnins1646
@johnins1646 Жыл бұрын
А что такое контрактное программирование? Это про интерфейсы или про рантайм лонику?
@TemkaGluck
@TemkaGluck 3 жыл бұрын
Как будто, увлекшись SOLID, забыли про инкапсуляцию. Почему бы не перегрузить setWidth(newWidth) и описать корректное поведение и для прямоугольника, и для квадрата как наследника?
@bubblesort6368
@bubblesort6368 3 жыл бұрын
Потому что это приведет к тем же проблемам что и метод mutation. Вместо 50 можно получить 25 и наоборот.
@TemkaGluck
@TemkaGluck 3 жыл бұрын
@@bubblesort6368 mutation не приведёт. Попробуйте: #include class Rectangle { protected: int width, height; public: Rectangle(int w, int h) : width(w), height(h) {} int getWidth() const { return width; } virtual void setWidth(int newWidth) { width = newWidth; } int getHeight() const { return height; } virtual void setHeight(int newHeight) { height = newHeight; } long getArea() const { return width * height; } }; class Square : public Rectangle { public: Square(int w) : Rectangle(w, w) {} void setWidth(int newWidth) override { width = height = newWidth; } void setHeight(int newHeight) override { width = height = newHeight; } }; void mutation(Rectangle * r) { if(r != nullptr) { r->setWidth(r->getWidth() * 3); } } int main() { Rectangle r(5, 10); Square s(5); mutation(&r); mutation(&s); std::cout
@user-gl9yo8rz8k
@user-gl9yo8rz8k 3 жыл бұрын
Шуточное объяснение принципа: Если что-то выглядит как утка, плавает как утка, крякает как утка, летает как утка, но требует батарейки - значит вы что-то делаете не так.
@komodo9109
@komodo9109 3 жыл бұрын
Может я пропустил, а как насчёт количества вкладок?
@user-ec7ne8rn5v
@user-ec7ne8rn5v 3 жыл бұрын
А можно ли добавить 2 setter'а width и height для квадрата?
@0imax
@0imax 3 жыл бұрын
Можно. И тогда придëтся думать над поведением в квадрате: игнорить один из сеттеров или менять w и h одновременно. В любом случае, базовый класс не подразумевает ни игнора одного из сеттеров, ни автоматического изменения размера той стороны, которую не трогали.
@Eugene.g
@Eugene.g 3 жыл бұрын
от изменения Width извне меня аж покоробило )) я бы, конечно, на своих C# и TS, первым делом закрыл сеттер для Width, сделал бы для квадрата и прямоугольника какой-нибудь implements IChangableWidth с методом "public void ChangeWidth(int newWidth)", но проблему с конструктором это бы, конечно, не решило
@0imax
@0imax 3 жыл бұрын
Я бы вообще не наследовал :) Но если прям позарез надо, то сделал бы автоматическое изменение ширины и высоты при изменении любого из них, а так же кидал бы исключение, если попросят квадрат, скажем, 5х15 :)
@Eugene.g
@Eugene.g 3 жыл бұрын
@@0imax ну да, я это и описал, интерфейс вместо наследования. Только конструктор "new Rectangle(5,5)" и исключение выглядит уже костылем и нарушением LSP
@0imax
@0imax 3 жыл бұрын
@@Eugene.g от нарушения тут в любом случае не уйти, если пытаться работать с квадратом и прямоугольником через общий интерфейс, использующий их размеры. Можно на сет любой стороны менять сразу и высоту, и ширину, но с точки зрения прямоугольника высота не должна зависеть от ширины, снова нарушение. Единственный, как мне кажется, адекватный вариант - сделать квадрат обëрткой над ректом, и использовать и рект, и квадрат через интерфейс, ничего не знающий об их размерах. Тогда нарушения не будет.
@isfland
@isfland 2 жыл бұрын
А как правильно реализовать этот пример, не нарушая принцип подстановки Барбары Лисков? Сделать два независимых класса Rectangle и Square с независимыми методами расчета площади?
@user-mu6bh9fc6x
@user-mu6bh9fc6x 2 жыл бұрын
Soer твоё видео по Hex редактором у меня на ютубе не открывается, хотя до этого открывались
@user-dn7qr7vs1h
@user-dn7qr7vs1h 3 жыл бұрын
ООП тут вообще второстепенен, суть ведь про подтипирование. LSP к ООП применяется только вследствие того, что наследование является одним из вариантов подтипирования ( o)( o). Думаю, на этом было бы важно заострить внимание, т.к. понимание этого могло бы дать пользу не только адептам ООП, но ещё и тем, кто просто использует языки с подтипированием и возможностью создавать новые подтипы.
@i_dont_want_a_handle
@i_dont_want_a_handle 2 жыл бұрын
был где-то очень годный доклад про канонические принципы SOLID, в частности про LSP, но я никак не могу ее найти... это был как будто Kevlin Henney, но может и не он, в общем да, там был как раз посыл про то, что LSP - это про подтипы, а не про ООП, со ссылками на оригинальную работу этой Барбары Лисков
@user-kf1xn1dq9t
@user-kf1xn1dq9t 3 жыл бұрын
Это все конечно замечательно,но как решить то проблемму квадрата и прямоугольника?
@0imax
@0imax 3 жыл бұрын
Очевидно: не наследовать друг от друга :)
@user-kf1xn1dq9t
@user-kf1xn1dq9t 3 жыл бұрын
@@0imax тогда код будет дублироваться, со всеми вытекающими последствиями. Прямоугольник и квадрат в прямом смысле слова используют одинаковую логику для всех операций над ними.
@0imax
@0imax 3 жыл бұрын
@@user-kf1xn1dq9t Лучше использовать только rect. Но если почему-то позарез нужен отдельный класс для квадрата, можно использовать композицию.
@user-kf1xn1dq9t
@user-kf1xn1dq9t 3 жыл бұрын
@@0imax я про общий подход к проблеммам такого плана. Тут недостаток примера в том что он не поясняет как надо ПРАВИЛЬНО (ТМ) поступать в такких ситуациях, когда вроде наследовать Y от X самое логическое что можно сделать чтобы не копировать километры кода, но потом из этого вылезает вагон проблем.
@0imax
@0imax 3 жыл бұрын
@@user-kf1xn1dq9t попробовать использовать композицию вместо наследования - вполне общий подход. А уж конкретное решение сильно зависит от конкретного кода.
@a4y_m5r
@a4y_m5r 3 жыл бұрын
И как же решить данную проблему? Делать разные классы для квадрата и прямоугольника?
@pavlomiklashevych1758
@pavlomiklashevych1758 3 жыл бұрын
Ага. Добавив абстрактный класс "фигура", которому дать абстрактный метод для расчета площади.
@mik_zd
@mik_zd 3 жыл бұрын
Я считаю квадрат это прямоугольник плюс ограничение на соотношение сторон или прямоугольник это как результат искажения квадрата с конкретной стороной - растягивания до конкретного соотношения
@DeathIncarante
@DeathIncarante 3 жыл бұрын
Вопрос не совсем по теме - не эффективнее было бы ли создать метод Mutate у объектов? Пусть каждый тип фигуры сам определяет своё поведение при мутации.
@user-eo3ns2ub9l
@user-eo3ns2ub9l 3 жыл бұрын
Или параллельную иерархию, где потомки будут переопределять метод Mutate() и делать с фигурой что хотят?
@VseNikiSukaZanyaty
@VseNikiSukaZanyaty 3 жыл бұрын
Эффективнее и не будет нарушения инкапсуляции
@mik_zd
@mik_zd 3 жыл бұрын
Квадрат это прямоугольник с ограничением соотношения сторон - ещё объект/класс. Изменение это ещё объект/класс который с учётом ограничения
@user-dy4nj1cd2d
@user-dy4nj1cd2d 3 жыл бұрын
Принцип Лисков это, на мой взгляд, единственный принцип из солида, который никогда нельзя нарушать. Если для мелких или специфичных скриптов на остальные принципы ещё можно закрыть глаза, тот тут прям ничего хорошего от нарушения не бывает никогда.
@0imax
@0imax 3 жыл бұрын
Есть редкие случаи, когда это нарушение сделано осознанно для универсальности интерфейса, и это нарушение настолько очевидное, что сразу понятно, как делать НЕ надо :)
@Boortwint
@Boortwint 3 жыл бұрын
Ну да. Тот же принцип единой ответственности можно смело нарушать, если изменение одной ответственности в классе не требует изменения другой ответственности. А попытки соблюдать этот принцип в одном классе порой нарушают его в другом. Да ещё и в добавок могут параллельно добавить проблем с принципом открытости/закрытости других классов.
@user-bq7co7fv2p
@user-bq7co7fv2p 3 жыл бұрын
Проблема в том что ты говоришь что квадрат это частый случай прямоуголика у которого h = w а сам берешь, еденичный случай использования hw и делаешь их равными. Нужно было задать сетеры чтобы синкать w и h
@user-bq7co7fv2p
@user-bq7co7fv2p 3 жыл бұрын
И потом фиксишь частный случай решения твоего наследования спомощью имутабельности. Ну вцелом норм. А что насчёт билдера. Так ты урезал класс и хочешь чтобы он работал так же как и родитель. В данном случае ты наследовался не для полиморфизма а для переиспользования кода. Для такого полиморфизма как у тебя необходимо чтобы были у всех те методы что используются после инстанцирования, для этого достаточно унаследоваться, и так как ты ещё взял на себя передачу параметров, необходимо чтобы их было одинаковое количества.
@user-bq7co7fv2p
@user-bq7co7fv2p 3 жыл бұрын
Мне кажется вывод неправильный. Наследовался можно. Нельзя использовать полиморфизм
@user-bq7co7fv2p
@user-bq7co7fv2p 3 жыл бұрын
А можешь окнуть или сказать что я даун) что нибудь)
@VladykaVladykov
@VladykaVladykov 3 жыл бұрын
Наследование прямоугольника от квадрата решает проблему?
@davyzaebali
@davyzaebali 3 жыл бұрын
нет
@DonEstorsky
@DonEstorsky 3 жыл бұрын
Так это прямоугольник является частным случаем квадрата, но с разными сторонами? ;)
@0imax
@0imax 3 жыл бұрын
Скорее квадрат - это такое состояние прямоугольника, когда w == h :) Хуже, когда от объекта нужно _поведение_ квадрата, т.е. при изменении одной стороны менялась бы и вторая.
@DonEstorsky
@DonEstorsky 3 жыл бұрын
@@0imax это мы привыкли так считать, что квадрат исключение или состояние прямоугольника, а может прямоугольник -- это искажение квадрата? С кругом мы считаем основной фигурой именно круг! Эллипсы же привыкли считать искажениями круга. Круг правильная фигура, а не частный случай эллипса. Всё зависит от восприятия.
@0imax
@0imax 3 жыл бұрын
@@DonEstorsky Это да. Восприятие многое решает. Сравнить хотя бы парадигмы ООП и ФП :)
@Mike-hp3fh
@Mike-hp3fh 3 жыл бұрын
Зачем использовать ООП, если с ним столько проблем?
@miptkol
@miptkol 3 жыл бұрын
Соер, здесь нету нарушения, так как принцип Лисков говорит о том, что если программа (корректно) использует экземпляры "подтипа", то замена этих экземпляров на "надтип" не должна вызывать проблем. в данном случае ты перевернул принцип с ног на голову и решил, что можешь менять надтип на подтип без получения сразу в фейс, что является нарушением предметной области и причиной копать яму где-то в лесу, а не рассказывать за солид.
@S0ERDEVS
@S0ERDEVS 3 жыл бұрын
Прочитай хотя бы Вики, что-ли: В последующей статье[2] Лисков кратко сформулировала свой принцип следующим образом: Пусть q(x) является свойством, верным относительно объектов x некоторого типа T. Тогда q(y) также должно быть верным для объектов y типа S, где S является подтипом типа T. Роберт С. Мартин определил[3] этот принцип так: Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом.
@miptkol
@miptkol 2 жыл бұрын
@@S0ERDEVS 1. Конструктор класса не является "свойством" экземпляра класса. Конструктор подтипа не обязан принимать те-же параметры, что и конструктор надтипа ни в одной из обозримых реальностей. Он обязан только создавать экземпляры подтипа при передаче !корректного! набора параметров. 2. В языках с богатым синтаксисом и метаданными, перечень допустимых для определённого метода исключительных ситуаций также является частью сигнатуры, а, значит, и интерфейса. Подтипы, действительно имеют право только сокращать этот перечень (не имеют права расширять). Но JS - не один из этих языков. Для любого действия может быть сформирована исключительная ситуация, которая может быть чем угодно. И это проблема пользователя, что он ее не обработал. 3. Если бы квадрат мог иметь стороны разного размера, то это уже был бы не квадрат (см. базовый курс планиметрии) - это тривиальная ошибка, связанная не спринципом Лисков, а с нарушением предметной области. 4. Использовать википедию вместо первоисточника - это признак высшей степени некомпетентности. (Тем более, что в ней даже ссылки на источник указаны) Википедия - средство ликбеза, а не источник истины.
@cyrilanisimov
@cyrilanisimov 3 жыл бұрын
Если фарисеи дожили до наших дней, то они стали программистами. P.S. а если рассмотреть квадрат не как отдельный класс, а как частный случай прямоугольника с методом bool isSquare()? И конструктор перегрузить (int a, int b = -1) { if(b == -1) { b = a; isSquare = true; }} P.S.S. Сначала пишу комментарии, потом смотрю видео))
@sergeydevyatov
@sergeydevyatov 3 жыл бұрын
Суть проблемы не ясна. Если Square перестанет наследоваться от Rectangle, код справа не начнет работать как-то иначе, а помещать в builder конструктор Square останется возможным. Стало быть проблема в разработчике, который помещает в этот билдер квадрат и удивляется, что площадь неверно посчитана
@0imax
@0imax 3 жыл бұрын
Проблема в том, что разработчик наследует квадрат от прямоугольника, тем самым не расширяя, а сужая интерфейс этого класса, что делает невозможным его использование в контексте, предназначенном для прямоугольника.
@AndrewLewman
@AndrewLewman 3 жыл бұрын
"код справа не начнет работать как-то иначе". Начнет, была условность что мы проверяем что аргумент наследуется или является классом Rect.
@CHERNOMORGAMES
@CHERNOMORGAMES 3 жыл бұрын
Как-то сразу резануло, что квадрат наследует от прямоугольника. Интуитивно, чувствовалось, что что-то не так. Наверняка у многих такое же ощущение возникло. Действительно, если прямоугольник будет наследовать от квадрата - проблемы не возникнет. Квадрат "проще" или "абстрактнее" прямоугольника. Если куб будет наследовать от гиперкуба: мы сразу "почувствуем", что что-то не так - здесь то же самое.
@vavilov2212
@vavilov2212 3 жыл бұрын
Аффтар жжот!
@alexandr-v
@alexandr-v 3 жыл бұрын
7:25 Не понял в чем тут ошибка. а сколько должно было получится, не 25? Сначала говоришь, мы хотим создавать прямоугольники, а потом создаешь квадрат, спрашивается, зачем? Только что же хотел только прямоугольники создавать.
@user-ey5xw2nx9s
@user-ey5xw2nx9s 3 жыл бұрын
Так квадрат - наследник прямоугольника
@jokeer3148
@jokeer3148 3 жыл бұрын
Как будто современные тренды ютуба, только на реалии IT блогера.
@vovasokolov768
@vovasokolov768 3 жыл бұрын
суть проста: не наследуйте классы и делов то!
@0imax
@0imax 3 жыл бұрын
Суть проста: не используйте ООП, а лучше вообще не пишите код :)
@nepBoHax
@nepBoHax 3 жыл бұрын
Кому в голову придет создавать квадрат, когда уже есть прямоугольник. Незачем плодить лишнюю сущность, квадрат и прямоугольник это одно и то же, ну передай ты два параметра вместо одного, это так сложно ?
@dann1kid
@dann1kid 3 жыл бұрын
Шрифт с засечками трудноразличим на этом фоне
@nanouasyn
@nanouasyn 3 жыл бұрын
либо автор не понимает, что такое утиная типизация, либо в js всё настолько шиворот навыворот, что и утиной типизацией называется не то, что у всех. утиная типизация - это когда мы устанавливаем факт реализации интерфейса по факту наличия у объекта необходимых для реализации этого интерфейса методов. скажем, если мы считаем, что прямоугольник - это любой объект, реализующий метод area, и для того, чтобы понять, прямоугольник ли перед нами, узнаём, определяет ли данный объект метод area, то мы используем утиную типизацию. однако, если мы проверяем, является ли объект экземпляром класса Rectangle или его дочернего класса, то это уже обычная типизация.
@user-uh8vk7fc9x
@user-uh8vk7fc9x 3 жыл бұрын
А где собственно нарушение LSP? Конструктор же не является частью интерфейса.
@0imax
@0imax 3 жыл бұрын
Ну был бы не конструктор, а метод ресайз, к примеру. Суть в том, что наследование подразумевает расширение функционала базового класса, но квадрат этот функционал сужает, а не расширяет.
@user-uh8vk7fc9x
@user-uh8vk7fc9x 3 жыл бұрын
​@@0imax суть в том, что видео называется "Нарушаем принцип подстановки Лисков и смотрим, что получилось", но никакого нарушения на видео нет. Есть мутирование объекта и есть плохой дизайн "билдера". Кстати, если у прямоугольника будет метод resize(width, height): Rectangle, то у квадрата этот метод может просто возвращать прямоугольник, если переданные стороны разные, и квадрат, если стороны равны - и это по прежнему не будет нарушением LSP.
@0imax
@0imax 3 жыл бұрын
@@user-uh8vk7fc9x ну вот и начинаются финты ушами - вместо того, чтобы поменять две цифры, приходится создавать новый объект. Опять же, как быть с методами setWidth и setHeight ?? Если квадрат при изменении одной стороны будет менять и вторую, дабы остаться квадратом - может получиться ситуация, когда мы насоздавали прямоугольников, но один из них получился квадратом случайно, и далее на смену ширины реагирует не так, как мы ожидали. Если же квадрат при изменении одной из его сторон будет "превращаться" в прямоугольник ( как с предложенным выше ресайзом ), то вообще не понятно, нафига нужен класс Квадрат, если ведёт себя он точно так же, как его родитель :)
@S0ERDEVS
@S0ERDEVS 3 жыл бұрын
@@user-uh8vk7fc9x попробуй сделать три интерфейса (в контексте условий видео) Shape, Rectangle, Square, тогда поймешь о чем речь в видео. Там не про реализацию конструктора, а именно про реализацию интерфейса через конструктор. Что касается примера про resize, то это нифига не "просто", так как позволяет обходить проверку типов. И тут надо долго и вдумчиво читать про инвариантность, ковариантность и контрвариантность. В двух словах не объясню.
@Mike-hp3fh
@Mike-hp3fh 3 жыл бұрын
В этих примерах конструктор является частью интерфейса, т.к. в одну из функций передается класс.
@Alexander-lp2qy
@Alexander-lp2qy 3 жыл бұрын
Выводы: Оставить только Rectangular. Не использовать наследование. Использовать классы как структуры данных, а логику запихнуть в функции.
@0imax
@0imax 3 жыл бұрын
Достаточно ограничиться классом Rectangle. Выносить функции наружу нет смысла.
@dmproger
@dmproger 3 жыл бұрын
гут. но хорош маяться, переходите на Ruby class RectangleOrSquare attr_accessor :width def initialize(width, height = nil) @width = width @height = height end def area width * height end def height @height || @width end def height=(value) @height = value if @height end end
@KopoLPedov
@KopoLPedov 3 жыл бұрын
def width @width || @height end def height @height || @width end ооочень интересно, продолжайте(нет)
@dmproger
@dmproger 3 жыл бұрын
@@KopoLPedov А продолжать и не нужно, все готово. width даж не требуется патчить (обновил), только height. И никакого аccidental complexity с бесконечными паттернами.
@PowWowVideo
@PowWowVideo 3 жыл бұрын
@@dmproger добавь еше в название...OrCircleOrOval и поиграйся с двумя радиусами вместо или вместе с w и h.
@donpedro2125
@donpedro2125 Ай бұрын
Выключил как только услышал про прямоугольник и квадрат. Выделение корневой абстракции неверно.
[柴犬ASMR]曼玉Manyu&小白Bai 毛发护理Spa asmr
01:00
是曼玉不是鳗鱼
Рет қаралды 51 МЛН
🍟Best French Fries Homemade #cooking #shorts
00:42
BANKII
Рет қаралды 42 МЛН
WHY DOES SHE HAVE A REWARD? #youtubecreatorawards
00:41
Levsob
Рет қаралды 40 МЛН
Принцип подстановки Барбары Лисков - SOLID в деталях
16:04
Уголок сельского джависта
Рет қаралды 3,3 М.
JWT авторизация. Основы JWT - механизма.
6:45
Хочу вАйти
Рет қаралды 2,2 М.
Принцип подстановки Лисков. SOLID для React
15:26
Михаил Непомнящий
Рет қаралды 11 М.
Инвариант в программировании
18:54
[柴犬ASMR]曼玉Manyu&小白Bai 毛发护理Spa asmr
01:00
是曼玉不是鳗鱼
Рет қаралды 51 МЛН