اگرچه کیفیت کد، اساسیترین فاکتور Maintainability در پروژههای Legacy ست، اما بیشتر نرمافزارها برای اجرا شدن وابسته به مجموعهای از زیرساختها و ابزارها هستند و کیفیت این ابزارها تاثیر به سزایی توی بهرهوری تیم داره.
محیط توسعه فرآیند Checkout کردن پروژه از Version Control و رسیدن به مرحلهای که بتونیم اون رو روی سیستم خودمون اجرا کنیم در یک پروژهی Legacy، پروسهی زمانبریه و معمولا شامل دانلود و نصب کردن و یادگرفتن راز و رمز وابستگیهای اون سیستم، اجرای اسکریپتهای عجیبغریب و طی کردن یک سری مراحل دستیه. درسته که این کارها رو یکبار و وقتی که میخوایم برای اولین بار پروژه رو بگیریم انجام میدیم، اما فقط ما نیستیم که مجبور به گذروندن این مراحلیم و بهای این ضعف، بالا رفتن زمان تلفشدهایه که هر توسعهدهندهای توی تیم یا در آینده صرف این پروسه میکنه.
وابستگیهای قدیمی و منسوخ شده هر پروژهای به یکسری Library و نرمافزارهای Third-Party وابستگی داره که میزان تغییرات اونها در اختیار ما نیست. اینکه اونها رو همیشه با آخرین نسخه آپدیت نگهداریم هم مستلزم یک تلاش مداومه، اما ارزش زمان صرف کردن رو داره. بهروزرسانی معمولا موجب بهبود عملکرد میشه، باگ نسخههای پیشین رفع میشه و گاهی شامل Patchهای امنیتی Critical هستند. بهروزرسانیهای منظم به ورژنهای Minor شاید در ماه چند دقیقه وقت بگیره، اما اگه اینکار رو پشت گوش بندازیم، بدون اینکه خبردار بشیم چند ورژن Major رو جا انداختیم و وقتی به صرافت بهروزرسانی میوفتیم که ریسک و هزینهی توسعه و تست زیادی رو باید متحمل بشیم و نویسنده از شرکتی میگه که در یک پروژهی Legacy ماهها درگیر Upgrade کردن برنامهشون از Java 6 به Java 7 بودند. اونها از ترس بروز شکست در قسمتهای مبهم برنامه سالها در برابر بهروزرسانی وابستگیهاشون مقاومت کرده بودند و چون با یک پروژهی Legacy سر و کار داشتند، هیچکسی دید واضحی از رفتار فعلی برنامه یا رفتاری که ازش انتظار میره داشته باشه، نداشت. زمانی که عمر Java 6 به آخر رسید، تصمیم گرفتند که تن به بهروزرسانی بدهند و ارتقاء به Java 7 به معنی ارتقاء دادن سایر وابستگیها هم بود. این کار موجب ایجاد شکست در APIهای تغییر کرده، و همچنین ایجاد تغییرات نامحسوس و غیرمستقیم در رفتار برنامه شد. این داستان عاقبت خوشی هم نداشت و پس از چند هفته تلاش برای حل و فصل کردن تغییراتِ رفتاریِ مبهمی که در XML Serialization ایجاد شده بود، از خیر بهروزرسانی گذشتند.
محیطهای اجرای ناهماهنگ بیشتر نرمافزارها در طول حیات با عزتشون در محیطهای مختلفی اجرا میشن، مثلا:
توسعهدهندهها اون رو روی سیستم Local خودشون اجرا میکنند
بعد برای تست Automatic و Manual توی محیط تست Deployش میکنند
در قدم بعدی توی محیط Stage اون رو Deploy میکنن تا محیط Production رو شبیهسازی بکنند
و در نهایت Release میگیرند و برنامه رو در محیط Deploy ،Production میکنند
هدف این پروسهی چند مرحلهای اینه که قبل از Release کردن، مطمئن بشیم که برنامه داره به درستی کار میکنه. اما ارزش اینکار بستگی به میزانِ همانندی این محیطها با هم داره. محیط Staging اگر که کپیِ دقیقی از محیط Production نباشه ارزشش رو در نشون دادن رفتار برنامه در اون محیط از دست میده. همانندی محیط توسعه و تست با محیط Production هم، باعث میشه مسائل پیش اومدهی مربوط به محیط و نرمافزار رو - بدون اینکه مجبور به Deploy کردن در محیط Staging باشیم - سریعتر تشخیص بدیم. برای مثال استفاده از یک ورژن یکسان از MySQL در همهی محیطها، تمامی شُبهات در مورد تغییر رفتار -که مربوط به این ناهماهنگی ورژنها در محیطی که نرمافزار به درستی کار میکنه و محیطی که نرمافزار در اون به مشکل خورده باشه- رو مرتفع میکنه.
حرف زدن از این انطباق بین محیطها، از عمل کردن به اون سادهتره. مخصوصا زمانی که از Automation استفاده نشه. در حالت همانندسازی به صورت دستی احتمال پیدایش اختلاف در این محیطها، از راههای متفاوتی افزایش پیدا میکنه :
آپگرید کردن از محیط Production به دیگر محیطها نشت کنه تیم Operation در پاسخ به یک اکسپلویت Zero-Day، یکی از وابستگیهای سیستم رو در Production آپگرید میکنند، چند هفته بعد یکی متوجه میشه این بهروزرسانی در محیط Staging صورت نگرفته و انجامش میده، چند ماه بعدتر هم یکی دیگه یادش میوفته که ورژنِ روی محیط تست رو بهروزرسانی کنه. اما اون برنامه روی سیستم توسعهدهنده داره به درستی کار میکنه و نیازی برای تغییرش ایجاد نمیشه و به همون صورت باقی میمونه.
استفاده از ابزار متفاوت در محیطهای متفاوت مثلا شما از یک دیتابیس Lightweight در محیط توسعه استفاده میکنید، اما دیتابیس مناسبتر رو روی محیطهای دیگه راه میاندازید.
تغییرات موقتی شما در حال صحنهسازی برای تست کردن یک Feature جدید هستید و به این منظور به Redis احتیاج دارید و اون رو روی محیط Test نصب میکنید. آخرش تصمیم میگیرید این Feature پیادهسازی نشه اما یادتون میره Redis رو Uninstall کنید و سالها میگذره و کسی دیگه یادش نمیاد چرا Redis روی محیط تست نصبه.
این واگرایی به مروز زمان بیشتر و بیشتر میشه و موجب وحشتناکترین پدیدهی نرمافزاری میشه، باگی که فقط در Production ایجاد میشه! این باگ در اثر تعامل نرمافزار با محیطی که توش اجرا میشه و فقط در Production به وجود میاد و انجام هزاران هزار تست در محیطهای دیگه کاملا بیفایدهست.
فرهنگ Legacy
بیشتر تیمهایی که اغلب زمانشون رو صرف نگهداری از پروژهی Legacy میکنن، معمولا ویژگیهای مشترکی در رابطه با روش توسعهی محصول و ارتباطاتِ بینِ خودشون دارند.
ترس از تغییر کسانی که پروژههای Legacy رو Maintain میکنند، به دلیل پیچیدگی پروژه و نداشتن مستندِ قوی، نمیتونن همهچیز رو راجع به اون بدونند. مثلا اینکه از کدوم Feature دیگه استفاده نمیشه و حذف کردنش مشکلی ایجاد نمیکنه، یا کدوم باگ رو اگه Fix کنیم به مشکل برنمیخوریم (مورد بوده که بعضی کاربرها با یک باگ انقدر خو گرفتن که فکر میکنند اون Feature کارکردش همینطوریه و برطرف کردنش کاربر رو دچار مشکل میکنه)، یا با کدوم کاربرها باید قبل از ایجاد تغییر در رفتار برنامه مشورت کرد. به دلیل فقدان این اطلاعات، بسیاری از تیمها سعی میکنن این امنترین وضعیت رو همینطوری نگهدارند و از ایجاد هرگونه تغییرات غیرضروری ترس داشته باشند. هر تغییری یه خطر محسوب میشه و عطای مزایای احتمالی اون تغییر رو به لقاش میبخشن و پروژه وارد یک فاز سکون میشه که در اون توسعهدهندهها بیشتِر انرژی خودشون رو صرف حفظ وضع موجود میکنند. قرار گرفتن در این موقعیت که اجازه نمیده برنامه تکامل پیدا کنه،سازمان رو با خطر بزرگتری روبهرو میکنه و اون اینه که توسط رقیبانشون پشتسر گذاشته میشن. بحث سر زمانه. اگر رقیب بتونه زودتر از ما یک Feature رو به برنامه اضافه کنه، که کاملا هم در این حالت سکون محتمله، باید اونجوری که شایستهست با مشتریهامون وداع کنیم و جمع کنیم بریم. میتونه اینطوری هم پیش نره، اگر که تیم یک چشمانداز داشته باشه و وزن مزایای یک تغییر رو در مقابل ریسکهایی که داره بسنجه و فعالانه به دنبال اطلاعات گمشدهای که برای چنین تصمیماتی بهش کمک میکنه بگرده، نرمافزار میتونه تکامل و با تغییرات سازگاری پیدا کنه.
انبارهای دانش معمولا بزرگترین مشکلی که توسعهدهندهها هنگام توسعه و نگهداری از نرمافزار باهاش مواجه میشن، فقدان دانشه و ممکنه شامل «کمبود اطلاعات Domain در مورد نیازهای کاربران و مشخصات کاربردی نرمافزار»، «کمبود اطلاعات فنیِ خاصِ پروژه در مورد طراحی نرمافزار و معماری» و یا «کمبود دانش فنی عمومی مانند الگوریتمهای بهینه، ویژگیهای زبانیِ پیشرفته، ترفندهای کدنویسیِ سودمند و Libraryهای مفید» باشه. یک مزیت کار کردن در قالب تیم اینه که اگه شما چیزی را بلد نباشید، ممکنه یک عضو دیگهی تیم بتونه اون رو ارائه بده. برای اینکه این اتفاق بیوفته، یا باید ازشون بخواهید و یا بهتر از اون، اونها به خواست و رغبت خودشون با شما دانش رو به اشتراک بذارن. این موضوع خیلی بدیهیه، اما تو خیلی از تیم ها این مبادلهی اطلاعات صورت نمیگیره. هر توسعهدهندهای به اصطلاح تبدیل به یک انبارِ دانش میشه که همهی دانشِ باارزشش به جای اینکه در جهت منافع کل تیم به اشتراک گذاشته بشه پیش خودش میمونه، مگر اینه تلاش زیادی صورت بگیره تا یک محیط ارتباطی و به اشتراکگذاری اطلاعات پرورش داده بشه. عوامل موثر در کمبود ارتباطات درون یک تیم میتونه شامل موارد زیر باشه: ◦ نداشتن ارتباط رو در رو --توسعهدهندهها بغلدست هم نشستن اما به جای گفتگو با هم چت میکنن. ◦ Ego کد --«اگه بذارم کسی کد منو ببینه، ممکنه بهش انتقاد کنه» ◦ استایل سرشلوغی گرفتن --یک روش دفاعی متداول برای توسعهدهندهها، برای قرار نگرفتن در معرضِ انجامِ کارِ ناخواستهست. (بزرگوار اشاره میکنن به داستان هندزفری و اخم و اینها D: ) این کار همچنین باعث میشه این افراد کمتر برای توسعهدهندههای دیگه که میخوان ازشون سوال بپرسن در دسترس باشند. و در انتها از کارهایی مثل Code Review ، Pair Programming یا برگزاری Hackathonها میگه که میتونه به بالابردن ارتباط درون یک تیم کمک کنه که در فصلهای بعدی راجع به اینها بیشتر صحبت شده.