Frau Aydin fragt nach der Inventur das, was jede Fachperson fragt: „Und womit fangen wir an? Können wir nicht einfach den Kundenstamm als Erstes ins Web bringen?“ Vielleicht ja. Vielleicht hängt der Kundenstamm aber an Dingen, die vorher fertig sein müssen. Diese Lektion gibt Ihnen ein Muster, das die Frage ordnet, und ein kleines Skript, das die Reihenfolge begründet.

Das Muster heißt Strangler Fig, nach einer Pflanze, die einen Baum nach und nach umwächst, bis er entbehrlich ist. Es ist das Muster dieses Kurses: Das Altprogramm läuft weiter, das Neue wächst daneben, und am Ende wird das Alte abgeschaltet. K4, Modul 4.11 (Architekturstile) zeigt es in der Breite; hier wenden Sie es auf ein Desktop-Programm an.

Das Muster nach Microsoft Learn

Microsofts Beschreibung geht vom Problem aus: Je älter ein System wird, desto eher sind seine Entwicklungswerkzeuge, seine Hosting-Technik und seine Architektur überholt, und mit jeder neuen Funktion wird es schwerer zu pflegen. Ein komplexes System auf einmal zu ersetzen ist schwierig. Es gradweise zu ersetzen hat ein eigenes Problem: Wer zwei Versionen parallel betreibt, muss den Clients sagen, welche Funktion wo liegt.

Die Lösung besteht aus einer Fassade (einem Proxy), die Anfragen entgegennimmt und entweder an das Altsystem oder an das neue System weiterreicht. Die Kunden benutzen weiter dieselbe Schnittstelle und merken nicht, dass gewandert wird. Das Muster läuft in vier Phasen:

mermaid
flowchart LR
    subgraph P1["Phase 1: Fassade einführen"]
        C1[Client] --> F1[Fassade]
        F1 -->|fast alles| A1[Altsystem]
        F1 -->|wenig| N1[Neues System]
    end
    subgraph P2["Phase 2: schrittweise verlagern"]
        C2[Client] --> F2[Fassade]
        F2 -->|weniger| A2[Altsystem]
        F2 -->|mehr| N2[Neues System]
    end
    subgraph P3["Phase 3: Altsystem abschalten"]
        C3[Client] --> F3[Fassade]
        F3 --> N3[Neues System]
    end
    subgraph P4["Phase 4: Fassade entfernen"]
        C4[Client] --> N4[Neues System]
    end
    P1 --> P2 --> P3 --> P4

Dazu nennt Microsoft Punkte, die Sie bedenken müssen:

  • Gemeinsame Daten. Dienste und Datenspeicher, die Alt und Neu beide nutzen, müssen gleichzeitig erreichbar sein.
  • Klare Grenzen. Bauen Sie Neues so, dass es sich später wieder leicht abfangen und ersetzen lässt.
  • Die Fassade ist vorübergehend. Normalerweise entfernen Sie sie am Ende. Sie kann auch als Adapter für alte Clients bleiben. Wägen Sie den Nutzen gegen die Kosten dieser Übergangsarchitektur ab.
  • Die Fassade darf nicht zum Engpass werden, weder als Ausfallstelle noch bei der Leistung, und sie muss mit der Migration Schritt halten.
  • Abhängigkeiten zwischen den Systemen. Alt und Neu müssen sich eine Weile aufrufen. Dafür empfiehlt Microsoft den Anti-Corruption-Layer: einen Adapter, der Aufrufe übersetzt und den Entwurf des Neuen vor den Begriffen des Alten schützt.
  • Nicht änderbare Altteile. Bei datenbankzentrierten Anwendungen kann die Datenbank selbst Nachrichten an neue Dienste senden, ohne dass das Altprogramm sich ändert. Microsoft nennt dafür einen Trigger oder die Änderungsnachverfolgung (Change Data Capture).

Das Beispiel in Microsofts Dokumentation überträgt das Muster auf eine Datenbank: Ein neuer Dienst bedient zuerst seine Tabellen in der alten Datenbank, dann bekommt er eine eigene Datenbank, die per Kopie und Änderungsnachverfolgung synchron gehalten wird. Nach einer Prüfung wird sie das führende System für diesen Bereich, und erst dann entfernt man die alten Tabellen. Bis dahin ist der Rückweg möglich; danach kostet er viel Aufwand und Risiko. Das Entfernen alter Objekte ist deshalb ein bewusster letzter Schritt je Bereich.

Wann das Muster nicht passt

Microsoft nennt vier Fälle, in denen es ungeeignet sein kann:

Fall Warum
Anfragen an das Altsystem lassen sich nicht abfangen Ohne Stelle zum Umleiten gibt es keine Fassade
kein Zugriff auf den Quelltext und keine andere änderbare Schnittstelle (etwa die Datenbank) Umgeleitete Funktionen müssen sich im Altsystem abschalten lassen
ein kleines System, dessen Ersatz einfach ist Der Aufwand des Musters übersteigt den Nutzen
das Original muss schnell vollständig abgelöst werden Das Muster setzt einen langen Parallelbetrieb voraus

Gelten für das Auftragsbuch alle vier? Der dritte und vierte Fall treffen nicht zu: Das Programm ist klein, aber seine Regeln sind es nicht, und es muss nicht schnell abgelöst werden. Prüfen wir die ersten beiden.

Das Muster beim Desktop-Programm

Das Auftragsbuch hat ein Problem mit dem ersten Fall: Es gibt keine Anfragen, die ein Proxy abfangen könnte. Das Programm läuft auf dem Rechner von Frau Aydin und spricht mit ADO.NET direkt mit der Datenbank. Es gibt keine Stelle im Netz, an der man umleiten könnte. Der zweite Fall trifft nicht zu: Sie haben den Quelltext, können das Altprogramm ändern, und die Datenbank ist eine zweite Schnittstelle, die Sie ändern können.

Deshalb ist die Fassade beim Desktop-Programm kein Proxy, sondern eine gemeinsame Schicht, auf die Alt und Neu zugreifen. Sie entsteht in drei Stufen, die dieser Kurs nacheinander baut:

  1. Die Fachlogik wandert aus den Formularen in eine Bibliothek (Lektion M3.1).
  2. Eine Web-API stellt die Bibliothek zur Verfügung (Lektion M4.1). Sie ist die Schnittstelle, die Web und Windows-Programm teilen.
  3. Das Windows-Programm ruft die API auf, Funktion für Funktion, mit einem Schalter je Funktion (Lektion M4.2). Das ist der Ersatz für die Umleitung des Proxys: Der Schalter entscheidet, ob eine Funktion alt (Datenbank) oder neu (API) läuft.
mermaid
flowchart TD
    subgraph Heute
        F0[Formulare] --> D0[DataSet] --> DB0[(Datenbank)]
    end
    subgraph Nach_M3[Nach Modul 3]
        F1[Formulare] --> L1[Bibliothek] --> DB1[(Datenbank)]
    end
    subgraph Nach_M4[Nach Modul 4]
        F2["Formulare, Funktion für Funktion"] -->|Schalter| API[Web-API]
        W2[Blazor-Seiten] --> API
        API --> L2[Bibliothek] --> DB2[(Datenbank)]
    end
    Heute --> Nach_M3 --> Nach_M4

Das ist eine Übertragung des Musters, nicht Microsofts Wortlaut. Die Phasen bleiben dieselben: eine gemeinsame Stelle einführen, Funktion für Funktion verlagern, das Alte abschalten, die Zwischenschicht abbauen. Die Anforderungen aus Microsofts Liste gelten unverändert: Die gemeinsame Datenbank braucht klare Besitzer (Lektion M3.3), Alt und Neu brauchen einen Anti-Corruption-Layer, wo sie sich gegenseitig aufrufen, und die Fassade ist eine Übergangsarchitektur (Lektion M6.5 baut sie wieder ab).

Nähte finden

Eine Naht ist eine Stelle, an der sich das Programm mit wenig Aufwand teilen lässt, weil dort wenig durchläuft. Gute Nähte haben fünf Eigenschaften:

Eigenschaft Frage
schmale Schnittstelle Wie viele Pfeile der Landkarte kreuzen den Schnitt?
eigene Daten Gehört ein Datenstück eindeutig auf eine Seite des Schnitts?
testbar vorher Lässt sich das Verhalten festhalten, bevor etwas geändert wird (Lektion M2.1)?
fachlich benennbar Kennt Frau Aydin den Namen („Preisregeln“, „Wartungsplan“)?
einzeln auslieferbar Hat der Schnitt für sich einen Nutzen, auch wenn der Rest warten muss?

So finden Sie sie in der Landkarte aus Lektion M1.3: Ziehen Sie gedanklich Linien durch das Diagramm und zählen Sie die Pfeile, die sie kreuzen. Wenige Pfeile, eine Naht. Die Bruchstellen aus Lektion M1.2 sind Kandidaten, denn jede ist ein Ort, an dem etwas herausgelöst werden muss. Für das Auftragsbuch ergeben sich neun:

Id Naht Bruchstelle Was die Linie kreuzt
N1 Preisregeln aus HauptForm in eine Bibliothek B5 zwei Aufrufer (Druck, Export), Eingaben aus einer Zeile und der Konfiguration
N2 Konfiguration aus App.config B2 Einstellungen ist die einzige Klasse, die App.config kennt
N3 Datenzugriff: DataSet durch Entity Framework Core ersetzen B4 jedes Formular, daher breit
N4 Wartungsregel: Trigger und Prozedur in die Bibliothek B6 unsichtbar: der Trigger wird von keinem Programm aufgerufen
N5 Auftragsliste als Web-API und Blazor-Seite B4, B11 Daten, Preisregeln, Zustand
N6 Rechnungsdruck als PDF B7 Rechnungsdruck und Preisregeln
N7 Dateiexport in den Blob-Speicher B8 der Ordner auf dem Netzlaufwerk, ein Leser auf der anderen Seite
N8 Anmeldung mit Microsoft Entra ID B3 Rechte in jeder Funktion
N9 Kundenkarte mit WebView2 B9 ein Formular, kein Datenzugriff

Zwei Nähte sind trügerisch. N3 sieht aus wie eine Naht, ist aber eine Wand: Jedes Formular hängt dran. Und N4 hat keinen einzigen Aufrufer, den Sie finden könnten. Genau deshalb ist sie riskant: Wer sie übersieht, verliert die Regel.

Reihenfolge nach Risiko und Nutzen

Jede Naht bekommt zwei Zahlen von eins bis fünf: Nutzen (was der Betrieb davon hat, auch den Menschen, nicht nur der Technik) und Risiko (wie wahrscheinlich ist ein Fehler, wie groß wäre er). Es sind Urteile, keine Messungen. Schreiben Sie dazu, wer sie vergeben hat und warum; was das Team nicht weiß, bleibt eine offene Frage. Daraus ergibt sich ein Wert, Nutzen geteilt durch Risiko: Viel Nutzen bei wenig Risiko kommt zuerst. Microsofts Dokumentation zum Muster beschreibt dasselbe Ziel: Ersetzungen mit hohem Ertrag sollen vor denen mit niedrigem kommen.

Eine Regel kommt dazu, die den Wert überstimmt: Keine Naht steht vor ihrer Voraussetzung. Die Auftragsliste im Web (N5) hat einen hohen Nutzen, aber sie braucht die Preisregeln (N1) und den neuen Datenzugriff (N3). Die Voraussetzungen stehen in der Datei:

Id;Naht;Nutzen;Risiko;Voraussetzung
N1;Preisregeln aus HauptForm in eine Bibliothek;5;2;
N2;Konfiguration aus App.config;3;1;
N3;Datenzugriff: DataSet durch Entity Framework Core ersetzen;4;4;N1
N4;Wartungsregel: Trigger und Prozedur in die Bibliothek;4;5;N1,N3
N5;Auftragsliste als Web-API und Blazor-Seite;5;3;N1,N3
N6;Rechnungsdruck als PDF;3;3;N1
N7;Dateiexport in den Blob-Speicher;2;2;N1
N8;Anmeldung mit Microsoft Entra ID;4;4;N5
N9;Kundenkarte mit WebView2;2;1;

Ein Skript ordnet die Nähte: Es wählt jeweils aus den Nähten, deren Voraussetzungen erledigt sind, die mit dem höchsten Wert. Es liest nur, es prüft, ob jede Voraussetzung eine Naht ist, die es gibt, und es bricht ab, wenn Voraussetzungen im Kreis laufen.

PowerShell
<#
.SYNOPSIS
Ordnet die Nähte aus docs/nahtstellen.csv nach Nutzen je Risiko und achtet darauf, dass keine Naht vor ihrer Voraussetzung kommt.
Liest nur, ändert nichts.

.EXAMPLE
./scripts/Reihenfolge.ps1 -Datei ./docs/nahtstellen.csv
#>
[CmdletBinding()]
param(
    [Parameter(Mandatory)]
    [string] $Datei
)

$ErrorActionPreference = 'Stop'
$nähte = @(Import-Csv -LiteralPath $Datei -Delimiter ';' -Encoding utf8)
$ids = $nähte.Id

foreach ($naht in $nähte) {
    foreach ($id in ($naht.Voraussetzung -split ',' | Where-Object { $_ })) {
        if ($id -notin $ids) {
            throw "$($naht.Id) setzt $id voraus, aber es gibt keine Naht $id."
        }
    }
}

$fertig = [System.Collections.Generic.List[string]]::new()
$rest = [System.Collections.Generic.List[object]]::new($nähte)
$rang = 0
$ergebnis = while ($rest.Count -gt 0) {
    $bereit = @($rest | Where-Object { @($_.Voraussetzung -split ',' | Where-Object { $_ -and $_ -notin $fertig }).Count -eq 0 })
    if ($bereit.Count -eq 0) {
        throw "Die Voraussetzungen kreisen: $(($rest.Id) -join ', ')."
    }

    $nächste = $bereit | Sort-Object { [double]$_.Nutzen / [double]$_.Risiko } -Descending | Select-Object -First 1
    $rest.Remove($nächste) | Out-Null
    $fertig.Add($nächste.Id)
    $rang++
    [pscustomobject]@{
        Rang = $rang
        Id = $nächste.Id
        Naht = $nächste.Naht
        Wert = [math]::Round([double]$nächste.Nutzen / [double]$nächste.Risiko, 2)
    }
}

$ergebnis | Format-Table -AutoSize | Out-String -Width 200
PowerShell
./scripts/Reihenfolge.ps1 -Datei ./docs/nahtstellen.csv

Rang Id Naht                                                       Wert
---- -- ----                                                       ----
   1 N2 Konfiguration aus App.config                               3,00
   2 N1 Preisregeln aus HauptForm in eine Bibliothek               2,50
   3 N9 Kundenkarte mit WebView2                                   2,00
   4 N3 Datenzugriff: DataSet durch Entity Framework Core ersetzen 1,00
   5 N5 Auftragsliste als Web-API und Blazor-Seite                 1,67
   6 N6 Rechnungsdruck als PDF                                     1,00
   7 N7 Dateiexport in den Blob-Speicher                           1,00
   8 N8 Anmeldung mit Microsoft Entra ID                           1,00
   9 N4 Wartungsregel: Trigger und Prozedur in die Bibliothek      0,80

Lesen Sie die Reihenfolge nicht als Befehl. N3 steht vor N5, obwohl N5 den höheren Wert hat, weil N5 N3 voraussetzt. N4 steht zuletzt, weil das Risiko am größten ist und der Nutzen erst mit dem neuen Datenzugriff entsteht. Und die Konfiguration (N2) steht ganz vorn, weil sie wenig kostet und sonst nichts aufhält. Das Team darf die Reihenfolge ändern, aber jede Änderung braucht einen Satz, warum. Ein Beispiel: Die Anmeldung (N8) kann früher kommen, wenn die erste Pilotgruppe sie braucht.

Der Plan als Dokument

Das Ergebnis dieses Moduls ist ein Dokument im Repository, docs/modernisierungsplan.md. Es hat sieben Abschnitte:

  1. Ziel: ein Satz, was nach der Modernisierung anders ist, aus Sicht des Betriebs.
  2. Ausgangslage: der Verweis auf die Landkarte aus Lektion M1.3.
  3. Nähte: die Tabelle der Nähte mit Nutzen und Risiko.
  4. Reihenfolge: das Ergebnis des Skripts mit den Abweichungen und ihren Gründen.
  5. Sicherheitsnetz: welche Tests und Kopien vor jeder Etappe stehen (Modul M2).
  6. Rückfallplan: je Etappe, wie Sie in Minuten zum Alten zurückkehren.
  7. Entscheidungen: die Verweise auf die ADRs, etwa das aus Lektion M1.1.

Der Plan ist ein Arbeitsdokument: Er ändert sich, wenn sich die Lage ändert, und jede Änderung ist ein Commit mit einem Satz, warum. Eine Entscheidung, die schwer zurückzunehmen ist, bekommt zusätzlich ein ADR; dass Alt und Neu nebeneinander laufen, ist eine solche (siehe die Lösung zu Übung 2).

Was kann schiefgehen

  • Die Fassade bleibt für immer. Microsoft nennt sie eine Übergangsarchitektur mit eigenen Kosten. Planen Sie ihren Abbau am Anfang ein (Lektion M6.5).
  • Die Fassade wird zum Engpass. Eine API, die alles durchleitet, ist eine Ausfallstelle. Beobachten Sie sie von Anfang an (Lektion M6.4).
  • Eine gemeinsame Datenbank ohne Besitzer. Wenn Alt und Neu dieselbe Tabelle beschreiben, ohne dass geklärt ist, wer wann schreibt, entstehen Konflikte (Lektionen M3.3 und M6.2).
  • Nähte, die keine sind. „Alles ins Web“ ist keine Naht. Zerlegen Sie, bis jede Naht einen Namen hat, den Frau Aydin versteht.
  • Reihenfolge nach Spaß. Das schönste Stück zuerst ist verlockend. Das Skript zwingt Sie, den Nutzen für den Betrieb und das Risiko aufzuschreiben.
  • Alte Objekte zu früh entfernen. Microsoft warnt: Wer Tabellen und Prozeduren aus der alten Datenbank entfernt, bevor das Neue geprüft ist, verliert den Rückweg.
  • Der Plan veraltet. Ein Plan, den niemand nachführt, wird nach einem Monat falsch und danach ignoriert.

Übung 1

Legen Sie docs/nahtstellen.csv und scripts/Reihenfolge.ps1 in Ihrem Repository an und führen Sie das Skript aus. Verändern Sie dann zwei Zahlen so, wie Ihr Team es für richtig hält, und beobachten Sie, ob sich die Reihenfolge ändert. Prüfen Sie danach die Schutzregeln des Skripts: Setzen Sie bei N4 eine Voraussetzung N10 ein, die es nicht gibt, und laufen Sie danach zwei Nähte gegenseitig voraussetzen (N8 setzt N9 voraus und N9 setzt N8 voraus).

So prüfen Sie Ihr Ergebnis: Das Skript endet im Normalfall mit dem Exit-Code 0, bei den beiden Fehlern mit einer verständlichen Meldung und dem Exit-Code 1.

Lösung 1

Eine Voraussetzung, die es nicht gibt, meldet das Skript mit dem Namen der Naht und der fehlenden Id:

N4 setzt N10 voraus, aber es gibt keine Naht N10.

Eine Schleife der Voraussetzungen meldet es so:

Die Voraussetzungen kreisen: N8, N9.

Beide Meldungen kommen aus einem throw; PowerShell zeigt sie mit dem Ort im Skript, und pwsh -File endet mit dem Exit-Code 1. Ändern Sie eine Zahl, etwa den Nutzen der Kundenkarte (N9) von 2 auf 5, rückt die Naht nach vorn, weil ihr Wert (5 geteilt durch 1) größer ist als der der Preisregeln. Wenn Sie das für falsch halten, ist die Zahl falsch, nicht das Skript. Diskutieren Sie die Zahl, nicht die Reihenfolge.

Übung 2

Schreiben Sie docs/modernisierungsplan.md mit den sieben Abschnitten. Für das Auftragsbuch nehmen Sie die Ergebnisse dieser Lektion und der vorigen. Der Plan nennt für jede der ersten drei Nähte: den Test, der vorher stehen muss, und den Rückfall. Legen Sie außerdem ein ADR an: docs/adr/0002-alt-und-neu-nebeneinander.md, die Entscheidung, das Altprogramm bis zum Schluss zu behalten.

So prüfen Sie Ihr Ergebnis: Jede Naht im Plan hat einen Rückfall, der ohne neue Auslieferung des Altprogramms geht, und das ADR nennt mindestens zwei Optionen.

Lösung 2

markdown
# Modernisierungsplan: Auftragsbuch

## Ziel

Frau Aydin und Herr Kowalski sehen und bearbeiten Aufträge auch im Browser und vom Telefon. Das Altprogramm läuft bis zur Abschaltung
unverändert weiter und ist jederzeit der Rückfall.

## Ausgangslage

Siehe docs/landkarte.md: ein Windows-Forms-Projekt auf .NET Framework 4.8, DataSet direkt gebunden, Preisregeln im Hauptformular,
Wartungsregel in Trigger und Prozedur.

## Nähte

| Id | Naht | Nutzen | Risiko | Quelle der Zahlen |
| --- | --- | --- | --- | --- |
| N1 | Preisregeln in eine Bibliothek | 5 | 2 | Team, nach Lektion M1.3 |
| N2 | Konfiguration aus App.config | 3 | 1 | Team |
| N3 | Datenzugriff mit Entity Framework Core | 4 | 4 | Team |

(weitere Nähte laut docs/nahtstellen.csv)

## Reihenfolge

Ergebnis von scripts/Reihenfolge.ps1: N2, N1, N9, N3, N5, N6, N7, N8, N4. Abweichung: N8 (Anmeldung) rückt vor die Pilotgruppe, weil
Herr Kowalski nur mit Anmeldung auf den Plan zugreifen soll.

## Sicherheitsnetz

Vor N1: Tests, die die vier Preisregeln für je einen Beispielauftrag festhalten. Vor N3: eine Kopie der Datenbank und Tests, die die
Ergebnisse der Abfragen alt und neu vergleichen. Vor jeder Naht: ein Commit, der baut.

## Rückfallplan

N1: Das Hauptformular nutzt wieder seine eigenen Methoden (ein Commit zurück). N2: App.config bleibt neben appsettings.json bestehen,
bis die Naht abgeschlossen ist. N3: Das Altprogramm liest weiter über das DataSet; die Kopie der Datenbank liegt bereit.

## Entscheidungen

- 0001: Das Auftragsbuch modernisieren
- 0002: Alt und neu nebeneinander betreiben
markdown
# 0002: Alt und neu nebeneinander betreiben

- Status: angenommen
- Zuversicht: mittel

## Kontext

Das Auftragsbuch wird Schritt für Schritt ersetzt (ADR 0001). Frau Aydin darf an keinem Tag ohne Programm sein. Das Altprogramm kann
geändert werden, der Quelltext ist vorhanden.

## Optionen

### Option 1: Alt und neu nebeneinander, Funktion für Funktion umschalten

Eine gemeinsame API und Bibliothek, das Altprogramm ruft sie je Funktion über einen Schalter auf. Rückfall in Minuten, aber zwei
Welten über eine längere Zeit.

### Option 2: Umstellung an einem Stichtag

Das Neue wird fertig gebaut und an einem Tag eingeführt. Kein Doppelbetrieb, aber der Stichtag trägt das gesamte Risiko.

### Option 3: Proxy vor dem Altprogramm

Ein Proxy leitet Anfragen um. Passt hier nicht, weil das Desktop-Programm keine abfangbaren Anfragen schickt.

## Entscheidung

Wir nehmen Option 1, weil sie den Rückfall in Minuten erlaubt und das Risiko in kleine Etappen teilt. Option 3 scheidet aus, weil es
keine Anfragen zum Umleiten gibt.

## Abwägungen

Wir pflegen eine Zeit lang zwei Programme und müssen klären, wer welche Daten schreibt. Dafür zahlt das Ziel „einfacher Betrieb“.

## Folgen

Eine Web-API und ein Schalter je Funktion entstehen; die Fassade wird am Ende wieder abgebaut.

## Folgen für Sicherheit und Datenschutz

Die API ist neue Angriffsfläche und braucht Anmeldung und Rechte, bevor eine Funktion umgeschaltet wird.

## Überprüfen, wenn

der Doppelbetrieb länger dauert als zwei Etappen ohne Abschaltung oder die Daten in Alt und Neu auseinanderlaufen.

Was Sie jetzt können

  • Sie erklären das Strangler-Fig-Muster mit seinen vier Phasen, seinen Bedingungen und den Fällen, in denen es nicht passt.
  • Sie setzen bei einem Desktop-Programm eine gemeinsame API und Bibliothek als Fassade ein, wo ein Proxy nichts abfangen kann.
  • Sie finden Nähte in der Landkarte und beurteilen sie nach Schnittstelle, Daten und Testbarkeit.
  • Sie ordnen die Nähte nach Nutzen und Risiko, ohne eine Naht vor ihre Voraussetzung zu setzen.
  • Sie halten den Modernisierungsplan als Dokument im Repository fest.

Mit der nächsten Datei prüfen Sie dieses Können an einem zweiten Programm: in der Modulprüfung zu Landkarte und Reihenfolge.

Weiterlesen