Jak poprawić czytelność kodu


(Mr Hektor) #1

Witam, powiedzmy, że mam do wykonania wiele praktycznie identycznych instrukcji typu:

Label1.Caption := IntToStr(StrToInt(Edit1.Text) + StrToInt(Edit2.Text));

Label2.Caption := IntToStr(StrToInt(Edit3.Text) + StrToInt(Edit4.Text));

Label3.Caption := IntToStr(StrToInt(Edit5.Text) + StrToInt(Edit6.Text));

Widać, że będą się tylko zmieniały numerki przy Captionie i Edicie. Jak zapisać to jakoś krócej w czytelniejszej formie ? Bez sensu jest pisanie tego po 50 razy zmieniając tylko 3 numerki, utrudnia to znalezienie błędów to maksimum. Dzięki z góry. :slight_smile:


(nnick) #2

Dodać elementy do listy a potem lecieć pętlą po elementach listy?


(Mr Hektor) #3

Mozę jakiś przykład w postaci kodu dla zobrazowania bym prosił.


(Pablo_Wawa) #4

Musisz przerobić swój kod tak, żeby elementy formatki takie jak Label oraz Edit były umieszczone w tablicy, a nie jako osobne, kolejno iterowane zmienne. Wtedy Twój kod mógłby wyglądać tak:

for i=1 to 3 do

  Label[i].Caption := IntToStr(StrToInt(Edit[2*i-1].Text) + StrToInt(Edit[2*i].Text));

EDIT: poprawiłem kod tak, by zgadzał się z tym co sam podałeś.


(Mr Hektor) #5

Ah, dzięki, wiec rozwiązanie kryje się w tablicy. Bo próbowałem tam powstawiać zmiennie i zwiększać je pętla, ale nie ruszało. Teraz na pewno będzie śmigać, dzięki.


([alex]) #6

Ja bym Edity dał w dwuwymiarowej tablice, wtedy:

for i=1 to 3 do Label[i].Caption:=IntToStr(StrToInt(Edit[i,0].Text) + StrToInt(Edit[i,1].Text));

Poza tym po napisaniu dodatkowej procedury:

procedure Form1.Add(Label:TLabel;EditA,EditB:TEdit);

begin

  Label.Caption:=IntToStr(StrToInt(EditA.Text)+StrToInt(EditB.Text));

end;


for i=1 to 3 do Add(Label[i],Edit[i,0],Edit[i,1]);

(soanvig) #7

ZAWSZE staraj się stosować do DRY a poprawisz czytelność kodu bardzo znacząco :slight_smile:


(Enterbios) #8

Tak szybko wytłumaczę że DRY to jedna z zasad clean code co w rozwinięciu znaczy Don’t repeat yourself (nie powtarzaj się) i jest to jedna ze złotych zasad tworzenia oprogramowania.

Co do problemu -> powinieneś utworzyć klasę/strukturę która zgrupuje logicznie label z dwoma polami edit. Wtedy na tym poziomie abstrakcji który pokazujesz tutaj wystarczy Ci jedna tablica/lista elementów owego typu, a do realizacji zadania jeden foreach.

Jeśli przyjmiesz propozycje trzymania tego w tablicach - zacierasz relacje między tymi elementami i utrudnisz tym samym komuś a może nawet sobie czytanie tego kodu za jakiś czas.


(Mr Hektor) #9
implementation

var

tab:array[1..10] of TLabel;



{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);

var

i : integer;

begin

for i := 1 to 10 do


tab[i]:=TLabel.Create(Self);

       With tab[i] do

            begin

              Left:=i*30+100;

              Top:=i*30+100;

              Caption:='Ohgyvu';

              Parent:=self;

              Font.Size:=16;

            end;

end;

end.

Dlaczego to nie działa ? Tzn zamiast zapełnić okno 10-cioma labelami wywala błąd (acces violation…).


([alex]) #10
type

  TForm1 = class(TForm)

    procedure FormCreate(Sender: TObject);

  private

    Tb:array[0..9]of record LbC:TLabel; EdA,EdB:TEdit; end;

    procedure EditChange(Sender:TObject);

  public

    { Public declarations }

  end;


var

  Form1: TForm1;


implementation


{$R *.DFM}


procedure TForm1.FormCreate(Sender: TObject);

var I:Integer;

var Lb:TLabel;

var Ed:TEdit;

var S:String;

begin

  for I:=Low(Tb) to High(Tb) do

  begin

    S:=IntToStr(I);

    Ed:=TEdit.Create(Self);

    Ed.Top:=I*30+100;

    Ed.Left:=50;

    Ed.Name:='EdA'+S;

    Ed.Text:='0';

    Ed.Tag:=I;

    Ed.OnChange:=EditChange;

    Ed.Parent:=Self;

    Tb[I].EdA:=Ed;

    Ed:=TEdit.Create(Self);

    Ed.Top:=I*30+100;

    Ed.Left:=250;

    Ed.Name:='EdB'+S;

    Ed.Text:='0';

    Ed.Tag:=I;

    Ed.OnChange:=EditChange;

    Ed.Parent:=Self;

    Tb[I].EdB:=Ed;

    Lb:=TLabel.Create(Self);

    Lb.Top:=I*30+100;

    Lb.Left:=450;

    Lb.Name:='LbC'+S;

    Lb.Caption:='0';

    Lb.Font.Size:=16;

    Lb.Parent:=Self;

    Lb.Tag:=I;

    Tb[I].LbC:=Lb;

  end;

end;


procedure TForm1.EditChange(Sender:TObject);

var T:Integer;

begin

  T:=TEdit(Sender).Tag;

  try

    Tb[T].LbC.Caption:=IntToStr(StrToInt(Tb[T].EdA.Text)+StrToInt(Tb[T].EdB.Text));

  except

    Tb[T].LbC.Caption:='Błąd';

  end;

end;

(Mr Hektor) #11

Dzięki, już znalazłem błąd, po prostu zapomniałem tam o jednym begin-end. :slight_smile: