Ответы пользователя по тегу ООП
  • Правильно ли я использую абстрактный класс Animal?

    @red-barbarian
    Сам вопрос провоцирует: Да! Не правильно! )
    Но если серьезно.
    Не стройте систему от абстрактного к конкретному. Так хорошо в учебнике. в реальности это порождает много ненужных слоем и классов. Делайте это от конкретного к абстрактному. Т.е. есть два класса которые вы применяете. у них есть общее. Вынесите общее в абстрактный класс. Т.е. исходим с низу к абстрактному.

    Второй момент. Связана с полиморфизмом. Это придумать интерфейс а затем его реализацию. Но это другая песня.
    Ответ написан
  • Как вы проектируете классы в ООП и их взаимодействие?

    @red-barbarian
    Чаще всего, в той сфере где вы работаете уже есть уже принятые архитектурные решения. Бест практики. Придерживаться их - избавиться от многих проблем в будущем.
    1. обще принятое - значит не будет сюрпризов для программистов которые сопровождают код
    2. не нужно тратить время для изобретения велосипеда.
    3. название переменных, пакетов и функций говорят о предназначении в контексте архитектуре.
    4. помощь сообщества.
    Теперь если программист решил придерживаться общепринятого (хорошего) решения, у него не будет вопросов как организовать ключевые классы. остаются 20% классов для особых случаев (упростить, разбить большие классы и проч) Желательно эти случае решать также "общепринято". Попробовать шаблоны, если они подходят. Типовые решения и типовые названия.
    Если нужна для проектирования даже бумажка - это значит есть сложность. Это уже плохо. Эта сложность должна быть очень обоснована. Постараться сделать все максимально просто - это искусство и в этом творчество.)
    Ответ написан
    Комментировать
  • Что учить первым OOP или java?

    @red-barbarian
    Это практически две разные сферы.
    В хорошей книге всегда будет java + основы ООП.
    Но проблема в том что основы не меняют обычное мышление новичка на объектное.
    Т.е. по привычке все пишется и понимается с точки зрения процедурной парадигмы. А нужно старается понимать с точки зрения где сложная система это набор объектов. Поэтому хорошо бы взять что то простое и паралельно изучать объектно ориентированное проектирование.

    Также лучше сразу читать основы чистого кода. Что бы потом не переучиваться и не ломать себя.
    Три вещи параллельно.
    Хотя многое зависит и от Вашего опыта.
    Ответ написан
    Комментировать
  • Как правильно вывести часть данных?

    @red-barbarian
    Танцуй от DI
    Т.е. нужно решить какие методы нужны от класса.
    Если выборка всех фирм, то что-нибудь типа getAll
    Если выборка по ид, то getById(id)
    и т.д.
    Исходить надо из интерфейса который требует клиент класса. А сам класс реализует его.
    Так ты сделаешь скрытым то, что не требуется клиенту и дашь себе возможность менять реализацию класса, без изменения его клиента.
    Реализацию класса старайся делать без повторений используя скрытые методы.
    Если в классе есть места которые будут часто изменяться, то выноси их в другие классы и делегируй им выполнение. SRP
    Ну и прочитай про остальные принципы SOLID. Что бы использовать их. Без фанатизма. Это очень поможет тебе делать понятный для себя и других код. Ну и тестируемый.
    Ответ написан
    Комментировать
  • Сколько замедляет ооп работа программы php?

    @red-barbarian
    Программисты тратят огромное количество времени, размышляя и беспокоясь о некритичных местах кода, и пытаются оптимизировать их, что исключительно негативно сказывается на последующей отладке и поддержке. Мы должны вообще забыть об оптимизации в, скажем, 97% случаев. Поспешная оптимизация является корнем всех зол. И, напротив, мы должны уделить все внимание оставшимся 3%.
    — Дональд Кнут
    Ответ написан
    Комментировать
  • Как лучше реализовать иерархию классов птицы и метод летать?

    @red-barbarian
    Посмотрите в сторону шаблона Стратегия.
    Летание это довольно динамическое свойство. Даже может меняться а процессе жизни объекта. Поэтому это свойство чаще всего полезнее выносить за объект. И присваивать полю "летание" некую реализацию из вне.
    Например
    Ласточка летает одним методом. Птенцы и курицы другим. И т. д.
    Наследование довольно жесткая связь. Ее стоит избегать. Если это возможно.
    Ответ написан
    Комментировать
  • Как использовать ооп на практике?

    @red-barbarian
    Ну прежде всего понять, что есть две (точнее больше) парадигмы. ОО и процедурная.
    Это типы мышления. Первая это разбивать систему на части, как на компоненты. И описывать связи между ними. Вторая - Описать структуру данных и функции на ними. И у них есть свои плюсы и минусы. (да. ООП это не волшебная пуля.)
    Второе. Применения ООП эффективно к достаточно сложной системе. Сложная в смысле, что твой мозг определит там много частей и много связей между ними. Например вывести на экран приветствие это вряд ли сложное.
    Третье. Понять , что дублирование это зло. Это не только копипаст, но делать дважды похожие классы компонентов с начала. Применять нужно наследование. В суперклассы переносить общее.
    Четвертое. Система должна быть гибкой. Если приходят новые требования, нужно легко их реализовывать. И реализовывать локально. Т.е. по мере поступления изменений, мы находим места которые часто изменяются и стараемся вынести их в отдельные классы. В итоге получаем, при новом изменении, мы меняем только этот класс ничего более не цепляя.
    Пятое. понять что между компонентами есть некий протокол взаимодействий. И для компонент важен именно он, а не реальный объект по ту сторону. Пример: розетка . не важно какая она в стене, в удлинителе, или от большой черной коробки, но в нее можно подключить утюг, компьютер, чайник и проч. Есть протокол - две дырки, напряжение 220 и достаточная мощь и этого достаточно. Это дает возможность менять компоненты не затрагивая остальные.
    Примерно так.
    По поводу принципов. любых. (ооп или солид) Обязательно нужно знать что они решают. Какую проблему. Это позволит не усердствовать. А применять в меру. оставляя код проще.
    ну и книги по анализу.
    Ответ написан
    Комментировать
  • Какой паттерн лучше использовать при необходимости реализации методов из разных классов?

    @red-barbarian
    не зная как так получилось)
    Возможно из-за перегруженного интерфейса. ( очень важно придерживаться тонких интерфейсов. например интерфейс M1 интерфейс M2)
    Но разрешить (возможно) так
    D реализует интерфейс, но делегирует выполнение M1 классу B, M2 классу C
    т.е. шаблон делегирование
    Ответ написан
    Комментировать
  • Является ли хорошей практикой делать интерфейсы даже тогда, когда класс не планируется заменять?

    @red-barbarian
    принцип инверсии - самый крутой принцип.
    разработка начинается с головы. Т.е. если у вас задача проектировать программу, то вы начинаете строить ее с самого главного - ее бизнес логики. Вы не будете знать какие сущности логика будет использовать. Это возникнет из процесса. Поэтому, все что бизнес-логике нужно вы определяете интерфейсами.
    В таком случае получится, разбиение логики и сущностей которые ее обслуживают.
    из-за того, что первая меняется быстро и часто (по разным причинам, даже не зависящих от девелопера) это разбиение очень полезно. Главное, можно отдать разработку обслуживания другим людям, мы не в курсе библиотек которые будут применяться (и можем менять из), мы легко можем тестировать свою логику.
    Примерно так.
    Интерфейсы хорошо применять на границах слоев программы. Это дает возможность тестирования и разбиения.
    Ответ написан
    Комментировать
  • Прикладное применение интерфейсов?

    @red-barbarian
    Первое: интерфейсы принадлежат не уровню реализации, а уровню использования.
    Что значит?
    У вас есть проект самолета.
    Есть транспортная компания перевозящая грузы.
    Есть пассажирская - соответственно перевозящая пассажиров.
    у транспортной есть некий шаблон под названием транспортное средство. Все что подпадает под этот шаблон может компанией использоваться.
    У пассажирской - все что подпадает под шаблон "средство перевозки пассажиров"
    Т.е. по большему счету им не важно что будет самолет или автобус.
    Вы хотите, что бы ваши самолеты использовались. Вам нужно реализовать интерфейс (шаблон использования) грузоперевозчик. Для одной компании. Для пассажирской вы можете реализовать шаблон пассажироперевозчик.
    Т.е. интерфейс это некая договоренность, способ использования. И он лежит не на уровне библиотеки (т.е. на уровне реализации класса), а на уровне более высокой логики. (транспортное средство)
    Интерфейс становиться неким шаблоном между двумя частями системы. Он достаточно стабилен. Из этого мы получаем разделение большой системы на две части. и соответственно мы можем разрабатывать раздельно эти части, не боясь что-то нарушить в другой части.
    По части использования. Интерфейсы очень широко применяются. Даже в небольших проектах. Они разбивают на части систему, что очень полезно для построения прозрачных моделей. Также это дает возможность работать нескольким людям над одним проектом (или одному. Над частями проекта)
    Это дает возможность Сосредотачиваться на логике проекта, оставляя реализация на "позже" - делая простые затычки для тестирования.
    В примере с животными. Есть зоопарк где животные. По большей части они работают с интерфейсом животные (кормят, ограждают и т.е.) И все что подпадает под интерфейс животное легко там содержится. Если им привезти новое животное, они его посадят в клетку, будут кормить и показывать детям. Т.е. Животное - это скорее договоренность, а не сущность. (для зоопарка)
    Ответ написан
    Комментировать
  • Разбить God class?

    @red-barbarian
    навскидку (не разбираясь с логикой класса)
    у тебя много методов зависят просто от $this->route
    их уже можно выделить в один класс.
    если есть аналогичные моменты от других переменных поступать также.
    Вообщем разбиение делается так: анализ структуры класса и выделение подсттруктур переменных + методов. Эти подструктуры будут внутренне сильно связаны. И слабо связаны между собой. Это будет намек, что можно выделять классы из текста.
    Пониманию структуры может помочь анализ ответственности год-класса.
    Как бы первое, что нужно сделать. Остальное станет ясным по мере разбиения.
    Ответ написан
    2 комментария
  • Зачем прописывать методы в Interface когда можно так же в классе?

    @red-barbarian
    Интерфейс это некий протокол, договоренность между частями системы. Т. К. Мы выносим эту договоренность отдельно, мы можем менять одну часть не боясь нарушить что-то в другой.
    Т. Е. В итоге из сложной системы мы сделали две боле простые подсистемы. Которые также могут использоваться и в других местах.
    Это наиболее важное применение интерфейса. Хотя не единственная его польза.
    Ответ написан
    1 комментарий
  • Правила хорошего тона protected или private?

    @red-barbarian
    Ну если подходить философски) , то класс это довольно самодостаточный кусок кода. Т.е. если что-то случилось, то ты идешь в этот класс и исправляешь или (дополняешь его - что не совсем правильно). т.е. функциональность лежит в одном месте (этакая модульность) и не размазана по коду. Все рады и поют пиво. Встает вопрос как разбить программу на такие классы. На помощь приходит принцип инверсиии зависимостей. Звучит страшно, но на деле это разработка сверху вниз. Т.е. пишешь ты работу со счетами. Понадобилось сохранять счета. Этокое хранилище. У него вырисовывается метод сохранитьсчет. Хорошо делам заглушку Хранилище, с методом сохранить. Затем по мере реализации логики, понадобился метод загрузитьсчет. вставляем в хранилище.
    т.е. у нас вырисовывается интерфейс класса Хранилище который требуется для логики. И метода этого интерфейса будут все public. и ничего лишнего.
    Отлично. приходит помощник, мы говорим "у меня нет время, но есть работа. нужно реализовать методы моего хранилища" Помощник берет за основу ваш интерфейс и реализовывает свою Impl. Методы интерфейса public, и остальные которые он выделил для своего удобства privat. Все рады и работа сменяется зависоном на toster.ru. но приходит начальник и говорит"wtf?!!!" ..;%:;№. "вы сделали реализацию на mysql, а у нас полклиентов работает на оракле!"
    Вы берете Impl, медитируете и понимаете, что можно в принципе переписать только часть класса для оракла, а часть оставить. но люди продвинутые и понимаете, что общий код можно выделить в базовый класс. Итак у вас вырисовывается Общий класс в котором есть public, private, protected. public и protected - могут быть абстрактными. Отлично. Вы реализовываете только часть которую нужно для оракла и все готово. Более того если нужно подключить MSSQL, вы легко это сделаете.
    Вот такая сказка. В ней намек - не плодите лишнего в интерфейсе. выделяйте то что нужно. Не делайте лишнего protected. только то что нужно переиспользовать потомками. Вы же не фреймворки пишите. Заранее не нужно впихивать ненужное.
    Ответ написан
    Комментировать
  • Что плохого в моем коде тестового задания на java?

    @red-barbarian
    Навскидку с телефона.
    Пользуйтесь интерфейсом когда нужно описать правила взаимодействия с объектом. Абстрактным классом когда можно выделить некие общие моменты из классов.
    Т. Е конденсатор это интерфейс. Как там храниться значение в цифрах это вопрос реализации. Хоть в текстовом поле. Но это может меняться и поэтому должно быть отделено.
    Т. Е. Наследование лучше от интерфейса.
    2. Дублирование кода
    Если случайное число =...
    init
    set
    add
    Иначе
    init
    set
    add
    ...
    INIT отличается, но set add одни и те же.
    На то и обьктное наследование чтобы это выделять.
    Ответ написан
    Комментировать
  • Вопрос про ООП, как использовать?

    @red-barbarian
    Дело не в том какая парадигма лучше/хуже. Дело в том какая ближе к вашему мышлению и моделировании области которую вы описываете. Если вы мыслите процедурами, то ооп в коде будет притянута за уши. Если код понятен, легко читается, то этого достаточно.
    В качестве развития можно почитать что-то из оо проектирования.
    Процедурность и ООП это два разных подхода к пониманию системы. (Это не ключевые слова в синтаксисе. ). Разные подходы к решениям проблем всегда полезны. Хотя не напрямую.
    Т.е. умейте много, применяйте что эффективно для конкретного случая.
    Ответ написан
    Комментировать
  • Как правильно составить диаграмму классов?

    @red-barbarian
    Вообще, это правильный подход к диаграммам. )
    Вот что писал Боб Мартин:
    "Возьмите за правило выбрасывать ненужные UML-диаграммы. А еще
    лучше, не создавайте их на постоянном носителе. Рисуйте на доске или
    на клочках бумаги. Почаще стирайте с доски и выбрасывайте эти об-
    рывки. Не привыкайте к инструментарию CASE или к графическим ре-
    дакторам. Для таких инструментов есть свое время и место, но жизнь
    большинства UML-диаграмм недолговечна."
    Хотя, далее, некоторые полезно и сохранять. Общий дизайн системы (идея) или те моменты которые из текста программы будет сложно понять.

    Упрощенно можно так подходить к выделению классов и интерфейсов.
    Есть два реальных объекта. Они относятся к разным классам. Со своими особенностями. Но у них есть некие одинаковые свойства. Например шаблоны функций. пример в общем случае быстрая сортировка это шаблон реализующий алгоритм, но этот шаблон не знает как реально сравнивать объекты. То есть это абстрактный класс объединяющий конкретные быстрые сортировки конкретных объектов. Можно сказать, что абстрактный класс это вынос общих методов и полей их своих потомков. При том что реально мы никогда не создадим экземпляр этого класса.
    Выделение интерфейса. Обычно применяется для разделения систем на отдельные на зависимые части. Например кнопка включает лампу. В программе это реализуется так
    кнопка имеет поле лампа. т.е. реализация кнопки зависит от лампы. Если тип (или код) лампы поменялся, то и часть кода ответственная за кнопку тоже меняется. По крайней мере должна протестироваться. Но можно договориться разделить все устройства которые могут что-то включать (кнопки) и могут быть включены (лампы, двигатели, телевизоры...) и указать как им взаимодействовать.
    Т.е. примерно так:
    Кнопка управляет устройствами.
    Устройство должно иметь метод "включить".
    Лампы, телевизоры, двигатели должны реализовать это метод у себя.
    Итого одна и та же кнопка (без изменения кода) управляет целой группой разнородный устройств (но реализующих общие правила взаимодействия)

    По картинкам:
    у нас есть объекты
    связь 0, связь 1, ...связь 3
    так же объект шина из связей.
    общее для них это они все имеют имя.
    также они имеют некоторые правила передачи сигналов.
    Это дает нам два класса Net и Bus. Кроме того Bus включает в себя много Net.
    Далее хотелось бы , что бы эти классы были независимы от правил. т.е что бы правила мы могли назначать сами. возможно динамически. Поэтому net и bus имеют метод назначающий правила rule (с общим интерфейсом) (которые можно менять, и не менять реализацию net, bus ).
    Итого Выделили общие свойства из net, bus в абстрактный класс AbstractNet. bus включает много net. Вынесли правила (которые будут часто меняться и которые мы возможно еще не знаем) за общий интерфейс.
    примерно так. упрощенно.
    Ответ написан
    6 комментариев