SalarSoftwares logo

خوش آمدید. در این سایت می توانید ابزارهای دلفی و نرم افزارها را دریافت کنید.

صفحه اصلی | مقالات | سوال و جواب | Downloads | Beeper help | جستجو | تصاویر برنامه ها | تبلیغات | تماس با ما | وبلاگ شخصی

برنامه نویسی ساخت یافته
بخش 1 : نوشتن برنامه های منسجم

مقدمه:

در مقابل برنامه های منسجم برنامه های اسپاگتی (Spaghetti) قرار دارند. اسپاگتی به معنای ماکرونی است و این اصطلاح به این علت به کار برده می شود که تمام بخش های برنامه به طور نا صحیح با هم در ارتباط هستند. یعنی برای مثال کلاس TClass1 از یک مغیر عمومی از نوع TClass2 برای تنظیم مقادیر خود استفاده می کنند و  به آن وابسطه هستند. مانند کد زیر:

Type
    Tclass1=class
        SumResult:Integer;
        procedure Calculate;
        Val1,Val2:integer;
    End;
    TClass2=class
        fResult:Integer;
        function DoSum(sum1, sum2:integer): integer;
    End;
Var
    fClass1:TClass1;
    fClass2:TClass2;
impelemention

function TClass2.DoSum(sum1, sum2:integer): integer;
begin
    fClass1:=TClass1.Create;
    fClass1.Val1:=sum1;
    fClass1.Val2:=sum2;
    fClass1.Calculate;
    Result:=fClass1.SumResult;
    fClass1.Free;
end;
procedure Tclass1.Calculate;
begin
    SumResult:=Val1+Val2;
    fClass2.fResult:=SumResult;
end;

این کد به شدت در معرض شکست قرار دارد ، چون هر دو کلاس به هم وابسته بوده و با تغییری اندک در یکی از آنها باید دیگری را نیز اصلاح و به روز رسانی کرد. علاوه بر این هنگامی که می خواهید از یکی از کلاس ها استفاده کنید با هر دو متغیر fClass1 و fClass2 ایجاد شده و آماده باشند در غیر این صورت با یک خطا روبرو خواهید شد.

در چنین برنامه هایی با تغییری اندک در هر یک از کلاس ها ( یا فرم هایی مانند این کلاس ها) باید تغییرات در هر دو اعمال شوند که البته زمان زیادی را خواهد گرفت و با بزرگتر شدن پروژه این مشکل حاد تر خواهد شد.

جنگ با ماکرونی!:

یک راه حل بسیار مناسب نوشتن فرم ها ، کلاس ها و در صورت امکان رویه های مستقل است. یعنی باید به صورت مستقل عمل نمایند و از هیچ کلاسی استفاده ننمایند. این بهترین حالت است؛ اما معمولا این چنین کلاس هایی کمتر استفاده  می شوند.

اگر کلاسی از سایر اشیا استفاده می کند نباید از متغیر های عمومی آن شیئ استفاده کند. برای رفع این مشکل می توان آن اشیاء را به صورت پاراکتر به ایجاد کننده آن () ارسال کرد. در این صورت کلاس مد نظر این شیئ را در یک متغیر برای استفاده ذخیره نماید.
به این مثال توجه فرمایید:

TMyClass = class
private
    fBitmap:TBitmap;
public
    constructor Create(bmp:TBitmap);
    procedure DrawBorder;
end;
implementation
constructor TMyClass.Create(bmp: TBitmap);
begin
    fBitmap:=bmp;
end;
procedure TMyClass.DrawBorder;
begin
    fBitmap.Canvas.Pen.Width:=1;
    fBitmap.Canvas.Rectangle(fBitmap.Canvas.ClipRect);
end;

این نمونه یک کلاس کارآمد است. در این مثال bmp به عنوان پارامتر به ایجاد کننده TmyClass ارسال می شود. سپس برای استفاده های بعدی در متغیر داخلی fBitmap ذخیره مشود. fBitmap آدرس bmp ارسالی را در خود ذخیره کرده و هنگام استفاده از همانند آن است که از خود متغییر bmp استفاده می کنید.
بدین ترتیب هیچ گونه ارجاع و استفاده مستقیمی به خارج از کلاس صورت نمی گیرد. این واقعا عالی است!

منسجم کردن رابطه فرم ها:

به طور معمول هر فرمی را که به پروژه اضافه میکنید دستور Application.CreateForm(TFormClass, FormVar); به فایل پروژه تان (dpr) افزوده می شود. این دستور سبب خواهد شد که به محض اجرای برنامه فرم ایجاد شود. برای برنامه های کوچک شیوه مناسبی است. اما برای پروژه های بزرگ مشکل ساز خواهد بود.
برای زمانی که چندین فرم در پروژه وجود دارد می توان در زمان نیاز فرم را ایجاد کرده ، نمایش داده و سپس حافظه اش را آزاد کنید. این روش بسیار مفیدی است.
برای مثال یک دکمه در روی TForm1 و 2 دکمه در روی TForm2 قرار دهید. خصوصیت ModalResult یکی از دکمه های فرم2 را برابر mrOK قرار دهید. سپس در فرم1 در رویداد کلیک Button1، کد زیر را وارد نمایید:

procedure TForm1.Button1Click(Sender: TObject);
var frm2:TForm2;
begin
    frm2:=TForm2.Create(Application);
    frm2.ShowModal;
    frm2.free;
end;

البته این مثال ناقص است ولی به خوبی کار خواهد کرد. برای اینکه بدانید چه دکمه ای در فرم 2 فشرده شده است از کد زیر استفاده کنید.

procedure TForm1.Button1Click(Sender: TObject);
var frm2:TForm2;
begin
    frm2:=TForm2.Create(Application);
    if frm2.ShowModal=mrOK then
        messageDlg('Hey! you pressed a button',mtInformation,[mbOK],0);
    frm2.free;
end;

در این مثال ShowModal فرم دوم را نمایش خواهد و تا زمانیکه دکمه ای که  ModalResult آن تنظیم شده، فشرده نشود فرم بسته نخواهد شد. پس از بسته شدن فرم2 مقدار برگشتی ShowModal بررسی خواهد شد و صورت صحیح بودن شرط پیغامی صادر خواهد شد.

در این مثال فرم1 تا بسته شدن فرم2 غیر فعال خواهد بود. حال اگر نیاز باشد که هر دو فرم به طور همزمان در دسترس و فعال باشند چه می توان کرد؟ پاسخ این سوال استفاده از روشی است که در ادامه مورد بررسی می باشد.

ابتدا باید متغیری از نوع فرم دوم ایجاد کنید. سپس مس میتوانید با فراخوانی متد show فرم2 را نمایش داد. در این صورت هر دو فرم به صورت همزمان قابل دسترسی هستند.
اما مشکل اینجاست که با بستن فرم2 حافظه مربوط به آن آزاد نخواهد و آن همچنان در حافظه باقی خواهد ماند. برای رفع این مشکل نیز می توان  با تخصیص دادن مقدار caFree به پارامتر Action در رویداد OnClose مربوط به فرم2 برطرف نمود.

procedure TForm1.Button1Click(Sender: TObject);
var frm2:TForm2;
begin
    frm2:=TForm2.Create(Application);
    frm2.Show;
end;

و در فرم دوم:

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;

البته این مثال ناقصی است که می توانید نقایص آن را مرتفع سازید. تخصیص مقداد caFree به Action سبب آزاد سازی حافظه آن و تخصیص مقداد caHide فقط باعث مخفی شدن آن خواهد شد و فرم همچنان  در حافظه می باشد.

بخش دوم برنامه نویسی ساخت یافته به زودی در سایت قرار خواهد گرفت.

نویسنده: سالار خلیل زاده
 

Titles

صفحه اصلی
Up
سوال و جواب
Downloads
Beeper help
جستجو
تصاویر برنامه ها
تبلیغات
تماس با ما
وبلاگ شخصی

جستجو در سایت

لینک سایر سایت ها


 صفحه اصلی | مقالات | سوال و جواب | Downloads | Beeper help | جستجو | تصاویر برنامه ها | تبلیغات | تماس با ما | وبلاگ شخصی
در صورت بروز هر گونه مشكل در استفاده از نرم افزار هاي اين سايت, مشكل را با مدير اين سايت در ميان بگذاريد.

Creative Commons License
This work is licensed under a Creative Commons Attribution 2.5 License.

آخرين به روز رسانی: آمار بازدید: