Clean Code - Class
Single Responsibility Principle (SRP)
一個模組應只對唯一一個使用者或利益相關者負責。
Bad
from importlib import metadata
class VersionCommentElement:
"""An element that renders an HTML comment with the program's version number
"""
def get_version(self) -> str:
"""Get the package version"""
return metadata.version("pip")
def render(self) -> None:
print(f'<!-- Version: {self.get_version()} -->')
VersionCommentElement().render()
Good
from importlib import metadata
def get_version(pkg_name: str) -> str:
"""Retrieve the version of a given package"""
return metadata.version(pkg_name)
class VersionCommentElement:
"""An element that renders an HTML comment with the program's version number
"""
def __init__(self, version: str):
self.version = version
def render(self) -> None:
print(f'<!-- Version: {self.version} -->')
VersionCommentElement(get_version("pip")).render()
Open-Close Principle (OCP)
可以在不修改現有的原始碼的前提下,變更他的行為或實作新的功能。
Liskov Substitution Principle (LSP)
子型態必須遵從父型態的行為進行設計。
Interface Segregation Principle (ISP)
模組與模組之間的依賴,不應該有用不到的功能可以被對方呼叫
Dependency Inversion Principle (DIP)
高層模組不應依賴底層模組,他們都應該依賴於抽象介面。抽象介面不應該依賴於具體實作,具體實作應依賴抽象介面。
Don’t repeat yourself (DRY)
Bad:
from typing import List, Dict
from dataclasses import dataclass
@dataclass
class Developer:
def __init__(self, experience: float, github_link: str) -> None:
self._experience = experience
self._github_link = github_link
@property
def experience(self) -> float:
return self._experience
@property
def github_link(self) -> str:
return self._github_link
@dataclass
class Manager:
def __init__(self, experience: float, github_link: str) -> None:
self._experience = experience
self._github_link = github_link
@property
def experience(self) -> float:
return self._experience
@property
def github_link(self) -> str:
return self._github_link
def get_developer_list(developers: List[Developer]) -> List[Dict]:
developers_list = []
for developer in developers:
developers_list.append({
'experience': developer.experience,
'github_link': developer.github_link
})
return developers_list
def get_manager_list(managers: List[Manager]) -> List[Dict]:
managers_list = []
for manager in managers:
managers_list.append({
'experience': manager.experience,
'github_link': manager.github_link
})
return managers_list
## create list objects of developers
company_developers = [
Developer(experience=2.5, github_link='<https://github.com/1>'),
Developer(experience=1.5, github_link='<https://github.com/2>')
]
company_developers_list = get_developer_list(developers=company_developers)
## create list objects of managers
company_managers = [
Manager(experience=4.5, github_link='<https://github.com/3>'),
Manager(experience=5.7, github_link='<https://github.com/4>')
]
company_managers_list = get_manager_list(managers=company_managers
Good:
from typing import List, Dict
from dataclasses import dataclass
@dataclass
class Employee:
def __init__(self, experience: float, github_link: str) -> None:
self._experience = experience
self._github_link = github_link
@property
def experience(self) -> float:
return self._experience
@property
def github_link(self) -> str:
return self._github_link
def get_employee_list(employees: List[Employee]) -> List[Dict]:
employees_list = []
for employee in employees:
employees_list.append({
'experience': employee.experience,
'github_link': employee.github_link
})
return employees_list
## create list objects of developers
company_developers = [
Employee(experience=2.5, github_link='<https://github.com/1>'),
Employee(experience=1.5, github_link='<https://github.com/2>')
]
company_developers_list = get_employee_list(employees=company_developers)
## create list objects of managers
company_managers = [
Employee(experience=4.5, github_link='<https://github.com/3>'),
Employee(experience=5.7, github_link='<https://github.com/4>')
]
company_managers_list = get_employee_list(employees=company_managers)