Одна строка функционирует в C? - PullRequest
9 голосов
/ 24 апреля 2009

Что вы думаете об однострочных функциях? Это плохо? Одно преимущество, которое я могу придумать, заключается в том, что он делает код более полным (если вы выберете для него хорошее имя). Например:

void addint(Set *S, int n)
{
     (*S)[n/CHAR_SIZE] |= (unsigned char) pow(2, (CHAR_SIZE - 1) - (n % CHAR_SIZE));
}

Один недостаток, о котором я могу подумать, заключается в том, что он замедляет код (вставка параметров в стек, переход к функции, добавление параметров, выполнение операции, возврат к коду - и только для одной строки?)

лучше ли помещать такие строки в функции или просто помещать их в код? Даже если мы используем их только один раз?

Кстати, я не нашел никаких вопросов по этому поводу, так что извините, если такой вопрос задавался ранее.

Ответы [ 8 ]

25 голосов
/ 24 апреля 2009

Не бойтесь 1-строчных функций!

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

Если это делает код чище и чище, извлеките строку в функцию.

Производительность, вероятно, не будет затронута.

Любой достойный компилятор, созданный за последнее десятилетие (и, возможно, в дальнейшем), автоматически встроит простую однострочную функцию. Кроме того, 1 строка C может легко соответствовать многим строкам машинного кода. Вы не должны предполагать, что даже в теоретическом случае, когда вы берете на себя все накладные расходы при вызове функции, эти накладные расходы значительны по сравнению с вашей «одной маленькой строкой». Не говоря уже о значительном влиянии на общую производительность вашего приложения.

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

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

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

Может быть, ваша 1-я строка должна быть больше строк.

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

8 голосов
/ 24 апреля 2009

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

Я настоятельно рекомендую , в каждом вопросе такого рода, посмотреть (купить, одолжить, (не) скачать (бесплатно)) на эту книгу: Роберт К. Мартин - Чистый код . Это книга, на которую должен взглянуть каждый разработчик.

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

5 голосов
/ 24 апреля 2009

Поскольку в вашем примере используется синтаксис C (++), вы можете прочитать о встроенных функциях , которые исключают накладные расходы на вызов простой функции. Это ключевое слово является только рекомендацией для компилятора, и оно может содержать не все функции, которые вы отметили, и может включать встроенные неотмеченные функции.

В .NET JIT встроит методы, которые, по его мнению, являются подходящими, но вы не можете контролировать, почему или когда это происходит, хотя (насколько я понимаю) сборки отладки никогда не будут встроенными, поскольку это остановит сопоставление исходного кода. скомпилированное приложение.

5 голосов
/ 24 апреля 2009

Если используется более одного раза, определенно сделайте это функцией, и пусть компилятор сделает встраивание (возможно, добавив «inline» к определению функции). (<Обычный совет по преждевременной оптимизации приведен здесь>)

1 голос
/ 24 апреля 2009

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

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

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

0 голосов
/ 24 апреля 2009

Иногда неплохо использовать препроцессор:

#define addint(S, n) (*S)[n/CHAR_SIZE] |= (unsigned char) pow(2, (CHAR_SIZE - 1) - (n % CHAR_SIZE));

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

#define addint(S, n) do { \
    unsigned char c = pow(2, (CHAR_SIZE -1) - (n % CHAR_SIZE)); \
    (*S)[n/CHAR_SIZE] |= c \
  } while(0)
0 голосов
/ 24 апреля 2009

На каком языке? Если вы имеете в виду C, я бы также использовал квалификатор inline. В C ++ у меня есть опция inline, boost.lamda или и продвижение собственной поддержки C ++ 0x для lamdas.

0 голосов
/ 24 апреля 2009

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

...