बोरिंग आर्किटेक्चर नियम के साथ सीखें कि कैसे जनित कोड को मेंटेनेबल रखें: स्पष्ट फ़ोल्डर सीमाएँ, सुसंगत नामकरण और सरल डिफ़ॉल्ट जो भविष्य के काम को कम करते हैं।

जनित कोड रोज़मर्रा के काम को बदल देता है। आप सिर्फ फ़ीचर नहीं बना रहे होते, बल्कि एक ऐसी प्रणाली निर्देशित कर रहे होते हैं जो तेज़ी से कई फ़ाइलें बना सकती है। यह स्पीड असली है, पर छोटी असंगतियाँ जल्दी बढ़ जाती हैं।
जनित आउटपुट अक्सर अलग‑अलग देखकर ठीक लगता है। लागतें दूसरे और तीसरे बदलाव पर दिखती हैं: आप नहीं बता पाते कि कोई हिस्सा कहाँ रखता है, आप एक ही व्यवहार को दो जगह ठीक करते हैं, या आप किसी फ़ाइल को छूने से बचते हैं क्योंकि आपको नहीं पता कि उसका असर और कहाँ होगा।
“क्लेवर” संरचना महंगी हो जाती है क्योंकि इसे अनुमान लगाना कठिन है। कस्टम पैटर्न, छुपी हुई जादूगरी और भारी एब्स्ट्रैक्शन पहले दिन में समझ में आ सकती है। लेकिन हफ्ते छठे पर अगला बदलाव धीमा हो जाता है क्योंकि आप सुरक्षित रूप से अपडेट करने से पहले फिर से वह ट्रिक सीखते हैं। AI‑सहायक जेनरेशन के साथ, वह चतुराई भविष्य की जेनरेशन्स को भी भ्रमित कर सकती है और लॉजिक की नक़ल या नई परतें जोड़ सकती है।
बोरिंग आर्किटेक्चर इसका उल्टा है: सादे सीमाएँ, सादे नाम और स्पष्ट डिफ़ॉल्ट। यह पूर्णता के बारे में नहीं है। यह उस लेआउट को चुनने के बारे में है जिसे एक थका हुआ टीममेट (या भविष्य का आप) 30 सेकंड में समझ सके।
سادہ लक्ष्य: अगला बदलाव आसान बनाइए, प्रभावशाली नहीं। आमतौर पर इसका मतलब है हर तरह के कोड (UI, API, डेटा, साझा उपयोगिताएँ) के लिए एक स्पष्ट जगह, उस फ़ाइल के काम से मेल खाने वाले अनुमानित नाम, और कम “मैजिक” जैसे ऑटो‑वायरिंग, छुपी ग्लोबल्स, या मेटाप्रोग्रामिंग।
उदाहरण: अगर आप Koder.ai से “team invites” जोड़ने को कहते हैं, तो आप चाहेंगे कि वह UI को UI क्षेत्र में रखे, API में एक ही रूट जोड़े, और इनवाइट डेटा को डेटा लेयर में संग्रहित करे—बिना उस फ़ीचर के लिए नया फ़ोल्डर या पैटर्न बनाये। वही बोरिंग सुसंगति भविष्य के संपादनों को सस्ता रखती है।
जनित कोड महंगा हो जाता है जब यह एक ही काम के कई तरीके देता है। बोरिंग आर्किटेक्चर नियम सरल है: अगला बदलाव अनुमानित बनाओ, भले ही पहली बार में बनावट कम चतुर लगे।
आपको इन सवालों का जल्दी जवाब देना चाहिए:
एक सादा संरचना चुनें और हर जगह उसी पर टिके रहें। जब कोई टूल (या टीममेट) कोई फैंसी पैटर्न सुझाव दे, डिफ़ॉल्ट उत्तर “नहीं” होना चाहिए जब तक कि वह असली दर्द नहीं हटाता।
ऐसी व्यावहारिक डिफ़ॉल्ट जो समय के साथ टिकती हैं:
कल्पना करें कि एक नया डेवलपर आपके रेपो को खोलता है और उसे “Cancel subscription” बटन जोड़ना है। उसे पहले कोई कस्टम आर्किटेक्चर सीखने की ज़रूरत नहीं होनी चाहिए। उसे एक स्पष्ट फीचर एरिया, एक स्पष्ट UI कॉम्पोनेंट, एक सिंगल API क्लाइंट स्थान और एक सिंगल डेटा एक्सेस पाथ मिलना चाहिए।
यह नियम विशेष रूप से vibe‑coding टूल्स जैसे Koder.ai के साथ अच्छा काम करता है: आप तेज़ी से जेनरेट कर सकते हैं, लेकिन हर बार आउटपुट को वही बोरिंग सीमाओं में गाइड कर सकते हैं।
जनित कोड तेजी से बढ़ने का झुकाव रखता है। उसे मेंटेनेबल रखने का सबसे सुरक्षित तरीका एक बोरिंग फ़ोल्डर मैप है जहाँ कोई भी अनुमान लगा सके कि बदलाव कहाँ आता है।
कई वेब ऐप्स के लिए एक छोटा टॉप‑लेवल लेआउट:
app/ — स्क्रीन, रूटिंग और पेज‑लेवल स्टेटcomponents/ — पुन: उपयोग योग्य UI हिस्सेfeatures/ — हर फ़ीचर के लिए एक फ़ोल्डर (billing, projects, settings)api/ — API क्लाइंट कोड और request हेल्पर्सserver/ — बैकएंड हैंडलर्स, सर्विसेस और बिज़नेस नियमयह सीमाएँ स्पष्ट बनाती हैं: UI app/ और components/ में रहता है, API कॉल api/ में, और बैकएंड लॉजिक server/ में।
डेटा एक्सेस भी बोरिंग होना चाहिए। SQL क्वेरीज और रिपॉज़िटरी को बैकएंड के पास रखें, UI फ़ाइलों में बिखरे हुए नहीं। Go + PostgreSQL सेटअप में, एक सरल नियम है: HTTP हैंडलर्स सर्विसेस को कॉल करते हैं, सर्विसेस रिपॉज़िटरीज को कॉल करती हैं, रिपॉज़िटरीज डेटाबेस से बात करती हैं।
शेयर की गई टाइप्स और यूटिलिटीज़ का एक स्पष्ट घर होना चाहिए, पर छोटे रखें। क्रॉस‑कटिंग टाइप्स को types/ में रखें (DTOs, enums, शेयर की गई इंटरफेस) और छोटे हेल्पर्स utils/ में रखें (date formatting, simple validators)। अगर utils/ दूसरी एप्प जैसा लगने लगे, तो कोड शायद किसी फीचर फ़ोल्डर में होना चाहिए।
जनित फ़ोल्डर्स को रिप्लेसेबल मानें।
generated/ (या gen/) में रखें और इसे सीधे एडिट करने से बचें।features/ या server/ में रखें ताकि रीजनरेशन उसे ओवरराइट न करे।उदाहरण: अगर Koder.ai एक API क्लाइंट जेनरेट करता है, तो उसे generated/api/ के तहत रखें, फिर api/ में पतले रैपर्स लिखें जहाँ आप retries, logging, या स्पष्ट त्रुटि संदेश जोड़ सकें बिना जनित फ़ाइलों को छुए।
जनित कोड बनाना आसान और एकत्र करना आसान है। नामकरण वह है जो इसे एक महीने बाद पठनीय रखता है।
एक नामकरण शैली चुनें और उसे मिलाते रहें:
kebab-case (user-profile-card.tsx, billing-settings)PascalCase (UserProfileCard)camelCase (getUserProfile)SCREAMING_SNAKE_CASE (MAX_RETRY_COUNT)भूमिका के अनुसार नाम दें, आज के काम करने के तरीके के अनुसार नहीं। user-repository.ts एक भूमिका है। postgres-user-repository.ts एक इम्प्लीमेंटेशन विवरण है जो बदल सकता है। जब वास्तव में आपके पास कई इम्प्लीमेंटेशन हों तभी इम्प्लीमेंटेशन सुफिक्स का उपयोग करें।
misc, helpers, या एक विशाल utils जैसे जंक ड्रॉअर से बचें। अगर कोई फ़ंक्शन सिर्फ़ एक फीचर द्वारा उपयोग होता है, तो उसे उस फीचर के पास रखें। अगर वह साझा है, तो नाम से क्षमता बताएं (date-format.ts, money-format.ts, id-generator.ts) और मॉड्यूल छोटा रखें।
जब routes, handlers, और components एक पैटर्न का पालन करते हैं, आप चीज़ें ढूँढ सकते हैं बिना सर्च किए:
routes/users.ts जैसे पाथ्स /users/:userIdhandlers/users.get.ts, handlers/users.update.tsservices/user-profile-service.tsrepositories/user-repository.tscomponents/user/UserProfileCard.tsxअगर आप Koder.ai (या किसी भी जनरेटर) का उपयोग कर रहे हैं, तो इन नियमों को प्रॉम्प्ट में डालें और संपादनों के दौरान उन्हें लगातार रखें। लक्ष्य प्रत्याश्यता है: अगर आप फ़ाइल नाम का अनुमान लगा सकते हैं, तो भविष्य के बदलाव सस्ते रहेंगे।
जनित कोड पहले दिन में प्रभावशाली और तीसरे दिन में पीड़ादायक लग सकता है। ऐसे डिफ़ॉल्ट चुनें जो कोड को स्पष्ट बनाते हैं, भले ही थोड़ी दोहराव हो।
मैजिक घटाएँ। डायनामिक लोडिंग, रिफ्लेक्शन‑स्टाइल ट्रिक्स, और ऑटो‑वायरिंग को छोड़ दें जब तक कि मापनीय आवश्यकता न हो। ये सुविधाएँ यह छुपाती हैं कि चीज़ें कहाँ से आ रही हैं, जिससे डिबग और रिफ़ैक्टरिंग धीमा होता है।
स्पष्ट इम्पोर्ट्स और स्पष्ट निर्भरताओं को प्राथमिकता दें। अगर किसी फ़ाइल को किसी चीज़ की ज़रूरत है, तो उसे सीधे इम्पोर्ट करें। अगर मॉड्यूल्स को वायरिंग चाहिए, तो इसे एक दिखाई देने वाली जगह पर करें (उदाहरण के लिए, एक सिंगल composition फ़ाइल)। किसी रीडर को यह अनुमान नहीं लगाना चाहिए कि पहले क्या रन होगा।
कन्फ़िगुरेशन को बोरिंग और केंद्रीकृत रखें। एन्वायरनमेंट वेरिएबल्स, फीचर फ्लैग्स, और ऐप‑वाइड सेटिंग्स को एक मॉड्यूल में रखें एक नामकरण स्कीम के साथ। रैंडम फ़ाइलों में कन्फ़िग फैलाने से बचें क्योंकि वह सुविधाजनक लग रहा था।
कुछ नियम जो टीमों को संगठित रखते हैं:
त्रुटि हैंडलिंग वह जगह है जहाँ चतुराई सबसे ज्यादा नुकसान पहुँचाती है। एक पैटर्न चुनें और उसे हर जगह इस्तेमाल करें: डेटा लेयर से संरचित त्रुटियाँ लौटाएँ, एक जगह पर उन्हें HTTP रिस्पॉन्स में मैप करें, और UI बॉर्डर पर उपयोगकर्ता‑सामना संदेशों में अनुवादित करें। फ़ाइल के अनुसार तीन अलग‑अलग त्रुटि प्रकार फेंकने से बचें।
अगर आप Koder.ai से ऐप जेनरेट करते हैं, तो इन डिफ़ॉल्ट्स को पहले मांगें: स्पष्ट मॉड्यूल वायरिंग, केंद्रीकृत कन्फ़िग, और एक त्रुटि पैटर्न।
UI, API और डेटा के बीच स्पष्ट रेखाएँ बदलावों को सीमित रखती हैं। अधिकांश मिस्ट्री बग तब होते हैं जब एक लेयर दूसरे लेयर का काम करने लगती है।
UI (अक्सर React) को स्क्रीन रेंडर करने और UI‑ओनली स्टेट मैनेज करने की जगह समझें: कौन सा टैब खुला है, फॉर्म त्रुटियाँ, लोडिंग स्पिनर, और बेसिक इनपुट हैंडलिंग।
सर्वर स्टेट अलग रखें: फ़ेच्ड लिस्ट्स, कैश्ड प्रोफ़ाइल्स, और जो कुछ भी बैकएंड से मेल खाना चाहिए। जब UI कॉम्पोनेंट्स टोटल्स निकालने, जटिल नियमों का वेलिडेशन करने, या परमिशन्स तय करने लगते हैं, तो लॉजिक स्क्रीन पर फैल जाती है और बदलना महंगा हो जाता है।
API लेयर को प्रत्याश्यनीय रखें। यह HTTP रिक्वेस्ट्स को बिज़नेस कोड कॉल्स में ट्रांसलेट करे, फिर परिणामों को स्थिर request/response शेप्स में वापस करे। डेटाबेस मॉडल्स को सीधे वायर पर भेजने से बचें। स्थिर रिस्पॉन्स से आप इंटरनल्स को बिना UI तोड़े रिफ़ैक्टर कर सकेंगे।
एक सरल पाथ जो अच्छा काम करता है:
SQL (या ORM लॉजिक) को रिपॉज़िटरी बाउंडरी के पीछे रखें ताकि बाकी ऐप यह “न जाने” कि डेटा कैसे स्टोर होता है। Go + PostgreSQL में, यह आमतौर पर UserRepo या InvoiceRepo जैसी रिपॉज़िटरीज के छोटे, स्पष्ट मेथड्स (GetByID, ListByAccount, Save) का मतलब होता है।
ठोस उदाहरण: डिस्काउंट कोड जोड़ना। UI एक फ़ील्ड रेंडर करती है और अपडेट की हुई कीमत दिखाती है। API code स्वीकार करता है और {total, discount} लौटाता है। सर्विस तय करती है कि कोड वैध है या नहीं और डिस्काउंट कैसे स्टैक होते हैं। रिपॉज़िटरी आवश्यक रो को फ़ेच और पर्सिस्ट करती है।
जनित ऐप्स जल्दी “डन” दिख सकते हैं, पर संरचना ही वह चीज़ है जो बदलावों को सस्ता रखती है। पहले बोरिंग नियम तय करें, फिर केवल उतना ही कोड जेनरेट करें जितना उन्हें साबित करने के लिए चाहिए।
एक छोटा प्लानिंग पास के साथ शुरू करें। अगर आप Koder.ai का उपयोग करते हैं, तो Planning Mode फ़ोल्डर मैप और कुछ नामकरण नियम लिखने के लिए एक अच्छा स्थान है इससे पहले कि आप कुछ भी जेनरेट करें।
फिर इस अनुक्रम का पालन करें:
ui/, api/, data/, features/) और कुछ नामकरण नियम तय करें।CONVENTIONS.md जोड़ें और इसे एक कॉन्ट्रैक्ट की तरह ट्रीट करें। कोडबेस बढ़ने के बाद नाम और फ़ोल्डर पैटर्न बदलना महंगा होता है।रीयलिटी चेक: अगर एक नया व्यक्ति अनुमान नहीं लगा सकता कि “edit contact” कहाँ डालना है बिना पूछे, तो आर्किटेक्चर अभी भी काफी बोरिंग नहीं है।
सोचिए एक सरल CRM: एक contacts लिस्ट पेज और एक contact edit फॉर्म। आप पहली बार तेज़ी से बनाते हैं, फिर एक सप्ताह बाद “tags” जोड़ने की ज़रूरत आती है।
ऐप को तीन बोरिंग बॉक्स की तरह ट्रीट करें: UI, API, और डेटा। हर बॉक्स को स्पष्ट सीमाएँ और शाब्दिक नाम दें ताकि “tags” बदलाव छोटा रहे।
एक साफ़ लेआउट कुछ इस तरह दिख सकता है:
web/src/pages/ContactsPage.tsx और web/src/components/ContactForm.tsxserver/internal/http/contacts_handlers.goserver/internal/service/contacts_service.goserver/internal/repo/contacts_repo.goserver/migrations/अब “tags” अनुमानित हो जाता है। स्कीमा अपडेट करें (नया contact_tags टेबल या tags कॉलम), फिर एक‑एक लेयर छुएँ: repo टैग्स पढ़े/लिखे, सर्विस वैलिडेट करे, हैंडलर फ़ील्ड एक्सपोज़ करे, UI उसे रेंडर और एडिट करे। हैंडलर्स में SQL चुपके से डालने या React कम्पोनेंट्स में बिज़नेस नियम घुसाने से बचें।
टेस्ट और फिक्स्चर के लिए चीज़ें छोटी और कोड के पास रखें:
server/internal/service/contacts_service_test.go उन नियमों के लिए जैसे “tag नाम एक contact पर यूनिक होने चाहिए”server/internal/repo/testdata/ न्यूनतम फिक्स्चर के लिएweb/src/components/__tests__/ContactForm.test.tsx फॉर्म व्यवहार के लिएअगर आप इसे Koder.ai से जेनरेट कर रहे हैं, तो वही नियम एक्सपोर्ट के बाद भी लागू होते हैं: फ़ोल्डर्स बोरिंग रखें, नाम लैटरल रखें, और एडिट्स पुरातत्व की तरह नहीं लगें।
जनित कोड पहले दिन साफ़ दिख सकता है और फिर भी बाद में महंगा हो सकता है। सामान्य कारण “खराब कोड” नहीं, असंगति है।
एक महँगी आदत यह है कि जनरेटर हर बार संरचना गढ़ने दे। एक फीचर अपनी ही फ़ोल्डर्स, नामकरण शैली, और हेल्पर फ़ंक्शन्स के साथ आता है, और आपके पास वही काम करने के तीन तरीके रह जाते हैं। एक पैटर्न चुनें, उसे लिखें, और किसी भी नए पैटर्न को एक सचेत परिवर्तन मानें, डिफ़ॉल्ट नहीं।
एक और जाल लेयर्स को मिलाना है। जब UI कम्पोनेंट डेटाबेस से बात करना शुरू कर देती है, या API हैंडलर SQL बनाता है, छोटे बदलाव पूरे ऐप में जोखिमभरे संपादनों में बदल जाते हैं। सीमा रखें: UI API को कॉल करे, API सर्विस को कॉल करे, सर्विस डेटा एक्सेस को।
बहुत जल्दी जनरल एब्स्ट्रैक्शन्स का उपयोग भी लागत बढ़ाता है। एक यूनिवर्सल “BaseService” या “Repository” फ्रेमवर्क अच्छा लग सकता है, पर शुरुआती एब्स्ट्रैक्शन्स अनुमान होते हैं। जब वास्तविकता बदलेगी, आप अपने ही फ्रेमवर्क के खिलाफ़ लड़ेंगे बजाय शिप करने के।
लगातार रिनेमिंग और पुनर्गठन एक धीमी‑धीर प्रकार का डेट है। अगर फ़ाइलें हर हफ्ते मूव होती हैं, लोग लेआउट पर भरोसा करना बंद कर देते हैं और तेज़ फिक्सेस यादृच्छिक जगहों पर आते हैं। पहले फ़ोल्डर मैप को स्थिर करें, फिर योजनाबद्ध टुकड़ों में रिफ़ैक्टर करें।
अंत में, “प्लेटफ़ॉर्म कोड” के साथ सावधान रहें जिसका कोई असली उपयोगकर्ता नहीं है। शेयर लाइब्रेरीज़ और होमग्रोन टूलिंग तभी भुगतान करती हैं जब आपकी बार‑बार साबित हुई ज़रूरतें हों। तब तक, डिफ़ॉल्ट्स सीधे रखें।
अगर कोई नया व्यक्ति रेपो खोलता है, तो उसे एक सवाल का तेज़ जवाब मिलना चाहिए: “मैं इसे कहाँ जोड़ूँ?”
प्रोजेक्ट को एक टीममेट (या भविष्य का आप) को दें और उनसे कहें कि एक छोटा फीचर जोड़ें, जैसे “signup फॉर्म में एक फ़ील्ड जोड़ें।” अगर वे सही स्थान जल्दी नहीं ढूँढ पाते, तो संरचना अपना काम नहीं कर रही।
तीन स्पष्ट घरों की जाँच करें:
अगर आपकी प्लेटफ़ॉर्म इसे सपोर्ट करती है, तो रोलबैक पाथ रखें। संरचना के साथ एक्सपेरिमेंट करने पर स्नैपशॉट्स और रोलबैक विशेष रूप से उपयोगी होते हैं।
मेंटेनबिलिटी तब सबसे तेज़ी से सुधरती है जब आप शैली पर बहस करना बंद कर दें और कुछ निर्णय लें जो टिकें।
फाइलों का स्थान, नामकरण, और त्रुटि‑कन्फिग कैसे हैं—इन पर एक छोटा सेट लिखें जो रोज़ के हिचक को हटाता है। इसे एक मिनट में पढ़ा जा सके इतना छोटा रखें।
फिर उन नियमों से मिलाने के लिए एक सफाई पास करें और साप्ताहिक रूप से फ़ाइलें फिर से न घुमाएँ। बार‑बार पुनर्गठन अगला बदलाव धीमा कर देता है, भले ही कोड सुंदर दिखे।
अगर आप Koder.ai (koder.ai) के साथ बना रहे हैं, तो इन कन्वेंशन्स को एक स्टार्टिंग प्रॉम्प्ट के रूप में सेव करने में मदद मिलती है ताकि हर नई जेनरेशन एक ही संरचना में उतरे। टूल तेज़ी से मूव कर सकता है, पर वही बोरिंग सीमाएँ कोड को बदलने में आसानी देती हैं।