Как перейти от плохого ООП-дизайна к хорошему?

Я много читаю о хороших и плохих методах ООП-дизайна. Приятно знать, что твой дизайн плохой или хороший. Но как перейти от плохого к хорошему дизайну? Я отделил интерфейс (xaml) и программный код от основного класса бизнес-логики. Этот последний класс становится большим. Я пытался разделить его на более мелкие классы, но теперь я застрял. Любые идеи о том, как разделить большие классы? Основной класс имеет 1 список данных разных типов. Я делаю расчеты по сумме, но также и по отдельным типам. У меня есть методы для выполнения этих вычислений, которые вызываются из событий, обрабатываемых в отделенном коде. Любые идеи, куда идти отсюда?

Дополнительная информация:

Мы уже около 6 месяцев в этом проекте. Я много лет работал с объектно-ориентированными языками (сначала С++, Java, а теперь и С#), но никогда не работал над такими большими проектами, как этот. Я считаю, что мы сделали несколько неправильных поворотов в начале, и я думаю, что нам нужно их исправить. На данный момент я не могу указать какие-либо подробности об этом проекте. Я собираюсь заказать одну или две книги о дизайне. Если я разделю все классы, как мне склеить их вместе? Может быть, даже лучше продолжать так до первого релиза и пересобирать части после этого, для второго релиза?


person Sorskoot    schedule 13.01.2009    source источник


Ответы (12)


Основной класс имеет 1 список данных разных типов. Я делаю расчеты по сумме, но также и по отдельным типам. У меня есть методы для выполнения этих вычислений, которые вызываются из событий, обрабатываемых в отделенном коде. Любые идеи, куда идти отсюда?

Если есть много вычислений, основанных на содержимом списка, рассматривали ли вы перенос операций в настраиваемый класс списка? То же самое касается операций над конкретными типами, возможно, они могли бы жить внутри типов?

С точки зрения выполнения похожих, но разных операций над разными типами рассмотрите возможность использования шаблона состояния (см. замена операторам switch), что позволяет обрабатывать сущности единообразно.

Много ООП заключается в том, чтобы отказаться от подхода «сверху вниз»/микроменеджмента и рассмотреть подход «снизу вверх»/самодостаточный подход. Стоит помнить, что ни один из подходов не является "правильным" по отдельности. Создание поддерживаемого кода — это поиск разумного баланса, который требует много размышлений и обычно развивается с опытом.

person Quibblesome    schedule 13.01.2009
comment
Мне нравится идея перемещения списка в класс списка. Я должен изучить шаблон состояния. - person Sorskoot; 13.01.2009

Практикуйтесь и читайте. Повторение :)

Некоторые рекомендуемые книги:

  • Чистый код Роберта Мартина
  • Шаблоны проектирования GoF
  • Рефакторинг Мартина Фаулера

Лично мне также понравились шаблоны проектирования Head First, но этот стиль может подойти не всем. Есть похожая книга под названием «Шаблоны проектирования C# 3.0» (см. ora.com). В нем много того же, но в более традиционной манере.

person Brian Rasmussen    schedule 13.01.2009
comment
Дополнительный + за рефакторинг. Если вы ничего не делаете, выучите наизусть главу 3 — плохой код пахнет — и поймите причины, стоящие за ними. Простое понимание принципов, лежащих в основе этих запахов, поможет вашему объектно-ориентированному коду больше, чем любая другая отдельная глава, которую я когда-либо читал. - person Bill K; 14.01.2009
comment
Я согласен - знать, как идентифицировать запахи кода, очень ценно. - person Brian Rasmussen; 14.01.2009

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

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

Редактировать: перенесите это мышление на уровень «метода» - сделайте свои методы ответственными за одну вещь и только одну вещь. Помогает очень быстро разбивать большие (> 50 строк) методы на повторно используемые фрагменты кода.

person Rob    schedule 13.01.2009
comment
Я хочу разделить обязанности, но у меня так много методов, зависящих друг от друга. Небольшие методы, за исключением нескольких +/- 50 вкладышей, все 10 строк или меньше. - person Sorskoot; 13.01.2009
comment
Можете ли вы сгруппировать эти маленькие методы в несколько категорий? - person Rob; 14.01.2009
comment
да. Я пытался поместить их в свои собственные классы, но поскольку все они делятся и работают над одним и тем же списком, их трудно разделить. Я даже назвал методы в этих категориях, поэтому я знаю, для чего они нужны, глядя на их имена. - person Sorskoot; 14.01.2009
comment
Проголосовал за Code Complete ref. Распределение ответственности имеет ключевое значение. Вы также можете ознакомиться с GRASP от Крейга Лармана. Кроме того, я считаю, что основательный объектно-ориентированный анализ является частью успешного объектно-ориентированного проектирования. - person Fuhrmanator; 13.04.2012

Измените свое отношение к объектам. У каждого объекта должна быть одна очень конкретная обязанность. Если у вас есть класс с общим именем, например «MainBusinessLogic», вы, вероятно, делаете что-то не так.

Отличное место для начала: прочтите книгу Дэвида Уэста Объектное мышление.

person user53564    schedule 13.01.2009
comment
Формулировка «ответственность» немного двусмысленна. - person Joe Phillips; 13.01.2009
comment
Именование этого класса — одна из вещей, которые, я думаю, я сделал хорошо. Это одно существительное, объясняющее, что это такое, например, Counter (в магазине). - person Sorskoot; 13.01.2009
comment
Из всех перечисленных книг «Объектное мышление» является самой сложной — на ее осмысление в реальном мире могут уйти годы... - person goofballLogic; 02.03.2010

Это всего лишь дополнение к некоторым хорошим книжным предложениям.

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

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

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

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

Дизайн в первую очередь может быть трудным. Считайте, что способности к программированию аналогичны спортивным способностям. Большинство из нас играет на подъездных дорожках, некоторые играют в местных спортивных командах. Сделать хороший предварительный дизайн сложного проекта — задача игрока национальной лиги, таких один на миллион. Примите это и планируйте изменения — итерации — ваш друг. (Кстати, большинство из нас ДУМАЕТ, что мы легко находимся на государственном уровне. Это не так).

person Bill K    schedule 13.01.2009
comment
Извините за придирки, но разве вы не имеете в виду классы или типы, а не объекты? - person Brian Rasmussen; 14.01.2009
comment
Да, у меня есть расстройство, из-за которого я иногда заменяю родственные термины в разговоре. (Хм, интересно, есть ли такая вещь! Если есть, то она у меня есть, а если нет, то она должна быть названа в мою честь) - person Bill K; 14.01.2009

В дополнение к рекомендации Брайана о Чистом коде Роберта К. Мартина, вы можете прочитать «Дядя Боб» Основы объектно-ориентированного проектирования SOLID.

Вы можете услышать, как он говорит о принципах SOLID в подкасте Hanselminutes 145, а также о чистом коде в .NET рулит! Показать #388. Кроме того, на .NET Rocks! Покажите #410, но то, о чем он говорит, на самом деле не имеет отношения к вашему вопросу, я просто включил его на тот случай, если вам понравились первые два.

Из трех подкастов я предпочел Hanselminutes.

person Grant Wagner    schedule 13.01.2009
comment
Я просто люблю оба этих шоу. Я сейчас слушаю .net Rocks #410 :) - person Sorskoot; 14.01.2009

Рефакторинг Мартина Фаулера — отличная книга о том, как изменить дизайн вашего программного обеспечения, не нарушая его.

Шаблоны проектирования работают аналогично алгоритмам, но говорят вам, как объединять предметы для выполнения различных полезных задач.

Наконец, Мартин Фаулер предлагает множество полезных шаблонов проектирования для приложений. Например, пассивный просмотр

person RS Conley    schedule 13.01.2009

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

То же самое касается "Рефакторинг по шаблонам".

person duffymo    schedule 13.01.2009

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

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

person Joe Phillips    schedule 13.01.2009

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

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

Во-первых, единственный раз, когда вам нужно сохранять информацию, это когда вы получаете ее в момент А и нуждаетесь в ней позже в момент Б. Если вы получаете ее и работаете с ней одновременно, может оказаться, что нет необходимости ее хранить. .

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

В-третьих, как часто информация меняется? Если часть информации меняется очень редко, вы можете использовать частичную оценку (т. е. генерацию кода). То есть вы берете редко меняющуюся информацию и используете ее для создания специальной программы, которая делает то же, что и ваша программа в целом, но гораздо быстрее. Генератор кода легко написать, потому что он работает только с частью входной информации, той частью, которая изменяется медленно.

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

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

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

Просто мой минус-приманка...

person Mike Dunlavey    schedule 13.01.2009

Я рекомендую книгу Feather Эффективная работа с устаревшим кодом, доступную и доступную для поиска на Safari, после рефакторинга. В нем много полезных и чутких глав, таких как У меня мало времени, и я должен его изменить и У моего приложения нет структуры.

Перспективы для рассмотрения:

  1. Автоматизация тестирования качества дизайна — ищите инструменты, которые предоставляют метрики качества дизайна в качестве перекрестной проверки ваших дизайнерских решений.
  2. Тестируемость кода — какой-либо из ваших рефакторингов помогает или мешает разработке через тестирование, написанию модульных тестов или написанию функциональных тестов? Насколько сложно будет протестировать большие части архитектуры после ее интеграции?
  3. Обоснование — как вы защищаете эти решения, как от циничного CYA до руководства, так и, что более важно, чтобы ваша команда поверила в редизайн. Можете ли вы легко и последовательно объяснить, почему было внесено изменение, и легко ли будет найти это объяснение через 6 месяцев?

Личные предпочтения в дизайне, особенно в рефакторинге:

  1. Классы для понятий. В случае сомнений, если есть одно четкое понятие, его следует обернуть в класс, а не подразумевать как поведение в одном или методах.
  2. О многих мелочах, связанных с обязанностями, легче думать и проверять. Если вы сомневаетесь в том, как дизайн соотносится с реальным миром, вернитесь к старому Responsibility-Driven- Разработайте подход к записи обязанностей каждого класса. Если вам это покажется трудным, ваши представления о том, что делает каждый класс, могут быть запутанными или они делают слишком много.
  3. Не пугайтесь больших вещей, если они обычные. Иногда, например: много обработчиков событий в графическом интерфейсе, у вас законно будут классы с гораздо большим количеством методов или свойств, чем рекомендуют метрики.
person Andy Dent    schedule 14.01.2009

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

person Toran Billups    schedule 14.01.2009