Oldingi mavzuda Architecture styles ko‘rgan edik. Endi arxitektor uchun juda muhim amaliy mavzu:
Architecture Decision Records - ADR
Bu mavzu ichida quyidagilar bor: ADR format & lifecycle, trade-off analysis, fitness functions, architecture governance, tech radar.
1. ADR nima?
ADR - Architecture Decision Record
Ya’ni:
Muhim texnik qaror nima uchun qabul qilinganini yozib qo‘yadigan qisqa hujjat.
Masalan:
Nega monolith tanladik?
Nega PostgreSQL ishlatyapmiz?
Nega Kafka emas, RabbitMQ?
Nega REST emas, gRPC?
Nega Redis cache qo‘shildi?
Nega modular monolithdan microservicesga o‘tyapmiz?
Nega Spring Boot tanlandi?
ADR kod emas. Lekin u koddan ham muhim bo‘lishi mumkin, chunki u qarorning sababini saqlaydi.
2. Nega ADR kerak?
Ko‘p loyihalarda shunday bo‘ladi:
Developer: Nega bu yerda Kafka ishlatilgan?
Teamlead: Bilmayman, men kelganimda bor edi.
Arxitektor: Oldin bir sabab bo‘lgan, lekin hech kim eslamaydi.Bu yomon holat.
ADR bo‘lsa, yangi odam kelib o‘qiydi:
ADR-004: Use RabbitMQ for order notifications
Status: Accepted
Date: 2026-03-12
Context:
Order yaratilganda SMS, email, push notification yuborish kerak.
Bu jarayon order yaratishni sekinlashtirmasligi kerak.
Decision:
RabbitMQ ishlatamiz.
Reason:
Routing murakkab emas, latency past, team RabbitMQ bilan ishlagan.
Kafka bu holat uchun ortiqcha complexity beradi.
Consequences:
Notification async bo‘ladi.
Agar RabbitMQ vaqtincha ishlamasa, retry va DLQ kerak.Endi hamma sababni tushunadi.
3. ADR qachon yoziladi?
Har bir kichik qarorga ADR kerak emas.
ADR kerak bo‘ladigan qarorlar
Qaror turi | Misol |
|---|---|
Architecture style | Modular monolith tanlash |
Database tanlash | PostgreSQL vs MongoDB |
Messaging tanlash | Kafka vs RabbitMQ |
API style | REST vs gRPC vs GraphQL |
Security approach | JWT vs Session |
Deployment strategy | Kubernetes vs VM |
Cache strategy | Redis qo‘shish |
Data consistency | SAGA tanlash |
Framework/library | Spring Cloud Gateway ishlatish |
ADR kerak bo‘lmaydigan holatlar
Bular uchun odatda ADR shart emas:
method nomini o‘zgartirish;
bitta class refactor qilish;
kichik bug fix;
oddiy dependency version update;
bitta endpoint path nomi;
UI rangini o‘zgartirish.
Qoida:
Qaror keyingi 6-24 oy davomida sistemaga ta’sir qilsa - ADR yozish kerak.
4. ADR formati
ADR juda katta document bo‘lishi shart emas. 1-2 sahifa yetadi.
Eng oddiy format:
# ADR-001: Use Modular Monolith
## Status
Accepted
## Date
2026-05-20
## Context
Biz e-commerce backend qurmoqdamiz.
Team kichik: 5 developer.
Domain hali tez o‘zgaradi.
Mustaqil deploy hozircha shart emas.
## Decision
Boshida modular monolith architecture tanlaymiz.
## Alternatives Considered
1. Traditional monolith
2. Microservices
3. Modular monolith
## Consequences
Positive:
- Development tezroq bo‘ladi.
- Deployment oddiy.
- Modul chegaralari keyinchalik microservicesga ajratishga yordam beradi.
Negative:
- Hamma modul bitta app sifatida deploy qilinadi.
- Developerlar modul chegarasini buzmasligi uchun code review kerak.
## Review Date
2026-11-205. ADR statuslari
ADR lifecycle’da status muhim.
Status | Ma’nosi |
|---|---|
Proposed | Taklif qilingan, hali qabul qilinmagan |
Accepted | Qabul qilingan qaror |
Rejected | Rad qilingan |
Deprecated | Endi tavsiya qilinmaydi |
Superseded | Yangi ADR bilan almashtirilgan |
Misol
ADR-002: Use MongoDB for Orders
Status: RejectedNega rejected ADR ham saqlanadi?
Chunki 6 oy keyin yana kimdir:
"Orders uchun MongoDB ishlatsak bo‘lmaydimi?"
desa, javob tayyor bo‘ladi:
Bu variant ko‘rib chiqilgan.
Sabablari bilan rad qilingan.Bu team vaqtini tejaydi.
6. ADR lifecycle
ADR hayoti odatda shunday:
Problem paydo bo‘ladi
↓
Variantlar yoziladi
↓
Trade-off tahlil qilinadi
↓
Qaror qabul qilinadi
↓
ADR accepted bo‘ladi
↓
Amalda ishlatiladi
↓
Vaqti-vaqti bilan qayta ko‘riladi
↓
Kerak bo‘lsa deprecated/superseded qilinadi7. Trade-off analysis
Arxitektor qaror qabul qilganda "bu yaxshi, bu yomon" demaydi.
U shunday o‘ylaydi:
Har bir tanlov nimanidir beradi, nimanidir olib qo‘yadi.
Bu trade-off deyiladi.
Misol: Kafka vs RabbitMQ
Mezon | Kafka | RabbitMQ |
|---|---|---|
Throughput | Juda yuqori | O‘rtacha/yaxshi |
Routing | Oddiyroq | Juda kuchli |
Message retention | Kuchli | Asosan queue modeli |
Learning curve | Qiyinroq | Osonroq |
Replay | Juda yaxshi | Tabiiy emas |
Use case | Event streaming | Task queue / routing |
Arxitektor xulosasi:
Agar event streaming, replay, audit kerak bo‘lsa → Kafka.
Agar task queue, notification, routing kerak bo‘lsa → RabbitMQ.Misol ADR
# ADR-005: Use RabbitMQ for Notification Delivery
## Status
Accepted
## Context
Order yaratilganda SMS, Telegram, Push, Email notification yuboriladi.
Har notification turi turli service tomonidan qayta ishlanadi.
Bizga murakkab routing va retry kerak.
Event replay hozircha kerak emas.
## Decision
RabbitMQ ishlatamiz.
## Alternatives Considered
1. Kafka
2. RabbitMQ
3. Direct synchronous HTTP calls
## Trade-offs
RabbitMQ:
+ Routing uchun qulay
+ Team tajribasi bor
+ DLQ va retry oson
- Event replay Kafka kabi kuchli emas
Kafka:
+ High throughput
+ Replay imkoniyati kuchli
- Hozirgi case uchun complexity ortiqcha
HTTP calls:
+ Oddiy
- Order yaratish sekinlashadi
- Notification service yiqilsa order flow ta’sirlanadi
## Consequences
Notification async ishlaydi.
RabbitMQ monitoring va DLQ handling majburiy bo‘ladi.8. Fitness Functions
Fitness function nima?
Architecture’da fitness function - architecture qarori ishlayotganini avtomatik yoki yarim avtomatik tekshiradigan qoida.
Oddiy qilib:
"Biz tanlagan architecture vaqt o‘tib buzilmayaptimi?"
Misol: Modular Monolith
Biz ADR’da shunday qaror qildik:
Order module Product module’ning repositorysini to‘g‘ridan-to‘g‘ri chaqirmasin.
Fitness function:
Order package ichida product.infrastructure package import qilinmasin.Buni test bilan tekshirish mumkin.
Java’da ArchUnit bilan:
@Test
void orderShouldNotAccessProductInfrastructure() {
noClasses()
.that().resideInAPackage("..order..")
.should().accessClassesThat()
.resideInAPackage("..product.infrastructure..")
.check(importedClasses);
}Bu test CI’da yursa, architecture buzilishi build’da ko‘rinadi.
Boshqa fitness function misollari
Architecture qarori | Fitness function |
|---|---|
Controller domain entity qaytarmasin | REST response faqat DTO bo‘lsin |
Service layer repositorysiz ishlamasin | Controller repository chaqirmasin |
Module boundary saqlansin | Cross-module importlar nazorat qilinsin |
API latency 300ms’dan oshmasin | Performance test / metric alert |
Service stateless bo‘lsin | Local file/session ishlatilmasin |
Security majburiy bo‘lsin | Public endpointlar ro‘yxati tekshirilsin |
9. Architecture Governance
Governance nima?
Architecture governance - teamlar architecture qoidalariga amal qilishini boshqarish.
Bu "arxitektor hammani majburlaydi" degani emas.
To‘g‘ri governance:
Qarorlar aniq
Sabablar yozilgan
Qoidalar avtomatlashtirilgan
Istisnolar muhokama qilinadi
Teamlar tushunadiYomon governance
Arxitektor: Bunday qilmang.
Developer: Nega?
Arxitektor: Chunki men shunday dedim.Bu ishlamaydi.
Yaxshi governance
Arxitektor: Biz ADR-003'da module boundary qoidasini qabul qilganmiz.
Sababi: payment logic order ichiga aralashib ketmasligi kerak.
ArchUnit test ham shuni tekshiradi.
Agar exception kerak bo‘lsa, yangi ADR yoki amendment qilamiz.Bu sog‘lom yondashuv.
10. Tech Radar
Tech Radar nima?
Tech Radar - kompaniya yoki team qaysi texnologiyalarni ishlatishi, sinashi yoki tark etishini ko‘rsatadigan xarita.
Odatda 4 kategoriya bo‘ladi:
Kategoriya | Ma’nosi |
|---|---|
Adopt | Ishlatishga tavsiya qilinadi |
Trial | Sinab ko‘rish mumkin |
Assess | O‘rganish kerak |
Hold | Hozircha ishlatmaslik kerak |
Java team uchun misol Tech Radar
Texnologiya | Status | Sabab |
|---|---|---|
Java 21 | Adopt | LTS, virtual threads mavjud |
Spring Boot 3.x | Adopt | Production-ready stack |
PostgreSQL | Adopt | Ishonchli relational DB |
Redis | Adopt | Cache va distributed lock uchun |
Kafka | Trial | Streaming case’lar uchun |
RabbitMQ | Adopt | Queue/routing uchun |
GraphQL | Assess | Ayrim frontend-heavy case’lar uchun |
MongoDB | Trial | Document-heavy domain bo‘lsa |
Custom framework | Hold | Maintenance xavfi katta |
11. ADR qayerda saqlanadi?
Eng yaxshi joy - project repository ichida.
project-root
├── src
├── docs
│ └── adr
│ ├── 0001-use-modular-monolith.md
│ ├── 0002-use-postgresql.md
│ ├── 0003-use-rabbitmq.md
│ └── 0004-use-redis-cache.md
└── README.mdNega repository ichida?
code bilan birga versionlanadi;
pull request’da review qilinadi;
tarix Git’da qoladi;
yangi developer osongina topadi.
12. ADR yozishda eng katta xatolar
1. Juda uzun yozish
ADR 20 sahifa bo‘lsa, hech kim o‘qimaydi.
Yaxshi ADR:
1-2 sahifa
aniq sabab
aniq qaror
aniq consequence2. Faqat qarorni yozish, sababni yozmaslik
Yomon:
We use Kafka.Yaxshi:
We use Kafka because we need event replay, high throughput,
and event streaming as integration backbone.3. Alternative variantlarni yozmaslik
Qaror kuchli bo‘lishi uchun boshqa variantlar ham ko‘rsatilishi kerak.
Considered:
- Kafka
- RabbitMQ
- PostgreSQL LISTEN/NOTIFY
- Direct HTTP calls4. Negative consequence yozmaslik
Har qarorning minuslari bor.
Agar ADR faqat pluslardan iborat bo‘lsa, bu marketing document bo‘lib qoladi.
Yaxshi ADR minuslarni ham aytadi:
Negative:
- Kafka operation complexity oshadi.
- Schema evolution boshqarilishi kerak.
- Local development murakkablashadi.13. Real Spring Boot loyiha uchun ADR namunasi
# ADR-001: Use Modular Monolith for Initial Architecture
## Status
Accepted
## Date
2026-05-20
## Context
We are building a sales management system with two Android apps:
Supervisor app and Sales Agent app.
The backend includes:
- authentication
- agent management
- customer management
- visit tracking
- order collection
- reporting
The team is small.
The domain is still evolving.
Independent service deployment is not required yet.
## Decision
We will start with a modular monolith architecture using Spring Boot.
Modules:
- auth
- agents
- customers
- visits
- orders
- reports
- notifications
Each module must expose public application services or facades.
Direct access to another module's repository or internal package is not allowed.
## Alternatives Considered
### Traditional Monolith
Pros:
- fastest to start
- simple deployment
Cons:
- boundaries will likely become unclear
- future extraction will be harder
### Microservices
Pros:
- independent deployment
- independent scaling
Cons:
- too much operational complexity for current team size
- distributed transactions and observability are not ready yet
- domain boundaries are not stable
### Modular Monolith
Pros:
- simple deployment
- clear module boundaries
- easier future extraction to microservices
Cons:
- requires discipline
- all modules are still deployed together
## Consequences
Positive:
- Faster development
- Easier local debugging
- Clear business modules
- Lower infrastructure complexity
Negative:
- Cannot deploy modules independently
- Requires architecture tests and code review discipline
## Fitness Functions
- No module can access another module's infrastructure package.
- Controllers must not access repositories directly.
- All inter-module communication must go through public facades or ports.
## Review Date
2026-11-2014. Arxitektor uchun asosiy qoida
ADR yozishdan maqsad "hujjat ko‘paytirish" emas.
Maqsad:
Qaror yo‘qolmasin.
Sabab unutilmasin.
Team bir xil tushunsin.
Yangi odam tez moslashsin.
Kelajakda noto‘g‘ri qayta qaror qilinmasin.15. Qisqa formula
ADR = Decision + Context + Alternatives + ConsequencesYana qisqaroq:
Nima tanladik, nega tanladik, nimalardan voz kechdik, endi qanday oqibat bo‘ladi?
Yakuniy xulosa
Architecture Decision Records arxitektor uchun juda amaliy qurol.
U quyidagilarni beradi:
qarorlar tarixini saqlaydi;
team alignment yaratadi;
yangi developerga context beradi;
"nega bunday qilingan?" savoliga javob beradi;
architecture drift’ni kamaytiradi;
kelajakdagi refactor va migration’ni osonlashtiradi.
Arxitektor darajasida yaxshi savol bu emas:
"Qaysi texnologiya zo‘r?"
Yaxshi savol:
"Biz bu qarorni qaysi contextda, qaysi trade-offlar bilan qabul qilyapmiz va buni keyinchalik qanday tekshiramiz?"