ChatGPT, GitHub Copilot, Cursor ಮತ್ತು ಅವುಗಳ ಸಮಾನಾಂತರ ಪರಿಕರಗಳು ನೀವು ಪ್ರಾಂಪ್ಟ್ ಟೈಪ್ ಮಾಡುವ ಮೊದಲೇ ಈಗ ಒಂದು React component ಅನ್ನು ನೀಡಬಲ್ಲವು. Next.js route ಅನ್ನು Supabase ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಬೇಕೆ? ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮುಗಿದುಹೋಗುತ್ತದೆ. ಆ ಗೊಂದಲಮಯ TypeScript utility ಅನ್ನು refactor ಮಾಡಬೇಕೆ? ಇಲ್ಲಿ type guards ಒಳಗೊಂಡ ಮೂರು ಆಯ್ಕೆಗಳಿವೆ. ಆಧುನಿಕ web stacks ನಲ್ಲಿ ಕೆಲಸ ಮಾಡುವ ಯಾರಿಗಾದರೂ, ಈ ಅನುಭವವು ಮಾಂತ್ರಿಕತೆಯಂತೆ ಭಾಸವಾಗಬಹುದು.

ನಾನು ಈ ಪರಿಕರಗಳನ್ನು ಪ್ರತಿದಿನ ಬಳಸುತ್ತೇನೆ. ನನ್ನ stack Next.js, TypeScript ಮತ್ತು Supabase ಆಗಿದೆ, ಮತ್ತು AI ನನ್ನ ಎಡಿಟರ್‌ನಲ್ಲೇ ಇರುತ್ತದೆ, custom hooks ರಚಿಸಲು, database queries ಜನರೇಟ್ ಮಾಡಲು ಅಥವಾ ಗೊಂದಲಮಯ conditional logic ಅನ್ನು ಸರಿಪಡಿಸಲು ಸಿದ್ಧವಾಗಿರುತ್ತದೆ. ಸಣ್ಣ ಮಟ್ಟದಲ್ಲಿ, ಇದು ಅತ್ಯಂತ ವೇಗವಾದ junior developer ನಂತೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ಇದು syntax ಅನ್ನು ಅಚ್ಚುಕಟ್ಟಾಗಿ ಬಲ್ಲದು. ನಾನು Google ಮಾಡಬೇಕಾದ API surface areas ಅನ್ನು ಇದು ನೆನಪಿಟ್ಟುಕೊಳ್ಳುತ್ತದೆ. Boilerplate ಬರೆಯಲು ಇದು ಎಂದಿಗೂ ಸುಸ್ತಾಗುವುದಿಲ್ಲ.

ಆದರೆ ಸಾಫ್ಟ್‌ವೇರ್ ಪದೇ ಪದೇ ಮುರಿದುಬೀಳುತ್ತಿದೆ. ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ನಿಧಾನವಾಗುತ್ತಿವೆ. ಗ್ರಾಹಕರ ಡ್ಯಾಶ್‌ಬೋರ್ಡ್‌ಗಳು ಲಾಗ್ ಆಗುತ್ತಿವೆ. Edge cases ಫಾರ್ಮ್‌ಗಳನ್ನು ಕ್ರ್ಯಾಶ್ ಮಾಡುತ್ತಿವೆ. AI ಕೋಡಿಂಗ್ ಅನ್ನು ಇಷ್ಟು ಸುಲಭವಾಗಿಸಿದರೆ, ಸಾಫ್ಟ್‌ವೇರ್ ಬಳಸುವುದು ಕೆಲವು ವರ್ಷಗಳ ಹಿಂದಿಗಿಂತ ಈಗ ಯಾಕೆ ಕೆಟ್ಟದಾಗಿ ಅನಿಸುತ್ತಿದೆ?

ಉತ್ತರವೆಂದರೆ, syntax ಜನರೇಟ್ ಮಾಡುವುದು ಮತ್ತು ಸಾಫ್ಟ್‌ವೇರ್ ನಿರ್ಮಿಸುವುದು ಒಂದೇ ಕೆಲಸವಲ್ಲ.

Syntax ಎಂಬುದು Architecture ಅಲ್ಲ

AI ಟೋಕನ್‌ಗಳನ್ನು (tokens) ಅದ್ಭುತವಾಗಿ ನಿರ್ವಹಿಸುತ್ತದೆ. Supabase real-time channel ಅನ್ನು ಗಮನಿಸುವ useEffect hook ಬರೆಯಲು ನೀವು ಕೇಳಿದರೆ, ಅದು compile ಆಗುವಂತಹದ್ದನ್ನು ನೀಡುತ್ತದೆ. ನೀವು ಕಾಫಿ ಕುಡಿಯುವ ಮೊದಲೇ, ಇದು untyped JavaScript ಫೈಲ್ ಅನ್ನು strict TypeScript ಗೆ ಪರಿವರ್ತಿಸಬಹುದು ಅಥವಾ Zod validation ಹೊಂದಿರುವ form component ಅನ್ನು ಸಿದ್ಧಪಡಿಸಬಹುದು.

ಆದರೆ ನಿಮ್ಮ ನಿರ್ದಿಷ್ಟ ಅಪ್ಲಿಕೇಶನ್‌ನ ಸ್ವರೂಪವನ್ನು (contours) ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಇದಕ್ಕೆ ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ. ಉತ್ತಮ ಸಾಫ್ಟ್‌ವೇರ್‌ಗೆ ಉದ್ದೇಶಪೂರ್ವಕ state management, race conditions ಗಳ ಎಚ್ಚರಿಕೆಯ ನಿರ್ವಹಣೆ ಮತ್ತು ಡೇಟಾ ಎಲ್ಲಿ ಸಂಗ್ರಹವಾಗಿದೆ ಮತ್ತು ಎಲ್ಲಿ ಕೇವಲ ಪ್ರದರ್ಶನಕ್ಕಿದೆ ಎಂಬ ಸ್ಪಷ್ಟ ನಕ್ಷೆ ಬೇಕಾಗುತ್ತದೆ. AI ಕೇವಲ ತಕ್ಷಣದ ಫೈಲ್ ಅನ್ನು ನೋಡುತ್ತದೆಯೇ ಹೊರತು ಇಡೀ ಸಿಸ್ಟಮ್ ಅನ್ನು ಅಲ್ಲ. ಇದು ನಿಮ್ಮ codebase ಅನ್ನು ತೂಕವನ್ನು ಹೊರಲು ಗೋಡೆಗಳಿರುವ ಜೀವಂತ ರಚನೆಯಂತೆ ನೋಡದೆ, ಕೇವಲ ಒಂದು ಸಮತಟ್ಟಾದ ಪಠ್ಯದ ಕಾರಿಡಾರ್‌ನಂತೆ ಪರಿಗಣಿಸುತ್ತದೆ.

ಇದನ್ನು ಎಂದಿಗೂ ಮನೆಯಲ್ಲಿ ವಾಸಿಸದ ಒಬ್ಬ ವಾಸ್ತುಶಿಲ್ಪಿಯಂತೆ (architect) ಭಾವಿಸಿ. ಅವರು ಸುಂದರವಾದ ಫ್ಲೋರ್ ಪ್ಲಾನ್‌ಗಳನ್ನು ಬಿಡಿಸಬಹುದು. ಬೆಡ್‌ರೂಮ್‌ಗೆ ಎಷ್ಟು ಕಿಟಕಿಗಳಿರಬೇಕು ಎಂಬುದು ಅವರಿಗೆ ತಿಳಿದಿರುತ್ತದೆ. ಆದರೆ ಫೆಬ್ರವರಿಯಲ್ಲಿ ಪೈಪ್‌ಗಳು ಎಲ್ಲಿ ಸೋರಿಕೆಯಾಗಬಹುದು ಅಥವಾ ಬೇಸಿಗೆಯ ಬಿಸಿಲಿನಲ್ಲಿ ಯಾವ ಕಾರಿಡಾರ್ ಬಳಕೆಗೆ ಬರುವುದಿಲ್ಲ ಎಂಬುದು ಅವರಿಗೆ ತಿಳಿದಿರುವುದಿಲ್ಲ. ಆ ಅನುಭವದ ಜ್ಞಾನವೇ ಕಟ್ಟಡವನ್ನು ಸ್ಥಿರವಾಗಿ ಇರಿಸುತ್ತದೆ. ಕೋಡ್ ಕೂಡ ಅದೇ ರೀತಿ ಕೆಲಸ ಮಾಡುತ್ತದೆ.

ಎರಡು ಘರ್ಷಣಾ ಬಿಂದುಗಳು

ಕಟ್ಟುನಿಟ್ಟಾದ ನಿಯಮಗಳಿಲ್ಲದೆ (guardrails) AI ಅನ್ನು ದೊಡ್ಡ ಪ್ರಮಾಣದ ಕೋಡ್ ಬರೆಯಲು ಬಿಟ್ಟಾಗ, ಒಂದೇ ರೀತಿಯ ಎರಡು ಸಮಸ್ಯೆಗಳು ಪದೇ ಪದೇ ಎದುರಾಗುತ್ತಿರುವುದನ್ನು ನಾನು ಗಮನಿಸುತ್ತೇನೆ.

ಮೊದಲನೆಯದಾಗಿ, ನೀವು ಈಗಾಗಲೇ ಸ್ಥಾಪಿಸಿರುವ design patterns ಅನ್ನು ಇದು ನಿರ್ಲಕ್ಷಿಸುತ್ತದೆ. ಬಹುಶಃ ನಿಮ್ಮ ತಂಡವು ಎಲ್ಲಾ data fetching ಅನ್ನು custom hooks ನ ಪ್ರತ್ಯೇಕ ಲೇಯರ್‌ಗೆ ವರ್ಗಾಯಿಸಿರಬಹುದು. ಅಥವಾ Supabase RLS policies ಹೇಗೆ frontend helpers ಗೆ ಹೊಂದಿಕೆಯಾಗಬೇಕು ಎಂಬ ಕಟ್ಟುನಿಟ್ಟಿನ ನಿಯಮವಿದ್ದಿರಬಹುದು. AI ಗೆ ಇದರ ಬಗ್ಗೆ ಕಾಳಜಿಯಿಲ್ಲ. ತಕ್ಷಣದ ಪ್ರಾಂಪ್ಟ್ ಅನ್ನು ಇದು ಪರಿಹರಿಸಿದರೆ, ಅದು ಬಟನ್‌ನ onClick ಒಳಗೆ ನೇರವಾಗಿ ಒಂದು raw supabase.from().select() ಅನ್ನು ಹಾಕಿಬಿಡುತ್ತದೆ. ಕೋಡ್ ರನ್ ಆಗುತ್ತದೆ. ಅದು ನೋಡಲು ಸ್ವಚ್ಛವಾಗಿಯೂ ಕಾಣುತ್ತದೆ. ಆದರೆ ಅದು ನಿಮ್ಮ codebase ನಲ್ಲಿ ಒಂದು ವ್ಯತ್ಯಯ (outlier), ಮತ್ತು ಪ್ರತಿಯೊಂದು ವ್ಯತ್ಯಯವೂ ಭವಿಷ್ಯದ refactoring ತೆರಿಗೆಯಂತಿದೆ. ಆರು ತಿಂಗಳ ನಂತರ, ಯಾರಾದರೂ ಆ ಸೂಜಿಯನ್ನು ಹುಡುಕಬೇಕು, ಅದು ಏಕೆ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ ಎಂದು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಬೇಕು ಮತ್ತು ಅದನ್ನು ಮತ್ತೆ ಸರಿಯಾದ ಕ್ರಮಕ್ಕೆ ತರಬೇಕು.

ಎರಡನೆಯದಾಗಿ, ಸರಳತೆಯೇ ಸಾಕಾಗುವ ಜಾಗದಲ್ಲಿ ಇದು ಸಂಕೀರ್ಣತೆಯನ್ನು ತರುತ್ತದೆ. ಈ ಪರಿಕರವನ್ನು abstract factories, ಸಂಕೀರ್ಣ reducer patterns ಮತ್ತು ಬಹು-ಪದರಗಳ higher-order components ಅಗತ್ಯವಿರುವ ದೊಡ್ಡ ರೆಪೊಸಿಟರಿಗಳ ಮೇಲೆ ತರಬೇತಿಗೊಳಿಸಲಾಗಿದೆ. ನೀವು ಒಂದು ಸರಳ contact form ಅನ್ನು ನಿರ್ಮಿಸಲು ಕೇಳಿದಾಗ, ಅದು ನಿಮಗೆ ಒಂದು state machine, context provider ಮತ್ತು ಮೂರು ಫೈಲ್‌ಗಳವರೆಗೆ ಹರಡಿರುವ ಒಂದು custom hook abstraction ಅನ್ನು ನೀಡಬಹುದು. ಈ ಪರಿಹಾರವು ತಾಂತ್ರಿಕವಾಗಿ ತಪ್ಪಲ್ಲ. ಆದರೆ ಅದು ತುಂಬಾ ಭಾರವಾಗಿದೆ. ಪ್ರತಿಯೊಂದು ಅನಗತ್ಯ ಪದರವು cognitive debt ಅನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ. ನೀವು ಕೆಲಸವನ್ನು ಬಿಟ್ಟುಬಿಟ್ಟಿಲ್ಲ; ಬದಲಾಗಿ ಬಡ್ಡಿಯೊಂದಿಗೆ ಅದನ್ನು ಮುಂದೂಡಿದ್ದೀರಿ ಅಷ್ಟೆ.

ವೇಗತೆಯ ಬಲೆ

ಇಲ್ಲಿ ಒಂದು ಅಪಾಯಕಾರಿ ಫೀಡ್‌ಬ್ಯಾಕ್ ಲೂಪ್ ಇದೆ. AI ನಿಮಗೆ ಫೀಚರ್‌ಗಳನ್ನು ಎರಡರಷ್ಟು ವೇಗವಾಗಿ ನಿರ್ಮಿಸಲು ಅನುಮತಿಸುತ್ತದೆ, ಆದರೆ ಮಾನವನ ಗಮನವು ಅದೇ ರೀತಿಯಲ್ಲಿ ಬೆಳೆಯುವುದಿಲ್ಲ. ನೀವು ಅರ್ಧದಷ್ಟು ಸಮಯದಲ್ಲಿ ಕೆಲಸವನ್ನು ಪೂರ್ಣಗೊಳಿಸುತ್ತಿದ್ದರೆ, ಕೋಡ್ ರಿವ್ಯೂ (code review) ಮಾಡಲು ನೀವು ಎರಡರಷ್ಟು ಸಮಯವನ್ನು ವ್ಯಯಿಸುತ್ತಿದ್ದೀರಾ? ನೀವು ಹೆಚ್ಚು ಟೆಸ್ಟ್‌ಗಳನ್ನು ಬರೆಯುತ್ತಿದ್ದೀರಾ ಅಥವಾ ಕಡಿಮೆ ಬರೆಯುತ್ತಿದ್ದೀರಾ?

ಪ್ರಾಯೋಗಿಕವಾಗಿ, ಜನರೇಟ್ ಮಾಡಿದ ಕೋಡ್ ಅನ್ನು ನಂಬುವುದು ತುಂಬಾ ಸುಲಭ, ಏಕೆಂದರೆ ಅದು ಅಧಿಕೃತವಾಗಿ ಕಾಣುತ್ತದೆ. ಅದು ಆಧುನಿಕ syntax ಅನ್ನು ಬಳಸುತ್ತದೆ. ಸರಿಯಾದ ಸ್ಥಳಗಳಲ್ಲಿ ಕಾಮೆಂಟ್‌ಗಳು (comments) ಇರುತ್ತವೆ. ವೇರಿಯೇಬಲ್ ಹೆಸರುಗಳು ವೃತ್ತಿಪರವಾಗಿರುತ್ತವೆ. ಆ ಹೊಳಪಿನ ಅಡಿಯಲ್ಲಿ ಸೂಕ್ಷ್ಮ ದೋಷಗಳು (subtle bugs) ಅಡಗಿರುತ್ತವೆ. ಒಂದು hook ನಲ್ಲಿ setter ಅನ್ನು ಬಿಟ್ಟುಹೋದ dependency array. ತಾಂತ್ರಿಕವಾಗಿ ಸರಿಯಾದ ಆದರೆ ನೀವು ನಿರ್ಲಕ್ಷಿಸಿದ null state ಅನ್ನು ಅನುಮತಿಸುವ TypeScript type. ನಿಮ್ಮ ನಿರ್ದಿಷ್ಟ schema ನಲ್ಲಿ soft-deleted ಸಾಲುಗಳನ್ನು ಪರಿಗಣಿಸಲು ಮರೆತ Supabase query. ವಿತರಣೆಯ ವೇಗವು ಅದನ್ನು ಬಯಸುವುದರಿಂದ, ನೀವು ಪ್ರತಿ ಸಾಲನ್ನು ಓದುವ ಬದಲು ಮೇಲ್ನೋಟಕ್ಕೆ ನೋಡುತ್ತೀರಿ. ಸೋಮವಾರ ಆ ವೇಗವು ಅದ್ಭುತವಾಗಿ ಕಾಣುತ್ತದೆ. ಆದರೆ ಶುಕ್ರವಾರದ ಡಿಬಗ್ಗಿಂಗ್ (debugging) ಸೆಷನ್ ಮಧ್ಯರಾತ್ರಿಯವರೆಗೆ ನಡೆಯುತ್ತದೆ.

ನಿಜವಾದ ವೆಚ್ಚ

ಇದಕ್ಕೆ ಬೆಲೆ ತೆರುವವರು ಡೆವಲಪರ್‌ಗಳಲ್ಲ. ಅವರು ಅಂತಿಮ ಬಳಕೆದಾರರು (end users).

Software feels clunkier because complexity is growing faster than teams can steward it. We are building bigger applications with smaller crews, armed with tools that make us feel invincible. When one developer can scaffold an entire dashboard in an afternoon, the organization expects three dashboards by Wednesday. Scale without care produces fragile systems. State balloons. Bundle sizes creep up. Race conditions multiply. The interface might look modern, but it resets itself when a user hits the back button, or it takes four seconds to hydrate because nobody had time to profile the waterfall of AI-generated data fetches.

Work With the Machine, Not For It

None of this means you should throw AI out of your editor. It means you need boundaries.

Use it for what it is good at. Let it write the dull stuff: repetitive TypeScript interfaces, boilerplate Supabase queries, Jest setup