Сергей Дуплик дата публикации 16-09-2009 11:28 Выносим за скобки
Работая одним из ведущих программистов в группе разработке программных средств, мне часто приходилось просматривать исходные коды программ наших молодых (да и не только молодых) разработчиков. И хоть ребята они во многом были знающие и умеющие решать поставленные перед ними задачи, от недостатка опыта (а иной раз просто от нежелания) они применяли неэффективные конструкции программирования. На некоторых таких конструкциях хотелось бы остановиться и показать, как можно повысить эффективность и быстродействие программы, уменьшить размер используемой памяти, улучшить читаемость кода и повысить удобство работы с исходными текстами программ.
if a > b then
begin
y := f(x);
Massiv1[i] := y;
end
else
begin
y := f(x);
Massiv2[i] := y;
end;
|
|
Здесь вычисляется значение некоторой функции, которое в зависимости от условия заносится то в один, то в другой массив. Напрашивается вопрос: а почему не вынести общий член за операторные скобки begin — end, точно так же, как в математике выносятся за скобки общие множители:
y := f(x);
if a > b then Massiv1[i] := y
else Massiv2[i] := y;
|
|
Исходный код стал более компактным, более понятным и меньшим по размеру. К тому же, вместо простого выражения y:=f(x) здесь может использоваться любое количество операторов. При изменении кода в первом случае нужно не забывать вносить изменения в оба места, что может привести к ошибкам.
Еще одной очень часто встречающейся нехорошей особенностью является многократное повторение в тексте программы одинаковых или похожих участков кода. От нее спасает очень простое правило: все повторяющиеся куски кода должны выноситься в отдельные процедуры или функции. Данный прием, во-первых, позволяет экономить память, заменяя многократное повторение одного и того же кода на многократные вызовы, во-вторых, спасает от ошибок, когда во все повторяющиеся части кода нужно внести одинаковые изменения. Все различия в переменных, объектах и т.п. передаются как параметры данным процедурам и функциям. Незначительные различия в разных частях кода можно реализовать, введя в общую процедуру соответствующие проверки и, при необходимости, соответствующие входные параметры.
Итак, все повторение — за скобки.
Пусть нам надо вывести сообщение об успешности выполнения некоторого действия. В случае успешного завершения выводится сообщение "Выполнение завершено успешно", в случае неуспешного — "Выполнение завершено неуспешно" или "Выполнение завершено с ошибкой".
Самым распространенным вариантом решения данной задачи является следующий. Пусть ErrCode содержит код ошибки выполнения процедуры или 0, если ошибок не возникло. Тогда пишется следующий код:
if ErrCode = 0 then ShowMessage('Выполнение завершено успешно')
else ShowMessage('Выполнение завершено неуспешно');
|
|
Недостаток данного примера заключается в том, что в программе будут сохранены две почти идентичные строковые константы. Объявим строковую переменную s и перепишем его в следующем виде:
if ErrCode <> 0 then s := 'не';
ShowMessage('Выполнение завершено ' + s + 'успешно');
|
|
или
if ErrCode = 0 then s := 'успешно'
else s := 'неуспешно';
ShowMessage('Выполнение завершено ' + s);
|
|
Для второго примера пишем:
if ErrCode = 0 then s := 'успешно'
else s := 'с ошибкой';
ShowMessage('Выполнение завершено ' + s);
|
|
Фактически данный пример является очередным выносом за скобки.
Пусть есть две переменные a и b, значения которых нужно сравнить и логическая переменная IsAbove, которой нужно присвоить true, если a больше b и false в противном случае. Довольно часто это делается следующим образом:
if a>b then IsAbove := true
else IsAbove := false;
|
|
Перепишем эту конструкцию проще, сэкономив некоторое количество памяти:
Скобки здесь использовать не обязательно, они нужны только для повышения читаемости кода.
Одним из наиболее распространенных приемов является неэффективное управление логическими свойствами визуальных компонентов, такими как Enabled и Visible. К примеру (воспользуемся все той же переменной IsAbove):
if IsAbove then
begin
Button1.Enabled := true;
Button2.Enabled := true;
Edit1.Enabled := true;
end
else
begin
Button1.Enabled := false;
Button2.Enabled := false;
Edit1.Enabled := false;
end;
|
|
Напрашивается следующее представление приведенного кода:
Button1.Enabled := IsAbove;
Button2.Enabled := IsAbove;
Edit1.Enabled := IsAbove;
|
|
Рассмотрим еще один пример, когда в зависимости от условия некоторые компоненты должны стать доступными, а некоторые нет.
if IsAbove then
begin
Button1.Enabled := true;
Button2.Enabled := false;
Edit1.Enabled := true;
end
else
begin
Button1.Enabled := false;
Button2.Enabled := true;
Edit1.Enabled := false;
end;
|
|
Перепишем его так:
Button1.Enabled := IsAbove;
Button2.Enabled := not IsAbove;
Edit1.Enabled := IsAbove;
|
|
Если компонентов, которым нужно установить not IsAbove, достаточно много, можно завести логическую переменную IsNotAbove, присвоить ей not IsAbove и использовать в дальнейшем.
Не надо уповать на постоянно растущее быстродействие и объемы памяти. Они растут для того, чтобы программы работали быстрее, чтобы можно было закладывать больше полезных функций, которые могли бы выполняться за то же время, а не как оправдание использования неэффективных приемов программирования.
Приведенные в данной статье примеры — не более чем примеры. Однако примеры эти вполне реально экономят память и упрощают процесс внесения изменений в текст программы, что неоднократно проверено автором.
Обсуждение материала [ 16-10-2009 19:09 ] 48 сообщений |