# The Clean Architecture

গত কয়েক বছরে আমরা system architecture নিয়ে অনেক ধরনের ideas দেখেছি। এর মধ্যে আছে:

* **Hexagonal Architecture** (যাকে Ports and Adapters ও বলা হয়) — Alistair Cockburn এর দেওয়া, যেটা Steve Freeman এবং Nat Pryce তাদের দুর্দান্ত বই *Growing Object Oriented Software* এ গ্রহণ করেছেন
    
* **Onion Architecture** — Jeffrey Palermo এর দেওয়া
    
* **Screaming Architecture** — গত বছর আমার একটা blog থেকে
    
* **DCI** — James Coplien এবং Trygve Reenskaug এর দেওয়া
    
* **BCE** — Ivar Jacobson তার বই *Object Oriented Software Engineering: A Use-Case Driven Approach* থেকে
    

যদিও এই architectures গুলোর details একটু আলাদা, তবুও এরা খুবই similar। এদের সবার **একই উদ্দেশ্য**, আর সেটা হলো **separation of concerns**। এরা সবাই software কে **layers এ ভাগ করে** এই separation achieve করে। প্রতিটাতে অন্তত একটা layer আছে business rules এর জন্য, আর আরেকটা আছে interfaces এর জন্য।

এই architectures গুলো এমন systems তৈরি করে যেগুলো:

**✅ Framework থেকে Independent**  
Architecture টা কোনো feature-heavy library এর উপর depend করে না। এর ফলে তুমি এসব frameworks কে **tools হিসেবে** use করতে পারো, বরং তোমার system কে তাদের সীমিত constraints এ আটকে ফেলতে হয় না।

**✅ Testable**  
Business rules গুলো UI, Database, Web Server বা অন্য কোনো external element ছাড়াই test করা যায়।

**✅ UI থেকে Independent**  
UI সহজেই change করা যায়, system এর বাকি অংশ change না করেই। যেমন একটা Web UI কে console UI দিয়ে replace করা যেতে পারে, business rules কে change না করেই।

**✅ Database থেকে Independent**  
তুমি Oracle বা SQL Server কে swap out করে Mongo, BigTable, CouchDB বা অন্য কিছু use করতে পারো। তোমার business rules database এর সাথে bound নয়।

**✅ যেকোনো external agency থেকে Independent**  
আসলে তোমার business rules বাইরের দুনিয়া সম্পর্কে কিছুই জানে না।

এই article এর শুরুতে যে diagram আছে, সেটা এই সব architectures কে একটা **single actionable idea** তে integrate করার চেষ্টা।

---

## ⚖️ The Dependency Rule

Concentric circles গুলো software এর বিভিন্ন areas কে represent করে। সাধারণত, যত ভিতরে যাবে, software তত high-level হয়ে যায়। বাইরের circles গুলো **mechanisms**। ভিতরের circles গুলো **policies**।

যে মূল নিয়মটা এই architecture কে কাজ করায়, সেটা হলো **The Dependency Rule**। এই rule বলে যে **source code dependencies শুধুমাত্র ভিতরের দিকে point করতে পারবে**।

একটা inner circle এর কিছু outer circle সম্পর্কে কিছুই জানতে পারবে না। বিশেষত, outer circle এ declare করা কোনো কিছুর নাম inner circle এর code এ mention করা যাবে না। এর মধ্যে আছে — functions, classes, variables বা অন্য যেকোনো named software entity।

একইভাবে, outer circle এ যেসব data formats use হয়, সেগুলো inner circle এ use করা উচিত নয়, বিশেষ করে যদি সেই formats কোনো framework থেকে generate হয়ে থাকে। আমরা চাই না যে outer circle এর কিছু inner circles কে impact করুক।

---

## 🔷 Entities

**Entities** হলো Enterprise-wide business rules এর encapsulation। একটা entity হতে পারে methods সহ একটা object, অথবা হতে পারে data structures আর functions এর একটা set। এটা কোনো ব্যাপার না — যতক্ষণ পর্যন্ত এই entities enterprise এর বিভিন্ন applications এ use করা যায়।

যদি তোমার কোনো enterprise না থাকে, আর তুমি শুধু একটা single application লিখছো, তাহলে এই entities হলো application এর **business objects**। এরা সবচেয়ে general এবং high-level rules encapsulate করে। External কিছু change হলে এদের change হওয়ার সম্ভাবনা সবচেয়ে কম।

যেমন, তুমি expect করবে না যে page navigation বা security এর কোনো change এই objects কে affect করবে। কোনো particular application এর operational change entity layer কে affect করবে না।

---

## 🔷 Use Cases

এই layer এর software এ থাকে **application-specific business rules**। এটা system এর সব use cases কে encapsulate এবং implement করে। এই use cases, entities এর দিকে এবং থেকে data এর flow orchestrate করে, এবং সেই entities দের direct করে তাদের enterprise-wide business rules use করতে, যাতে use case এর goals achieve করা যায়।

আমরা expect করি না যে এই layer এর changes entities কে affect করবে। আমরা এটাও expect করি না যে এই layer টা externalities যেমন database, UI বা common frameworks এর changes দ্বারা affected হবে। এই layer এসব concerns থেকে isolated।

তবে আমরা expect করি যে application এর operation এর changes use-cases কে affect করবে এবং তাই এই layer এর software কেও। যদি কোনো use-case এর details change হয়, তাহলে এই layer এর কিছু code অবশ্যই affected হবে।

---

## 🔷 Interface Adapters

এই layer এর software হলো **adapters এর একটা set**, যেগুলো data কে convert করে — use cases এবং entities এর জন্য সবচেয়ে convenient format থেকে, কোনো external agency যেমন Database বা Web এর জন্য সবচেয়ে convenient format এ।

যেমন এই layer এই সম্পূর্ণভাবে একটা GUI এর **MVC architecture** থাকবে। Presenters, Views এবং Controllers সব এখানে belong করে। Models সম্ভবত শুধু data structures যেগুলো controllers থেকে use cases এ pass হয়, এবং তারপর use cases থেকে presenters এবং views এ ফিরে আসে।

একইভাবে, এই layer এ data convert হয় — entities এবং use cases এর জন্য সবচেয়ে convenient form থেকে, যেকোনো persistence framework এর জন্য সবচেয়ে convenient form এ। যেমন Database। এই circle এর ভিতরের কোনো code database সম্পর্কে কিছুই জানবে না।

যদি database টা SQL database হয়, তাহলে সব SQL এই layer এই restricted থাকবে, এবং বিশেষভাবে এই layer এর সেই parts এ যেগুলোর database এর সাথে সম্পর্ক আছে।

এছাড়া এই layer এ আরো যেকোনো adapter থাকে যেটা data কে কোনো external form থেকে convert করে, যেমন কোনো external service থেকে, use cases এবং entities এর internal form এ।

---

## 🔷 Frameworks and Drivers

সবচেয়ে বাইরের layer টা সাধারণত frameworks এবং tools নিয়ে তৈরি, যেমন Database, Web Framework ইত্যাদি। সাধারণত তুমি এই layer এ বেশি code লিখো না — শুধু glue code যেটা পরের circle এর সাথে communicate করে।

এই layer এ সব **details** থাকে। Web একটা detail। Database একটা detail। আমরা এই জিনিসগুলো বাইরে রাখি যেখানে তারা খুব কম harm করতে পারে।

---

## 🔷 শুধু চারটা Circles?

না, circles গুলো schematic। তুমি হয়তো দেখবে যে তোমার এই চারটার চেয়ে বেশি দরকার। এমন কোনো rule নেই যে তোমাকে সবসময় শুধু এই চারটা রাখতে হবে।

তবে, **The Dependency Rule সবসময় apply হয়**। Source code dependencies সবসময় inwards point করে। যত inwards যাবে, abstraction এর level তত বাড়ে। সবচেয়ে বাইরের circle হলো low-level concrete detail। যত inwards যাবে, software তত abstract হয়, এবং higher-level policies encapsulate করে। সবচেয়ে inner circle টা সবচেয়ে general।

---

## 🔄 Boundaries cross করা

Diagram এর নিচের ডান দিকে একটা example আছে কীভাবে আমরা circle boundaries cross করি। এটা দেখাচ্ছে Controllers এবং Presenters পরের layer এর Use Cases এর সাথে communicate করছে।

**Control এর flow লক্ষ্য করো।** এটা controller এ শুরু হয়, use case এর মধ্য দিয়ে যায়, এবং তারপর presenter এ গিয়ে execute হয়।

**Source code dependencies ও লক্ষ্য করো।** প্রতিটা inwards point করছে use cases এর দিকে।

আমরা সাধারণত এই apparent contradiction কে **Dependency Inversion Principle** use করে resolve করি। যেমন Java এর মতো language এ, আমরা interfaces এবং inheritance relationships এমনভাবে arrange করি যাতে source code dependencies, control এর flow এর opposite direction এ থাকে — ঠিক boundary cross করার জায়গায়।

যেমন, ধরো use case একটা presenter কে call করতে চায়। কিন্তু এই call টা direct হতে পারবে না কারণ সেটা **The Dependency Rule** violate করবে: outer circle এর কোনো নাম inner circle mention করতে পারবে না।

তাই আমরা use case কে একটা **interface** call করাই (এখানে দেখানো হয়েছে Use Case Output Port হিসেবে) inner circle এ, এবং outer circle এর presenter সেটা implement করে।

একই technique use করা হয় architectures এর সব boundaries cross করতে। আমরা **dynamic polymorphism** এর সুবিধা নিই source code dependencies তৈরি করতে যেগুলো control এর flow এর opposite direction এ — যাতে আমরা **The Dependency Rule** মানতে পারি, control এর flow যে দিকেই যাক না কেন।

---

## 📦 Boundaries cross করার সময় কী data যায়

সাধারণত boundaries cross করার সময় যে data যায়, সেটা **simple data structures**। তুমি চাইলে basic structs বা simple Data Transfer objects use করতে পারো। অথবা data হতে পারে function calls এর arguments। অথবা তুমি এটাকে hashmap এ pack করতে পারো, বা একটা object তৈরি করতে পারো।

**Important বিষয় হলো** — isolated, simple data structures boundaries cross করে। আমরা চাই না যে Entities বা Database rows pass করা হোক, কারণ সেটা cheating হবে। আমরা চাই না যে data structures এর এমন কোনো dependency থাকুক যেটা **The Dependency Rule** violate করে।

যেমন, অনেক database frameworks query এর response এ একটা convenient data format return করে। আমরা এটাকে RowStructure বলতে পারি। আমরা চাই না যে এই row structure টা inwards একটা boundary cross করুক। সেটা **The Dependency Rule** violate করবে কারণ সেটা একটা inner circle কে outer circle সম্পর্কে কিছু জানতে force করবে।

তাই যখন আমরা data একটা boundary cross করাই, এটা সবসময় সেই form এ থাকে যেটা **inner circle এর জন্য সবচেয়ে convenient**।

---

## 🎯 Conclusion

এই simple rules মানা কঠিন কিছু না, এবং এটা ভবিষ্যতে তোমাকে অনেক headaches থেকে বাঁচাবে।

Software কে layers এ ভাগ করে, এবং **The Dependency Rule** মেনে চলে, তুমি এমন একটা system তৈরি করবে যেটা **intrinsically testable**, এবং এর সাথে আসা সব benefits পাবে।

যখন system এর কোনো external parts obsolete হয়ে যায়, যেমন database বা web framework, তুমি সেই obsolete elements গুলো minimum fuss এ replace করতে পারবে।

Credit : The Clean Code Blog(Robert C. Martin)
