ورود

نسخه کامل مشاهده نسخه کامل : Message In N_Tier



shotok
29-10-2012, 20:37
بسم الله الرحمن الرحيم با سلام معمولا در کلاس ها در پروژه هاي چند لايه چگونه پيغام ها رو کنترل ميکنند؛ از چه نوعي ميگيرند و با اون پيغام مورد نظر رو به لايه بالايي ميفرستند. با سپاس فراوان

_H2_
30-10-2012, 02:26
سلام
سوال و نکته سنجی بسیار بجایی است.
باید به مفهوم لایه ها دقت کرد و نباید هرکجا خواستیم هر کاری انجام دهیم و فقط از لایه بندی اسمش بماند ...
(گرچه افسوس این دقت نظرها در جامعه حرفه ای ما خیلی خریداری ندارد ...)
روش های گوناگون و بسیار خوب و مطمئنی وجود دارد.

- پیام ها و ارتباطات قابل انتقال به اول کد:
از این جمله میتوان به انجام اعتبار سنجی های UI قبل از ارسال به لایه پایین اشاره کرد یا مواردئی که کاربر باید بین چند حالت انتخابی داشته باشد و...

این ساده ترین موردی است که حتماً به آن فکر کرده اید...

مثلاً ...
برای پرسش اطمینان حذف یک مورد می توان در همان لایه UI انجام شود و سپس متد اصلی لایه های پایین تر اجرا شود.

یا در حالتی که با چند وضعیت مختلف روبرو هستیم میتوان Enum ای در لایه پایین تعریف کرد که مقدار آن از بالاترین لایه UI اخذ و ارسال شود...


برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

که State از پرسش ها و ارتباطات مختلف اولیه UI پر خواهد شد.
ولی باید دقت داشت که در این کار افراط نشود.
چون تعریف enum منجر به استفاده از swith case خواهد شد و این میتواند دشمنی با پلی مورفیزم تعبیر شود ! که اصلا خوب نیست.

در حالت حداقلی (نه switch case و نه polymorphism) شاید بتوان چند متد برای هر کدام از این امور داشت که موجب تولید متدهایی با کدهای کمتر میشود.
(همواره تلاش کنید متدهای با کدهای حجیم و طولانی را به قطعات کوچکتر خرد کنید)

در خصوص روش های جالب تر دیگر در روزهای آتی خواهم نوشت ...

shotok
30-10-2012, 11:47
بسم الله الرحمن الرحيم با سلام از اينکه پاسخ داديد سپاسگزارم. لطفا براي روشن تر شدن مطلب مثالي از مقدار دهي State در لايه هاي UIو مياني بياوريد. با سپاس فراوان

shotok
30-10-2012, 14:32
بسم الله الرحمن الرحيم با سلام منظورتون اينه که مثلا لايه UI بعد از اينکه متدي از لايه مياني رو فراخواني کرد مقدار state رو بررسي کنه و اگه state=0 بود آنگاه پيغام بده که بر فرض مثال عمليات با موفقيت انجام نشد. با صحيح بودن فرض بالا مگر نبايد هر لايه اطلاعي از جزئيات لايه پاييني نداشته باشد و تنها از اون استفاده کنه؟ منظورتون رو از جمله "پیام ها و ارتباطات قابل انتقال به اول کد:" متوجه نشدم. با سپاس فراوان

senaps
30-10-2012, 17:51
سلام....
من هم نگرفتم که چی شد و البته یه چیز جالب برام پیش اومد که میخوام بپرسم در ادامه.....

کاری که من میکنم اینه که اول همه‌ی چیزایی که تو رابط کاربر میشه بررسی کرد رو بررسی میکنم و بعد پارامتر ها رو به تابع در لایه‌ی پایین تری میفرستم...(که همون لایه‌ی لاجیکالم در خود برنامه باشه؟!) و بعد کلاس ها و کدهای اون قسمت، پارامتر هایی نهایی رو برای رابطم با دیتابیس می‌فرستن که جدیدا دیگه سرویس هایی روی وب میباشه!!! نمیدونم چقدر درسته...


این مثال اینام که زده شد، برای من یه شبهه ایجاد کرد....

ایا من میتونم مقادیر چند باکس مختلف(تکست، رادیو و چک باکس و ...!!) رو داخل اینام ذخیره کنم و بعد از اینها برای کوری گرفتن استفاده کنم؟! مثلا من 12 تا تکست باکس دارم که همه دسته بندی شدن و من میخوام کاربر هرچقدر از اینها رو بیشتر وارد کرد، جست‌و‌جوش دقیق تر باشه و خوب، هرچی کمتر بود یه جست‌و‌جوی کلی تر بگیره....؟!!! نمیدونم اگر تونسته باشم منظورم رو درست بفهونم؟!!!
در این روش باید از چی استفاده کرد؟! و ایا اصولا در بحث این سواله یا نه؟!!

_H2_
02-11-2012, 17:07
سلام

مثالي از مقدار دهي ... در لايه هاي UIو مياني بياوريد

من هم نگرفتم که چی شد
شما میتوانید یکسری فرآیند های تصمیم گیری را با enum ها کنترل کنید.

در واقع برای به دو سبک شمارشی یا بیتی میتوان از یک enum استفاده کرد و کمبود های یک bool را جبران کرد.
شمارشی برای حالتی که بیشتر دو حالت true/false نیاز باشد که در نهایت موجب استفاده از switch case در جایی از کد میشود.
و
بیتی برای حالتی که بیش از یک bool نیاز باشد
یعنی کد اول بجای کد دوم:

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

==============

مثال عملی:
در برنامه های حسابداری قالباً لازم میشود همراه ثبت یک "فاکتور" یک "سند حسابداری" هم صادر شود...

گرچه راه حل های متفاوتی وجود دارد ولی شاید پیمانکار یا کارفرمائی ترجیح بدهد طی MessgageBox ای این مورد پرسیده شود...


برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

در واقع بجای آنکه درون لایه پایینی این پرسش انجام شود، قبل از آن در لایه بالا پرسیده شده و نتیجه تصمیم به لایه پایین ارسال شده تا لایه پایین دیگر نیازی به تعامل با کاربر نداشته باشد.

تا اینجا درست!

حالا فرض کنید می خواهیم در خصوص صدور "قبض انبار" هم بپرسیم.
یعنی میخواهیم بدانیم با "صدور فاکتور" باید "سند حسابداری" یا "قبض انبار" هم (جداگانه) صادر شود یا خیر؟
اینجا دیگر نمیتوان یک bool به لایه پایین تحویل داد، اینجا دو bool یا یک enum لازم است.

یعنی میتوان یک MessgaeBox سفارشی با دو CheckBox ساخت که دو مورد فوق را پرسید و نتیجه را در یک enum به لایه پایین پاس داد.

==============

البته ...
این فقط یک مثال برای نحوه کاربرد بود.
وگرنه همانطور که بیان شد مثال فوق و هر مثال دیگری راه حل های متفاوتی میتواند داشته باشد.
از جمله در تنظیمات سراسری برنامه بله/خیر آن مشخص گردد
یا
پس از ثبت فاکتور دکمه ای برای "ثبت سند" و "ثبت قبض" ظاهر گردد و...
یا
عملیات "ثبت سند" و "ثبت قبض" دو متد مستقل باشند که از همان لایه UI فراخوانی شوند
و...

ولی تمام این روش ها تغییری در مفهوم اولیه بیان شده ایجاد نمیکند.
در واقع هدف از بیان enum آن بودکه می میتوانیم کمبودهای bool را با enum جبران کنیم و فکر خودمان را در حصار bool (دوحالته) محدود نکنیم.
روش اول: پرسش اولیه برخی موارد و ارسال به لایه پایین تا لایه پایین تعامل با کاربر نخواهد.

==============

چند مورد دیگر را برای یک تنفس کوتاه(!) و تفکیک بهتر مطالب در پست بعدی پاسخ میدهم ...

_H2_
02-11-2012, 17:42
سلام


کاری که من میکنم اینه که اول همه‌ی چیزایی که تو رابط کاربر میشه بررسی کرد رو بررسی میکنم و بعد پارامتر ها رو به تابع در لایه‌ی پایین تری میفرستم...(که همون لایه‌ی لاجیکالم در خود برنامه باشه؟!) و بعد کلاس ها و کدهای اون قسمت، پارامتر هایی نهایی رو برای رابطم با دیتابیس می‌فرستن که جدیدا دیگه سرویس هایی روی وب میباشه!!! نمیدونم چقدر درسته...

بله همه این موارد درست است...



ایا من میتونم مقادیر چند باکس مختلف(تکست، رادیو و چک باکس و ...!!) رو داخل اینام ذخیره کنم و بعد از اینها برای کوری گرفتن استفاده کنم؟! مثلا من 12 تا تکست باکس دارم که همه دسته بندی شدن و من میخوام کاربر هرچقدر از اینها رو بیشتر وارد کرد، جست‌و‌جوش دقیق تر باشه و خوب، هرچی کمتر بود یه جست‌و‌جوی کلی تر بگیره....؟!!! نمیدونم اگر تونسته باشم منظورم رو درست بفهونم؟!!!
در این روش باید از چی استفاده کرد؟! و ایا اصولا در بحث این سواله یا نه؟!!

این مورد هم مشابه مورد قبلی بیان شده شما، همه و همه حالتی هستند که میتوان در اول کد فراخوانی لایه پایین تعبیه کرد
(((ولی مواردی پیش خواهد آمد که نمیتوان در اول (یا آخر) کد فراخانی لایه پایین کار را تمام کرد.)))

البته طبیعتاً (و همانطور که حتماً بهتر مطلع هستید) اگر بخواهید چندین مقدار شامل string, Datetime, int و... و... را به لایه پایین پاس دهید میتوانید و (شاید بهتر است) از یک class یا struct کمکی استفاده کنید....
در حالت حداقل حداقل یک ظرفی شبیه این میتوانید داشته باشید.

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
البته شاید...
بتوانید از کلاس های پیش ساخته لایه "دیتابیس" هم صرفاً برای انتقال استفاده کنند.
مخصوصاً موارد تولیدی ADO.Net Entity Framework بسیار مناسب تر هستند.
فوقش برای لایه بندی بیشتر و نیز افزودن امکانات میتوانید از کلاس هاس سطرهای جداول در لایه های بالا وراثت بگیرید
و...



منظورتون اينه که مثلا لايه UI بعد از اينکه متدي از لايه مياني رو فراخواني کرد مقدار state رو بررسي کنه و اگه state=0 بود آنگاه پيغام بده که بر فرض مثال عمليات با موفقيت انجام نشد

تا حدودی!
این مورد بیان شده شما میشود، "پیام ها و ارتباطات قابل انتقال به آخر کد"

- پیام ها و ارتباطات قابل انتقال به آخر کد
یعنی میتوان یکسری از پیام ها مانند نتیجه عملیات که خودتان اشاره کردید را به آخر فراخوانی کد در UI واگذار کرد که روش های آن خیلی شبیه مورد بیان شده قبلی است.
میتوان در یک bool دوحالته یا یک enum چند حالته نتیجه عملیات را به لایه بالاسری برگرداند تا لایه بالا سری در خصوص چشم پوشی یا اطلاع رسانی مناسب به کاربر تصمیم بگیرد.




منظورتون رو از جمله "پیام ها و ارتباطات قابل انتقال به اول کد:" متوجه نشدم

یعنی UI هایی که میتوان نشان دادن آنها را قبل از فراخوانی کد لایه پایین انجام داد...
نوع دیگر میشود نمایش UI هایی پس از اجرای عملیات لایه پایین، مانند آنچه خودتان اشاره کردید و به موفق/ناموفق بودن عملیات اشاره داشت.

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

==============

عیدتان مبارک و شب خوش.

shotok
05-11-2012, 13:52
بسم الله الرحمن الرحيم با سلام از جناب _H2_ بخاطر مطلب مفيدشون تشکر ميکنم؛‌ سوالي از خدمتتون دارم و اون اينکه تا چه حد اين موضوع به نظر و سليقه فرد بستگي داره و تا چه حد اصول دخيل هستند؟ لطفا مقاله يا پياده سازي هايي که در اين باره انجام شده و مورد تائيد شما مي باشد رو مطرح بفرمائيد تا مطالعه بيشتري راجع به اين موضوع داشته باشيم. با تشکر فراوان از وقتي که ميگذاريد.

_H2_
10-11-2012, 11:43
سلام
انتقال استثناها:

چیزی که ما معمولاً با نام خطا در برنامه میشناسیم در واقع یک مکانیزم انتقال اطلاعات بین لایه های مختلف است.
که با هوشمندی زیبا در دات نت به جای کلمه Error به آن کلمه وسیع تر Exception را داده اند.

این شیوه انتقال در مواردی استفاده میشود که لایه پایین به دلیلی نتواند کارش را به درستی انجام دهد و بخواهد این مسئله و دلایل آن را به لایه بالاسری اطلاع دهد.
ابتدا اجازه دهید یک شیوه دیگر برخورد با این مسئله را بررسی کنیم تا از مشکلات و ایرادات آن روش، محاسن و جذابیت های روش Exception را بهتر درک کنیم. تا کمتر از آن بترسیم! و به آن به چشم یک ناجی و امکان بسیار کارآمد و مطمئن پی ببریم.

پس میخواهیم راه حل کاملی پیدا کنیم تا اگر متدی در لایه پایین به دلایلی نتوانست کارش را صحیح انجام دهد بتواند آن را به لایه بالا اعلان کند و لایه بالا هم بتواند خودش به تصمیم خودش و شیوه مناسب آن را به کاربر اعلان کند یا نکند.
دقت کنید که لایه آخر میتواند یک WinForm, WpfForm, ... WinService, WebService, ... XNA, ... WebSite و... باشد که فقط و فقط لایه آخر میداند چطور باید پیغام مناسب را نمایش دهد.
ضمن اینکه این مفهوم میتواند بین لایه های میانی (غیر آخر و UI) هم کاربرد داشته باشد.

=====

روش ناقص و مشکل دار:

در ساده ترین دید تشکیل یک enum میدهم

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

خوب مشکل من را که حل کرد! پس چه ایرادی دارد؟!
1) switch case عریض و طویل همیشه از منظر دید شی گرایی مطرود و بد است و باید شیوه های مناسب شی گرایی تعویض شود.

2) اگر Func1 خودش مقدار بازگشتی داشته باشد چه؟
بله میدانم که حداقل سه راه متفاوت میتوان بیان کرد، ولی قبول دارید هر سه راه کمی قشنگ نیستند و مناسب لفظ کثیف کاری هستند؟!

3) اگر Func1 خودش چند تابع دیگر را اجرا کند که هر کدام هم یک سری خطای عریض و طویل مخصوص خود را داشته باشند چه؟
آنگاه حتماً باید enum نتیجه خروجی Func1 شامل جمیع enum های توابعی که صدا کرده باشد؟؟؟!
افتضاح زمانی بالا میگیرید که آن چند تابع هم خودشان توابع دیگری را اجرا کنند...!
و حتماً بعدش هم با تغییر کدهای داخل یک تابع باید enum آن و کلیه enum های توابع بالاسری را اصلاح کنم ... ! چه شود ... !
پیشنهاد میکنم مطمئن شوید که این بند (3) را حداقل متوجه شده اید!

4) اگر یک خطا اطلاعات اضافه داشته باشد چه؟
مثلاً "فاکتور فروش" در سیستم ثبت نشده چون "یک کالای خاص" در فهرست فاکتور، موجودی اش در انبار "صفر" بوده.
خوب نمیخواهید به کاربر بگویید "کدام کالا" بوده؟
پس در یک دید کلی باید بتوان همراه یک خطا اطلاعات اضافه هم به لایه بالاتر ارسال کرد.

و...

هر روشی (غیر از Exception) که پیشنهاد کنید مشکلات این تیپی را خواهد داشت.
با تنفسی کوتاه در ساعت آتی مطلب را ادامه خواهیم داد...

_H2_
10-11-2012, 22:55
سلام
ادامه مطالب ...
روش صحیح: (Exception)

Exception ها راه حلی بر مبنای اصول شی گرایی برای برخورد با مسئله فوق الذکر هستند.
بدلیل فرصت کم و عدم تکرار مطالب موجود، فرض میشود دوستان مطلب زیر را قبلاً مطالعه کرده اند:
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

میدانم طولانی میشود ولی یا من باید اینجا دوباره بنویسم و شما بخوانید یا باید ارجاع بدهم و شما انجا بخوانید، در هر صورت شما باید بخوانید...!
لطفاً مطالعه شود و سپس مطالب بعدی را بخوانید.

=====

ادامه ...

پس طبق مطالب قبل متوجه شدیم Exception در واقع کلاس هایی هستند که خطاها را حمل میکنند و نیازی به تنظیم پارامتر خاصی در ورودی یا خروجی تابع ندارند.

اگر دقت کنید متوجه میشوید که این شیوه استاندارد دات نت در توابع خودش هم است.
به عنوان نمونه دستور زیر را اجرا میکنیم:

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

این کد میتواند از انواع پروژه های مختلف فراخوانی شود.
ولی رویکرد WriteAllText وقوع Exception برای حالات استثنا است تا لایه فراخوان در مورد نحوه عملکرد خود تصمیم بگیرید.
دقت کنید که خیلی مهم است که در این رویکرد دیگر "کد خطا" نداریم، بجایش "کلاس استثنا" داریم.
مثلاً کد زیر میتواند استثنا های زیر را راه اندازی کند.

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

مثلاً با کد زیر میتوانیم در لایه بالا با این امر تعامل داشته باشیم.

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

در این رویکرد حتی میتوان تغییر زبان UI را هم به سادگی مدیریت کرد...
مثلاً میتوان دیکشنری از انواع کلاس های استثنا و متن نمایشی معادلشان داشت (که مثلاً از یک فایل XML پر شده باشد)

حتی میتوان خطاهای سفارشی خودمان را تولید کنیم یا خطاهای سلسه مراتبی ایجاد کنیم که به خطاهای دیگری ارجاع داشته باشد.
مثال مسخره ای از حذف تعدادی تصویر مرتبط با عدد شماره کالا

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

همانطورکه قبلاً هم بیان شد، در واقع این یک روش انتقال اطلاعات از لایه های پایین به سمت بالا است
که در تولید و تسخیر کاملاً از قوانین شی گرایی تتبعیت میکند...
میتواند متن و دلیل اتفاق از داخل لایه پایین تنظیم شود و فقط لایه بالا در نحوه نمایش یا برخورد با ان تصمیم بگیرید...
میتوانید شامل اطلاعات اضافه تشریحی برای لایه بالا باشد.
به راحتی رویکرد صحیحی در فراخوانی های تو دو تو دارد و میتواند پیام های فراخوانی های لایه های پایین را از لایه های میانی انتقال دهد
و...
و...
و...
مزیت های این روش واقعاً بیشمار است و از حوصله من یکی خارج است
این روشی مطمئن برای انتقال داده است و تنها قید آن این است که موجب توقف اجرای کد در تمام متدهای فراخوان میشود.
موفق باشید.

_H2_
11-11-2012, 18:24
سلام


اينکه تا چه حد اين موضوع به نظر و سليقه فرد بستگي داره و تا چه حد اصول دخيل هستند؟

تولید چند لایه در واقع یک روش مفهومی مهندسی نرم افزار است که هیچ کلمه کلیدی ساختار مدون قطعی ندارد.

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

مهم رعایت آن تفکر اصلی است که به ایجاد گروه هایی از کلاس ها برای انجام وظیفه ای مشابه و عدم انجام کارهای متنواع در یک کلاس واحد اشاره دارد.

مانند آنکه که خودتان هم به درستی اشاره کردید که یک لایه میانی حق ارتباط گیری مستقیم با کاربر یا دیتابیس را ندارد و باید وظیفه فوق را به گروه یا لایه مربوطه محول کند.


[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

منابع:
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

shotok
27-11-2012, 14:36
بسم الله الرحمن الرحیم
با سلام
از استاد بزرگوار جناب _H2_ نهایت تشکر رو دارم و برای ایشان و تمامی _H2_هایی که با اخلاص علمشون رو در اختیار ما قرار میدهند آرزوی توفیق و سلامت دارم.
سوالی دارم 2 رویکرد در این موضوع میتوان داشت:
1) در هر لایه ای پیغام های مخصوص به خودش رو قرار بدهیم. ایراد این روش این است که نمی توان تغییر زبان UI را مدیریت کرد.
2) پیغام را به لایه بالاترش بفرستیم و لایه بالاسری تصمیم گیری کند. ایراد روش ذکر شده این است که باید در لایه بالاتر دوباره کاری انجام شود. ( فرض بفرمائید بخواهیم با جزئیات مشخص کنیم که کدام استثنا رخ داده است.اگر استثنا1:آنگاه ... اگر استثنا2:آنگاه... و الی غیر)
و به نظر میرسد مشکلی که در مورد Enum مطرح شده بود؛ تکرار شود.

اگر Func1 خودش چند تابع دیگر را اجرا کند که هر کدام هم یک سری خطای عریض و طویل مخصوص خود را داشته باشند چه؟
آنگاه حتماً باید enum نتیجه خروجی Func1 شامل جمیع enum های توابعی که صدا کرده باشد؟؟؟!
افتضاح زمانی بالا میگیرید که آن چند تابع هم خودشان توابع دیگری را اجرا کنند...!
با تمام این تفاسیر کدام روش مقرون به صرفه است.
با سپاس فراوان

_H2_
28-11-2012, 01:30
سلام
اول عضر خواهی میکنم چون باید اعتراف کنم که این تاپیک را کلاً فراموش کرده بودم و اگر شما تاپیک را فعال نکرده بودید معلوم نبود کی مجدد یادم بیاید... میبخشید...

دوم در مورد سوالتان ...
برای چند زبانه شما میتوانید یا از فایلهای resx خود دات نت استفاده کنید و یا یک مخزن XML ای از متون تشکیل دهید.
به دلایلی استفاده از مستقیم از فایلهای XML مقبولیت بیشتری از فایلهای resx داشته (که البته آنها هم ذاتاً XML هستند...)

هم میتوان کل این را در یک فایل واحد برای کل پروژه ذخیره کرد و هم میتوان آن را در قالب چند فایل مجزا دید، مثلاً یک فایل XML برای هر لایه و حتی یک فایل XML برای پیام های مشترک در تمام لایه ها و...
برنامه به سادگی میتواند زمان بالا آمدن تمام این فایلها در یک Dictinary بارگذاری کند که در تمام لایه ها در دسترس باشد.
این دیکشنری میتواند شامل کلیه پیام های خطا و هشدار و موفقیت و نام دکمه ها و برچسب ها و... باشد.

این فایل یا فایلهای XML هم میتواند داخل exe باشد و هم (چه بهتر) در خارج از برنامه و کنار Exe باشد.
(تا هر کسی از روی نسخه انگلیسی و بدون کمترین دانش برنامه نویسی بنواند آن را به زبان خودش ترجمه کند)


برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

shotok
29-11-2012, 09:53
بسم الله الرحمن الرحیم
با سلام
از پاسختون بینهایت ممنون.
لطفا راجع به مطلبی هم که در مورد دیکشنری فرمودید بیشتر توضیح بدید.
متاسفانه هنوز متوجه نشدم که:
1) در هر لایه ای پیغام های مخصوص به خودش رو قرار بدهیم؟ ایراد این روش این است که نمی توان تغییر زبان UI را مدیریت کرد.
یا
2) پیغام را به لایه بالاترش بفرستیم و لایه بالاسری تصمیم گیری کند؟ ایراد روش ذکر شده این است که باید در لایه بالاتر دوباره کاری انجام شود. ( فرض بفرمائید بخواهیم با جزئیات مشخص کنیم که کدام استثنا رخ داده است.اگر استثنا1:آنگاه ... اگر استثنا2:آنگاه... و الی غیر)
و به نظر میرسد مشکلی که در مورد Enum مطرح شده بود؛ تکرار شود.
می بخشید دوباره سوالم رو تکرار کردم.
با سپاس فراوان

_H2_
06-12-2012, 11:37
سلام
انشاا... فرصت کنم، تلاش میکنم امروز و فردا به جای تایپ مطلب بعدی یک نمونه پروژه فوق العاده ساده چند لایه حاضر کنم که مورد ترجمه مدنظر شما را داشته باشد.
شاید مشاهده این پروژه، ساده تر از توضیح دادن باشد.

_H2_
16-12-2012, 17:34
سلام
میبخشید دیر شد طبق معمول مشکلات الوان تمامی ندارد...

یک نمونه فوق العاده بچه گانه درست کردم...
خیلی ساده است و خیلی از اصول عالی را رعایت نکرده است.
ولی نمونه مخزن متن های xml و خطای چند زبانه را دارد.
کد خیلی خیلی کم بیش از ترجمه xml ای صرف دیده شده و چند کلاس و اینترفیس اضافه برای کمی نزدیک شدن به پروژه های واقعی را هم دارد...


برای ترجمه و آرشیو xml از یک dll از خودم استفاده کردم تا سرعت تولید را کاهش دهم ...
دوستان میتوانند خودشان یک فهرست و مفسر xml به پروژه اضافه کنند...


در پروژه جاری فایل های ترجمه در قالب فایل xml جداگانه و در پوشه Localization در بیرون برنامه قرار دارد.
برنامه قابلیت ادغام xml ها را دارد به این معنی که میتوان یک xml را به چند فایل xml بشکنید، برنامه خودکار زمان بالا امدن همه آنا را به نوعی در حافظه merge میکند.
کلید ادغام عدد فرهنگ زبان LCID است.
مثلاً فایل زیر:

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

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

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
و

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید


در نتیجه انتخاب آنها متن های هر لایه یا گروه یا فرم یا بخش و... در یک فایل xml مستقل باشد یا اینکه کل پروزه یک فایل xml واحد داشته باشد به عهده خودتان است و نیاز به تغییر یک خط از کدها هم ندارد.

دقت کنید در محیط VS (به دلیل ریست تنظیمات) شاید combobox ای که زبان برنامه را تغییر میدهد شاید دفعه اول کار نکند ولی اگر نمونه exe را مستقیماً اجرا کنید متوجه میشوید مشکلی وجود ندارد.

بررسی کنید مشکلی بود روی معیار همین پروژه بحث میکنیم.

با کمی تغییرات امکان ذخیره xml ها درون خود dll ها و exe ها هم وجود دارد.

[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]
موفق باشید.

shotok
18-12-2012, 13:34
بسم الله الرحمن الرحیم
با سلام
قبل از هر چیز از اینکه وقت گذاشتید و نمونه برنامه رو حاضر کردید بینهایت ممنون؛ سپاسگزارم.

دقت کنید در محیط VS (به دلیل ریست تنظیمات) شاید combobox ای که زبان برنامه را تغییر میدهد شاید دفعه اول کار نکند ولی اگر نمونه exe را مستقیماً اجرا کنید متوجه میشوید مشکلی وجود ندارد.
کل برنامه اجرا نمی شود خطای زیر رو میده.
a project with an output type of class library cannot be started directly. in order to debug...
چون میخواهم برنامه رو خط به خط اجرا بگیرم برام مهمه که در محیط VS اجرا بگیرم ولی فایل exe به خوبی کار میکنه.
حدود یک ربع به این برنامه به قول خودتون بچه گانه زل زدم ولی کلیت کار دستم نیومد:n13:
جسارت بنده رو ببخشید ولی لطفا توضیحات بیشتری در مورد برنامه بفرمائید.
خیلی وقته که منتظر این برنامه بودم بنابراین نمی تونم به راحتی ازش بگذرم.
ببخشید که وقتون رو میگیرم.
ان شاالله تا شما جواب میدید بازهم خودم تلاش میکنم تا ابهاماتم رو مرتفع کنم.
پیشاپیش تشکر میکنم.:n16:

_H2_
18-12-2012, 23:14
سلام

کل برنامه اجرا نمی شود خطای زیر رو میده.
a project with an output type of class library cannot be started directly. in order to debug...
در solution هایی که شامل بیش از یک project هستند، فقط و فقط یک پروژه را باید به عنوان startup مشحص کنید.
این پروژه آغاز کننده معمولاً نامش در solution explorer به صورت bold شده نشان داده میشود.

در حال حاضر دررایانه شما با این پروژه صفر کیلومتر، یکی از dll ها به عنوان startup قرار گرفته که قابل اجرا نیست.
مشابه آن است که بخواهید با دبل کلیک یک dll برنامه را اجرا کنید ... !


کافیست روی پروژه اصلی exe در solution explorer راست کلیک کنید و گزینه startup را فعال کنید.
VS این تنظیم را برای solution در قالب یک فایل مخفی جداگانه ذخیره خواهد کرد و در دفعات بعد آن را حفظ خواهد کرد.


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

4 پروزه داریم...
PublicLibrary به عنوان کتابخانه عمومی است که به تمام لایه های دیگر سرویس های خلی کلی و عمومی را ارائه میدهد...
مثلاً میتواند شامل تعریف خالی بدنه interface ها باشد...
میتواند شامل تعریف کلاس های static حاوی توابع عمومی باشد ... توابه کمکی LINQ ... توابع کمکی ریاضی مثل factorial ... توابع محاسباتی ... توابع پردازش string ... و..و...و...
وجود این لایه در معماری سرویس گرایی خیلی مهم تر خواهد شد...

DatabaseLayer
لایه دیتابیس که فعلاً بجز به جریان انداختن یک Exception چند زبانه کار دیگری انجام نمیدهد.

KernelLayer
لایه هسته مرکزی که فرض شده ماژول ها و سرویس های مختلفی را زمان بالا آمدن برنامه به جریان خواهد انداخت...
بطرز خیلی بچه گانه ای کلاس ساده Kernel.Application ، معرف بارگذاری این لایه و کلاس اصلی آن است که مسئول بارگذاری سایر خدمات این لایه است، همچنین در صورت لزوم نابود سازی این خدمات در زمان بسته شدن برنامه برعهده دارد...

در یک طراحی عالی میتوان کاری کرد که ضمن انجام اکثر پردازش های برنامه در این لایه، ولی تمام کلاس های این لایه به صورت خصوصی باشند و کلاً خارج از دسترس مستقیم تمام لایه های دیگر باشد و نیازی هم به فراخانی مستقیم انها از لایه های دیگر نباشد .... شاید الآن کمی گفته هایم نا معقول بنظر برسد ولی به آن فکر کنید ... ... ... ...

کلاس StringResourceModule در این لایه مسئول اصلی بارگذاری xml های زبان است که برای این کار کمی از پارسر و دیکشنری داخل ghdiamond کمک گرفته ...
توجه کنید که به عنوان مثال به جای new کردن مستقیم این کلاس در لایه exe .... آمده ام و در لایه exe کلاس اصلی Kernel.Application را نمونه سازی کرده ایم و این کلاس آمده و کل مکانیزم هالی موجود در لایه kernel را برای ما در حافظه بارگذاری کرده که از البته فعلاً فقط کلاس StringResourceModule ...

در یک پروژه کامل ، هر لایه میتواند شامل کلاسی مشابه Kernel.Application جهت مدیریت لایه و فرمان بارگذاری و نابود سازی اشیای لایه باشد و میتوان تمام هزینه زمانی بازگذاری ماژول های این لایه ها را به پشت پنجره SplashScreen منتقل کرد و حتی گزارش بارگذاری ماژول ها هم روی SplashScreen نشان داد ...

UILayer
یک پروژه winform در ساده ترین حالت ممکن است...
شاید مهم ترین تابع این بخش، (تابع خیلی ناقص و مشکل دار) Transfer باشد که در یک حالت حداقلی وظیفه ترجمه اشیای روی فرم (جالب تر انکه هر کنترلی) را بر عهده دارد.

در پست قبلی نمونه xml را دیدید و متوجه شدید که نمونه xml پیشنهادی من دو سطحی است که یک gkey گروه دارد و هر گروه میتواند چندین جزء با skey دیگری داشته باشد.

تابع Transfer هم gkey یک گروه را میگیرد و در ان گروه Text کنترلها را به عنوان skey جزء استفاده میکند...


برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید


کد را از داخل vs اجرا و دنبال کنید، متوجه میشوید...
موفق باشید.

senaps
22-12-2012, 10:27
سلام..... من یه سوال برام پیش اومد و اون اینکه من همیشه کل دیتام رو میگیرم و میارم به لایه‌ی نمایش و تمام.... حالا الان که دارم با سرویس ها کار میکنم، راستش فکر میکنم که بهینه ترین حالت ممکن اینه که دیتای خام رو از سرور و سرویس بگیرم و تو کلاینتم روش کار کنم........................اگر تو ویندوز 7 چیزی رو سرچ کنین، مثلا یه جست‌جوی اینفینت که همه‌ی فایل ها رو نشون بده، به حالتی نمایش میده که فقط اسمشون رو داری، بعد اگه حالت نمایش رو بذاری روی دیتیل، دوباره میره تو سرچ و طول میکشه!!! این اتفاقیه که الان برا من و برنامه‌های کلاینتم می‌افته.... چون کلاینت فقط نمایش میده و میره دیتاش رو از سرویس میگیره!!!!............اگر مثلا کاربرم بخواد فیلدی رو از گرید حذف بکنه یا نمایش بده، یا نوع سورت دیتا رو عوض بکنه، باید اطلاعات به اون شکل دوباره دریافت بشن!!! راه حل این مسئله چیه؟!

_H2_
28-12-2012, 13:49
سلام علیکم،
شما خیلی ساده میتوانید از مکانیزم های Cache و Paging استفاده کنید.
Paging با کاهش حجم دریافت اطلاعات سرعت انتقال و بازدهی برنامه را افزایش میدهد و در نهایت به پهنای باند شبکه هم کمک میکند
و
Cache هم با عدم درخواست مجدد همین نتایج را در بر دارد.


[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

برای مرتب سازی و برخی موارد ف-ی-ل-ت-ر سریع (غربال در حین تایپ کیبورد) میتوان در مکانیزم های FX4-Typed از Linq و در سایر موارد از کامپونت هایی مانند BindingSorurce استفاده کرد
((
مثلاً در لیست های بازشویی از جداول افراد، کالاها و خدمات و... و...میتوان مکانیزم های کاملی پیاده سازی کرد که در حین تایپ کاربر امکان غربال اطلاعات را بر اساس کد و نام و ... فراهم کند...
در این موارد که به نوعی جستجوی سریع است نمیتوان با تایپ هر کاراکتر یک دستور SQL جدید را اجرا نمود
))


[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

البته در مورد کش باید به حجم لازم RAM و میزان تغییر اطلاعات هم دقت کنید
مواردی که خیلی کم تغییر میکنند و خیلی زیاد استفاده میشوند و حجم کمی دارند برای کش بسیار ایده آل هستند.

بطور مثال در یک برنامه خرید و فروش "گروه های کالا" یا " واحدهای شمارش کالا" یا در مقیاس تجاری بزرگتر "فهرست انبارها" و... گزینه های خوبی برای کش هستند تا کل لیست های بازشو برنامه را تغذیه کنند.

در مبنای پیشرفته تر میتوانید یک ماژول مرکزی کش داشته باشید که با یک کلید (مثلاً string ای شامل نام دلخواه با ترکیب نام جدول دیتابیس و...) داشته باشید که ضمن کش اطلاعات بتواند زمان انقضایی برای آنها هم در نظر گرفته و بعد گذشت این زمان اطلاعات را حذف کند... چیزی شبیه ماژول مشابه اش در ASP.Net ....
برای بارگذاری اطلاعات هم میتوان از تکنیک Lazy استفاده کرد و تا زمان اولین درخواست بعدی این کار را به عقب انداخت ...

=====

این کارها بدون شک به کدنویسی نیاز دارد و سادگی یک DataAdapter.Fill را ندارد ولی دقت به این جزئیات که شما گفتید و تولید برنامه خوب بدون کدنویسی نمیشود

مورد اول انکه شما میتوانی مجموعه ای از کلاس ها و کامپونت ها برای خودتان ایجاد کنید که برای هر پروژه و هر کار نیازی به دوباره کاری نداشته باشید.
یعنی وقتی به یک مکانیزم نیاز دارید با دید وسیع تری آن را طوری طراحی و کدنویسی کنید که برای پروژه های بعدی هم قابل استفاده باشد.
همین مفهوم لایه بندی / پلاگین پذیری / DLL / OOP و... اگر درست انجام شود به تولید کدهای "قابل استفاده مجدد" (یکی از اصول پایه برنامه نویسی) کمک میکند.

و مطلب دوم هم آنکه اگر به هر جزء به طور تکی نگاه کنید، متوجه میشود، خیلی هم پیچیده و مشکل نیست، شاید کمی کدبخواهد ولی کد سختی نیست و الگوریتم های پیچیده ریاضی ندارد.

حالا نمیدانم از مطالب فوق بطور دقیق با پیاده سازی کدام بخشش مشکل دارید؟!

====

گمانم باید بقیه مطالبی که قولش را داده بودم تایپ کنم...
بابت طولانی شدن انشاا... خواهید بخشید...
موفق باشید.

senaps
28-12-2012, 15:41
بسیار ممنون....
از همون نیاز به کش کردن می‌ترسیدم!!
دوبار تو برنامه‌هام ازش استفاده کردم پشت دستم رو داغ کردم که تا تسلط کافی دیگه دیتابیس رو کش نکنم :n02:
ولی این صفحه‌بندی رو نفهمیدم کاربردش دقیقا چی بود(غیر از خود صفحه‌بندی!!)....
به هر صورت، بسیار ممنون دوست گرامی ایده‌ی خوبی دادید.... و به ظاهر، باید برم تو کار همون نوشتن یه سری dll....(اخرش کارم به اونجا میرسه که یه کتابخونه‌ی گنده مثل دات‌نت داشته باشم!! خودم میدونم:n09: )

به شدت منتظر ادامه‌ی مطالبتون در این تاپیک هستم....

shotok
28-12-2012, 23:20
بسم الله الرحمن الرحیم
با سلام
بینهایت از پاسخ جناب _H2_ سپاسگزارم.:n16:
با اجازه ایشون پاسخ کوتاهی خدمت senaps ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]) عرض میکنم.

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

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

یعنی وقتی به یک مکانیزم نیاز دارید با دید وسیع تری آن را طوری طراحی و کدنویسی کنید که برای پروژه های بعدی هم قابل استفاده باشد.
همین مفهوم لایه بندی / پلاگین پذیری / DLL / OOP و... اگر درست انجام شود به تولید کدهای "قابل استفاده مجدد" (یکی از اصول پایه برنامه نویسی) کمک میکند.
متاسفانه نتونستم برای صفحه بندی این کار رو انجام بدم و حالت کلی در نظر بگیرم.
موفق باشید.

_H2_
03-01-2013, 14:26
ولی این صفحه‌بندی رو نفهمیدم کاربردش دقیقا چی بود

گمانم منظورتان نحوه صفحه بندی و چگونگی ان نباشد.
من چنین برداشت میکنم که منظورتان چرایی آن است. اینکه که چه ربطی به بحث داشت؟ و چه لزومی دارد؟
اگر چنین است...

هدف نهایی آن است که فرمان کاربر در حداقل زمان ممکن انجام شود.
در واقع گمانم روی این توافق داشته باشیم که چکیده پست 19 شما نگرانی در خصوص بازدهی زمانی باشد.

=====

مثال: کاربر میخواهید Sort اطلاعات را براساس یک ستون تغییر دهد ...

بالاخره یک جایی یک کدی باید این Sort مجدد را انجام دهد، این کاری است که بحرحال باید انجام شود، الگوریتم های Sort هم مشخص است، حالا یا SQLServer یا LINQ یا BindingSorurce و...

بطور دقیق چه چیز باعث تفاوت سرعت پاسخ به کاربر خواهد شد؟!
الگوریتم Sort که مشخص است و فقط کدهای مختلف آن را انجام میدهند نباید اینقدر تفاوت ایجاد کند.

تفاوت بازدهی در نحوه دسترسی به اطلاعات و انتقال آنها وجود دارد که خود را نشان میدهد.
یعنی اگر میشد، پارامتر تاثیرگذار فوق را حذف کرد، شاید همه سه روش فوق در سرعت یکسانی این کار را انجام میداند.

پس در واقع گلوگاه مشکل "دسترسی و انتقال" اطلاعات است.

دقت کنید که وقتی از انتقال اطلاعات صحبت میکنیم این شامل
- سریالی کردن اطلاعات در برنامه سرور
- ارسال اطلاعات (بطور معمول تحت پروتکل TCP/IP) از هفت لایه شبکه
- دریافت اطلاعات از هفت لایه شبکه
- سرانجام دی-سریالی اطلاعات در برنامه کلاینت
است.

به عملیات های فوق باید ظرفیت انتقال و ترافیک شبکه را هم اضافه کرد، اغلب شبکه های داخلی شرکت های ما حدود 10MByte/S ظرفیت انتقال دارند. (که البته کافی است)
یعنی وقتی سروری با یک کارت/کابل شبکه معمولی به سوییچری متصل است و همزمان 10 کلاینت درخواستی میدهند، حداکثر با سرعت 1MByte/S میتواند پاسخ هر یک را بدهد و...
اگر روی همین سرور ISA/IIS/SQLServer و... هم نصب باشد، این عدد بین دسترسی به اینترنت و شبکه داخلی و بانک اطلاعاتی و... تقسیم خواهد شد.
((شاید بارها مشاهده کرده باشید که در شبکه های عادی شرکتی وقتی کسی فایل سنگینی دانلود میکند، حتی یک سایت معمولی برای دیگران به سختی باز میشود))

البته لزومی ندارد خیلی نگران شوید!
بر میگردیم سر بحث اصلی ...

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

Paging هم با انتقال کمتر اطلاعات میتواند بازدهی سرعتی را افزایش دهد.
و همان ترتیب ترافیک شبکه را کمتر اشغال کند و در سرعت عمومی کل شبکه و حتی سایر کلاینت ها کمک کند.

(((
شرکت مان برای پروژه ای با یک بخش دولتی در حال مذاکره بودیم که یکی از جداول آنها نزدیک 100 میلیون رکورد داشت...
البته سرورهای خوبی داشتند و مشکل RAM و CPU و... اصلاً نداشتند و آخر هم سر قیمت به توافق نرسیدیم ...
بیخیال 100 میلیون...

شما نمیتوانید یعنی منطقی نیست که 20000 رکورد را یکباره دانلود کنید و به کاربر نشان دهید، این کار حافظه و پردازش گر و شبکه را بسیار درگیر میکند و زمان پاسخ دهی برنامه تان بسیار کند خواهد کرد.
)))
موفق باشید.

_H2_
03-01-2013, 15:41
سلام
کمی داریم از بحث اصلی دور میشویم ولی چاره ا نیست ...
پست قبلی به "چرایی" صفحه بندی گذشت.
در این پست کمی در خصوص "چگونگی" آن صحبت میکنیم



متاسفانه نتونستم برای صفحه بندی این کار رو انجام بدم و حالت کلی در نظر بگیرم

اصولاً خود ذات صفحه بندی در مبنای کامل و بزرگش یک Cache دیگر کوچک کنارش نیاز دارد.
این کش مخصوص کمک به صفحه بندی است.

برخی از موارد صفحه بندی روی خروجی خالص یک جدول انجام میشود.
ولی در بسیاری موارد دیگر این خروجی یک نوعی SEARCH است.
یا روی ForeginKey ها و Index ها و Text ها و...

مخصوصاً جستجوی های غیر ایندکسی بسیار هزینه بر و سنگین است.
شما نمیتوانید در مقابل حرکت کاربر بین صفحات مختلف هربار یکمرتبه این جستجو های سنگین را به سیستم تحمیل کنید.

برای صفحه بندی باید خروجی های SEARCH کش شود.
این کش میتواند فقط شامل PrimaryKey سطرهای یافته شده باشد. (سرعت دسترسی بالا و حافظه کم)
در تحت وب و ASP.Net این کش میتواند دو جدول در دیتابیس باشد.

در پروزه های exe میتوان بجای دیتابیس از یک List-int یا List-long و... هم استفاده کرد.

یعنی باید جستجو را یکمرتبه انجام دهید و تک ستون های PrimaryKey این نتایج به داخل کش واکشی شوند.
سپس بخش نمایش از این کش PrimaryKey برای صفحه بندی استفاده کند.

اگر این کش با جداول خود دیتابیس باشد، هم میتوان عدد RowNumber را به خود جدول اضافه کرد و هم میتوان از دستور SQL آن استفاده کرد.

اگر هم کش یک List/Array دات نتی باشد (برنامه Exe) که هم Count دارد و هم دسترسی تصادفی دارد و گمانم استفاده از آن نیاز به تشریح هم ندارد.
این موارد را به راحتی میتوان در قالب کدهای مشترک تجمیع کرد.
بدلیل مشکلات زمانی ، نمیتوانم قولی دهم، ولی تلاش میکنیم اگر فرصتی شد روی ارائه یک نمونه کد بسیار ساده صفحه بندی به روش بالا زمان بگذارم...

_H2_
19-01-2013, 11:47
سلام
متاسفانه به علت مشغله کاری کمی زمان بر شد ولی به بحث اصلی ادامه میدهیم...

رویداد گرایی
هر کلاسی از هر وراثت ، واسط ، شرایط و... میتواند رویداد داشته باشد و اتفاقات و وقایع خود را منتشر کند.
(((
پیاده سازی زیر بنایی یک رویداد در واقع یک مجموعه اشاره گر توابع است.
کدی که قصد گوش دادن به رویداد و مطلع شدن از آن اتفاق را دارد اشاره گر یک تابع نماینده را به فهرست رویداد اضافه میکند.
کلاس اصلی هر وقت تشخیص داد با به جریان انداختن رویداد تمام توابع نماینده را اجرا میکند
)))

هر رویداد یک "امضا تابعی" خاص خود دارد.
(امضا تابع: نوع و ترتیب پارامترهای ورودی یک تابع)

==============

مثال عملی برای درک بهتر کاربرد وسیع این امکان:

به عنوان نمونه حتماً در WinForm از رویداد Click دکمه ها با امضای object, EventArgs استفاده کرده اید.
این رویداد را کلاس Button هرگاه تشخیص دهد کلیک شده به جریان می اندازد و باعث میشود، تمام توابع نماینده گوش دهنده اجرا شوند. گرچه احتمالاً شما معمولاً برای هر رویداد فقط یک تابع نماینده داشته اید ولی در واقع محودیتی وجود ندارد.

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

>>> یک مثال عملی جالب تر در انتهای بحث با یک شبه کد بیان شده است.

==============

پیاده سازی:
اولین مطلب قبل بحث میتواند تایین امضای یک رویداد باشد که با کمک Delegate ها انجام میشود.
(((
Delegate ها اشاره گرهای توابع در دات نت هستند و پرداختن به انها خود بحثی مجزا و گفتاری بسیار می طلبد، دوستان برای اطلاعات بیشتر میتوانند به کتاب های موجود و یا MSDN مراجعه کنند.
)))

دات نت یکسری Delegate آماده دارد مثل System.EventHandler و در دات نت سه System.Action و System.Func که بسیار کاربردی هستند و... و...

بعنوان نمونه EventHandler همان delegate آشنای امضای object, EventArgs است که در WinForm به کرات به ان گوش میدهیم!

تعریف یک رویداد با امضای object, EventArgs :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
از لحاظ استفاده کاربردی میتوان گفت هر سه شکل تعریف فوق برابر هستند و خیلی تفاوتی برای نحوه استفاده ندارند
در واقع مهم "امضای تابع" است که در هر سه مورد فوق بطور مستقیم و غیر مستقیم، امضا را روی دو آرگومان object, EventArgs گذاشته ایم، نتیجتاً عملاً سه شکل فوق یک عمل یکسان انجام میدهند.

به جریان انداختن رویداد (در کلاس مالک رویداد):

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

گوش دادن به یک رویداد در کدی که از کلاس ما استفاده میکند:

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
یا حتی سینتکس زیر برای کدهای کوچک تر

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
بخش AnyCode همان جایی است که کدی خواهید نوشت که در قبال رخ دادن رویداد باید اجرا شود.

قطع ارتباط و عدم گوش دادن به رویداد:

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

=====

مثال ما در این پست برای کلاس ناهمزمان با پشتیبانی رویداد پیشرفت کار:
میتوان کلاسی برای کپی فایل ها، فشرده سازی، بروزرسانی نرم افزار، انتقال اطلاعات دیتابیس، پشتیبان گیری اطلاعات و... در لایه های پایین نوشت بطوریکه مستقل از لایه UI و تکنولوژی آن (WinForm,Wpf, Web, Service و...) باشد. ولی با این وجود این کدها بطور طبیعی نیاز دارند تا حین کارکرد مواردی را به لایه UI یا کاربر گزارش دهند از جمله درصد پیشرفت کار، عملیات جاری در حال انجام و... و تصمیم نمایش و عدم نمایش و طریقه نمایش را بر عهده لایه UI بگذارند.

کد کلاس اصلی در لایه پایین

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

کد لایه UI که در واقع مستقل از مکانیزم لایه پایین است و به راحتی میتوان آن را مطابق الگوی Wpf یا ASP.Net و... کرد یا در WinService باشد که اصلاً گزارش دادن این اطلاعات به کاربر برایش مهم نباشد و به رویداد مربوطه گوش ندهد و...

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

==============

مطلب اول:
لازم میدانم که حتماً بیان کنم شیوه دیگری از رویداد گرایی وجود دارد که بیش از رویداد گرایی با نام Callback شناخته میشود که در اصل بسیار مشابه رویدادگرایی بیان شده فوق است و طی آن میتوانید تابع نماینده ای برای ارتباط با کد خودتان به لایه پایین تحویل دهید تا با آن بتواند کد لایه بالاتر را (معمولاً در حین انجام کار یا پایان کار) اجرا نماید.

مطلب دوم:
تمام موارد فوق عین در VB.Net هم قابل پیاده سازی و انجام است، طبیعتاً سینتکس نوشتاری خودش را دارد.
حقیقتش دیگر حوصله کافی نوشتن کدهای VB.Net اش را هم نداشتم ولی اگر دوستان با هر بخشی از ان در VB.Net مشکلی داشتند در تالار مطرح بفرمایند، سایر دوستان عزیز و همچنین خودم انشاا... پاسخ خواهیم داد.

مطلب آخر:
در آخر لازم میدانم متذکر شوم که مطالب فوق فقط سرنخ های این کار بوده و شاید 33% مطالب بیان شده و جزئیات و قابلیت های متنوع دیگری در این حیطه وجود دارد که دوستان برای تکمیل بحث و قابلیت های این حیطه میتوانند به کتوب و MSDN مراجعه کنند.

==============

موفق باشید.