← Back to Learning Hub

Lesson 3: Code Review & Enhancement

Improving Your Solutions with Real Code

90 minutes Code Review Enhancement

Today's Focus

We'll review the code you've already written, identify what works well, spot areas for improvement, and enhance your solutions together.

Professional developers spend more time reading and improving code than writing new code.

Lesson Summary

This lesson covers three main parts:

  1. Correcting your code - Fix bugs and logic errors
  2. Improving your code - Add error handling and validation
  3. Testing your code - Verify improvements work correctly

Theory: CIA Triad 5 min

Why Do Bugs Matter?

Before reviewing code, let's understand why quality and security matter through the CIA Triad.

The CIA Triad

Three fundamental principles of secure software design:

1. Confidentiality

Data is only accessible to authorized users. Not directly applicable to today's code, but important for future work with user data.

2. Integrity

Data remains accurate and consistent. Wrong calculations corrupt data integrity.

Example: If a calculation bug returns an incorrect value and that value is stored in a database, you'd have corrupt financial records.

Real-world: An ATM dispensing the wrong amount = integrity failure.

3. Availability

Systems remain accessible and functional when needed. Crashes make systems unavailable.

Example: If a program crashes due to invalid user input, the system becomes unavailable. Users can't complete their transactions.

Real-world: An e-commerce site that crashes during checkout loses sales and customer trust.

Key takeaway: Code quality isn't just about "making it work" - it's about data integrity and system availability. Bugs have real consequences.

Part 1: Library Fee Calculator 20 min

Your Code

Library Fee Calculator
def activity1():
    days = int(input("Please input the number of days overdue: "))

    def calculate_fee(days):
        if (days < 0):
            print("You cannot have a book overdue for negative days")
            fee = 0
            return fee

        elif (days == 0):
            fee = 0
            return fee

        elif(days <= 7):
            fee = days*0.5
            return fee

        elif days > 7 and days < 12:
            fee = days
            return fee

        elif(days > 12):
            fee = 25
            return fee

    fee = calculate_fee(days)
    print(f"Your fee is ${fee}")

What Works Well

  • Nested function structure - good organization
  • Negative day validation
  • Clear variable names
  • F-string formatting for output

Task: Review the code and test it. Can you spot the issues?

Issues Found (Click to Reveal)
Issue #1: Day 12 boundary gap

The condition days > 7 and days < 12 covers days 8-11.

The condition days > 12 covers days 13+.

Day 12 doesn't match either condition, so the function returns None and prints "Your fee is $None".

Fix: Change days < 12 to days <= 12 OR change days > 12 to days >= 12

Issue #2: ValueError on non-numeric input

The line days = int(input("...")) will crash if the user types "abc" or any non-numeric value.

Fix: Add try/except to catch ValueError and handle invalid input.

Fix the Issues

Work together to fix both issues in the code.

Theory: Code Quality Principles 5 min

What Makes Code "Quality"?

Quality code isn't just code that works. It has three key attributes:

1. Readability

Code should be easy to understand for humans, not just computers.

  • Clear variable names (budget vs b)
  • Logical structure and organization
  • Comments where logic isn't obvious

2. Maintainability

Code should be easy to modify and extend in the future.

  • Modular design (functions, not giant blocks)
  • Avoid hardcoding values
  • Consistent patterns throughout

3. Robustness

Code should handle unexpected situations gracefully.

  • Input validation
  • Error handling (try/except)
  • Professional user messages

Key takeaway: Quality code = Readable + Maintainable + Robust. All three matter for professional software.

Part 2: Shop System 20 min

Your Code

Shop System with Discounts
def activity2():
    budget = int(input("How much money: "))
    is_member_input = input("Are you a member? (yes/no): ").strip().lower()
    is_member = is_member_input in ["yes", "y", "true", "t", "1"]
    print("Welcome to the store, below you can see all items inside the store")

    items = {
        'Apple' : [1, "An apple a day keeps the doctor away"],
        'Toothpaste' : [3, "Keep the dentist away"],
        'Toothbrush' : [200, "What are you gonna brush with ur finger?"],
        'Watch' : [50, "Time to get a watch"]
    }

    for key, value in items.items():
        print(f"{key}: {value}")

    purchase = input("Please enter the item you wish to purchase: ")
    cart = items[purchase]

    def calculate_discount(cart, is_member):
        price = cart[0]
        discount = 0

        if(is_member == True):
            if(price >= 100):
                discount = price*0.2
            elif price >= 50 and price < 100:
                discount = price*0.1
            else:
                discount = price*0.05

        if(is_member == False):
            if(price >= 100):
                discount = price*0.1

        return discount
    discount = calculate_discount(cart, is_member)


    def amount(budget, cart, discount):
        price = cart[0]

        if budget >= price - discount:
            budget -= (price - discount)
            print(f"You bought {purchase}")
            print(f"Discount applied: ${discount}")
            print(f"Your new budget is ${budget}")
        else:
            print("You are too poor")
            print(f"you are mising ${price - budget - discount}")
    amount(budget, cart, discount)
activity2()

What Works Well

  • Dictionary structure with prices and descriptions
  • Smart membership detection (handles multiple inputs)
  • Good use of nested functions
  • Tiered discount system
  • Budget tracking

Task: Review the code. What could go wrong? Try to find at least 3 potential issues.

Issues Found (Click to Reveal)
Issue #1: Unhandled KeyError

If the user types "banana" or any item not in the dictionary, the line cart = items[purchase] will crash with a KeyError.

Test it: Type "banana" and see what happens.

Issue #2: Case sensitivity

Items are stored as 'Apple', 'Toothpaste', etc. If a user types "apple" (lowercase), it won't match and will crash.

Fix idea: Convert input to title case or search case-insensitively.

Issue #3: No budget validation

The code accepts budget = int(input("How much money: ")) without validation. User could enter -100.

Issue #4: User message tone

The message "You are too poor" could be more professional: "Insufficient funds" or "You need $X more".

Why it matters: User experience includes how error messages make people feel. Professional software uses respectful, helpful messages.

Issue #5: Single purchase limit

The user can only buy one item, then the program ends. No shopping loop to keep browsing.

Issue #6: ValueError on non-numeric input

What if the user types "abc" as their budget? The program crashes with ValueError.

Theory: Exception Handling 5 min

Understanding Exceptions

When Python encounters an error during runtime, it raises an exception. If not handled, the program crashes.

Common Exception Types

ValueError

Raised when a function receives the right type but wrong value.

Example
days = int("abc")  # ValueError: invalid literal for int()

KeyError

Raised when accessing a dictionary key that doesn't exist.

Example
items = {'Apple': 1}
price = items['Banana']  # KeyError: 'Banana'

TypeError

Raised when an operation is applied to the wrong type.

Example
result = "5" + 10  # TypeError: can't concatenate str and int

try/except Structure

Basic Pattern
try:
    # Code that might raise an exception
    days = int(input("Enter days: "))
except ValueError:
    # Handle the specific error
    print("Please enter a valid number")
    days = 0

Catching Multiple Exceptions

Multiple except blocks
try:
    item = items[user_input]
    price = int(item['price'])
except KeyError:
    print("Item not found")
except ValueError:
    print("Invalid price format")

Key takeaway: Use try/except to catch specific exceptions and handle them gracefully. Don't let your program crash when errors can be anticipated.

Part 3: Code Enhancement 35 min

Choose as many Enhancements as you want to Implement

We'll implement improvements to make your shop system more robust.

Challenge A: Add Error Handling

Handle the case when a user enters an invalid item name.

  • Use try/except to catch KeyError
  • Display friendly error message
  • Show available items
Challenge B: Case Insensitive Search

Allow users to type item names in any case.

  • Convert input to title case
  • Or: search dictionary keys case-insensitively
Challenge C: Shopping Loop

Let users buy multiple items until they choose to stop.

  • Add a while loop
  • Ask "Keep shopping? (yes/no)"
  • Track total spent
Challenge D: Input Validation

Validate the budget input.

  • Ensure budget is positive
  • Handle non-numeric input (ValueError)
  • Ask for input again if invalid
Challenge E: Better Item Display

Improve how items are shown to the user.

  • Format items nicely (price and description)
  • Show item number for selection
  • Allow selection by number or name

Part 4: Testing 15 min

Test Your Enhanced Code

Try these test cases to ensure your improvements work:

Test Cases to Try

  • Enter an item that doesn't exist
  • Enter "apple" (lowercase) when item is "Apple"
  • Enter a negative budget
  • Enter "abc" as the budget
  • Try to buy something you can't afford
  • Buy multiple items in one session

Key Concept: Defensive programming means anticipating what users might do wrong and handling it gracefully.

What You've Learned

  • Code review process
  • Error handling with try/except
  • Input validation techniques
  • Iterative development
  • Edge case testing

Next lesson: We'll start exploring Year 12 concepts building on your improved code.

← Back to Blake's Learning Hub