refactoring_before.py

Download
python 304 lines 8.9 KB
  1"""
  2BAD CODE EXAMPLE - Before Refactoring
  3
  4This code DELIBERATELY violates clean code principles:
  51. Long, complex functions (God functions)
  62. Magic numbers everywhere
  73. Poor naming (abbreviations, unclear names)
  84. God class (does too much)
  95. No separation of concerns
 106. Tight coupling
 117. No error handling
 128. Deep nesting
 139. Code duplication
 14
 15DO NOT use this code as a reference!
 16This is the "before" example for refactoring.
 17"""
 18
 19
 20# ❌ God class - does everything!
 21class UsrMgr:
 22    """Terrible class name and does way too much"""
 23
 24    def __init__(self):
 25        self.usrs = []  # Bad name
 26        self.cnt = 0  # What is cnt?
 27        self.x = 100  # What is x?
 28
 29    # ❌ Long function with magic numbers and deep nesting
 30    def p(self, n, e, a, s):  # Terrible parameter names!
 31        """What does 'p' mean? Process? Print? ???"""
 32
 33        # Magic number! What is 18?
 34        if a < 18:
 35            print("too young")
 36            return False
 37
 38        # What is 150000?
 39        if s < 150000:
 40            # Deep nesting starts here
 41            if len(n) < 2:
 42                print("bad name")
 43                return False
 44            else:
 45                if "@" not in e:
 46                    print("bad email")
 47                    return False
 48                else:
 49                    # More nesting!
 50                    if len(self.usrs) > 0:
 51                        for u in self.usrs:
 52                            if u["e"] == e:  # Duplicate email check
 53                                print("dup email")
 54                                return False
 55                    # Finally add user (buried deep in nesting!)
 56                    self.usrs.append({"n": n, "e": e, "a": a, "s": s})
 57                    self.cnt += 1
 58                    return True
 59        else:
 60            # Code duplication! Same validation as above
 61            if len(n) < 2:
 62                print("bad name")
 63                return False
 64            else:
 65                if "@" not in e:
 66                    print("bad email")
 67                    return False
 68                else:
 69                    if len(self.usrs) > 0:
 70                        for u in self.usrs:
 71                            if u["e"] == e:
 72                                print("dup email")
 73                                return False
 74                    # Different logic based on salary - but duplicated validation!
 75                    self.usrs.append({"n": n, "e": e, "a": a, "s": s, "pr": True})
 76                    self.cnt += 1
 77                    # Magic number 1.2!
 78                    self.x = self.x * 1.2
 79                    return True
 80
 81    # ❌ Does too much, magic numbers, no separation of concerns
 82    def calc(self):
 83        """Calculate what? Naming is unclear"""
 84        t = 0  # What is t?
 85        for u in self.usrs:
 86            # Magic numbers: 0.1, 0.15, 0.2
 87            if u["s"] < 50000:
 88                t += u["s"] * 0.1
 89            elif u["s"] < 100000:
 90                t += u["s"] * 0.15
 91            elif u["s"] < 150000:
 92                t += u["s"] * 0.2
 93            else:
 94                # More magic numbers!
 95                t += u["s"] * 0.25 + 5000
 96
 97        # What are these conditions?
 98        if len(self.usrs) > 10 and self.cnt > 5:
 99            t *= 1.1
100
101        # Magic number 0.3
102        if t > 100000:
103            t -= t * 0.3
104
105        return t
106
107    # ❌ Another long function with unclear purpose
108    def g(self, e):
109        """Get what? User? Data? Unclear name"""
110        for u in self.usrs:
111            if u["e"] == e:
112                # Direct data access - no encapsulation
113                return u
114        return None
115
116    # ❌ Function that modifies global state unpredictably
117    def upd(self, e, **kwargs):
118        """Update - but what can be updated? No validation!"""
119        u = self.g(e)
120        if u:
121            # Direct modification without validation!
122            for k, v in kwargs.items():
123                u[k] = v
124            return True
125        return False
126
127    # ❌ Complex logic with no error handling
128    def del_usr(self, e):
129        """Only good name in this class!"""
130        for i, u in enumerate(self.usrs):
131            if u["e"] == e:
132                # What if user doesn't exist? No error handling!
133                self.usrs.pop(i)
134                self.cnt -= 1
135                # Forgot to update self.x! Bug!
136                return True
137        return False
138
139
140# ❌ Function with magic numbers and unclear purpose
141def process_data(d):
142    """What data? What processing? Unclear name and purpose"""
143    r = []
144    for item in d:
145        # Magic number 5
146        if item > 5:
147            # Magic numbers 2 and 10
148            r.append(item * 2 + 10)
149        else:
150            # Magic number 3
151            r.append(item * 3)
152    return r
153
154
155# ❌ Global variables! Very bad practice
156total = 0
157count = 0
158flag = False
159
160
161def calculate_something(nums):
162    """What is something? Uses global state!"""
163    global total, count, flag
164
165    for n in nums:
166        # Magic number 100
167        if n > 100:
168            total += n
169            count += 1
170            flag = True
171
172
173# ❌ Long parameter list, unclear purpose
174def do_stuff(a, b, c, d, e, f, g, h):
175    """Too many parameters! What does this do?"""
176    # Magic numbers everywhere!
177    return (a * 2 + b * 3 - c * 0.5 + d / 2 + e * 1.5 - f * 0.8 + g * 2.3 + h / 1.7)
178
179
180# ❌ No error handling, assumes everything works
181def read_and_process(filename):
182    """No error handling for file operations!"""
183    # What if file doesn't exist?
184    f = open(filename, 'r')
185    data = f.read()
186    # What if file isn't properly formatted?
187    lines = data.split('\n')
188    result = []
189    for line in lines:
190        # What if line is empty or malformed?
191        parts = line.split(',')
192        # What if there aren't enough parts?
193        result.append({
194            'name': parts[0],
195            'value': int(parts[1]),  # What if not a number?
196            'category': parts[2]
197        })
198    # File never closed!
199    return result
200
201
202# ❌ Boolean parameter (flag argument) - code smell!
203def get_users(include_inactive):
204    """Boolean parameter makes function do two different things"""
205    users = []
206    # ... get users from somewhere ...
207    if include_inactive:
208        # One behavior
209        return users
210    else:
211        # Different behavior
212        return [u for u in users if u.get('active')]
213
214
215# ❌ Comments explaining bad code instead of fixing it
216def complex_calculation(x, y, z):
217    """Bad code with comments trying to explain it"""
218    # Add x and y
219    temp1 = x + y
220    # Multiply by z
221    temp2 = temp1 * z
222    # Divide by 2 (why? magic number!)
223    temp3 = temp2 / 2
224    # Subtract 10 (why? magic number!)
225    temp4 = temp3 - 10
226    # Multiply by 1.5 (why? magic number!)
227    result = temp4 * 1.5
228    return result
229
230
231# ❌ Demonstration of bad code
232if __name__ == "__main__":
233    print("=" * 70)
234    print("BAD CODE DEMONSTRATION")
235    print("=" * 70)
236    print("\nThis code has many problems:")
237    print("  ✗ Magic numbers everywhere")
238    print("  ✗ Poor naming (abbreviations, single letters)")
239    print("  ✗ God class doing too much")
240    print("  ✗ Deep nesting")
241    print("  ✗ Code duplication")
242    print("  ✗ No error handling")
243    print("  ✗ Global state")
244    print("  ✗ Long parameter lists")
245    print("  ✗ Unclear purpose")
246    print("  ✗ No separation of concerns")
247    print("\nSee refactoring_after.py for the cleaned-up version!")
248
249    # Using the bad code
250    print("\n" + "-" * 70)
251    print("Running bad code example:")
252    print("-" * 70)
253
254    mgr = UsrMgr()
255
256    # These function calls are unclear without looking at implementation!
257    mgr.p("Alice", "alice@example.com", 25, 60000)
258    mgr.p("Bob", "bob@example.com", 30, 180000)
259    mgr.p("Charlie", "charlie@example.com", 15, 0)  # Too young
260
261    print(f"\nTotal users: {mgr.cnt}")
262    print(f"Calculation result: {mgr.calc():.2f}")
263
264    # What does 'g' return? Need to check code!
265    user = mgr.g("alice@example.com")
266    if user:
267        print(f"Found user: {user}")
268
269    # Global state makes this unpredictable
270    calculate_something([50, 150, 200, 30])
271    print(f"\nGlobal total: {total}, count: {count}, flag: {flag}")
272
273    print("\n" + "=" * 70)
274    print("PROBLEMS WITH THIS CODE:")
275    print("=" * 70)
276    print("""
2771. READABILITY
278   • Impossible to understand without deep inspection
279   • Abbreviations hide meaning
280   • Magic numbers have no context
281
2822. MAINTAINABILITY
283   • Hard to modify without breaking things
284   • Code duplication means bugs multiply
285   • Deep nesting is hard to follow
286
2873. TESTABILITY
288   • God class is hard to test
289   • Global state makes tests unreliable
290   • No error handling means tests can't verify error cases
291
2924. EXTENSIBILITY
293   • Tight coupling prevents easy extension
294   • No interfaces or abstractions
295   • Violates SOLID principles
296
2975. RELIABILITY
298   • No error handling
299   • No input validation
300   • Assumes everything works perfectly
301
302NEXT: See refactoring_after.py for the solution!
303""")