Sourcery لـ Swift: الدليل الشامل لتوليد الكود التلقائي
1. ما هو Sourcery ولماذا تحتاجه؟
Sourcery هي أداة قوية لتوليد الكود التلقائي (Code Generation) للغة Swift، طورها Krzysztof Zabłocki وفريقه. تتيح لك هذه الأداة إنشاء الكود المتكرر (Boilerplate Code) تلقائيًا بناءً على التعليقات التوضيحية (Annotations) وهيكل ملفات المصدر الخاصة بك. بدلاً من كتابة تطبيقات البروتوكولات المتكررة يدويًا مثل Equatable وHashable وCodable، أو إنشاء كائنات وهمية (Mocks) للاختبارات، أو كتابة كود Auto Layout، يمكنك وصف قواعد التوليد مرة واحدة فقط، ويقوم Sourcery بالباقي.
لماذا تحتاج إليه؟ في المشاريع الحقيقية بلغة Swift، جزء كبير من الكود هو كود ميكانيكي ومتكرر. هذا لا يستهلك وقت المطور فحسب، بل هو أيضًا مصدر للأخطاء: نسيت إضافة حقل جديد إلى Equatable — تحصل على خطأ. يحل Sourcery هذه المشكلة بتولي المهام الروتينية. يقوم بتحليل الكود الخاص بك (AST — شجرة التركيب النحوي المجردة) وبناءً على قوالب (Stencil أو Swift-based) يقوم بإنشاء ملفات جديدة. هذا مفيد بشكل خاص في المشاريع الكبيرة التي تحتوي على عشرات أو مئات النماذج (Models) ووحدات التحكم (ViewControllers) والخدمات (Services).
Sourcery ليست مكتبة وقت تشغيل (Runtime Library) — بل هي أداة وقت الترجمة (Compile-Time Tool). تقوم بتشغيلها كجزء من عملية البناء (عبر Build Phase في Xcode أو عبر SPM/Tuist)، فتقوم بتوليد الملفات، ثم يتم تجميع هذه الملفات مع بقية الكود. هذا النهج يضمن عدم وجود أي حمل إضافي (Overhead) في وقت التشغيل ويوفر قابلية توقع كاملة.
2. التثبيت
هناك عدة طرق لتثبيت Sourcery. الطريقة الأسهل والأكثر توصية هي عبر Homebrew:
brew install sourcery
للمشاريع التي تستخدم Swift Package Manager (SPM)، يمكن إضافة Sourcery كإضافة (Plugin). لكن الأكثر شيوعًا هو استخدامه كملف ثنائي منفصل (Binary) يتم استدعاؤه من سكريبت البناء. للتثبيت عبر Mint (مدير حزم لأدوات Swift):
mint install krzysztofzablocki/Sourcery
يمكنك أيضًا تنزيل الملف الثنائي الجاهز من GitHub Releases ووضعه في مجلد المشروع. بعد التثبيت، تأكد من أن الأمر متاح:
sourcery --version
3. البداية السريعة — مثال عملي بسيط
لنقم بإنشاء مثال بسيط: التوليد التلقائي لتطبيق بروتوكول Equatable لهيكل (Struct).
الخطوة 1: قم بإنشاء ملف الكود المصدري (مثلًا Sources/Models/User.swift):
import Foundation
// sourcery: AutoEquatable
struct User {
let id: Int
let name: String
let email: String
}
لاحظ التعليق // sourcery: AutoEquatable — هذا هو التعليق التوضيحي (Annotation) الذي يخبر Sourcery بضرورة توليد تطبيق Equatable لهذا الهيكل.
الخطوة 2: قم بإنشاء قالب (Template) (مثلًا Templates/AutoEquatable.stencil):
// Generated by Sourcery
// swiftlint:disable all
{% for type in types.all where type.annotations.AutoEquatable %}
extension {{ type.name }}: Equatable {
static func == (lhs: {{ type.name }}, rhs: {{ type.name }}) -> Bool {
{% for variable in type.storedVariables %}
{% if not forloop.first %} && {% endif %}lhs.{{ variable.name }} == rhs.{{ variable.name }}
{% endfor %}
}
}
{% endfor %}
الخطوة 3: قم بتشغيل Sourcery:
sourcery --sources Sources/Models --templates Templates --output Generated
الخطوة 4: النتيجة — في مجلد Generated سيظهر ملف AutoEquatable.generated.swift:
// Generated by Sourcery
// swiftlint:disable all
extension User: Equatable {
static func == (lhs: User, rhs: User) -> Bool {
return lhs.id == rhs.id && lhs.name == rhs.name && lhs.email == rhs.email
}
}