Что такое простой процесс проектирования системы ООП перед ее кодированием?

10

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

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

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

g.arbia777
источник
8
«Теперь я знаю, что это не правильный способ создания программного обеспечения» - кто вам это сказал? Похоже, вы попадаете в популярную ловушку, полагая, что «дизайн - это то, что вы делаете перед написанием кода, возможно, рисуя причудливые UML-диаграммы». Чтобы вылечить вас от этого заблуждения, я рекомендую начать с «Code as Design» Джека Ривза.
Док Браун
@DocBrown. Не думаете ли вы, что дизайн во время кодирования делает нашу работу такой кустарной? Я не могу представить, чтобы другие двигатели работали одинаково. Представьте себе, как архитектор укладывает кирпичи и строительный раствор и проектирует здание / мост на пути.
Laiv
5
@Laiv: «кодирование» является частью того , что в других инженерных дисциплинах , как называются дизайном. В жилищном строительстве шаг от проектирования до конечного продукта осуществляется с помощью кирпича и раствора. В программировании этот шаг выполняется компилятором при переводе проекта (= программы) в конечный продукт (= исполняемый двоичный файл). И это не новая мудрость. Ривз эссе 25 лет.
Док Браун
@DocBrown, разработчик. * Больше не курирует? Кнопка подписки сломана, например.
радаробоб

Ответы:

20

Нисходящий стиль водопада OOAD не гарантирует, что код, который вы пишете, вообще ориентирован на объект. Я видел горы строго OOAD-кода, доказывающего это. Если ОО смущает вас, не ищите здесь помощи. Вы не найдете это. ОО НЕ требует от вас дизайна сверху вниз.

Если вам нравится заниматься программированием, так и будет. Позвольте мне сказать вам подсказку. Медлить.

Удивительно, как легко проектировать классы, написав код, который использует их, даже когда они еще не существуют. Забудьте процедуру. Забудьте структуру. Просто установите себе хороший уровень абстракции и придерживайтесь его. Не поддавайтесь искушению и не смешивайте в нем дополнительные детали. Все, что выводит вас из текущей абстракции, может быть сделано в каком-то методе, который может быть в другом объекте, который каким-то образом знает все, что ему нужно знать. Не создавайте ничего, что вы можете просто попросить передать вам.

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

Если вы можете войти в этот способ мышления, то остается архитектура. Мы все еще выясняем это. От MVC к чистой архитектуре до доменного дизайна. Изучай их и играй. Используйте то, что работает. Если вы найдете что-то на 100% надежное, вернитесь и дайте мне знать. Занимался этим десятилетиями, а я все еще ищу.

candied_orange
источник
2
Или вы обнаружите, что не делаете OO, и все же все «как-то» работает нормально в любом случае ...
Дерек Элкинс покинул SE
2
«Удивительно, как легко проектировать классы, написав код, который использует их, даже когда они еще не существуют», - я называю этот нисходящий дизайн, но, похоже, я ошибаюсь. Что такое дизайн сверху вниз и что я так назвал? Это программирование для интерфейса?
Пиовезан
Это не просто сверху вниз. Вы также должны быть готовы не создавать вещи, которые вы можете просто попросить, принимая параметры.
candied_orange
@Piovezan вы можете сделать это, даже если интерфейс еще не существует. Просто немного проигнорируйте ваш компилятор. Позже вы сделаете это существующим.
candied_orange
@CandiedOrange "Вы также должны быть готовы не создавать вещи, которые вы можете просто попросить, принимая параметры". - Я не уверен, что понимаю, не могли бы вы уточнить / предоставить краткий пример (или контрпример в этом отношении)?
Пиовезан
4

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

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

Вы утверждаете, что разработка на лету без «первоначального плана» - это:

«... не правильный способ создания программного обеспечения ...»

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

Если ваша проблема заключается в том, что вы не уверены в своих навыках документирования / дизайна / UML , попробуйте документировать существующий проект.

Лично я бы порекомендовал не беспокоиться о том, что ваши проекты идеально объектно-ориентированы, большинство систем не на 100% объектно-ориентированы. Цель состоит в том, чтобы создать лучшее понимание и визуализацию системы, а не совершенную абстракцию. Объектная ориентация - это не серебряная пуля, это просто еще один инструмент на поясе.

Эрдрик Айронроуз
источник
Я также хотел упомянуть, хотя и немного не по теме для ответа ... Ваши планы не должны быть очень большими! Иногда план - это просто вопрос: «Я хочу запустить его, и он что-то делает». Это достаточно хорошо, если это действительно все, что он собирается сделать.
Эрдрик Айронроуз
2

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

Мой совет: лучшее, что вы можете сделать для себя, - это кодировать фасады , предоставляя простой интерфейс для ввода и вывода, и надеяться, что входы и выходы меняются не часто. Хотя, даже если они это сделают, знайте, что это не проблема дизайна, а проблема спецификаций (изменение в необходимости / работе / функциональности). Это сделает вашу программу несколько устойчивой к проблемам, резонирующим в вашей программе с теми, кто называет вашу программу или часть кода, и наоборот.

Что касается проектирования объектно-ориентированной системы, нужно сказать что-то, чтобы попытаться сделать все объектно-ориентированным, когда этого не должно быть. Это распространенная ошибка среди языков программирования ООП, таких как C # и Java, состоит в том, чтобы пытаться рассматривать все как объект, что часто приводит к созданию единственного экземпляра класса для выполнения того, что в противном случае было бы статическим методом, который вообще не изменяет состояние. Тем не менее, конечно, вы должны использовать дизайн ООП, где это применимо, хотя не думайте, что вы делаете это неправильно, когда кажется более естественным написать статический метод. Это не всегда неправильный инстинкт.

Вам следует подумать об использовании класса, когда вы ответите «да» на любой из следующих вопросов:

  • Есть ли у меня группа информации, которая относится к одному и тому же понятию (например, имя, фамилия, адрес)?
  • Нужно ли выполнять операцию, требующую нескольких частей информации (т.е. calculatePrice(basePrice, quantity, tax))?
  • Есть ли у меня else, если с большими блоками кода выполняются несколько разные операции с одинаковой или похожей информацией (т.е. if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }==> animal.speak())
  • Есть ли у меня существующий класс, который выполняет более одной конкретной задачи и становится слишком большим?

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

Нил
источник
2

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

« Теперь я знаю, что это не правильный способ создания программного обеспечения » - кто вам это сказал? Похоже, вы попадаете в популярную ловушку, полагая, что «дизайн - это то, что вы делаете перед написанием кода, возможно, рисуя причудливые UML-диаграммы». Чтобы вылечить вас от этого заблуждения, я рекомендую начать с «Code as Design» Джека Ривза. - Док Браун 21 июня в 5:27

@Laiv: «кодирование» является частью того, что в других инженерных дисциплинах называется дизайном. В жилищном строительстве шаг от проектирования до конечного продукта осуществляется с помощью кирпича и раствора. В программировании этот шаг выполняется компилятором при переводе проекта (= программы) в конечный продукт (= исполняемый двоичный файл). И это не новая мудрость. Ривз эссе 25 лет. - Док Браун 21 июня в 6:39

Это же чувство отражается и в других местах. Рассмотрите доклады Гленна Вандербурга о «Реальной разработке программного обеспечения» и, в некоторой степени, его доклады «Ремесло, инженерия и сущность программирования» и «Ремесло и разработка программного обеспечения». Также рассмотрите страницы / обсуждения WhatIsSoftwareDesign и TheSourceCodeIsTheDesign на вики-сайте C2.

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

В сложной системе, вероятно, будет какой-то уровень архитектурного проектирования - определение подсистем, компонентов, модулей, сервисов и распределение требований к ним до того, как вы начнете писать код. Вы можете использовать UML как способ создания, документирования и помощи в обсуждениях этого архитектурного проекта. Рассмотрим идею режимов UML, которую обсуждает Мартин Фаулер , в частности UML как эскиз и UML как примечания . Также рассмотрим некоторые идеи из Agile Modeling - моделирование начальной архитектуры , итерационное моделирование и просто достаточно хорошие модели .

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

Томас Оуэнс
источник
1

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

OOAD не исключает возможности мыслить в системе как большие модули. Вы все еще можете сделать это. Каждый модуль существует для удовлетворения набора пользовательских историй (вариантов использования). Такие пользовательские истории нуждаются в классах, которые сотрудничают, чтобы выполнить их.

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

В Extreme Programming есть методика, называемая CRC Cards . CRC расшифровывается как «классовые обязанности-соавторы».

В основном вы идентифицируете очевидные классы и назначаете карту каждому. Скажем, у класса Invoiceесть своя карта.

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

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

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

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

Это упражнение можно (и нужно) делать в группе, в которой участвуют даже деловые люди.

Вы можете узнать больше об этой технике по этим ссылкам:

http://en.wikipedia.org/wiki/Class-responsibility-collaboration_card

http://www.extremeprogramming.org/rules/crccards.html

Примеры карт CRC:

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

Тулаинс Кордова
источник
0

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

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

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

Возьмите пример производителя автомобилей, который охватывает различные категории автомобилей: коммерческие автомобили, потребительские автомобили (седаны, хэтчбеки, универсалы) и т. Д.

Чтобы у производителя было четкое разделение по категориям и целям, существует несколько способов создания классов.

Производитель автомобилей OOAD

  1. В зависимости от категории (сектор рынка) транспортных средств: тяжелый автомобиль, потребительский автомобиль [седан, хэтчбек, универсал и т. Д.]

  2. В зависимости от объема двигателя и манеры вождения: 800-1500 куб. См,> 1500 куб. См и т. Д.

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

Акаш Мишра
источник
Вы начинаете хорошо, но затем последний бит выглядит как заблуждение о том, что OOD относится к категоризации вещей, а не к группированию схожего поведения.
Пит