PDA

View Full Version : سوال: نظر برای پیاده سازی شکل خاصی از Object Oreinted



ghayegh
جمعه 26 مهر 1387, 00:41 صبح
با سلام
:لبخندساده:
من یک کد ساده با C# نوشتم که فایلش را به سایت فرستادم . می خواستم هر کس می تونه به این سوال نگاه کنه و بگه که آیا راه حل بهتری هم برای پیاده سازی Object Oreintedمربوط به پروژه هست یا نه و اینکه آیا اینطور پیاده سازی مشکلی ندارد ؟ ضمنا فایلی که فرستادم مربوط به Visual Studio.NET 2005است.
:خجالت:
البته برای اینکه همان اول متوجه شوید که ساختار برنامه نویسی ام چطور است ، یک فایل Gif هم با نام University در همان پوشه ی برنامه ی اصلی است که اگر از اول آن را ببینید ، تمام مطلب را تا ته خط می روید. من در این فایل تصویری یک جورایی UML را با طراحی DataBase ترکیب کرده ام . هر مستطیل در این فایل تصویری ، یک کلاس است و آن چنگک ها هم ، همان ارتباطات یک به چند در مبحث DataBase است.
ممنون

SMRAH1
جمعه 26 مهر 1387, 07:28 صبح
سلام

اول اين نکته رو تاکيد کنم که احساس کردم مي خواهيد يک DataBase ساده رو (احتمالا براي آموزش) طراحي کنيد.در نتيجه تمام نکات بعدي متاثر از اين درک من خواهد بود.

قبل از هر چيز يک اشاره کوچکي به طراحي پايگاه داده مي کنم(جايش اينجا نيست ولي در هر حال با يک اشاره رد ميشوم).در اين پايگاه با اين که رابطه درس-استاد يک رابطه چند به چند است،ولي رابطه درس-استاد--کدکلاس يک رابطه يک به چند است و نياز به جدول جداگانه براي درس-استاد-کدکلاس نيست و کدکلاس مي توان در جدول درس-استاد ادغام شود.

اما در مورد طراحي برنامه: به نظر من بزگترين مشکل در هنگام کار با برنامه ها عدم پشتيابني از يک راه کار (معمولا ساده) براي برقراري ارتباط بين اشيا است.براي روشن شدن مطلب يک مثال مي زنم.در VB6 (دوستاني که کار کرده اند به ياد دارند) براي تغيير عنوان يک دکمه يا برچسب (Label) خصوصيت به نام caption وجود داشت در حالي که در کنترل هايي مثل CobmoBox و TextBox و ... خصوصيت Text موجود بود.با اينکه اين اسامي باعث درک بهتر از کنترل مي شد (قطعا براي نام عنوان در دکمه ها Caption بهتر از کلمه text است) ولي يک ايراد بزرگ به وجود مي آورد.اگر مي خواستيد عناوين را عوض کنيد،بايد با توجه به اينکه خصوصيات شما از چه نوعي است،خصوصيت Caption و Text را به کار مي برديد.اين مشکل در #C و VB.NET حل شده و شما با فقط يک خصوصيت به نام Text طرف هستيد و کافيست که بدانيد که شي مورد نظر يک کنترل است،در اين صورت با استفاده از خصوصيت Text مي توانيد عناوين را تغيير دهيد.

در اين برنامه هم به نظرم يک راه ارتباطي استاندارد براي برقراري ارتباط تعريف نشده است.براي برقراري راه ارتباطي دو گزينه پيش روي ماست.اول استفاده از Interface که باعث مي شود با معرفي متدهايي در آن و پياده سازي در کلاس هاي مورد بحث،اين راه ارتباطي را ايجاد کنيد (مثلا اينکه شي چيست و ....).راه دوم (که من پيشنهاد مي کنم) استفاده از وراثت است.به اين مفهوم که يک کلاس پايه اي براي اين موردها(استاد،کدکلاس و ..) پياده سازي کنيد.براي اين منظور دو راهکار متفاوت به نظرم مي رسد.اول معرفي کلاسي به نام Record که همه کلاسهاي ديگر (استاد،دانشجو و کد کلاس و ...) از آن مشتق مي شود و داراي متد هايي براي دريافت نام يک خصوصيت (با توجه به ايندکس آن) يا مقدار يک فيلد (با توجه به ايندکس يا نام) و ... که معمولا در هر رکود مورد نياز است،باشد.در اين صورت نيز بايد يک کلاس مديريت براي رکود ها بنويسيد.دوم پياده سازي يک کلاس به نام Tabel که درواقع وظيفه مديريت فيلدها و عناوين و همچنين مقادير را برعهده دارند(چيزي کاملا شبيه همان اتفاقي که در پايگاه داده مي افتد،البته از ديد ناظر).در اينجا کلاس ،مثلا کلاس استاد،در واقع وارث يک ،Tabel است و در پياده سازي آن متناسب با داده هاي استاد،اهتمام شده است.

در هر حال اينها نظر بنده است و قطعا خالي از اشکال (کلي يا جزئي) نيست.

موفق باشيد

ghayegh
جمعه 26 مهر 1387, 11:02 صبح
با سلام و تشکر از توجهی که کردید
:تشویق:
آن اشکالی که راجع به رابطه ی یک به چند گفتید ، تصحیح کردم و دوباره فایل آن را به سایت فرستادم . البته آن فایل GIFرا هم دوباره ویرایش کردم ( نمی دانم آن چه می گفتید ، شد یا نه ).
:خجالت:
من منظور شما را از شکل بهتری از پیاده سازی که گفتید ، خیلی متوجه نشدم . اگر زحمتی برایتان نیست ، مثل آن فایل GIF ای که درست کردم ، یک فایل ساده ی اینچنینی درست کنید تا شاید طراحی شما را متوجه شوم.
:لبخندساده:
ممنون

ghayegh
جمعه 26 مهر 1387, 13:24 عصر
با سلام
اینکه گفته بودید :


به نظر من بزگترين مشکل در هنگام کار با برنامه ها عدم پشتيابني از يک راه کار (معمولا ساده) براي برقراري ارتباط بين اشيا است

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

SMRAH1
جمعه 26 مهر 1387, 21:14 عصر
سلام

توي اين طراحي جديد،کاملا متوجه منظور من نشديد.براي توضيح بيشتر فرض کن دروس ما ،رياضي،فيزيک،زبان و ... است و استاد ها هم الف،ب،ج و ... هستند.در جدول کد کلاس وقتي ما ميگوييم مثلا کلاس داراي کد 101 است،در واقع اين کلاس همان کلاس فيزيک آقاي الف است.به عبارت ديگر به محض تعريف کد،بايد يک نام درس و يک نام استاد هم به آن بيافزاييم.در واقع در نمودار شما عملا بايد جداول کد کلاس و درس-استاد يکي باشند و کد کلاس به صورت يک فيلد (که فيلد کليد رکود هم هست) در اين جدول قرار مي گيرد.

اما در مورد پياده سازي؛شما با استفاده از ObjectManagement،سعي در ايجاد يک مديريت واحد داشته ايد.اين به خودي خود خوب است ولي به نظر من در پروژه هاي بزرگتر،ناکارامدي خود را نشان مي دهد چون اين مديريت از خارج اشيا به آنها القا مي شود و کاري به ساختار دروني آنها ندارد.در واقع آنچه من در مورد راه کار هاي يکسان براي ارتباط با جداول عنوان مي کنم و در برنامه شما نيست را مي توان در يک جمله خلاصه کرد «کلاس Dars هيچ نقطه اشتراکي با کلاس Ostad ندارد» و اين يعني عدم وجود يک راهکار ارتباطي هماهنگ با کلاس ها.در واقع interface يا کلاس پايه به شما امکان مي دهد که در کلاس Dars و کلاس ostad يک نقطه مشترک (نه در مفهوم بلکه در پياده سازي) ايجاد کنيد.

موفق باشيد

ghayegh
شنبه 27 مهر 1387, 17:03 عصر
با سلام
از توضیحاتتان ممنون .
:لبخند:
گفته بودید :


به عبارت ديگر به محض تعريف کد،بايد يک نام درس و يک نام استاد هم به آن بيافزاييم.در واقع در نمودار شما عملا بايد جداول کد کلاس و درس-استاد يکي باشند


اگر کاری که گفتید ، انجام دهم ، آنگاه مشکلی که بوجود می آید ، این است که اگر اپراتوری بخواهد فقط این اطلاعات را در دیتابیس وارد کند که هر استادی ، چه درسی را می تواند بدهد ، دیگر نمی تواند . چون همان لحظه باید بگوید که کد کلاس او چیست و تمامی مشخصات کد کلاس از جمله :
کد کلاس : پ روز چهارشنبه ساعت 7:30 تا 9:30 را هم وارد کند.

گفته بودید :


در برنامه شما نيست را مي توان در يک جمله خلاصه کرد «کلاس Dars هيچ نقطه اشتراکيبا کلاس Ostad ندارد» و اين يعني عدم وجود يک راهکار ارتباطي هماهنگ با کلاس ها.


کاش راجع به این نقطه ی اشتراک بیشتر توضیح می دادید . من فکر نمی کنم در مقایسه ی درس و استاد ، اطلاعاتی مهمتر از این وجود داشته باشد : که هر استادی چه درسی را اخذ کرده . خوب گرفتن اطلاعات این ارتباط هم که در برنامه هست . من کلاس Vaset_DarsOstadرا هم به همیندلیل به برنامه اضافه کردم . این کلاس ظرفی برای نگهداری دو کلاس Dars و Ostadاست . این کلاس می گوید هر آبجکتی که از این ظرف گرفته می شود ، داخلش استاد و درس قرار می گیرد . این استاد و درس ، در کنار یکدیگر و در داخل یک ظرف قرار می گیرند . در حقیقت جائی که هم استاد هست و هم درس ، کلاس Vaset_DarsOstadاست . در این کلاس است که این دو به هم مربوط می شوند. اما قبل از آن ، یعنی جائی که کلاس Darsرا مقداردهی می کردیم ، و بعد هم رفتیم و کلاس Ostadرا مقداردهی کردیم . خوب بله تا اینجا دو کلاس درس و استاد ، هیچ ارتباطی با هم نداشتند. ولی وقتی آبجکت گرفته شده از درس و استاد را به Vaset_DarsOstadپاس کردیم ، به هم ارتباطشان دادیم.
:لبخندساده:
اگر باز هم ایرادی می بینید ، لطف کنید بگوئید.
:خجالت:
ممنون.

SMRAH1
شنبه 27 مهر 1387, 18:33 عصر
سلام

1) اگر منظورتان از طراحی کلاس درس-استاد:

هر استادی ، چه درسی را می تواند بدهدبوده،حق با شماست.

2) اصلا منظورم، ارتباط مفهومی کلاس ها (مثلا دانشجو و استاد) نیست بلکه ایجاد یک روش استاندارد برای برخورد با همه کلاسهایی است که داده ها را ذخیره می کنند .(تاکید کردم که 'نه در مفهوم بلکه در پياده سازي').به عبارت دیگر اگر شما یک جدول دیگر به برنامه بیافزایید،باید کلاس ObjectManagement را متناسب با افزودن این کلاس،تصحیح کنید.البته در هنگام تصحیح کاملا از نحوه کار کلاس جدید آگاه هستید.ولی اگر تمام کلاس های داده،دارای یک راه کار ارتباطی مشترک باشند،بدون نیاز به نحوه پیاده سازی کلاس جدید،به صرف اینکه شما می دانید این کلاس داده جدید آن راهکار استاندارد را پشتیبانی می کند،می توانید کلاس ObjectManagement را با تغییرات کمتری آماده بهره برداری کنید.

موفق باشید

ghayegh
شنبه 27 مهر 1387, 23:04 عصر
با سلام
:لبخندساده:
تا اینجا ، بعضی از ایراداتی که از برنامه ام گرفتید ، خیلی موثر و مفید بود و باعث شد که بهینه ترش کنم . به خصوص مشکل آخری که گفتید :


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

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

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

نمی دانم بالاخره آن چیزی که می گفتید ، شد یا نه . اگر باز هم مشکلی می بینید ، لطفا دوباره ذکر کنید..

باز هم از ایراداتی که تا الان گرفتید ، بی نهایت سپاسگزارم .

ghayegh
یک شنبه 28 مهر 1387, 11:32 صبح
با سلام
:خجالت:
من البته یک ایبوک خوب در رابطه با همین قضیه ی مدیریت آبجکت ها ( و البته نه فقط همین قضیه) دارم که فایلش را به سایت فرستادم . این ایبوک راجع به مدلهای مختلف Design Pattern در C# است . من خودم دو سرفصل اصلی این ایبوک یعنی مدلهای Creational و Structural را خواندم . ولی در رابطه با قضیه ای که گفتید ، خیلی راضیم نکرد . به خاطر همین آن کلاس ObjectManagement را در برنامه ام نوشتم.

SMRAH1
یک شنبه 28 مهر 1387, 15:02 عصر
سلام

اول از همه به دوستان پيشنهاد مي کنم که حتما PDF پست بالا رو ببينند (در مورد کاربر Pattern ها در #C و مثالهايي براي آنها صحبت شده و به زيان انگليسي است).

دوم برنامه رو هم ديدم.با اينکه با توجه به يک ايده خلاقانه (استفاده از HashTabel) برخي ايرادها از جمله نياز به دانستن پياده سازي کلاس داده،فرار کرده ايد،ولي در کل اين روش کارآمد نيست.

براي آنکه بهتر متوجه منظور من شود به همان PDF بالا ،صفحه 41 ارجاع مي دهم.در اين صفحه،ابتدا کلاس Abstract با نام DataObject معرفي شده و سپس کلاس CustomersData از آن مشتق شده است.در اين حالت چناچه کلاس هاي داده اي ديگري هم باشند (مثلا SalersData) که از همان DataObject مشتق شده باشند (که البته بايد اينگونه باشد)،براي حرکت به رکورد بعد کافيست متد NextRecord کلاس را فراخواني کنيد بدونه اينکه بدانيد کلاس داده شما دقيقا از چه نوع است.در واقع اين متد در آن کلاس (بدليل ارث بري از DataObject) موجود است.و اين يعني يک راهکار استاندار (و يکسان) براي برخود با داده ها.

موفق باشيد

ghayegh
یک شنبه 28 مهر 1387, 18:40 عصر
با سلام
:لبخندساده:
من آن صفحه ای را که گفتید ، ببینید ، دیدم . یک فایل پاورپوینت از طراحی که کردم ، به سایت فرستادم . لطف کنید آن را ببینید که آن چیزی که می گفتید ، بالاخره درآمده یا نه .
گرچه خیلی اینطوری نمی توان گفت . باید در برنامه نویسی دید که چه چیزهایی اضافه می شود.
جالب است که دقیقا من هم قبلا همین مدل را برای پیاده سازی مثالی که گفتم ، انتخاب کردم . ولی به دلیل اینکه فکر کردم ، یک کم پیچوندتش ازش استفاده نکردم.
ضمنا این را هم بگویم ، متاسفانه این ایبوکی که فرستادم ، با وجود اینکه خیلی مثال های خوبی داره ، ولی گاهی اوقات اشتباهاتی در نامگذاری دارد.

SMRAH1
دوشنبه 29 مهر 1387, 11:10 صبح
سلام
منظور من همین بود.
هیچ الزامی برای استفاده از کلاس پایه برای این مورد نیست و می تواندی از Interface هم برای این موضوع استفاده کنید.

موفق باشید

ghayegh
دوشنبه 29 مهر 1387, 11:24 صبح
با سلام و تشکر دوباره
:لبخندساده:
من همانطور که قبلا گفتم تصور می کنم که مدل Builder ( از ایبوکی که معرفی کردم ) ، کمی قضیه را پیچانده . در این مدل ، ته تمام کارهایی که دارد انجام می شود ، توسط یک ArrayList در کلاس CustomerData یا همان Refined Abstraction است . یعنی اطلاعات تمام Object ها را در ArrayList ذخیره می کند. متدهای NextRecord و DeleteRecord و ShowRecord و غیره ، به نظر من تماماً متدهایی هستند که Override شده ی متدهای اصلی خودِ ArrayList است . منظورم این است که متدهای تعریف شده در کلاس CustomerData یا همان Refined Abstraction ، کار خاصی انجام نمی دهند ، فقط با نامگذاری شان تحت عنوانِ NextRecord و DeleteRecord و ShowRecord ، فقط وضوح را بیشتر کرده اند. شما تصور کنید حالتی را که این متدهای NextRecord و DeleteRecord و ShowRecord نباشد ( ضمناً ArrayList تعریف شده در کلاس CustomerData یا همان Refined Abstraction ، از نوعِ Public تعریف شده باشد) . آنگاه براحتی از خارج از کلاس CustomerData یا همان Refined Abstraction ، و با استفاده از همان ArrayList ی که Public تعریفش کردیم ، کارهای انجام شده توسط متدهای NextRecord و DeleteRecord و ShowRecord ، قابل انجام است . مثلا برای NewRecord می گوئیم :


Dars d = new Dars();


d.ArrayList-Dars.Add(‘Operation System’);
یا مثلا متدهای NextRecord و PriorRecord و ShowRecord و ShowAllRecord ، با همان foreach ی که من در فایل خودم نوشته بودم ، قابل انجام است. برای DeleteRecord هم که مشخص است.
:خجالت:
به هر حال کسی که می خواهد برنامه نویسی کند ، کسی است که می داند یک ArrayList ، دارای متدهای Add و Remove و غیره است . پس یک ArrayList ، تمام این خاصیت ها و رفتارها را به خودی خود ، دارد و نیاز نیست که برای آن ، یک تعریف و نامگذاری جدید داشته باشیم . حتی اگر مسئله ی وضوح خیلی مهم باشد که هست ، مگر متدهای Add و یا Remove و یا foreach ، وضوح ندارند که حالا ما بیائیم یک نامگذاری جدیدی نسبت دهیم ؟

البته من می دانم در جواب به من می خواهید بگوئید که بیشتر این قضیه مد نظرتان بوده که همه ی کلاس ها از یک استاندارد یکسان پیروی کنند و البته قبلا هم گفتید که بیشتر برای اینکه کارایی بالا برود ، این را می گوئید :

1- همانطور که گفتم ، ArrayList ، به خودی خود تمام کارهای تعریف شده توسط متد ها را انجام می دهد.
2- من تصور می کنم مدلِ Builder ، به جای استانداردسازی ، یک وابستگی بیهوده را ( به دلایلی که گفتم ) ، در تمام کلاس ها ، نسبت به کلاس Data Object یا همان Abstraction ، ایجاد کرده . ( من می دانم بعضی وقت ها ، تعریف کلاس Abstract ، لازم است ، مثل زمانی که کلاس های مشتق شده از کلاس Abstract ، با هم متفاوتند . مثلا اگر کلاس مربع و کلاس مثلث داشته باشیم ، هر کدام یک جور محیط و مساحت را حساب می کنند ) . اما در اینجا مگر کار اصلی که همان کارهای یک ArrayList است ، خیلی با هم فرق می کند ؟

و حالا من :
من آمدم و یک کلاس ObjectManagement درست کردم . ته مفهوم کلاس من هم با ArrayList پیاده سازی شده ( مثل عمق مفهوم مدل Builder ) . منظورم این است که من هم آبجکت هایم را در ArrayList ذخیره کرده ام.
من به جای اینکه مثل مدل Builder ، کدهای Override اضافی برای هر کلاس داشته باشم ، ( که این کدها باید در هر کلاسی در Builder اضافه می شد و جالب هم هست که متدهای Override همه ی کلاس ها دارند مثل هم عمل می کنند! ) ، یک کلاس ObjectManagement درست کردم که به همه ی درخواست ها ، ArrayList حاوی آبجکت هایش را می داد.
:متفکر:
باز هم لطف می کنید اگر نظراتتان را بگوئید.

SMRAH1
دوشنبه 29 مهر 1387, 17:45 عصر
سلام

سعي مي کنم نکاتي رو که گاه تاييد صحبت شما است و گاه نکته هاي پشت پرده اين مفاهيم رو در چند جمله خلاصه کنم:

1) همانطور که طراحي مناسب يک نرم افزار مي تواند باعث افزايش کارآيي و رضايت مندي و ... و کاهش هزينه و کد نويسي و ... شود ،به همان نسبت يک طراحي بد و نامناسب مي تواند انرژي ،زمان و .. را به شکل بهينه هدر دهد.در واقع مفهوم مهندسي نرم افزار (نه مهندسين نرم افزار) و تحليلگر نرم افزار در ايجاست که شکل مي گيرد و اهميتش هويدا مي شود.

2) معمولا در مثالهاي آموزشي،هدف نحوه نمايش کارکرد (يک روش يا دستور) است و معمولا به بهينه بودن توجه نمي شود.تا کنون فقط يک کتاب رو ديدم (کتاب ريچي-گرونيگان در آموزش C) که هر مثال آن آنقدر هوشمندانه انتخاب شده است که علاوه بر آموزش،بهينه بودن را هم مي توان درک کرد (هر مثال آن کتاب را به روشي غير آنکه گفته است حل کنيد،از قدرت زبان C دور مي شويد و در هر مثال دليل وجود آن مفهوم يا عملگر يا .. رو مشاهده مي کنيد).

3) خيلي اوقات در پروژه هاي کوچک ايراد ها به چشم نمي آيند در عين حال زوائد کمتر به چشم مي آيند.اما هرچه پروژه بزرگتر شود ،بهتر در مورد تحليل اوليه و ساختار به کار رفته مي توان نظر داد.

4) در اينکه گاهي اوقات متدها مانند هم باز نويسي مي شوند شکي نيست (در واقع تفاوت متدها Abstract و Virtual در همين است که متد Virtual داراي يک پياده سازي اوليه است و در صورت نياز بازنويسي مي شود) اما بايد حتما به اين نکته که آيا واقعا ساختار اين مفاهيم مثل هم هستند،تشکيک کرد.براي نمونه متد New که بايد باز نويسي شود،اگر من بودن آن را به اين شکل معرفي مي کردم:

bool abstract New(string atrName,Object [] objs)
چون اولا هر جدول داراي پارامترهايي با تعداد و نوع متفاوتي است و ثانيا بايد حتما افزودن آن به داده هاي جاري تاييد شود.حالا آيا اين نکات در پياده سازي هر کلاس داده نياز به پياده سازي مستقلي ندارد (هر چند الگوريتم کلي يکي است ولي به تعداد و نوع داده و همينطور اعتبار سنجي آنها متفاوت است)؟.

موفق باشيد