0% found this document useful (0 votes)
5 views32 pages

Better Function

The document provides a guide on improving code quality and maintainability through ten principles, including the Single Responsibility Principle, limiting method size, and using descriptive names. It emphasizes the importance of clear function design, minimizing parameters, avoiding side effects, and reusing existing code. The guide also suggests practices like early returns, keeping methods stateless, and adding proper comments where necessary.

Uploaded by

Wali Ullah
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views32 pages

Better Function

The document provides a guide on improving code quality and maintainability through ten principles, including the Single Responsibility Principle, limiting method size, and using descriptive names. It emphasizes the importance of clear function design, minimizing parameters, avoiding side effects, and reusing existing code. The guide also suggests practices like early returns, keeping methods stateless, and adding proper comments where necessary.

Uploaded by

Wali Ullah
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Writing Better Functions

A guide to improving code quality and maintainability

[Link] 1
1. Follow the Single Responsibility Principle
A function should do only one thing well. Combining tasks makes
maintenance and debugging harder.

[Link] 2
Problem
A function loads, cleans, and creates features, making it hard to
reuse and debug.

def process_data(file_path):
data = pd.read_csv(file_path) # Loading data
data = [Link]() # Cleaning data
data['new_feature'] = data['feature1'] * data['feature2'] # Feature engineering
return data

[Link] 3
Solution
Split tasks into individual functions:

def load_data(file_path):
return pd.read_csv(file_path)

def clean_data(data):
return [Link]()

def create_features(data):
data['new_feature'] = data['feature1'] * data['feature2']
return data

def process_data(file_path):
data = load_data(file_path)
data = clean_data(data)
return create_features(data)

[Link] 4
2. Limit the Method Size
Smaller functions improve readability and testability.

[Link] 5
Problem
A large function mixes prediction, metrics, and visualization.

def analyze_model_performance(model, X_train, X_test, y_train, y_test):


y_train_pred = [Link](X_train)
y_test_pred = [Link](X_test)
train_mse = mean_squared_error(y_train, y_train_pred)
test_mse = mean_squared_error(y_test, y_test_pred)
print("Train MSE:", train_mse)
print("Test MSE:", test_mse)
[Link](y_test, y_test_pred)
[Link]()

[Link] 6
Solution
Break it into focused functions:

def calculate_mse(model, X, y):


predictions = [Link](X)
return mean_squared_error(y, predictions)

def plot_predictions(y_true, y_pred):


[Link](y_true, y_pred)
[Link]("True Values")
[Link]("Predicted Values")
[Link]()

def analyze_model_performance(model, X_train, X_test, y_train, y_test):


train_mse = calculate_mse(model, X_train, y_train)
test_mse = calculate_mse(model, X_test, y_test)
print("Train MSE:", train_mse)
print("Test MSE:", test_mse)
plot_predictions(y_test, [Link](X_test))

[Link] 7
3. Use Descriptive Names
Names should clearly describe a function’s purpose.

[Link] 8
Problem
Ambiguous names make code hard to understand.

def do_work(df):
df = [Link]()
df['norm_col'] = df['col'] / df['col'].max()
return df

[Link] 9
Solution
Use meaningful names:

def clean_and_normalize_data(df):
df = [Link]()
df['normalized_column'] = df['column'] / df['column'].max()
return df

[Link] 10
4. Minimize Parameters
Too many parameters make functions harder to use and
maintain.

[Link] 11
Problem
A function with many parameters is difficult to call and modify.

def train_model(X_train, y_train, learning_rate, epochs, batch_size):


model = SomeModel()
[Link](X_train, y_train, lr=learning_rate, epochs=epochs, batch_size=batch_size)
return model

[Link] 12
Solution
Encapsulate parameters in a dictionary:

def train_model(X_train, y_train, config):


model = SomeModel()
[Link](X_train, y_train, lr=config['learning_rate'], epochs=config['epochs'], batch_size=config['batch_size'])
return model

config = {
'learning_rate': 0.01,
'epochs': 100,
'batch_size': 32
}
model = train_model(X_train, y_train, config)

[Link] 13
5. Avoid Side Effects
Functions that modify external states can cause unpredictable
behavior.

[Link] 14
Problem
A function modifies a global variable:

global_data = [Link]()

def clean_data():
global global_data
global_data = global_data.dropna()

[Link] 15
Solution
Return a modified copy instead:

def clean_data(data):
return [Link]()

global_data = clean_data(global_data)

[Link] 16
6. Handle a Single Level of Abstraction
Mixing high- and low-level tasks makes code harder to read and
refactor.

[Link] 17
Problem
A function mixes file reading and data analysis:

def process_and_analyze(file_path):
data = pd.read_csv(file_path)
data = [Link]()
print("Data processed")
print([Link]())

[Link] 18
Solution
Separate responsibilities:

def load_data(file_path):
return pd.read_csv(file_path)

def process_data(data):
return [Link]()

def analyze_data(data):
print("Data processed")
print([Link]())

def process_and_analyze(file_path):
data = load_data(file_path)
data = process_data(data)
analyze_data(data)

[Link] 19
7. Use Early Returns
Early returns simplify logic by reducing nesting.

[Link] 20
Problem
Deeply nested conditions:

def validate_data(data):
if data is not None:
if len(data) > 0:
if 'important_column' in [Link]:
return True
return False

[Link] 21
Solution
Simplify with early returns:

def validate_data(data):
if data is None or len(data) == 0 or 'important_column' not in [Link]:
return False
return True

[Link] 22
8. Reuse Existing Code
Avoid duplicating logic by extracting shared functionality.

[Link] 23
Problem
Duplicate logic wastes effort and increases maintenance.

def calculate_mean(values):
return sum(values) / len(values)

def calculate_mean_squared(values):
mean = sum(values) / len(values)
return mean ** 2

[Link] 24
Solution
Extract shared logic:

def calculate_mean(values):
return sum(values) / len(values)

def calculate_mean_squared(values):
mean = calculate_mean(values)
return mean ** 2

[Link] 25
9. Keep Methods Stateless
Stateless functions are predictable and avoid external state.

[Link] 26
Problem
A method modifies an internal variable:

class Model:
def __init__(self):
[Link] = []

def predict(self, data):


[Link] = [x * 2 for x in data]

[Link] 27
Solution
Return results instead:

class Model:
def predict(self, data):
return [x * 2 for x in data]

[Link] 28
10. Add Proper Comments (If Needed)
Use comments to explain non-obvious logic.

[Link] 29
Problem
Complex logic without explanation:

def calculate_growth_rate(data):
return (data[-1] - data[0]) / data[0] # Ambiguous growth calculation

[Link] 30
Solution
Add clear comments or docstrings:

def calculate_growth_rate(data):
"""
Calculate the growth rate of a dataset.

Args:
data (list or array): Time-series data with numerical values.

Returns:
float: Growth rate as a percentage.
"""
return (data[-1] - data[0]) / data[0]

[Link] 31
Thank You!
Adopt these principles to improve your code !

[Link] 32

You might also like