Как улучшить ремонтопригодность функций - PullRequest
1 голос
/ 12 февраля 2010

Я подробно остановлюсь здесь на комментарии, который я сделал к Когда у метода слишком много параметров? , где у OP были незначительные проблемы с чужой функцией, у которой было 97 параметров.

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

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

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

  • Адекватная документация в форме (в актуальном состоянии) комментариев в формате DoxyGen, описывающих природу и характер каждого параметра.
  • абсолютно NO задние махинации с глобальными переменными в качестве скрытых параметров.
  • попытайтесь ограничить параметры шестью или восемью. Если больше, передайте связанные параметры как структуру; если они не связаны, то серьезно пересмотрите функцию. Если ему нужно так много информации, это слишком сложно поддерживать? Можно ли его разбить на несколько более мелких функций?
  • используйте CONST как можно чаще и значимее.
  • стандарт кодирования, который говорит, что сначала идут входные параметры, затем только вывод и, наконец, ввод / вывод, которые модифицируются функцией.
  • Я также #define несколько пустых макросов, чтобы сделать декларации еще проще для чтения:

    # определить вход
    # определить выход
    # определить MODIFY
    bool DoSomething (INPUT int howOften, MODIFY Wdiget * myWidget, OUTPUT WidgetPtr * const nextWidget)

Всего несколько идей. Как я могу улучшить это? Спасибо.

Ответы [ 4 ]

4 голосов
/ 12 февраля 2010

Адресация ваших очков по порядку:

  1. Хорошо спроектированные типы обычно делают комментарии в формате Doxygen пустой тратой времени.
  2. Несмотря на то, что истина, как было сказано («махинации» являются плохими по определению), не все виды использования глобалов действительно настолько плохи, как полагают многие. Если вам нужно передать параметр более четырех раз, прежде чем он действительно будет использован, скорее всего, глобальный будет менее подвержен ошибкам.
  3. Восемь или даже шесть параметров обычно являются чрезмерными. Любое больше двух или трех начинает указывать на то, что функция делает больше, чем одну вещь. Одним очевидным исключением является конструктор, который объединяет ряд других элементов в объект (например, объект адреса, который принимает в качестве входных данных название улицы, номер, город, страну, почтовый индекс и т. Д.).
  4. Лучше указать как «напишите правильный код».
  5. Учитывая возможность параметров по умолчанию в C ++, обычно лучше сортировать в порядке возрастания вероятности использования значения по умолчанию.
  6. Не. Просто не надо! Если неясно, что является входными данными и что является выходными данными, это в значительной степени доказывает, что базовый дизайн фатально ошибочен.

Что касается идей, которые я считаю на самом деле хорошими:

  1. Как следует из первого пункта, сконцентрируйтесь на типах. Как только вы поймете их правильно, большинство других проблем просто исчезнут.
  2. Используйте несколько (даже только одну) центральную тему (ы). Для Лисп все есть список. Для Unix все является файлом (а файлы - это просто потоки байтов). Подражайте этой простоте.

Редактировать: отвечая на комментарии:

  1. Хотя у вас есть кое-что интересное, мой опыт по-прежнему показывает, что документация, созданная с помощью Doxygen (и тому подобное, например, javadoc), практически бесполезна. Теоретически, инструмент не мешает достойной документации, но на самом деле он в лучшем случае редкий.
  2. Глобалы, конечно, могут вызывать проблемы - но я достаточно взрослый, чтобы использовать Фортран еще до того, как он предоставил много альтернатив, и с некоторой осторожностью он действительно был не таким плохим, как полагают многие. Многие истории кажутся, по крайней мере, третьей рукой, и каждый раз, когда их повторяют, добавляется немного «специй». Я видел одну историю, которая звучит очень похоже на преувеличенную версию истории, которую я рассказал пару десятилетий назад или около того ...
  3. Хм ... Форматирование уценки, похоже, не подходит для моих пропущенных номеров.
  4. И снова ...
  5. Мой комментарий был специфичен для C ++, но довольно много других языков также поддерживают параметры по умолчанию и / или перегрузку, и он может также применяться к большинству из них. Даже без этого вызов типа f(param1, param2, 0,0,0); довольно легко увидеть как имеющий параметры по умолчанию. В некоторой степени упорядочение по использованию удобно, но когда вы делаете заказ, который выбираете, не так важно, как просто быть последовательным.
  6. Правда, параметр void * мало о чем вам говорит, но MODIFY void * немного лучше. Реальный тип и последовательное использование const предоставляет гораздо больше информации и проверяется компилятором. Другие языки могут не иметь / использовать const, но они, вероятно, также не имеют макросов. OTOH, некоторые напрямую поддерживают то, что вы хотите - например, Ada имеет спецификаторы in, out и inout.
2 голосов
/ 12 февраля 2010

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

1 голос
/ 12 февраля 2010

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

Например (вырезать и вставить из кода, над которым я только что работал):

void UartEnable(bool enable, int baud);

вместо:

void UartEnable(int baud);
void UartDisable(void);

Другими словами - параметры для передачи «данных», а не «контроля».

0 голосов
/ 12 февраля 2010

Я бы использовал «правило», предложенное дядей Бобом в его книге «Чистый код».

Вот те, которые я помню, я помню:

  • 2 параметра в порядке, 3 плохих, больше нужно рефакторинга
  • Комментарии являются признаком дурных имен. Так что их не должно быть, а назначение функции и параметров должно быть ясно из названий
  • сделать метод коротким. Стремитесь к менее чем 10 строкам кода.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...