من المترجم: مرحبا يا هبر! نعم ، هذا مقال آخر حول مزايا وعيوب المستودعات. كنت بصدد كتابة مقالتي حول كيفية استخدامنا للمستودع الأحادي ، وكيف تحولنا من مخضرم إلى بازيل وماذا جاء منه. لكن بينما كنت أفكر في الأمر ، ظهرت مقالة ممتازة من المطور من Lyft ، والتي قررت ترجمتها نيابة عنك. أعدك بنشر الإضافات إلى المقالة ، بالإضافة إلى تجربة bazel كتتمة.
نحن في عام 2019 الجديد ، وأنا على استعداد لمناقشة أخرى حول مزايا (أو عدم وجودها) في تخزين جميع التعليمات البرمجية المصدر للمنظمة في "Monorepository". بالنسبة لأولئك الذين ليسوا على دراية بهذا النهج ، تتمثل الفكرة في تخزين كل شفرة المصدر في مستودع واحد لنظام التحكم في الإصدار. البديل ، بالطبع ، هو تخزين الكود المصدري في عدة مستودعات مستقلة ، وعادةً ما يتم تقسيمهم على طول حدود الخدمات / التطبيقات / المكتبات.
في هذا المنشور ، سوف أسمي هذا النهج "متعدد المستودعات".
تستخدم بعض عمالقة تكنولوجيا المعلومات مستودعات أحادية ، بما في ذلك Google و Facebook و Twitter وغيرها. بالطبع ، إذا كانت هذه الشركات ذات السمعة الطيبة تستخدم مستودعات أحادية ، فعندئذ يجب أن تكون فوائد هذا النهج ضخمة ، وعلينا جميعًا أن نفعل الشيء نفسه ، أليس كذلك؟ لا! كما يقول عنوان المقال: "الرجاء عدم استخدام المستودع الأحادي!" لماذا؟ لأنه
على نطاق واسع ، سوف يحل المخزون الموحل جميع المشكلات نفسها التي يحلها المستودع ، ولكن في الوقت نفسه يستفزك إلى التماسك القوي للرمز الخاص بك ويتطلب بذل جهود لا تصدق لزيادة قابلية تطوير نظام التحكم في الإصدار الخاص بك .
وبالتالي ، على المدى المتوسط والبعيد ، لا يوفر المستودع الأحادي أي مزايا تنظيمية ، في حين أنه يترك أفضل المهندسين في الشركة مصابًا بمتلازمة ما بعد الصدمة (يتجلى ذلك في شكل الترويل والتمتم غير المتماسك حول أداء البوابة).
استطراد قصير: ماذا أعني بـ "على نطاق واسع"؟ لا توجد إجابة واحدة على هذا السؤال ، ولكن بسبب أنا متأكد من أنك سألتني عن هذا الأمر ، دعنا نقول أن هناك حوالي 100 مطورًا يكتبون رمزًا بدوام كامل.
المزايا النظرية لمستودع أحادي السبب ولماذا لا يمكن تحقيقه دون استخدام الأدوات التي تستخدم في polyrezitories (أو خطأ)
الميزة النظرية 1: تعاون أسهل ومشاركة الكود
يزعم مؤيدو المستودعات الأحادية أنه عندما تكون جميع الشفرات في نفس المستودع ، يكون احتمال تكرار الكود أقل ، ومن المرجح أن تعمل فرق مختلفة معًا على بنية تحتية مشتركة.
هذه هي الحقيقة المريرة حول المستودعات الأحادية متوسطة الحجم (وسيظهر هذا باستمرار في هذا القسم): سرعان ما يصبح من غير العملي بالنسبة للمطور الاحتفاظ بكامل رمز المستودع في محطة العمل الخاصة به أو البحث في قاعدة الشفرة بأكملها باستخدام أدوات مساعدة مثل grep. لذلك ، يجب أن يوفر أي مستودع أحادي يريد توسيع النطاق شيئين:
1) يشبه نظام الملفات الظاهري الذي يسمح لك بتخزين جزء محلي فقط من التعليمات البرمجية محليًا. يمكن تحقيق ذلك باستخدام نظام ملفات خاص مثل
Perforce ، والذي يدعم هذا الوضع محليًا ، باستخدام أداة
G3 الداخلية من Google أو
GVFS من Microsoft.
2) أدوات متطورة كخدمة (كخدمة) لفهرسة / البحث / عرض شفرة المصدر. بسبب لن يقوم أي من المطورين بتخزين جميع التعليمات البرمجية المصدر على محطة العمل الخاصة بهم في حالة قابلة للبحث ، يصبح من الأهمية بمكان أن تكون قادرة على إجراء مثل هذا البحث في جميع أنحاء قاعدة الشفرة.
بناءً على حقيقة أن المطور سيكون لديه حق الوصول إلى جزء صغير فقط من الكود المصدري في أي وقت معين ، هل هناك بعض الاختلاف على الأقل بين تنزيل جزء من المستودع الأحادي أو تنزيل عدة مستودعات مستقلة؟
لا يوجد فرق .
في سياق الفهرسة / البحث / التصفح ورمز مماثل ، يمكن لهذه الأداة الافتراضية البحث بسهولة في عدة مستودعات ودمج النتيجة. في الواقع ، هذا هو بالضبط كيفية عمل البحث على GitHub ، وكذلك أدوات البحث والفهرسة الأكثر تطوراً مثل
Sourcegraph .
وبالتالي ، من وجهة نظر العمل التعاوني على الكود على نطاق واسع ، يضطر المطورين في أي حال إلى العمل فقط مع جزء من قاعدة الكود ويستخدمون أدوات عالية المستوى. لا يوجد فرق بين ما إذا كان يتم تخزين الكود في مستودع أحادي أم في عدة مستودعات مستقلة ، ويتم حل المشكلة بالطريقة نفسها ،
وتعتمد فعالية العمل معًا على الكود فقط على الثقافة الهندسية ، وليس على طريقة تخزين الأكواد المصدر .
الميزة النظرية 2: تجميع واحد / لا إدارة تبعية
الحجة التالية ، التي يستشهد بها عادة مؤيدو المستودعات الأحادية ، هي أن تخزين جميع الشفرات في مستودع أحادي واحد يحرمك من الحاجة إلى إدارة التبعيات ، كما يتم جمع كل رمز في نفس الوقت. هذه كذبة! على نطاق واسع ، لا توجد ببساطة طريقة لإعادة إنشاء كل شفرة المصدر وتشغيل جميع الاختبارات الآلية في كل مرة يرتكب فيها شخص ما تغييرات على نظام التحكم في الإصدار (أو الأهم من ذلك ، في كثير من الأحيان ، على خادم CI عند إنشاء فرع جديد أو طلب سحب). لحل هذه المشكلة ، تستخدم جميع المستودعات الأحادية الكبيرة نظام
الإنشاء المتطور (على سبيل المثال
Bazel / Blaze من Google أو
Buck من Facebook) ، والذي تم تصميمه لمراقبة التغييرات وكتلها التابعة وبناء رسم بياني للاعتماد على الكود المصدري. يتيح لك هذا الرسم البياني تنظيم التخزين المؤقت الفعال لنتائج التجميع واختباراته ، لذا فإن التغييرات واعتماداتها فقط تحتاج إلى إعادة التجميع والاختبار.
علاوة على ذلك ، منذ ذلك الحين يجب نشر الكود الذي تم جمعه في نهاية المطاف ، وكما تعلم ، لا يمكن نشر جميع البرامج في وقت واحد ، من المهم أن يتم التحكم في جميع القطع الأثرية للتجميع ، بحيث تتم إعادة صياغة القطع الأثرية حسب الضرورة. وهذا يعني في جوهره أنه حتى في عالم المستودعات الأحادية ، يمكن أن توجد عدة إصدارات من الكود في نفس الوقت بطبيعتها ، ويجب مراقبتها وتنسيقها بعناية.
سيؤكد مؤيدو المستودعات الأحادية أنه حتى مع مراعاة الحاجة إلى تتبع التجميعات / التبعيات ، فإن هذا لا يزال يوفر ميزة لا يمكن إنكارها ، حيث يصف التزام واحد الحالة الكاملة للعالم بأسره. أود أن أقول أن هذه الميزة مثيرة للجدل إلى حد ما ، بالنظر إلى أن الرسم البياني للاعتماد موجود بالفعل ، ويبدو أن مهمة معرف تكميلية لكل مستودع مستقل كجزء من هذا الرسم البياني ، قد تكون مهمة تافهة إلى حد ما ، ويمكن في الواقع أن يعمل Bazel بسهولة مع عدة مستودعات مستقلة وكذلك مع واحد مستودع أحادي ، يستخلص المستوى الأساسي من المطور. علاوة على ذلك ، من السهل تطبيق أدوات إعادة التخزين الآلية هذه التي تقوم تلقائيًا بتحديث إصدارات المكتبات التابعة في عدة مستودعات مستقلة في وقت واحد ، مما يؤدي إلى تسوية الفرق بين المستودع الأحادي والمستودع متعدد الأقسام في هذا الجزء (المزيد حول هذا لاحقًا).
والنتيجة النهائية هي أن حقائق التجميع / النشر على نطاق واسع هي نفسها في الغالب بالنسبة للمستودعات الأحادية والمستودعات المتعددة.
لا يوجد فرق للأدوات ، لا ينبغي أن يكون للمطورين كتابة التعليمات البرمجية .
الميزة النظرية 3: إعادة بناء الكود هو التزام ذري بسيط
أخيرًا ، فإن الفضيلة الأخيرة التي ذكرها مؤيدو المستودعات الأحادية هي أن المستودع الواحد يجعل إعادة ترميز الكود أكثر بساطة نظرًا لسهولة البحث ، وفكرة أن التزامًا منفردًا يمكن أن يمتد لمستودع التخزين بأكمله. هذا غير صحيح لعدة أسباب:
1) كما هو موضح أعلاه ، على نطاق واسع ، لن يتمكن المطور من تعديل أو البحث في قاعدة الشفرة بأكملها على جهازه المحلي. وبالتالي ، فإن فكرة أنه يمكن لأي شخص بسهولة استنساخ مستودعه بالكامل لأنفسهم وفقط grep / استبدال ليس من السهل تطبيقه.
2) حتى لو افترضنا أنه بمساعدة نظام ملفات ظاهري معقد ، يمكن للمطور استنساخ وتحرير قاعدة الشفرة بأكملها ، فكيف يحدث هذا؟ أنا لا أتحدث عن إصلاح الخلل في تنفيذ مكتبة مشتركة ، لأن هذا الموقف يتم التعامل معه بشكل متساوٍ في حالة مستودع واحد وفي حالة مستودع متعدد (بافتراض نظام إنشاء / نشر مماثل ، كما هو موضح أعلاه). أنا أتحدث عن تغيير واجهة برمجة التطبيقات للمكتبة ، والتي ستتبعها العديد من أخطاء الترجمة في الأماكن التي تسمى هذه المكتبة. في قاعدة التعليمات البرمجية الكبيرة جدًا ،
يكاد يكون من المستحيل إجراء تغيير على واجهة برمجة التطبيقات الأساسية ، والتي ستتم معاينتها من قبل جميع الفرق المشاركة قبل أن تجبرك تعارضات الدمج على بدء العملية مرة أخرى . لدى المطور احتمالان حقيقيان: يمكنه الاستسلام والتوصل إلى حل للمشكلة المتعلقة بواجهة برمجة التطبيقات (في الممارسة ، يحدث هذا في كثير من الأحيان أكثر مما نود جميعًا) ، أو يمكنه تحويل واجهة برمجة التطبيقات الحالية ، وكتابة واجهة برمجة تطبيقات جديدة ، ثم الشروع في العمل لفترة طويلة تحديث مؤلم جميع المكالمات إلى API القديمة في جميع أنحاء قاعدة التعليمات البرمجية. في أي حال ،
هذه هي نفس العملية تماما كما هو الحال مع مستودع .
3) في عالم موجه نحو الخدمة ، تتكون التطبيقات من العديد من المكونات المزدوجة التي تتفاعل مع بعضها البعض باستخدام نوع من واجهة برمجة التطبيقات الموصوفة جيدًا. ستتحول المؤسسات الكبيرة عاجلاً أم آجلاً إلى استخدام IDL (لغة وصف الواجهة) ، مثل Thrift أو Protobuf ، والتي تسمح لك بإجراء واجهات برمجة تطبيقات آمنة من النوع وإجراء تغييرات متوافقة مع الإصدارات السابقة. كما هو موضح في القسم السابق بشأن التجميع / النشر ،
لا يمكن نشر الكود في وقت واحد . يمكن نشره على مدار فترة زمنية: ساعات أو أيام أو حتى أشهر. لذلك ، يجب على المطورين التفكير في التوافق مع التغييرات التي أجراها. هذه هي حقيقة تطوير البرمجيات الحديثة ، والتي يود الكثيرون تجاهلها ، لكن لا يمكنهم تجاهلها. لذلك ، عندما يتعلق الأمر بالخدمات (على عكس مكتبات API) ، ينبغي للمطورين استخدام أحد النهجين الموصوفين أعلاه (لا تقم بتغيير API أو الانتقال إلى دورة الإهمال)
وهذا هو نفسه تمامًا لكل من المستودع الأحادي ومستودع البيانات .
عند الحديث عن إعادة بناء قواعد الكود الكبيرة ، تقوم العديد من المؤسسات الكبيرة بتطوير أدوات إعادة
التجهيز الآلية الخاصة بها ، مثل
fastmod ، التي تم إصدارها مؤخرًا بواسطة Facebook. كما هو الحال دائمًا ، يمكن أن تعمل هذه الأداة بسهولة مع مستودع واحد أو عدة مستودعات مستقلة. Lyft لديه أداة تسمى "refactorator" التي تفعل ذلك تماما. إنه يعمل مثل fastmod ، لكنه يعمل على أتمتة التغييرات عبر العديد من مستودعاتنا ، بما في ذلك إنشاء طلبات السحب ، وتتبع حالات المراجعات ، وما إلى ذلك.
مساوئ فريدة من monospositories
في القسم السابق ، قمت بإدراج جميع المزايا النظرية التي يوفرها المستودع ، ولاحظت أنه من أجل الاستفادة منها ، من الضروري إنشاء أدوات معقدة بشكل لا يصدق ولن تختلف عن تلك الخاصة بالمستودعات المتعددة. في هذا القسم ، سأذكر عيبين فريدين للمستودعات الأحادية.
العيب 1: اتصال قوي وبرمجيات المصدر المفتوح
من الناحية التنظيمية ، يستفز المونوريتوري إنشاء برامج هشة مزدوجة الإحكام. إنه يمنح المطورين الشعور بأنه يمكنهم بسهولة إصلاح الأخطاء في التجريد ، على الرغم من أنهم في الواقع لا يمكنهم ذلك بسبب عملية التجميع / النشر غير المستقرة والعوامل البشرية / التنظيمية / الثقافية التي تنشأ عند محاولة إجراء تغييرات فورًا عبر قاعدة الكود.
تمثل بنية الكود في مستودعات البيانات الحدودية الواضحة والشفافة بين أصحاب الفرق / المشروعات / التجريدات / أصحاب الكود وتفرض على المطور التفكير بعناية في واجهة التفاعل. هذه ميزة بسيطة ولكنها مهمة للغاية: فهي تجعل المطورين يفكرون على نطاق أوسع وعلى المدى الطويل. علاوة على ذلك ، لا يعني استخدام المستودعات المتعددة أن المطورين لا يمكنهم تجاوز حدود المستودع. سواء حدث ذلك أم لا ، فإنه يعتمد فقط على ثقافة التطوير ، وليس على ما إذا كان يتم استخدام مستودع أو مستودع متعدد.
ملزمة قوية لها أيضا عواقب وخيمة فيما يتعلق بفتح شفرة المصدر. إذا أرادت شركة إنشاء أو استهلاك برنامج مفتوح المصدر ، فإن استخدام المستودعات المتعددة أمر لا بد منه. إن التشوهات التي تحدث عندما تحاول شركة ما أن تضع مشروعها في مصدر مفتوح من مستودعها الأحادي (استيراد / تصدير أكواد المصدر ، متتبع الأخطاء العامة / الخاصة ، طبقات إضافية لاستخلاص الفرق في المكتبات القياسية ، وما إلى ذلك) لا تؤدي إلى تعاون مثمر و بناء مجتمع وكذلك خلق النفقات العامة كبيرة.
العيب 2: قابلية تطوير نظام التحكم في الإصدار
يعد توسيع نطاق نظام التحكم في الإصدار لمئات المطورين ومئات الملايين من أسطر التعليمات البرمجية ودفق ضخم من المهام مهمة هائلة. مستودع تويتر الأحادي ، الذي تم إنشاؤه منذ 5 سنوات (استنادًا إلى git) ، كان أحد أكثر المشاريع التي لا قيمة لها شاهدتها في حياتي المهنية. تشغيل أمر بسيط مثل
git status
استغرق
دقائق . إذا كانت النسخة المحلية من المستودع قديمة جدًا ، فقد يستغرق التحديث
ساعات (في ذلك الوقت كانت ممارسة إرسال محركات الأقراص الثابتة بنسخة من المستودع للموظفين البعيدين باستخدام أحدث إصدار من الشفرة). أتذكر هذا ليس للسخرية من مطوري Twitter ، ولكن لتوضيح مدى تعقيد هذه المشكلة. أستطيع القول أنه بعد 5 سنوات ، لا يزال أداء مستودع Twitter الأحادي بعيدًا عن الأداء الذي يود مطورو فريق Tilling رؤيته ، وهذا ليس لأنهم حاولوا جاهدين.
بالطبع ، على مدى السنوات الخمس الماضية ، حدث بعض التطور في هذا المجال. لقد أدى
Git VFS من Microsoft ، والذي يستخدم لتطوير Windows ، إلى ظهور نظام ملفات ظاهري حقيقي لـ git ، والذي وصفته أعلاه كشرط أساسي لتوسيع نطاق نظام التحكم في الإصدار (ومع شراء Microsoft Github ، يبدو أن هذا المستوى من القياس التطبيق في الميزات التي تقدم GiHub لعملائها من الشركات). وبالطبع ، تواصل Google و Facebook استثمار موارد ضخمة في أنظمتها الداخلية حتى تستمر في العمل ، على الرغم من عدم توفر أي شيء تقريبًا للجمهور.
إذن لماذا تحتاج إلى حل هذه المشكلات بشكل عام من خلال توسيع نطاق نظام التحكم في الإصدار ، إذا كانت مجموعة الأدوات ، كما هو موصوف في القسم السابق ، مطلوبة تمامًا كما هي الحال بالنسبة للمستودع متعدد المستويات؟ لا يوجد سبب معقول لهذا.
الخاتمة
كما يحدث غالبًا في تطوير البرامج ، فإننا ننظر إلى أكثر شركات البرمجيات نجاحًا كمثال ونحاول استعارة أفضل ممارساتها دون فهم ما الذي دفع هذه الشركات إلى النجاح. المخازن الاحتكارية ، في رأيي ، هي مثال نموذجي لمثل هذه الحالة. لقد استثمرت Google و Facebook و Twitter قدراً هائلاً من الموارد في أنظمة تخزين الأكواد الخاصة بها للتوصل إلى حل
مماثل للحل
المطلوب في مستودع متعدد ، ولكنه يثير ارتباطًا قويًا ويتطلب استثمارًا كبيرًا في التحكم في إصدار الإصدارات .
في الواقع ، على نطاق واسع ، كيف تعمل الشركة مع العمل مع الكود ، التعاون ، الربط القوي ، إلخ.
يعتمد بشكل مباشر على الثقافة الهندسية والقيادة ، وليس له علاقة بما إذا كان يتم استخدام مستودع أو polypository . كلا الحلول تبدو متماثلة للمطور. فلماذا استخدام monorepository؟
من فضلك لا!