مقدمة: لما الدنيا خربت في مشروع “مطعمك ببلاش” 😅
بتذكر مشروع “مطعمك ببلاش” اللي اشتغلت عليه قبل كم سنة؟ يا سيدي العزيز، كان مشروع ناشئ واعد، فكرته بسيطة: تطبيق بجمع عروض المطاعم المحلية. بلشنا بحماس، واستخدمنا أحدث التقنيات… بس بعد شهرين، صار التعديل على أي شغلة كابوس! تغيير قاعدة البيانات؟ بدك تعيد كتابة نص التطبيق. إضافة طريقة دفع جديدة؟ مصيبة! 🤯
هون عرفت إنه في شغلة غلط في التصميم. كنا رابطين منطق عمل التطبيق (عرض العروض، البحث عن المطاعم) بتفاصيل التنفيذ (قاعدة البيانات، واجهة المستخدم). هاي التجربة علمتني قيمة معمارية Hexagonal، واللي بتفصل هاي التفاصيل عن بعضها.
شو هي معمارية Hexagonal (المعمارية السداسية)؟
معمارية Hexagonal، أو Ports and Adapters Architecture، هي نمط تصميم برمجيات بيساعدك تبني تطبيقات مرنة وقابلة للصيانة. الفكرة الرئيسية بسيطة:
* **جوهر التطبيق (Core/Domain):** هو منطق العمل الأساسي (business logic). هذا الجزء بيكون معزول تمامًا عن العالم الخارجي.
* **المنافذ (Ports):** هي واجهات (interfaces) بتحدد كيف بيتفاعل جوهر التطبيق مع العالم الخارجي. في منافذ *داخلية* (incoming ports) بتسمح للعالم الخارجي بتحريك التطبيق (مثل واجهة المستخدم أو الـ API)، ومنافذ *خارجية* (outgoing ports) بتسمح للتطبيق بالوصول إلى العالم الخارجي (مثل قاعدة البيانات أو خدمات الطرف الثالث).
* **المحولات (Adapters):** هي تطبيقات (implementations) للمنافذ. المحولات بتحول البيانات بين تنسيق جوهر التطبيق وتنسيق العالم الخارجي.
ليش اسمها “سداسية”؟
التسمية “سداسية” مش ضرورية بالمعنى الحرفي. ممكن يكون عندك أقل أو أكثر من ستة أطراف بيتفاعلوا مع التطبيق. الفكرة هي تمثيل تعدد الأطراف والتفاعلات المحتملة.
مكونات معمارية Hexagonal بالتفصيل
خلينا نفصل المكونات الأساسية للمعمارية السداسية:
1. جوهر التطبيق (Application Core)
* هو قلب التطبيق، بيحتوي على منطق العمل (business logic) والقواعد الأساسية.
* لا يعتمد على أي تفاصيل تقنية مثل قواعد البيانات أو واجهات المستخدم.
* يتم اختباره بشكل مستقل وسهل.
* مثال: في تطبيق “مطعمك ببلاش”، جوهر التطبيق بيحتوي على منطق البحث عن المطاعم، تطبيق الخصومات، وإدارة العروض.
2. المنافذ (Ports)
* هي واجهات (interfaces) بتحدد كيف بيتفاعل جوهر التطبيق مع العالم الخارجي.
* بتحدد العمليات اللي ممكن العالم الخارجي يعملها على جوهر التطبيق (منافذ داخلية) والعمليات اللي بيحتاجها جوهر التطبيق من العالم الخارجي (منافذ خارجية).
* مثال: منفذ داخلي ممكن يكون `RestaurantSearchService` اللي بيسمح بالبحث عن المطاعم. منفذ خارجي ممكن يكون `RestaurantRepository` اللي بيسمح بالوصول إلى بيانات المطاعم.
3. المحولات (Adapters)
* هي تطبيقات (implementations) للمنافذ.
* بتحول البيانات بين تنسيق جوهر التطبيق وتنسيق العالم الخارجي.
* مثال: محول لقاعدة بيانات MySQL، محول لواجهة مستخدم React، محول لخدمة دفع PayPal.
مثال عملي: تطبيق “مطعمك ببلاش” بإصدار Hexagonal
خلينا نشوف كيف ممكن نعيد تصميم تطبيق “مطعمك ببلاش” باستخدام معمارية Hexagonal.
1. تحديد جوهر التطبيق (Domain)
* `Restaurant`: كلاس بيمثل مطعم (اسم، عنوان، قائمة طعام).
* `Offer`: كلاس بيمثل عرض (وصف، خصم، تاريخ انتهاء).
* `RestaurantSearchService`: واجهة (interface) بتمثل خدمة البحث عن المطاعم.
2. تعريف المنافذ (Ports)
* **منفذ داخلي:**
“`java
public interface RestaurantSearchService {
List
}
“`
* **منفذ خارجي:**
“`java
public interface RestaurantRepository {
List
Restaurant getRestaurantById(Long id);
}
“`
3. تطبيق المحولات (Adapters)
* **محول لواجهة المستخدم (UI Adapter):**
* بيستقبل طلبات البحث من المستخدم.
* بيستخدم `RestaurantSearchService` للبحث عن المطاعم.
* بيعرض النتائج للمستخدم.
* **محول لقاعدة بيانات MySQL (Database Adapter):**
* بينفذ واجهة `RestaurantRepository`.
* بيسترجع بيانات المطاعم من قاعدة بيانات MySQL.
مثال كود (Java):
“`java
// Domain
public class Restaurant {
private Long id;
private String name;
// … getters and setters
}
// Port (Outgoing)
public interface RestaurantRepository {
Restaurant getById(Long id);
}
// Adapter (Database)
public class MySQLRestaurantRepository implements RestaurantRepository {
@Override
public Restaurant getById(Long id) {
// Logic to fetch restaurant from MySQL
return new Restaurant(); // Dummy implementation
}
}
// Usage in the core
public class RestaurantService {
private final RestaurantRepository restaurantRepository;
public RestaurantService(RestaurantRepository restaurantRepository) {
this.restaurantRepository = restaurantRepository;
}
public Restaurant getRestaurantDetails(Long id) {
return restaurantRepository.getById(id);
}
}
“`
فوائد معمارية Hexagonal
* **مرونة عالية:** تغيير قاعدة البيانات أو واجهة المستخدم ما بأثر على جوهر التطبيق.
* **قابلية للاختبار:** جوهر التطبيق قابل للاختبار بشكل مستقل وسهل.
* **قابلية للتطوير:** إضافة ميزات جديدة أو تغيير الميزات الحالية بيكون أسهل.
* **صيانة أسهل:** الكود بيكون منظم ومفصول، مما بيسهل فهمه وصيانته.
نصائح من أبو عمر لتطبيق معمارية Hexagonal بنجاح
* **ابدأ صغير:** لا تحاول تطبيق المعمارية السداسية على كل التطبيق مرة واحدة. ابدأ بجزء صغير وطبقه عليه، وبعدين وسع نطاقه.
* **ركز على جوهر التطبيق:** أهم شي هو تعريف جوهر التطبيق بشكل واضح ومستقل.
* **استخدم واجهات (interfaces):** الواجهات هي أساس المعمارية السداسية. استخدمها لتحديد التفاعلات بين جوهر التطبيق والعالم الخارجي.
* **لا تخف من التجريد:** التجريد هو مفتاح المرونة. استخدمه بحكمة لفصل التفاصيل التقنية عن منطق العمل.
* **استخدم Domain-Driven Design (DDD):** بتساعدك في فهم جوهر عملك.
متى تستخدم معمارية Hexagonal؟
* عندما يكون لديك تطبيق معقد بمنطق عمل كبير.
* عندما تتوقع تغييرات متكررة في البنية التحتية (قاعدة البيانات، واجهة المستخدم).
* عندما تريد تطبيق قابل للاختبار والصيانة بسهولة.
خلاصة ونصيحة أخيرة 💡
معمارية Hexagonal هي أداة قوية لبناء تطبيقات مرنة وقابلة للتطوير. صحيح إنها بتطلب شوية جهد في البداية، بس الاستثمار فيها بيستاهل على المدى الطويل. تذكر، مش كل المشاريع بتحتاج هاي المعمارية، بس لما تحس إنك وصلت لمرحلة من التعقيد، جربها وشوف كيف ممكن تحسن من جودة الكود تبعك. 💪