AI के दौर में सीनियर Flutter इंजीनियर की तरह सोचिए
Flutter community में एक ऐसी बात है जिसके बारे में कोई खुलकर बात नहीं करता। जब हम "systems design" कहते हैं, तो ज़्यादातर इंजीनियर तुरंत load balancer और message queue के diagrams बनाने लगते हैं। और देखिए, मुझे समझ आता है — interview prep books ने हमें यही सिखाया है। लेकिन जैसे ही आपसे *frontend* systems design करने को कहा जाता है — Flutter app का widget tree, state flow, data layer — तो पूरे कमरे में सन्नाटा छू जाता है।
बात ये है कि frontend systems design असली है, मुश्किल है, और ठीक यही वो जगह है जहाँ AI tools आपको या तो बहुत ज़्यादा productive बना देंगे, या फिर खतरनाक तरीके से sloppy। बीच का रास्ता नहीं है।
पिछले एक साल में मैंने AI coding agents को Flutter apps बनाते देखा है — और वो speed वाकई डरावनी है। उसमें से कुछ code बहुत शानदार है। लेकिन ज़्यादातर code technical debt का ऐसा ढेर है जिसे एक `StatefulWidget` ने पकड़ रखा है, और वो widget तीन अलग-अलग APIs को छू रहा है। ये tooling की समस्या नहीं है। ये सोचने की समस्या है।
चलिए इसे ठीक करते हैं।
Flutter के लिए "Systems Design" का असली मतलब
जब कोई senior engineer सुनता है "design a chat app", तो वो `ListView.builder` से शुरू नहीं करता। वो boundaries से शुरू करता है।
Backend engineers services, databases और queues में सोचते हैं। Flutter engineers को इनमें सोचना चाहिए:
- **Widget decomposition** — 600 lines का widget कब एक folder में बंटे हुए focused widgets में बदलना चाहिए?
- **State ownership** — कौन सा state widget tree में रहेगा, कौन सा controller में, और कौन सा repository में?
- **Data flow** — network से pixels तक data का one-way direction क्या है?
- **Failure handling** — retries, fallbacks और error states कहाँ रहेंगे?
एक senior Flutter engineer app को प्याज़ की तरह देखता है। सबसे बाहरी layer widget tree है — presentation। बीच की layer state management है — application logic। और अंदर का core data access है — repositories, services, local storage। Systems design का काम ये है कि ये layers आपस में पिघलकर एक न हो जाएँ।
जो Rule आपकी जान बचाएगा: Widgets Business Logic नहीं जानते
मैं हर mentee को एक rule देता हूँ: **आपके widgets को आपकी business logic नहीं पता होनी चाहिए, और आपकी business logic को आपके widgets नहीं पता होने चाहिए।**
अगर कोई `TextFormField` सीधे repository को call कर रहा है, तो आपने boundary तोड़ दी। अगर आपकी repository जानती है कि `TextEditingController` क्या होता है, तो आपने उल्टी दिशा में boundary तोड़ी है। यही separation code को testable, replaceable बनाती है — और AI के दौर में सबसे ज़रूरी बात, यही वजह है कि कोई agent आपके पूरे app को उड़ाए बिना code edit कर पाता है।
AI Game कैसे बदलता है
GitHub Copilot, Claude Code और Cursor जैसे AI tools ने कोड लिखने का तरीका पूरी तरह बदल दिया है। मैं आजकल एक पूरा CRUD app एक दोपहर में खड़ा कर सकता हूँ। ये exaggeration नहीं है; ये आम दिन है।
लेकिन दर्जनों AI-assisted Flutter projects के बाद मैंने जो सीखा, वो ये है: **agents code लिखने में शानदार होते हैं और architectural decisions लेने में बिल्कुल बेकार।**
किसी agent को एक अधूरे widget वाला folder दीजिए और साफ instruction दीजिए — वो करके दिखाएगा। लेकिन उसे ऐसा vague prompt दीजिए, "make this app better", तो वो चुपचाप चालीस अलग-अलग decisions लेगा, और उनमें से कुछ बिल्कुल गलत होंगे।
यही वजह है कि OpenClaw agent का वो gym reservation system hack करने वाला मामला वायरल हुआ था — code इसलिए नहीं कि वो clever था, बल्कि इसलिए क्योंकि agent को सिर्फ *goal* दिया गया था, कोई *constraints* नहीं। यही pattern मैं Flutter codebases में देखता हूँ जहाँ agents को बिना architectural guardrails के छोड़ दिया जाता है।
Scenario One: AI-Generated गड़बड़
पिछले महीने मेरे एक mentee ने अपना project खोला और दिखाया कि agent ने क्या बनाया था। Task साधारण था: "Add offline support to the orders screen."
Agent ने जो किया:
- `pubspec.yaml` में `path_provider` और `sqflite` डाल दिए
- एक widget के `initState` में SQLite database बना दी
- तीसरे पक्ष के HTTP client को बिना किसी interface के एक custom class में लपेट दिया
- पूरे JSON responses को एक global static variable में cache कर दिया
तकनीकी रूप से वो "चल गया" — happy path पर। लेकिन database connection leak कर रही थी, cache की कोई invalidation strategy नहीं थी, और slow devices पर UI freeze हो जाता था क्योंकि SQLite operations main isolate पर चल रहे थे।
समाधान बेहतर prompts नहीं था। समाधान था **बेहतर systems design** — agent से code लिखवाने से *पहले* ये तय करना कि persistence एक abstract repository के पीछे रहेगी, [drift](https://drift.simonbinder.eu) जैसी compile-time-safe storage का इस्तेमाल होगा, और UI सिर्फ state की एक stream को observe करेगी।
Systems Design Patterns जो हर Flutter Engineer को आने चाहिए
मैं आपको वो playbook देता हूँ जो मैं खुद इस्तेमाल करता हूँ जब मुझसे कोई Flutter feature design करने को कहा जाता है — चाहे वो human के लिए हो, agent के लिए, या दोनों के लिए।
1. Three-Layer Cake (Presentation / Application / Data)
- **Presentation layer**: widgets, animations, routing। ये सिर्फ state consume करता है और intents emit करता है।
- **Application layer**: state management (Riverpod providers, Bloc cubits, ChangeNotifiers)। ये intents को state changes में बदलता है।
- **Data layer**: repositories, services, local databases, network clients। ये बाहरी दुनिया से बात करने का गंदा काम संभालता है।
हर layer सिर्फ अपने ठीक नीचे वाली layer से बात करती है। Widgets कभी `Dio` को touch नहीं करते। Repositories कभी `BuildContext` return नहीं करतीं।
अगर आप सोच रहे हैं "form validation कहाँ रहेगी?" या "API key Provider में रखूँ?", तो जवाब हमेशा यही है — "उस layer में जिसकी concern है।"
2. State Management as a Unidirectional Flow
मुझे इससे फर्क नहीं पड़ता कि आप कौन सी state management library चुनते हैं — [Riverpod](https://riverpod.dev), [Bloc](https://bloclibrary.dev), या सीधा-सादा `InheritedWidget` — बशर्ते flow एक दिशा में हो:
```
State की Stream -> Widgets Render -> User Intents -> State Mutations -> Repeat
```
जिस दिन आपके पास two-way bindings होंगे, bugs होंगे। जिस दिन widgets सीधे state mutate करेंगे, ऐसे bugs होंगे जिन्हें आप reproduce नहीं कर पाएँगे। और जिस दिन आप user data को global `static var` में रखेंगे, उस दिन आपके भविष्य में security review लिखा हुआ है।
3. Error Boundaries और Graceful Degradation
एक senior engineer पहले failure के लिए design करता है। हर screen इन सवालों का जवाब देती है:
- अगर API down है तो क्या होगा?
- अगर user के पास internet नहीं है तो क्या होगा?
- अगर JSON का shape बदल जाए तो क्या होगा?
- अगर data null है तो क्या होगा?
इसका मतलब हर चीज़ को try-catch में लपेटना नहीं है। इसका मतलब है ऐसे *state types* design करना जिनमें `loading`, `loaded`, `error` और `empty` states शामिल हों — और फिर ये सुनिश्चित करना कि हर widget चारों states को render करना जानता है। मेरा विश्वास कीजिए, ये किसी भी obscure package से कहीं ज़्यादा valuable है।
AI-Assisted Flutter के लिए "Spec First" तरीका
मैंने पहले कहा कि AI agents बिना constraints के भटक जाते हैं। मेरे लिए जो तरीका हमेशा काम करता है, वो है **spec-driven development**। Agent code लिखना शुरू करे उससे *पहले* spec लिखिए।
ये रहा workflow:
1. **Feature के लिए एक-page Architecture Decision Record (ADR) लिखिए।** 500 शब्दों से कम रखिए। उसमें widget tree structure, state management hooks, और data contracts शामिल कीजिए।
2. **File boundaries तय कीजिए।** Folders के नाम दीजिए: `features/checkout/widgets/`, `features/checkout/logic/`, `features/checkout/data/`। Agent को साफ file paths दीजिए।
3. **Agent को ये instruction दीजिए कि वो architectural decisions आपसे पूछे, खुद न ले।** ये एक वाक्य 90% AI-driven architecture horror stories रोक देता है।
4. **Agent का code चलाने से पहले ADR के हिसाब से review कीजिए।** Code review आपका सबसे अच्छा test है।
ये bureaucracy नहीं है। ये सुनिश्चित करना है कि agent के 500 lines code सही जगह लैंड करें। क्योंकि इसका विकल्प refactoring है — और AI-generated code का refactoring human code के refactoring से भी बदतर है, क्योंकि *किसी ने भी* उसे intent के साथ नहीं लिखा था।
Scenario Two: Streaming AI Responses (हाँ, आप भी AI feature बना रहे हैं)
मान लीजिए आप एक AI chat feature बना रहे हैं। Agent मिनटों में एक खूबसूरत animated streaming response screen बना सकता है। लेकिन एक step पीछे जाइए और systems-level सोचिए:
- Conversation history कहाँ रहेगी? Memory में, local storage में, server पर?
- HTTP stream बीच में टूट जाए तो क्या होगा?
- Rate-limit और 429s कैसे handle करेंगे?
- UI में unsafe या hallucinated content कैसे handle करेंगे?
एक senior engineer पहला widget लिखने से पहले ही streaming state (`StreamBuilder`, buffer-backed state, retry logic) design करता है। Agent बाकी भर सकता है।
Scenario Three: Offline-First To-Do App
ऐसी app बनाइए जहाँ user हवाई जहाज़ में tasks manage करे। Systems design का सवाल है: आप किसके लिए optimize कर रहे हैं — data कभी न खोए, या speed?
`drift`-based local database, एक repository जो REST API से sync करती है, और एक connectivity provider जो network state track करता है — इनके साथ design साफ रहता है। Agent plumbing लिखता है; senior engineer plumbing का *shape* design करता है।
AI किस चीज़ को "Unnecessary" बनाता है (और किसे नहीं)
इन दिनों ढेर सारे think-pieces आ रहे हैं कि AI human developers की ज़रूरत खत्म कर देगा। Bull case ये है कि AI creators को ज़्यादा autonomy देता है; bear case ये है कि ये उन gaps को उजागर करता है जिन्हें autonomy छिपाना मुश्किल बना देती है — Andy Budd ने digital design के लिए ये लिखा था, और ये Flutter पर भी बिल्कुल सटीक बैठता है: AI code लिखने की *friction* हटाता है, लेकिन ये जानने की *जिम्मेदारी* नहीं हटाता कि क्या लिखना है।
AI ये कर सकता है:
- Boilerplate widget code आपके टाइप करने से तेज़ी से generate कर सकता है
- Design mock को seconds में widget tree में बदल सकता है
- आपकी repositories के लिए unit tests लिख सकता है
AI ये नहीं कर सकता:
- ये तय नहीं कर सकता कि state कहाँ रहेगी
- ये तय नहीं कर सकता कि cache freshness और API cost के बीच trade-off क्या होगा
- ये तय नहीं कर सकता कि API slow होने पर loading skeleton कैसा दिखेगा
ये design decisions हैं। ये *आपका* काम हैं, और दस साल बाद भी आपका काम यही रहेगा।
आपके अगले Flutter Systems Design के लिए Quick Checklist
जब कोई आपसे Flutter app design करने को कहे — interview में, design doc में, या सिर्फ अपने दिमाग में — ये checklist चलाइए:
1. **Functional atoms क्या हैं?** App को features में बाँटिए। हर feature independently buildable, testable और removable होना चाहिए।
2. **State atoms क्या हैं?** हर feature के लिए पहचानिए: कौन सा state local है, कौन सा shared है, और कौन सा persisted है?
3. **Data अंदर और बाहर कैसे जाता है?** हर data source के लिए एक repository होनी चाहिए। हर repository typed objects return करे, raw JSON नहीं।
4. **टूटने पर क्या होता है?** हर async call के लिए failure states। हर stream के लिए loading states।
5. **एक नया developer (या AI agent) code कैसे ढूँढेगा?** Folder structure self-documenting होनी चाहिए।
Keeping It Real: "Good Enough" Principle
मैं नहीं चाहता कि आप इस post को पढ़कर सोचें कि login button जोड़ने से पहले आपके app को abstraction की छह layers चाहिए। Systems design *proportion* के बारे में है।
Two-screen वाली utility app को Riverpod with code generation नहीं चाहिए। उसे एक `StatefulWidget` और एक repository चाहिए। Production e-commerce app को products list दिखाने के लिए तीस providers नहीं चाहिए। उसे clear boundaries, deliberate state ownership और एक data layer चाहिए जो UI में leak न हो।
अच्छे senior engineers जानते हैं कि complexity कब *नहीं* लगानी है। AI agents ये नहीं जानते — वो खुशी-खुशी उस feature के लिए factory pattern बना देंगे जो सिर्फ चालीस lines का हो सकता था। आपका काम guardrail बनना है।
Final Thoughts
AI के दौर में junior और senior Flutter engineers में ये फर्क है: **juniors AI से app बनवाते हैं, फिर जो टूटता है उसे ठीक करते हैं। Seniors app की boundaries design करते हैं, फिर AI को उन्हीं boundaries के अंदर बनाने देते हैं।**
Three-layer mindset अपनाइए। Agents को छोड़ने से पहले छोटी specs लिखिए। Intent के साथ review कीजिए। पहले failure के लिए design कीजिए। और याद रखिए: system उस *चीज़* के बारे में है जो आप बना रहे हैं, न कि उस AI के बारे में जो लिख रहा है।
क्योंकि चाहे code human टाइप करे या language model, किसी को तो ये तय करना होगा कि state कहाँ रहेगी। वो कोई आप होना चाहिए।
FAQ
1. क्या Flutter के लिए सच में "systems design" ज़रूरी है? क्या ये backend वाली चीज़ नहीं है?
Frontend systems design बिल्कुल असली है। इसका मतलब है ये तय करना कि state कहाँ रहेगी, data कैसे flow होगा, और widgets, logic व data layers के बीच boundaries कहाँ होंगी। Backend design scale संभालता है; frontend design *complexity* संभालता है। जिस Flutter app में पचास interdependent widgets हों और कोई boundaries न हों, उसे maintain करना उतना ही मुश्किल है जितना spaghetti services वाले backend को।
2. Flutter interview में systems design कैसे approach करूँ?
Concerns को अलग करने पर ध्यान दीजिए। Interviewers ये सुनना चाहते हैं कि आप widget tree decomposition, state ownership (क्या local है बनाम क्या global है), data contracts (repository क्या return करती है?) और failure handling के बारे में बात करते हैं। Riverpod या Bloc जैसे tools का नाम लेना अच्छा है, लेकिन ये बताना बेहतर है कि *कब* कौन सा इस्तेमाल करेंगे। और code की तरफ मत भागिए — पहले trade-offs के बारे में बात कीजिए।
3. क्या मुझे AI agents से अपनी Flutter architecture शुरू से design करवानी चाहिए?
नहीं। Agents boundaries के अंदर implement करने में बहुत अच्छे होते हैं, लेकिन अगर prompt vague है तो वो खुशी से widget के अंदर database call लगा देंगे। Agent शुरू होने से पहले एक छोटी spec लिखिए — bullet points भी चलेंगे — जिसमें folders, state management hooks और data contracts हों। फिर output को उसी spec के हिसाब से review कीजिए। आपकी spec सबसे ज़रूरी control lever है।
4. बड़े Flutter apps के लिए Riverpod या Bloc better है?
दोनों production-ready हैं; ये tech से ज़्यादा philosophy का सवाल है। Riverpod compile-time safety, scoped providers और ज़्यादा functional style देता है। Bloc strict event/state pattern enforce करता है, जो document करने में आसान है लेकिन verbose है। बड़े apps के लिए, अपनी team की comfort के हिसाब से चुनिए और फिर consistent रहिए। दोनों में से किसी को भी consistently apply करना, project के बीच में switch करने से बेहतर है। दोनों docs पढ़िए — [riverpod.dev](https://riverpod.dev) और [bloclibrary.dev](https://bloclibrary.dev) — और अपनी team के साथ मिलकर फैसला कीजिए।
टेक्नोलॉजी
Comments (0)
No comments yet. Be the first to comment!
Leave a Comment