بسم الله الرحمن الرحيم با سلام معمولا در کلاس ها در پروژه هاي چند لايه چگونه پيغام ها رو کنترل ميکنند؛ از چه نوعي ميگيرند و با اون پيغام مورد نظر رو به لايه بالايي ميفرستند. با سپاس فراوان
بسم الله الرحمن الرحيم با سلام معمولا در کلاس ها در پروژه هاي چند لايه چگونه پيغام ها رو کنترل ميکنند؛ از چه نوعي ميگيرند و با اون پيغام مورد نظر رو به لايه بالايي ميفرستند. با سپاس فراوان
سلام
سوال و نکته سنجی بسیار بجایی است.
باید به مفهوم لایه ها دقت کرد و نباید هرکجا خواستیم هر کاری انجام دهیم و فقط از لایه بندی اسمش بماند ...
(گرچه افسوس این دقت نظرها در جامعه حرفه ای ما خیلی خریداری ندارد ...)
روش های گوناگون و بسیار خوب و مطمئنی وجود دارد.
- پیام ها و ارتباطات قابل انتقال به اول کد:
از این جمله میتوان به انجام اعتبار سنجی های UI قبل از ارسال به لایه پایین اشاره کرد یا مواردئی که کاربر باید بین چند حالت انتخابی داشته باشد و...
این ساده ترین موردی است که حتماً به آن فکر کرده اید...
مثلاً ...
برای پرسش اطمینان حذف یک مورد می توان در همان لایه UI انجام شود و سپس متد اصلی لایه های پایین تر اجرا شود.
یا در حالتی که با چند وضعیت مختلف روبرو هستیم میتوان Enum ای در لایه پایین تعریف کرد که مقدار آن از بالاترین لایه UI اخذ و ارسال شود...
که State از پرسش ها و ارتباطات مختلف اولیه UI پر خواهد شد.کد:برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
ولی باید دقت داشت که در این کار افراط نشود.
چون تعریف enum منجر به استفاده از swith case خواهد شد و این میتواند دشمنی با پلی مورفیزم تعبیر شود ! که اصلا خوب نیست.
در حالت حداقلی (نه switch case و نه polymorphism) شاید بتوان چند متد برای هر کدام از این امور داشت که موجب تولید متدهایی با کدهای کمتر میشود.
(همواره تلاش کنید متدهای با کدهای حجیم و طولانی را به قطعات کوچکتر خرد کنید)
در خصوص روش های جالب تر دیگر در روزهای آتی خواهم نوشت ...
بسم الله الرحمن الرحيم با سلام از اينکه پاسخ داديد سپاسگزارم. لطفا براي روشن تر شدن مطلب مثالي از مقدار دهي State در لايه هاي UIو مياني بياوريد. با سپاس فراوان
بسم الله الرحمن الرحيم با سلام منظورتون اينه که مثلا لايه UI بعد از اينکه متدي از لايه مياني رو فراخواني کرد مقدار state رو بررسي کنه و اگه state=0 بود آنگاه پيغام بده که بر فرض مثال عمليات با موفقيت انجام نشد. با صحيح بودن فرض بالا مگر نبايد هر لايه اطلاعي از جزئيات لايه پاييني نداشته باشد و تنها از اون استفاده کنه؟ منظورتون رو از جمله "پیام ها و ارتباطات قابل انتقال به اول کد:" متوجه نشدم. با سپاس فراوان
سلام....
من هم نگرفتم که چی شد و البته یه چیز جالب برام پیش اومد که میخوام بپرسم در ادامه.....
کاری که من میکنم اینه که اول همهی چیزایی که تو رابط کاربر میشه بررسی کرد رو بررسی میکنم و بعد پارامتر ها رو به تابع در لایهی پایین تری میفرستم...(که همون لایهی لاجیکالم در خود برنامه باشه؟!) و بعد کلاس ها و کدهای اون قسمت، پارامتر هایی نهایی رو برای رابطم با دیتابیس میفرستن که جدیدا دیگه سرویس هایی روی وب میباشه!!! نمیدونم چقدر درسته...
این مثال اینام که زده شد، برای من یه شبهه ایجاد کرد....
ایا من میتونم مقادیر چند باکس مختلف(تکست، رادیو و چک باکس و ...!!) رو داخل اینام ذخیره کنم و بعد از اینها برای کوری گرفتن استفاده کنم؟! مثلا من 12 تا تکست باکس دارم که همه دسته بندی شدن و من میخوام کاربر هرچقدر از اینها رو بیشتر وارد کرد، جستوجوش دقیق تر باشه و خوب، هرچی کمتر بود یه جستوجوی کلی تر بگیره....؟!!! نمیدونم اگر تونسته باشم منظورم رو درست بفهونم؟!!!
در این روش باید از چی استفاده کرد؟! و ایا اصولا در بحث این سواله یا نه؟!!
سلام
مثالي از مقدار دهي ... در لايه هاي UIو مياني بياوريدشما میتوانید یکسری فرآیند های تصمیم گیری را با enum ها کنترل کنید.من هم نگرفتم که چی شد
در واقع برای به دو سبک شمارشی یا بیتی میتوان از یک enum استفاده کرد و کمبود های یک bool را جبران کرد.
شمارشی برای حالتی که بیشتر دو حالت true/false نیاز باشد که در نهایت موجب استفاده از switch case در جایی از کد میشود.
و
بیتی برای حالتی که بیش از یک bool نیاز باشد
یعنی کد اول بجای کد دوم:
کد:برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید==============کد:برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مثال عملی:
در برنامه های حسابداری قالباً لازم میشود همراه ثبت یک "فاکتور" یک "سند حسابداری" هم صادر شود...
گرچه راه حل های متفاوتی وجود دارد ولی شاید پیمانکار یا کارفرمائی ترجیح بدهد طی MessgageBox ای این مورد پرسیده شود...
در واقع بجای آنکه درون لایه پایینی این پرسش انجام شود، قبل از آن در لایه بالا پرسیده شده و نتیجه تصمیم به لایه پایین ارسال شده تا لایه پایین دیگر نیازی به تعامل با کاربر نداشته باشد.کد:برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
تا اینجا درست!
حالا فرض کنید می خواهیم در خصوص صدور "قبض انبار" هم بپرسیم.
یعنی میخواهیم بدانیم با "صدور فاکتور" باید "سند حسابداری" یا "قبض انبار" هم (جداگانه) صادر شود یا خیر؟
اینجا دیگر نمیتوان یک bool به لایه پایین تحویل داد، اینجا دو bool یا یک enum لازم است.
یعنی میتوان یک MessgaeBox سفارشی با دو CheckBox ساخت که دو مورد فوق را پرسید و نتیجه را در یک enum به لایه پایین پاس داد.
==============
البته ...
این فقط یک مثال برای نحوه کاربرد بود.
وگرنه همانطور که بیان شد مثال فوق و هر مثال دیگری راه حل های متفاوتی میتواند داشته باشد.
از جمله در تنظیمات سراسری برنامه بله/خیر آن مشخص گردد
یا
پس از ثبت فاکتور دکمه ای برای "ثبت سند" و "ثبت قبض" ظاهر گردد و...
یا
عملیات "ثبت سند" و "ثبت قبض" دو متد مستقل باشند که از همان لایه UI فراخوانی شوند
و...
ولی تمام این روش ها تغییری در مفهوم اولیه بیان شده ایجاد نمیکند.
در واقع هدف از بیان enum آن بودکه می میتوانیم کمبودهای bool را با enum جبران کنیم و فکر خودمان را در حصار bool (دوحالته) محدود نکنیم.
روش اول: پرسش اولیه برخی موارد و ارسال به لایه پایین تا لایه پایین تعامل با کاربر نخواهد.
==============
چند مورد دیگر را برای یک تنفس کوتاه(!) و تفکیک بهتر مطالب در پست بعدی پاسخ میدهم ...
سلام
بله همه این موارد درست است...نوشته شده توسط senaps
این مورد هم مشابه مورد قبلی بیان شده شما، همه و همه حالتی هستند که میتوان در اول کد فراخوانی لایه پایین تعبیه کردنوشته شده توسط senaps
(((ولی مواردی پیش خواهد آمد که نمیتوان در اول (یا آخر) کد فراخانی لایه پایین کار را تمام کرد.)))
البته طبیعتاً (و همانطور که حتماً بهتر مطلع هستید) اگر بخواهید چندین مقدار شامل string, Datetime, int و... و... را به لایه پایین پاس دهید میتوانید و (شاید بهتر است) از یک class یا struct کمکی استفاده کنید....
در حالت حداقل حداقل یک ظرفی شبیه این میتوانید داشته باشید.
البته شاید...کد:برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
بتوانید از کلاس های پیش ساخته لایه "دیتابیس" هم صرفاً برای انتقال استفاده کنند.
مخصوصاً موارد تولیدی ADO.Net Entity Framework بسیار مناسب تر هستند.
فوقش برای لایه بندی بیشتر و نیز افزودن امکانات میتوانید از کلاس هاس سطرهای جداول در لایه های بالا وراثت بگیرید
و...
تا حدودی!نوشته شده توسط shotok
این مورد بیان شده شما میشود، "پیام ها و ارتباطات قابل انتقال به آخر کد"
- پیام ها و ارتباطات قابل انتقال به آخر کد
یعنی میتوان یکسری از پیام ها مانند نتیجه عملیات که خودتان اشاره کردید را به آخر فراخوانی کد در UI واگذار کرد که روش های آن خیلی شبیه مورد بیان شده قبلی است.
میتوان در یک bool دوحالته یا یک enum چند حالته نتیجه عملیات را به لایه بالاسری برگرداند تا لایه بالا سری در خصوص چشم پوشی یا اطلاع رسانی مناسب به کاربر تصمیم بگیرد.
یعنی UI هایی که میتوان نشان دادن آنها را قبل از فراخوانی کد لایه پایین انجام داد...نوشته شده توسط shotok
نوع دیگر میشود نمایش UI هایی پس از اجرای عملیات لایه پایین، مانند آنچه خودتان اشاره کردید و به موفق/ناموفق بودن عملیات اشاره داشت.
در نهایت شاید لازم باشد لایه پایین در حین کار برای مواردی با کاربر تعامل داشته باشد ... مانند گزارشات و خطاها و درصد پیشرفت ... لغو و توقف عملیات در جریان ... و... که به سه چهار روش مختلف در این راستا در روزهای آتی میپردازیم.
(انشاا... حداقل سه روش انتقال مختلف را بیان میکنم)
==============
عیدتان مبارک و شب خوش.
بسم الله الرحمن الرحيم با سلام از جناب _H2_ بخاطر مطلب مفيدشون تشکر ميکنم؛ سوالي از خدمتتون دارم و اون اينکه تا چه حد اين موضوع به نظر و سليقه فرد بستگي داره و تا چه حد اصول دخيل هستند؟ لطفا مقاله يا پياده سازي هايي که در اين باره انجام شده و مورد تائيد شما مي باشد رو مطرح بفرمائيد تا مطالعه بيشتري راجع به اين موضوع داشته باشيم. با تشکر فراوان از وقتي که ميگذاريد.
سلام
انتقال استثناها:
چیزی که ما معمولاً با نام خطا در برنامه میشناسیم در واقع یک مکانیزم انتقال اطلاعات بین لایه های مختلف است.
که با هوشمندی زیبا در دات نت به جای کلمه 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) که پیشنهاد کنید مشکلات این تیپی را خواهد داشت.
با تنفسی کوتاه در ساعت آتی مطلب را ادامه خواهیم داد...
Last edited by _H2_; 12-11-2012 at 12:52. دليل: غلط املائی ناشی از تایپ سریع
سلام
ادامه مطالب ...
روش صحیح: (Exception)
Exception ها راه حلی بر مبنای اصول شی گرایی برای برخورد با مسئله فوق الذکر هستند.
بدلیل فرصت کم و عدم تکرار مطالب موجود، فرض میشود دوستان مطلب زیر را قبلاً مطالعه کرده اند:
[ برای مشاهده لینک ، با نام کاربری خود وارد شوید یا ثبت نام کنید ]
[ برای مشاهده لینک ، با نام کاربری خود وارد شوید یا ثبت نام کنید ]
[ برای مشاهده لینک ، با نام کاربری خود وارد شوید یا ثبت نام کنید ]
میدانم طولانی میشود ولی یا من باید اینجا دوباره بنویسم و شما بخوانید یا باید ارجاع بدهم و شما انجا بخوانید، در هر صورت شما باید بخوانید...!
لطفاً مطالعه شود و سپس مطالب بعدی را بخوانید.
=====
ادامه ...
پس طبق مطالب قبل متوجه شدیم Exception در واقع کلاس هایی هستند که خطاها را حمل میکنند و نیازی به تنظیم پارامتر خاصی در ورودی یا خروجی تابع ندارند.
اگر دقت کنید متوجه میشوید که این شیوه استاندارد دات نت در توابع خودش هم است.
به عنوان نمونه دستور زیر را اجرا میکنیم:
این کد میتواند از انواع پروژه های مختلف فراخوانی شود.کد:برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
ولی رویکرد WriteAllText وقوع Exception برای حالات استثنا است تا لایه فراخوان در مورد نحوه عملکرد خود تصمیم بگیرید.
دقت کنید که خیلی مهم است که در این رویکرد دیگر "کد خطا" نداریم، بجایش "کلاس استثنا" داریم.
مثلاً کد زیر میتواند استثنا های زیر را راه اندازی کند.
مثلاً با کد زیر میتوانیم در لایه بالا با این امر تعامل داشته باشیم.کد:برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
در این رویکرد حتی میتوان تغییر زبان UI را هم به سادگی مدیریت کرد...کد:برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مثلاً میتوان دیکشنری از انواع کلاس های استثنا و متن نمایشی معادلشان داشت (که مثلاً از یک فایل XML پر شده باشد)
حتی میتوان خطاهای سفارشی خودمان را تولید کنیم یا خطاهای سلسه مراتبی ایجاد کنیم که به خطاهای دیگری ارجاع داشته باشد.
مثال مسخره ای از حذف تعدادی تصویر مرتبط با عدد شماره کالا
همانطورکه قبلاً هم بیان شد، در واقع این یک روش انتقال اطلاعات از لایه های پایین به سمت بالا استکد:برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
که در تولید و تسخیر کاملاً از قوانین شی گرایی تتبعیت میکند...
میتواند متن و دلیل اتفاق از داخل لایه پایین تنظیم شود و فقط لایه بالا در نحوه نمایش یا برخورد با ان تصمیم بگیرید...
میتوانید شامل اطلاعات اضافه تشریحی برای لایه بالا باشد.
به راحتی رویکرد صحیحی در فراخوانی های تو دو تو دارد و میتواند پیام های فراخوانی های لایه های پایین را از لایه های میانی انتقال دهد
و...
و...
و...
مزیت های این روش واقعاً بیشمار است و از حوصله من یکی خارج است
این روشی مطمئن برای انتقال داده است و تنها قید آن این است که موجب توقف اجرای کد در تمام متدهای فراخوان میشود.
موفق باشید.
هم اکنون 1 کاربر در حال مشاهده این تاپیک میباشد. (0 کاربر عضو شده و 1 مهمان)