استاد

هنرجوی هنرهای رزمی، نزد استاد رفت و گفت:

-« می خواهم استاد مسلم آیکیدو بشوم. اما فکر می کنم بهتر است به جودو هم بپردازم، تا روش های مبارزه ی بیشتری یاد بگیرم، تنها به این گونه می توانم بهتر از همه باشم.»

-« اگر مردی به دشت برود و سعی کند هم زمان دنبال دو راه بدود، سرانجام هر کدام از روباه ها به طرفی می دوند و او نمی تواند تصمیم بگیرد به دنبال کدام یک آن ها برود. وقتی تصمیمش را می گیرد که دیگر دیر شده و آنها دور شده اند و او فقط وقت و نیرویش را از دست داده است.»

«کسی که می خواهد استاد باشد، باید یک چیز را که خودش ترجیح می دهد، انتخاب کند. بقیه اش فلسفه بافی است.»

اصل (DRY (Don’t Repeat Yourself

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

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

 اما یک دلیل که فکر کنم ریشه روانشناسی هم داشته باشد در سالهای اول دانشگاه بوجود می آید و بعدها بعضی ها نمی توانند ترک کنند. شاید جملاتی مانند این که پروژه من چند هزار سطر شد و یا شبیه آن برای خیلی از دوستان آشنا باشد. جملاتی که در ترمهای اول دانشگاه تکرار می شود و تعداد سطرها بدون توجه به هر اصل دیگر، عامل اصلی برتری یک پروژه در بین گروه خاص از دانشجویان می شود. و سپس بعضی از دوستان نمی توانند از دام این عامل برتری خلاص شوند. و اغلب مشکلاتی که بخاطر این مسئله در برنامه هایشان بوجود می آید را با جملاتی مانند اینکه پروژه در این حجم (از لحاظ تعداد سطرها) نگهداریش واقعا مشکل و کار هر کسی نیست و … را تکرار می کنند. و صدها دلیل کوچک و بزرگ می توان پیدا کرد که می تواند عامل مشکل بالا باشد. اما برای رفع این مشکل بد نیست که یک اصل را به نام DRY (Don’t Repeat Yourself ) را مرور کنیم.

تعریف اصلی DRY

DRY: Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

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

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

class Line {

public:

Point start;

Point end;

double length;

};

تکه کد بالا را در نظر بگیرید، فکر می کنید مشکلی روی این کد وجود دارد یا نه. شاید در نگاه اول این کد مشکل نداشته باشد اما در این تکه کد اصل DRY رعایت نشده است. صفت length را در نظر بگیرید، مقدار این صفت با توجه به مقادیر start و end محاسبه می شود و با تغییر هر کدام از این صفات، آن نیز تغییر می کند (همیشه این نوع تکرار کد را با افزونگی در پایگاه داده مقایسه می کنم و می کویم صفتی که  قابل محاسبه از روی صفات دیگر باشد، نیازی به ذخیره سازی ندارد. می شود نرمالسازی در پایگاه داده را مفهومی مشابه این اصل دانست). پس بهتر است این تکه کد به صورت زیر تغییر کند.

class Line {

public:

Point start;

Point end;

double length() { return start.distanceTo(end); }

};

 

می توانیم به سادگی راه حل های زیادی برای رهایی از این دام پیدا کنیم و فکر می کنم نیاز زیادی به بحث روی این موضوع نیست، البته پیشگیری مثل همیشه بهترین شیوه درمان است. اما دوست دارم ادعای جالبی که آقایان  Andy Hunt و  Dave Thomas(اصل DRY، برای اولین با توسط این دو نفر ارائه شده است.) رابیان کنم و دوست دارم نظر شما را در مورد این ادعا بدانم. به نظر شما مرحله نگهداری یک برنامه  از چه زمانی شروع می شود؟ نمی دانم دقیقا پاسخ شما چیست، اما پاسخ دو نفر بالا به این صورت است که برنامه نویسان همیشه در مرحله نگهداری هستند.  و تنها در 10 دقیقه اول یعنی زمانیکه شما برای اولین با یک تکه کد را تایپ می کنید در مرحله نگهداری قرار ندارید و سپس شما بارها و بارها یک تکه کد را تغییر می دهید تا به هدف خود برسد و اینها جزء مرحله نگهداری هستند. حال نظر شما چیست؟

برچسب‌ها:

بدون شرح

 آن که دیگران را می شناسد، خردمند است.

آن که خود را می شناسد، روشنیده است.

آن که بر دیگران پیروز می شود، نیرومند است.

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

آن که شادی را می شناسد، ثروتمند است.

آن که بر راه خویش پا بر جا می ماند، با اراده است.

 

فروتن باش، و اما غرور خویش را حفظ کن.

خم شو، اما سرافراز بمان.

خود را خالی کن، و اما سرشار بمان.

خود را بفرسای، اما تازه بمان.

 

خردمند خود را به نمایش نمی گذارد، و از این راه می درخشد.

خود نمایی نمی کند، و بنابراین او را می بینند.

خود را ستایش نمی کند، و بنابراین سزاوار است.

و از آن جا که رقابت نمی کند، هیچ کس را در جهان یارای رقابت با او نیست.

اصل open-closed

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

مهم نیست که شما کجا کار می کنید، روی چه محصولی کار می کنید و با کدام زبان برنامه نویسی، برنامه نویسی می کنید. یک چیز، همیشه می تواند رخ بدهد. تغییر.

تنها یک چیز تغییر نمی کند. تغییر.

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

اصل open-closed

موجودیت های نرم افزاری برای نمونه کلاس ها، توابع و پیمانه ها باید برای توسعه باز باشند(اجازه داشته باشند)، اما برای تغییر باید بسته باشند(اجازه تغییر را ندارند).

یک تشبیه زیبا(فکر می کنم به زبان اصلی خیلی زیباتر است.)

Code should be closed(to change) like the lotus in the evening. Yet open(to extension) like the lotus flower in the morning.

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

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

یک طراحی می تواند به این صورت باشد که شما یک کلاس Shape تعریف می کنید، که اشکال دیگر از آن کلاس به ارث می برند، و یک کلاس دیگر مثلا با نام DrawManager تعریف می کنید که لیست اشیاء را نگهداری می کنید و مسئول رسم اشکال مختلف بر روی صفحه نمایش است. مثلا متدی یا نام DrawAllShape داریم که با توجه به هر نوع هر شکل تابع مخصوص رسم ان شکل را فراخوانی می کند. در این متد ما کدی شبیه کد پایین خواهیم داشت.

If TypeOf S Is Circle Then

DrawCircle()

ElseIf TypeOf S Is Triangle Then

DrawTriangle()

Elseif

End If

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

حالا تصور کنید که کلاس انتزاعی یا یک اینترفیس به نام Shape تعریف کرده ایم که دارای یک متد به نام Draw می باشد، و تمام اشکال این متد را به ارث می براند و متد Draw را بازنویسی می کنند. در این حالت هر شکلی  جدیدی به برنامه اضافه شود، کلاس shape را به ارث می برد و متد Draw را بازنویسی می کند و نیازی نیست که در کلاس DrawManager تغییری ایجاد کنم و این کلاس، تنها متد Draw هر شکل را برای رسم آن شکل فراخوانی می کند. همانطوریکه مشاهده کردید ما در این حالت در کد مربوط به هیچ یک از کلاس های موجود تغییری ایجاد نکردیم اما برنامه خود را توسعه دادیم.

در بسیاری از الگوهای طراحی یکی از مهمترین ویژگیهای که در نظر گرفته شده است، اصل open-closed می باشد. برای نمونه می توانید الگوی TEMPLATE را بررسی کنید. ما باید بعضی از تغییراتی که می تواند در سیستم رخ دهد را، پیش بینی کنیم و با استفاده از مفهوم abstractions از سیستم خود در مقابل این تغییرات حفاظت کنیم. در واقع می توان گفت که کلید اصل open-closed دو مفهوم abstractions و encapsulation می باشد.

خوب و بد

روزي از روزها ، شبي از شبها خواهم افتاد  و خواهم مرد

اما مي خواهم هرچه بيش تر بروم

تا هرچه دورتر بيفتم

تاهرچه ديرتر بيفتم

هرچه دورترو ديرتر بميرم

نمي خواهم حتي يک گام يا يک لحظه پيش از آنکه مي توانسته ام بروم و بمانم افتاده باشم و جان داده باشم.

استاد شریعتی

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

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

تولدت مبارک

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

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

الگوی Mediator

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

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

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

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

ساعت شروع باید کوچکتر از ساعت اتمام باشد.

هنگامیکه کاربر تعداد مهمانها و ساعت و تاریخ را وارد می کند و یک نوع سرویس را انتخاب کرد، لیست غذا ها فعال می شود. با توجه به تاریخ، ساعت و نوع سرویس، لیست غذاهای ارائه شده متفاوت خواهد بود.

هنگامیکه حداقل یک نوع غذا انتخاب شد، و داده ها دیگر معتبر بودند، دکمه رزور فعال می شود.

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

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

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

  1. سادگی تغییر در برنامه : با استفاده از این الگو وابستگی میان کلاس های مختلف کاهش می یابد و در اکثر موارد فقط با تغییر در کلاس Mediator و یا ایجاد زیر کلاس های از این کلاس، می توانیم تغییرات مورد نظر را اعمال کنیم بدون اینکه تغییری در کلاس های دیگر بدهیم.
  2. افزایش قابلیت استفاده مجدد: با کاهش وابستگی میان کلاس، قابلیت استفاده مجدد کلاس ها افزایش می یابد.

ولی باید توجه داشت که کلاس Mediator باعث کاهش پیچیدگی وابستگی بین کلاس ها می شود، اما این پیچیدگی به درون ساختار Mediator منتقل می شود و ممکن است باعث شود که تغییر آن مشکل شود.

نمودار UML الگو ی Mediator

در نمودار بالا شی Mediator، یک اینترفیس برای ارتباط با اشیاء Colleague تعریف می کند که این اینترفیس توسط کلاس ConcreteMediator پیاده سازی می شود. و Colleague کلاس ها، کلاس های هستند که باهم ارتباط داشتند و ما این ارتباط و وابستگی را از آنها جدا کردم و در کلاس Mediator قرار دادیم.

استاد شریعتی

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

او بود که به من آموخت که:

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

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

عشق در هر رنگی و سطحی با زیبایی محسوس، در نهان یا آشکار، رابطه دارد. چنانچه شوپنهاور می گوید: “شما بیست سال بر سن معشوقتان بیافزید، آنگاه تاثیر مستقیم آن را بر احساستان مطالعه کنید.”!

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

عشق با دور و نزدیگی در نوسان است. اگر دوری به طول انجامد ضعیف می شود، اگر تمام دوام یابد به ابتذال میکشد. و تنها با بیم و امید و تزلزل و اضطرب و “دیدار و پرهیز”، زنده و نیرومند می ماند.

اما دوست داشتن با این حالات ناآشنا است. دنیایش دنیای دیگری است. عشق جوشش یک جانبه است. به معشوق نمی اندیشد که کیست؟! یک ” خود جوشی ذاتی” است، و از این رو همیشه اشتباه می کند و در انتخاب به سختی می لغزد و یا همواره یک جانبه می ماند و گاه، میان دو بیگانه ناهمانند ، عشق جرقه می زند و چون در تاریکی است و یکدیگر را نمی بینند، پس از انفجار این صاعقه است که در پرتو روشنایی آن، چهره یکدیگر را می توانند دید و در اینجاست که گاه، پس از جرقه زدن عشق، عاشق و معشوق در چهره همدیگر می نگرند، احساس می کنند که همدیگر را نمی شناسند و بیگانگی و نا آشنایی پی از عشق – که درد کوچکی نیست – فراوان است.

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

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

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

عشق در دریا غرق شدن است و دوست داشتن در دریا شنا کردن. عشق بینایی را می گیرد و دوست داشتن هدیه می دهد.

الگوی Decorator

وارد فروشگاه می شوید، غرفه ها را یکی یکی نگاه می کنید، بدنبال یک هدیه مناسب برای یک شخص خاص هستید. با زحمت و وسواس زیاد آنرا انتخاب می کنید و به فروشنده تحویل می دهید و می گوید آنرا برایتان کادو و تزئین کند. فروشنده جعبه های تزیئنی مختلف را برای قرار دادن هدیه برای شما نشان می دهد تا یکی از آنها را انتخاب کنید. شما جعبه مورد نظر را انتخاب می کنید. و پیشنهاد می کنید در صورت امکان بعد از قرار دادن هدیه شما و پیچیدن آن در کاغذ کادو، یک شاخه کل روی آن بچسباند. کار تمام می شود. فروشنده می گوید قیمت هدیه ای که انتخاب کرده اید، X تومان است، قیمت جعبه Y تومان است و فیمت شاخه گل  Z تومان است. شما باید سر جمع X+Y+Z تومان را پرداخت کنید.

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

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

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

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

طراحی های مختلفی را می توان برای  هر دو مسئله بالا ارائه داد. اما یک طراحی و راه حل خوب الگوی Decorator است.

در هر دو مثال بالا، ما می خواهیم یک رفتار جدید را به یکی شی اضافه کنیم. ولی می خواهیم بدون استفاده از وراثت این رفتار را به شی اضافه کنیم. این الگو اجازه می دهد، تا یک رفتار را بدون استفاده از وراثت و بصورت دینامیک به یک شی اضافه کنیم. نمودار کلاس این الگو بصورت زیر است:

 

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

در مثال اول، شما یک هدیه، یک جعبه و یک گل می خرید. فرضی کنید می خواهیم، مقدار کل را با الگوی Decorator محاسبه کنیم:

در ابتدا یک شیی از کلاس هدیه 1 ایجاد می کنیم. این کلاس یک متد به نام قیمت برای محاسبه قیمت خود دارد.

هدیه 1  قیمت ()

سپس مشتری یک جعبه را انتخاب کرده بود، و فروشنده هدیه را در داخل آن قرار داده بود. پس ما نیز همین کار را می کنیم، یعنی فرضا نمونه ای از جعبه 1 را ایجاد می کنیم و شی هدیه ایجاد شده را در داخل آن قرار می دهیم. و هدیه را با جعبه تزئین می کنیم.

جعبه 1 قیمت()

هدیه 1  قیمت ()

 

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

گل قیمت()

جعبه 1 قیمت()

هدیه 1  قیمت ()

 

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

کلاس Gift (Component)

Public MustInherit Class Gift

    Public MustOverride Function Cost() As Double

End Class

کلاس Decorator

Public MustInherit Class Decorator

    Inherits Gift

End Class

کلاس Gift1 (ConcreteComponent)

Public Class Gift1

    Inherits Gift

    Public Overrides Function Cost() As Double

        Return 30000

    End Function

End Class

کلاس Gift2 (ConcreteComponent)

Public Class Gift2

    Inherits Gift

    Public Overrides Function Cost() As Double

        Return 10000

    End Function

End Class

کلاس Box1 (ConcreteDecorator )

Public Class Box1

    Inherits Decorator

    Private Gift As Gift

    Public Sub New(ByVal Giftvar As Gift)

        Gift = Giftvar

    End Sub

    Public Overrides Function Cost() As Double

        Return 1000 + Gift.Cost

    End Function

End Class

کلاس Box2 (ConcreteDecorator )

Public Class Box2

    Inherits Decorator

    Private Gift As Gift

    Public Sub New(ByVal Giftvar As Gift)

        Gift = Giftvar

    End Sub

    Public Overrides Function Cost() As Double

        Return 1500 + Gift.Cost()

    End Function

End Class

کلاس Flower (ConcreteDecorator )

Public Class Flower

    Inherits Decorator

    Private Gift As Gift

    Public Sub New(ByVal Giftvar As Gift)

        Gift = Giftvar

    End Sub

    Public Overrides Function Cost() As Double

        Return 2000 + Gift.Cost

    End Function

End Class

ماژول Main

Sub Main()

        Dim Gift1 As Gift = New Gift1()

        Gift1 = New Box1(Gift1)

        Gift1 = New Flower(Gift1)

        System.Console.WriteLine(“Price = “ & Gift1.Cost)

 

        Dim Gift2 As Gift = New Gift2()

        Gift2 = New Box1(Gift1)

        Gift1 = New Flower(Gift1)

        System.Console.WriteLine(“Price = “ & Gift1.Cost)

        Console.ReadLine()

 

    End Sub

 

زیبایی

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

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

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

می گفت وقتی نرگس مرد، اوریادها- الهه ی جنگل – به کنار دریاچه آمدند که از یک دریاچه آب شیرین، به کوزه ای سرشار از اشک های شور استحاله یافته بود.

اوریادها پرسیدند: «چرا می گریی؟»

دریاچه گفت: «برای نرگس می گریم».

 اوریادها گفتند: «آه، شکفت آور نیست که برای نرگس می گریی …»و ادامه دادند: « هر چه بود، با آنکه همه ما همواره در جنگل در پی اش می شتافتیم، تنها تو فرصت داشتی از نزدیک زیبایی اش را تماشا کنی».

دریاچه پرسید: «مگر نرگس زیبا بود؟».

اوریادها، شگفت زده پاسخ دادند: «کی می تواند بهتر از تو این حقیقت را بداند؟ هر چه بود در کنار تو می نشست».

دریاچه لختی ساکت ماند. سرانجام گفت:

«من برای نرگس می گریم، چون هر بار از فراز کناره ام به رویم خم می شد، می توانستم در اعماق دیدگانش، بازتاب زیبایی خودم را ببینم».

کیمیاگر گفت: «چه داستان زیبایی».

پائولو کوئلیو

مقدمه کتاب کیمیاگر

از زیبایی نوشتم. اما یکی از زیباترین هنرها و اولین هنر نزد بشر، هنر رقصی است. و زیبایی این هنر را می توانید در حرکات زیبا و ظریف دوست خوبم، استاد یاشار ایرانی مشاهده کنید. شما را حتما به دیدن کارهای زیبای ایشان و گروهشان تشویق می کنم. سایت گروه هنرهاي آئيني آذربايجاني “اوتلار”