مستودع واحد مع Java: تنظيم الكود عمليًا
\nفي تطوير Java الحديث، يبرز السؤال بشكل متزايد حول الاختيار بين المستودع الواحد (monorepo) ومجموعة من المستودعات المنفصلة. المستودع الواحد هو نهج يتم فيه تخزين جميع أكواد المشروع (عدة خدمات، مكتبات، تكوينات) في مستودع Git واحد. في هذه المقالة، سنشرح كيفية تنظيم مستودع واحد مع Java عمليًا: من هيكل المجلدات إلى إعداد البناء وCI/CD. ستحصل على أمثلة كود جاهزة وتوصيات تساعدك على تجنب الأخطاء النموذجية.
\n\nلماذا المستودع الواحد لـ Java؟
\nالمستودع الواحد مفيد بشكل خاص لمشاريع Java حيث تعتمد العديد من الوحدات على بعضها البعض. المزايا الرئيسية:
\n- \n
- إصدار موحد للتبعيات — تستخدم جميع الوحدات إصدارًا واحدًا من المكتبات، مما يمنع التعارضات. \n
- إعادة هيكلة مبسطة — تغيير API في وحدة واحدة يظهر فورًا في جميع الوحدات التابعة. \n
- تكوين بناء مشترك — يتم إعداد Gradle أو Maven مرة واحدة لجميع الوحدات. \n
- تكامل CI/CD متكامل — خط أنابيب واحد لجميع الخدمات، مما يسهل تتبع التغييرات. \n
ومع ذلك، يتطلب المستودع الواحد انضباطًا: بدون هيكل واضح، يتحول إلى فوضى. دعنا ننظر في التنظيم الصحيح.
\n\nهيكل المستودع الواحد لمشروع Java
\nالهيكل الموصى به للمستودع الواحد مع Java (على سبيل المثال باستخدام Gradle):
\nmy-monorepo/\n├── build.gradle.kts # ملف البناء الجذر\n├── settings.gradle.kts # يشمل جميع الوحدات\n├── gradle.properties # خصائص مشتركة\n├── libs/ # مكتبات مشتركة\n│ ├── common-utils/\n│ │ ├── build.gradle.kts\n│ │ └── src/\n│ └── logging/\n│ ├── build.gradle.kts\n│ └── src/\n├── services/ # خدمات مصغرة\n│ ├── user-service/\n│ │ ├── build.gradle.kts\n│ │ └── src/\n│ └── payment-service/\n│ ├── build.gradle.kts\n│ └── src/\n├── config/ # تكوينات (مثل checkstyle, spotbugs)\n│ └── checkstyle.xml\n└── docker/ # ملفات Docker لكل خدمة\n ├── user-service.Dockerfile\n └── payment-service.Dockerfile\n\nالمبادئ الأساسية:
\n- \n
- تنقسم الوحدات إلى
libs(مكتبات) وservices(تطبيقات قابلة للتنفيذ). \n - يحدد ملف
build.gradle.ktsالجذر الإضافات والإصدارات المشتركة. \n - يتضمن ملف
settings.gradle.ktsجميع المشاريع الفرعية. \n
مثال على settings.gradle.kts:
rootProject.name = "my-monorepo"\n\ninclude(\n "libs:common-utils",\n "libs:logging",\n "services:user-service",\n "services:payment-service"\n)\n\n\nإعداد التبعيات بين الوحدات
\nالمهمة الرئيسية للمستودع الواحد هي إدارة التبعيات الداخلية. دعنا ننظر في مثال حيث يعتمد user-service على common-utils.
الخطوة 1. في ملف gradle.properties الجذر، نعلن الإصدارات:
# gradle.properties\nkotlinVersion=1.9.0\nspringBootVersion=3.2.0\ncommonUtilsVersion=1.0.0\n\nالخطوة 2. في ملف build.gradle.kts الجذر، نضيف الإضافات ونضبط الإعدادات المشتركة:
plugins {\n id("java-library") apply false\n id("org.springframework.boot") version "3.2.0" apply false\n id("io.spring.dependency-management") version "1.1.4" apply false\n}\n\nallprojects {\n group = "com.example"\n version = "1.0.0"\n\n repositories {\n mavenCentral()\n }\n}\n\nsubprojects {\n apply(plugin = "java-library")\n\n java {\n sourceCompatibility = JavaVersion.VERSION_17\n targetCompatibility = JavaVersion.VERSION_17\n }\n\n dependencies {\n implementation("org.slf4j:slf4j-api:2.0.9")\n testImplementation("org.j