Принципы программирования: назначение против условий
Я провел некоторое исследование, но не смог найти ответ, который искал, поэтому решил, что решу эту проблему здесь. Я думаю, что лучше продемонстрировать это на примерах, поэтому рассмотрим следующие фрагменты кода:
int delta = 0;
if (some_condition)
delta = 42;
x1 = regular_value1 + delta;
x2 = regular_value2 + delta;
// ...
// where delta is used a lot of times
// basically - if (some_condition == true) => add delta to all variables
// if FALSE - add 0 (thus, effectively not changing anything)
против
int delta = 42;
if (some_condition)
{
x1 = regular_value1 + delta;
x2 = regular_value2 + delta;
// ...
}
else
{
x1 = regular_value1;
x2 = regular_value2;
// ...
}
Например, очень простой сценарий реального мира может быть следующим: допустим, я создаю форму окна, которая может содержать изображение слева, а может и нет. Если изображения нет - создайте все остальные элементы управления формы слева, а если изображение - переместите все остальные элементы управления вправо от изображения (добавьте дельту в X-положение каждого элемента управления).
Я программирую игру на C# XNA (поэтому производительность в некоторой степени важна, но принципы ООП ни в коем случае не должны быть опущены), поэтому мой вопрос - какой код будет работать быстрее при условии, что "some_condition" будет TRUE 50% времени? Кроме того, какой блок кода легче поддерживать / читать?
Я знаю, что это не большая проблема, но я просто пытаюсь привыкнуть писать "лучший" код. Любой вклад и даже личный опыт будут оценены.
Благодарю.
4 ответа
Последний может быть немного быстрее, или они оба могут быть оптимизированы для одной и той же вещи. Это не имеет значения, вы всегда можете изменить его позже, если обнаружите, что это становится проблемой (чего, в данном конкретном случае, определенно не будет - это всего лишь общий совет). Но первое, на мой взгляд, легче читать и поддерживать. Если вы хотели изменить regular_value1
или же regular_value2
Вы должны изменить только в одном месте, а не в двух. Перейти на это.
Это, безусловно, тривиальный случай, и оба могут действительно воплотиться в одном и том же коде. Я бы предложил использовать тот, который легче понять - решение, которое должно основываться на большей части программы, чем вы показали здесь.
Но второе решение может быть быстрее, особенно если "дельта" превращается в константу. Если "some_condition" имеет значение false, добавление не требуется, и optmizer может найти способ ускорить фактические назначения, так что я вижу преимущество в производительности. Я думаю, что лучше всего написать самый быстрый код, который вы можете, если вы не повредите удобству обслуживания. Даже с чем-то с гораздо большей разницей в производительности, чем это, вы реально никогда не вернетесь позже в поисках способов ускорить это. Вы можете также написать код производительности и забыть об этом. Продолжайте в том же духе, и ваш код будет работать быстрее без каких-либо затрат для вас.
Возможно, когда-нибудь профилирование укажет на этот код как на самую медленную точку в вашей программе. Но, скорее всего, вы - и другие - просто примете факт, что код работает с определенной скоростью, и будете использовать его соответствующим образом. Тот факт, что он может быть ускорен и использован в новых местах, скажем, между нажатиями клавиш, не раздражает пользователя.
Разница в производительности здесь незначительна, и в любом случае код, вероятно, никогда не будет использоваться в условиях, критичных к скорости, но я думаю, что кодирование для скорости - это хорошая идея. Это не займет много времени, как только вы привыкнете, и вы знаете, что может сделать ваш код, если он настроен, потому что он уже настроен и делает это.
(По моему опыту, быстрый код и читаемый код - это одно и то же. Если человек может легко понять код, то может оптимизатор, и в наши дни оптимизатор - король. В тех редких случаях, когда мне приходится выбирать, я делайте это для ясности, а не для скорости, если я не знаю, что все зависит от скорости кода. Затем я документирую как сумасшедший искупить.)
Как отмечает @minitech, второй подход может и, безусловно, вызовет проблемы с удобством сопровождения (указывает на размышление: как долго длится жизненный цикл приложения? Будет ли код, который вы пишете, повторно использоваться или потребляться другими?) И читаемость. Учитывая, что вы уже учли эти факторы, я бы порекомендовал вам решить и установить некоторые показатели производительности, которым должно соответствовать ваше приложение.
Как только требования к производительности были четко установлены, вы можете решить, какой подход придерживаться. Принципы ООП и удобочитаемость - мечта каждого программиста, но помните, что как только вы отправляете приложение клиенту, не имеет значения, какой подход вы использовали, единственное, что имеет значение, - это то, что ваше приложение работает должным образом (с точки зрения обоих функциональность и производительность).
Вам нужно будет оценить с заинтересованными сторонами последствия написания "лучшего" и фактического влияния на производительность, которое может вызвать "лучший" код.
Это немного субъективный вопрос, но одна вещь, которая влияет на читабельность (а также на удобство сопровождения), - это количество кода, которое повторяется. В этом случае первый вариант приводит к меньшему количеству кода для обслуживания и чтения (меньше избыточности) и будет моим предпочтительным методом