Подтвердить что ты не робот

Где я могу найти примеры процедурного кода, преобразованного в код объекта

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

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

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

Спасибо

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

mysql_query(conn, "create database testdb")

и в С++:

query.execute();

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

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

Ответ 4

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

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

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