Я уже довольно давно программирую на процедурных языках, и моя первая реакция на проблему состоит в том, чтобы начать разбивать ее на задачи для выполнения, а не рассматривать различные сущности (объекты), которые существуют, и их отношения.
Я прошел университетский курс по ООП и понимаю основы инкапсуляции, абстракции данных, полиморфизма, модульности и наследования.
Я читаю /programming/2688910/learning-to-think-in-the-object-oriented-way и /programming/1157847/learning-object-oriented-thinking , и будет смотреть на некоторые из книг, на которые указывают эти ответы.
Я думаю, что некоторые из моих средних и крупных проектов выиграют от эффективного использования ООП, но как новичок я бы хотел избежать распространенных ошибок, отнимающих много времени.
Исходя из вашего опыта, что это за подводные камни и как их обойти? Если бы вы могли объяснить, почему они являются ловушками, и насколько ваше предложение эффективно для решения проблемы, это будет оценено.
Я думаю о чем-то вроде: «Является ли обычным иметь достаточное количество методов наблюдателей и модификаторов и использовать частные переменные или есть методы для их объединения / сокращения?»
Меня не беспокоит использование C ++ в качестве чистого ОО-языка, если есть веские причины смешивать методы. (Напоминает о причинах использования GOTO, хотя и экономно.)
Спасибо!
источник
Ответы:
Одна большая вещь, которую я узнал, - это проектирование классов извне. Разработайте интерфейс, прежде чем вы даже начнете думать о реализации. Это сделает класс намного более понятным для ваших пользователей (тех, кто его использует), чем написание базовых алгоритмов и создание класса, а также написание новых открытых функций-членов по мере необходимости.
источник
Ну, во-первых, это ловушка для раскрытия слишком большого количества информации. По умолчанию должно быть
private
, а неpublic
.После этого приходит слишком много добытчиков / сеттеров. Допустим, у меня есть член данных. Мне действительно нужны эти данные в другом классе? Хорошо, сделай добытчик. Действительно ли мне действительно нужно изменять эти данные в течение срока службы объекта? Тогда сделай сеттер.
Большинство начинающих программистов по умолчанию создают геттер / сеттер для каждого элемента данных. Это мешает интерфейсам и часто является плохим выбором дизайна.
источник
Когда я преодолел эту пропасть, я остановился на следующем подходе:
0) Я начал медленно, с маленькими / средними процедурными приложениями и без критически важных вещей на работе.
1) простое 1-ое проходное отображение того, как я написал бы программу с нуля в ОО-стиле - что наиболее важно для меня в то время, и это СУБЪЕКТИВНО - состояло в том, чтобы выяснить все базовые классы. Моей целью было инкапсулировать как можно больше в базовые классы. Чистые виртуальные методы для всего возможного в базовых классах.
2) Затем следующим шагом было создание дериваций.
3) последний шаг - в исходном процедурном коде отделить структуры данных от кода наблюдателя / модификатора. Затем используйте скрытие данных и отобразите все общие данные в базовые классы, и в подклассы пошли данные, которые не были общими для всей программы. И такой же подход к процедурному коду наблюдателя / модификатора - вся логика «везде использовалась» вошла в базовые классы. И логика просмотра / изменения, которая действовала только на подмножестве данных, вошла в производные классы.
Это субъективно, но БЫСТРО, если вы хорошо знаете процедурный код и структуры данных. Ошибка в обзоре кода - это когда немного данных или логики не появляется в базовых классах, но используется везде.
источник
Взгляните на другие успешные проекты, которые используют ООП, чтобы почувствовать хороший стиль. Я рекомендую взглянуть на Qt , проект, на который я всегда обращаю внимание при принятии собственных дизайнерских решений.
источник
В зависимости от того, с кем вы общаетесь, все данные в ООП должны быть частными или защищенными и доступны только через методы доступа и мутаторы. В целом, я считаю, что это хорошая практика, но бывают случаи, когда я отклоняюсь от этой нормы. Например, если у вас есть класс (скажем, в Java), единственной целью которого является объединение некоторых фрагментов данных в логическую единицу, имеет смысл оставить поля открытыми. Если это неизменяемая капсула, просто пометьте их как финальные и инициализируйте их в конструкторе. Это уменьшает класс (в данном случае) до уровня, превышающего структуру (на самом деле, используя C ++, вы должны называть это структурой. Работает так же, как класс, но видимость по умолчанию общедоступна, и ваше намерение более понятно), но Я думаю, вы обнаружите, что использовать его гораздо удобнее в этих случаях.
Одна вещь, которую вы определенно не хотите делать, - это иметь поле, которое необходимо проверить на согласованность в мутаторе, и оставить его открытым.
источник
struct
s - это не делает никакой семантической разницы, но это проясняет намерение и делает их использование более естественным, особенно для программистов на Си.Книга «Реализация шаблонов реализации» Кента Бека - отличное обоснование того, как использовать, а не злоупотреблять объектно-ориентированными механизмами.
источник
Меня не беспокоит использование C ++ в качестве чистого ОО-языка, если есть веские причины смешивать методы. (Напоминает о причинах использования GOTO, хотя и экономно.)
Я действительно не думал, что мне есть что предложить, пока я не увидел это. Я должен не согласиться с мнением. ООП - это только одна из парадигм, которые можно и нужно использовать в C ++. Честно говоря, на мой взгляд, это не одна из его сильных сторон.
С точки зрения ОО, я думаю, что C ++ на самом деле немного отстает. Например, идея иметь не виртуальные функции - это галочка против этого. У меня были споры с теми, кто не согласен со мной, но не виртуальные участники просто не соответствуют парадигме, насколько я обеспокоен. Полиморфизм является ключевым компонентом ОО, и классы с не виртуальными функциями не являются полиморфными в смысле ОО. Так что, как ОО-язык, я думаю, что C ++ на самом деле довольно слаб по сравнению с такими языками, как Java или Objective-C.
Обычное программирование, с другой стороны, в C ++ это довольно неплохо. Я слышал, там сказано, что есть и лучшие языки для этого, но комбинация объектов и универсальных функций - это нечто очень мощное и выразительное. Кроме того, он может быть чертовски быстрым как во время программирования, так и во время обработки. Я думаю, что именно в этой области светит C ++, хотя по общему признанию это могло бы быть и лучше (например, поддержка языков для концепций). Кто-то думает, что он должен придерживаться ОО-парадигмы и относиться к другим по порядку утверждения goto на уровнях безнравственности, действительно упускают из виду, не глядя на эту парадигму.
Возможность метапрограммирования шаблонов также впечатляет. Взгляните на библиотеку Boost.Units, например. Эта библиотека обеспечивает поддержку типов для размерных величин. Я широко использовал эту библиотеку в инженерной фирме, в которой я сейчас работаю. Это просто обеспечивает гораздо более немедленную обратную связь для одного аспекта возможного программиста или даже ошибки спецификации. Невозможно скомпилировать программу, использующую формулу, в которой обе стороны оператора '=' не являются размерно-эквивалентными без явного приведения. Лично у меня нет опыта работы с любым другим языком, на котором это возможно, и, конечно, не с языком, обладающим мощью и скоростью C ++.
Метапрограммирование - это чисто функциональная парадигма.
На самом деле, я думаю, что вы уже вступили в C ++ с некоторыми неудачными заблуждениями. Других парадигм, кроме ОО, не следует избегать, их нужно НАЧИСЛЯТЬ. Используйте парадигму, которая естественна для аспекта проблемы, над которой вы работаете. Не навязывайте объектам то, что по существу не является проблемой, склонной к объектам. Насколько я понимаю, OO - это еще не половина истории C ++.
источник
Я хотел принять ответ на этот вопрос, но я не мог выбрать один ответ, чтобы поставить галочку на. Таким образом, я проголосовал за авторов оригинала и создал это как краткий ответ. Спасибо всем, кто потратил несколько минут, и обнаружил, что предоставленная вами информация дала мне хорошее направление и немного уверенности в том, что я не сошел с рельсов.
@nightcracker
Я чувствовал, что наблюдал эту проблему в действии в прошлом. Ваши комментарии заставили меня также вспомнить, что, скрывая лежащие в основе переменные и их реализацию, я могу свободно изменять их реализацию, не разрушая ничего зависящего от них.
Доминик Гурто
Я думал, что комментарий Доминика был отличным идеалом, к которому можно стремиться, но я думаю, что комментарий Джина действительно соответствует реальности ситуации. До сих пор я видел это в действии ... и чувствую себя немного лучше, что это не редкость. Я думаю, что, становясь программистом, я склоняюсь к более полным проектам, но сейчас я все еще страдаю от скачка и получаю некоторый написанный код.
wantTheBest
В этом много смысла ... Мне понравилась идея, чтобы все работало на работе, но чтобы реорганизовать некритические вещи с помощью классов.
JPM
Некоторое время я знал, что это одна из сильных сторон инкапсуляции данных ... способность обеспечивать согласованность и в этом отношении условия / диапазоны / и т. Д.
Сумасшедший Эдди
Изначально я многое пропустил в ответе Сумасшедшего Эдди, я думаю, потому что я не читал некоторые из упомянутых тем ... как метапрограммирование. Я думаю, что большое сообщение в посте CE состояло в том, что C ++ - это такое сочетание возможностей и стилей, что каждый из них должен использоваться с максимальной отдачей ... включая необходимость, если это имеет смысл.
Итак, еще раз, спасибо всем, кто откликнулся!
источник
Самым большим подводным камнем является вера в то, что ООП - это серебряная пуля или «одна идеальная парадигма».
источник