Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,18 @@ Here you can find slides for Clean Code conversations or classes.
[tire-pressure-kata-cpp]: https://github.com/Coding-Cuddles/tire-pressure-monitoring-cpp-kata
[99-bottles-kata-python]: https://github.com/Coding-Cuddles/99-bottles-of-beer-python-kata
[99-bottles-kata-cpp]: https://github.com/Coding-Cuddles/99-bottles-of-beer-cpp-kata

### Legacy Code (Blue Belt)

| # | Session Type | Name |
| --: | ------------ | ------------------------------------------------------------------------------------------------------ |
| 1 | Discussion | [Understanding Legacy Code](legacy-code/01-understanding-legacy.md) |
| 2 | Kata | [Identifying Legacy Code Kata](legacy-code/02-kata-identifying.md) |
| 3 | Discussion | [Building a Safety Net](legacy-code/03-safety-net.md) |
| 4 | Kata | [Characterization Testing Kata](legacy-code/04-kata-characterization-testing.md) |
| 5 | Discussion | [Safe, Non-Invasive Changes](legacy-code/05-safe-changes.md) |
| 6 | Kata | [Sprouting & Wrapping Kata](legacy-code/06-kata-sprouting-wrapping.md) |
| 7 | Discussion | [Core Dependency Breaking Techniques](legacy-code/07-dependency-breaking.md) |
| 8 | Kata | [Dependency Breaking Kata](legacy-code/08-kata-dependency-breaking.md) |
| 9 | Discussion | [Advanced Topics & Large-Scale Strategy](legacy-code/09-advanced-topics.md) |
| 10 | Kata | [Large-Scale Refactoring Kata](legacy-code/10-kata-large-scale-refactoring.md) |
85 changes: 0 additions & 85 deletions legacy-code/01-sprout-wrap-worksheet.md

This file was deleted.

102 changes: 102 additions & 0 deletions legacy-code/01-understanding-legacy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
% Understanding Legacy Code
% Week 1: Discussion Session
% Advanced Software Engineering

# Learning Objectives

- Define legacy code and its characteristics
- Understand the challenges and mindset needed
- Learn to approach legacy code systematically

# What is Legacy Code?

> "Code without tests" - Michael Feathers

## Characteristics

- Difficult to change
- High coupling
- Low cohesion
- Insufficient documentation
- Missing or outdated tests

# Discussion Questions

1. How does Feathers' definition of legacy code differ from the common industry perception? What implications does this have for how we treat our codebase?

2. In your experience, what are the most challenging aspects of working with legacy code? How do these challenges affect team productivity and morale?

3. What strategies have you used or seen used to deal with legacy code in your projects? How effective were they?

# Code Examples

## C++ Example: Tightly Coupled Legacy Code

```cpp
class DataProcessor {
Database db;
Logger logger;

public:
void process(const std::string& data) {
db.connect("hardcoded:connection:string");
logger.log("Processing started");

// Complex business logic intertwined with
// database calls and logging
if (data.length() > 0) {
db.insert(data);
logger.log("Data inserted");
}

db.disconnect();
}
};
```

## Python Example: Missing Abstraction

```python
class ReportGenerator:
def generate_report(self, data):
# Direct database access
conn = mysql.connector.connect(
host="localhost",
database="reports_db",
user="admin"
)

# Business logic mixed with data access
cursor = conn.cursor()
cursor.execute("SELECT * FROM sales")
results = cursor.fetchall()

# Direct file system access
with open('report.pdf', 'wb') as f:
pdf = PDF()
for row in results:
pdf.add_line(row)
f.write(pdf.output())
```

# Key Takeaways

1. Legacy code is any code without tests, regardless of age
2. Working with legacy code requires a systematic approach
3. Understanding code dependencies is crucial
4. Small, safe changes are preferable to large refactoring

# Required Reading

- Chapters 1-3 of "Working Effectively with Legacy Code"
- Focus on:
- Understanding the legacy code dilemma
- The role of testing
- Basic strategies for working with legacy code

# Next Week

Prepare for hands-on kata:
- Identifying legacy code characteristics
- Initial assessment techniques
- Setting up a testing strategy
151 changes: 151 additions & 0 deletions legacy-code/02-kata-identifying.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
% Identifying Legacy Code Kata
% Week 2: Practical Session
% Advanced Software Engineering

# Learning Objectives

- Identify characteristics of legacy code
- Assess code for testability
- Plan initial refactoring steps

# Kata Instructions

Work in pairs to analyze and improve the following code examples.

## C++ Starting Point

```cpp
class OrderProcessor {
private:
static OrderProcessor* instance;
Database* db;
EmailService* emailService;

OrderProcessor() {
db = new Database("production_db");
emailService = new EmailService();
}

public:
static OrderProcessor* getInstance() {
if (instance == null) {
instance = new OrderProcessor();
}
return instance;
}

bool processOrder(Order order) {
if (!db->isConnected()) {
db->connect();
}

bool success = false;
if (order.getTotal() > 0) {
success = db->executeQuery(
"INSERT INTO orders VALUES (" +
order.getId() + "," +
order.getCustomerId() + "," +
order.getTotal() + ")"
);

if (success) {
emailService->sendEmail(
order.getCustomerEmail(),
"Order Confirmation",
"Your order #" + order.getId() + " has been processed."
);
}
}
return success;
}
};
```

## Python Starting Point

```python
class ReportGenerator:
def __init__(self):
self.db = Database()
self.template_engine = TemplateEngine()

def generate_monthly_report(self, month, year):
# Connect to database
self.db.connect()

# Get data
sales_data = self.db.execute_query(
f"SELECT * FROM sales WHERE MONTH(date) = {month} "
f"AND YEAR(date) = {year}"
)

# Process data
total = sum(sale['amount'] for sale in sales_data)
avg = total / len(sales_data) if sales_data else 0

# Generate report
report = self.template_engine.load_template('monthly_report')
report.set_data({
'month': month,
'year': year,
'sales': sales_data,
'total': total,
'average': avg
})

# Save to file system
filename = f"report_{month}_{year}.pdf"
report.save_as_pdf(filename)

# Send email
email = EmailService()
email.send(
to="management@company.com",
subject=f"Monthly Report {month}/{year}",
body="Please find attached the monthly report.",
attachment=filename
)
```

# Tasks

1. Code Analysis (30 minutes)
- Identify all dependencies in the code
- List specific legacy code characteristics
- Document potential risks in making changes

2. Testability Assessment (30 minutes)
- Identify what makes the code hard to test
- List specific changes needed to enable testing
- Prioritize which parts need testing first

3. Refactoring Plan (30 minutes)
- Create a step-by-step plan for adding tests
- Identify seams that could be used
- Document potential breaking points

4. Discussion (30 minutes)
- Present findings to another pair
- Compare different approaches
- Agree on best practices for similar situations

# Success Criteria

- Comprehensive list of dependencies identified
- Clear testing strategy documented
- Practical refactoring plan created
- Risks and mitigation strategies outlined

# Notes for Facilitators

- Ensure pairs rotate roles during the exercise
- Encourage discussion of real-world examples
- Focus on identifying patterns that can be applied to actual work situations
- Emphasize the importance of small, safe steps

# Follow-up

Prepare for next week's session on:
- Building a safety net
- Writing characterization tests
- Understanding test coverage strategies
Loading