Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.60.166] |
|
Страницы: (8) « Первая ... 3 4 [5] 6 7 ... Последняя » все ( Перейти к последнему сообщению ) |
Сообщ.
#61
,
|
|
|
Нет, все ж привыкли строить иерархии наследования. Хотя, HTML, например, близок: только тэги и их атрибуты, никакого наследования. Нечаяно можно и метод в базовом классе поменять и поломать всё к чертям. Синглтон — антипаттерн уже давно. Цитата Wound @ вот есть у меня класс Checkbox : public Button, у класса checkbox я реализовал функцию отрисовки, все. Теперь у меня есть checkbox, который имеет все те же методы что и кнопка, но выглядит по другому. Вот и по рукам тебе за такой класс надавать. CheckBox — это не Button. CheckBox = Pane { check ; label } Какие те же? Зачем CheckBox'у методы Button'а? Ты про click/keypress/etc? Так это не методы Button'а. Ещё раз посмотри на HTML: на любой элемент можно повесить onclick-обработчик, например. И кого же ты процитировал? Добавлено В том что нет ISP. Вместо interface Vehicle { } interface WheelVehicle : IVehicle { } interface FlyingVehicle : IVehicle { } Хотя бы interface Vehicle { } interface Ground { } interface Flying { } Почувствуй разницу. P.S. Как же раздражает ииотская шарповая нотация interface I<name> |
Сообщ.
#62
,
|
|
|
Цитата korvin @ Нет, все ж привыкли строить иерархии наследования. Хотя, HTML, например, близок: только тэги и их атрибуты, никакого наследования. HTML - это язык гипертекстовой разметки, если чего. Как ты его увязал с ЯП, не понимаю. Цитата korvin @ Нечаяно можно и метод в базовом классе поменять и поломать всё к чертям. С глобальной переменной это сделать проще. Цитата korvin @ Синглтон — антипаттерн уже давно. Незнаю, вот у меня перед глазами лежит книга "Приемы Объектно-Ориентированного проектирования. Паттерны проектирования" за авторством: Э.Гамма, Р.Хелм, Р.Джонсон, Д.Влиссидес. Синглтон описывается на странице 130. Обозначен как паттерн проектирования Цитата korvin @ Вот и по рукам тебе за такой класс надавать. CheckBox — это не Button. С чего вдруг? Между прочим, в некоторых фреймворках, чекбоксу можно сделать стиль PressedButton, т.е. меняется только отрисовка - вжатая/отжатая кнопка, либо галочка - есть/нет. В остальном него точно такие же методы как и у кнопки, ну разве что вводятся дополнительные свойства - Checked/Unchecked Цитата korvin @ CheckBox = Pane { check ; label } Примитивный пример. Я уже давал на этот счет пояснения тут: Инкапсуляция vs Агрегирование (сообщение #3813134) И если label понятно что это такое, то что такое check - остается только догадываться. Никогда не встречал такого класса Даже в HTML он идет как checkbox Цитата korvin @ Какие те же? Зачем CheckBox'у методы Button'а? Ты про click/keypress/etc? Так это не методы Button'а. Ещё раз посмотри на HTML: на любой элемент можно повесить onclick-обработчик, например. Да причем тут HTML то я никак не пойму? Ты сравниваешь разметку с языком программирования. Цитата korvin @ В том что нет ISP. Что такое ISP? Я там написал ниже, что не корректно пример понял, так как изначально комментировал его с телефона, а там у меня не все раскрылось. Цитата korvin @ Почувствуй разницу. И в чем разница? В других именах? Если сущность одна, и у тебя есть такие же, но более конкретизированные, почему не унаследовать? В любом случае у тебя получится дублирование методов в разных интерфейсах. Добавлено Цитата korvin @ Как же раздражает ииотская шарповая нотация А меня бесят маленькие буквы в методах в Java. Придумали какую то хрень, не пойми зачем, и приходится потом с этим извращаться. Добавлено Цитата Qraizer @ Хорошо, когда язык поддерживает агрегацию искаропки, да? Вот и ответь теперь, что тебе мешает сделать так же при наследовании реализаций. Гм, ну да... хорошо, когда язык поддерживает множественное наследование реализаций искаропки. Я стараюсь избегать множественного наследования. Уж очень высока вероятность там поиметь проблемы. Не всегда можно что то учесть. Цитата Qraizer @ Если сильная связь подразумевается, как в лице гуёвых иерархий, например, когда кнопка она же окно, то наследование не привнесёт дополнительного дисбаланса в архитектуру. Переделывай базовый класс окна на здоровье, кнопки автоматом подхватят все модификации, и разве не это ожидается в итоге? Ну так я не против этого. Просто почитал про это. Народ везде пишет что фигня все это, типа больше проблем, чем пользы. Но лично вот я не понимаю, как тогда ГУИ писать. Вон korvin Знает, у него все просто Берешь и делаешь как в HTML. |
Сообщ.
#63
,
|
|
|
Цитата Wound @ HTML - это язык гипертекстовой разметки, если чего. Как ты его увязал с ЯП, не понимаю. На этом языке разметки уже давно клепают UI. Ну да, +JS для поведения. При чём тут ЯП, когда речь шла о UI, не понятно. Цитата Wound @ С глобальной переменной это сделать проще. Конечно. Как и многое другое. Цитата Wound @ Незнаю, вот у меня перед глазами лежит книга "Приемы Объектно-Ориентированного проектирования. Паттерны проектирования" за авторством: Э.Гамма, Р.Хелм, Р.Джонсон, Д.Влиссидес. Синглтон описывается на странице 130. Обозначен как паттерн проектирования Библию ещё положи. Тебя не смущает, что книга 1994-го года, а на дворе 2019-й? И что это не Конституция РФ и тем более не учебник по алгебре, например? https://www.michaelsafyan.com/tech/design/patterns/singleton Цитата Wound @ Между прочим, в некоторых фреймворках, чекбоксу можно сделать стиль PressedButton, т.е. меняется только отрисовка - вжатая/отжатая кнопка, либо галочка - есть/нет. Обычно это ToggleButton, который к чекбоксам никакого отношения не имеет, кроме как обеспечения такой же смысловой нагрузки: On/Off (Checked/Unchecked, и т.п.) — представления булевого свойства. Ты стиль наследуешь или поведение? Ну да, в этих ваших фреймворках часто представление и семантика слиты в один класс. Каша, да и только. Потом наследуете мух от котлет и наоборот. Цитата Wound @ ну разве что вводятся дополнительные свойства - Checked/Unchecked «Дополнительные»? Лол, это и есть вся его смысловая нагрузка, определяющая суть чекбокса как элемента интерфейса. Цитата Wound @ то что такое check - остается только догадываться. Никогда не встречал такого класса Это то маленькое окошко, где ставится галочка. Цитата Wound @ Даже в HTML он идет как checkbox Потому что там checkbox — готовый примитив, который, кстати, не наследуется от button. Цитата Wound @ Да причем тут HTML то я никак не пойму? Ты сравниваешь разметку с языком программирования. При чём тут язык программирования? Мы о UI фреймворках/тулкитах говорим. HTML+CSS+JS — это UI-тулкит. Цитата Wound @ Что такое ISP? Interface Segregation Principle. Цитата Wound @ И в чем разница? В других именах? Если сущность одна, и у тебя есть такие же, но более конкретизированные, почему не унаследовать? Flying может быть не только Vehicle. Ты внимательней прочитай. Цитата Wound @ А меня бесят маленькие буквы в методах в Java. Придумали какую то хрень, не пойми зачем, и приходится потом с этим извращаться. А маленькие буквы в именах полей в C# тебя не бесят? Нахера вы захламляете имена идиотскими префиксами? У классов префикс C пишете? А у абстарктных классов — AC? А если публичный, нужно P добавлять? А S к sealed? |
Сообщ.
#64
,
|
|
|
Написал незафэйленный сценарий: #include <iostream> using namespace std; struct IBaseInterface { virtual void madeMeCool() = 0; }; struct ICoolInterface : IBaseInterface { /* тут что-то оригинальное своё */ virtual void madeMeCool() override { cout << "ICoolInterface сделал cool\n"; } }; struct ICoolerInterface: IBaseInterface { /* тут что-то совсем другое своё */ virtual void madeMeCool() override { cout << "ICoolerInterface тоже сделал cool\n"; } }; struct CCoolImpl: virtual ICoolInterface, virtual ICoolerInterface { /* всё сделано по правилам, и ничего, как говорится, не предвещало */ virtual void madeMeCool() override { ICoolInterface::madeMeCool(); ICoolerInterface::madeMeCool(); cout << "CCoolImpl сделал cool вдогоночку\n"; } }; int main() { CCoolImpl cool; cool.madeMeCool(); return 0; } И как его зафэйлить? Приведи пример, плс. |
Сообщ.
#65
,
|
|
|
Скрытый текст Цитата korvin @ Как же раздражает ииотская шарповая нотация Она как минимум дельфийская |
Сообщ.
#66
,
|
|
|
Цитата korvin @ На этом языке разметки уже давно клепают UI. Ну да, +JS для поведения. При чём тут ЯП, когда речь шла о UI, не понятно. Не только на этом языке разметки клепают UI, это во первых. Потому как в практически любой ОС, есть окна/диалоги и т.п. которые работают не через HTML, а ты говоришь судя по всему исключительно про Web, только причем он тут? Цитата korvin @ Тебя не смущает, что книга 1994-го года, а на дворе 2019-й? И что это не Конституция РФ и тем более не учебник по алгебре, например? https://www.michaelsafyan.com/tech/design/patterns/singleton Нет не смущает Может быть и SOLID тогда устарел и его нужно в топку выкинуть? А то ему тоже уже под 20 лет. Цитата korvin @ Обычно это ToggleButton, который к чекбоксам никакого отношения не имеет, кроме как обеспечения такой же смысловой нагрузки: On/Off (Checked/Unchecked, и т.п.) — представления булевого свойства. Ты стиль наследуешь или поведение? Ну да, в этих ваших фреймворках часто представление и семантика слиты в один класс. Каша, да и только. Потом наследуете мух от котлет и наоборот. Ну давай посмотрим как это в HTML описывается: https://www.w3schools.com/tags/att_input_type_checkbox.asp HTML <input type="checkbox"> input? А чего не checkbox ? Цитата korvin @ «Дополнительные»? Лол, это и есть вся его смысловая нагрузка, определяющая суть чекбокса как элемента интерфейса. Я с тобой не соглашусь, потому как помимо Checked/Unchecked - ему хорошо бы иметь все те же методы, что имеет кнопка. Нажать/Отпустить/Отрисовка/MouseMove и т.д. Зачем писать повторно все тоже самое, что ты будешь писать для кнопки какой нибудь? Дублирование кода на лицо получается. Цитата korvin @ При чём тут язык программирования? Мы о UI фреймворках/тулкитах говорим. HTML+CSS+JS — это UI-тулкит. Причем тут HTML+CSS+JS, мы о Веб не говорим(я так точно о нем не говорил), а ты приводишь Веб. Зачем рассматривать Веб, если речь идет о ГУИ фреймворках языков программирования? Цитата korvin @ Interface Segregation Principle. Если ты имел ввиду те 10 интерфейсов, то я уже писал что там херня написана. А если ты имеешь ввиду три первых - то в каком месте там что нарушается? Этот принцип нарушится тогда, когда у тебя классы будут вынуждены реализовывать методы интерфейсов, который реализовывать не должны. А если ты самые общие методы вынесешь в базовый интерфейс, а те два дополнишь своими, то этот принцип нарушаться не будет. Цитата korvin @ Flying может быть не только Vehicle. Ты внимательней прочитай. В реальной жизни? Очень может быть. Но обычно проектируют согласно ТЗ. Если ты пишешь какую то программу для управления исключительно транспортными средствами, то например птиц - можно не учитывать. Цитата korvin @ А маленькие буквы в именах полей в C# тебя не бесят? Это как тут что ле: http://hg.openjdk.java.net/jdk8/jdk8/jdk/f.../ArrayList.java ? private static final long serialVersionUID = 8683452581122892189L; ... /** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size; Цитата korvin @ Нахера вы захламляете имена идиотскими префиксами? У классов префикс C пишете? По поводу префиксов - необязательно так делать. Я думаю так делают в основном С++сники, я вот не помню какую книгу по шарпам читал, так там автор говорил что поля могут совпадать с входными значениями, и никакого криминала в этом нет, более того, даже принято вызывать поля через this. Ну что то типа там: public class SomeClass { private int speed; SomeClass(int speed) { this.speed = speed; } } На сколько я знаю С++сники не любят писать this, поэтому видимо придумали название полей с подчеркивания писать. Ну типа чтоб не писать длинный this. и при этом чтоб было понятно что это поле класса, а не какая то левая переменная в методе или из параметров. По поводу префикса C у класса - это тоже дело рук С++сников, ЕМНИП, а пошло это еще из классов MFC, и венгерской нотации. Цитата korvin @ А у абстарктных классов — AC? А если публичный, нужно P добавлять? А S к sealed? Ну это ты уже сам придумал. |
Сообщ.
#67
,
|
|
|
Цитата Wound @ Ну вот везде пишут - что такого, что ты предлагаешь надо избегать. Если будут переделки в базовых класах - то это повлечет кучу проблем. Лично я не люблю делать такие большие иерархии наследования. Слишком запутанно получается, слишком большая связанность классов. На лицо нарушение принципов SOLID. Ну вот возьмем цепочку классов: interface IEvent { IEventType EventType {get;} string Textoverlay {get;} string AlarmMessage {get;} IDatabaseDto DatabaseDto {get;} ну и еще пара пропертей } class abstract ShoeEvent : IEvent { } class abstract GameEvent : ShoeEvent { } class abstract CardDrawEvent : GameEvent { Rank Rank { get; } Suit Suit { get; } ... string Textoverlay {get { реализация } } string AlarmMessage {get { реализация } } IDatabaseDto DatabaseDto {get { реализация } } } class DiscardCardEvent : CardDrawEvent { } class PlayerCardEvent : CardDrawEvent { } class BankerCardEvent : CardDrawEvent { } как тут можно заменить наследование агрегацией? Ну в данном примере (в том виде, как показано тут) ShoeEvent и GameEvent можно заменить интерфейсами. А вместо DiscardCardEvent, PlayerCardEvent и BankerCardEvent можно сделать enum. Но ведь это не агрегация Цитата Wound @ Я не знаю всей специфики твоей задачи, но обычно всякие ивенты решаются с помощью шаблона Посетитель(Visitor) или Наблюдатель(Observer). Возможно тебе нужно пересмотреть дизайн. Слишком много у тебя наследования. ИМХО. Пересмотреть дизайн - это написать все с нуля Тут коду больше 10 лет и сейчас сделан один класс, который отвечает за все. Недостатком такой структуры является то, что Textoverlay, AlarmMessage и DatabaseDto живут "вне" эвента в результате для обработки всего этого добра пишется куча ненужного кода. |
Сообщ.
#68
,
|
|
|
Цитата Fester @ как тут можно заменить наследование агрегацией? Ну в данном примере (в том виде, как показано тут) ShoeEvent и GameEvent можно заменить интерфейсами. А вместо DiscardCardEvent, PlayerCardEvent и BankerCardEvent можно сделать enum. Но ведь это не агрегация Очень просто, то от чего ты наследуешься - делаешь полем класса + в конструктор параметр прокидываешь. Я не знаю специфики твоей задачи, но у тебя слишком много наследования в твоей иерархии классов. Может быть проще какой нибудь Visitor прикрутить или Наблюдатель там? Почему ты не хочешь пресмотреть свою задачу и юзнуть шаблоны проектирования, вместо бездумного наследования. У тебя потом по ходу работы, всплывет какая то хрень, и будешь ты костыли лепить к этой иерархии, и писать еще больше наследования. Цитата Fester @ Пересмотреть дизайн - это написать все с нуля Тут коду больше 10 лет и сейчас сделан один класс, который отвечает за все. Недостатком такой структуры является то, что Textoverlay, AlarmMessage и DatabaseDto живут "вне" эвента в результате для обработки всего этого добра пишется куча ненужного кода. Ну вот видишь - вот и вылезла проблема. Рефакторингу не подлежит, т.к. вот такое наследование в него заложено. А была бы агрегация, то отрефакторилось бы легко. |
Сообщ.
#69
,
|
|
|
И какое это имеет отношение к обсуждаемой теме? И D не уникален в этом плане. Ruby и PHP тоже умеют обрабатывать вызовы несуществующих методов и при желании можно проксировать их в агрегируемый объект.
Цитата Wound @ Ну, по крайней мере на этом форуме, полагаю, никто так не считает. Ну речь зашла о том, что наследование классов - это всегда плохо. Лучше ее избегать всегда и везде, где это возможно. И только если уж совсем приспичит, то можно оставить, и то с нацелом на то, чтоб потом переписать. Цитата Wound @ Нет, классические C++сники так не делают. Посмотри boost и стандартную либу - никаких префиксов.По поводу префиксов - необязательно так делать. Я думаю так делают в основном С++сники, Префиксы это другая болезнь - Microsoft Головного Мозга. |
Сообщ.
#70
,
|
|
|
Цитата Wound @ Очень просто, то от чего ты наследуешься - делаешь полем класса + в конструктор параметр прокидываешь. Но рано или поздно мне надо будет отправить, скажем, Textoverlay. Т.е. конечный класс должен имплементировать этот интерфейс чтобы я "разматывать" цепочку агрегаций. Цитата Wound @ Может быть проще какой нибудь Visitor прикрутить или Наблюдатель там? Может и проще, но для этого надо все переписать. Сейчас сделано в лоб - пришел евент -> добавили эвент в игру -> проверили нарушаются ли правила (их штук 10), если нарушаются, то создали соответствующий эвент -> отправили все (начальные и созданные) на отправку в подсистемы (сохранение в БД, отправка Textoverlay, сообщение о нарушениях итд). Т.е. наверное это ближе к наблюдателю, но переделывать существующий код никто не даст. Цитата Wound @ Ну вот видишь - вот и вылезла проблема. Рефакторингу не подлежит, т.к. вот такое наследование в него заложено. А была бы агрегация, то отрефакторилось бы легко. Рефакторингу не подлежит, т.к. там сейчас вообще нет никакого дизайна Все делается в лоб. Грубо говоря, есть класс, который отвечает за отправку данных на все подсистемы. Так вот в этом классе есть поле Textoverlay, которое заполняется по мере обработки сообщения, потом, когда вызывается вункция "отправить все на подсистемы", берется поле Textoverlay и отправляется куда надо и сколько надо раз. После чего содерживое поля обнуляется |
Сообщ.
#71
,
|
|
|
Цитата Fester @ Но рано или поздно мне надо будет отправить, скажем, Textoverlay. Т.е. конечный класс должен имплементировать этот интерфейс чтобы я "разматывать" цепочку агрегаций. Ну так и в чем проблема, не пойму? У тебя все классы, которые друг от друга наследуются, теперь будут наследоваться от IEvent, и плюс еще от какого то, если тебе расширить функционал нужно. А передавать в них через конструктор ты будешь то, от чего сейчас наследуешься. В итоге все классы у тебя имплементируют твой интерфейс. Цитата Fester @ Может и проще, но для этого надо все переписать. Сейчас сделано в лоб - пришел евент -> добавили эвент в игру -> проверили нарушаются ли правила (их штук 10), если нарушаются, то создали соответствующий эвент -> отправили все (начальные и созданные) на отправку в подсистемы (сохранение в БД, отправка Textoverlay, сообщение о нарушениях итд). Т.е. наверное это ближе к наблюдателю, но переделывать существующий код никто не даст. Ну тут можно только посочувствовать. |
Сообщ.
#72
,
|
|
|
Никаких противоречий! Интерфейсы определяют "поведение" (или "способность поведения"), а праперти - "состояние". Цвет - это состояние. Конкретная конфигурация - это состояние. Вот тут я полностью согласен с Килей, он как-то пару листов назад расписал условия, когда нужно руководствоваться здравым смыслом и опираться на отношения "является" или "имеет". По факту: 1) Наследование используется, если имеем отношение "является" 2) Агрегация или композиция используются, если имеем отношение "имеет" При агрегации что-то конструируем во-вне класса и сконструированное передаем в виде параметра конструктору. При композиции конструируем нужное с самом классе. Ну как-то так вроде, если я все правильно понял. |
Сообщ.
#73
,
|
|
|
Цитата JoeUser @ Вот тут я полностью согласен с Килей, он как-то пару листов назад расписал условия, когда нужно руководствоваться здравым смыслом и опираться на отношения "является" или "имеет". По факту: 1) Наследование используется, если имеем отношение "является" 2) Агрегация или композиция используются, если имеем отношение "имеет" При агрегации что-то конструируем во-вне класса и сконструированное передаем в виде параметра конструктору. При композиции конструируем нужное с самом классе. Ну как-то так вроде, если я все правильно понял. Ну тут еще есть всякие оговорки, типа если у тебя отношение "является", но при этом дочерний класс замещает методы базового, или вообще не использует их, то такое наследование - плохое, ибо чревато проблемами. И тут надо уже вводить агрегирование, либо пересматривать дизайн. В идеале наследование подходит там, где у тебя отношения "is a" плюс ко всему дочерний класс будет исключительно добавлять новую функциональность и вообще не будет замещать методы базового класса. Называется это вроде Принцип подстановки Барбары Лисков |
Сообщ.
#74
,
|
|
|
Цитата Fester @ Грубо говоря, есть класс, который отвечает за отправку данных на все подсистемы. Так вот в этом классе есть поле Textoverlay, которое заполняется по мере обработки сообщения, потом, когда вызывается вункция "отправить все на подсистемы", берется поле Textoverlay и отправляется куда надо и сколько надо раз. После чего содерживое поля обнуляется |
Сообщ.
#75
,
|
|
|
Цитата Wound @ Ну тут еще есть всякие оговорки Согласен. Как раз вчера с чьей-то подачи про SOLID читал. |