نقش و اهمیت نسخهزدن در نرمافزار
شماره نسخه: نخ تسبیح در ردگیری و مدیریت چرخه حیات آرتیفکتهای نرمافزاری
نسخه مهم است. اگر درست نسخه نزنیم، مدیریت چرخه حیات آرتیفکتهای نرمافزاری از دستتان خارج میشود.
1. چه چیزی را نسخه بزنیم؟
از همه مهمتر «کد» باید نسخه بخورد. وقتی کد به نقطهای رسید که خواستیم release بدهیم، اول نسخه میزنیم. شماره نسخه قاعدتاً یه جاهایی در کد منعکس میشود. ما جاواکارها در فایل تنظیمات maven یا gradle میگذاریم. مثل این و این. در مرحله بعد باید شماره نسخه در نام آرتیفکتهایی که از روی اون کد ساخته شده ظاهر بشه. مثلاً در jar فایل یا داکر ایمیجی که از روی کد میسازید. مثل اینها.
2. آرتیفکت Immutable یعنی چی؟
اگر قرار باشد آرتیکفتهامون Immutable یا غیر قابل تغییر باشند، با کمترین تغییر کد، لازم است شماره نسخه را تغییر بدهیم. با شماره جدید، دوباره روی گیت تگ میزنیم و یک آرتیفکت با نام جدید میسازیم. اینطوری از روی نام آرتیفکت دقیقاً میشه فهمید با چه نسخهای از کد طرف هستیم. دیگه دو جور نسخه x نداریم. کش کردن آرتیفکتها هم امکانپذیر میشود.
3. نسخه زدن به چه دردی میخورد؟
کدها تغییر میکنند. با تغییر کدها، آرتیفکتهای جدید ساخته میشود. آرتیفکتها، نصب و اجرا میشوند. وقتی همه چیز نسخه داشته باشد اگر باگی پیش بیاید خیلی راحت میتوانیم کدی که باگ دارد را پیدا کنیم. در حالیکه ممکن است آن کد نسبت به چیزی که نصب شده، چندین بار تغییر کرده باشد. همینطور اگر بخواهیم روی آرتیفکت در حال اجرا تغییر و توسعه جزئی داشته باشیم، کد آن نسخه را از روی تگهای گیت پیدا میکنیم، تغییر میدهیم و دوباره نسخه میزنیم.
4. نسخه را چطور نامگذاری کنیم؟

رایجترین قالب نامگذاری نسخهها Semantic Versioning نام دارد. در این قالب اسم نسخه از سه بخش major version و minor version و patch version تشکیل میشود مثل 1.2.0 یا 9.2.20 . هر توسعهای در کد اتفاق بیفتد minor version افزایش پیدا میکند و همزمان patch version برمیگردد روی صفر. مثلاً از 1.2.5 میرویم روی 1.3.0. اگر توسعه خیلی اساسی باشد و مخصوصاً Backward Compatible نباشد major version میرود بالا و minor version و patch version ریست میشود روی صفر. مثلاً از 1.2.5 میرود به 2.0.0. اگر تغییر کد فقط در راستای رفع باگ باشد یا به عبارتی specification کد تغییر نکند و فقط implementation اصلاح شود، عدد سوم زیاد میشود مثلاً از 1.2.5 میرویم روی 1.2.6.
5. دیگه چیه چیزی را نسخه بزنیم؟
یکی از جاهای مهم دیگه که نسخه ثبت میشود Issueها هستند. نسخههای مختلف نرمافزار (مثل 1.9.1و 1.9.0) در Issue Tracker پروژه (مثل جیرا) تعریف و به ازای هر Issue مشخص میشود که تغییرات روی چه نسخهای (یا چه نسخههایی) اعمال شده. برای ثبت این داده، جیرا فیلدی به نام Fix Version پیشبینی کرده. معمولاً رفع باگ روی چندین نسخه (که تحت پشتیبانی فعال هستند) همزمان اعمال میشود و بنابراین در ایشوهای از نوع باگ، ثبت چند Fix Version طبیعی است. اگر Fix Version را در Issue Tracker ثبت کنیم، به صورت خودکار برای هر نسخهای که ترخیص کنیم Release Notes خواهیم داشت.
6. رابطه سیاستهای پشتیبانی و نسخهها
نرمافزارها و کتابخانهها معمولاً همه نسخههای قبلی را به صورت فعال پشتیبانی نمیکنند. یعنی اگر باگی پیدا شود روی همه نسخههای قبلی فیکسش نمیکنند. یک یا چند بازه از نسخهها تحت پشتیبانی هستند. یعنی میگن از فلان نسخه تا فلان نسخه تحت پشتیبانی هستند.
مثلاً از 1.9 تا 1.10 به علاوه 2.1 تا 2.3. بعضیها سیاستهای از پیش تعیین شده دارند مثلاً از قبل اعلام میکنند شش ماه از هر major version پشتیبانی میکنند. برخی از نسخهها به عنوان LTS (یا Long Time Support) معرفی میشوند، یعنی دوره پشتیبانیشون طولانیتر است مثلاً سه سال. یک نگاهی به برنامه پشتیبانی نسخ جاوا بیندازید.
7. نسخه snapshot یا pre-release چیست؟
وسط اسپرینت که مشغول کد زدن هستیم و قصد ترخیص و نصب نداریم، لازم نیست با هر تغییری نسخه زده شود. پس شماره نسخه را با پسوند SNAPSHOT مشخص میکنیم. در واقع میشود گفت نسخه SNAPSHOT یه جورایی immutable نیست. بنابراین قابل کش هم نیستند یا موقع کش کردن باید برایشان سیاست بهروزرسانی مشخص کنید. یعنی تعیین کنید روزی یه بار یا ساعتی یه بار یا حتی هر بار نسخه جدید دانلود شود.
8. مرور همه چی کنار هم
فرض کنید که برای مخزن کد از گیت و برای مدیریت پروژه از جیرا استفاده میکنیم و یک پروژه جاوایی داریم که کار build اش رو به maven سپردیم. گامهای اول پروژه اینطور برداشته میشود:
- 1) پروژه را میسازیم. نسخه توی pom.xml را برابر 1.0.0-SNAPSHOT مقدار میدهیم. اولین فایلهای پروژه در شاخه master پوش میشود.
- 2) هر تسکی را انجام دادیم کدش رو کامیت و پوش میکنیم. فعلاً در pom.xml، نسخه تغییر نمیکند و هر تسکی که انجام میشود و کدش میآید داخل مخزن گیت، fix version اون تسک در جیرا را 1.0.0 میگذاریم.
- 3) وقتی تصمیم گرفتیم release بدهیم، نسخه در pom.xml به 1.0.0 تغییر میکند و کامیت و پوش میشود. یعنی پسوند SNAPSHOT حذف میشود.
- 4) روی مخزن گیت، از روی شاخه master تگ 1.0.0 ساخته میشود.
- 5) از روی شاخه master، آرتیفکت با نسخه 1.0.0ساخته میشود مثلاً myapp-1.0.0. jar
- 6) در شاخه master در فایل pom.xml نسخه را یکی میبریم بالا. یعنی میرویم روی نسخه 1.1.0-SNAPSHOT.
- 7) در جیرای پروژه نسخه 1.0.0 را release میدهیم و نسخه 1.1.0 را باز میکنیم.
در ظاهر کار طولانی و سخت شد. ولی عمده کارها مثل ساخت تگ و تولید آرتیفکتها را میشود به پایپلاین CI/CD سپرد.
۹. اگر باگی روی 1.0.0 گزارش شود، چه کنیم؟
- ۱) موقع ترخیص تگ 1.0.0 را ساخته بودیم. از روی این تگ شاخهای به نام 1.0.x میسازیم. در اسم شاخه به جای patch version از حرف x استفاده کردیم. چون برای patch versionهای بعدی هم از همین شاخه استفاده میکنیم.
- ۲) در فایل pom.xml مقدار نسخه را از 1.0.0 به 1.0.1-SNAPSHOT تغییر میدهیم.
- ۳) اصلاحات را در کدها اعمال و در شاخه 1.0.x کامیت و پوش میکنیم.
- ۴) کار که تمام شد، نسخه را در pom.xml به 1.0.1 تغییر میدهیم (یعنی «SNAPSHOT» را از انتهای آن برمیداریم) و کامیت و پوش میکنیم.
- ۵) در مخزن گیت، تگ 1.0.1 را از روی برنچ 1.0.x میسازیم.
- ۶) آرتیفکت با نسخه 1.0.1 ساخته میشود مثلاً myapp-1.0.1. jar
- ۷) در ایشوی رفع باگ در جیرا مقدار fix version را برابر 1.0.1 قرار میدهیم.
۱۰. از پایپلاین CI/CD کمک بگیرید
در ظاهر کار طولانی و سخت شد. ولی عمده کارها مثل ساخت تگ و تولید آرتیفکتها را میشود به پایپلاین CI/CD سپرد. اینطوری هم سرعت بالاتر میرود و هم مطمئن هستیم همه مراحل به صورت منظم انجام میشود. مثلاً مطمئن میشویم که هر آرتیفکتی ساخته شده حتماً روی گیت، تگ معادلش موجود است.
سید جمالالدین پیشوایی
رئیس هیئت مدیره و مدیر فنی علاقهمند به معماری راهحلهای نرمافزاری
اگر این موضوع در سازمان شما به یک چالش تبدیل شده...
تیم اعوان میتواند در ارزیابی معماری و زیرساخت فعلی شما همراه باشد. تجربه ما در پروژههای بانکی و... برای همین موقعیتها جمعآوری شده است.