مونوريبو مع Rust: تنظيم الكود وأفضل الممارسات

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة
```html

مقدمة



المستودع الأحادي (monorepo) هو نهج لإدارة الكود المصدري، حيث يتم تخزين عدة مشاريع (مكتبات، تطبيقات، خدمات) في مستودع واحد. في نظام Rust البيئي، حصل هذا النهج على دعم قوي من خلال آلية Cargo Workspace. في هذه المقالة، سنشرح كيفية تنظيم مستودع أحادي في Rust بشكل فعال، وسنتناول الهيكل، وإدارة التبعيات، وأفضل الممارسات.



لماذا يعتبر المستودع الأحادي مفيدًا لمشاريع Rust؟ يسمح بما يلي:

  • إعادة استخدام الكود بين عدة كريتات (مكتبات وبرامج تنفيذية).
  • تبسيط إدارة الإصدارات و CI/CD.
  • ضمان ذرية التغييرات (يمكن لالتزام واحد تحديث عدة كريتات).
  • تقليل تعقيد إدارة التبعيات.


أساسيات Cargo Workspace



Cargo Workspace هي آلية مدمجة في Rust لإدارة المستودع الأحادي. إنها تجمع عدة كريتات (crates) تحت ملف Cargo.toml واحد على المستوى الأعلى.



إنشاء workspace



للبدء، سننشئ دليل المشروع وملف Cargo.toml في الجذر:



# Cargo.toml (الجذر)[workspace]members = [    "core",    "cli",    "web-api",    "utils"]

[workspace.dependencies]serde = { version = "1.0", features = ["derive"] }tokio = { version = "1.37", features = ["full"] }


هنا قمنا بتعريف أربعة كريتات: core و cli و web-api و utils. النقطة الأساسية هي [workspace.dependencies]. هذا يسمح بتحديد تبعيات مشتركة لجميع كريتات workspace. يمكن لكل كريت أن يشير إليها دون تكرار الإصدارات.



هيكل الدليل



الهيكل النموذجي للمستودع الأحادي في Rust يبدو كالتالي:



my-monorepo/├── Cargo.toml          # workspace الجذر├── Cargo.lock          # ملف lock المشترك├── core/│   ├── Cargo.toml│   └── src/│       └── lib.rs├── cli/│   ├── Cargo.toml│   └── src/│       └── main.rs├── web-api/│   ├── Cargo.toml│   └── src/│       └── main.rs├── utils/│   ├── Cargo.toml│   └── src/│       └── lib.rs└── README.md


كل دليل فرعي هو كريت منفصل له ملف Cargo.toml الخاص به. يمكن أن تكون الكريتات إما مكتبات (lib.rs) أو تطبيقات قابلة للتنفيذ (main.rs).



إدارة التبعيات وإعادة استخدام الكود



التبعيات الداخلية



يمكن للكريتات داخل workspace أن تشير إلى بعضها البعض من خلال المسارات المحلية. على سبيل المثال، يمكن أن يعتمد cli على core و utils:



# cli/Cargo.toml[package]name = "cli"version = "0.1.0"edition = "2021"

[dependencies]core = { path = "../core" }utils = { path = "../utils" }serde = { workspace = true }tokio = { workspace = true }


لاحظ الصياغة { workspace = true } — إنها تسمح باستخدام التبعيات المشتركة المعلنة في ملف Cargo.toml الجذر. هذا يضمن أن جميع الكريتات تستخدم نفس الإصدار من المكتبة.



مثال: مكتبة core المشتركة



لننشئ مكتبة core بسيطة تحتوي على منطق الأعمال:



// core/src/lib.rsuse serde::{Serialize, Deserialize};

#[derive(Debug, Clone, Serialize, Deserialize)]pub struct User { pub id: u64, pub name: String, pub email: String,}

pub fn create_user(name: String, email: String) -> User { User { id: rand::random(), name, email, }}

pub fn greet(user: &User) -> String { format!("Hello, {}!", user.name)}


الآن يمكن لكريت cli استخدام هذه المكتبة:



// cli/src/main.rsuse core::{create_user, greet};

fn main() { let user = create ```

المدونات

توصيات الكتب