Спартан Программирования

мне очень понравилось Джефф должности on Спартанец Программирования. Я согласен, что такой код приятно читать. К сожалению, я не уверен, что это обязательно будет радостью работать.

while (bytes = read(...))
{
   ...
}

while (GetMessage(...))
{
   ...
}

недавно, я выступал за один выражение для каждой строки по более практическим причинам-отладка и поддержка производства. Получение файла журнала из производства, который утверждает исключение NullPointer в "строке 65", которое гласит:

ObjectA a = getTheUser(session.getState().getAccount().getAccountNumber());

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

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

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

какой стиль делать вы адвокат и вы можете рационализировать его в практический смысл?

8 ответов


на Прагматичный Программист Хант и Томас говорят об исследовании, которое они называют законом Деметры, и оно фокусируется на связи функций с модулями, отличными от собственных. Позволяя функции никогда не достигать 3-го уровня в ее соединении, вы значительно уменьшаете количество ошибок и повышаете ремонтопригодность кода.

Так:

ObjectA a = getTheUser (сеанс.getState().getAccount().getAccountNumber ());

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

лучше:


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

"сладкое пятно" находится где-то посередине.


одно выражение на строку.

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


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


Я обычно в лагере" короче-лучше". Ваш пример хорош:

ObjectA a = getTheUser(session.getState().getAccount().getAccountNumber());
obja State = session.getState();
objb Account = State.getAccount();
objc AccountNumber = Account.getAccountNumber();
ObjectA a = getTheUser(AccountNumber);

это компромисс:

objb Account = session.getState().getAccount();
ObjectA a = getTheUser(Account.getAccountNumber());

но я все равно предпочитаю однострочное выражение. Вот анекдотическая причина: мне трудно для перечитывания и проверки ошибок 4-liner прямо сейчас для немых опечаток; в одной строке нет этой проблемы, потому что просто меньше символов.


ObjectA a = getTheUser(session.getState().getAccount().getAccountNumber());

это плохой пример, вероятно, потому, что вы только что написали что-то с головы. Вы присваиваете переменной с именем a типа ObjectA возвращаемое значение функции с именем getTheUser.
Поэтому предположим, что вы написали это вместо этого:

User u = getTheUser(session.getState().getAccount().getAccountNumber());

Я бы сломал это выражение так:

Account acc = session.getState().getAccount();
User user = getTheUser( acc.getAccountNumber() );

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

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

второй фактор, который нужно иметь в виду: нужно ли мне когда-нибудь снова ссылаться на эту сущность в этом контексте?
Если, скажем, я вытаскиваю больше вещей из состояния сеанса, я бы представил SessionState state = session.getState().

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


ремонтопригодность, а с ней, читаемость, является королем. К счастью, "короче" очень часто означает "читабельнее".

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

  • имена переменных: как бы вы описали эту переменную кому-то еще из вашей команды? Вы бы не сказать "numberOfLinesSoFar целое". Вы бы сказали "numLines" или что - то подобное-понятное и короткое. Не притворяйся, сопровождающий не знает кода вообще, но убедитесь, что вы сами могли бы выяснить, что такое переменная, даже если вы забыли свой собственный акт написания. Да, это вроде как очевидно, но это стоит больше усилий, чем я вижу многих кодеров, поэтому я перечисляю его первым.
  • поток управления: избегайте сразу множества заключительных предложений (серия} в C++). Обычно, когда вы видите это, есть способ избежать этого. Общее дело-это нечто как

:

if (things_are_ok) {
  // Do a lot of stuff.
  return true;
} else {
  ExpressDismay(error_str);
  return false;
}

можно заменить на

if (!things_are_ok) return ExpressDismay(error_str);
// Do a lot of stuff.
return true;

если мы можем получить ExpressDismay (или его оболочку), чтобы вернуть false.

другой пример:

  • цикл итераций: чем больше стандартов, тем лучше. Для более коротких циклов хорошо использовать односимвольные итераторы, когда переменная используется только как индекс в одном объекте.

конкретном случае я бы поспорил вот против "правильного" способа использования контейнера STL:

for (vector<string>::iterator a_str = my_vec.begin(); a_str != my_vec.end(); ++a_str)

многословнее и требует перегруженных операторов указателя *a_str или a_str->size() в цикле. Для контейнеров с быстрым произвольным доступом гораздо проще читать следующее:

for (int i = 0; i < my_vec.size(); ++i)

со ссылками на my_vec[i] в теле цикла, что никого не смутит.

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


хорошее объяснение. Я думаю, что это версия general Разделяй и властвуй менталитет.