What is 3 Tier Architecture? And Why?

رابط الفيديو على يوتيوب


المقدمة

النهارده هنتكلم عن موضوع مهم جدًا في البرمجة اسمه 3 Tier Architecture. يمكن يكون فيه ناس سمعت عنه وناس لأ.

أغلبنا عارف إن أهم حاجة في شغل البرمجة هي (Software Architecture) نفسها. ليه؟ علشان كل الـComponents في البرنامج تشتغل مع بعض بشكل منظم من غير ما نخبط في بعضنا، ونقدر نعدّل أو نوسّع الكود بسهولة في المستقبل.

فكرة الـ3 Tier Architecture ببساطة إنه يخلّي الكود بتاعنا متقسّم على شكل طبقات (Tiers)، كل طبقة مسؤولة عن جزء معيّن من منطق البرنامج. ده بيساعدنا قوي في شغل الصيانة (Maintenance) وتطوير السيستم، وكمان بيسهّل علينا إننا نضيف مميزات (Features) جديدة.


1) Presentation Layer

هنفترض اننا شغالين على مشروع بنك وكل الأمثلة هتبقا عليه.

دي الطبقة اللي بنكتب فيها كل حاجة تخص الـUI أو واجهة المستخدم. يعني شكل الأبليكيشن على الموبايل بيكون في الطبقة دي، وشكله على الويب برضه هنا، وهكذا للديسكتوب. أي حد هيستخدم السيستم هيشوف الحاجات اللي في الطبقة دي.

المفروض ما نكتبش في الـPresentation Layer غير الحاجات المتعلقة بعرض الداتا أو فورم الإدخال أو الشاشات اللي قدام المستخدم. لكن logic تحويل الفلوس نفسه (مثلاً الـFunction اللي تخصم رصيد وتضيفه لحد تاني) مش مكانه هنا، علشان ما نضطرش نكرّره في أكتر من واجهة.


2) Business Layer

الطبقة دي فيها كل منطق البرنامج (Business Logic). يعني مثلًا هنا بتحط الكلاسات (Classes) أو الـFunctions اللي مسئولة عن تنفيذ عملية التحويل، حساب العمولة، التأكد إن فيه رصيد كافي… إلخ.

لما ييجي تطبيق الموبايل أو الويب أو الديسكتوب يعوز ينفّذ تحويل، بيستدعي نفس الـFunction الموجودة في الـBusiness Layer. فلو فيه أي تغيير في المنطق ده، بنعدّل في مكان واحد بس. ده بيساعد جدًا إنك تمنع الـSpaghetti Code (كود متداخل ومكرر) ويوفّر وقت وجهد على المدى الطويل.


3) Data Layer

الطبقة التالتة هي المسئولة عن التعامل مع الـDatabase أو أي نوع تاني من الـStorage. سواء عندنا SQL Server, Oracle, MySQL أو حتى Files، الطبقة دي بتتولّى إنها تنفّذ أوامر حفظ البيانات أو قراءتها أو تحديثها.

الميزة هنا إنك تقدر تغيّر الـDatabase اللي شغال عليها من غير ما تلمس الـBusiness Layer أو الـPresentation Layer، لأن التعامل مع الداتا في مكان لوحده. وكل ما تيجي البزنس لير تحتاج إنها تحفظ أو تقرأ حاجة من الداتا، بتنده للـData Layer علشان تنفذ الطلب ده.


ليه الـ3 Tier Architecture مفيد؟

  1. مركزية الكود (Centralization):
    أي منطق (Logic) بيتكتب مرة واحدة بس في الـBusiness Layer، ولما نحب نضيف تعديل صغير أو نصلّح مشكلة، نعمله هنا بس.

  2. إعادة الاستخدام (Reusability):
    ممكن نعمل أكتر من واجهة (موبايل، ويب، ديسكتوب… إلخ) كله بيستخدم نفس الـFunctions في البزنس لير، فمش بنضيع وقت نكرّر الكود.

  3. سهولة الصيانة (Maintainability):
    فصل الطبقات بيخلّي الكود مرتب، ولو فيه Bug في الـData Layer مثلاً، بنصلحه هناك وما نلمسش الـPresentation Layer أو الـBusiness Layer.

  4. قابلية التوسّع (Scalability):
    لو فجأة البنك عايز يفتح API علشان بنك تاني يستخدم نفس خدمات التحويل، هنضيف طبقة Intégration أو حاجة زي كده بسهولة، ونظلّ مستفيدين من البزنس لير والداتا لير من غير ما نكرّر الكود.


الخاتمة

الفكرة في 3 Tier Architecture إننا نقسّم المسئوليات (Separation of Concerns) بحيث يبقى عندنا حد بيعرض الداتا (Presentation)، وحد بيعالج المنطق (Business)، وحد بيتعامل مع الداتا الفعلية (Data). عشان كده أي مبرمج محترف بيفكر في الموضوع ده من أول يوم، علشان Divide and Conquer في كل حتة في الكود.

فيه ناس ممكن يفضلوا يكتبوا الكود كله في حتة واحدة بحجّة إنهم فاهمين الدنيا، لكن التطوير ده هيسبب مشاكل كبيرة مع مرور الوقت في الصيانة والإضافة. البرمجة مستويات وخبرات، والأساس فيها هو إنك تفهم الحاجات دي من بدري. ومع الوقت هتلاقي الموضوع فعلاً بيسهّل عليك جدًا أي تعديل أو تطوير في المستقبل.

أتمنى إن الموضوع يكون واضح وبسيط، وإن شاء الله هنتعلم ونطبّق الموضوع ده عمليًا في كورسات قادمة أو مشاريع تانية. يعطيكم ألف عافية، والسلام عليكم ورحمة الله وبركاته.

مثال

في العادة، عند الحديث عن 3-Tier Architecture (الطبقات الثلاث) في سياق تطبيقات .NET، نقصد بها الفصل بين الطبقات التالية بشكل واضح:

  1. Presentation (أو Application أو UI Layer):
    • مسؤولة عن الـ Endpoints مثل Controllers في حالة ASP.NET API، أو واجهة المستخدم في حالة تطبيقات ويب أو مكتبية.
    • يتم فيها استقبال الطلبات (Requests) وإرجاع الاستجابات (Responses).
    • لا تحتوي عادة على منطق الأعمال (Business Logic) بل تستدعي الخدمات أو الطبقات الأخرى.

  2. Business Logic (أو Domain أو Application Core أو Service Layer):
    • تحتوي على المنطق الخاص بالأعمال (Business Rules) ومعالجة البيانات.
    • قد تضم خدمات (Services) تقوم بعمليات ملموسة حسب احتياجات المشروع (مثل الحسابات أو التحقق Validation أو التعامل مع الدومين).
    • من الممكن أن تحتوي على نماذج الدومين Entities أو قد تُستقل طبقة الـ Domain وحدها في مشاريع كبيرة (مثلاً في DDD سيتواجد Domain Layer منفصل).
    • تحتوي على واجهات (Interfaces) تحدد طريقة التعامل مع الـ Repositories.

  3. Data Access (أو Infrastructure أو Persistence Layer):
    • مسؤولة عن التخاطب مع قواعد البيانات أو أي مصادر بيانات خارجية (مثل ملفات، خدمات خارجية، إلخ.).
    • تحتوي على الـ Repositories (كلاسات ملموسة Concrete Classes تطبق الواجهات Interface الموجودة في طبقة الـ Business Logic).
    • أي تفاصيل تخص البنية التحتية (Access to DB, External Services, Configurations… إلخ).

في ما يلي مثال تفصيلي يُظهر بنية مشروع .NET API بشكل عام مع توزيع الملفات/المجلدات المقترحة:

└─ MyCompany.ProjectName  
   ├─ ProjectName.API                  (Presentation Layer)  
   │   ├─ Controllers                  (Controllers/Endpoints)  
   │   │   ├─ WeatherForecastController.cs  
   │   │   ├─ UsersController.cs  
   │   │   └─ …  
   │   ├─ DTOs                         (Data Transfer Objects) [اختياري إذا أردت فصلها]  
   │   │   ├─ UserDTO.cs  
   │   │   └─ …  
   │   ├─ Program.cs                   (نقطة الدخول الرئيسية .NET 6+)  
   │   ├─ Startup.cs or similar        (في .NET 5 ومادون أو إذا أردت فصل الإعدادات)  
   │   ├─ appsettings.json             (إعدادات التطبيق)  
   │   ├─ …  
   │   └─ ProjectName.API.csproj  
   ├─ ProjectName.Core                 (Business Logic/Domain Layer)  
   │   ├─ Entities                     (نماذج الدومين أو الكيانات)  
   │   │   ├─ User.cs  
   │   │   ├─ WeatherForecast.cs  
   │   │   └─ …  
   │   ├─ Interfaces                   (واجهات الخدمات أو الريبو)  
   │   │   ├─ IUserService.cs  
   │   │   ├─ IWeatherForecastService.cs  
   │   │   ├─ IUserRepository.cs  
   │   │   └─ IGenericRepository.cs  
   │   ├─ Services                     (الخدمات أو منطق الأعمال)  
   │   │   ├─ UserService.cs  
   │   │   ├─ WeatherForecastService.cs  
   │   │   └─ …  
   │   └─ ProjectName.Core.csproj  
   ├─ ProjectName.Infrastructure       (Data Access/Infrastructure Layer)  
   │   ├─ Data                         (عناصر الـ EF Core مثلاً أو أي ORM)  
   │   │   ├─ AppDbContext.cs  
   │   │   └─ DbInitializers.cs  
   │   ├─ Repositories                 (تطبيق interfaces من Core)  
   │   │   ├─ UserRepository.cs  
   │   │   ├─ WeatherForecastRepository.cs  
   │   │   └─ GenericRepository.cs  
   │   ├─ Services                     (خدمات مرتبطة بالنشر، الـ Logging أو أي تواصل ببنية تحتية أخرى)  
   │   │   └─ SmtpEmailSender.cs  
   │   └─ ProjectName.Infrastructure.csproj  
   ├─ ProjectName.Tests                (اختياري … مكان لاختبارات الوحدة/التكامل)  
   │   ├─ ProjectName.API.Tests        (اختبارات API)  
   │   │   ├─ UsersControllerTests.cs  
   │   │   └─ …  
   │   ├─ ProjectName.Core.Tests       (اختبارات للوحدات في الـ Business Logic)  
   │   │   ├─ UserServiceTests.cs  
   │   │   └─ …  
   │   ├─ ProjectName.Infrastructure.Tests (اختبارات للوصول إلى البيانات وغير ذلك)  
   │   └─ …  
   └─ README.md (الوصف والتوثيق … اختياري)

في هذا المثال: • ProjectName.API: هو مشروع الـ ASP.NET Core الذي يستقبل الطلبات ويعيد الاستجابات. يحتوي على الـ Controllers وملفات الإعدادات (appsettings، Program، إلخ.)
• ProjectName.Core: يمثل الطبقة المسؤولة عن الدومين (Entities) والواجهات (Interfaces) والخدمات (Services/Business Logic) وكل ما يتعلق بالمنطق الخاص بالتطبيق.
• ProjectName.Infrastructure: يحتوي على تفاصيل الـ Repositories والتواصل مع قواعد البيانات وملفات السيرفيس أو الـ Classes التي تقدم خدمات خاصة بالبنية التحتية (مثل إرسال بريد، تسجيل Logging، إلخ.).
• ProjectName.Tests: قد تشارك اختبارات الوحدة/التكامل إن أحببت فصل الاختبارات عن المشروع الرئيسي.

بعض النقاط الإضافية: • يمكن دمج الطبقات في مشروعين فقط (مثلاً دمج Core وInfrastructure معاً تحت اسم Application) في حال كان المشروع صغيراً.
• إن كنت تتبع نهج Domain-Driven Design (DDD) فقد ترى طبقة Domain وطبقة Application وطبقة Infrastructure كل على حدة.
• يمكن وجود أي عدد إضافي من المجلدات/المشاريع تبعاً لحجم المشروع وتعقيداته (مثل فصل لوحة الإدارة Admin عن الـ API أو فصل مشاريع الـ Microservices).

ملخص: 4) ضع الـ Controllers في طبقة العرض (API).
5) ضع الكيانات (Entities) والواجهات (Interfaces) والخدمات (Services) في طبقة الأعمال.
6) ضع أكواد التواصل مع قاعدة البيانات (Repositories، DbContext) في البنية التحتية.
7) تأكد من حقن الـ Repositories والخدمات في الـ Controllers عبر الـ Dependency Injection.

هذه الهيكلة تساعدك على فصل الاهتمامات (Separation of Concerns) وجعل المشروع قابلاً للتوسع والصيانة بطريقة واضحة.