Software engineering principles - Time & Space Complexity
When we think about software engineering principles, we often focus on how they guide building good software. But it is also important to understand how following these principles affects the time it takes for software to run or grow.
We want to answer: How does the work needed change as the software or its input grows?
Analyze the time complexity of the following code snippet.
// Example: Simple function following single responsibility principle
function sumArray(numbers) {
let total = 0;
for (let i = 0; i < numbers.length; i++) {
total += numbers[i];
}
return total;
}
This function adds all numbers in an array, showing a clear, focused task.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each number in the array once.
- How many times: Exactly as many times as there are items in the array.
As the array gets bigger, the function does more additions, one for each item.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 additions |
| 100 | 100 additions |
| 1000 | 1000 additions |
Pattern observation: The work grows directly with the number of items. Double the items, double the work.
Time Complexity: O(n)
This means the time to complete the task grows in a straight line with the input size.
[X] Wrong: "Since the function has a loop, it must be slow or complicated."
[OK] Correct: A single loop that goes through data once is actually very efficient and simple. It grows steadily, not wildly.
Understanding how simple, clear principles like doing one thing well also help keep your code efficient is a valuable skill. It shows you can write code that is both easy to maintain and performs well as it grows.
"What if we changed the function to sum only even numbers in the array? How would the time complexity change?"
Practice
Solution
Step 1: Understand the principle names
SRP means each module or class should have one responsibility or reason to change.Step 2: Match the description to the principle
Writing code that does one thing well matches SRP.Final Answer:
Single Responsibility Principle (SRP) -> Option CQuick Check:
One responsibility = SRP [OK]
- Confusing SRP with DRY which avoids repetition
- Thinking KISS means single responsibility
- Mixing Open/Closed with SRP
Solution
Step 1: Recall DRY meaning
DRY stands for "Don't Repeat Yourself", meaning avoid code duplication.Step 2: Match option to DRY
Avoid duplicating code or logic in multiple places says avoid duplicating code or logic, which matches DRY.Final Answer:
Avoid duplicating code or logic in multiple places -> Option AQuick Check:
DRY = no repetition [OK]
- Confusing DRY with Open/Closed principle
- Mixing DRY with KISS which is about simplicity
- Thinking DRY means single responsibility
def calculate_area(radius):
return 3.14 * radius * radius
area = calculate_area(5)
print(area)What will be the output?
Solution
Step 1: Calculate area using formula
Area = π * radius² = 3.14 * 5 * 5 = 3.14 * 25 = 78.5Step 2: Check code output
The function returns 78.5 and print outputs it.Final Answer:
78.5 -> Option BQuick Check:
3.14 * 25 = 78.5 [OK]
- Using 2 * π * r (circumference) instead of area formula
- Expecting error due to missing math module (not needed here)
- Confusing output with None from missing return
class Shape:
def area(self, shape_type, size):
if shape_type == 'circle':
return 3.14 * size * size
elif shape_type == 'square':
return size * size
else:
return 0Solution
Step 1: Understand Open/Closed Principle
It says software entities should be open for extension but closed for modification.Step 2: Analyze the area method
The method uses if-else to handle different shapes, so adding a new shape requires modifying this method.Final Answer:
The area method uses conditional logic to handle multiple shapes -> Option DQuick Check:
Conditional logic breaks Open/Closed [OK]
- Thinking inheritance is used properly here
- Believing the class is closed for modification
- Confusing open for extension with modifying code
class User:
def __init__(self, name, email):
self.name = name
self.email = email
def save_to_database(self):
# code to save user data
pass
def send_welcome_email(self):
# code to send email
passWhat is the best way to apply SRP here?
Solution
Step 1: Understand SRP
SRP says a class should have only one reason to change, so User should only hold user data.Step 2: Identify responsibilities
Saving to database and sending emails are separate concerns from user data storage.Step 3: Refactor accordingly
Move save_to_database to a DatabaseHandler class to separate concerns.Final Answer:
Move save_to_database to a separate DatabaseHandler class -> Option AQuick Check:
Separate responsibilities = SRP applied [OK]
- Keeping all methods in one class breaks SRP
- Combining methods increases complexity
- Removing functionality instead of refactoring
Ready to prove it?
Pass the test and this pattern moves unknown
