4.5.19 · Coding › Software Engineering
Refactoring ka matlab hai code ki internal structure ko badalna bina us cheez ko badle jo woh bahar se karta hai . Aap behaviour bilkul wahi rakhte ho (same inputs → same outputs) lekin code ko padhna, badalna, aur extend karna aasaan banate ho. Socho: ek messy room ko tidy karna bina kuch phenke .
Code ki ek disciplined, behaviour-preserving transformation jo uski internal quality (readability, structure, maintainability) improve karti hai bina uske external behaviour ko badle.
Key word: behaviour-preserving . Agar observable output badal jaaye, toh woh refactoring nahi hai — woh editing/bug-fixing/feature work hai.
Code mein ek ==surface symptom jo ek deeper design problem suggest karta hai==. Smell koi bug nahi hai; code perfectly kaam kar sakta hai. Yeh ek hint hai ki refactoring help kar sakti hai. ("Smell" isliye kyunki aap isse notice karte ho real rot samajhne se pehle.)
WHY 1 — Cost of change: Software likhe jaane se ~10x zyada padhha jaata hai. Messy code har future change ko slower aur riskier banata hai.
WHY 2 — Compounding: Chhoti chhoti gandi cheezein milke "technical debt" ban jaati hain. Refactoring us debt ko chukane ka kaam karti hai interest (bugs, slowdowns) ke tumhe dabaane se pehle.
WHY 3 — Safety: Ek clean structure bugs ko visible aur changes ko local banata hai.
Intuition "Behaviour-preserving" iska dil kyun hai
Agar aap structure aur behaviour ek saath badlo aur koi test fail ho jaaye, toh aap nahi bata sakte ki kaun si change ne ise toda. Behaviour fixed rakhna refactoring ko ek controlled experiment banata hai: koi bhi failing test seedha tumhari refactoring ki galti dikhata hai.
Golden rule: tests ke bina kabhi refactor mat karo .
Ensure karo ki ek passing test suite code ko cover karti hai.
Ek chhoti si change karo.
Tests run karo. Green? Rakho. Red? Turant undo karo.
Commit karo.
Repeat karo.
Definition Smell catalogue (the 80/20 set)
==Long Method == — ek function jo bahut zyada kaam kar raha hai; ek screen mein padhna mushkil.
==Duplicated Code == — same logic copy-paste ki gayi; ek jagah fix karo doosri bhool jaao wale bugs.
==Large Class / God Object == — ek class bahut saari responsibilities hoarding kar rahi hai.
==Long Parameter List == — bahut zyada args; sahi se call karna mushkil.
==Magic Numbers == — 0.0825 jaise unexplained literals idhar udhar bikhre hue.
==Feature Envy == — ek method apni class ke data se zyada doosri class ke data mein interested hai.
==Data Clumps == — variables ka ek hi group har jagah saath saath travel karta hai.
==Shotgun Surgery == — ek change kai jagahon par edits karne par majboor karti hai.
==Comments (as deodorant) == — comments jo buri code ko fix karne ki jagah explain karte hain.
Definition Extract Method
Code ka ek fragment lo jo group kiya ja sake, use apne well-named method mein move karo , aur use call karo.
Worked example Extract Method
Before:
def print_invoice (order):
print ( "=== Invoice ===" )
total = 0
for item in order.items:
total += item.price * item.qty # tax-free subtotal
total *= 1.0825 # add 8.25% tax
print ( f "Total: $ { total :.2f } " )
After:
TAX_RATE = 0.0825 # also fixes Magic Number smell
def compute_total (order):
subtotal = sum (item.price * item.qty for item in order.items)
return subtotal * ( 1 + TAX_RATE )
def print_invoice (order):
print ( "=== Invoice ===" )
print ( f "Total: $ { compute_total(order) :.2f } " )
Yeh step kyun? Tax/total logic ek self-contained idea hai. Isko ek naam dena (compute_total) reader ko print_invoice ek nazar mein samajhne deta hai, aur ab compute_total reusable aur independently testable hai. Behaviour unchanged hai — same number print hota hai.
Ek poorly-named identifier ko aisa naam do jo intent reveal kare . Sabse sasta, sabse zyada value wala refactoring.
def calc(a, b): return a*b*r → def line_total(price, qty): return price * qty * TAX_RATE
Yeh step kyun? calc, a, b reader ko meaning reconstruct karne par majboor karte hain. Acche naam documentation hain jo kabhi stale nahi hote.
if (user.age >= 18 ) and (user.country in ALLOWED ) and user.verified:
...
→
is_adult = user.age >= 18
region_ok = user.country in ALLOWED
can_purchase = is_adult and region_ok and user.verified
if can_purchase:
...
Yeh step kyun? Ek tangled boolean ke andar ke concepts ko naam deta hai. Same truth value, kaafi zyada clear.
circumference = 2 * 3.14159 * r → PI = 3.14159; circumference = 2 * PI * r
Yeh step kyun? Truth ka ek hi source; literal ka meaning explicit ho jaata hai.
Worked example Data clump → object
validate(x1, y1, x2, y2) har jagah repeat hota hai → ek Point(x, y) introduce karo aur Point objects pass karo.
Yeh step kyun? Chaar coordinates secretly do points the. Us structure ko naam dena clump aur long parameter list dono ek saath hata deta hai.
Common mistake Galat ideas ko steel-man karna
Galat idea A: "Refactoring ka matlab hai feature add karte waqt ise better rewrite karna."
Kyun sahi lagta hai: tum already file mein ho, toh improve kyun nahi karo? Fix: hats alag rako — refactor (behaviour-preserving) aur add-feature (behaviour-changing) alag commits mein. Milana failures ko un-diagnosable banata hai. Kent Beck: "Pehle change ko easy banao, phir easy change karo."
Galat idea B: "Comments buri code ko theek kar dete hain."
Kyun sahi lagta hai: comment sach mein mess explain karta hai. Fix: ek comment jo batata hai code kya karta hai woh aksar ek smell hai — ek method extract karo jiska naam yeh bataye. Comments kyun ke liye rako, kya ke liye nahi.
Galat idea C: "Main tests ke bina refactor karoonga; main careful hoon."
Kyun sahi lagta hai: change trivially safe lagta hai. Fix: "trivial" refactors silently ek <= ko < mein flip kar dete hain ya side effects ko reorder kar dete hain. Tests ke bina tumhare paas koi proof nahi ki behaviour preserve hua — aur woh proof hi definition hai .
Galat idea D: "Zyada, chhote methods hamesha better hote hain."
Kyun sahi lagta hai: small = clean. Fix: over-extraction "shotgun" indirection create karta hai jahan ek idea follow karne ke liye 8 files mein bounce karna padta hai. Tab extract karo jab yeh ek concept ko naam de , sirf line count kaat ne ke liye nahi.
Recall Feynman: ek 12-saal-ke-bachche ko samjhao
Socho tumhara LEGO castle bahut acchi tarah kaam karta hai, lekin andar se ek tangled mess hai — bricks random jagahon par thuse hue hain. Refactoring bricks ko carefully rearrange karna hai taaki castle bahar se bilkul waise hi dikhe , lekin andar se neat ho aur baad mein ek naya tower add karna aasaan ho. Tum ek baar mein ek brick move karte ho aur har move ke baad check karte ho ki castle abhi bhi khada hai (woh checks "tests" hain). Ek code smell ek ajeeb wobble jaisi hai jo tumhe warn karti hai ki andar kuch messy hai — chahe castle abhi gira nahi ho.
Mnemonic Workflow yaad rakho:
"Red room? CRT it."
C over with tests → R efactor one tiny step → T est (green rakho, red revert karo).
Aur kab refactor karna hai: "Rule of Three" — code ek baar copy karo = theek hai, do baar = winch karo, teesri baar = refactor karo .
Refactoring ki defining property kya hai? Yeh behaviour-preserving hai — external behaviour wahi rehta hai jabki internal structure improve hoti hai.
Code smell kya hota hai (aur kya yeh bug hai)? Ek surface symptom jo deeper design problem hint karta hai; BUG NAHI hai — code theek kaam kar sakta hai.
Refactor karne se pehle passing tests kyun hone chahiye? Tests behaviour ki tumhari proxy hain; unke bina tum prove nahi kar sakte ki change ne behaviour preserve kiya, jo refactoring ki definition hi hai.
Refactoring safety loop batao. Tests se cover karo → ek chhoti si change karo → tests run karo → green rakho / red revert karo → commit karo → repeat karo.
Extract Method mainly kaun sa smell fix karta hai? Long Method (aur reuse / independent testing enable karta hai).
Rename ko cheap hote hue bhi high-value kyun maana jaata hai? Acche naam intent reveal karte hain aur documentation ki tarah kaam karte hain jo kabhi stale nahi hoti.
Yeh smell bolo: variables ka ek group hamesha saath pass hota hai. Data Clumps (fix: Extract Class / ek object introduce karo).
Yeh smell bolo: ek change kai files mein edits karne par majboor karti hai. Shotgun Surgery.
Refactoring aur feature changes ko alag commits mein kyun rakhna chahiye? Taaki ek failing test unambiguously ek tarah ki change ko point kare; milana failures ko undiagnosable banata hai.
Duplication ke liye Rule of Three kya hai? Ek baar duplicate karna theek hai, do baar winch karo; teesre occurrence par refactor karo duplication hatane ke liye.
Feature Envy kya hai? Ek method jo apni class ke data se zyada doosri class ka data use karta hai — use data ke paas move karo.
Replace Magic Number with Named Constant se kya milta hai? Truth ka single source aur ek otherwise unexplained literal ka explicit meaning.
Unit Testing — woh safety net jo refactoring ko enable karti hai.
Technical Debt — jo refactoring chukati hai.
Clean Code / Naming Conventions — Rename & Extract ke peeche ke principles.
Design Patterns — refactorings aksar ek pattern ki taraf hoti hain.
Cyclomatic Complexity — ek metric jo Long Method / God Object smells flag karta hai.
DRY Principle — seedha Duplicated Code hatane ki motivation deta hai.
Single Responsibility Principle — God Object / Large Class ka ilaaj.