Architecture and Design Principles
22. What is software architecture, and how does it differ from software design?
Software Architecture হলো একটি system এর high-level structure — অর্থাৎ system টি কোন কোন major component/module নিয়ে গঠিত, সেগুলো একে অপরের সাথে কীভাবে interact করে, এবং overall system কীভাবে সংগঠিত। এটি মূলত "big picture" decisions নিয়ে কাজ করে, যা পরবর্তীতে পরিবর্তন করা কঠিন এবং costly।
Software Design এর তুলনায় Architecture বেশি abstract এবং strategic, যেখানে Design বেশি concrete এবং tactical।
| বিষয় | Architecture | Design |
|---|---|---|
| Level | High-level, system-wide | Component/module-level, detailed |
| Focus | Structure, component interaction, technology choice | Class structure, algorithm, data structure, internal logic |
| Decision Type | দীর্ঘমেয়াদী, পরিবর্তন করা কঠিন (যেমন monolith vs microservices) | তুলনামূলক flexible, পরিবর্তন করা সহজ |
| উদাহরণ | "System টি microservices architecture ব্যবহার করবে, message queue দিয়ে communicate করবে" | "OrderService ক্লাসে কোন কোন method থাকবে, কীভাবে data validate হবে" |
| কে করে | সাধারণত Software/Solution Architect | Developer/Senior Developer |
সহজভাবে বলতে গেলে, Architecture ঠিক করে "বাড়িটার overall structure কেমন হবে — কয়তলা, কোথায় pillar থাকবে" আর Design ঠিক করে "প্রতিটি রুমের ভেতরের layout, furniture কীভাবে সাজানো হবে"।
How does architecture address cross-cutting concerns like scalability and security?
Cross-cutting concerns হলো এমন সব বিষয়, যা system এর একটি নির্দিষ্ট module এ সীমাবদ্ধ না থেকে পুরো system জুড়ে ছড়িয়ে থাকে — যেমন scalability, security, logging, performance।
Scalability এর ক্ষেত্রে:
- Architecture level এ horizontal scaling সম্ভব কিনা তা ঠিক করা হয় (যেমন load balancer ব্যবহার করে একাধিক server এ traffic distribute করা)
- Stateless service design বেছে নেওয়া, যাতে যেকোনো সময় নতুন instance যোগ করা যায়
- Caching layer (Redis, Memcached) এবং database sharding/replication strategy আগে থেকে architecture তে অন্তর্ভুক্ত করা
- Microservices এর মতো architecture বেছে নেওয়া, যাতে শুধু যে service এ বেশি load আছে সেটাই আলাদাভাবে scale করা যায়
Security এর ক্ষেত্রে:
- Architecture level এ authentication/authorization layer (যেমন API Gateway এ centralized auth) ডিজাইন করা হয়
- Network segmentation — sensitive data বা service কে আলাদা secure zone এ রাখা
- Encryption strategy (data at rest এবং in transit) architecture এর অংশ হিসেবে ঠিক করা
- Defense in depth — একাধিক স্তরে security control রাখা (firewall, API gateway, application-level validation)
এই cross-cutting concern গুলো যদি শুরুতেই architecture এ বিবেচনা করা না হয়, তাহলে পরবর্তীতে সেগুলো প্রতিটি module এ আলাদাভাবে retrofit করা অনেক costly এবং error-prone হয়ে যায় — তাই এগুলো architecture design এর একদম প্রথম দিকের গুরুত্বপূর্ণ বিবেচ্য বিষয়।
23. What is the difference between high-level design (HLD) and low-level design (LLD)?
| বিষয় | HLD | LLD |
|---|---|---|
| Level | System-wide, architectural view | Module/component-level, detailed |
| Audience | Architect, Project Manager, senior stakeholder | Developer, যারা actual code লিখবেন |
| Content | Overall system architecture, major module, data flow, technology stack | প্রতিটি module এর internal logic, class diagram, algorithm, database schema detail |
| Abstraction | বেশি abstract | বেশি concrete এবং implementation-oriented |
| তৈরি হয় কখন | Requirement analysis এর পর, coding শুরুর আগে | HLD এর পর, coding শুরুর ঠিক আগে |
What artifacts are typically produced at each stage?
HLD Stage এর Artifacts:
- System Architecture Diagram — major components এবং তাদের interaction
- Data Flow Diagram (DFD) — data কীভাবে system এর মধ্যে দিয়ে flow করবে
- Technology Stack Document — কোন programming language, framework, database ব্যবহার হবে
- High-level Database Schema (ER Diagram)
- Third-party Integration Overview — external system/API এর সাথে কীভাবে যুক্ত হবে
- Deployment Architecture — server, cloud infrastructure এর overview
LLD Stage এর Artifacts:
- Class Diagrams — প্রতিটি class এর attribute, method, এবং relationship
- Sequence Diagrams — নির্দিষ্ট operation এ objects কীভাবে একে অপরের সাথে interact করে তার step-by-step flow
- Detailed Database Schema — table structure, column type, constraints, indexes সহ
- API Specification — প্রতিটি endpoint এর request/response format, parameters
- Pseudocode বা Algorithm Design — জটিল business logic এর জন্য
- State Diagrams (প্রয়োজনে) — কোনো object এর বিভিন্ন state এবং transition দেখানোর জন্য
24. What is the difference between a monolithic architecture and a microservices architecture?
Monolithic Architecture: পুরো application টি একটি single, unified codebase এবং deployment unit হিসেবে তৈরি হয়। সব feature/module (UI, business logic, database access) একসাথে একটি process এ চলে এবং একসাথেই deploy হয়।
Microservices Architecture: Application টিকে ছোট ছোট, independent service এ ভাগ করা হয়, যে খানে প্রতিটি service একটি নির্দিষ্ট business capability handle করে (যেমন: User Service, Order Service, Payment Service)। প্রতিটি service আলাদাভাবে develop, deploy, এবং scale করা যায়, এবং সাধারণত API (REST, gRPC) বা message queue এর মাধ্যমে একে অপরের সাথে communicate করে।
What are the trade-offs of microservices in terms of complexity, deployment, and team organization?
Complexity এর দিক থেকে:
- সুবিধা: প্রতিটি service ছোট এবং individually বোঝা সহজ
- অসুবিধা: Overall system এর complexity বৃদ্ধি পায় — distributed system এর সব challenge (network latency, service discovery, data consistency across services) সামলাতে হয়; debugging এবং monitoring কঠিন হয়ে যায় কারণ একটি request একাধিক service এর মধ্য দিয়ে যায়
Deployment এর দিক থেকে:
- সুবিধা: প্রতিট ি service independently deploy করা যায় — একটি service এ change করলে পুরো system redeploy করতে হয় না, যা faster release cycle সম্ভব করে
- অসুবিধা: Deployment infrastructure জটিল হয়ে যায় — container orchestration (Kubernetes), service mesh, CI/CD pipeline প্রতিটি service এর জন্য আলাদা setup দরকার হয়
Team Organization এর দিক থেকে:
- সুবিধা: ছোট ছোট team প্রতিটি service এর সম্পূর্ণ ownership নিতে পারে (Conway's Law অনুযায়ী), যা parallel development এবং autonomy বাড়ায়
- অসুবিধা: Team এর মধ্যে coordination overhead বাড়ে, বিশেষত যখন একাধিক service এর মধ্যে dependency থাকে; প্রতিটি team কে DevOps skill থাকা প্রয়োজন হয়
Monolith এর তুলনায় Microservices এ সাধারণত higher operational cost, বেশি infrastructure investment, এবং বেশি skilled team দরকার হয় — তাই ছোট team বা startup এর জন্য শুরুতেই microservices যাওয়া প্রায়ই "premature optimization" হিসেবে বিবেচিত হয়।
What is a "modular monolith," and how does it sit between the two extremes?
Modular Monolith হলো একটি architecture approach, যেখানে application টি single deployment unit হিসেবেই থাকে (Monolith এর মতো), কিন্তু কোডবেসের ভেতরে clear, well-defined module boundary বজায় রাখা হয় (Microservices এর modularity এর মতো)। প্রতিটি module এর নিজস্ব business logic এবং data থাকে, এবং module গুলোর মধ্যে strict interface/contract মেনে communicate করা হয় — যদিও সব module একই process এ চলে এবং একসাথে deploy হয়।
Modular Monolith কেন মাঝামাঝি অবস্থান করে:
- Monolith এর সুবিধা বজায় রাখে: Simple deployment, কম operational overhead, কোনো network latency নেই module-to-module communication এ, transaction management সহজ
- Microservices এর সুবিধাও কিছুটা পায়: Clear module boundary থাকার কারণে code maintainability ভালো থাকে, এবং team রা independently নিজেদের module এ কাজ করতে পারেন
- ভবিষ্যতে প্রয়োজন হলে, well-separated module গুলোকে তুলনামূলক সহজে আলা দা microservice এ migrate করা যায়, কারণ boundary গুলো আগে থেকেই স্পষ্ট থাকে
এই কারণে অনেক architect Modular Monolith দিয়ে শুরু করার পরামর্শ দেন, বিশেষত নতুন বা medium-size project এর জন্য, এবং প্রয়োজন অনুযায়ী (scale বাড়লে) পরবর্তীতে নির্দিষ্ট module গুলোকে microservice এ ভেঙে নেওয়ার কথা বলেন — এটাকে অনেক সময় "Monolith First" approach বলা হয়।
25. What is layered (n-tier) architecture, and what are its common layers?
Layered Architecture হলো একটি architectural pattern, যেখানে system কে বিভিন্ন horizontal layer এ ভাগ করা হয়, এবং প্রতিটি layer এর একটি নির্দিষ্ট responsibility থাকে। প্রতিটি layer শুধুমাত্র তার ঠিক নিচের layer এর সাথে interact করে (strict layering এ), যা separation of concerns নিশ্চিত করে।
Common Layers:
- Presentation Layer (UI Layer) — user এর সাথে সরাসরি interact করে; UI, forms, views এখানে থাকে
- Business Logic Layer (Application/Service Layer) — মূল business rule এবং logic এখানে implement হয়
- Data Access Layer (Persistence Layer) — database এর সাথে communicate করে, data retrieve/store করে
- Database Layer — actual data storage
What is the difference between a 3-tier architecture and an n-tier architecture?
3-Tier Architecture হলো layered architecture এর সবচেয়ে সাধারণ এবং classic রূপ, যেখানে ঠিক তিনটি layer থাকে:
- Presentation Tier — client-side UI (browser, mobile app)
- Application/Logic Tier — server-side business logic (application server)
- Data Tier — database server
N-Tier Architecture হলো একটি generalized concept, যেখানে "N" যেকোনো সংখ্যক layer কে বোঝাতে পারে — অর্থাৎ 3-Tier ও আসলে N-Tier এরই একটি specific উদ াহরণ (যেখানে N=3)। প্রয়োজন অনুযায়ী আরও বেশি layer যোগ করা যায়, যেমন:
- Presentation Layer
- API Gateway Layer
- Business Logic Layer
- Service Layer (আলাদা microservice বা external service call handle করার জন্য)
- Data Access Layer
- Database Layer
- Caching Layer
মূল পার্থক্য: 3-Tier একটি নির্দিষ্ট, fixed সংখ্যক (৩টি) layer এর architecture বোঝায়, যেখানে N-Tier একটি flexible, generic term, যেখানে system এর complexity অনুযায়ী প্রয়োজনমতো যত খুশি layer যোগ করা যায় (৪, ৫, বা তার বেশি)। বড়, complex enterprise system এ প্রায়ই আরও বেশি layer (N-Tier) ব্যবহার করা হয়, যাতে প্রতিটি concern (যেমন caching, security, external integration) এর জন্য আলাদা, dedicated layer থাকে — যা better separation of concerns এবং maintainability প্রদান করে।
26. What is MVC (Model-View-Controller), and how does it separate concerns?
MVC হলো একটি architectural pattern, যা একটি application কে তিনটি আলাদা, interconnected component এ ভাগ করে:
- Model — application এর data এবং business logic handle করে। Database এর সাথে interact করে, data validate করে, এবং business rule implement করে। এটি View বা Controller সম্পর্কে কিছুই জানে না
- View — presentation/UI layer, যা user কে data দেখায়। এটি শুধু data render করে, কোনো business logic এখানে থাকে না
- Controller — User এর input গ্রহণ করে (যেমন button click, form submit), Model কে প্রয়োজনীয় data update করতে বলে, এবং তারপর সঠিক View render করার নির্দেশ দেয়। এটি Model এবং View এর মধ্যে middleman হিসেবে কাজ করে
Separation of Concerns কীভাবে হয়:
- Data/domain, presentation এবং request/control responsibility আলাদা রাখায় change impact কমানো যায়। বাস্তবে shared contract ও framework dependency থাকায় একটি অংশের change অন্যটিকে প্রভাবিত করতেই পারে।
- একাধিক developer parallel-ভাবে কাজ করতে পারেন (একজন UI নিয়ে, একজন business logic নিয়ে)
- একই Model এর জন্য একাধিক View তৈরি করা সহজ হয় (যেমন web view, mobile view)
- Testing সহজ হয়, কারণ business logic (Model) কে UI থেকে আলাদাভাবে test করা যায়
How does MVC differ from MVVM and MVP?
| বিষয় | MVC | MVP (Model-View-Presenter) | MVVM (Model-View-ViewModel) |
|---|---|---|---|
| Middle Component | Controller | Presenter | ViewModel |
| View এর Role | তুলনামূলক active — user input Controller এ পাঠায় | সম্পূর্ণ passive — সব logic Presenter এ থাকে | Passive, কিন্তু data binding এর মাধ্যমে ViewModel এর সাথে automatically sync থাকে |
| View-Middle Communication | Controller View select করে render করার জন্য বলে (এক-মুখী নির্দেশ) | Presenter এবং View এর মধ্যে সরাসরি reference থাকে (interface এর মাধ্যমে) | View এবং ViewModel এর মধ্যে data binding (two-way binding সম্ভব), সরাসরি reference লাগে না |
| Testability | Framework ও controller boundary অনুযায়ী | Presenter interface isolate করলে ভালো | ViewModel UI framework থেকে আলাদা থাকলে ভালো; data-binding code-ও test দরকার |
| সাধারণ ব্যবহার | Web application (Ruby on Rails, ASP.NET MVC, Django) | Android (পুরনো ধরনে), Desktop application | WPF, Angular, এবং modern frontend framework যেখানে data binding সমর্থিত |
মূল পার্থক্য সংক্ষেপে: MVC তে Controller View নির্বাচন করে, MVP তে Presenter এবং View interface এর মাধ্যমে সরাসরি যোগাযোগ করে, আর MVVM তে ViewModel এবং View এর মধ্যে automatic data binding থাকে, যা explicit update code লেখার প্রয়োজন কমিয়ে দেয়।
27. What is the difference between synchronous and asynchronous communication between services?
Synchronous Communication: এক service যখন অন্য service কে call করে, তখন caller অপেক্ষা করে (blocked থাকে) যতক্ষণ না response পাওয়া যায়। যেমন সাধারণ REST API call (HTTP request-response)।
- Response সাথে সাথেই পাওয়া যায়
- Implementation সহজ, বোঝা সহজ
- কিন্তু caller service, callee service এর উপর tightly dependent হয়ে যায় — callee slow হলে বা down থাকলে caller ও প্রভাবিত হয়
Asynchronous Communication: Caller request পাঠিয়ে response এর জন্য অপেক্ষা করে না — বরং কাজ চালিয়ে যায়, এবং response পরে (যদি প্রয়োজন হয়) কোনো callback, event, বা message queue এর মাধ্যমে পাওয়া যায়। যেমন message queue (RabbitMQ, Kafka) ব্যবহার করে communication।
- Caller এবং callee একে অপরের থেকে decoupled থাকে
- System এর resilience এবং scalability বৃদ্ধি পায় — একটি service down থাকলেও message queue তে জমা থেকে যায়, পরে process হয়
- কিন্তু complexity বৃদ্ধি পায় — eventual consistency, error handling, এবং debugging কঠিন হয়ে যায়
What is event-driven architecture, and how does it relate to asynchronous communication?
Event-Driven Architecture (EDA) হলো একটি architectural pattern, যেখানে system এর বিভিন্ন component events তৈরি (produce/publish) এবং সেগুলোতে প্রতিক্রিয়া (consume/subscribe) জানানোর মাধ্যমে একে অপরের সাথে communicate করে। কোনো service সরাসরি অন্য service কে call করে না — বরং একটি event (যেমন "OrderPlaced", "PaymentCompleted") publish করে, এবং যেসব service সেই event এ interested (subscribed), তারা independently সেটা handle করে।
Asynchronous Communication এর সাথে সম্পর্ক:
- Event-Driven Architecture মূলত asynchronous communication এর একটি বাস্তবায়ন (implementation) — Event publish করার পর producer আর অপেক্ষা করে না, consumer রা নিজেদের সময়মতো event process করে
- এটি সাধারণত Message Broker/Event Bus (Kafka, RabbitMQ, AWS SNS/SQS) ব্যবহার করে বাস্তবায়িত হয়
- Producer এবং Consumer সরাসরি runtime reference নাও রাখতে পারে, কিন্তু event schema, semantics, ordering এবং delivery contract-এর মাধ্যমে এখনও coupled থাকে। Coupling কমে, শূন্য হয় না।
- একটি event এ একাধিক consumer subscribe থাকতে পারে, যা scalability এবং extensibility বাড়ায় (নতুন consumer যোগ করলে producer এ কোনো change লাগে না)
28. What is the difference between tightly coupled and loosely coupled systems?
Tightly Coupled System: এখানে একটি component/module সরাসরি এবং গভীরভাবে অন্য component এর উপর নির্ভরশীল — এদের implementation details একে অপরের সাথে জড়িয়ে থাকে। একটি অংশে change করলে অন্য অংশেও change করতে হয়।
Loosely Coupled System: এখানে component গুলো well-defined contract দিয়ে যুক্ত থাকে এবং internal implementation কম জানে। Contract syntactically unchanged থাকলেও behavior, latency বা failure semantics বদলালে consumer প্রভাবিত হতে পারে—compatibility test প্রয়োজন।
| বিষয় | Tightly Coupled | Loosely Coupled |
|---|---|---|
| Dependency | সরাসরি, concrete class/implementation এর উপর নির্ভর | Interface/abstraction এর উপর নির্ভর |
| Change Impact | একটি জায়গায় change করলে অনেক জায়গায় প্রভাব পড়ে | Change এর impact সীমিত থাকে |
| Testability | কঠিন — component গুলোকে আলাদা করে test করা কঠিন | সহজ — mock/stub ব্যবহার করে individually test করা যায় |
| Flexibility | কম — নতুন implementation যোগ করা কঠিন | বেশি — সহজেই একটি implementation পরিবর্তন করা যায় |
| উদাহরণ | একটি class সরাসরি new DatabaseConnection() তৈরি করছে তার ভেতরেই | একটি class একটি Database interface এর উপর নির্ভর করছে, actual implementation বাইরে থেকে দেওয়া হচ্ছে |
How does dependency injection help reduce coupling?
Dependency Injection (DI) হলো একটি design pattern, যেখানে একটি class তার প্রয়োজনীয় dependency নিজে তৈরি না করে, বরং সেটা বাইরে থেকে (constructor, method, বা property এর মাধ্যমে) সরবরাহ (inject) করা হয়।
কীভাবে Coupling কমায়:
- Class টি একটি concrete implementation এর বদলে interface/abstraction এর উপর নির্ভর করে — অর্থাৎ class জানে না তার dependency আসলে কোন specific implementation, শুধু জানে সেটা কী কী কাজ করতে পারে (interface অনুযায়ী)
- এতে runtime এ সহজেই implementation পরিবর্তন করা যায় — যেমন production এ real database ব্যবহার করা, আর testing এ একটি mock/fake database ব্যবহার করা, কোনো class এর code পরিবর্তন না করেই
- Unit testing সহজ হয় — কারণ dependency mock করে inject করা যায়, real dependency (যেমন actual database, network call) ছাড়াই test করা সম্ভব হয়
- Component গুলো একে অপরের internal implementation সম্পর্কে অজ্ঞ থাকে, শুধু interface/contract জানে, যা loose coupling নিশ্চিত করে
- Single Responsibility বজায় থাকে — একটি class শুধু তার নিজের কাজে মনোযোগ দেয়, dependency তৈরি বা manage করার দায়িত্ব তার উপর থাকে না
উদাহরণ:
Code ExampleJavaClick to view details
// Tightly Coupled (Dependency নিজে তৈরি করছে)
class OrderService {
private PaymentGateway gateway = new StripeGateway(); // hardcoded
}
// Loosely Coupled (DI ব্যবহার করে)
class OrderService {
private PaymentGateway gateway;
OrderService(PaymentGateway gateway) { // বাইরে থেকে inject করা হচ্ছে
this.gateway = gateway;
}
}
দ্বিতীয় ক্ষেত্রে, OrderService কে StripeGateway, PayPalGateway, বা testing এর জন্য MockGateway — যেকোনো কিছু দিয়েই কাজ করানো যাবে, কোনো code change ছাড়াই।
29. What is "separation of concerns," and why is it a foundational design principle?
Separation of Concerns (SoC) হলো একটি design principle, যেখানে একটি system কে এমনভাবে ভাগ করা হয় যাতে প্রতিটি অংশ (module/component/class) শুধুমাত্র একটি নির্দিষ্ট, well-defined responsibility বা "concern" নিয়ে কাজ করে, এবং একে অপরের কাজের সাথে যতটা সম্ভব কম জড়িয়ে থাকে।
কেন এটি Foundational:
- Maintainability বৃদ্ধি করে — একটি concern এ change করতে হলে, শুধু সেই সংশ্লিষ্ট অংশটুকু modify করলেই হয়, পুরো system এ change করার প্রয়োজন হয় না
- Reusability বাড়ায় — যেহেতু প্রতিটি অংশ independent, সেটাকে অন্য প্রেক্ষাপটেও পুনরায় ব্যবহার করা যায়
- Testability সহজ করে — প্রতিটি concern কে আলাদাভাবে, isolation এ test করা যায়
- Collaboration সহজ করে — বিভিন্ন developer বা team আলাদা আলাদা concern নিয়ে parallel-ভাবে কাজ করতে পারেন, একে অপরের কাজে বাধা না দিয়ে
- Complexity manage করা সহজ হয় — মানুষের মস্তিষ্ক একসাথে অনেক জটিল বিষয় ধরে রাখতে পারে না; SoC এর মাধ্যমে একটি বড় সমস্যাকে ছোট ছোট, বোধগম্য অংশে ভাগ করা যায়
এই কারণেই SoC কে অনেক অন্যান্য design principle এবং pattern এর (MVC, Layered Architecture, Microservices, SOLID principles) ভিত্তি (foundation) হিসেবে গণ্য করা হয় — এই সব pattern-ই মূলত SoC কে বিভিন্নভাবে বাস্তবায়নের চেষ্টা।
Can you give an example of a design that violates separation of concerns?
Code ExampleJavaClick to view details
class UserController {
public void createUser(String name, String email, String password) {
// Validation logic (এটা Business Logic এর concern)
if (email == null || !email.contains("@")) {
throw new IllegalArgumentException("Invalid email");
}
// Database connection এবং SQL query সরাসরি এখানে (এটা Data Access এর concern)
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db");
String sql = "INSERT INTO users (name, email, password) VALUES ('"
+ name + "', '" + email + "', '" + password + "')";
conn.createStatement().execute(sql);
// Email পাঠানোর logic সরাসরি এখানে (এটা Notification Service এর concern)
SMTPClient client = new SMTPClient("smtp.gmail.com");
client.send(email, "Welcome!", "Thanks for signing up, " + name);
// HTML response তৈরি করা সরাসরি এখানে (এটা Presentation এর concern)
System.out.println("<html><body>User created successfully!</body></html>");
}
}
সমস্যা কী: এই একটি single class/method এ চারটি সম্পূর্ণ ভিন্ন concern (validation, database access, email notification, এবং presentation/response formatting) একসাথে মিশে আছে। এর ফলে:
- Database change করতে হলে (যেমন MySQL থেকে PostgreSQL এ যাওয়া)
UserControllerএর code touch করতে হবে - Email service পরিবর্তন করতে হলেও একই class এ change করতে হবে