تجزیه سیستم های پیچیده

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

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

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

تجزیه به وسیله الگوریتم:

تجزیه الگوریتمی

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

تحزیه به وسیله شی گرایی:

تجزیه شی گرایی

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

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

پیچیدگی سیستم

در قسمت قبل دیدیم که تمامی سیستم های پیچیده از یک سری قوائد کلی تبعیت می کنند و به عبارتی تمامی قوانین آن در سیستم های پیچیده تکرار می شوند.

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

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

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

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

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

زمانی که ما یک سیستم جدید را مورد بررسی قرار می دهیم، قسمت های زیادی از سیستم را پیدا می کنیم که با هم به صورت پیچیده ای ارتباط دارند. از طرفی آن قسمت ها نقاط اشتراک پایینی با یکدیگر دارند.حال فرض کنید در یک سیستم پیچیده مثل ترافیک هوایی ما  نیاز داریم که تمامی حالت های ممکن را بررسی کنیم .به عنوان مثال سرعت،مکان ، آب و هوا و…  .در این حالت بررسی تمامی این شرایط توسط یک نفر تقربیا غیر قابل  ممکن است و طبق آزمایشی که روانشناسان بر روی مغز انسان انجام داده اند هر فرد تقریبا  به صورت همزمان می تواند ۷(+ یا – ۲) موضوع همزمان را مد نظر قرارد بدهند و برای پذیرش مطلب جدید نیاز به ۵ ثانیه زمان دارند.

پس یکی از دشواری های ما در مواجه با سیستم های پیچیده محدودیت ذاتی ما است.ما چگونه می توانیم این مشکل را حل کنیم؟

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

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

۵ مشخصه یک سیستم پیچیده

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

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

ساختار سلسله مراتبی دارند:

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

همه سیستم های پیچیده از یک سری اجزای اصلی و یک سری اجزای فرعی تشکیل شده اند:

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

Separation of Concerns:

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

الگوهای مشترک در آنها وجود دارد:

سیستم های پیچیده معمولا از تعدادی زیر سیستم های کوچک تر در ترتیب و ترکیب های مشترک درست شده اند.به عنوان مثال هم برگ و هم بدن انسان از سلول تشکیل شده است.ولی کار آن ها با یکدیگر کاملا متفاوت است.

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

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

راهکارهای مختلف برای ذخیره Session در Asp.net

به علت اینکه HTTP یک پروتکل Stateless است ، ما نیاز داریم اطلاعات مورد نیاز هر کاربر را در جایی از سرور ذخیره کنیم.این اطلاعات ممکن است  نام یا اطلاعات کاربری باشند و یا حتی تنظیمات مربوط به هر کاربر.ما باید این اطلاعات را در جایی از سرور ذخیره کنیم و در صورت نیاز به آن رجوع کنیم و از آن ها استفاده کنیم.یکی از راههای ذخیره سازی بر روی سرور، استفاده از session است.

session

استفاده از session مزیت هایی برای ما دارد:

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

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

در سمت سرور هر session به وسیله یک آی دی ۱۲۰ bitی نام گذاری می شود.این آی دی به اندازه کافی امن هست و نمی توان با مهندسی معکوس به آن رسید.زمانی که سرور و کلاینت با یکدیگر ارتباط برقرار می کنند session ID بین آن ها جابجا می شود.زمانی که کلاینت یک درخواست به سرور برای بازیابی داده ای ارسال می کند،سرور به وسیله همین session ID است که میتواند داده های مناسب برای کلاینت را بازیابی کند.در تمامی  درخواست یک سشن آی دی مشخص در نظر گرفته و این آی دی در کوکی ذخیره شده است.در صورتی که این کوکی پاک شود session Id  جدید تولید خواهد شد.اگر شما از دو مرورگر متفاوت استفاده می کنید این session ID ممکن است در مرورگرهایتان، با هم تفاوت داشته باشند.session ID به صورت text به سمت کلاینت فرستاده می شود و ممکن است در این بین کسی بتواند آن را به دست آورد.بنابراین اگر از session برای ذخیره اطلاعات حساس استفاده می کنید بهتر است حتما از ssl استفاده شود.

Session state store provider

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

session state provider

در شکل بالا نحوه مدیریت یک درخواست از کلاینت به سرور و همچنین خواندن session به وسیله یک State Provide  نشان داده شده.

در asp.net می توانیم از providerهای زیر استفاده کنیم:

  • InProc
  • StateServer
  • SQLServer
  • Custom

 State Provider

نگاهی به مد InProc:

در حالتی که ما از این قابلیت استفاده کنیم،داده های ما در application domain جاری فقط در دسترس خواهند بود.این کار به وسیله worker process مدیریت خواهد شد.داده ها در این حالت در رم ذخیره خواهند شد و بدیهی است که با ریست شدن سرور از بین خواهند رفت.این راه خیلی سریع است ، زیرا که داده ها در application domain جاری هستند.علاوه بر آن نیازی به serialization  برای ذخیره سازی و بازیابی داده ها نیست.البته باید توجه داشت که در این حالت نمی توانیم از web garden  و web farm استفاده کنیم.

Overview of InProc session mode

شاید یکی از مزایای این روش مدیریت راحت تر session end باشد ، زیرا که در حالت هایی که ما از یک پروایدر خارج از app domain استفاده می کنیم event مربوط به session end را نخواهیم گرفت.session life cycle

نگاهی به مد StateServer:

به این مد Out-Proc نیز گفته می شود. در این حالت از یک Windows Service مستقل از IIS برای نگهداری session ها استفاده می شود که در حالتی که iis(یا apppool) ریست شود داده های ما باقی خواهند ماند.برای ذخیره و خواندن داده ها نیاز است که serialization انجام شود.در این مد اگر سرور ریست شود اطلاعات ما ماندگار نخواهد بود(البته امکان استفاده از سرور مجزا نیز وجود خواهد داشت).این حالت برای زمانی که ما از web farm و web garden استفاده می کنیم می کنیم مناسب است.

Overview of StateServer session mode

tateServer Session Mode

نگاهی به مد SQLServer:

در این مد داده ها در SQL Server ذخیره خواهند شد.این حالت نیز مثل StateServer نیاز به serialization  دارد ولی چون در sql است داده ها با اطمینان بیشتری ذخیره خواهند شد.این حالت برای زمانی که ما از web farm و web garden استفاده می کنیم می کنیم مناسب است.یکی دیگر از مزایای استفاده این روش ، نگهداری داده ها در یک مکان واحد است و ما می توانیم مدیریت بیشتری روی داده ها داشته باشیم و همچنین با ریست شدن سرور نیز ، داده ها از بین نخواهند رفت. ولی این روش در مقایسه با دو روش قبلی کند تر عمل می کند.زمانی که از این روش استفاده میکنیم می توانیم session ها را بین دو برنامه به اشتراک بگذاریم.

Overview of SQL Server Session Mode

نگاهی به مد Custom:

در سناریو هایی ما نیاز داریم که از این مد استفاده کنیم .مثل زمانی که میخواهیم Session Id را خودمان بسازیم.در این حالت می توانیم داده ها را نیز در جایی به غیر از sql server ذخیره کنیم.علاوه بر آن می توانیم داده ها را در یک پایگاه داده موجود ذخیره کنیم.

 

یکی از مشکلاتی که ممکن است زمانی که شما از modeی به غیر از inproc استفاده می کنید برای شما به وجود آید، این است که دیگر event مربوط به session_end را نمی توانید مدیریت کنید.از این رو سناریویی را فرض کنید که نیاز است در هنگام expire شدن session، عملیاتی مثل تمیز سازی یا … انجام دهید.برای این منظور اگر از web farm و یا از web garden استفاده نکنید مشکل زیادی نخواهید داشت و می توانید به راحتی به وسیله یک http module عمل expire شدن session را مدیریت کنید.ولی زمانی که شما از  web farm و یا از web garden استفاده می کنید در این حالت مشکل اینجاست که هر سری کاربر ممکن است به یک پروسس و یا یک سرور مجزا وصل شود که دیگر راه حل قبلی جواب نخواهد داد.زیرا عمل expire دیگر ،در app domain جاری اتفاق نمی افتد و توسط پروسس دیگر مدیریت می شود.

 

طراحی شی گرا

مدتی است که به پیشنهاد یکی از دوستانم شروع به خواندن کتاب Object-Oriented Analysis and Design with Applications Notes نوشته پروفسور گریدی بوچ کرده ام.در واقع متد من در خواندن کتاب note برداری از نکات مهم است که در آینده بتوانم به آن رجوع کنم.

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

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

من سعی خواهم کرد که ابتدا فصل اول کتاب را در قالب چند پست منتشر کنم و سپس سراغ فصل های بعدی خواهم رفت.

فصل اول:پیچیدگی

سیستم های کارآمد معمولا از پیچیدگی خاصی برخوردار هستند.

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

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

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

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

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

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

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

پیچیدگی در نرم افزار یک خصوصیت اجباری است تا یک خصوصیت تصادفی.

پیچیدگی در نرم افزار از چهار دلیل اصلی نشات میگیرد:

  • مشکلات دامین
  • مدیریت روند توسعه
  • منعطف بودن نرم افزار
  • مشخص کردن رفتار در سیستم های مجزا

مشکلات دامین:مشکلاتی برای حل یک مسئله نظیر مدیریت فرودگاهی با چندین پرواز هم زمان را به علاوه بر پیچیدگی هایی به مانند کاربرد پذیر کردن برنامه یا دسترس پذیری را در نظر بگیرید.همه این ها به پیچیدگی نرم افزار اضافه می کنند.

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

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

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

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

 

تجربه تست نویسی در یک پروژه پیچیده

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

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

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

دلیل اینکه روی تست نویسی تاکید می کنم این است که واقعا زمانی که پروژه پیچیده می شود ،  می توان به راحتی درک کرد که عدم تست نویسی می تواند چه بلایی سرمان نازل کند.

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

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

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

code coverage در این سیستم بسیار خوب بود.البته code coverage آمار مناسبی برای صحت عملکرد یک پروژه نیست ولی سعی کردم تمامی متدهایی که در سیستم وجود دارند را حداقل با مقادیر مختلفی تست کنم.

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

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

اگر بخواهم جمع بندی کلی روی مطلب داشته باشم این است که تست باعث بهتر و بیشتر شدن تجربه من هم در کد نویسی و هم در مواجه با پروژه های پیچیده  شد.