PDA

View Full Version : گفتگو: بهترین راه برای مدیریت تعداد زیادی if تو در تو



BORHAN TEC
چهارشنبه 24 آبان 1391, 11:37 صبح
سلام
برنامه ای دارم که در آن باید تعداد زیادی if تو در تو داشته باشم که بتوانم کارم را به درستی انجام دهم. به نظر من این کار زیاد جالب نیست. در ضمن if ها تعداد سطوح مختلفی دارد. مثلاً در یک جا 4 تا if تو در تو داریم و در جایی دیگر 2 تا و الی آخر...
if cboMainAct.Text = 'test 1' then
begin
if cboSubAct = 'test 1-d' then
begin
if edt1.text = 'hello' then
// do somethings
else if edt2.text := 'B' then
// do somethings
end
else
if cboSubAct = 'test 1-2' then
begin
if edt1.text = 'hello' then
// do somethings
else
// do somethings
end
else
if cboSubAct = 'test 1-d' then
begin
if edt1.text = 'hello' then
// do somethings
else
// do somethings
end
else
if cboSubAct = 'test 1-2' then
begin
if edt1.text = 'hello' then
// do somethings
else
// do somethings
end
end;
else
if cboMainAct.Text = 'test 2' then
begin
// do somethings
// do somethings
end
else
// other conditions
آیا دوستان تکنیک بهتری را برای حل این مسئله سراغ دارند؟
با تشکر از راهنمایی شما دوستان...

mehdi.mousavi
چهارشنبه 24 آبان 1391, 12:12 عصر
سلام.
در C/C++‎، من قبلا یه بار چنین شرایطی برام پیش اومده بود. اونجا، آرایه ای ساختم که مقادیر مورد نظرم رو در اون قرار دادم (در مثال شما، test1, test1d، test1_test1d_proc و ...) و سپس در حلقه ای، بر اساس این مقادیر، تشخیص دادم که کدوم Pointer به Function رو باید Call کنم (در همین مثال، اگر MainAcct ام test1 باشه، SubAcct ام، test1d باشه، اونوقت میدونم test1_test1d_proc رو باید Call کنم) و اونو Call میکردم. بدین ترتیب، کل کد به یه حلقه تمیز تبدیل شدش که Function های متعددی رو بر اساس ورودی فعلی Call میکرد.

حالا نمیدونم شما در Pascal چنین امکانی دارید یا خیر، اما یکی از راه های حل چنین مسائلی همین Function Pointer هاست.

موفق باشید.

Felony
چهارشنبه 24 آبان 1391, 12:21 عصر
حالا نمیدونم شما در Pascal چنین امکانی دارید یا خیر، اما یکی از راه های حل چنین مسائلی همین Function Pointer هاست.
بله ؛ Method Pointer ها در Object Pascal هم وجود دارند ، توسط توابع کتابخانه RTTI موردی که شما توضیح دادید رو میشه پیاده کرد ، یعنی تابعی نوشت که نام یک متد رو به صورت رشته از ورودی دریافت کنه و بررسی کنه اون متد در کلاس مورد نظر وجود داره یا خیر ، اگر وجود داشت اون رو اجرا کنه :

http://delphi.about.com/cs/adptips2004/a/bltip0204_3.htm

BORHAN TEC
چهارشنبه 24 آبان 1391, 13:29 عصر
حالا نمیدونم شما در Pascal چنین امکانی دارید یا خیر، اما یکی از راه های حل چنین مسائلی همین Function Pointer هاست.
علاوه بر توضیحاتی که آقا ماهان دادند، RTTI موجود در دلفی امکان فوق العاده دیگری هم در این مورد دارد و آن هم این است که شما حتی می توانید به آن توابع آرگومان هم بفرستید. فرقی هم نمیکنه که اون تابع چند تا پارامتر داشته باشه، چون این مورد در دلفی به راحتی قابل مدیریت کردن است. در مورد RTTI هم آقای Robert Love در کنفرانسهای CodeRage 6 سه درس فوق العاده خوب را در همین رابطه ارائه کرده اند که مشاهده آنها را به بقیه دوستان هم توصیه می کنم.

AMIBCT
چهارشنبه 24 آبان 1391, 15:18 عصر
بسته به کاری که می‌خواهید انجام بدهید روش‌های مختلفی برای سازماندهی کد وجود داره

دومطلب زیر رو مطالعه کنید:

کد قابل توسعه: تورفتگی کد (http://amib.ir/weblog/?p=768)
کد قابل توسعه: عبارت‌های شرطی (http://amib.ir/weblog/?p=621)

مجموعه‌ی نوشته‌های من با عنوان «کد قابل توسعه» (http://amib.ir/weblog/?tag=%DA%A9%D8%AF-%D9%82%D8%A7%D8%A8%D9%84-%D8%AA%D9%88%D8%B3%D8%B9%D9%87)

Ananas
چهارشنبه 24 آبان 1391, 16:54 عصر
سلام.
آقای عشایری ببخشیدا فکر میکنم if های مثالتون تکراری هستن و از نظر منطقی بعضیاشون هیچ موقع اجرا نمیشن ولی فرض میگیریم تکراری نباشه ، اگه من باشم به دو روش زیر این کار رو تو دلفی انجام می دم (مثال خودتون با اندکی تغییر تو حالت های ممکن) :

var
bi1, bi2, bj1, bj2, bj3, bj4, ed_txt_hello : Boolean;
s : string;
begin
s := cboMainAct.Text;
bi1 := s = 'test 1';
bi1 := s = 'test 2';
if bi1 then
begin
s := cboSubAct;
bj1 := s = 'test 1-d';
bj2 := s = 'test 1-2';
bj3 := s = 'test 2-d';
bj4 := s = 'test 2-2';
ed_txt_hello := edt1.text = 'hello';
if ed_txt_hello then
begin
if (bj1) then
;
if (bj2) then
;
if (bj3) then
;
if (bj4) then
;
end else begin
if (bj1) then
;
if (bj2) then
;
if (bj3) then
;
if (bj4) then
;
end;
end;
if bi2 then
begin

end else begin

end;
end;

توضیح اینکه شرط هایی که دو حالت بیشتر ندارن در اولویت قرار می دم بعد تو بلاک های بعدی شرط هایی که حالت های بیشتری دارن. و اینکه برای تغییر شرایط if ها کافیه تو یک جا در ابتدا اون رو تغییر بدین و لازم نیست تو کل کد دنبالش بگردین.
و یا با cese .. of :
const
CBO_MAIN_1 = 1; // cboMainAct.Text = 'test 1'
CBO_MAIN_2 = 1 shl 1; // cboMainAct.Text = 'test 2';
CBO_SUB_1 = 1 shl 2; // cboSubAct = 'test 1-d'
CBO_SUB_2 = 1 shl 3; // ??????
CBO_SUB_3 = 1 shl 4; // ?????
CBO_SUB_4 = 1 shl 5;
var
ui64 : UInt64;
begin
ui64 := (CBO_MAIN_1 * UInt64(cboMainAct.Text = 'test 1')) or
(CBO_MAIN_1 * UInt64(cboMainAct.Text = 'test 2')) or
(CBO_SUB_1 * UInt64(cboSubAct = 'test1')) or
(CBO_SUB_2 * UInt64(cboSubAct = 'test2')) or
(CBO_SUB_3 * UInt64(cboSubAct = 'test3')) or
(CBO_SUB_4 * UInt64(cboSubAct = 'test4'));

case ui64 of
CBO_MAIN_1 or CBO_SUB_1 :
begin

end;
CBO_MAIN_1 or CBO_SUB_2 :
begin

end;
CBO_MAIN_1 or CBO_SUB_3 :
begin

end;
CBO_MAIN_1 or CBO_SUB_4 :
begin

end;
CBO_MAIN_2 or CBO_SUB_1 :
begin

end;
CBO_MAIN_2 or CBO_SUB_2 :
begin

end;
CBO_MAIN_2 or CBO_SUB_3 :
begin

end;
CBO_MAIN_2 or CBO_SUB_4 :
begin

end;
end;
end;

خوبی این روش اینه که اگه دو یا چند تا حالت باشن که تو بلاک های متفاوتی هستن ولی دستوری که قراره در صورت درست بودنشون اجرا بشه، یکی هستن، رو می تونم خیلی راحت با هم or کنم. مثلا تو case ... of ای که بالا نوشتم اگه دستور مورد 5 و مورد 8 قراره یکی باشه کافیه اونها رو با هم or کنم.
-------------------------------------------------
و اگه تو C++‎ باشه شاید از مکرو استفاده کنم.