در بخش ششم، به موضوع Learnability پرداختیم. در این بخش دو مفهوم Evolution و Refactoring را مورد بحث قرار می دهیم.
مسئله Change و Evolve شدن، دو موضوع نزدیک به هم اما متفاوت هستند. مسئله Evolvability، در حدی با اهمیت و تاثیر گذار است که صرفا به عنوان quality attribute، به آن اشاره نمی شود و بیشتر یک Meta-Characteristic است که ابعاد مختلفی دارد.
مسئله evolution دارای چند قسمت است.
در software و در مسئله Dynamic، با تغییراتی روبرو می شویم که قبل از اتفاق افتادن، قابل پیش بینی نیستند. و در بعضی مواقع از وجود چیزهایی که قرار است تغییر کنند نیز بی خبر هستیم. می تواند شامل تکنولوژی، سازمان ها، آدم ها و غیره شود. از طرفی مسئله Balance را داریم که در تغییرات سعی می کنیم تعادل را برقرار کنیم و زاویه طراحی را به سمت آن تغییرات می بریم.
مسئله Evolutionary Architecture که در سال های اخیر در حوزه معماری پر رنگ شده است، به این موضوع می پردازد که ما چگونه می توانیم معماری را طوری طراحی کنیم که تغییر پذیر باشد. مساله evolution در یک مسیر اتفاق می افتد و به حرکت خود ادامه می دهد. evolution در طول زمان ممکن است یک معماری را مدام تغییر دهد.
قوانینی پیرامون program evolution تحت عنوان Laws of Program Evolution وجود دارد.
تمام پروژه هایی که در حال حاضر وضعیت خوبی ندارند، بخاطر عدم تغییر بوده است. اکثر این پروژه ها در شروع کار و از نگاه طراح، بهترین design را داشته اند.
به معماری هایی Evolutionary Architecture گفته می شود که از تغییرات کوچک در راستای ابعاد مختلف پشتیبانی می کنند.
فرض کنید در حوزه availability، نرم افزاری داریم که 98% available است و به دنبال اعمال تغییراتی برای بهتر کردن آن هستیم. اولین موضوع این است که از کجا بفهمیم که این تغییرات ما را به چیزی که می خواهیم نزدیک می کند یا خیر. احتمالا در این مورد به این فکر می کنیم که با هر اتفاقی، این عدد پایین تر نخواهد آمد. بنابراین از طریق یک function به نام Fitness Function، تمام موضوعات characteristic را ارزیابی می کنیم. در اینجا ممکن است عدد uptime نرم افزار را به عنوان ورودی function در نظر بگیریم.
مفهوم Fitness Function، مکانیزمی است که مشخص می کند آیا ما داریم در مسیر درست حرکت می کنیم یا خیر. از testها می توانیم برای ساده ترین نوع پیاده سازی استفاده کنیم. برای مثال تست عدم وجود dependency به کلاسی خاص. نمونه ابزار این مدل تست ها ArchUnitNET وجود دارد که می توان با آن تست های در سطح structure نوشت. نوع دیگری از fitness function، خانواده metricها هستند. برای ساده ترین نوع آن میتوانیم Cyclometric Complexity را نام ببریم. در نظر بگیرید که fitness functionها الزاما automate نیستند و می توانند Manual باشند. به این معنی که شخصی چیزی را از طریق مشاهده چک کند.
Refactoring
از نگاه design، تغییرات structural یا ساختاری در راستای درایور های Easier to change و More readable که با تغییرات نکردن ماهیت سیستم همراه است.
بزرگترین مشکل refactoring، تبدیل به فاز شدن آن است. به این معنی که تجمیع بدهی های فنی، refactoring را با پیامد های زیادی همراه می کند و ممکن به سادگی قابل انجام نباشد. بنابراین همگام شدن با تغییرات کوچک تر، نکته اساسی refactoring است.
مفهوم Detour در refactoring مطرح می شود. زمانی که مشکلات پروژه به حدی می رسد که در وضعیت فعلی نمی توان از آن استفاده کرد. بنابراین با ایجاد detorها، اجازه می دهیم سیستم release شود و همزمان تغییرات نیز در حال انجام باشند. در این زمینه، می توانید تکنیک BranchByAbstraction آقای Martin Fowler را مطالعه فرمایید.
اتفاقی که در این تصویر مشاهده می کنید، abstraction مناسب تری ایجاد شده است و یکی از clientها به این abstraction جدید اشاره می کند و بقیه clientها به همان با همان کلاس قدیمی کار می کنند. اما client که از abstraction جدید استفاده می کند هم در نهایت از همان پیاده سازی قدیمی استفاده می کند. هدف برداشتن گام کوچک است. گام اول این بوده که یک نفر این abstraction را بشناسد. در جریان این کار، application می تواند release شود و کار کند.
در گام بعدی، یک پیاده سازی بهتر برای آن در نظر گرفته می شود. این کار ادامه پیدا می کند تا dependency از پیاده سازی قدیمی کم شود و در نهایت از پروژه حذف شود. این کارها با استفاده از fitness functionهایی که مساله را ارزیابی می کنند، انجام می شود.