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

Что должно быть в контрольном списке, который поможет кому-то разработать хорошее программное обеспечение OO?

Я использовал языки и методы программирования OO много лет назад (прежде всего на С++), но в промежуток времени не много сделал с OO.

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

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

Что должно быть в контрольном списке, который поможет кому-то разработать хорошее программное обеспечение OO?

И наоборот, какие "тесты" могут быть применены, чтобы показать программное обеспечение не OO?

4b9b3361

Ответ 1

Похоже, вы хотите задать некоторые основные вопросы "да/нет", чтобы спросить себя на вашем пути. Все дали отличные списки "сделать это" и "подумать так", так что вот моя трещина в некоторых простых да/нет.

Могу ли я ответить "да" на все эти вопросы?

  • Разделяют ли мои классы существительные, которыми я занимаюсь?
  • Предоставляют ли мои классы методы действий/глаголов, которые он может выполнять?

Могу ли я ответить на все эти вопросы?

  • Есть ли у меня глобальные данные состояния, которые можно либо помещать в одноэлементные, либо хранить в реализациях классов, которые работают с ним?
  • Можно ли удалить общедоступные методы в классе и добавить их в интерфейс или сделать их конфиденциальными/защищенными, чтобы лучше инкапсулировать поведение?
  • Должен ли я использовать интерфейс для ветки поведения от других интерфейсов или класса реализации?
  • Есть ли у меня код, который повторяется между связанными классами, которые я могу переместить в базовый класс для лучшего повторного использования кода и абстракции?
  • Я тестирую ли тип чего-то, чтобы решить, что делать? Если это так, то это поведение должно быть включено в базовый тип или интерфейс, который используется в этом коде, чтобы позволить большему эффекту использовать абстракцию или если код, о котором идет речь, должен быть реорганизован для использования лучшего базового класса или интерфейса?
  • Я неоднократно проверяю некоторые данные контекста, чтобы решить, какой тип создать экземпляр? Если это так, это можно абстрагировать в шаблон дизайна factory для лучшего абстрагирования логики и повторного использования кода?
  • Является ли класс очень большим с несколькими функциями? Если это так, я могу разделить его на несколько классов, каждый из которых имеет свою собственную цель?
  • Есть ли у меня несвязанные классы, наследующие от того же базового класса? Если это так, я могу разделить базовый класс на лучшие абстракции или я могу использовать композицию для доступа к функциям?
  • Является ли моя иерархия наследования страшной глубиной? Если это так, я могу сгладить или разделить вещи через интерфейсы или функции разделения?
  • Я слишком беспокоился о своей иерархии наследования?
  • Когда я объясняю дизайн резиновым уткам, я чувствую себя глупо в дизайне или глупо об разговоре с уткой?

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

Ответ 2

  • Объекты делают вещи. (Самый важный момент во всем ООП!) Не думайте о них как о "владельцах данных" - отправляйте им сообщение, чтобы что-то сделать. Какие глаголы должны иметь мой класс? Школа мышления, ориентированная на ответственность, является блестящей для этого. (См. "Дизайн объекта: роли, обязанности и сотрудничество", Ребекка Вирфс-Брок и Алан МакКин, Эддисон-Уэсли 2003, ISBN 0201379430.)
  • Для каждой вещи, которую должна выполнить система, придумать кучу конкретных сценариев, описывающих, как объекты общаются друг с другом, чтобы выполнить работу. Это означает мышление в терминах диаграмм взаимодействия и разыгрывание вызовов метода. - Не начинайте с диаграммы классов - что SQL-мышление не OO-мышление.
  • Узнайте о тестируемых разработках. Никто не получает свою объектную модель прямо вверх, но если вы делаете TDD, вы вкладываете в основу, чтобы убедиться, что ваша объектная модель делает то, что ей нужно, и делает ее безопасный для рефакторинга, когда ситуация изменится позже.
  • Создавайте только те требования, которые у вас есть сейчас - не зацикливайтесь на "повторном использовании" или на материалах, которые будут "полезны позже". Если вы только строите то, что вам нужно прямо сейчас, вы сохраняете пространство дизайна, которое вы могли бы сделать позже, гораздо более открытым.
  • Забудьте о наследовании, когда вы моделируете объекты. Это всего лишь один способ реализации общего кода. Когда вы моделируете объекты, просто притворяйтесь, что вы смотрите на каждый объект через интерфейс, который описывает, что можно попросить сделать.
  • Если метод принимает множество параметров или вам нужно многократно называть кучу объектов для получения большого количества данных, метод может быть в неправильном классе.. Лучшим местом для метода является рядом с большинством полей, которые он использует в одном классе (или суперклассе...)
  • Прочитайте книгу "Шаблоны дизайна" для вашего языка.. Если это С#, попробуйте "Design Patterns in С#" от Steve Metsker. Это научит вас серии трюков, которые вы можете использовать для разделения работы между объектами.
  • Не тестируйте объект, чтобы посмотреть, какой тип он есть, а затем выполните действие на основе этого типа - что запах кода, который объект должен, вероятно, выполнять. Это намек на то, что вы должны вызвать объект и попросить его выполнить работу. (Если только некоторые виды объектов выполняют работу, вы можете просто реализовать "ничего не делать" в некоторых объектах... Это законное ООП.)
  • Применение методов и данных в правильных классах делает OO-код более быстрым (и дает виртуальным машинам шанс оптимизировать лучше) - это не просто эстетическое или теоретическое. Исследование Sharble and Cohen указывает на это out - см. http://portal.acm.org/citation.cfm?doid=159420.155839 (См. график показателей "количество команд, выполняемых для каждого сценария" )

Ответ 3

Собранные из разных книг, знаменитые программисты на С# и общие советы (не так много, если это мое, это в том смысле, что это разные вопросы, которые я задаю себе во время разработки, но что это):

  • Структуры или классы? Является ли элемент, который вы создаете, своим значением, сделать его структурой. Если это "объект" с атрибутами и суб-значениями, методами и, возможно, состоянием, то сделать его объектом.
  • Запечатанные классы. Если вы собираетесь создавать класс, и вам явно не нужно унаследовать его, сделайте его запечатанным. (Я делаю это для предполагаемого увеличения производительности)
  • Не повторяйте себя. Если вы обнаружите, что вы копируете код (a/e), тогда вы должны (, но не всегда) переосмыслить свой дизайн чтобы свести к минимуму дублирование кода.
  • Если вам не нужно предоставлять базовую реализацию для данного абстрактного класса, превратите его в интерфейс.
  • Принцип специализации. Каждый объект, который у вас есть, должен делать только одно. Это помогает избежать "объекта Бога".
  • Использовать свойства для общедоступного доступа. Это обсуждалось снова и снова, но это действительно лучшее, что нужно сделать. Свойства позволяют делать то, что вы обычно не можете с полями, а также позволяет вам больше контролировать способ получения и установки объекта.
  • Синглтоны: еще одна спорная тема, и здесь идея: используйте их только тогда, когда вам абсолютно необходимо. Большую часть времени множество статических методов может служить цели одноэлементного. (Хотя, если вам абсолютно необходим синглетный шаблон, используйте Jon Skeet отлично один)
  • Свободная связь. Убедитесь, что ваши классы зависят друг от друга как можно меньше; убедитесь, что пользователям вашей библиотеки легко обмениваться части вашей библиотеки с другими (или настраиваемыми частями). Это включает в себя использование интерфейсов, где это необходимо, инкапсуляцию (другие упоминали об этом) и большинство остальных принципов в этом ответе.
  • Дизайн с простотой в виду. В отличие от замораживания пирога, теперь проще продумать что-то простое и добавить позже, чем сейчас проектировать комплекс и удалить позже.

Я мог бы отбросить часть или все это из двери, если я:

  • Написание личного проекта
  • действительно спешит что-то сделать (но я вернусь к нему позже... когда-нибудь.....;))

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

Ответ 4

Стив Макконнелл Code Complete 2 содержит много готовых к использованию контрольных списков для хорошей разработки программного обеспечения.

Роберт К. Мартин Agile Principles, Patterns и Practices в С# содержит много принципов для хорошего OO desgin.

Оба предоставят вам прочную основу для начала.

Ответ 5

  • Данные принадлежат коду, который работает на нем (т.е. в том же классе). Это улучшает ремонтопригодность, поскольку многие поля и методы могут быть частными (инкапсуляция) и, таким образом, в какой-то мере удалены из рассмотрения при рассмотрении взаимодействия между компонентами.
  • Использовать полиморфизм вместо условий - всякий раз, когда вам нужно делать разные вещи в зависимости от того, какой класс является объектом, попробуйте поместить это поведение в метод, который разные классы реализуют по-разному, чтобы все, что вам нужно do это вызов этого метода.
  • Использовать наследование экономно, предпочитайте композицию. Наследование является отличительной чертой программирования OO и часто рассматривается как "сущность" ООП. Это на самом деле серьезно злоупотребление и должно быть классифицировано как наименее важная функция.

Ответ 6

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

Я бы также рекомендовал контрольные списки в "Маркете" Роберта Мартина.

Ответ 7

  • Я четко определил требования? Документация формальных требований может не понадобиться, но перед началом кодирования у вас должно быть четкое видение. Инструменты отображения и прототипы интеллектуального анализа или проектные эскизы могут быть хорошими альтернативами, если вам не нужна формальная документация. Работайте с конечными пользователями и заинтересованными сторонами как можно раньше в процессе разработки программного обеспечения, чтобы убедиться, что вы реализуете то, что им нужно.

  • Я заново изобретаю колесо? Если вы кодируете решение общей проблемы, найдите надежную библиотеку, которая уже решает эту проблему. Если вы считаете, что можете решить проблему в другом месте вашего кода (или, возможно, у сотрудника), сначала найдите существующее решение.

  • Есть ли у моего объекта четкая цель?. Следуя принципу инкапсуляции, объект должен иметь поведение вместе с данными, на которых он работает. Объект должен иметь только одну серьезную ответственность.

  • Могу ли я кодировать интерфейс? Дизайн по контракту - отличный способ включить модульное тестирование, подробные документы, требования к классу и поощрять повторное использование кода.

    /li >
  • Могу ли я проверить свой код? Разработка, основанная на тестировании (TDD), не всегда проста; но модульные тесты неоценимы для рефакторинга и проверки поведения регрессии после внесения изменений. Идет рука об руку с дизайном по контракту.

  • Я переоцениваю? Не пытайтесь закодировать повторно используемый компонент. Не пытайтесь предвидеть будущие требования. Эти вещи могут показаться противоречивыми, но они приводят к лучшему дизайну. В первый раз, когда вы что-то кодируете, просто реализуйте его как можно проще, и заставьте его работать. Во второй раз вы используете ту же логику, копируете и вставляете. Когда у вас есть два рабочих раздела кода с общей логикой, вы можете легко реорганизовать, не пытаясь предвидеть будущие требования.

  • Я представляю код redudant? Не повторяйте себя (DRY) - это самый главный главный рефакторинг. Используйте copy-and-paste только как первый шаг к рефакторингу. Не кодируйте одно и то же в разных местах, это кошмар для обслуживания.

  • Является ли это общим шаблоном проектирования, анти-шаблоном или запахом кода? Будьте знакомы с общими решениями проблем с дизайном OO и смотрите на них по мере кода - но не попробуйте заставить проблему соответствовать определенной схеме. Следите за кодом, который попадает в общий шаблон "плохой практики".

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

  • Я могу разоблачить слишком много информации? Скрывать информацию о практике. Если метод или поле не должны быть общедоступными, сделайте его закрытым. Выставлять только минимальный API, необходимый для выполнения объекта. Не делайте данные реализации доступными для объектов клиента.

  • Я защищаю кодирование? Проверяем условия ошибки и Fail Fast. Не бойтесь использовать исключения, и пусть они распространяются. Если ваша программа достигает неожиданного состояния, гораздо лучше прекратить операцию, запишите трассировку стека, с которой вы будете работать, и избегайте непредсказуемого поведения в вашем нисходящем коде. Следуйте рекомендациям по очистке ресурсов, например, инструкции using() {}.

  • Смогу ли я прочитать этот код через шесть месяцев? Хороший код читается с минимальной документацией. Поставьте комментарии, если это необходимо; но и написать код, который интуитивно понятен и использовать значащие имена классов, методов и переменных. Практика хорошего стиля кодирования; если вы работаете над проектом команды, каждый член команды должен написать код, который выглядит одинаково.

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

Ответ 8

  • SOLID
  • DRY
  • TDD
  • Состав над наследованием

Ответ 9

Убедитесь, что вы прочитали и поняли следующее

  • Инкапсуляция
    • (убедитесь, что вы только открываете минимальное состояние и функциональность, чтобы выполнить работу)
  • Полиморфизм
    • (Возможность для производных объектов вести себя как их родители)
  • Разница между интерфейсом и абстрактным классом
    • (Абстрактный класс позволяет функциональность и состояние для совместного использования с ним потомки, интерфейс является только обещанием, что функциональность будет реализована)

Ответ 10

Мне нравится этот список, хотя он может быть немного плотным, чтобы использоваться в качестве контрольного списка.

Ответ 11

UML - унифицированный язык моделирования, для моделирования объектов и определения структуры и отношений между классами

http://en.wikipedia.org/wiki/Unified_Modeling_Language

Тогда, конечно, методы программирования для OO (большинство уже упомянутых)

  • Скрытие информации
  • Абстракция
  • Интерфейсы
  • Герметизация
  • Наследование/Полиморфизм

Ответ 12

Некоторые из правил являются агностиками языка, некоторые правила отличаются от языка к языку.

Вот несколько правил и комментариев, которые противоречат другим ранее опубликованным правилам:

  • OO имеет 4 принципа: Абстракция, инкапсуляция, полиморфизм и наследование.
    Читайте о них и помните о них.

  • Моделирование - ваши классы должны моделировать объекты в проблемной области:
    Разделите проблему на поддомены (пакеты/пространства имен/сборки)
    затем разделите сущности в каждом поддомене на классы.
    Классы должны содержать методы, которые моделируют, какие объекты этого типа делают.

  • Используйте UML, подумайте о требованиях, примерах использования, затем диаграммах классов, их последовательностях. (применимые в основном для высокоуровневого дизайна - основные классы и процессы.)

  • Шаблоны проектирования - хорошая концепция для любого языка, реализация отличается между языками.

  • Struct vs. class - в С# это вопрос передачи данных по значению или по ссылке.

  • Интерфейс против базового класса, является базовым классом, имеет интерфейс.

  • TDD - это не OO, на самом деле это может вызвать недостаток дизайна и привести к большому количеству перезаписи. (Например, Scrum рекомендует против него, для XP это обязательно).

  • С# Отражение в некотором роде переопределяет OO (например, сериализацию на основе отражения), но это необходимо для расширенных фреймворков.

  • Удостоверьтесь, что классы не "знают" о других классах, если они не должны, делятся на несколько сборок и скудны с помощью ссылок.

  • AOP (аспектно-ориентированное программирование) улучшает ООП (см., например, PostSharp) таким революционным способом, что вы должны по крайней мере искать его и смотреть их клип.

  • Для С# ознакомьтесь с рекомендациями MS (ознакомьтесь с рекомендациями в справочной системе VS MSDN), у них есть много полезных рекомендаций и соглашений там

  • Рекомендуемые книги:
    Руководство по разработке рамок: соглашения, идиомы и шаблоны для многоразовых библиотек .NET
    С# 3.0 в двух словах