انتخاب بین مخزن یکپارچه (monorepo) و درختهای ماژولار یکی از تصمیمات کلیدی است که نحوهٔ توسعه، انتشار و نگهداری پروژههای بزرگ را تعیین میکند. بحثهای عمومی در Hacker News و ردیت و تجربههای استخراجشده از نگهداری کرنل لینوکس نشان میدهد راهحل کارآمد معمولاً ترکیبی از سیاستها و ابزارها است، نه صرفاً ترجیح به یکی از مدلها.
تعاریف مختصر
- مخزن یکپارچه (Monorepo): یک مخزن واحد که چندین پروژه، کتابخانه یا سرویس را در خود دارد و تاریخچهٔ مشترک برای کل کد فراهم میآورد. برای مرجع بیشتر: Monorepo در ویکیپدیا.
- درختهای ماژولار / چند-مخزنی: هر پروژه یا مؤلفه در مخزن جداگانه نگهداری میشود و نسخههای وابستگی میتوانند بین مؤلفهها متفاوت باشند.
مزایای عملی مخزن یکپارچه
- اعمال و بررسی تغییرات میانمؤلفهای بهصورت اتمیک ممکن است؛ یک pull request میتواند تمام اصلاحات لازم را شامل شود.
- ردیابی رگرسیون سادهتر میشود، چرا که کد مرتبط در یک commit یا شاخهٔ واحد قرار دارد.
- نیاز به اسکریپتهای پیچیدهٔ هماهنگسازی بین مخازن کاهش یافته و خطاهای ناشی از بازنگریهای ناسازگار کمتر میشود.
معایب و هشدارهای عملی
- استقرار مستقل همچنان واقعیت دارد: حتی با merge اتمیک، سرویسها معمولاً روی زمانبندی و استراتژی rollout مستقل اجرا میشوند؛ بنابراین merge بهتنهایی به معنای استقرار همزمان همهٔ اجزا نیست.
- حس کاذب اتمیک بودن: تیمها ممکن است تصور کنند یک commit تمام سیستم را به وضعیت جدید میبرد؛ اما بازگردانی جزئی و rollback برای مؤلفههایی که مستقل deploy میشوند لازم است.
- سیاست وابستگی سختگیرانه: monorepo معمولاً یک نسخهٔ واحد از هر وابستگی را تحمیل میکند که برای مؤلفههایی با چرخهٔ عمر متفاوت مشکلآفرین است.
شناسهٔ آرتیفکتها (تگها و هشها) — مسئله و راهحلها
وقتی PR شامل بهروزرسانیِ مشخصهٔ انتشار است اما آرتیفکت ساختهشده (مثلاً تصویر کانتینر یا بسته) هنوز در دسترس نیست، باید راهی برای اشارهٔ امن و بازتولیدپذیر به آرتیفکت پیدا کرد. راهکارهای متداول:
- دو مرحلهای کردن جریان تغییر: مرحلهٔ اول: ادغام کد و تولید آرتیفکت در CI که تگ یا هش را ایجاد میکند. مرحلهٔ دوم: commit یا PR خودکار که مشخصهٔ انتشار را با تگ واقعی بهروز میکند و روند CD را تحریک میکند.
- برچسبهای موقت و پروسهٔ تبلیغ: ساخت آرتیفکت با تگ موقت، اجرای تستها، ارتقاء به تگ انتشار و سپس بهروزرسانی manifest.
- منفکسازی مشخصههای انتشار: نگهداری manifestها بهصورت اشیاء واقعی در یک دایرکتوری مشخص یا پایگاهداده انتشار که CI بتواند بهصورت اتمی بهروزرسانی کند.
- امضای آرتیفکت و provenance: درج شناسهٔ ساخت و امضای دیجیتال آرتیفکت در مشخصهٔ انتشار برای تضمین آنچه قرار است استقرار یابد.
الگوی عملی پیشنهادی: GitOps صریح و مشخصههای انتشار ملموس
ترکیب مزایای monorepo با اصول GitOps و استفاده از «مشخصات انتشار reified» مؤثر است. اصول کلیدی:
- هر مؤلفهٔ deployable دارای manifest مستقل (Helm chart، منیفست Kubernetes یا فایل release) باشد.
- فقط وقتی manifest یک مؤلفه تغییر کند باید فرایند CD آن چرخش یابد؛ نه صرفاً بهخاطر ادغام کد در نوک شاخه.
- CI مسئول تولید آرتیفکتها و نوشتن تگ تولیدشده به manifest بهصورت خودکار و قابل رهگیری باشد.
چه چیز از مدل نگهداری لینوکس میآموزیم
مدل نگهداری کرنل لینوکس براساس تقسیم مسئولیت و سلسلهمراتب نگهدارندههاست: تغییرات ابتدا به زیرسیستمها میرسد، آنها مجموعهای از patchها را در شاخهٔ خود نگه میدارند و سپس نگهدارندههای بالاتر و لینوس توری آنها را ادغام میکنند. این ساختار امکان تقسیم مسئولیت، تست متمرکز برای هر زیرسیستم و نگهداری تطبیقی را فراهم میآورد. برای مرجع: کرنل لینوکس در ویکیپدیا.
درسهای عملی برای پروژههای بزرگ
- مسئولیتها را شفاف تعریف کنید: صاحب هر مؤلفه مسئول manifest، تست و rollout باشد.
- از سازوکارهای بررسی سلسلهمراتبی بهره ببرید: نگهبانان زیرسیستم بررسیهای اولیه را انجام دهند قبل از اینکه تغییرات به شاخهٔ عمومی بروند.
- ابزارهای خودکار برای تولید، امضای آرتیفکت و بهروزرسانی manifest بهکار ببرید تا خطای انسانی کاهش یابد.
راهنمای تصمیمگیری
- اگر تغییرات اتمیک میانمؤلفهای زیاد و هماهنگی بین تیمها پرهزینه است، monorepo مزیت دارد.
- اگر مؤلفهها چرخهٔ عمر، تیم یا وابستگیهای جداگانه دارند، درختهای ماژولار منطقیتر است.
- در بسیاری از موارد ترکیبی از دو مدل مناسبتر است: کد میتواند در مخزن واحد باشد اما مشخصههای انتشار و مکانیزمهای CD باید صریح و مستقل مدیریت شوند.
قدم بعدی برای هر تیم مشخص است: چارچوبی برای manifestها تعریف و جریان CI/CD را حولِ تولید و نوشتن شناسهٔ آرتیفکتها خودکار کنید؛ مرزبندی مسئولیتها را شفاف سازید. این اقدامات از اشتباهات رایج در مسیر از کد تا اجرا جلوگیری میکند و امکان رشد مستقل مؤلفهها را بدون از دست دادن هماهنگی فراهم میآورد.





