#ARCH-7 MVC, MVP, MVVM, MVI — farqi nimada?
Ko'pchilik eshitadigan lekin ko'pincha farqini bilmaydiganlar patternlar, bugungi post ularni tushunish uchun ancha foydali bo'ladi degan umiddamn. Bu patternlarning asosiy maqsadi bir xil: UI va logic orasidagi mas’uliyatni to‘g‘ri ajratish. Farqi — ular qanday aloqa qilishida.
MVC — Model, View, Controller
View → Controller → Model
Controller user actionlarini qabul qiladi va Model bilan ishlaydi. Oddiy loyihalarda tushunarli, lekin murakkab UI’da Controller kattalashib ketishi mumkin.
MVP — Model, View, Presenter
View → Presenter → Model
↓
View
Presenter logicni boshqaradi va View’ga
showLoading(), showError() kabi buyruqlar beradi. Kamchiligi — Presenter View bilan kuchliroq bog‘lanishi mumkin.MVVM — Model, View, ViewModel
View → ViewModel
↓
State
↓
View
ViewModel View’ga nima qilishni buyurmaydi. U state beradi, View esa state’ni kuzatadi.
Flutter’da
Cubit/BLoC + state bilan ko‘p hollarda shunga yaqin yondashuv quriladi.MVI — Model, View, Intent
Intent → Logic → State → View
↑ │
└─────────────────────┘
Asosiy g‘oya — Unidirectional Data Flow. Event keladi → yangi state hosil bo‘ladi → UI state asosida render qilinadi.
Masalan:
PayPressed
↓
Processing
↓
Success / Failure
↓
UI
💡 Muhim: BLoC ishlatish avtomatik ravishda MVI yoki Clean Architecture degani emas. Patternni package emas, responsibility va data flow belgilaydi.
Qisqacha:
MVC → Controller boshqaradi
MVP → Presenter View'ga buyruq beradi
MVVM → View state'ni kuzatadi
MVI → Intent → State → View oqimi
Xulosa: Pattern tanlashda “qaysi biri eng zo‘r?” emas, loyiha murakkabligi uchun qaysi biri yetarli? degan savol muhim.
@flutterDevTalk
👍2❤1
#ARCH-8 Logic & Validations — qaysi logic qayerda turadi?
Architecture’da ko‘p uchraydigan savol:
“Bu `if` qaysi layer’da turishi kerak?”
Buni `if`ning o‘ziga emas, u qanday qaror chiqarayotganiga qarab aniqlaymiz.
📱 1. Presentation — UI qanday behave qiladi?
if (state.isLoading) {
// button disabled
}
Loading, button state, error ko‘rsatish — presentation responsibility.
💼 2. Domain — business bo‘yicha mumkinmi?
Masalan transfer uchun:
bool canTransfer({
required int amount,
required int min,
required int max,
}) {
return amount >= min && amount <= max;
}
amount limit ichidami — business rule.
⚙️ 3. Application / UseCase — operation qanday bajariladi?
limitni olish
↓
balance'ni olish
↓
business rule'ni tekshirish
↓
transferni boshlash
UseCase bir nechta business/data operatsiyalarini orchestrate qilishi mumkin.
🌐 4. Data — ma’lumot qayerdan va qanday keladi?
API → DTO → mapping → domain model
HTTP request, JSON parsing, DTO mapping — data concern.
Masalan:
API'dan min/max olish → Data
amount limit ichidami? → Domain
transfer jarayonini boshqarish → Application
Pay buttonni disable qilish → Presentation
💡 Xulosa:
> “Flutter/UI’ni olib tashlasam, bu qoida hali ham ma’noga egami?”
Agar ha bo‘lsa, u katta ehtimol bilan business/domain logic.
Agar “UI qanday ko‘rinadi?” degan savolga javob bersa — presentation logic. Va har bir validation uchun UseCase, Service, Validator yaratish shart emas.
🎯 Architecture — ko‘proq layer yaratish emas. Logic uchun to‘g‘ri owner topish.
@flutterDevTalk
🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
👏9❤2🔥2
#ARCH-9 Validation Boundary
Dasturlarda ko'p uchraydigan savol qaysi logicani qayerda tekshirishim kerak, buni validation misolida ko'rib chiqamiz.
Validation’da ko‘p uchraydigan savol:
- “Buni qaysi layer tekshirishi kerak?”
Yaxshiroq savol esa:
- “Bu qiymatga qaysi boundary ishonishi mumkin?”
Masalan, transfer summasi:
User input: "6000000"
Bir xil amount bir necha joyda tekshirilishi mumkin:
1️⃣ Presentation / Input
final amount = int.tryParse(input);
Savol: “Bu input umuman valid raqammi?”
2️⃣ Domain / Business
if (amount < min || amount > max) {
return AmountNotAllowed();
}
Savol: “Business bo‘yicha bu summaga ruxsat bormi?”
3️⃣ Server
Server ham limitni qayta tekshiradi.
Savol: “Hozirgi authoritative ma’lumot bo‘yicha transaction haqiqatan ruxsat etilganmi?”
Flow:
"6000000"
↓
Presentation
parse bo‘ladimi?
↓
Domain
business rule'dan o‘tadimi?
↓
Server
haqiqatan ruxsatmi?
Bu har doim duplicate validation emas.
Har bir boundary boshqa narsaga javobgar:
Presentation → yaxshi UX va valid input
Domain → business correctness
Server → authoritative validation
Masalan, client max = 5 000 000 deb tekshirganidan keyin serverdagi limit `4 000 000`ga o‘zgarishi mumkin.
Shuning uchun:
> Client validation server validation’ni almashtirmaydi.
💡 Architecture’da validation’ni joylashtirishda faqat “kim tekshiradi?” deb emas, “bu layer nimaga ishonishi mumkin va qanday qaror uchun javobgar?” deb o‘ylash foydaliroq.
🎯 Bir xil data bir nechta boundary’da tekshirilishi mumkin, chunki har bir boundary’ning responsibility’si boshqa.
❤1🔥1
#ARCH-10 Architecture Learning — DTO, Domain Model & Mapper
Bugun hammaga qiziq bo'lgan va o'zim farqiga borishga juda qiynalgan mavzuni ko'rib chiqamiz. Bundan keyin Model va Entityni farqi nimaga ishlatish va qachon ishlatish kerak ekanini bilib olamiz.
API’dan kelgan modelni to‘g‘ridan-to‘g‘ri butun app’da ishlatish har doim ham yaxshi yechim emas.
Masalan backend:
{
"article_id": 123,
"liked": 1,
"status": "PUBLISHED"
}
qaytardi.
Bu — DTO (Data Transfer Object):
class ArticleDto {
final int articleId;
final int liked;
final String status;
}
DTO - “Server data’ni qanday ifodalaydi?” savolga javob beradi.
Application ichida esa bizga qulayroq model kerak bo‘lishi mumkin:
class Article {
final int id;
final bool isLiked;
final ArticleStatus status;
}
Bu — Domain Model(yoki Entity).
Ular orasida Mapper ishlaydi:
Article toDomain(ArticleDto dto) {
return Article(
id: dto.articleId,
isLiked: dto.liked == 1,
status: mapStatus(dto.status),
);
}
Flow:
API
↓
DTO
↓
Mapper
↓
Domain Model
↓
Application / UI
💡 Asosiy foyda — backend contract o‘zgarishini application ichiga tarqatmaslik.
Masalan:
liked: 1
ertaga:
is_liked: true
bo‘lsa, ideal holatda o‘zgarish DTO + Mapper atrofida qoladi.
• Anemic vs Rich Model
Domain Model faqat data saqlasa:
article.isLiked
article.status
→ Anemic Model
O‘ziga tegishli behaviorni ham bilsa:
bool get canLike =>
status == ArticleStatus.published && !isLiked;
→ Rich Model hisoblanadi.
Lekin Rich Model har doim yaxshiroq degani emas.
Xar doimgi qoidamiz: DTO → Domain → UI uchun alohida model yaratishning o‘zi Clean Architecture emas.
Agar API va application modeli bir xil va sodda bo‘lsa — bitta model yetishi mumkin.
Agar backend contract tez o‘zgarsa, representation farq qilsa, bir nechta data source bo‘lsa yoki business model tashqi datadan mustaqil bo‘lishi kerak bo‘lsa — DTO + Mapper + Domain Model ajratilishi real qiymat beradi.
🎯 Senior qarori: Abstraction’ni layer ko‘paytirish uchun emas, o‘zgarishning tarqalishini to‘xtatish uchun yaratiladi.
@flutterDevTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
#ARCH-11 Architecture Learning — Mapper, Domain Invariant & Business Rule
Payment flow’da API’dan kelgan ma’lumotni Domain Model’ga aylantirish faqat fieldlarni ko‘chirish emas.
Muhim savol:
Tashqi tizimdan kelgan ma’lumotga qachondan boshlab ishonishimiz mumkin?
Masalan, Payment API quyidagicha response qaytardi:
{
"bill_id": "12345",
"amount": -100000,
"commission": 1500,
"status": "CREATED"
}
Bu yerda uchta tushunchani ajratishimiz kerak.
1️⃣ Mapper — Data’ni tarjima qilish
PaymentStatus mapStatus(String status) {
return switch (status) {
'CREATED' => PaymentStatus.created,
'PAID' => PaymentStatus.paid,
'EXPIRED' => PaymentStatus.expired,
_ => throw FormatException('Unknown status'),
};
}
Mapper API representation’ni application tushunadigan formatga aylantiradi.
2️⃣ Domain Invariant — Model doim valid bo‘lishi kerak
class Payment {
Payment({
required this.amount,
required this.commission,
}) {
if (amount <= 0 || commission < 0) {
throw ArgumentError('Invalid payment');
}
}
// Summalar eng kichik pul birligida
final int amount;
final int commission;
int get total => amount + commission;
}
Invariant — model mavjud bo‘lishi uchun bajarilishi shart bo‘lgan qoida.
Masalan, bizning taxminiy talabimizda:
- amount > 0
- commission >= 0
-
Bu shartlar buzilsa, valid Payment yaratib bo‘lmaydi.
3️⃣ Business Rule — Payment qilish mumkinmi?
bool canPay({
required Payment payment,
required int balance,
}) {
return balance >= payment.total;
}
Payment modeli valid bo‘lishi uning to‘lanishi mumkinligini anglatmaydi.
Masalan:
Amount: 100 000
Commission: 1 500
Total: 101 500
Balance: 100 000
Payment valid, lekin balans yetarli emas.
Flow:
Payment API
↓
PaymentDto
↓
Mapper → API data validmi?
↓
Payment Model → Invariant bajarilganmi?
↓
Business Rule → Payment qilish mumkinmi?
↓
Application → Payment flow
💡 Senior yondashuvi
Mapper tashqi data’ni tarjima qiladi. Domain Model o‘z invariantlarini himoya qiladi. Business Rule esa operation bajarilishiga ruxsat borligini aniqlaydi.
Biroq client’dagi canPay tekshiruvi serverning yakuniy validation’ini almashtirmaydi. Balans yoki payment status tekshiruvdan keyin o‘zgarishi mumkin.
🎯 Asosiy xulosa:
Valid Payment ≠ Payable Payment
Model valid bo‘lishi boshqa, shu model bilan payment operation bajarishga ruxsat bo‘lishi boshqa masala.
Architecture’da muhim narsa har bir `if`ni alohida layer’ga chiqarish emas, balki har bir qoida uchun to‘g‘ri owner tanlashdir.
@flutterDevTalk
Uzum ertalabdan beri ishlamayapti. Bunga sabab yandex serverlari dron hujumiga uchragani va uzum yandex serverlaridan foydalangani deyishyapti.
Shu to’g’rimikin ??
Shu to’g’rimikin ??
#ARCH-12 Architecture Learning — Soft vs Hard Boundary
Flutter’da kodlarni bir-biridan ajratishning ikki xil usuli bor.
1️⃣ Soft Boundary — Yumshoq chegara
Kodlarni papkalarga ajratamiz:
lib/
├── presentation/
├── domain/
└── data/
Lekin presentation ichidan `data`ni to‘g‘ridan-to‘g‘ri import qilish mumkin.
Ya’ni chegara bor, lekin uni buzishga texnik to‘siq yo‘q.
2️⃣ Hard Boundary — Qattiq chegara
Kodlarni alohida package’larga ajratamiz:
packages/
├── presentation/
├── domain/
└── data/
Masalan, presentation faqat `domain`ga dependency qilsa, `data`ni to‘g‘ridan-to‘g‘ri import qila olmaydi.
Ya’ni chegara texnik jihatdan ham nazorat qilinadi.
💡 Qaysi biri yaxshiroq?
Kichik loyihalarda Soft Boundary yetarli bo‘lishi mumkin. Katta loyihalarda esa Hard Boundary dependency’larni nazorat qilishga yordam beradi.
Soft Boundary — developer qoidalarga amal qiladi.
Hard Boundary — texnik cheklovlar ham qoidalarga amal qilishga majbur qiladi.
Xulosa: Yaxshi arxitektura — ko‘p package yaratish emas, kerakli joyda to‘g‘ri chegara qo‘yish.
@flutterDevTalk
#ARCH-13 Architecture Learning — Soft vs Hard Boundary (PART 2)
📌 Shared Module — kodni qayta ishlatish har doim ham yaxshi yechimmi?
Flutter’da bir nechta feature’da bir xil kod uchrasa, uni shared modulga chiqarishimiz mumkin.
Bu kod takrorlanishini kamaytiradi. Lekin ba’zida ortiqcha bog‘liqlik ham yaratadi.
💻 Oddiy misol:
Tasavvur qilaylik, ilovamizda ikkita feature bor:
- payment — to‘lov qilish
- transfer — pul o‘tkazish
Ikkalasida ham Limit modeli mavjud:
class Limit {
final int minAmount;
final int maxAmount;
}
Kodlar bir xil ekan deb, bitta shared/Limit modelini yaratdik.
Endi ikkala feature ham shu modelga bog‘liq.
⚠️ Muammo qayerda?
Ertaga transfer uchun qo‘shimcha limit qoidasi kerak bo‘lib qolsa, umumiy modelni o‘zgartirishimiz mumkin.
Bu esa `payment`ga ham ta’sir qilishi yoki model ichida keraksiz shartlar paydo bo‘lishiga olib kelishi mumkin.
Ya’ni kod takrorlanishini kamaytirdik, lekin feature’larni bir-biriga bog‘lab qo‘ydik.
💡 Qanday yo‘l tutish kerak?
Agar ikkita model faqat tashqi ko‘rinishi bilan o‘xshash bo‘lsa, ularni alohida qoldirgan yaxshi.
Agar ular haqiqatan ham bitta tushunchani ifodalasa, `shared`ga chiqarish mumkin.
🎯 Xulosa:
Bir xil kod har doim ham umumiy modulga chiqarilishi kerak degani emas.
Ba’zida 10 qator kodning takrorlanishi, ikkita feature’ni keraksiz bog‘lab qo‘yishdan yaxshiroq.
@flutterDevTalk
🧠 #algoritms
Boyer–Moore Majority Vote Algorithm
Array ichida
n / 2 dan ko‘p uchraydigan elementni O(n) Time va O(1) Space bilan topish algoritmi.💡 Asosiy g‘oya: Har xil ikkita element bir-birini bekor qiladi.
int majorityElement(List<int> nums) {
int candidate = 0, count = 0;
for (final num in nums) {
if (count == 0) candidate = num;
count += num == candidate ? 1 : -1;
}
return candidate;
}
Masalan:
[2, 2, 1, 1, 1, 2, 2] → 2⚠️ Majority element mavjudligi kafolatlanmagan bo‘lsa, natijani ikkinchi loop bilan tekshirish kerak.
@flutterDevTalk
Techie's Blog
Tekinga bo’lsa ham ishlab ko’rardim 😁
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡3👍1🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁3💯1👨💻1
Flutter dastur iOSda yoki Androidda nativedek ko'rinishi kerak bo'lsa ushbu packagedan foydalanib ko'rilar. Package platformani automatik aniqlaydi va iOS uchun iOS26 LiquidGlass va eski iOS designi, Android uchun esa Material designdan foydalanadi. Kirib o'rganib chiqishni tavsiya beraman.
Dart packages
adaptive_platform_ui | Flutter package
Adaptive platform-specific widgets for Flutter. Auto renders native iOS 26+ liquid glass designs, traditional Cupertino widgets for older iOS versions, Material Design for Android.
👍2
Yaqinda Samarqanda formda GooglePay kirib kelgani haqida yozishgandi. OctoBank birinchi bo'lib integratsiya qilayotgani va qachon ApplePay kirib kelarkin deyishgandi. Mana Uzum va Kapital banklar tezda integratsiya qilib bo'lishibdi 😅. Androidchilar hate qilishyotgandi rosa endi nima bo’larkin. LinkedInda rosa postlar ko’rarkanmizda
❤2
Flutter Dev Talk
Yaqinda Samarqanda formda GooglePay kirib kelgani haqida yozishgandi. OctoBank birinchi bo'lib integratsiya qilayotgani va qachon ApplePay kirib kelarkin deyishgandi. Mana Uzum va Kapital banklar tezda integratsiya qilib bo'lishibdi 😅. Androidchilar hate qilishyotgandi…
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1🔥1