262 lines
6.5 KiB
Markdown
262 lines
6.5 KiB
Markdown
# 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*
|