Traceability فرصت یا مکافات ؟
مقدمه ۱٫ حدود سال ۱۳۷۲ با زبانی برنامه مینوشتیم به نام Cobol و ناچار بودیم دستورات برنامه را دقیقا مشابه یک زبان محاورهای بنویسیم و از این بابت تقریبا همگی شاکی بودیم.
مقدمه ۲٫ زمانی (حدود سال ۱۳۷۳) قرارشد یک نرمافزار شبیه یک سیستم انبارداری خیلی ساده برای یکی از دوستانم بنویسم که نوشتن این نرمافزار حدودا ۲ ماه طول کشید و یک تفاوت کوچک با دیگر نرمافزارهای انبارداری داشت؛
این یکی با اسمبلی نوشته شده بود!
برای این کار طبیعتا نمیشد همه برنامه را جدا جدا بنویسی و راهی که من انتخاب کردم استفاده از ماکروهای اسمبلی بود. در واقع تمام functionهایی را که لازم داشتم با ماکرو نوشتم و بعد آنها را یکی یکی در برنامه صدا زدم.
این نوع برنامهنویسی را البته در سالهای بعد نیز بسیار کاربردی یافتم و کم کم برای هر کاری که دو بار قرار بود انجام شود یک “library” مینوشتم. خلاصه کار به آنجا کشید که نقریبا ۷۰% توابع Foxpro را به زبان c نوشتم و در چند header file بصورت مجزا ذخیره کردم و توانستم به کمک آنها سرعت تولید نرمافزارم را تقریبا شش تا هشت برابر کنم. از طرفی این نوع برنامهسازی یک دستاورد خوب برای من داشت، هر جا به خطا میخوردم یک بار خطا را پیدا و رفع میکردم و از آن به بعد برای همه برنامههای دیگرم نیز آن خطا رفع شده بود!
بعد از مدتی به نتیجه رسیدم نباید کارهای کوچک و جزئی را در کد اصلی بنویسم. مثلا فرض کنید یک فرم لازم داشتم که حقوق پرسنل را برای آخر ماه محاسبه نموده و گزارش مربوطه را ارائه دهد. آن را به این صورت مینوشتم:
{
initialSalaryCalculationParameters();
calculateSalary();
buildSalaryReport();
}
و بعد function مربوط به مقدار دهی اولیه و تابع محاسبه حقوق و الی آخر. مثلا برای Function محاسبه حقوق مینوشتم:
در واقع با چند تکنیک ساده، هیچ وقت داخل کد سردرگم نمیشدم و قابلیت دنبال کردن اجرای برنامه ( traceability ) واقعا در برنامهای که مینوشتم وجود داشت. شاید بتوانم چند اصل کلی که برای خودم رعایت میکردم را در قالب موارد زیر ذکر کنم:
(پیش از ذکر این چند مورد لازم است ذکر کنم این موارد تنها تجربیات شخصی من است و البته به نظرم این موارد را میتوان هم در نرمافزارهای ساختیافته و هم در دیدگاه Object oriented یا Model driven بکارگرفت و تا کنون منعی برای بکارگیری آنها در برنامهنویسی با دیدگاههای غیر ساختیافته ندیدم)
۱- یکی از مشکلاتی که همیشه با آن دست و پنجه نرم میکردم traceability در ساختار برنامه بود، یعنی این که بتوانم هر چه سریعتر محل تغییری که باید اعمال کنم را پیدا کنم. ساختار نرمافزار را از بالا به پایین میدیدم. یعنی ابتدا از کلانترین کارکردهایی که قصد داریم نرمافزار انجام دهد شروع کنیم و لایه به لایه آنها را جزئیتر نموده و آنگاه باز هر لایه جزئی را به چند کارکرد شکسته و همین روال را طی کنیم تا به توابع محاسباتی یا توابع مدیریت دادهها برسیم. پیش خودم به این ساختار Program Breakdown Structure یا PBS میگفتم. ساختاری بود که مشخص میکرد کارکردهای اصلی برنامهها (use Caseها) چه مواردی هستند و چطور میتوانم از بالا به پایین به آنها نگاه کنم! این تقریبا همان ساختاری بود که بالاتر در برنامهنویسی Cobol ذکر کردم.
۲- اگر اجرای یک نرمافزار را چیزی شبیه یک Finite automaton (ماشین با حالات محدود) ببینیم، یک برنامهنویس خوب باید بتواند شرائطی که هر لحظه ممکن است بر برنامه حاکم شود را پیشبینی نموده و برای هریک چارهای بیندیشد. طبیعتا این موارد خیلی تکراری هستند و میتوان برای مدیریت آنها از یک controller متمرکز استفاده نموده و مثل تابع logHandler که در بالا نوشتم با آن برخورد نمود. معمولا برای درک شرائطی که برنامه در آن شرائط اجرا میشود یک گراف (تقریبا شبیه درخت) رسم میکردم که نام آن را Condition tree گذاشته بودم و همیشه از هر حالتی به حالت دیگر روی شاخههای درخت حرکت میکردم. برای همین وقتی خیلی در کد سردرگم میشدم فقط شرائط اجرای برنامه را از روی درخت دنبال میکردم و معمولا جواب خوبی از این پیگیری میگرفتم. البته اینجا یک مشکل کوچک داشتم و آن اطمینان از توسعه برنامه بر اساس Condition tree بود که حداقل ۵% کل زمان توسعه زمان میبرد.
۳- یکی از راههای بالابردن traceability برای من استفاده مجدد از بخشهای قابل تکرار کد برنامه بود. هر بخشی از برنامه (واقعا هر بخشی! حتی چند قلم داده که چند بار در کنار هم آمدهبودند، مثل بخشهای ثابت از اطلاعات فردی) که بیشتر از دوبار در کل نرمافزار تکرار میشد را حتما به libraryها منتقل میکردم و morphهای مختلفی از آن را مینوشتم که بتوانم بارها آن را استفاده کنم. (حاصل آن تلاش، چند فایل library است با سایز حدود ۴۲۰۰۰ خط!) نکته جالب در این re-usability آن بود که احساس میکردم وقتی میتوانم یک تابع را به چند صورت و با چند نوع پارامتر صدا بزنم، عملا کار چندانی برای نوشتن نرمافزار نداشتم. کار به جایی رسید که اواخر شرکت نامآوران مشهد، من فقط توابع را سر هم میکردم و خود برنامه بصورت خودجوش مردمی ساخته میشد!
۴- مزیت بزرگ برنامههایی که با این روش مینوشتم این بود که اگر یکی کار میکرد مطمئن بودم با احتمال بسیار بالایی دیگر ماژولهایی که از آن Component استفاده کردهاند نیز به درستی کار خواهند کرد. بنابراین با تکیه بر همین توابع کتابخانهای که نوشته بودم سالها و سالها برنامه نویسی کردم و مطمئن بودم نرمافزاری که به مشتری ارائه میدهم خطا ندارد ویا خطایی بسیار کوچک دارد که تا کنون از چشم من مخفی مانده است و خبر خوب اینکه اگر آن خطا را یک بار رفع میکردم در همه بخشهایی که از آن کد استفاده میشد آن خطا رفع شده بود.
نمیدانم چقدر توانستم تکنیکهای مورد نظرم را درباره traceability خلاصه و ساده بیان کنم، اما امیدوارم اگر نکتهای جامانده و یا دوستان عزیزم تجاربی در این زمینه دارند حتما آن را در بخش دیدگاههای این مطلب ذکر کنند.