Skip to content

Commit b231260

Browse files
committed
Add 04_additional/ with 6 programming principles + new _basic.py format
New principles with instant clarity approach: - 01_business_logic/ - "Does it exist without computers?" test - 02_tell_dont_ask/ - Object encapsulation patterns - 03_law_of_demeter/ - "One dot rule" for loose coupling - 04_composition_over_inheritance/ - Flexible behavior composition - 05_dependency_injection/ - External dependency management - 06_static_vs_runtime/ - Compile-time vs execution-time decisions Each principle includes: - README.md with concise definitions - violation.py + violation_basic.py (10-15 lines, instant problem visibility) - solution.py + solution_basic.py (clean approach) - exercises.md with hands-on practice _basic.py format: Zero cognitive load, 5-second understanding, focus on essence. Dual format allows quick learning + detailed exploration.
1 parent 4fdf10c commit b231260

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+4579
-866
lines changed

day0.md

Lines changed: 0 additions & 866 deletions
This file was deleted.

day0_principles/03_general_principles/01_dry/README.md

Whitespace-only changes.

day0_principles/03_general_principles/01_dry/exercises.md

Whitespace-only changes.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
"""
2+
DRY Solution - Don't Repeat Yourself
3+
Eliminacja duplikacji poprzez wydzielenie wspólnej logiki
4+
"""
5+
6+
from datetime import datetime
7+
8+
9+
class UserValidator:
10+
def _is_valid_email_format(self, email):
11+
# DRY: Jedna implementacja podstawowej walidacji
12+
return "@" in email and "." in email and len(email) >= 5
13+
14+
def validate_email(self, email):
15+
return self._is_valid_email_format(email)
16+
17+
def validate_admin_email(self, email):
18+
# Reużywa podstawowej walidacji + dodaje specyficzną logikę
19+
return (self._is_valid_email_format(email) and
20+
email.endswith("@company.com"))
21+
22+
23+
class OrderProcessor:
24+
TAX_RATE = 0.23
25+
SERVICE_FEE_RATE = 0.05
26+
27+
def _calculate_base_fees(self, amount):
28+
# DRY: Wspólna logika obliczania opłat
29+
tax = amount * self.TAX_RATE
30+
service_fee = amount * self.SERVICE_FEE_RATE
31+
return tax + service_fee
32+
33+
def _apply_discount(self, amount, discount_rate):
34+
# DRY: Wspólna logika aplicacji zniżki
35+
base_fees = self._calculate_base_fees(amount)
36+
discount = amount * discount_rate
37+
return amount - discount + base_fees
38+
39+
def calculate_discount_for_regular(self, amount):
40+
return self._apply_discount(amount, 0.10)
41+
42+
def calculate_discount_for_premium(self, amount):
43+
return self._apply_discount(amount, 0.15)
44+
45+
def calculate_discount_for_vip(self, amount):
46+
return self._apply_discount(amount, 0.20)
47+
48+
49+
class DatabaseLogger:
50+
def _get_timestamp(self):
51+
# DRY: Jedna implementacja timestampu
52+
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
53+
54+
def _log_message(self, message):
55+
# DRY: Wspólna logika logowania
56+
timestamp = self._get_timestamp()
57+
formatted_message = f"[{timestamp}] {message}"
58+
print(f"INSERT INTO logs VALUES('{formatted_message}')")
59+
60+
def log_user_action(self, user_id, action):
61+
self._log_message(f"User {user_id}: {action}")
62+
63+
def log_system_event(self, event):
64+
self._log_message(f"System: {event}")
65+
66+
def log_error(self, error):
67+
self._log_message(f"ERROR: {error}")
68+
69+
70+
# Bonus: Configuration-driven approach dla jeszcze lepszego DRY
71+
class AdvancedOrderProcessor:
72+
"""Przykład data-driven approach dla eliminacji duplikacji"""
73+
74+
DISCOUNT_RATES = {
75+
'regular': 0.10,
76+
'premium': 0.15,
77+
'vip': 0.20
78+
}
79+
80+
TAX_RATE = 0.23
81+
SERVICE_FEE_RATE = 0.05
82+
83+
def calculate_discount(self, amount, customer_type):
84+
# DRY: Jedna metoda dla wszystkich typów klientów
85+
if customer_type not in self.DISCOUNT_RATES:
86+
raise ValueError(f"Unknown customer type: {customer_type}")
87+
88+
discount_rate = self.DISCOUNT_RATES[customer_type]
89+
base_fees = amount * (self.TAX_RATE + self.SERVICE_FEE_RATE)
90+
discount = amount * discount_rate
91+
92+
return amount - discount + base_fees
93+
94+
95+
if __name__ == "__main__":
96+
validator = UserValidator()
97+
print(validator.validate_email("test@example.com"))
98+
print(validator.validate_admin_email("admin@company.com"))
99+
100+
processor = OrderProcessor()
101+
print(f"Regular: ${processor.calculate_discount_for_regular(100):.2f}")
102+
print(f"Premium: ${processor.calculate_discount_for_premium(100):.2f}")
103+
104+
# Bonus: Data-driven approach
105+
advanced = AdvancedOrderProcessor()
106+
print(f"VIP (advanced): ${advanced.calculate_discount(100, 'vip'):.2f}")
107+
108+
logger = DatabaseLogger()
109+
logger.log_user_action(123, "login")
110+
logger.log_system_event("startup")
111+
logger.log_error("Database connection failed")
112+
113+
print("✅ Jedna implementacja dla każdej logiki")
114+
print("✅ Zmiana walidacji = 1 miejsce do edycji")
115+
print("✅ Zmiana timestamp = 1 miejsce do edycji")
116+
print("✅ Nowe typy klientów = dodanie do dictionary")
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""
2+
DRY Violation - Don't Repeat Yourself
3+
Duplikacja kodu w różnych miejscach
4+
"""
5+
6+
7+
class UserValidator:
8+
def validate_email(self, email):
9+
# PROBLEM: Duplikacja logiki walidacji
10+
if "@" not in email or "." not in email:
11+
return False
12+
if len(email) < 5:
13+
return False
14+
return True
15+
16+
def validate_admin_email(self, email):
17+
# PROBLEM: Ta sama logika co wyżej - duplikacja!
18+
if "@" not in email or "." not in email:
19+
return False
20+
if len(email) < 5:
21+
return False
22+
# Plus dodatkowa logika
23+
if not email.endswith("@company.com"):
24+
return False
25+
return True
26+
27+
28+
class OrderProcessor:
29+
def calculate_discount_for_regular(self, amount):
30+
# PROBLEM: Identyczna logika obliczania
31+
tax = amount * 0.23
32+
service_fee = amount * 0.05
33+
total_fees = tax + service_fee
34+
return amount - (amount * 0.10) + total_fees
35+
36+
def calculate_discount_for_premium(self, amount):
37+
# PROBLEM: Kopia powyższej metody z innym procentem
38+
tax = amount * 0.23
39+
service_fee = amount * 0.05
40+
total_fees = tax + service_fee
41+
return amount - (amount * 0.15) + total_fees # Tylko ta linijka się różni
42+
43+
def calculate_discount_for_vip(self, amount):
44+
# PROBLEM: Znowu ta sama logika
45+
tax = amount * 0.23
46+
service_fee = amount * 0.05
47+
total_fees = tax + service_fee
48+
return amount - (amount * 0.20) + total_fees
49+
50+
51+
class DatabaseLogger:
52+
def log_user_action(self, user_id, action):
53+
timestamp = "2024-01-15 10:30:00" # PROBLEM: Duplikacja formatowania
54+
message = f"[{timestamp}] User {user_id}: {action}"
55+
print(f"INSERT INTO logs VALUES('{message}')")
56+
57+
def log_system_event(self, event):
58+
timestamp = "2024-01-15 10:30:00" # PROBLEM: Ta sama logika timestampu
59+
message = f"[{timestamp}] System: {event}"
60+
print(f"INSERT INTO logs VALUES('{message}')")
61+
62+
def log_error(self, error):
63+
timestamp = "2024-01-15 10:30:00" # PROBLEM: Znowu duplikacja
64+
message = f"[{timestamp}] ERROR: {error}"
65+
print(f"INSERT INTO logs VALUES('{message}')")
66+
67+
68+
if __name__ == "__main__":
69+
validator = UserValidator()
70+
print(validator.validate_email("test@example.com"))
71+
print(validator.validate_admin_email("admin@company.com"))
72+
73+
processor = OrderProcessor()
74+
print(f"Regular: ${processor.calculate_discount_for_regular(100)}")
75+
print(f"Premium: ${processor.calculate_discount_for_premium(100)}")
76+
77+
logger = DatabaseLogger()
78+
logger.log_user_action(123, "login")
79+
logger.log_system_event("startup")
80+
81+
print("❌ Duplikacja kodu w wielu miejscach - naruszenie DRY")
82+
print("❌ Zmiana walidacji email = 2 miejsca do edycji")
83+
print("❌ Zmiana formatu timestamp = 3 miejsca do edycji")

day0_principles/03_general_principles/02_kiss/README.md

Whitespace-only changes.

day0_principles/03_general_principles/02_kiss/exercises.md

Whitespace-only changes.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
"""
2+
KISS Solution - Keep It Simple, Stupid
3+
Proste rozwiązania dla prostych problemów
4+
"""
5+
6+
7+
def calculate_total(items):
8+
"""KISS: Prosta funkcja do prostego zadania"""
9+
return sum(items)
10+
11+
12+
def calculate_weighted_total(items, weights):
13+
"""KISS: Dodaj złożoność tylko gdy potrzebna"""
14+
return sum(item * weight for item, weight in zip(items, weights))
15+
16+
17+
def authenticate_user(username, password):
18+
"""KISS: Prosta autentykacja dla prostej aplikacji"""
19+
users = {"admin": "password123", "user": "pass456"}
20+
return username in users and users[username] == password
21+
22+
23+
class SimpleShoppingCart:
24+
"""KISS: Prosta implementacja koszyka"""
25+
26+
def __init__(self):
27+
self.items = []
28+
29+
def add_item(self, name, price):
30+
self.items.append({"name": name, "price": price})
31+
32+
def get_total(self):
33+
return sum(item["price"] for item in self.items)
34+
35+
def get_item_count(self):
36+
return len(self.items)
37+
38+
39+
class UserManager:
40+
"""KISS: Proste zarządzanie użytkownikami"""
41+
42+
def __init__(self):
43+
self.users = {}
44+
self.logged_in_users = set()
45+
46+
def register_user(self, username, password):
47+
if username in self.users:
48+
return False
49+
self.users[username] = password
50+
return True
51+
52+
def login(self, username, password):
53+
if username in self.users and self.users[username] == password:
54+
self.logged_in_users.add(username)
55+
return True
56+
return False
57+
58+
def logout(self, username):
59+
self.logged_in_users.discard(username)
60+
61+
def is_logged_in(self, username):
62+
return username in self.logged_in_users
63+
64+
65+
# Przykład: Kiedy można dodać złożoność (ale tylko gdy potrzebna)
66+
class UserManagerWithSecurity:
67+
"""
68+
KISS + Security: Dodajemy złożoność tylko tam gdzie jest potrzebna
69+
Większość firm potrzebuje basic security, więc to uzasadnione
70+
"""
71+
72+
def __init__(self):
73+
self.users = {}
74+
self.logged_in_users = set()
75+
self.failed_attempts = {} # Dodane tylko dla security
76+
self.max_attempts = 3
77+
78+
def register_user(self, username, password):
79+
if username in self.users:
80+
return False
81+
self.users[username] = password
82+
return True
83+
84+
def login(self, username, password):
85+
# Prosta logika, ale z podstawowym security
86+
if self.failed_attempts.get(username, 0) >= self.max_attempts:
87+
return False # Account locked
88+
89+
if username in self.users and self.users[username] == password:
90+
self.logged_in_users.add(username)
91+
if username in self.failed_attempts:
92+
del self.failed_attempts[username] # Reset on success
93+
return True
94+
95+
# Track failed attempts
96+
self.failed_attempts[username] = self.failed_attempts.get(username, 0) + 1
97+
return False
98+
99+
def logout(self, username):
100+
self.logged_in_users.discard(username)
101+
102+
def is_logged_in(self, username):
103+
return username in self.logged_in_users
104+
105+
106+
# Przykład progresywnej złożoności - zaczynamy prosto, dodajemy gdy potrzeba
107+
class FileProcessor:
108+
"""KISS: Start simple, add complexity when needed"""
109+
110+
def read_file(self, filename):
111+
# V1: Najprostsza implementacja
112+
with open(filename, 'r') as f:
113+
return f.read()
114+
115+
def read_file_safe(self, filename):
116+
# V2: Dodajemy error handling tylko gdy mamy problemy
117+
try:
118+
with open(filename, 'r') as f:
119+
return f.read()
120+
except FileNotFoundError:
121+
return None
122+
except Exception as e:
123+
print(f"Error reading file: {e}")
124+
return None
125+
126+
def read_file_with_encoding(self, filename, encoding='utf-8'):
127+
# V3: Dodajemy encoding tylko gdy mamy problemy z różnymi plikami
128+
try:
129+
with open(filename, 'r', encoding=encoding) as f:
130+
return f.read()
131+
except FileNotFoundError:
132+
return None
133+
except Exception as e:
134+
print(f"Error reading file: {e}")
135+
return None
136+
137+
138+
if __name__ == "__main__":
139+
# Proste rozwiązania dla prostych problemów
140+
print(f"Sum: {calculate_total([1, 2, 3, 4])}")
141+
print(f"Weighted sum: {calculate_weighted_total([1, 2, 3], [0.5, 1.0, 2.0])}")
142+
143+
print(f"Auth admin: {authenticate_user('admin', 'password123')}")
144+
print(f"Auth wrong: {authenticate_user('admin', 'wrong')}")
145+
146+
# Prosta klasa zamiast over-engineered patterns
147+
cart = SimpleShoppingCart()
148+
cart.add_item("Laptop", 1000)
149+
cart.add_item("Mouse", 50)
150+
print(f"Cart total: ${cart.get_total()}")
151+
152+
# User management - prosty i czytelny
153+
user_mgr = UserManager()
154+
user_mgr.register_user("john", "secret123")
155+
print(f"Login successful: {user_mgr.login('john', 'secret123')}")
156+
print(f"Is logged in: {user_mgr.is_logged_in('john')}")
157+
158+
# Security tylko tam gdzie potrzebne
159+
secure_mgr = UserManagerWithSecurity()
160+
secure_mgr.register_user("admin", "admin123")
161+
print(f"Login attempts: {secure_mgr.login('admin', 'wrong')}")
162+
print(f"Login attempts: {secure_mgr.login('admin', 'wrong')}")
163+
print(f"Login attempts: {secure_mgr.login('admin', 'wrong')}")
164+
print(f"Account locked: {secure_mgr.login('admin', 'admin123')}") # Should fail - locked
165+
166+
print("✅ Proste rozwiązania = łatwe do zrozumienia")
167+
print("✅ Dodajemy złożoność tylko gdy rzeczywiście potrzebna")
168+
print("✅ 5 linii zamiast 50 dla podstawowych operacji")
169+
print("✅ Kod robi dokładnie to co potrzebne, nic więcej")

0 commit comments

Comments
 (0)