# LF 11a: Funktionalität in Anwendungen realisieren > **3. Ausbildungsjahr** | Zeitrichtwert: **80 Stunden** ## Kernkompetenz Die Schülerinnen und Schüler verfügen über die Kompetenz, modulare Komponenten zur informationstechnischen Verarbeitung von Arbeitsabläufen und Geschäftsprozessen zu entwickeln und deren Qualität zu sichern. --- ## Lernziele Nach diesem Lernfeld kannst du: - [ ] Datenstrukturen und Funktionalitäten aus Anforderungen ableiten - [ ] Modulare Softwarekomponenten planen - [ ] Objektorientierte Programmierung anwenden - [ ] Schnittstellen dokumentieren - [ ] Testfälle formulieren und automatisierte Tests durchführen - [ ] Qualitätskriterien anwenden --- ## Objektorientierte Programmierung (OOP) ### Grundkonzepte ``` OOP-Prinzipien: ├── Kapselung (Encapsulation) │ └── Daten und Methoden zusammenfassen ├── Vererbung (Inheritance) │ └── Gemeinsame Eigenschaften vererben ├── Polymorphismus │ └── Gleiches Verhalten, unterschiedliche Formen └── Abstraktion └── Komplexität reduzieren ``` ### Klassen-Beispiel (Python) ```python from abc import ABC, abstractmethod from datetime import datetime class Kunde(ABC): """Abstrakte Basisklasse für Kunden""" def __init__(self, kundennummer: int, name: str): self._kundennummer = kundennummer self._name = name self._erstellt_am = datetime.now() @property def kundennummer(self) -> int: return self._kundennummer @abstractmethod def berechne_rabatt(self, betrag: float) -> float: """Berechnet den Rabatt für den Kunden""" pass def __str__(self) -> str: return f"Kunde {self._kundennummer}: {self._name}" class Privatkunde(Kunde): """Privatkunde mit Standard-Rabatt""" def __init__(self, kundennummer: int, name: str): super().__init__(kundennummer, name) self._rabatt_stufe = 1 def berechne_rabatt(self, betrag: float) -> float: return betrag * 0.05 * self._rabatt_stufe class Firmenkunde(Kunde): """Firmenkunde mit erhöhtem Rabatt""" def __init__(self, kundennummer: int, name: str, firmenname: str): super().__init__(kundennummer, name) self._firmenname = firmenname self._rabatt_stufe = 2 def berechne_rabatt(self, betrag: float) -> float: return betrag * 0.10 * self._rabatt_stufe ``` --- ## Entwurfsmuster (Design Patterns) ### Singleton ```python class DatabaseConnection: """Singleton für Datenbankverbindung""" _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) cls._instance.connection = None return cls._instance def connect(self, connection_string: str): if self.connection is None: print(f"Verbinde mit: {connection_string}") self.connection = "Datenbankverbindung hergestellt" def disconnect(self): if self.connection: print("Trenne Verbindung") self.connection = None ``` ### Factory Method ```python class KundeFactory: """Factory für Kunden-Erstellung""" @staticmethod def create_kunde(kundentyp: str, **kwargs) -> Kunde: if kundentyp == "privat": return Privatkunde(**kwargs) elif kundentyp == "firma": return Firmenkunde(**kwargs) else: raise ValueError(f"Unbekannter Kundentyp: {kundentyp}") ``` --- ## Schnittstellen ### API-Design ```python from typing import List, Optional from pydantic import BaseModel class BestellPosition(BaseModel): """Datenmodell für Bestellposition""" artikel_id: int menge: int einzelpreis: float class Bestellung(BaseModel): """Datenmodell für Bestellung""" bestell_id: Optional[int] = None kundennummer: int positionen: List[BestellPosition] gesamtpreis: float def berechne_gesamtsumme(self) -> float: return sum(p.menge * p.einzelpreis for p in self.positionen) ``` ### REST-API mit FastAPI ```python from fastapi import FastAPI, HTTPException from typing import List app = FastAPI(title="Bestell-API") bestellungen: List[Bestellung] = [] @app.post("/bestellungen", response_model=Bestellung) async def create_bestellung(bestellung: Bestellung): """Neue Bestellung erstellen""" bestellung.gesamtpreis = bestellung.berechne_gesamtsumme() bestellung.bestell_id = len(bestellungen) + 1 bestellungen.append(bestellung) return bestellung @app.get("/bestellungen/{bestell_id}") async def get_bestellung(bestell_id: int): """Bestellung abrufen""" for b in bestellungen: if b.bestell_id == bestell_id: return b raise HTTPException(status_code=404, detail="Nicht gefunden") ``` --- ## Qualitätssicherung ### Testmethoden ``` Test-Pyramide: ╱╲ ╱ ╲ E2E Tests ╱────╲ ╱ ╲ Integrationstests ╱────────╲ ╱ ╲ Unit-Tests ╱────────────╲ ``` ### Unit-Tests (pytest) ```python import pytest from bestellung import Bestellung, BestellPosition class TestBestellung: @pytest.fixture def beispiel_bestellung(self): positionen = [ BestellPosition(artikel_id=1, menge=2, einzelpreis=10.00), BestellPosition(artikel_id=2, menge=1, einzelpreis=25.00) ] return Bestellung(kundennummer=100, positionen=positionen) def test_gesamtsumme_berechnung(self, beispiel_bestellung): """Test der Gesamtsummen-Berechnung""" ergebnis = beispiel_bestellung.berechne_gesamtsumme() # 2 × 10 + 1 × 25 = 45 assert ergebnis == 45.00 def test_leere_bestellung(self): """Test mit leerer Positionen-Liste""" bestellung = Bestellung(kundennummer=100, positionen=[]) ergebnis = bestellung.berechne_gesamtsumme() assert ergebnis == 0.00 ``` --- ## Handlungsphasen 1. **Analysieren**: Anforderungen verstehen, Datenmodelle ableiten 2. **Planen**: Module und Schnittstellen entwerfen 3. **Implementieren**: Komponenten entwickeln 4. **Testen**: Tests durchführen, Qualität sichern 5. **Optimieren**: Verbesserungen einarbeiten --- ## Prüfungsrelevanz - Programmierkenntnisse für Teil 2 - Wichtig für Abschlussprojekt --- ## Querverweise - [[3-Ausbildungsjahr/LF10a-Benutzeroberflächen|Vorher: LF 10a]] - [[3-Ausbildungsjahr/LF12a-Kundenspezifische-Entwicklung|Nachher: LF 12a]] - [[Programmiersprachen/Python|OOP mit Python]] --- *Stand: 2024 | Quelle: KMK Rahmenlehrplan 13.12.2019*