فصل چهارم Clean Architecture - برنامه‌نویسی ساخت‌یافته

1. مقدمه:آقای دیکسترا در سال 1930 در شهر روتردام هلند متولد شد. او از بمباران‌های هلند توسط آلمانی‌ها در جریان جنگ جهانی دوم جان سالم به در برده و در سال 1948 از دبیرستان با بالاترین نمرات در ریاضی، فیزیک، شیمی و زیست‌شناسی فارغ التحصیل شد. در مارچ سال 1952 و در سن 21 سالگی (سالها قبل از اینکه خیلی از ما به دنیا بیایم) در مرکز ریاضیات آمستردام به عنوان یکی از اولین برنامه‌نویسان هلندی مشغول به کار شد.در سال 1955 و در حالی که تنها 3 سال از اشتغال او به کار برنامه نویسی می‌گذشت و هنوز دانشجو بود، به این نتیجه رسید که چالش‌های آن زمان دنیای توسعه‌نرم افزار بیش از رشته‌ای مثل رشته فیزیک است و تصمیم گرفت برنامه‌نویسی را به عنوان حرفه‌ای بلند مدت انتخاب کند.در سال 1957 او با ماریا دبیز ازدواج کرد و در آن زمان، به عنوان بخشی از مراسم ازدواج در هلند باید به بیان حرفه خود می‌پرداختید. اما جامعه آن زمان برنامه‌نویسی را به عنوان حرفه و کار قبول نداشت. اصلا در آن زمان کسی در باره کاری به نام برنامه نویسی چیزی نشنیده بود. برای رهایی از این شرایط شاه داماد مجبور به پذیرش شغل فیزیکدان نظری شد تا از این آخرین خان رستم عبور کند.از آنجایی که او تصمیم گرفته بود برنامه‌نویسی را به عنوان حرفه خود انتخاب کند، در مورد این تصمیم با رئیس خود آدریان فن جینگاردن صحبت کرد. او نگران بود که هیچ کس برنامه‌نویسی را به عنوان یک کار جدی تلقی نکند. اما رئیس دیکسترا به او گفت باید از این فرصت استفاده کند و باید به عنوان یکی از پیشگامان این کار برای تبدیل توسعه نرم‌افزار به یک دانش تلاش کند. ( تقریبا مثل شرایطی که ما در ایران تجربه می‌کنیم و در برابر هر خلاقیتی قطعا کلی حمایت و انرژی دریافت می‌کنیم. :-| )او فعالیت خود را در شرایطی که رایانه‌ها بزرگ، شکننده، کند، غیرقابل اطمینان و محدود بودند شروع کرد. در آن زمان برنامه‌ها به صورت باینری نوشته می‌شدند و یا اگر بنا به استفاده از زبان سطح بالایی قرار می‌گرفت، برنامه‌ای بسیار شلوغ و شلخته اسمبلی توسعه داده می‌شد. رایانه‌ها برنامه‌ها را در قالب نوار، یا کارت پانج دریافت می‌کردند و چرخه کامپایل، تست و ویرایش برنامه‌ها بسیار کند و زمانگیر بود.در چنین شرایط وحشتناکی دیکسترا شروع به ارائه دستاورد‌های خود کرد که دنیای نرم‌افزار را تا امروز مدیون خود ساخته است.تصویر آقای دیکسترا در کلاس درس2. اثبات:اولین مشکلی که توجه دیکسترا را به خود جلب کرد این بود که برنامه‌نویسی بسیار سخت بود و برنامه نویسان نمی‌توانستند خیلی خوب برنامه‌نویسی کنند. حتی برای نوشتن ساده‌ترین برنامه‌ها نیز توسعه دهنده‌ها نیاز داشتند به جزئیات خیلی زیادی توجه کنند و مطالب زیادی را به خاطر بسپارند که برای مغز انسان‌ها بیش از حد پیچیده بود و در راه انجام این کار هیچ راهنمایی وجود نداشت. فراموش کردن یک نکته جزئی باعث می‌شد برنامه‌ای که در ظاهر تصور می‌شد باید به خوبی کار کند، در عمل دچار مشکل باشد.راهکار دیکسترا برای حل این مشکلات استفاده از روش اثبات ریاضیات بود. او می‌خواست یک سلسله مراتب اقلیدسی از قضایای فرضیه ها ، نتایج و لمها را ایجاد کند. او فکر می‌کرد برنامه نویسیان می‌توانند از این سلسله مراتب مانند ریاضی‌دانان استفاده کنند. در حقیقت او تصویر می‌کرد برنامه نویسان می‌توانند تعداد حقیقت اثبات شده از قبل را به کمک کدنویسی به هم متصل کنند و در نهایت نتیجه ای درست بگیرند. دیکسترا متوجه شد برای انجام این کار باید بتواند راهکار‌هایی برای نوشتن اثبات‌های پایه‌ای برای الگوریتم‌های ساده ارائه کند. در این مرحله او متوجه چالشی بودن کاری که در پیش گرفته شد.او در طول تحقیقاتش متوجه شد وجود برخی goto در برنامه‌ها باعث می‌شود که نتوان برنامه‌ها را به ماژول‌های کوچک شکاند. در نتیجه اگر شما نتوانید برنامه‌ها را به واحد‌های کاری کوچکی بشکانید، امکان استفاده از روش تقسیم و غلبه نیز وجود ندارد. این اولین مشکل بود. برای داشتن اثبات‌های‌ پایه برای الگوریتم‌های ساده باید بتوان از روش تقسیم و غلبه استفاده کرد.در طرف مقابل دستورات goto قرار داشتند که این مشکل را ایجاد نمی‌کردند. با بررسی دقیق‌تری روی دستورات goto که ساختار برنامه را دچار مشکل نمی‌کردند او متوجه شد این دستورات شامل دستوراتی برای انتخاب و تکرار می‌باشند. این دستورات پایه ای برای دستورات امروز مثل if/then/else و do/while بودند. بخش‌هایی از برنامه که فقط از این دسته دستورات goto استفاده می‌کردند به سادگی قابل شکستن به ماژول‌های کوچک‌تری بودند. دیکسترا می‌دانست این دستورات کنترلی هنگامی که در ساختار اجرای متوالی قرار بگیرند، کارایی ویژه‌ای پیدا می‌کنند. البته این مورد 2 سال قبل توسط بوهم و ژاکوپینی به اثبات رسیده بود. آن‌ها اثبات کرده بودند که هر برنامه‌ای می‌تواند از ترکیب سه ساختار ایجاد شود که این سه ساختار عبارتند از :توالیانتخابتکراراین دستاوردی مهم بود: ساختاری‌های بسیار کنترلی که باعث ایجاد ماژول‌های کوچک قابل اثبات می‌شد می‌توانستند ساختار هر برنامه‌ای را ایجاد کنند. از اینجا بود که برنامه نویسی ساخت‌یافته متولد شد.دیکسترا نشان داد که دستورات متوالی با یک بار بررسی پشت‌سرم هم قابل تایید و اثبات هستند. در این روش برای بازبینی تعدادی ورودی دریافت شده و بر اساس ترتیبی خاص پردازش و بازبینی شده و خروجی‌‌هایی تولید می‌شود. این کار تفاوت چندانی با اثبات‌های معمول ریاضی ندارد.در این روش هنگامی که با یک ساختار انتخابی سر و کار داشته باشیم، چندین بار مراحل را طی خواهیم کرد و هر بار یکی از مسیر‌های قابل انتخاب را دنبال خواهیم کرد. اگر در پایان هر بار مسیریابی و ادامه راه به نتیجه درستی برسیم کار به پایان می‌رسد.ساختار‌های تکراری اما کمی متفاوت است. برای اثبات یک تکرار صحیح باید از استقرا استفاده کنیم. او ابتدا برای ساختار‌های تکرار حال 1 را بررسی می‌کردو سپس حالت N و N +1 را بررسی و اثبات می‌کرد در نهایت شرط‌های ابتدایی و انتهایی را نیز اثبات می‌کرد.هر چند این روش اثبات بسیار پرزحمت و زمانگیر بود، اما به هر حال نتیجه‌ای حاصل می‌شد و این دستاوردی بسیار بزرگ بود. 3. یک اعلامیه دردناک:در سال 1968 دیکسترا نامه‌ای را برای سردبیر CACM که در مارچ منتشر شده بود ارسال کرد و عنوان این نامه این بود " استفاده از عبارات goto مضر است" و در این مقاله او نظریه ساختار‌های سه‌گانه خود را شرح داد.در این زمان در جامعه برنامه نویسی آشوبی به پا شد. در آن زمان هنوز اینترنت و شبکه‌های اجتماعی وجود نداشت و جامعه برنامه نویسی نتوانست آنطور که باید و شاید از خجالت اقای دیسکترا در بیاید. ( امکان پیوند اقوام و بستگان ایشان و ابلاغ سلام خدمت برخی دیگر از بستگان ایشان توسط جامعه برنامه نویسان میسر نشد). البته آن‌ها نامه‌ها و مطالبی را برای بسیاری از مجلات آن زمان ارسال کردند که لزوما خیلی مودبانه نیز نبودند. در این بین البته با اینکه مطالب منفی زیادی ارسال شد، اما برخی نیز به شدت از این نظریه استقبال کرده و آن را مثبت ارزیابی کردند. اینجا بود که جنگی برای نزدیک به 10 سال بین این دو گروه به راه افتاد.در نهایت دیکسترا این جنگ را با پیروزی به پایان رسانید و مجادله‌ها به پایان رسید. زمانی‌که زبان‌های برنامه‌نویسی جدید پا به جهان گذاشتند اهمیت کمتری برای دستور goto قائل شدند و کم کم این دستور از چرخه برنامه‌نویسی حذف شد. اغلب زبان‌های برنامه‌نویسی مدرن یا دستور goto ندارند یا به صورت بسیار محدود قابل استفاده است و اگر توسعه دهنده‌ای این دستور را در کد توسعه دهنده دیگری مشاهده کند قطعا اولین چیزی به ذهنش می‌رسد ناتوانی ذهنی نویسنده است و بعد به بررسی دقیق شرایط خواهد پرداخت.این روز‌ها همه ما برنامه‌های ساخت یافته می‌نویسیم. نه به خاطر اینکه به این کار علاقه داریم و این روش را انتخاب کرده‌ایم بلکه به خاطر اینکه اصلا زبان‌های برنامه‌نویسی حالت دیگری را در اختیار ما قرار نداده‌اند و نمیتوانیم کنترل برنامه را بدون در نظر گرفتن شرایط از هر جایی به جای دیگر منتقل کنیم.البته برخی توسعه دهندگان دستورات break و exceptionها را معادل با توجه به شرایطی که دارند و به هم ریختگی‌که در جریان اجرای ترتیبی برنامه ایجاد می‌کنند معادل goto میدانند که البته خیلی هم دور از واقعیت نیست اما این دستورات غالبا تشکیل دهنده ساختار کلی برنامه‌ نبوده و به صورت پیش‌فرض نیز مثل گذشته به عنوان روالی عادی برای برنامه در نظر گرفته نمی‌شوند.4. تجزیه به عملکرد‌ها:برنامه نویسی ساختیافته این امکان را فراهم می‌کند که دائما برنامه را به ماژول‌های عملیاتی کوچکتری تقسیم کنیم. و این به این معناست که در نهایت برنامه ‌می‌تواند به توابع کوچکی تقسیم شود. در نتیجه شما می‌توانید یک مسئله بسیار بزرگ را دریافت کنید و برای حل آن تعدادی تابع مفهومی در حوزه مسئله استفاده کنید و آن توابع نیز در دل خود از تعدادی تابع کوچک‌تر استفاده کنند و این کار تا به پایان رسیدن حل مسئله ادامه پیدا کند.بر پایه این روش توسعه، تحلیل و تجزیه ساخت یافته نیز در دهه 1970 رواج بسیاری پیدا کرد. افرادی مانند اد یوردن، لری کنستانتین، تام دی‌مارکو و میلر پیجونز از پیشگامان و معرفی کنندگان این روش بودند. با این روش‌ها برنامه نویسان می‌توانستند مسئله‌های بسیار بزرگ را به واحد‌های کوچکی شکسته و در نهایت تعداد زیادی ماژول‌های کوچک قابل بررسی و اثبات بسازند. 5. اثبات بی اثبات:هر چند این روش بسیار مورد قبول جامعه برنامه نویسی قرار گرفت، اما هیچگاه آن دستاورد اولیه مورد نظر دیکسترا برای ساخت تعدادی نظریه و اثبات رسمی که برای هر کاری قابل قبول باشد، محقق نشد. هیچ گاه راهکار‌های ثابتی که که همیشه قابل اثبات باشند به جامعه ارائه نگردید. در نهایت رویای دیکسترا برای انجام این کار کمرنگ و کمرنگ‌تر شد و در نهایت از بین رفت. استفاده از روش‌های رسمی این روز‌ها طرفدارانی دارد و برخی هنوز معتقدند که استفاده از اثبات‌های رسمی راهکار دستیابی به نرم‌افزار‌های با کیفیت است. 6. علوم پایه نجات‌بخش: علوم پایه بعضا تفاوت‌های اساسی با ریاضیات دارند، برای مثال من نمی‌توانم به شما قانون دوم نیوتون را اثبات کنم. بلکه من تنها می‌توانم قانون را به شما بگویم و سپس با آزمایش و اندازه گیری نتایج شما را متقاعد کنم که قانونی که بیان شده است درست است. هرچقدر هم قانون ارائه شده صحیح باشد راهکار ریاضی که آن را اثبات کند وجود ندارد. همه چیز وابسته به آزمایش و اندازه گیری است. اصلا مهم نیست که یک قانون چند بار امتحان می‌شود و چند سال مورد قبول همکان است، هر لحظه ممکن است یک آزمایش انجام شود و متوجه شویم قانونی که تا امروز تصور می‌کردیم صحیح است دیگر کاربردی ندارد. طبیعت قوانی علوم پایه این است که آن‌ها قابل رد کردن هستند اما قابل اثبات نیستند. با این حال هنوز که هنوزه ما زندگی خود را بر مبنای این قوانین بنا می‌کنیم. هر بار که سوار ماشین می‌شود روی زندگی خود و اثبا F=m.a شرط بندی می‌کنید. علوم با اثبات صحت یک مطلب کار نمی‌کنند بلکه با رد صحت آن‌ها عمل می‌کنند. هر قاعده‌ای را که با چندین و چندبار آزمایش قابل رد کردن نباشد را می‌پذیریم تا روزی که دانش ما به حدی برسد که بتوانیم آن قانون را نقض کنیم. البته بعضی قواعد هم نه قابل تایید است و نه رد. برای مثال جمله " این یک دروغ است" نه صحیح است و نه غلط. این یک مثال ساده از مسائل غیر قابل اثبات است. در نهایت اینگونه جمع بندی می‌کنیم که با ریاضیات عبارات قابل اثبات صحیح را در اختیار ما قرار میدهد و به کمک علوم پایه عبارات ناصحیح را شناسایی می‌کنیم.7. تست‌ها: دیکسترا می‌گوید:"تست ها وجود باگ‌ها را اثبات می‌کند نه عدم وجود آن‌ها را". به بیان دیگر به کمک تست‌ها می‌توانیم ثابت کنیم که یک برنامه به درستی کار نمی‌کند ولی اگر همه تست‌ها هم به درستی پاس شود نمی‌توانیم به قطعیت بگوییم که برنامه به درستی کار می‌کند. نهایتا بعد از تعداد قابل قبولی تست می‌توانیم بگوییم برنامه آنقدر قابل اعتماد است که برای مدتی تا اثبات اشتباه کار کردن آن مورد استفاده قرار بگیرد. با پذیرش این جمله میپذیریم که هرچند توسعه نرم‌افزار در ظاهر بسیار وابسته و برگرفته از ریاضیات است اما در نهایت از جمله علوم پایه‌ای است. برنامه‌نویسی ساخت یافته ما را به سمت ساخت ماژول‌های کوچک و قابل اثبات سوق می‌دهند. سپس از تست ‌ها برای اثبات عدم صحت عملکرد این ماژول‌ها استفاده می‌کنیم و اگر هیچ تستی موفق به رد آن ماژول نشد می‌گوییم این ماژول به اندازه کفایت قابل اعتماد است و می‌توانیم از آن استفاده کنیم.8. نتیجه‌گیری:در هر سطحی که بخواهیم تصور کنیم، از کوچترین توابع تا بزرگترین ماژول‌های نرم‌افزاری، دنیای نرم‌افزار برگرفته از علوم پایه است. کار ما به عنوان معمار و توسعه دهنده نرم‌افزار این است که توابع و ماژول‌ها و سرویس‌هایی را ایجاد کنیم که به سادگی قابل تست باشد و به کمک این تست‌ها قابلیت اطمینان سازه‌ها قابل اندازه گیری باشد. به همین دلیل است که برنامه نویسی و تفکر ساخت‌یافته از کوچکترین توابع تا بزگترین بخش‌‌های نرم افزار باید جاری باشد.پی‌نوشت: وقتی به عملکرد افرادی مثل دیکسترا فکر می‌کنم که از چه دنیای اولیه‌ای چه دانش و دستاورد‌هایی ایجاد کردن و به سادگی و صادقانه در اختیاردنیا قرار دادن و دنیایی رو از تاریکی نجات دادن، از گفتن واژه "میدانم" در مورد خودم خجالت می‌کشم.