5.7 עקרונות סוליד הרצאה
הבעיה בOOP¶
- שימוש לא נכון בOOP יכול להיות רע מאוד, הקוד שלכם מהר מאוד יכול להיות לא קריא, לא ברור ובאגי.
עקרונות סוליד - SOLID¶
- עקרונות סוליד (SOLID) יכולים לעזור לנו לפתח עם OOP בצורה טובה יותר.
- הראשי תיבות של SOLID הן:
- S - Single-Responsibility Principle
- O - Open-Closed Principle
- L - Liskov substitution principle
- I - Interface segregation principle
- D - Dependency inversion principle
- בהרצאה הזו נעבור על כל אחת העקרונות הללו.
עקרון: Single-Responsibility Principle - משמעות אחת¶
-
למחלקה צריכה להיות רק אחריות אחת או תפקיד אחד
-
אחריות אחת:
- מחלקה צריכה להיות מתוכננת לטפל רק באחריות או דאגה ספציפית אחת. זה הופך את המחלקה לממוקדת ומבטיחה שהיא עושה דבר אחד ועושה אותו טוב.
- יתרונות:
- קריאות קוד קלה יותר: כאשר לכל מחלקה יש אחריות אחת, קל יותר להבין מה כל מחלקה עושה.
- תחזוקה קלה יותר: כאשר לכל מחלקה יש אחריות אחת, יהיה קל יותר לשנות דברים בקוד שלה ולתקן באגים. למה? בגלל שלמחלקה יהיה פחות קוד, כי לכל מחלקה יש תחום אחריות אחד.
# Without SRP
class Report:
def generate_report(self, data):
# Code to generate the report
pass
def save_to_database(self, report_data):
# Code to save the report to the database
pass
# With SRP
class ReportGenerator:
def generate_report(self, data):
# Code to generate the report
pass
class ReportSaver:
def save_to_database(self, report_data):
# Code to save the report to the database
pass
עקרון: Open-Closed Principle - פתוח-סגור¶
-
מחלקה צריכה להיות פתוחה להרחבות אבל סגורה לשינויים.
-
פתוח להרחבה:
- מחלקה צריכה להיות בנוייה בצורה שיהיה קל לנו להוסיף לה קוד, מבלי לשנות את הקוד שכבר קיים במחלקה.
- סגור לשינויים:
- אין לשנות את קוד של מחלקה שכבר קיים כדי להוסיף פונקציונליות חדשה למחלקה. במקום זאת, המחלקה מריכה להיות מתוכננת באופן המאפשר הרחבות בלי שינויים.
- יתרונות:
- יכולת תחזוקה: מכיוון שהקוד הקיים אינו משתנה, יש פחות סיכון לבאגים או תופעות לוואי לא מכוונות בעת הוספת תכונות חדשות למחלקה.
- שימוש באבסטרקציה:
- כדי להשיג את עקרון הפתוח-סגור, לעתים קרובות משתמשים באבסטרקציה. זה כולל הגדרת מחלקות אבסטרקציות או ממשקים.
עקרון: Liskov substitution principle - חילוף¶
-
מחלקות בת לא יכולות להחליף את המחלקות אבא שלהן עם לגרום לשגיאות.
-
בלי הפתעות:
- תת-מחלקות אמורות לעבוד כרגיל כשמחליפים את המחלקת אב שלהם. כמו שראינו בפרק הקודם יכולים להיות מצבים שהקוד תלוי בכך שמחלקת בת מסויימת מימשה מתודה מסויימת מהמחלקת אב שלה, ואם יום אחד המחלקת אב תתחלף, והמתודה כבר לא תהיה קיימת במחלקת אב, המחלקת בן עדיין צריכה לממש אותה כדי שהקוד עדיין יעבוד.
- שימוש בפולימורפיזם:
- השתמשו בפולימורפיזם! הדרך שלנו לוודא שמתודת אב מסויימת לא תעלם יום אחד היא לממש אותה בעצמנו.
עקרון: Interface segregation principle - הפרדת ממשק¶
-
מחלקות לא צריכות ליישם ממשקים שהן לא צריכות.
-
הימנעות מיישומים כפויים:
- על ידי יצירת ממשקים ספציפיים, מחלקות אינן נאלצות ליישם מתודות שאינן רלוונטיות לפונקציונליות שלהן. זה עוזר בהפחתת תלות מיותרת ובעיות פוטנציאליות הקשורות ליישום שיטות שאין להן משמעות בהקשר של מחלקה מסוימת.
- מניעת ממשקים גדולים:
- ממשקים גדולים, המכילים מתודות רבות, עלולים להיות בעייתיים. מחלקות שמיישמים ממשקים כאלה עלולים להיות כבדים באחריות מיותרת. העקרון ממליץ לפרק ממשקים כאלה לממשקים קטנים יותר וממוקדים יותר כדי למנוע בעיה זו.
# Without ISP
class Worker:
def work(self):
pass
def eat(self):
pass
# With ISP
class Workable:
def work(self):
pass
class Eatable:
def eat(self):
pass
class Worker(Workable, Eatable):
pass
עקרון: Dependency inversion principle - היפוך תלות¶
- מחלקות לא יכולות להיות תלויות במחלקות אחרות כל כך בקלות, כאשר מחלקות צריכות להיות תלויות באבסטרקציות
הסתכלו על הדוגמה הבאה:
# Without DIP class LightBulb: def turn_on(self): # Code to turn on the light bulb pass class Switch: def control_light(self, bulb): bulb.turn_on()
בדוגמה הראשונה, מחלקתSwitchתלויה ישירות במחלקהLightBulb, ויוצרת חיבור הדוק ביניהם.
# With DIP
from abc import ABC, abstractmethod
class Switchable(ABC):
@abstractmethod
def turn_on(self):
pass
class LightBulb(Switchable):
def turn_on(self):
# Code to turn on the light bulb
pass
class Switch:
def control_light(self, device: Switchable):
device.turn_on()
בדוגמה השנייה, גם
Switch וגם LightBulb תלויים באבסטרקציה (Switchable), מה שמאפשר יותר גמישות והחלפה של סוגי "מכשירים" יותר בקלות.