Skip to content

Principy vývoje SW

Owner: Daniel Vítek Tags: designpatterns

1. DRY (Don't Repeat Yourself)

Význam: Tento princip říká, že byste se měli vyvarovat opakování stejného kódu na více místech. Když opakujete stejné bloky kódu, je těžší je spravovat, aktualizovat nebo opravovat.

Špatný kód:

def calculate_tax(price):
    return price * 0.15

def calculate_total(price):
    return price + (price * 0.15)

Zde máme dvě funkce, které obě používají stejné výpočty pro daň. Pokud by se změnil způsob výpočtu daně, museli bychom změnit kód na dvou místech.

Dobrý kód:

def calculate_tax(price):
    return price * 0.15

def calculate_total(price):
    return price + calculate_tax(price)

V tomto případě se výpočet daně centralizuje v jedné funkci, což je efektivní a snadno spravovatelné.

2. CoC (Convention over Configuration)

Význam: Tento princip znamená, že byste měli používat standardní konvence a nastavení, pokud není potřeba specifikovat jiná nastavení. To zjednodušuje konfiguraci a zrychluje vývoj.

Špatný kód:

Když je nutné specifikovat mnoho konfiguračních parametrů, místo použití běžných konvencí.

db_connection = connect(host="localhost", port=5432, username="admin", password="password")

Dobrý kód:

Použití výchozích hodnot a konvencí.

db_connection = connect()  # Použije výchozí hodnoty pro host, port, atd.

3. SOLID Principles

Význam: SOLID je soubor pěti zásad pro objektově orientované programování, které pomáhají psát udržitelný, rozšiřitelný a flexibilní kód.

a) Single Responsibility Principle (SRP)

Význam: Tato zásada říká, že třída by měla mít pouze jednu odpovědnost, tedy jednu úlohu. Pokud třída vykonává více než jednu věc, je těžší ji udržovat a testovat.

Špatný kód:

class Order:
    def __init__(self, items):
        self.items = items

    def calculate_total(self):
        total = 0
        for item in self.items:
            total += item.price
        return total

    def save_to_db(self):
        # Kód pro uložení objednávky do databáze
        pass

Dobrý kód:

class Order:
    def __init__(self, items):
        self.items = items

    def calculate_total(self):
        total = 0
        for item in self.items:
            total += item.price
        return total

class OrderRepository:
    def save(self, order):
        # Kód pro uložení objednávky do databáze
        pass

b) Open/Closed Principle (OCP)

Význam: Třídy by měly být otevřeny pro rozšíření, ale uzavřeny pro modifikace. To znamená, že můžete přidávat nové funkce do existující třídy bez jejího změnění.

Špatný kód:

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

class AreaCalculator:
    def calculate_area(self, rectangle):
        if isinstance(rectangle, Rectangle):
            return rectangle.area()
        # Možná přidání dalších tvarů v budoucnu by vedlo k úpravám této třídy.

Dobrý kód:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius * self.radius

class AreaCalculator:
    def calculate_area(self, shape: Shape):
        return shape.area()

c) Liskov Substitution Principle (LSP)

Význam: Funkce, která pracuje s objekty nadtřídy, by měla správně fungovat i s objekty podtříd. Tedy podtřídy by měly být záměnné za své nadtřídy.

Špatný kód:

class Bird:
    def fly(self):
        pass

class Ostrich(Bird):
    def fly(self):
        raise NotImplementedError  # Pštros není schopen létat

Dobrý kód:

class Bird(ABC):
    @abstractmethod
    def move(self):
        pass

class Sparrow(Bird):
    def move(self):
        return "Flying"

class Ostrich(Bird):
    def move(self):
        return "Running"

d) Interface Segregation Principle (ISP)

Význam: Měli byste se vyvarovat vytváření velkých a složitých rozhraní. Místo toho rozdělte rozhraní na menší, specifičtější části, které budou lépe odpovídat potřebám uživatelů.

Špatný kód:

class Worker:
    def work(self):
        pass
    def eat(self):
        pass

Dobrý kód:

class Workable:
    def work(self):
        pass

class Eatable:
    def eat(self):
        pass

class Worker(Workable, Eatable):
    def work(self):
        pass

    def eat(self):
        pass

e) Dependency Inversion Principle (DIP)

Význam: Moduly vyšší úrovně by neměly záviset na modulech nižší úrovně, ale na abstrakcích (rozhraních). Detaily by měly záviset na abstrakcích, ne na konkrétních implementacích.

Špatný kód:

class FileManager:
    def save(self, data):
        with open('file.txt', 'w') as f:
            f.write(data)

Dobrý kód:

class DataSaver(ABC):
    @abstractmethod
    def save(self, data):
        pass

class FileManager(DataSaver):
    def save(self, data):
        with open('file.txt', 'w') as f:
            f.write(data)

class DatabaseSaver(DataSaver):
    def save(self, data):
        # Kód pro uložení do databáze
        pass

4. KISS (Keep It Simple, Stupid)

Význam: Tento princip říká, že systém by měl být co nejjednodušší a přímočarý. Nepřidávejte složitost tam, kde není nezbytná.

Špatný kód:

Kód, který je zbytečně složitý a těžko pochopitelný.

def process_order(order):
    if order.status == 'new':
        if order.item_type == 'premium':
            # Složitý kód pro zpracování prémiového zboží
            pass
        else:
            # Jiný složitý kód pro běžné zboží
            pass

Dobrý kód:

Kód, který je přehledný a jednoduchý na pochopení.

def process_order(order):
    if order.is_premium():
        # Kód pro zpracování prémiového zboží
        pass
    else:
        # Kód pro zpracování běžného zboží
        pass

5. YAGNI (You Aren't Gonna Need It)

Význam: Nepřidávejte funkcionalitu, dokud ji skutečně nebudete potřebovat. Pokud něco není okamžitě nutné, neimplementujte to.

Špatný kód:

Předvídání potřeb a implementace funkcí, které zatím nebudete používat.

class Order:
    def calculate_discount(self):
        # Předpokládaný mechanismus pro slevy, který není aktuálně potřebný
        pass

Dobrý kód:

Implementace pouze toho, co je opravdu potřebné.

class Order:
    def calculate_total(self):
        total = 0
        for item in self.items:
            total += item.price
        return total

6. CQRS (Command Query Responsibility Segregation)

Význam: Tento princip rozděluje operace na dva typy: příkazy (Commands), které mění stav systému, a dotazy (Queries), které pouze vrací data, aniž by měnily stav.

Špatný kód:

Kombinování příkazů a dotazů do jedné metody.

class Order:
    def update_status(self, status):
        self.status = status
        return self.status  # Vrací hodnotu i mění stav

Dobrý kód:

Oddělení příkazů a dotazů.

class Order:
    def update_status(self, status):
        self.status = status

    def get_status(self):
        return self.status

7. SoC (Separation of Concerns)

Význam: Rozdělení kódu do různých vrstev, kde každá vrstva se stará pouze o jeden aspekt aplikace. To usnadňuje údržbu a testování.

Špatný kód:

Kód, který míchá různé aspekty (například logiku aplikace a rozhraní).

class User:
    def save_to_db(self):
        pass
    def send_email(self):
        pass

Dobrý kód:

Oddělení odpovědností do různých tříd.

class User:
    def save(self):
        pass

class EmailService:
    def send_welcome_email(self, user):
        pass

Tento dokument shrnuje klíčové principy vývoje softwaru, které vedou k lepší udržovatelnosti, čitelnosti a efektivitě kódu.