Оператор with и декомпозиция методов в Delphi
У нас в команде запрещён к использованию оператор with
. Основная причина в проблемах с надёжность кода с withopen in new window. Существует и другая сторона работы с with
. Часто его применение указывает на плохую организацию кода и переместив код в более адекватное место оператор with
станет просто не нужен. Рассмотрим два примера.
Перемещение кода
Иногда with
используется для формы или датамодуля чтобы установить свойства, возможно, вызывать несколько методов.
procedure TFrmVrachStac.tbDiagrClick(Sender: TObject);
var
FormChart: TFormChart;
begin
FormChart := TFormChart.Create(nil);
try
with FormChart do
begin
Caption := 'Результаты измерений температуры, других исследований и процедур';
LFio.Caption := MTVrachStac.FieldByName('fio').AsString;
LDATE_B.Caption := MTVrachStac.FieldByName('date_b').AsString;
LAGE.Caption := MTVrachStac.FieldByName('age').AsString;
LCHAMBER.Caption := MTVrachStac.FieldByName('chamb').AsString;
LNIB.Caption := MTVrachStac.FieldByName('n_map').AsString;
id_ill := mt_id_ill;
width := Glob_main_form.Width - 100;
height := Glob_main_form.Height - 150;
end;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
В таком случае лучше оформить весь блок кода внутри формы FormChart
в виде метода. А вместо with
сделать вызов этого метода. Ещё лучше когда у вызыващие формы есть специальный интерфейс (не в смысле типа в Delphi, а в смысле API) через который идёт работа с формой.
Декомпозиция функций
Задача — перебрать все записи в датасете. Код может быть примерно такой
procedure TMyForm.MyFunction(ASourceDataSet: TDataSet);
var
LItem: TPMRItem;
Mark1: TBookMark;
begin
Mark1 := ASourceDataSet.GetBookmark;
with ASourceDataSet do
begin
DisableControls;
First;
try
while not eof do
begin
LItem := TPMRItem.Create;
with LItem do
begin
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Оператор with
применяется к датасету чтобы не писать его название несколько раз. В тоже самое время этот оператор создаёт лишнюю вложенность, затрудняет чтение, особенно если смотреть только diff
в svn. В такой ситуации метод можно разделить на два: один проходит цикл по датасету, другой обрабатывает отдельную запись.
procedure TMyForm.MyFunction(ASourceDataSet: TDataSet);
var
LItem: TPMRItem;
Mark1: TBookMark;
begin
Mark1 := ASourceDataSet.GetBookmark;
ASourceDataSet.DisableControls;
ASourceDataSet.First;
try
while not ASourceDataSet.eof do
ProcessOneRow(ASourceDataSet <...> )
2
3
4
5
6
7
8
9
10
11
12
В метод ProcessOneRow
можно даже не передавать весь датасет а только нужные поля. Таким подходом значительно уменьшается вложенность, with
становится не нужен.