Skip to content

Commit 67e95ff

Browse files
committed
update SOLID
1 parent c3a135d commit 67e95ff

File tree

2 files changed

+187
-23
lines changed

2 files changed

+187
-23
lines changed

notebooks/Untitled.ipynb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"id": "f0da3cda",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": []
10+
}
11+
],
12+
"metadata": {
13+
"kernelspec": {
14+
"display_name": "Python 3 (ipykernel)",
15+
"language": "python",
16+
"name": "python3"
17+
},
18+
"language_info": {
19+
"codemirror_mode": {
20+
"name": "ipython",
21+
"version": 3
22+
},
23+
"file_extension": ".py",
24+
"mimetype": "text/x-python",
25+
"name": "python",
26+
"nbconvert_exporter": "python",
27+
"pygments_lexer": "ipython3",
28+
"version": "3.10.8"
29+
}
30+
},
31+
"nbformat": 4,
32+
"nbformat_minor": 5
33+
}

notebooks/WhenObjectsAreAlike.ipynb

Lines changed: 154 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,23 +1908,173 @@
19081908
" print_dict(employee.to_dict())"
19091909
]
19101910
},
1911+
{
1912+
"cell_type": "markdown",
1913+
"id": "9f680e25",
1914+
"metadata": {},
1915+
"source": [
1916+
"## Inheritance Tax\n",
1917+
"\n",
1918+
"- \"You wanted a banana but what you got was a gorilla holding the banana and the entire jungle\" - Joe Armstrong\n",
1919+
"- inheritance is a powerful tool but it can be misused\n",
1920+
"- alternatives may be better to avoid the inheritance tax:\n",
1921+
" - interfaces and protocols\n",
1922+
" - delegation\n",
1923+
" - mixins\n",
1924+
"- interfaces and protocols give us polymorphism without inheritance\n",
1925+
"- delegation is a way to use composition instead of inheritance\n",
1926+
"- delegate to services - Has-A relationship Trumps Is-A relationship\n",
1927+
"- use mixins to share code and functionality\n"
1928+
]
1929+
},
19111930
{
19121931
"cell_type": "markdown",
19131932
"id": "80057b78",
19141933
"metadata": {},
19151934
"source": [
19161935
"## SOLID principle\n",
1936+
"\n",
19171937
"- a popular software design principle using OOP\n",
1918-
"- **inheritance** must follow L - Liskov Substitution principle\n",
19191938
"\n",
1920-
"### S: Single Responsibility Principle\n",
1939+
"### S: Single Responsibility Principle (SRP)\n",
1940+
"\n",
19211941
"- a class should have one responsibility\n",
1922-
"- one reason to change when the requirements change\n",
1942+
"- \"one and only reason\" to change when the requirements change\n",
1943+
"- a class should have a single, well-defined purpose; should be responsible for one aspect of the system's functionality\n",
1944+
"\n",
1945+
"#### How to Achieve the Single Responsibility Principle:\n",
1946+
"\n",
1947+
"- **Identify Responsibilities**:\n",
1948+
" - carefully analyze the responsibilities of each class in your design\n",
1949+
"\n",
1950+
"- **Separate Concerns**: \n",
1951+
" - if a class has multiple responsibilities, break it down into smaller classes, each with a single responsibility\n",
1952+
" \n",
1953+
"- **Use Cohesion**:\n",
1954+
" - aim for high cohesion within classes, meaning that all the elements within a class should be related to its single responsibility\n",
1955+
" \n",
1956+
"- **Avoid God Objects**:\n",
1957+
" - \"God objects\" are classes that try to do everything\n",
1958+
" \n",
1959+
"- **Refactor**: \n",
1960+
" - if you find that a class is violating the SRP, refactor it to separate its responsibilities\n",
1961+
" \n",
1962+
"#### What does \"reason to change\" mean?\n",
1963+
"\n",
1964+
"- A \"reason to change\" refers to a specific actor or requirement that could cause the class to be modified; e.g.:\n",
1965+
"\n",
1966+
" - A class that handles both data persistence and user interface logic has two reasons to change: changes in the database schema and changes in the UI design.\n",
1967+
" - A class that both calculates employee salary and generates reports has two reasons to change: changes in salary calculation rules and changes in report formatting.\n",
1968+
"\n"
1969+
]
1970+
},
1971+
{
1972+
"cell_type": "code",
1973+
"execution_count": null,
1974+
"id": "5409782d",
1975+
"metadata": {},
1976+
"outputs": [],
1977+
"source": [
1978+
"# e.g. design violating SRP\n",
1979+
"class Employee:\n",
1980+
" def __init__(self, employee_id, name, salary):\n",
1981+
" self.employee_id = employee_id\n",
1982+
" self.name = name\n",
1983+
" self.salary = salary\n",
1984+
"\n",
1985+
" def calculate_pay(self):\n",
1986+
" # Calculate employee pay\n",
1987+
" pass\n",
1988+
"\n",
1989+
" def generate_report(self):\n",
1990+
" # Generate employee report\n",
1991+
" pass\n",
1992+
"\n",
1993+
" def save_to_database(self):\n",
1994+
" # Save employee data to database\n",
1995+
" pass"
1996+
]
1997+
},
1998+
{
1999+
"cell_type": "code",
2000+
"execution_count": null,
2001+
"id": "f43f76ad",
2002+
"metadata": {},
2003+
"outputs": [],
2004+
"source": [
2005+
"# to adhere to SRP refactor the God class into three separate classes\n",
2006+
"class Employee:\n",
2007+
" def __init__(self, employee_id, name, salary):\n",
2008+
" self.employee_id = employee_id\n",
2009+
" self.name = name\n",
2010+
" self.salary = salary\n",
2011+
"\n",
2012+
"class PayCalculator:\n",
2013+
" def calculate_pay(self, employee):\n",
2014+
" # Calculate employee pay\n",
2015+
" pass\n",
19232016
"\n",
2017+
"class ReportGenerator:\n",
2018+
" def generate_report(self, employee):\n",
2019+
" # Generate employee report\n",
2020+
" pass\n",
2021+
"\n",
2022+
"class EmployeeRepository:\n",
2023+
" def save_to_database(self, employee):\n",
2024+
" # Save employee data to database\n",
2025+
" pass"
2026+
]
2027+
},
2028+
{
2029+
"cell_type": "markdown",
2030+
"id": "259b858a",
2031+
"metadata": {},
2032+
"source": [
19242033
"### O: Open/Closed\n",
1925-
"- a class should be open to extension but closed to modification\n",
19262034
"\n",
2035+
"- \"Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.\"\n",
2036+
"- Open for Extension: \n",
2037+
" - you should be able to add new functionality to your software without changing the existing code\n",
2038+
"- Closed for Modification\n",
2039+
" - once a piece of code is written and tested, you shouldn't need to modify its source code to accommodate new requirements\n",
2040+
" \n",
2041+
"#### Why is this important?\n",
2042+
"\n",
2043+
"- reduced risk of introducing bugs\n",
2044+
" - modifying existing code can introduce unintended side effects and break working functionality\n",
2045+
" - by extending instead of modifying, you minimize this risk\n",
2046+
" \n",
2047+
"- increased maintainability\n",
2048+
" - code that adheres to the OCP is easier to maintain and adapt to changing requirements\n",
2049+
"\n",
2050+
"- improved reusability\n",
2051+
" - well-designed, extensible code can be reused in different parts of your application or in other projects\n",
2052+
" \n",
2053+
"- enhanced stability\n",
2054+
" - stable, unmodified code provides a reliable foundation for building new features\n",
2055+
" \n",
2056+
"#### How to Achieve the Open/Closed Principle:\n",
2057+
"\n",
2058+
"- common techniques for achieving the OCP include:\n",
2059+
"\n",
2060+
"- **Abstraction**: \n",
2061+
" - using abstract classes or interfaces to define a contract that concrete classes must adhere to\n",
2062+
" \n",
2063+
"- **Inheritance**: \n",
2064+
" - creating new classes that inherit from existing classes and override or extend their behavior\n",
2065+
"\n",
2066+
"- **Polymorphism**: \n",
2067+
" - writing code that can work with objects of different types through a common interface\n",
2068+
" \n",
2069+
"- **Composition**: \n",
2070+
" - building complex objects by combining simpler objects, rather than inheriting from them\n",
2071+
" \n",
2072+
"- **Design Patterns**: \n",
2073+
" - using design patterns like the Strategy, Template Method, and Observer patterns, which are specifically designed to promote extensibility\n",
2074+
" \n",
19272075
"### L: Liskov Substitution\n",
2076+
"\n",
2077+
"- **inheritance** must follow L - Liskov Substitution principle\n",
19282078
"- named after Barbara Liskov creator of CLU programming language\n",
19292079
"- any subclass can be substituted for its superclass\n",
19302080
" - any code that uses superclass can be replaced with it's subclass without breaking any code!\n",
@@ -1940,25 +2090,6 @@
19402090
"- if two classes depend on each other, use a mixin class to reuse the dependence"
19412091
]
19422092
},
1943-
{
1944-
"cell_type": "markdown",
1945-
"id": "9f680e25",
1946-
"metadata": {},
1947-
"source": [
1948-
"## Inheritance Tax\n",
1949-
"\n",
1950-
"- \"You wanted a banana but what you got was a gorilla holding the banana and the entire jungle\" - Joe Armstrong\n",
1951-
"- inheritance is a powerful tool but it can be misused\n",
1952-
"- alternatives may be better to avoid the inheritance tax:\n",
1953-
" - interfaces and protocols\n",
1954-
" - delegation\n",
1955-
" - mixins\n",
1956-
"- interfaces and protocols give us polymorphism without inheritance\n",
1957-
"- delegation is a way to use composition instead of inheritance\n",
1958-
"- delegate to services - Has-A relationship Trumps Is-A relationship\n",
1959-
"- use mixins to share code and functionality\n"
1960-
]
1961-
},
19622093
{
19632094
"cell_type": "markdown",
19642095
"id": "86ab0315",

0 commit comments

Comments
 (0)