Separation of concerns organizes software so each part handles a distinct behavior or piece of knowledge, while dissimilar activities remain isolated. A concern may be small, such as calculating a square root, or broad, such as managing payments. This division reduces the amount of code a developer must hold in mind and makes behavior easier to reason about. section 2.0 section 2.2
Think of a software application like a workplace with specialist desks: one handles user interaction, another stores information, and another applies rules. Each desk can change without requiring every other desk to understand its internal work. section 6.3
Choose boundaries that make changes precise and responsibilities clear:
- Extract functions when a procedural block contains a named behavior. A function that joins names should not also decide how an introduction is presented. section 2.2.1
- Use classes to group closely related data and behaviors, modules to group related functions, classes, and data, and packages to organize modules hierarchically. section 2.3
- Separate application layers by concern: presentation, persistence, and actions or business rules. These layers can evolve independently and may be reused by other applications. section 6.3
- Prefer clarity and separation over reuse when extracting code; reuse is a secondary benefit. Avoid splitting code along arbitrary boundaries or creating abstractions before a sensible organization appears. section 2.3 section 9.0
From one procedure to focused functions
A Rock, Paper, Scissors program can mix input, random choice, output, and game rules in one long procedure. Separate functions such as get_human_choice, get_computer_choice, print_options, print_choices, and print_result give each activity a clearer home. Similarly, a name-introduction example becomes easier to change when join_names formats names and introduce handles the title and presentation.
Separating response formatting
A service endpoint can choose a formatter from the request's Accept header instead of combining format decisions with formatting code. Separate to_json and to_xml functions, together with get_format_function, make adding another response format a matter of adding a function and a mapping. section 9.2.2
A single interface over separated transformations
Query cleaning can keep removing spaces, removing quotes, and normalizing case as private transformations while exposing one clean_query function. The internal concerns stay separate, but callers use a simple shared interface. section 10.1.3
Listing 2.2. Code with extracted functions
import random
OPTIONS = ['rock', 'paper', 'scissors']
def get_computer_choice():
return random.choice(OPTIONS)
def get_human_choice():
choice_number = int(input('Enter the number of your choice: '))
return OPTIONS[choice_number - 1]
def print_options():
print('\n'.join(f'({i}) {option.title()}' for i,
option in enumerate(OPTIONS)))
def print_choices(human_choice, computer_choice):
print(f'You chose {human_choice}')
print(f'The computer chose {computer_choice}')
def print_win_lose(human_choice, computer_choice, human_beats,
human_loses_to):
if computer_choice == human_loses_to:
print(f'Sorry, {computer_choice} beats {human_choice}')
elif computer_choice == human_beats:
print(f'Yes, {human_choice} beats {computer_choice}!')
def print_result(human_choice, computer_choice):
if human_choice == computer_choice:
print('Draw!')
if human_choice == 'rock':
print_win_lose('rock', computer_choice, 'scissors', 'paper')
elif human_choice == 'paper':
print_win_lose('paper', computer_choice, 'rock', 'scissors')
elif human_choice == 'scissors':
print_win_lose('scissors', computer_choice, 'paper', 'rock')
print_options()
human_choice = get_human_choice()
computer_choice = get_computer_choice()
print_choices(human_choice, computer_choice)
print_result(human_choice, computer_choice)
Inspect the extracted Rock, Paper, Scissors functions to compare focused responsibilities with the original mixed procedure. section 2.2.1





















