Где я могу найти примеры процедурного кода, преобразованного в объектный код - PullRequest
16 голосов
/ 28 августа 2009

Я пытаюсь обернуть голову вокруг объектно-ориентированного программирования. Но у меня проблемы. Я (думаю) я понимаю общие концепции и аргументы, почему ООП - это «хороший» дизайн. Моя проблема возникает, когда я сижу и пытаюсь написать код, который является ООП.

Я, как правило, в конечном итоге получаю программы, которые либо очень процедурные, но для хорошей меры добавляются случайные объекты ... или программы, которые кажутся смехотворно длинными и сложными для того, что они делают ... все является объектом ; но объектов много, и деревья наследования становятся длинными и безобразными.

То, что я пытался найти, - это несколько нетривиальных примеров (я видел множество одноразовых / псевдокодов, касающихся кошек, собак и животных ... но, похоже, они не помогают, когда Я на самом деле пытаюсь кодировать что-то, что должно что-то делать) из действительно хорошо спроектированного исходного кода ООП. В идеале я ищу что-то, что поможет мне пройти через процесс мышления. Вроде «Хорошо - вот некоторый процедурный код, который делает XYZ. Теперь, вот действительно отличный код ООП, который делает то же самое! '.

Спасибо

Ответы [ 4 ]

10 голосов
/ 28 августа 2009

Реальность такова, что такие преобразования обычно не будут хорошим объектно-ориентированным кодом. Зачем? Потому что объектно-ориентированный код не просто перемещает функции в методы, а данные в члены.

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

Это означает, что нет преобразования 1: 1 от процедурных функций и процедурных структур данных к объектно-ориентированным.

Посмотрев вокруг, я не нашел ни одного примера, который бы мне понравился, поэтому просто приведу свои правила рефакторинга для преобразования процедурного кода в ООП.

Первый шаг - просто упаковать каждый модуль как объект. Другими словами, просто создайте объект, который содержит данные и функции. Это ужасно для пуриста, но с чего-то начинать надо. Например, если у вас был модуль BankAccount, теперь у вас будет объект BankAccount.

Очевидно, что функции передавали в них данные от внешних вызовов. Здесь вы ищете, как интернализировать эти данные и сделать их максимально частными. Цель должна состоять в том, чтобы вы получили свои данные в конструкторе (по крайней мере, в начальной точке) и удалили параметры, которые использовались для получения данных вручную, и заменили их ссылками на эти теперь личные данные. Используя объект BankAccount, теперь весь доступ к счету осуществляется через методы объекта, и фактические данные счета были усвоены.

Многие из ваших функций, вероятно, возвращали измененные версии структур данных: прекратите возвращать эти данные напрямую и оставьте эти изменения в частных структурах. Создайте свойства средства доступа, которые возвращают ваши теперь приватные данные, где это необходимо, и пометьте их как «устаревшие» (ваша цель - сделать объект хозяином своих данных и возвращать только результаты , а не внутренние данные). С объектом BankAccount мы больше не возвращаем фактические данные счета, но у нас есть свойства для CurrentBalance и такие методы, как AverageBalance (int days), чтобы просмотреть счет.

Со временем у вас будет набор автономных объектов, которые все еще мало похожи на то, что вы сделали бы, если бы начали с объектов в своем дизайне, но, по крайней мере, вы можете продолжить рефакторинг с новыми объектами. Мой следующий шаг обычно состоит в том, чтобы обнаружить, что объекты, созданные в результате такого рефакторинга, имеют много обязанностей. На данный момент некоторые общие потоки, вероятно, были обнаружены, и вы должны создать объекты для рефакторинга этих общих идей. Если у нас есть BankAccount, у нас, вероятно, есть другие типы учетных записей, и если мы приведем в соответствие методы всех этих типов учетных записей, мы сможем сделать Account в качестве базового класса, который реализует все общие функции, тогда как BackAccount, SavingsAccount и другие реализуют детали.

Как только структура классов начинает обретать форму, настало время почувствовать себя лучше в отношении преобразования. Рефакторинг - это процесс, а не конечная точка, поэтому я обычно нахожу, что структура моего класса продолжает развиваться. Одна из приятных вещей, достигнутых в этом, заключается в том, что ваши данные являются частными и обрабатываются с помощью методов, так что вы можете реорганизовывать внутренние компоненты более свободно по мере продвижения.

Одна вещь, которая делает это правдоподобным, это проведение хороших юнит-тестов. Выполняя процедурные преобразования в ООП, я часто сохраняю старый код как «базовый уровень», чтобы проверить его. То есть, тест может проверять результаты старой процедурной системы. Если вы не совпадаете, это хорошая идея, чтобы выяснить, почему. Я нахожу, что часто есть ошибка ... но иногда ваш новый более чистый код на самом деле делает что-то правильное, что было неправильно в прошлом.

Относительно создания "слишком глубоких" деревьев объектов: это может быть результатом того, что вы слишком одержимы наследованием. Я считаю, что композиты часто являются лучшей идеей, когда вы реализовали интерфейсы для нескольких объектов, а не пытались объединить все эти функции в один родительский объект. Если вы обнаруживаете, что создаете родительские объекты, которые просто представляют собой наборы функций, рассмотрите возможность упрощения путем создания интерфейса для каждого набора функций и реализации этих интерфейсов.

3 голосов
/ 28 августа 2009

Проблема процедурных программистов часто возникает при запуске объектно-ориентированного программирования: они продолжают проектировать процедуры и пытаются организовать их как объекты . Это не работает

Объектно-ориентированное программирование - это другая методология проектирования ; другой взгляд на роли и обязанности , который вы распространяете по всему коду, а не просто на другую методологию кодирования.

Когда вы преодолеете метафоры «собака-млекопитающее» (которые никогда не переводятся в реальные приложения), я бы порекомендовал эту книгу: Проектирование объектов: роли, обязанности и сотрудничество . Это была первая книга, которую я прочитал, где я наконец понял, почему мне пришлось прекратить просматривать (в моем случае) C ++ как "C с добавленными классами".

2 голосов
/ 28 августа 2009

Один очень интуитивный переход от API C к API C ++ часто происходит в базах данных; поэтому для этого примера мы кратко рассмотрим разницу в использовании API MySQL.

Я не уверен, что смогу скопировать код с этих сайтов (понятия не имею, что это за лицензия), но посмотрите раздел, помеченный «Создание базы данных» для демонстрации C, и Образец № 1 для демонстрации C ++; оба эти шага через создание базы данных MySQL программно.

В C API первый аргумент каждой функции - это «дескриптор» базы данных. В API C ++ мы работаем с подключением к базе данных объект , который неявно вызывает API C со своим частным дескриптором.

Чтобы посмотреть на один очень конкретный пример, чтобы выполнить запрос после его генерации, мы имеем в C:

mysql_query(conn, "create database testdb")

и в C ++:

query.execute();

Большая разница здесь в том, что привязка C ++ показывает вам только то, что вам нужно видеть, в то время как в C вы должны быть очень ясны в отношении каждой мелочи.

Я думаю, что API-интерфейсы баз данных - это хороший способ подобрать некоторые принципы ООП на примере, так что, надеюсь, они тоже помогут вам.

1 голос
/ 28 августа 2009

Я знаю, что это помечено .net, но хорошим примером будет PHP. До PHP5 PHP был только частично объектно-ориентированным. У многих разработчиков PHP была та же самая проблема с получением ООП.

У Зенда довольно хорошая статья здесь . Это должно быть довольно легко следовать.

Если вы чувствуете, что вам нужно лучшее направление в процессе объектно-ориентированного проектирования, вы можете проверить MIT Open CourseWare, в частности Основы программной инженерии (Lecture Notes # 2) или что-то подобное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...