Как я могу планировать свое программное обеспечение, чтобы избежать чрезмерного переписывания и взаимозависимостей - PullRequest
3 голосов
/ 13 августа 2010

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

Моя цель - 8-битный MCU, поэтому при восходящем подходе я могу лучше использовать аппаратное обеспечение.Если я иду сверху вниз, у меня нет какой-либо структуры для сборки или тестирования / отладки.

Я попытался составить некоторые общие диаграммы и диаграммы для конкретных уровней / драйверов, но я не уверенкак их структурировать, чтобы я мог быть очень систематическим и не пропустить нечетный сигнал, который должен пройти через 2-3 слоя.

Я думаю, что это является причиной степени CS?Я инженер-электрик: P

Ответы [ 7 ]

3 голосов
/ 13 августа 2010

Звучит так, как будто вы на правильном пути. Иногда никакое планирование не помешает вам перепроектировать или реорганизовать части системы на более позднем этапе. Попробуйте некоторые из следующих советов:

  • Храните ваш код в модулях, разделенных логическими функциями.
  • Не дублируйте код, а разрабатывайте повторно используемые методы для общей функциональности.
  • Старайтесь избегать соблазна добавлять хаки для особых случаев. В конце концов это станет неосуществимым. Вместо этого настройте и выполните рефакторинг небольших секций как можно скорее. Попытка сделать большой редизайн в конце будет более трудным.
  • Не пытайтесь чрезмерно проектировать систему с самого начала, так как вы, возможно, просто тратите время, когда переходите к реальной реализации.
  • Сохраняйте нижние уровни как можно более простыми, а затем создавайте более продвинутые возможности.
  • Документируйте свои функции и напишите несколько модульных тестов, особенно после добавления сложных условных операторов.
  • Старайтесь отлавливать ошибки как можно выше в стеке. Например, проверка входных данных и проверка возвращаемых значений. Это облегчит отладку.
3 голосов
/ 13 августа 2010

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

Вот несколько предложений:

  • Относитесь ко всем другим уровням, кроме того, над которым вы работаете, как к запечатанным. Создано другой компанией, разработчиком и т. Д. Не поддавайтесь желанию изменить другой уровень для решения проблемы текущего уровня.
  • Создайте «родственный уровень» для того, над кем вы работаете. Это трудно описать в абстрактном смысле, но допустим, что ваш нижний уровень - это бизнес-уровень, а более высокий - пользовательский интерфейс, создайте ДРУГОЙ уровень пользовательского интерфейса для другого приложения. Теперь наличие двух потребителей одного и того же API может помочь указать, что должно быть на каждом уровне.
  • Попробуйте чередовать порядок, в котором вы работаете на уровнях. Например, в некоторых приложениях я нахожу более полезным сначала спроектировать пользовательский интерфейс, а затем перейти к бизнес-уровню / базе данных, чтобы этот пользовательский интерфейс работал так, как задумано. В других случаях имеет смысл использовать статистику для модели данных и работать с пользовательским интерфейсом. Но дело в том, что вы «думаете» об API по-разному в этих двух сценариях. И, посмотрев на многоуровневый код с обеих сторон, помогает.
  • Опыт имеет значение. Иногда просто сделать ошибку из-за чрезмерно связанного кода - единственный способ научиться избегать этого. Вместо того чтобы планировать, что ваше приложение будет совершенным, планируйте, что оно будет несовершенным. Под этим я подразумеваю сначала настроить быстрый цикл разработки / тестирования / рефакторинга, чтобы вы могли быстро адаптироваться к ошибкам, которые вы не увидите до тех пор, пока не сделаете их. Это также область, где «одноразовые прототипы» пригодятся. Сделайте простой черновой набросок, поучитесь на нем и выбросьте его. Выброшенная часть важна. Даже если это удивительно, начните строить еще один с нуля. Вы неизбежно сделаете его лучше (и, по моему опыту, более организованным) на основе того, что вы узнали из прототипа.
2 голосов
/ 13 августа 2010

Если ваша проблема заключается в том, как создать правильные абстракции, что, кажется, имеет место, я думаю, что самое важное, что вы можете сделать, чтобы выучить (кроме того, чтобы попросить обзоры кода дизайна / прочитать книги / прочитать код) - ДУМАТЬ СЛОЖНО, ПРЕЖДЕ ЧЕМ НАЧАТЬ ПИСЬМЕННЫЙ КОД .

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

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

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

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

Это немного похоже на совет учителя классических шахмат: " сядь на руки ": -)

2 голосов
/ 13 августа 2010

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

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

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

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

1 голос
/ 13 августа 2010

Драйверы поддаются слоистому подходу.

Ваши драйверы могут иметь несколько «классов»:

  • Только вход
  • Только вывод
  • как I, так и O.

У них должен быть стандартизированный интерфейс, например:

GetKnobLevel()
GetNextKeyboardButton

Или, другой подход - это что-то вроде

syscall(DRIVERNUMBER, command)

, помещающее параметры / результаты в указанные регистры.

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

Вот ментальная модель, которую я использую:

---
Application
---
OS
---
Driver communicators
---
drivers
---
hardware

Тамявляется четко определенным интерфейсом без дисперсии между каждым слоем (я продолжаю воображать слоеный пирог с толстой глазурью между слоями ...).Конечно, ОС может не существовать для вас.

Если ваш MCU поддерживает программные и аппаратные прерывания, такие как процессор x86, вы можете использовать их для изоляции драйверов от коммуникаторов драйверов.

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

Если вы общаетесь между уровнями, вы можете использовать глобальную переменную для каждого коммуникационного "канала",и доступ к нему в дисциплинированном виде, используя только функции для доступа к нему.

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

Это подход, который я предпочел в работе со встроенными системами, и он хорошо работает для меня.

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

0 голосов
/ 16 августа 2010

Не для того, чтобы быть слишком бойким, но цитата из Мифический человеко-месяц приходит на ум: «Планируй выбросить одного, ты все равно будешь».

Следствие из которогоэто «Сделай так, чтобы это работало. Сделай это правильно. Сделай это быстро».

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

0 голосов
/ 13 августа 2010

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

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

...