WEBVTT

00:07.250 --> 00:09.870
Überlegen Sie schon mal, was mit dem Programm los ist, was das

00:09.870 --> 00:10.790
ausdruckt.

00:15.880 --> 00:17.780
Ich zeige Ihnen auch gleich die Wahlmöglichkeiten.

00:21.380 --> 00:22.640
Das sind die Wahlmöglichkeiten.

00:26.920 --> 00:30.660
Und jetzt nochmal genau hinschauen.

00:33.540 --> 00:37.860
Also, wir haben wieder mal ein ganz einfach aussehendes Programm.

00:38.360 --> 00:40.160
Wir machen Arbeiten mit Big Integer.

00:40.160 --> 00:44.460
Das ist eine Klasse für beliebig große Zahlen.

00:46.620 --> 00:49.640
Davon werden hier vier Stück erzeugt.

00:49.740 --> 00:53.600
Das eine heißt so 5.000, 50.000, 500.000 und eine Summe.

00:54.180 --> 00:56.420
Die wird initialisiert zu einer Null.

00:58.000 --> 01:04.480
Dann rechnen wir aus Summe, das ist die hier, Funktion Add, 5.000 und

01:04.480 --> 01:07.240
nochmal 50.000 und 500.000.

01:07.700 --> 01:08.860
Und dann drucken wir.

01:08.860 --> 01:10.700
Das Ergebnis aus.

01:15.280 --> 01:21.100
Big Integer hat eine ToString-Methode, also die Printline-Funktion

01:21.100 --> 01:23.140
müsste eigentlich ohne Schwierigkeiten arbeiten.

01:23.800 --> 01:25.540
Da jetzt die Frage, was wird ausgegeben?

01:27.920 --> 01:30.440
Wer ist denn für 555.000?

01:33.270 --> 01:34.230
Keiner.

01:35.450 --> 01:37.270
Irgendjemand für 500.000?

01:38.570 --> 01:39.710
Auch nicht.

01:40.330 --> 01:41.170
5.000?

01:42.710 --> 01:43.630
Null?

01:46.430 --> 01:47.890
Etwas ganz anderes?

01:49.810 --> 01:51.170
Die Nuller haben alle recht.

01:51.810 --> 01:52.670
Wer will es uns erklären?

01:57.520 --> 01:57.700
Bitte.

02:03.020 --> 02:04.360
Genau richtig.

02:05.140 --> 02:09.280
Big Integer ist ein sogenanntes immutable oder unveränderbares,

02:09.460 --> 02:13.920
unmutierbares Objekt oder Klasse für unmutierbare Objekte.

02:14.720 --> 02:18.820
Das heißt, wie würden wir das Programm reparieren, wenn wir das

02:18.820 --> 02:20.280
wirklich ausrechnen wollten?

02:22.860 --> 02:23.160
Ja, bitte.

02:25.740 --> 02:26.260
Genau.

02:26.820 --> 02:27.840
Das steht nochmal hier.

02:28.500 --> 02:28.840
Genauso.

02:30.040 --> 02:32.980
Gleich wie vorhin, aber ich muss immer das neue Objekt natürlich auf

02:32.980 --> 02:33.960
eine Summe zuweisen.

02:34.340 --> 02:39.540
Und das alte wird dann der Speicherbereinigung übergeben, dass es dann

02:39.540 --> 02:40.640
irgendwann mal abräumt.

02:41.000 --> 02:41.160
Genau.

02:41.480 --> 02:42.780
Das haben Sie sehr gut gekonnt.

02:43.560 --> 02:46.220
Haben Sie offenbar schon mal benutzt oder haben Sie es schon gesehen?

02:50.960 --> 02:51.480
Ausgezeichnet.

02:51.480 --> 02:53.480
So, dann gehen wir...

03:03.490 --> 03:04.750
Den können wir zumachen.

03:06.710 --> 03:09.110
Das Nächste ist dann die Entwurfsphase.

03:09.270 --> 03:10.470
Da waren Sie schon ziemlich weit.

03:12.770 --> 03:14.610
Ich gehe mal schon auf Folie 64.

03:17.450 --> 03:21.050
So, also erst mal...

03:23.890 --> 03:29.550
Sie hatten also letztes Mal über das Modul gesprochen und dabei vom

03:29.550 --> 03:33.250
Geheimnisprinzip gelernt und das Geheimnisprinzip sagt ja, man

03:33.250 --> 03:35.950
verbirgt etwas, damit man es später ändern kann.

03:36.830 --> 03:41.230
Und Sie hatten also Beispiele gesehen, wo die Implementierung, die

03:41.230 --> 03:45.390
Datenstrukturen, die innerhalb einer Klasse sitzen, durch

03:45.390 --> 03:50.850
Zugriffsfunktionen beschrieben oder gesetzt und gelesen werden, sodass

03:50.850 --> 03:55.090
ich hinterhergehen kann und manche der Datenstrukturen ersetzen kann

03:55.090 --> 03:55.710
durch eine andere.

03:55.710 --> 04:01.090
Der Vorteil ist, solange die Signatur, also die Schnittstelle des

04:01.090 --> 04:06.350
Moduls gleich bleibt, kann ich dieses Modul ersetzen durch eine neue

04:06.350 --> 04:10.730
Implementierung, ohne dass irgendein anderes Programm, irgendein

04:10.730 --> 04:13.830
anderes Klientprogramm durchforstet werden muss nach all diesen

04:13.830 --> 04:15.730
Aufrufen, um sie zu ersetzen.

04:18.630 --> 04:22.530
Also die eleganteste Technik dafür sind immer diese

04:22.530 --> 04:26.730
Zugriffsfunktionen, deswegen die Set- und Get-Funktionen unter

04:26.730 --> 04:29.570
anderem, aber es gibt auch andere Geheimnisse, die ich haben könnte,

04:30.010 --> 04:31.970
außer Datenstrukturen und Algorithmen.

04:32.510 --> 04:37.350
Es könnten auch Adaptionsfunktionen sein, die, sagen wir, auf ein

04:37.350 --> 04:40.190
bestimmtes Betriebssystem oder eine bestimmte Plattform adaptieren.

04:40.530 --> 04:43.110
Da brauche ich Funktionen, die sind auf den unterschiedlichen

04:43.110 --> 04:49.330
Plattformen, Linux, Mac, Windows, unterschiedlich zur Verfügung

04:49.330 --> 04:49.750
gestellt.

04:49.750 --> 04:56.130
Daher baue ich mir eine Klasse oder ein Objekt, das eine einheitliche

04:56.130 --> 04:59.450
Schnittstelle liefert, die dann für die verschiedenen Plattformen

04:59.450 --> 05:00.890
unterschiedlich implementiert sind.

05:01.350 --> 05:06.190
Das wäre eine andere Möglichkeit, das Modul, die Idee des Information

05:06.190 --> 05:08.370
Hiding oder des Geheimnisprinzips zu nutzen.

05:09.270 --> 05:15.370
Und jetzt sagte ich Ihnen ja, oder der Herr Landhäuser sagte Ihnen

05:15.370 --> 05:24.350
wahrscheinlich, dass die Idee des Geheimnisprinzips natürlich in der

05:24.350 --> 05:28.610
Objektorientierung anwendbar ist, angewendet werden muss, genau

05:28.610 --> 05:36.010
genommen ist das Modul ein Vorläufer des Konzepts der Klasse.

05:36.810 --> 05:40.050
Aber es hat einen wichtigen Unterschied, deswegen auch tatsächlich ein

05:40.050 --> 05:41.190
Vorläufer, es kann weniger.

05:41.870 --> 05:47.030
Und zwar, wenn Sie ein Modul haben, dann können Sie es nicht mehrfach

05:47.030 --> 05:47.810
instanziieren.

05:48.250 --> 05:49.930
Denken Sie an das Objektpunkt.

05:50.010 --> 05:52.390
Das Objektpunkt können Sie so oft anlegen, wie Sie wollen.

05:52.990 --> 05:56.730
Wenn Sie ein Modul hätten, das einen Punkt implementiert, dann gäbe es

05:56.730 --> 05:58.650
nur diesen einzigen Punkt.

05:59.330 --> 06:02.630
Das ist ein schwerer Nachteil des Moduls, des Modulkonzeptes.

06:03.410 --> 06:06.810
Es gibt ein einziges Exemplar der Schnittstelle und der

06:06.810 --> 06:07.990
Implementierung.

06:10.390 --> 06:15.130
Man kann drumherum programmieren, indem man zum Beispiel ein Modul für

06:15.130 --> 06:18.910
Punkte schreibt, in dem man sagt, hier drin werden Punkte gespeichert

06:18.910 --> 06:23.210
und man liefert eine zusätzliche Funktion für neue Punkte, die einen

06:23.210 --> 06:26.990
neuen Punkt anlegt und vielleicht existierende löscht.

06:26.990 --> 06:29.550
Aber Sie sehen schon, das wird etwas umständlicher.

06:29.970 --> 06:33.990
So elegant wie Klasse deklarieren und dann New Klassenname zu sagen,

06:34.470 --> 06:38.010
mit Initialisierungsparametern, geht das beim Modul nicht.

06:38.330 --> 06:40.970
Aber es ist natürlich auch programmierbar.

06:43.810 --> 06:47.650
Bei den objektorientierten Sprachen kann ich hergehen und sagen, ich

06:47.650 --> 06:53.410
trenne Klasse von Objekt, erkläre nur die Klasse und instanziere die

06:53.410 --> 06:54.150
Klasse mehrfach.

06:55.770 --> 07:00.110
Oder ich kann auch die Schnittstelle, wenn ich nur eine Schnittstelle

07:00.110 --> 07:02.370
angegeben habe, mehrfach instanzieren.

07:02.510 --> 07:06.670
Auch das geht im Modul nicht.

07:11.270 --> 07:14.670
Also eine Schnittstelle kann durch eine oder mehrere Klassen

07:14.670 --> 07:15.650
implementiert werden.

07:16.130 --> 07:18.430
Von diesen Klassen können mehrere Objekte erzeugt werden.

07:21.050 --> 07:26.330
Wenn Sie jetzt aber haben wollten, dass für den seltenen Fall, dass

07:26.330 --> 07:30.050
Sie in einer objektorientierten Sprache sind und garantieren wollen,

07:30.190 --> 07:36.490
dass es nur eine einzelne Instanz gibt, dann gibt es ein spezielles

07:36.490 --> 07:40.270
Entwurfsmuster dafür, das heißt das Einzelstück oder Singleton.

07:40.670 --> 07:43.330
Mit denen können Sie das auch erreichen, dass es nie möglich sein

07:43.330 --> 07:46.670
wird, von einer Klasse mehr als ein einziges Objekt anzulegen.

07:46.670 --> 07:51.190
Das geht ziemlich einfach, indem man sich merkt in einer Variablen, ob

07:51.190 --> 07:54.770
es ein solches Element schon gibt und wenn nicht, dann gebe ich

07:54.770 --> 07:59.710
einfach das einzelne Objekt im Konstruktor wieder zurück.

07:59.950 --> 08:01.350
Dann gibt es immer nur eines.

08:01.750 --> 08:03.230
Werden wir sehen, wie man das genau programmiert.

08:05.610 --> 08:11.770
Das andere, was ich natürlich bei EU-Sprachen habe, ist, dass wenn ich

08:11.770 --> 08:16.130
eine Schnittstelle vorgegeben habe und sie mehrfach implementiere, in

08:16.130 --> 08:21.390
zwei, drei Klassen, dann benutzen diese Implementierungen die gleichen

08:21.390 --> 08:24.730
Methodennamen, was es für mich als Programmierer vereinfacht.

08:25.130 --> 08:27.410
Im Modul kann ich das auch nicht erreichen.

08:28.330 --> 08:31.910
Wenn ich ein Modul habe, das zwar die gleiche Schnittstelle liefert,

08:32.690 --> 08:35.550
aber eine unterschiedliche Implementierung ist, zum Beispiel wir

08:35.550 --> 08:39.850
hatten das Hohlzeichen-Funktion und die Verschiebe-Hohlzeichen

08:39.850 --> 08:40.390
-Funktion.

08:40.390 --> 08:45.150
Da muss ich dann sagen, ich muss jedes Mal einen neuen Namen mehr

08:45.150 --> 08:50.950
ausdenken für die Hohlzeichen-Funktion, die dann angibt, aus welcher

08:50.950 --> 08:52.510
Instanzierung es jetzt stammt.

08:52.950 --> 08:57.310
Auch das kann ich in der objektorientierten Programmiersprache elegant

08:57.310 --> 09:02.390
anders lösen, nämlich den gleichen Namen beibehalten, den Namen der

09:02.390 --> 09:06.270
Klasse oder des Objektes voranstellen und schon ist die Geschichte

09:06.270 --> 09:06.750
fertig.

09:09.070 --> 09:12.850
Diese Namensgebung mit dem Objekt und davor, das muss ich eben in C,

09:12.990 --> 09:15.710
in einer Programmiersprache wie C, auf diese Art und Weise

09:15.710 --> 09:17.030
modellieren.

09:17.210 --> 09:20.210
In objektorientierter Sprache hätten Sie stattdessen VS oder

09:20.210 --> 09:21.750
Verschieber -Punkt-Hohlezeichen.

09:28.890 --> 09:35.030
Dann kommt noch ein wichtiger Punkt, die sogenannte Benutztrelation.

09:35.790 --> 09:39.890
Die Benutztrelation ist sehr wichtig, dass sie in einer bestimmten

09:39.890 --> 09:43.110
Struktur aufgebaut ist, nämlich hierarchisch, sodass ich ein

09:43.110 --> 09:48.170
Gesamtsystem Stück für Stück aufbauen kann, testen kann und nicht

09:48.170 --> 09:51.210
darauf warten muss, bis alles fertig geschrieben ist, bevor ich das

09:51.210 --> 09:52.290
erste Mal testen kann.

09:52.850 --> 09:58.350
Dazu ist es erforderlich, dass diese Benutztrelation hierarchisch ist.

09:58.610 --> 10:01.870
Nun gibt es eine ganze Menge von Relationen in Programmen.

10:02.650 --> 10:04.770
Ich habe einige davon aufgezählt hier.

10:06.350 --> 10:11.650
Delegiert an ist die Relation, die sagt, wenn ein Aufruf ankommt an

10:11.650 --> 10:16.290
eine bestimmte Klasse oder Objekt, dann wird das weitergegeben mit den

10:16.290 --> 10:18.090
gleichen Parametern an ein anderes.

10:18.550 --> 10:21.170
Das ist die Delegiert-an-Relation.

10:22.590 --> 10:27.890
Ist ein, das ist die Relation der Klassenhierarchie, das kennen Sie

10:27.890 --> 10:28.150
schon.

10:28.150 --> 10:31.630
Hat ein, das ist die Aggregationsrelation.

10:31.930 --> 10:33.850
Enthält, hat ein, ja.

10:34.730 --> 10:36.150
Enthält ein ist das Gleiche.

10:36.910 --> 10:40.590
Greift zu auf, das ist die Zugriffsrelation.

10:40.810 --> 10:44.810
Ich habe meine Klasse A, die greift auf Elemente der Klasse B zu.

10:46.430 --> 10:49.750
Ist privilegiert zu, das ist eine Privilegierungsrelation, die sagt,

10:50.210 --> 10:53.930
darf auf etwas zugreifen, darf eine bestimmte Funktion sehen,

10:54.070 --> 10:58.190
benutzen, eine bestimmte Klasse oder Objekt sehen und benutzen.

10:58.650 --> 11:03.770
Das ist in Programmiersprachen heute noch weniger ausgeprägt, aber mit

11:03.770 --> 11:09.810
der Wichtigkeit der Sicherheit könnte sich das demnächst ändern, dass

11:09.810 --> 11:13.890
es geschicktere Programmiersprachen gibt, die einen besseren Schutz

11:13.890 --> 11:14.270
bieten.

11:14.890 --> 11:20.590
Dann natürlich die Relation ruft auf, eine Methode X ruft eine Methode

11:20.590 --> 11:21.290
Y auf.

11:23.190 --> 11:28.130
Die Inverse ist dann aufgerufen von, benutzt, das ist die, die wir

11:28.130 --> 11:31.170
jetzt definieren wollen, und stellt Betriebsmittel bereit.

11:31.430 --> 11:36.210
Das wäre zum Beispiel ein Betriebssystem, das Zugriff auf Dateien oder

11:36.210 --> 11:38.770
auf eine Fernzugriffsschnelle bereitstellt.

11:40.090 --> 11:42.550
So, all diese Relationen gibt es.

11:42.790 --> 11:47.350
Wir interessieren uns im Entwurf besonders für die Benutzrelation oder

11:47.350 --> 11:48.470
Uses Relation.

11:49.490 --> 11:53.870
Die definieren wir jetzt, wir sagen, eine Programmkomponente A, was

11:53.870 --> 11:58.230
immer das ist, Klasse, Methode, Typ, Variable, benutzt

11:58.230 --> 12:04.610
Programmkomponente B, genau dann, wenn A für den korrekten Ablauf die

12:04.610 --> 12:07.750
Verfügbarkeit einer korrekten Implementierung von B erfordert.

12:08.730 --> 12:12.750
Also A erfordert, dass es B gibt und dass B richtig implementiert ist.

12:13.710 --> 12:20.530
Sie sehen, hier steht nicht, wenn A B aufruft zum Beispiel, sondern

12:20.530 --> 12:25.890
die Verfügbarkeit ist ein allgemeineres Konzept.

12:26.290 --> 12:27.230
Beispiele dafür.

12:29.450 --> 12:36.110
Also Verfügbarkeit kann heißen, A delegiert Arbeit nach B, benutzt

12:36.110 --> 12:41.690
also die Delegationsrelation, A greift auf Variablen von B zu, ein

12:41.690 --> 12:48.910
Objekt zum Beispiel, A ruft B auf, da ist aber eine Einschränkung

12:48.910 --> 12:55.410
dabei, es gibt nämlich Aufrufe, wobei nicht erforderlich ist, dass das

12:55.410 --> 12:59.210
aufgerufene Komponente tatsächlich richtig funktioniert.

12:59.850 --> 13:01.190
Das klingt jetzt ein bisschen komisch.

13:01.190 --> 13:03.050
Aber hier ist ein Beispiel.

13:06.850 --> 13:12.210
Wenn Sie ein Programm starten auf Ihrem Rechner, was dann eigentlich

13:12.210 --> 13:16.290
passiert ist, dass das Betriebssystem Ihr Programm aufruft, mit einem

13:16.290 --> 13:17.370
Aufruf an Main.

13:19.310 --> 13:24.530
Ist jetzt das Betriebssystem davon abhängig, dass Ihr Main richtig

13:24.530 --> 13:25.410
implementiert ist?

13:26.450 --> 13:27.310
Nein, ist es nicht.

13:27.450 --> 13:30.090
Das wäre ein schlechtes Betriebssystem, wenn es sofort zusammenbrechen

13:30.090 --> 13:33.090
würde, nur weil Sie ein inkorrektes Programm geschrieben haben.

13:33.870 --> 13:38.850
Das Betriebssystem ist bewusst so geschrieben, dass es fehlerhafte

13:38.850 --> 13:39.830
Programme überlebt.

13:41.010 --> 13:44.870
Und es braucht auch gar nichts von diesen fehlerhaften Programmen oder

13:44.870 --> 13:46.590
auch von den richtigen Anwendungsprogrammen.

13:47.170 --> 13:49.050
Es ist nur da, um es aufzurufen.

13:49.590 --> 13:54.130
Also sagen wir, A ruft B auf, wobei A den korrekten Ablauf von B auch

13:54.130 --> 13:55.470
tatsächlich erfordert.

13:56.870 --> 14:01.250
Wir werden heute noch ein anderes Beispiel sehen, wo ein Aufruf

14:01.250 --> 14:04.630
erfolgt, aber eine korrekte Implementierung des Aufrufs gar nicht mal

14:04.630 --> 14:05.670
erforderlich ist.

14:10.810 --> 14:14.330
A legt eine Instanz eines Typs von B an, auch das ist eine

14:14.330 --> 14:15.210
Benutzrelation.

14:15.970 --> 14:19.190
Ich habe meine Klasse und lege eine Instanz davon an.

14:19.850 --> 14:21.910
Dann benutzt A natürlich diese Klasse B.

14:22.870 --> 14:28.050
Oder, und das ist wieder etwas komplizierter, bis jetzt hatten wir

14:28.050 --> 14:32.890
immer gesagt, wenn wir etwas benutzen, dann kennen wir den Namen des

14:32.890 --> 14:34.770
Elementes, das wir benutzen.

14:34.850 --> 14:37.290
Zum Beispiel die Methode, die wir aufrufen wollen, die Klasse, die wir

14:37.290 --> 14:41.270
instanzieren wollen, die Instanzvariablen vom Namen her, die Konstante

14:41.270 --> 14:42.470
vom Namen her.

14:43.150 --> 14:47.310
Es kann auch sein, dass wir Programme benutzen, die wir gar nicht

14:47.310 --> 14:47.810
aufrufen.

14:49.430 --> 14:53.890
Und das ist immer dann der Fall im Inneren eines Betriebssystems.

14:56.050 --> 14:58.650
Zum Beispiel gibt es in einem Betriebssystem

14:58.650 --> 15:03.110
Unterbrechungsbehandlungsroutinen, die bei bestimmten Ereignissen

15:03.110 --> 15:08.150
automatisch ausgeführt werden, die natürlich Ihr Programm ausgelöst

15:08.150 --> 15:11.210
hat, aber nie per Namen aufgerufen hat.

15:12.090 --> 15:16.490
Zum Beispiel, angenommen, Sie lesen von einer Datei.

15:16.490 --> 15:20.090
Dann gibt es eine Funktion, die liest einen ganzen Block einer Datei

15:20.090 --> 15:20.370
ein.

15:21.110 --> 15:22.630
Sagen wir 4 KB auf einmal.

15:23.470 --> 15:28.210
Die Datei müssen Sie dazu vorher geöffnet haben zum Lesen und Sie

15:28.210 --> 15:30.670
rufen jetzt die Funktion read auf.

15:32.170 --> 15:38.170
Was jetzt passiert ist, dass dieser Funktionsaufruf read natürlich

15:38.170 --> 15:42.990
eine Betriebssystemfunktion aufruft, die das Lesen anstößt.

15:44.610 --> 15:48.630
Nachdem die Rotationsgeschwindigkeit einer Platte, von der Sie lesen,

15:49.470 --> 15:52.870
verglichen mit der Geschwindigkeit Ihres Rechners sehr, sehr langsam

15:52.870 --> 15:57.750
ist, im Bereich von Millisekunden, was jetzt passiert ist, dass Ihr

15:57.750 --> 16:01.070
Programm eigentlich angehalten wird und der Rechner sich die

16:01.070 --> 16:05.110
Gelegenheit nimmt und sagt, bis die Plattenrotation soweit ist, dass

16:05.110 --> 16:08.470
die Bytes da sind und ich sie ablesen kann, kann ich auch ein anderes

16:08.470 --> 16:09.470
Programm laufen lassen.

16:10.470 --> 16:13.010
Dadurch entsteht dieses Multiprogramming.

16:14.550 --> 16:22.470
Wenn aber der Lesevorgang vollständig ist, dann erzeugt die Platte,

16:23.310 --> 16:31.350
das Gerät Platte, eine Unterbrechung, setzt ein Unterbrechungsbit im

16:31.350 --> 16:35.110
Inneren des Rechners, tatsächlich gibt es ein Unterbrechungsvektor und

16:35.110 --> 16:40.350
der verursacht, dass bei der nächsten Instruktionsausführung

16:41.710 --> 16:44.850
automatisch die Unterbrechungsbehandlungsroutine ausgeführt wird, die

16:44.850 --> 16:48.150
sagt, aha, die Daten sind ja da, jetzt kann ich sie in den

16:48.150 --> 16:52.950
Benutzerbereich kopieren und das gestoppte Programm wieder

16:52.950 --> 16:54.530
weiterrechnen lassen.

16:55.790 --> 16:58.130
Diese Unterbrechungsbehandlungsroutine, auf die es mir ankommt, hat

16:58.130 --> 17:02.430
Ihr Programm aber nie aufgerufen, auch nicht das Programm, das bis in

17:02.430 --> 17:05.450
das Betriebssystem hinein ging und Read aufgerufen hat.

17:05.930 --> 17:12.230
Die Unterbrechungsbehandlungsroutine wird über den Umweg des

17:12.230 --> 17:14.030
Unterbrechungsmechanismus angesteuert.

17:15.310 --> 17:19.630
Also wir merken uns, natürlich benutzt eine Komponente A eine

17:19.630 --> 17:24.190
Komponente B, wenn sie zunächst mal, nennen wir mal an, den Namen

17:24.190 --> 17:28.590
dieses Elementes kennen, sodass es benutzt werden kann, aber es gibt

17:28.590 --> 17:32.690
auch eine Ausnahme, nämlich Unterbrechungsroutinen, die automatisch

17:32.690 --> 17:36.730
angesteuert werden über den Unterbrechungsmechanismus.

17:37.390 --> 17:42.210
Auch dann spricht man von einer Benutzung, denn die Lesefunktion

17:42.210 --> 17:46.550
könnte nicht korrekt funktionieren, wenn es keine korrekt

17:46.550 --> 17:51.170
implementierte Unterbrechungsmethode oder Funktion im Betriebssystem

17:51.170 --> 17:53.470
gäbe, die indirekt aufgerufen wird.

17:58.030 --> 18:02.810
Ich spreche deswegen ausführlich darüber, weil ein Vielfachstudent

18:02.810 --> 18:09.150
meint, jeder Aufruf ist eine Benutzung und mehr gibt es eh nicht.

18:09.590 --> 18:12.810
Es gibt erstens mehr und zweitens ist nicht jeder Aufruf eine

18:12.810 --> 18:13.470
Benutzung.

18:20.760 --> 18:24.320
Die Benutzrelation, Sie wissen ja, das ist eine Relation, die können

18:24.320 --> 18:29.220
wir jetzt so gestalten, dass sie eine totale Ordnung ist, dass A, B

18:29.220 --> 18:31.960
benutzt, B benutzt C, C benutzt D und so fort.

18:32.500 --> 18:35.940
Es kann auch eine Halbordnung sein, das heißt, es kann sein, dass es

18:35.940 --> 18:39.460
Verzweigungen in dieser Benutzrelation gibt.

18:39.980 --> 18:42.060
Es kann auch sein, dass sie zyklisch ist.

18:42.060 --> 18:45.460
Nur die zyklische Benutzrelation wollen wir nach Möglichkeit

18:45.460 --> 18:46.020
vermeiden.

18:47.160 --> 18:54.760
Es gibt ein sehr berühmtes Betriebssystem, das THE heißt das, in dem

18:54.760 --> 18:59.880
diese Idee der Benutzrelation das erste Mal durchgeführt wurde und ein

18:59.880 --> 19:02.360
Betriebssystem auf diese Art und Weise aufgebaut wurde.

19:03.000 --> 19:06.140
Dann das Maltex-Betriebssystem hat auch eine hierarchische

19:06.140 --> 19:07.020
Benutzrelation.

19:07.380 --> 19:08.280
Was ist Maltex?

19:08.600 --> 19:10.580
Maltex ist ein Vorläufer von Unix.

19:10.580 --> 19:15.100
Unix ist so eine abgeschwächte Kopie von Maltex, könnte man sagen.

19:15.240 --> 19:17.180
Und Linux ist eine Kopie von Unix.

19:17.800 --> 19:21.400
Also Maltex, Unix, Linux sind sehr eng verwandt.

19:22.440 --> 19:27.500
Die ISO-OSI-Protokollsuiten, das sind die Protokollsuiten, die sie

19:27.500 --> 19:31.540
brauchen, um Pakete vom Rechner A zum Rechner B zu bringen.

19:32.000 --> 19:37.060
Auch die sind in Schichten, also in einer Totalordnung aufgebaut.

19:38.080 --> 19:42.240
Benutzt die oberste Schicht, die darunter liegende Schicht, die

19:42.240 --> 19:44.420
wiederum benutzt eine tiefer liegende Schicht.

19:44.980 --> 19:47.300
DCP-IP-Protokollsuiten genauso.

19:47.780 --> 19:52.600
Drei-Schichten-Architektur ist sehr bekannt, die wird immer gerne

19:52.600 --> 19:58.060
erklärt, aber eine Drei-Schichten-Architektur besteht aus einer

19:58.060 --> 20:02.220
Schicht für die Datenhaltung, typischerweise ein Datenbanksystem,

20:03.040 --> 20:07.540
einem Applikationskern, der die Grundfunktionen zur Verfügung stellt

20:07.540 --> 20:12.140
und einer Benutzungsschnittstelle, die das Ansteuern der

20:12.140 --> 20:17.560
Kernfunktionen, des Applikationskerns über Menüs und Knöpfe usw.

20:18.000 --> 20:18.480
ermöglicht.

20:19.380 --> 20:24.140
Die Benutzungsschnittstelle benutzt natürlich den Applikationskern und

20:24.140 --> 20:27.480
der Applikationskern holt sich seine Daten aus der Datenhaltung,

20:27.560 --> 20:31.360
erfordert also eine korrekte Implementierung der Datenhaltung.

20:37.830 --> 20:40.410
Fragen Sie Ihren Nachbarn, er soll etwas leiser reden.

20:50.330 --> 20:53.750
Wenn wir also jetzt ein System entwerfen, wollen wir eine

20:53.750 --> 20:57.630
Benutzrelation gestalten, unter welchen Gesichtspunkten.

20:57.650 --> 21:01.670
Wir haben da meistens sehr viele Wahlmöglichkeiten, wie wir die

21:01.670 --> 21:05.130
einzelnen Komponenten voneinander abhängen lassen in der

21:05.130 --> 21:05.830
Benutzrelation.

21:09.490 --> 21:12.970
Also natürlich möchte man, dass A einfacher wird, dadurch, dass es B

21:12.970 --> 21:13.590
benutzen kann.

21:13.730 --> 21:15.730
Das heißt, ich muss den Code, der in B steckt, nicht nochmal

21:15.730 --> 21:16.410
implementieren.

21:17.090 --> 21:18.170
Das ist offensichtlich.

21:18.870 --> 21:21.590
B allerdings soll nicht umgekehrt A benutzen.

21:22.230 --> 21:23.550
Wir wollen keine Zyklen haben.

21:24.410 --> 21:28.910
Das heißt, B darf A gar nicht benutzen und es sollte so sein, dass das

21:28.910 --> 21:32.370
B dadurch nicht komplexer wird, dadurch, dass es A nicht benutzen

21:32.370 --> 21:32.710
darf.

21:34.410 --> 21:37.650
Es gibt mindestens eine nützliche Untermenge, die B aber nicht A

21:37.650 --> 21:38.110
enthält.

21:38.110 --> 21:44.550
Das heißt, Sie können sich diese Komponente B so vorstellen, dass Sie

21:44.550 --> 21:50.950
sie brauchen können in einer anderen Konfiguration der Gesamtsoftware,

21:51.070 --> 21:52.490
in der A nicht vorkommt.

21:53.010 --> 21:56.110
Wenn das nicht so wäre, bräuchte ich unter Umständen...

22:00.580 --> 22:02.000
Für Sie gilt das Gleiche.

22:03.920 --> 22:07.260
Ich komme echt durcheinander, gerade wenn Sie so weit vorne sitzen.

22:11.220 --> 22:14.160
Wenn es keine nützliche Untermenge, die B enthält, aber nicht A, nicht

22:14.160 --> 22:16.000
gäbe, dann können Sie A und B zusammenfassen.

22:19.820 --> 22:23.900
Und es gibt keine Untermenge, die A, aber nicht B enthält.

22:25.020 --> 22:28.040
Das heißt also, ich hätte gerne A, aber das B will ich gar nicht

22:28.040 --> 22:28.280
haben.

22:28.380 --> 22:31.000
Das klappt natürlich nicht, denn A benutzt ja B.

22:33.780 --> 22:36.080
Das sind also die Grundregeln.

22:36.780 --> 22:42.680
Dann sollten wir eine Benutzrelation für A einsetzen.

22:45.760 --> 22:49.180
Dann sagte ich, wenn die Benutzrelation zyklenfrei ist, heißt sie

22:49.180 --> 22:52.660
benutzt Hierarchie, weil sie dann eben eine hierarchische Stufung hat,

22:53.200 --> 22:56.120
das heißt eine Halbordnung oder sogar eine Totalordnung.

22:56.760 --> 22:58.040
Warum ist das wichtig?

22:59.640 --> 23:04.700
Schauen Sie sich erst mal dieses Geflecht von Benutzrelationen an.

23:05.060 --> 23:07.580
Die Pfeile hier bedeuten benutzt.

23:07.880 --> 23:12.020
Also das D benutzt das C, das A benutzt das C, das B benutzt das C.

23:12.120 --> 23:16.900
Sie sehen, dass es hier einen Zyklus gibt, dass nämlich das B, das E

23:16.900 --> 23:19.320
und das F benutzen und das F wiederum das B.

23:20.340 --> 23:24.420
Ich habe das ausgekreuzt, weil es eigentlich wenigstens eine dieser

23:24.420 --> 23:27.080
Relationen, wahrscheinlich die da hier, nicht geben sollte.

23:27.640 --> 23:30.520
Was ist der Nachteil, wenn es solche Zyklen gibt?

23:30.620 --> 23:34.200
Es gibt also hier einen Zyklus und hier einen Zyklus und hier nochmal

23:34.200 --> 23:34.840
einen Zyklus.

23:34.980 --> 23:39.640
Das heißt, es gibt möglicherweise Aufrufsketten von B nach E und E

23:39.640 --> 23:43.780
ruft das F auf und das F ruft umgekehrt wieder das B auf.

23:44.000 --> 23:47.540
Denken Sie sich, dass B, E und F Pakete oder Klassen seien.

23:49.140 --> 23:50.940
Warum ist das ungeschickt?

23:50.940 --> 23:54.720
Das ist ungeschickt, weil Sie keines dieser Module hier, oder

23:54.720 --> 23:58.420
Entschuldigung, dieser Klassen oder Pakete testen können, ohne dass

23:58.420 --> 23:59.560
alles schon funktioniert.

23:59.900 --> 24:03.900
Sie können das E nicht testen, das F nicht testen, wenn Sie das B

24:03.900 --> 24:05.220
nicht und das E nicht haben.

24:06.260 --> 24:09.260
Das gilt aber auch für alle anderen Knoten.

24:11.200 --> 24:16.260
Das ist ein Erfahrungswert, der ist schon, sage ich mal, ziemlich alt.

24:16.260 --> 24:21.540
Es gab eben die ersten großen Software-Systeme, die man in den 60er

24:21.540 --> 24:23.080
und 70er Jahren hatte, baute.

24:24.140 --> 24:30.960
Zum Beispiel das berühmte OS 360, ein Betriebssystem und dessen

24:30.960 --> 24:36.240
Vorläufer, wo man sich diese Gedanken nicht gemacht hatte und die dazu

24:36.240 --> 24:41.560
führten, dass man das nannte, zum einen, nothing works until

24:41.560 --> 24:44.120
everything works, weil man nichts testen konnte.

24:44.120 --> 24:48.320
Wenn man dann endlich alles fertig hatte und dann zum Testen begann,

24:48.420 --> 24:49.560
gab es den großen Knall.

24:50.760 --> 24:52.420
Es hat nämlich überhaupt nichts funktioniert.

24:53.100 --> 24:56.720
Man musste das Gesamtsystem laden, in einem Riesensystem nach Fehlern

24:56.720 --> 25:01.940
suchen und das erschwert eben die Fehlersuche und das Testen ungemein,

25:01.980 --> 25:04.640
wenn es diese zyklischen Abhängigkeiten gab, wenn man nicht ein

25:04.640 --> 25:07.120
Subkomponent herausnehmen kann und sie für sich testet.

25:08.260 --> 25:11.320
Deswegen vermeiden wir diese Zyklen nach Möglichkeit.

25:13.860 --> 25:15.260
Benutzterrelationen zyklenfrei gestalten.

25:16.140 --> 25:19.000
Wenn Sie jetzt schon ein bisschen programmiert haben, sagen Sie aber,

25:19.160 --> 25:20.700
aber, aber, da gibt es doch Fälle.

25:21.420 --> 25:25.140
Jawohl, es gibt Fälle, wo die Benutzterrelation zyklisch aussieht.

25:26.480 --> 25:27.360
Und hier ist so ein Fall.

25:28.960 --> 25:31.180
Man nennt das die Callbacks oder die Rückrufe.

25:31.940 --> 25:33.400
Die Rückrufe bestehen so.

25:34.040 --> 25:35.920
Das kann ich so illustrieren, dass Sie hier eine

25:35.920 --> 25:38.380
Benutzerschnittstelle, sagen wir einen Swing, geschrieben haben.

25:38.380 --> 25:42.380
Hier ist der Anwendungskern, da sind die Funktionen und die

25:42.380 --> 25:45.920
Benutzerschnittstelle ruft natürlich den Anwendungskern auf.

25:46.680 --> 25:49.920
Daher benutzt natürlich die Benutzerschnittstelle den Anwendungskern.

25:50.280 --> 25:52.900
Die Benutzerschnittstelle wäre völlig sinnlos, wenn es den

25:52.900 --> 25:56.260
Anwendungskern nicht gäbe oder wenn der inkorrekt implementiert wäre.

25:57.540 --> 26:00.280
Aber jetzt gibt es auch diese Rückrufe.

26:01.700 --> 26:05.040
Diese Rückrufe bestehen darin, dass Sie zum Beispiel hier in

26:05.040 --> 26:10.640
Benutzerschnittstelle eine Klasse an Objekte anlegen können, zum

26:10.640 --> 26:11.600
Beispiel für die Maus.

26:12.840 --> 26:18.100
Und in dieser Funktion der Maus-Klasse, den sogenannten MouseListener,

26:18.620 --> 26:20.020
haben Sie mehrere Funktionen.

26:20.080 --> 26:22.080
Zum Beispiel das eine heißt MouseClicked.

26:23.040 --> 26:26.500
Und die Funktion, diese MouseClicked-Funktion, hätten Sie gerne

26:26.500 --> 26:33.780
aufgerufen, wenn ein bestimmtes Ereignis eintritt.

26:34.680 --> 26:42.300
In diesem Fall nämlich der Aufruf, der der Mausknopf gedrückt wurde.

26:43.520 --> 26:47.820
Das ist jetzt in diesem Fall noch kein weiteres Problemchen, aber es

26:47.820 --> 26:50.960
kann sein, dass Sie an mehreren Stellen der Benutzerschnittstelle so

26:50.960 --> 26:54.640
eine Klasse mit mehreren Funktionen übergeben müssen an den

26:54.640 --> 26:57.980
Anwendungskern, worauf der Anwendungskern sagt, naja, wenn das und das

26:57.980 --> 27:01.540
eintritt, dann rufe ich die zugehörige Funktion auf.

27:01.900 --> 27:07.660
Zum Beispiel, wenn sich hier drin die Datenstruktur ändert, dann

27:07.660 --> 27:10.200
wollen Sie natürlich, wenn es eine dynamische Anzeige dieser

27:10.200 --> 27:14.640
Datenstruktur gibt, zum Beispiel als Graph oder als Bild, wenn sich da

27:14.640 --> 27:16.860
was geändert hat, dann wollen Sie, dass natürlich in der

27:16.860 --> 27:19.240
Benutzerschnittstelle dieses Bild neu gezeichnet wird.

27:20.500 --> 27:23.620
Diese Zeichenfunktion oder die Anzeigefunktion müssen Sie jetzt der

27:23.620 --> 27:28.860
Anwendungskern übergeben und bei Änderung des Bildes, der Anzeige,

27:29.500 --> 27:32.560
muss der Anwendungskern diesen Aufruf tätigen.

27:33.800 --> 27:36.680
Das ist aber ein klassischer Rückruf, denn das Zeichnen, die

27:36.680 --> 27:39.440
Zeichenfunktion selbst ist ja hier drin in der Benutzerschnittstelle.

27:41.200 --> 27:43.500
Also habe ich hier nicht, habe ich hier doch einen Zyklus.

27:43.880 --> 27:44.940
Und der ist böse.

27:46.660 --> 27:49.460
Und jetzt kommt das Beispiel, das ich vorhin schon nannte, ähnlich wie

27:49.460 --> 27:56.020
beim Betriebssystem, dass Ihre Anwendungsprogramm aufruft.

27:56.160 --> 27:59.160
Das Betriebssystem ruft das zwar auf, ist aber nicht von einer

27:59.160 --> 28:00.560
korrekten Implementierung abhängig.

28:00.940 --> 28:04.100
Es sagt eigentlich, naja, was immer du rechnen willst, wir rechnen

28:04.100 --> 28:04.360
mal.

28:05.080 --> 28:08.400
Aber ich gehe deswegen nicht in die Knie, nur weil ein Programm, sagen

28:08.400 --> 28:10.100
wir, einen Überlauf oder einen Unterlauf enthält.

28:11.480 --> 28:12.620
Genauso ist es hier.

28:13.080 --> 28:16.480
Dieser Rückruf, der sagt, zeichne ein neues Bild, da sagt der

28:16.480 --> 28:19.740
Anwendungskern, mir ist das Bild völlig egal.

28:20.440 --> 28:23.460
Ob das Bild schön ist oder schlecht ist, Fehler enthält oder nicht,

28:23.980 --> 28:29.180
solange die Funktion zurückkehrt und nicht zu einem Kellerüberlauf

28:29.180 --> 28:33.540
oder sonst etwas führt, kann der Anwendungskern immer weiterrechnen.

28:33.660 --> 28:38.140
Der Anwendungskern sagt, zeichne mal, ruf dich auf, aber es ist deine

28:38.140 --> 28:39.160
Verantwortung hier drin.

28:40.120 --> 28:42.900
Das heißt, der Anwendungskern ist gar nicht abhängig von einer

28:42.900 --> 28:44.760
korrekten Implementierung der Benutzerschnittstelle.

28:45.780 --> 28:47.900
Wenn ich das Programm ordentlich geschrieben habe, natürlich.

28:50.240 --> 28:54.780
Okay, das heißt also, gerade bei diesen Benutzerschnittstellen kommt

28:54.780 --> 28:58.760
es häufig vor, dass wir einen scheinbar zyklischen Fall haben, der

28:58.760 --> 29:03.180
aber bei näherem Hinsehen eine wichtige Eigenschaft der Benutzrelation

29:03.180 --> 29:06.620
nicht enthält, nämlich die Abhängigkeit von einer korrekten

29:06.620 --> 29:07.340
Implementierung.

29:08.420 --> 29:12.000
Auch eine fehlerhafte Implementierung würde der Anwendungskern

29:12.000 --> 29:15.540
ausführen lassen, wäre zwar nicht gut für den Benutzer, aber der

29:15.540 --> 29:19.280
Anwendungskern sagt selbst, ich bin davon nicht abhängig, benutze es

29:19.280 --> 29:19.760
gar nicht.

29:20.560 --> 29:21.460
Stoße es nur an.

29:26.940 --> 29:35.060
Das ist jetzt das, was ich Ihnen gerade erklärt habe, nochmal

29:35.060 --> 29:35.820
ausgeschrieben.

29:35.820 --> 29:37.740
Das kann ich jetzt also überspringen.

29:39.340 --> 29:43.880
Wir kommen damit schon zum Ende dieses ersten Abschnittes, und zwar

29:43.880 --> 29:46.260
ein bisschen Historie dazu.

29:47.200 --> 29:50.180
Wir hatten also über das Geheimnisprinzip gesprochen, oder meine

29:50.180 --> 29:51.800
Mitarbeiter hatten es Ihnen erklärt.

29:53.220 --> 30:01.360
Das hat das erste ein gewisser Panas, David Leuge Panas, formuliert,

30:04.060 --> 30:08.260
etwa 1972, so alt ist dieses Konzept schon, hat aber heute noch seine

30:08.260 --> 30:10.880
Gültigkeit, wie Sie gesehen haben, in objektorientierten Sprachen

30:10.880 --> 30:13.960
kommt es noch vor, ein bisschen implizit, wird nicht viel darüber

30:13.960 --> 30:18.500
geredet, aber ich habe darüber geredet, jetzt ausführlich, oder meine

30:18.500 --> 30:18.900
Mitarbeiter.

30:20.380 --> 30:24.220
Hat noch andere Beiträge geleistet, modulare Softwarearchitektur, zum

30:24.220 --> 30:27.240
Beispiel die Benutzrelation, so wie ich sie Ihnen gegeben habe, stammt

30:27.240 --> 30:27.800
auch von ihm.

30:28.660 --> 30:35.120
Ich muss sagen, als ich als Student in den 70er Jahren soweit war, da

30:35.120 --> 30:41.740
gab es eigentlich kaum Bücher und kaum Konzepte darüber, wie man große

30:41.740 --> 30:43.840
Systeme sauber programmiert.

30:44.100 --> 30:52.220
Es gab ein Buch, das hieß Structured Programming, wie man strukturiert

30:52.220 --> 30:52.800
programmiert.

30:53.600 --> 30:59.800
Das war ganz interessant, hatte aber wenig mit Entwurf zu tun, also

30:59.800 --> 31:00.900
Programmieren im Großen.

31:02.680 --> 31:09.760
Der Artikel von Panas über das Geheimnisprinzip war für mich eine

31:09.760 --> 31:10.280
Erleuchtung.

31:10.460 --> 31:13.340
Ach so war das, so ein Aha-Erlebnis.

31:13.440 --> 31:15.800
Jetzt ist es klar, so muss man das machen.

31:17.420 --> 31:20.660
Und es ist tatsächlich auch in Versuchen nachgewiesen worden, dass

31:20.660 --> 31:24.740
wenn man es so macht, die Softwarequalität steigt und die

31:24.740 --> 31:30.460
Programmierproduktivität auch steigt, im Falle dessen, dass man die

31:30.460 --> 31:31.320
Software ändern muss.

31:32.220 --> 31:36.640
Und der Grund, warum ich darauf so herumreite, ist natürlich, dass wir

31:36.640 --> 31:37.860
Software immer ändern müssen.

31:39.360 --> 31:40.940
Das ist einfach Fakt.

31:42.200 --> 31:44.580
Erst ab Version 3.0 sind die Benutzer zufrieden.

31:45.940 --> 31:48.780
Und dann gibt es Wettbewerber, und dann muss ich noch mehr

31:48.780 --> 31:51.200
hineinstopfen in die Software und noch besser machen, noch schöner

31:51.200 --> 31:54.340
machen und mobil machen und grafisch machen und das und jenes.

31:56.660 --> 31:58.660
Erfolgreiche Software wird permanent geändert.

31:59.300 --> 32:02.880
Deswegen machen wir einen Entwurf, der änderungsfreundlich ist.

32:04.180 --> 32:09.220
Okay, jetzt gehen wir...

32:10.120 --> 32:14.380
Übrigens, ich zeige Ihnen kurz, der erste Artikel...

32:16.440 --> 32:18.120
Hier drin formuliert er das.

32:18.160 --> 32:21.120
Wenn Sie das nachlesen wollen, finden Sie bestimmt am Internet On the

32:21.120 --> 32:24.080
criteria to be used in decomposing systems into modules.

32:24.180 --> 32:28.520
Das ist von 1972, aber eigentlich ist ein besserer Artikel von 1979,

32:28.700 --> 32:29.780
der verständlicher ist.

32:30.160 --> 32:32.680
Designing software for ease of extension and contraction.

32:33.240 --> 32:34.620
Genau das, was wir brauchen.

32:35.020 --> 32:36.440
Software muss immer erweitert werden.

32:36.800 --> 32:39.260
Er sagt, kontrahieren muss ich sie auch ab und zu.

32:39.320 --> 32:41.400
Ich muss eine abgespecktere Version liefern können.

32:41.400 --> 32:46.180
Oder eine Teilmenge des Systems woanders einbauen, in einem anderen

32:46.180 --> 32:46.600
Produkt.

32:48.580 --> 32:52.260
Also wenn Sie das noch genauer lesen wollen, auch das finden Sie

32:52.260 --> 32:53.260
garantiert am Internet.

32:53.800 --> 32:56.180
Designing software for ease of extension and contraction.

33:06.360 --> 33:11.380
Ein lustiger Artikel, auch von ihm, is a rational design process.

33:11.560 --> 33:13.640
How and why to fake it.

33:15.220 --> 33:21.260
Warum ein rationaler Entwurfsprozess, wie man den herbeischwindelt.

33:24.260 --> 33:29.080
Um es ganz kurz zu sagen, er sagt, der Entwurfsprozess ist ein

33:29.080 --> 33:30.080
kreativer Prozess.

33:30.380 --> 33:33.160
Kreative Prozesse gehen in Sprüngen vorhanden.

33:33.260 --> 33:35.600
Es fällt Ihnen etwas auf, dann sagen Sie, ach, das muss ich so und so

33:35.600 --> 33:35.860
machen.

33:35.860 --> 33:37.100
Ich denke, das passt so.

33:38.460 --> 33:41.340
Dann lösen Sie einen Teil der Aufgabe, der Entwurfsaufgabe, dann gehen

33:41.340 --> 33:43.660
Sie zum anderen Teil über und dann sagen Sie, ach, das war Mist.

33:44.200 --> 33:45.940
Ich muss das nochmal anders machen.

33:46.020 --> 33:47.100
Ganz anders, ganz anders.

33:47.260 --> 33:49.960
Das mache ich jetzt mit 25 Modulen anstelle von 17.

33:50.560 --> 33:53.020
Und mit der Schnittstelle, und dann nehme ich noch diese Komponente

33:53.020 --> 33:55.660
und sage, ist eigentlich auch nicht so gut.

33:56.180 --> 34:03.080
Und dann ist es ein chaotischer Prozess, bis Sie zu einem brauchbaren

34:03.080 --> 34:03.760
Entwurf gelangen.

34:03.760 --> 34:09.240
Und er sagt, tun Sie es dem Leser Ihrer Entwurfsdokumentation nicht

34:09.240 --> 34:15.820
an, alle diese Irrtümer nachzuerleben.

34:16.080 --> 34:19.200
Ja, als erstes habe ich mir gedacht, ich mache es so und so und so,

34:19.400 --> 34:20.520
und dann klären Sie den ganzen Mist.

34:20.940 --> 34:22.220
Aber das war alles nicht gut.

34:23.540 --> 34:24.280
Vergessen Sie es.

34:24.400 --> 34:29.200
Tun Sie es so, als hätten Sie von Anfang an einen guten Entwurf gehabt

34:29.200 --> 34:30.400
und erklären Sie genau den.

34:31.580 --> 34:36.320
Ohne die Fehler oder Fehlschläge, die Sie hinnehmen mussten.

34:37.460 --> 34:41.840
Und Dokumentation des Entwurfs sieht natürlich jetzt für Sie in der

34:41.840 --> 34:45.560
objektorientierten Zeit aus, dass Sie UML-Diagramme, Klassendiagramme

34:45.560 --> 34:49.260
liefern und diese Klassendiagramme dokumentieren, erklären, was die

34:49.260 --> 34:52.440
Funktionen sind und deren Geheimnisse natürlich.

34:55.040 --> 34:55.580
Okay,

35:00.600 --> 35:05.280
das hier, das lassen wir jetzt mal aus, aber müssen Sie nicht lesen.

35:07.460 --> 35:13.540
Panos ist dann hergegangen und hat gesagt, jetzt probiere ich das mal

35:13.540 --> 35:15.360
aus, und zwar an einem richtigen System.

35:16.520 --> 35:25.300
Und der hatte dann die Software eines Düsenjägers, die Flugsoftware

35:25.300 --> 35:29.380
eines Düsenjägers komplett neu strukturiert, mit dem Prinzip, die er

35:29.380 --> 35:32.840
genannt hatte, nämlich Hierarchische Benutzrelation, Geheimnisprinzip

35:32.840 --> 35:33.820
bei den Modulen.

35:37.880 --> 35:41.240
Ich weiß nicht mehr, wie sie geheißen hat, A7E oder so etwas.

35:41.820 --> 35:44.920
Ist inzwischen natürlich außer Dienst gestellt, ist inzwischen ein

35:44.920 --> 35:45.660
älteres Flugzeug.

35:46.780 --> 35:49.960
Und der hatte in diesem Artikel geschrieben, dass man sich das

35:49.960 --> 35:55.140
Anforderungsdokument dieser Flugsoftware da und dort bestellen konnte.

35:56.660 --> 36:01.460
Und ich dachte mir, da war ich schon in Chaosruhe, das würde mich

36:01.460 --> 36:02.060
interessieren.

36:02.980 --> 36:04.180
Ich habe die bestellt.

36:04.960 --> 36:07.820
Ein dickes Buch, da ist alles drin.

36:08.160 --> 36:11.060
Stellen Sie sich das mal vor, in der heutigen Zeit, ich kriege die

36:11.060 --> 36:15.420
Anforderungsspezifikation für die Flugsoftware eines Düsenjägers aus

36:15.420 --> 36:15.960
einem anderen Land.

36:17.200 --> 36:17.820
Wie kam?

36:18.560 --> 36:19.860
Ich glaube, ich habe sie noch irgendwo.

36:20.580 --> 36:23.940
Das Einzige war, dass immer, wenn es um Waffen ging, alles geschwärzt

36:23.940 --> 36:24.200
war.

36:25.860 --> 36:31.440
Die Waffen waren also geheim, aber das künstliche Horizont, die

36:31.440 --> 36:34.720
Steuerungssoftware, die Knöpfe, Sie können sich anschauen, wie der

36:34.720 --> 36:37.400
Steuerknüppel aussieht, in allen Details.

36:38.200 --> 36:39.560
Das wäre, glaube ich, heute nicht möglich.

36:39.920 --> 36:42.260
Möglicherweise, wenn ich das nur anfordern würde, hätte ich schon

36:42.260 --> 36:43.860
Schwierigkeiten bei der nächsten Einreise.

36:45.960 --> 36:47.040
Okay, so.

36:48.440 --> 36:51.540
Also, das ist eine Methode, die funktioniert und die Sie eigentlich

36:51.540 --> 36:56.420
schon im Programmieren I gewissermaßen implizit mitbekommen haben.

36:58.220 --> 37:00.460
So, und jetzt sprechen wir über den objekteorientierten Entwurf.

37:00.560 --> 37:02.020
Wir müssen jetzt gar nicht mehr viel sagen.

37:03.800 --> 37:07.380
Objekteorientierten Entwurf sagt lediglich, das geheime Prinzip bleibt

37:07.380 --> 37:07.920
erhalten.

37:08.600 --> 37:11.240
Wir haben Schnittstellen, die verbergen Entwurfsentscheidungen, wie

37:11.240 --> 37:13.660
beim Modul, die veränderbar bleiben sollen.

37:16.600 --> 37:21.440
Wir haben unseren externen Entwurf, der sagt, die Analoga zum Modul

37:21.440 --> 37:23.180
sind natürlich die Klassen und das Paket.

37:23.660 --> 37:26.740
Im Paket werden mehrere Klassen zusammengefasst, die gemeinsamen

37:26.740 --> 37:28.160
Entwurfsentscheidungen kapseln.

37:29.580 --> 37:35.320
In der Regel brauchen Sie, um so etwas Äquivalentes wie ein Modul, ein

37:35.320 --> 37:37.900
pandasches Modulkonzept zu haben, mehrere Klassen.

37:38.420 --> 37:45.000
Das heißt, normalerweise ist das Modul in einem Paket verwirklicht.

37:45.200 --> 37:46.440
Drei, vier oder mehr Klassen.

37:48.400 --> 37:51.980
Aber es kann auch sein, dass Sie eine einzelne große Klasse als ein

37:51.980 --> 37:52.960
Modul betrachten.

37:53.620 --> 37:54.370
Was kommt jetzt hinzu?

37:55.360 --> 37:58.820
Anstelle des Modulführers, der eben für jedes einzelne Modul sagt, was

37:58.820 --> 38:01.680
die Geheimnisse des Moduls und seine Schnittstellen sind, seine

38:01.680 --> 38:04.460
Funktionen, steht jetzt der Paket- und Klassenführer.

38:04.500 --> 38:09.080
Das heißt, Sie haben irgendwo in Ihrem Dokumentation ein Klassen- oder

38:09.080 --> 38:12.680
Paketdiagramm mit erläutertem Text, der die Entwurfsentscheidungen

38:12.680 --> 38:13.440
dokumentiert.

38:14.120 --> 38:19.400
Wie gesagt, in einer sauberen Form, ohne auf die Irrtümer, die Sie auf

38:19.400 --> 38:23.180
den Weg gemacht haben, wieder zu keulen.

38:26.540 --> 38:29.400
Genau, und das analog zu den Modul-Schnittstellen sind natürlich die

38:29.400 --> 38:32.320
Schnittstellen der Klassen, auch offensichtlich, oder abstrakte

38:32.320 --> 38:36.100
Klassen oder ganz abstrakte Klassen, nämlich Schnittstellen.

38:36.920 --> 38:37.880
So weit, so gut.

38:37.960 --> 38:39.360
Das haben wir auch längst verstanden.

38:39.360 --> 38:44.300
Der interne Entwurf, der besteht darin, dass Sie die Benutzrelation

38:44.300 --> 38:48.260
auf der Ebene von Paketen darstellen, nicht auf Einzelklassen, sondern

38:48.260 --> 38:49.500
auf der Ebene der Pakete.

38:50.200 --> 38:53.360
Innerhalb eines Paketes muss die Benutzrelation keineswegs

38:53.360 --> 38:56.300
hierarchisch sein, ist es oft nicht möglich.

38:59.740 --> 39:04.480
Der Feinentwurf liefert jetzt, genau wie beim anderen Entwurf auch,

39:04.600 --> 39:07.840
noch Beschreibung der Datenstrukturen und Algorithmen, eventuell auch

39:07.840 --> 39:10.460
noch Pseudocode, wenn wir in Assembler programmieren.

39:12.820 --> 39:15.540
Allerdings haben Sie jetzt beim Objektorientierten Entwurf mehr

39:15.540 --> 39:16.040
Möglichkeiten.

39:16.260 --> 39:19.860
Sie können mehrfach Instanzierung von Klassen haben, das hatten wir

39:19.860 --> 39:20.400
schon gesehen.

39:20.740 --> 39:24.400
Sie können mehrfach Implementierung von einer einzelnen Schnittstelle

39:24.400 --> 39:31.140
haben und sie uniform behandeln, ohne neue Methodennamen zu benutzen.

39:33.040 --> 39:37.800
Sie haben die Vererbung, die Polymorphie und die Möglichkeit der

39:37.800 --> 39:39.420
mehrfach Implementierung einer Schnittstelle.

39:40.340 --> 39:46.320
Das geht in c-artigen Sprachen ohne Objektorientierung schwerlich.

39:53.740 --> 39:58.820
Erstaunlicherweise diese wenigen Zusätze, diese Polymorphie und die

39:58.820 --> 40:02.500
Vererbung und die Schnittstellenimplementierung und die Instanzierung

40:02.500 --> 40:07.560
ermöglicht es jetzt ganz neue Architekturen und Strukturen zu

40:07.560 --> 40:13.360
beschreiben, die in anderen, ohne diese Möglichkeiten, schwierig sind

40:13.360 --> 40:15.720
darzustellen und diese Struktur nennt man Entwurfsmuster.

40:16.520 --> 40:19.380
Dieses Entwurfsmuster werde ich jetzt in den folgenden Vorlesungen

40:19.380 --> 40:19.840
behandeln.

40:19.980 --> 40:23.520
Das ist also eigentlich das Wissen, das aus der Objektorientierung

40:23.520 --> 40:28.140
herausfließt, wie man komplexe Systeme strukturiert, aber nicht nur

40:28.140 --> 40:29.100
aus der Objektorientierung.

40:29.200 --> 40:33.520
Wir werden heute einige sehen, die können Sie natürlich auch in c oder

40:33.520 --> 40:35.760
ähnlichen Sprachen verwirklichen.

40:38.400 --> 40:41.820
Gut, wir machen also jetzt Entwurfsmuster und Architekturstile, dabei

40:41.820 --> 40:43.840
die Architekturstile als nächstes.

40:48.370 --> 40:49.970
Auch wieder zur Historie.

40:50.910 --> 40:54.570
Ein ebenfalls sehr bekannter, berühmter Mann ist Grady Butch.

40:57.490 --> 41:01.610
Der war in der Rational Software Corporation, ich weiß nicht, wo er

41:01.610 --> 41:05.570
heute ist, und ist ein Pionier auf dem Gebiet der modularen,

41:05.670 --> 41:06.650
objektorientierten Software.

41:06.770 --> 41:08.970
Der hat zum Beispiel ein Buch über Software Engineering mit Ada

41:08.970 --> 41:09.750
geschrieben.

41:09.850 --> 41:17.630
Ada ist eine nicht ganz objektorientierte Sprache, aber bei den

41:17.630 --> 41:20.390
wiederverwendbaren Bibliotheken hat er also Klassenbibliotheken für

41:20.390 --> 41:21.350
C++ geschrieben.

41:22.890 --> 41:26.330
Seine Bücher hatten einen sehr großen Einfluss darüber, wie man

41:26.330 --> 41:27.970
objektorientiert programmiert.

41:28.970 --> 41:31.430
Grady Butch, also ein Name, mit dem man sich merken kann.

41:32.970 --> 41:33.270
Vielleicht

41:37.370 --> 41:40.310
haben Sie mal die Möglichkeit, etwas von ihm zu lesen.

41:46.540 --> 41:49.680
Als nächstes kommen jetzt die Architekturstile dran.

41:50.720 --> 41:56.700
Die sind noch meistens weniger objektorientiert, aber ich glaube,

41:56.800 --> 42:02.120
jetzt wird es langsam interessant, weil man jetzt Entwurfsmuster haben

42:02.120 --> 42:07.180
oder Entwurfsstrukturen, die recht hilfreich sind.

42:08.060 --> 42:12.440
Das Erste, was wir machen, ist eine sogenannte abstrakte Maschine oder

42:12.440 --> 42:14.200
virtuelle Maschine erst nur als Begriff.

42:15.180 --> 42:20.280
Virtuelle Maschine ist sicher schon über den Weg gelaufen, denn es

42:20.280 --> 42:23.320
gibt die JVM, die Java Virtual Machine.

42:24.180 --> 42:25.740
Aber was soll das eigentlich sein?

42:26.140 --> 42:27.840
Bis jetzt hatten Sie den Namen gehört.

42:27.840 --> 42:33.580
Man sagt jetzt einfach, eine virtuelle Maschine ist eine Menge von

42:33.580 --> 42:37.620
Softwarebefehlen und Objekten, die auf einer darunterliegenden

42:37.620 --> 42:41.200
abstrakten oder realen Maschine aufbauen und diese ganz oder teilweise

42:41.200 --> 42:42.140
verdecken können.

42:46.400 --> 42:48.630
Eine Menge von Softwarebefehlen und Objekten.

42:48.950 --> 42:49.790
Das ist das Wichtige.

42:50.630 --> 42:54.210
Wir könnten auch sagen, heutige Terminologie RP, Application

42:54.210 --> 42:59.790
Programming Interface, und die auf einer darunterliegenden Maschine

42:59.790 --> 43:04.070
aufbauen, ist klar, irgendwo müsste es realisiert werden und diese

43:04.070 --> 43:07.070
ganz oder teilweise verdecken, werden wir sehen, wann wir das machen

43:07.070 --> 43:07.350
müssen.

43:10.570 --> 43:15.910
Diese virtuelle Maschine baut also auch auf etwas auf, benutzt es also

43:15.910 --> 43:18.870
und da wollen wir natürlich auch dafür sorgen, dass diese

43:18.870 --> 43:20.610
Benutzrelation zyklenfrei ist.

43:21.770 --> 43:22.290
Beispiele.

43:23.110 --> 43:26.710
Die Java JVM, die hatte ich schon erwähnt.

43:26.710 --> 43:28.750
Was ist diese JVM eigentlich?

43:29.310 --> 43:32.870
Diese JVM liefert eine Menge von Befehlen.

43:34.110 --> 43:37.070
Softwarebefehlen, zum Beispiel zum Addieren von Zahlen, zum Anlegen

43:37.070 --> 43:41.330
von Objekten, zum Aufrufen von Methoden und so fort.

43:42.590 --> 43:48.070
Und diese Befehle sind implementiert als Befehlsreihenfolgen in der

43:48.070 --> 43:51.070
darunterliegenden Maschine auf ihrem PC zum Beispiel.

43:51.650 --> 43:54.550
Oder aber, sie werden durch ein anderes Programm interpretiert.

43:54.550 --> 43:55.310
Ja.

43:56.010 --> 44:00.110
Also die Java VM ist klarerweise eine virtuelle Maschine.

44:00.430 --> 44:04.430
Sieht so aus wie ein Rechner, hat Befehle, Grundbefehle zum

44:04.430 --> 44:11.030
Manipulieren von Daten, aber sie existiert nicht richtig als Hardware,

44:11.710 --> 44:15.930
weil es normalerweise keine, es gibt nur wenige Hardware

44:15.930 --> 44:19.050
-Implementierungen von Java, die sich übrigens auch gar nicht

44:19.050 --> 44:19.810
durchgesetzt haben.

44:20.110 --> 44:21.510
Das wäre so eine.

44:21.510 --> 44:26.670
Und natürlich, die Programmiersprache Java zum Beispiel oder auch C

44:27.450 --> 44:31.850
ist eine weitere virtuelle Maschine, die oberhalb der JVM sitzt.

44:33.050 --> 44:35.490
Sie programmieren in der Programmiersprache Java.

44:36.510 --> 44:41.270
Sie schreiben nie einen Maschinenbefehl und auch keinen JVM-Befehl.

44:41.550 --> 44:47.510
Sondern der Übersetzer nimmt ihr Java-Programm, übersetzt es in eine

44:47.510 --> 44:50.250
Folge von JVM-Befehlen.

44:51.810 --> 44:56.410
Diese JVM-Befehle werden dem Java-Laufzeitsystem gegeben und sagt, ach

44:56.410 --> 44:58.330
ja, diese JVM-Befehle verstehe ich.

44:58.650 --> 45:01.950
Die kann ich jetzt wieder übersetzen in Befehlsfolgen auf der zugrunde

45:01.950 --> 45:06.930
liegenden echten, nicht virtuellen, also der realen Maschine.

45:08.210 --> 45:09.930
So, was gibt es noch für Beispiele?

45:11.410 --> 45:12.010
Betriebssystem.

45:12.930 --> 45:16.990
Stellen Sie sich vor, Sie bekämen Ihren PC, ein Laptop oder sonst was

45:16.990 --> 45:17.970
ohne Betriebssystem.

45:18.950 --> 45:19.950
Ganz nackt.

45:21.390 --> 45:26.350
Dann haben Sie nur die Maschinenbefehle, die es gibt, einige

45:26.350 --> 45:29.770
zusätzliche, erkläre ich gleich, die sind normalerweise nicht zu sehen

45:29.770 --> 45:33.630
bekommen und dann ist das Leben ziemlich schwer.

45:35.010 --> 45:37.490
Sie könnten zum Beispiel nicht mal eine Datei lesen.

45:37.830 --> 45:39.790
Sie könnten auch nicht kommunizieren nach außen hin.

45:40.690 --> 45:42.250
Es gibt ja kein Programm, das das macht.

45:42.790 --> 45:50.170
Das Betriebssystem hingegen liefert diese zusätzlichen Funktionen, zum

45:50.170 --> 45:52.590
Beispiel eine Datei zu öffnen und zu lesen, zu schreiben, zu

45:52.590 --> 45:56.970
schließen, eine Netzwerkverbindung zu öffnen, Datenpakete zu

45:56.970 --> 45:59.650
verschicken, die Pakete zu stückeln, sie erneut zu schicken, wenn sie

45:59.650 --> 46:01.510
verloren gehen unterwegs oder kaputt gehen.

46:02.370 --> 46:05.790
Das heißt, dieses Betriebssystem liefert eine ganze Reihe von

46:05.790 --> 46:09.130
Funktionen, die die nackte Hardware nicht hat.

46:09.750 --> 46:14.410
Ist also auch eine virtuelle Maschine, denn alle diese Funktionen, die

46:14.410 --> 46:17.570
höherwertig sind und natürlich viel bequemer zu benutzen sind, werden

46:17.570 --> 46:23.650
letztendlich abgebildet auf Befehlsfolgen, die sie implementieren.

46:23.930 --> 46:27.130
Auf der tatsächlichen richtigen, wirklichen Maschine.

46:28.790 --> 46:29.910
Anwendungskern ist auch so...

46:29.910 --> 46:34.350
Ach so, ich hatte hier oben was gesagt, das ist ganz oder teilweise

46:34.350 --> 46:34.790
verdecken.

46:36.790 --> 46:40.730
Die JVM verdeckt komplett den Befehlssatz.

46:40.730 --> 46:44.210
Die brauchen den nicht, des Rechners.

46:44.490 --> 46:47.470
Wenn sie den Befehlssatz auch noch benutzen würden, aus Java heraus,

46:47.550 --> 46:50.650
was übrigens geht, dann müssen sie sehr, sehr viele Details kennen.

46:52.370 --> 46:54.550
Man nennt das auch das Window to Hell.

46:56.290 --> 46:57.230
Das Fenster in die Hölle.

46:57.850 --> 47:02.210
Wenn sie aus einer höheren Programmiersprache heraus die Befehle der

47:02.890 --> 47:05.690
grundlegenden Architektur benutzen, dann haben sie auch noch den

47:05.690 --> 47:08.650
Nachteil, dass es nur auf der Maschine funktioniert, für die sie es

47:08.650 --> 47:11.470
geschrieben haben und auf der vom Nächsten nicht mehr.

47:12.070 --> 47:13.530
Vom Hersteller unterschiedlich.

47:15.270 --> 47:16.350
Das ist eine Verdeckung.

47:16.910 --> 47:20.390
Das Betriebssystem verdeckt davon aber weniger.

47:20.590 --> 47:26.270
Das Betriebssystem erlaubt es weiterhin, ein Programm, das in

47:26.270 --> 47:27.710
Assembler geschrieben wird, auszuführen.

47:27.790 --> 47:30.490
Das heißt, die Maschinenbefehle sind weiterhin sichtbar.

47:32.030 --> 47:36.170
Allerdings gibt es dabei im Betriebssystem privilegierte Befehle.

47:38.290 --> 47:41.950
Und diese privilegierten Befehle, wenn sie die in ihr

47:41.950 --> 47:47.250
Maschinenprogramm einfügen würden, würden sie entweder eine Ausnahme

47:47.250 --> 47:51.230
erzeugen und das Programm abstoppen oder aber total ignoriert werden.

47:53.770 --> 48:00.510
Manche dieser Betriebssystem, der vom Betriebssystem verdeckten

48:00.510 --> 48:06.870
Befehle haben zum Beispiel zu tun mit dem Zugriff auf Platten.

48:07.290 --> 48:12.530
In ihrem Anwendungsprogramm dürfen sie den Zugriff auf Platten nur

48:12.530 --> 48:15.190
über den entsprechenden Systemaufruf steuern, aber sie dürfen nicht

48:15.190 --> 48:17.310
direkt das Gerät ansteuern.

48:17.890 --> 48:20.130
Denn das würde alles andere völlig durcheinander bringen.

48:22.790 --> 48:28.770
Das heißt also, die JVM verbirgt den Befehlssatz der Maschine.

48:29.830 --> 48:33.250
Das Betriebssystem verbirgt nur einen Teil dieses Befehlssatzes,

48:33.330 --> 48:36.070
nämlich nur die privilegierten Befehle.

48:41.770 --> 48:45.490
GUI-Bibliotheken, also Bibliotheken für grafische Benutzeroberflächen,

48:45.630 --> 48:46.050
sind ähnlich.

48:47.810 --> 48:52.930
Die geben Ihnen komplexe Funktionalität vor, nämlich Fenster und

48:52.930 --> 48:56.610
Knöpfe und Menüs und Rollbalken und was da hängt ab, was es da alles

48:56.610 --> 48:57.010
gibt.

48:57.490 --> 49:01.010
Sie müssen nicht die einzelnen Pixel per Hand andrehen, sondern das

49:01.010 --> 49:03.010
macht die GUI-Bibliothek direkt für Sie.

49:03.870 --> 49:06.970
Und da, wo die GUI-Bibliothek arbeitet, zum Beispiel im Rollbalken,

49:07.090 --> 49:08.570
können Sie auch nicht hineinschreiben.

49:09.690 --> 49:11.990
Es ist also auch ein Teil davon verdeckt.

49:16.230 --> 49:18.870
Das war also die Idee der virtuellen Maschine.

49:19.950 --> 49:21.290
Und jetzt benutzen wir das.

49:24.470 --> 49:28.730
Das ist die abstrakte Maschine oder virtuelle Maschine, das ist also

49:28.730 --> 49:31.610
das, was ich jetzt mündlich erklärt habe, nochmal skizziert.

49:33.650 --> 49:36.530
Natürlich sollten die Befehle, die die abstrakte Maschine zur

49:36.530 --> 49:39.630
Verfügung stellt, so vielfältig wie nur möglich eingesetzt werden

49:39.630 --> 49:39.990
können.

49:41.030 --> 49:46.530
Java -Programmiersprache, JVM, sehr universell einsetzbar sein für die

49:46.530 --> 49:48.250
Zwecke, die man vorhat.

49:53.170 --> 49:57.370
Beispiel, das Betriebssystem, das macht also die Kommunikation, die

49:57.370 --> 50:01.390
Kommandosprache, die Datenhaltung auf Hintergrundspeicher, also

50:01.390 --> 50:05.930
Platte, CD, DVD, Speicherstift und so weiter.

50:06.290 --> 50:08.390
Es bietet einen sogenannten virtuellen Speicher.

50:09.070 --> 50:12.350
Virtueller Speicher heißt, Sie programmieren, als hätten Sie einen

50:12.350 --> 50:15.950
unbegrenzten, ewig langen Hauptspeicher von einem ganzen Terabyte oder

50:15.950 --> 50:19.310
so etwas, wenn in Wirklichkeit die Rechner vielleicht nur einige

50:19.310 --> 50:20.210
Gigabyte enthält.

50:20.690 --> 50:28.810
Und die Abbildung des Gesamt- Adressraumes auf Ihren Hauptspeicher,

50:29.130 --> 50:32.610
der ja viel kleiner ist, übernimmt auch wieder das Betriebssystem.

50:34.470 --> 50:37.610
Ihr Gesamtspeicher eines Programms, wenn er sehr groß wird, muss dann

50:37.610 --> 50:39.390
natürlich auf die Platte ausgelagert werden.

50:39.750 --> 50:43.110
Wenn man da jetzt etwas braucht, das auf der Platte ist, aber nicht im

50:43.110 --> 50:45.810
Hauptspeicher, muss es erst reingeholt werden und dafür etwas anderes

50:45.810 --> 50:46.710
rausgeschrieben werden.

50:47.130 --> 50:51.850
Das macht man in der Regel mit einem Paging-Verfahren, also mit

50:52.810 --> 50:53.390
Seitenaustausch.

50:55.270 --> 50:58.370
So, und eine der grundlegenden Funktionen ist auch die

50:58.370 --> 50:59.150
Prozessverwaltung.

50:59.450 --> 51:04.290
Wenn Sie mal nachschauen in Ihrem Prozessmonitor auf Ihrem PC, werden

51:04.290 --> 51:07.570
Sie sehen, dass es ja Dutzende von Prozessen sind, die eigentlich

51:07.570 --> 51:10.390
permanent irgendwas zu tun haben oder gerade warten.

51:11.210 --> 51:14.150
Das ist nicht nur Ihr Applikationsprogramm, sondern alles mögliche an

51:14.150 --> 51:14.850
Dienstprogrammen.

51:15.830 --> 51:20.170
Und das Ausführen dieser Prozesse auf einem einzelnen Kern oder auch

51:20.170 --> 51:24.430
auf mehreren Kernen, der jetzt gerade laufen darf, wie lange, was dann

51:24.430 --> 51:25.310
passiert, wenn er stoppt.

51:25.790 --> 51:28.210
Das ist die Prozessverwaltung, die ist natürlich auch im

51:28.210 --> 51:29.030
Betriebssystem drin.

51:29.830 --> 51:33.810
Das heißt, man kann übrigens das Betriebssystem als eine Folge von

51:33.810 --> 51:35.850
virtuellen Maschinen sehen.

51:36.310 --> 51:41.250
Also als allererstes ist die Hardware selbst, als nächstes käme die

51:41.250 --> 51:44.890
Prozessverwaltung, die bietet Ihnen dann die Möglichkeit, Prozesse zu

51:44.890 --> 51:45.810
starten und anzuhalten.

51:46.770 --> 51:49.770
Darüber liegt dann der virtuelle Speicher, der dafür sorgt, dass wir

51:49.770 --> 51:53.090
einen virtuellen großen Speicherplatz haben und darüber kommen dann

51:53.090 --> 51:55.630
die Datenhaltung und die Kommunikation.

51:56.790 --> 52:01.690
Und als letztes die Benutzerschicht mit entweder einer Kommandosprache

52:03.010 --> 52:06.870
oder einer grafischen Benutzeroberfläche oder beides.

52:12.790 --> 52:16.170
Genau, das hatte ich auch schon gesagt, diese privilegierten Befehle,

52:16.270 --> 52:18.830
wenn Sie sie benutzen in Ihrem Programm, in dem nicht-privilegierten

52:18.830 --> 52:22.150
Modus, die werden Sie entweder ignoriert oder führen zu einem Fehler.

52:24.550 --> 52:25.630
Das hatten wir auch besprochen.

52:28.210 --> 52:33.430
Sie können auch sagen, angenommen, ich habe ein System zur Behandlung

52:33.430 --> 52:34.270
elektronischer Post.

52:36.050 --> 52:38.130
Auch dafür kann ich eine API schreiben.

52:39.070 --> 52:42.670
Denken Sie mal nicht unbedingt an Ihren grafischen Postklienten,

52:43.390 --> 52:45.550
sondern an die Grundfunktion, die Sie dafür brauchen.

52:46.130 --> 52:49.650
Und das machen natürlich die darunterliegenden Protokolle, Pufferung

52:49.650 --> 52:52.650
und Stückelung der Botschaften, Zusammensetzung von langen

52:52.650 --> 52:56.670
Nachrichten, Quittierungen, Fehlerbehandlungen, Kommunikation mit dem

52:56.670 --> 52:57.990
Dienstgeber und so weiter.

52:58.470 --> 53:00.970
Sodass ein zuverlässiger Nachrichtenaustausch entsteht.

53:02.670 --> 53:05.670
Wer von Ihnen hat schon mal mit Makros gearbeitet?

53:07.410 --> 53:10.830
Makros, Makros 1, 2, 3, 4...

53:10.830 --> 53:12.250
Also es sind nicht sehr viele.

53:13.450 --> 53:16.870
Ist auch nicht verwunderlich, denn Makros nimmt man hauptsächlich in

53:16.870 --> 53:20.370
Assemblerprogrammen her, aber auch noch in C übrigens.

53:21.570 --> 53:29.430
Makros sehen fast so aus wie Methoden oder Prozeduren, aber ein Makro

53:29.430 --> 53:32.510
ist einfach eine Kurzschrift, um ein Stück Code an einer anderen

53:32.510 --> 53:33.770
Stelle einzusetzen per Namen.

53:33.950 --> 53:37.730
Sie können also ein Makro definieren, der eine Befehlsfolge enthält

53:37.730 --> 53:41.070
und wenn Sie den Makro aufrufen, in Anführungszeichen, dann wird

53:41.070 --> 53:43.450
dieser Text an der Stelle eingepflanzt.

53:45.430 --> 53:48.450
Ist gelegentlich ganz praktisch.

53:50.370 --> 53:54.730
Zum Beispiel, wenn Sie in Assembler programmieren, haben Sie sicher

53:54.730 --> 54:00.430
Makros, die die Befehle einflechten, den Prozeduraufruf und Rückkehr

54:00.430 --> 54:01.750
liefern.

54:02.170 --> 54:06.190
Zum Aufrufen müssen Sie meistens Parameter anlegen und Platz schaffen

54:06.190 --> 54:10.490
und den Rückgabewert Platz vorhalten und Sie müssen die

54:10.490 --> 54:13.930
Rücksprungadresse aufbewahren und was da alles reingehört.

54:15.270 --> 54:19.510
Das ist also typischerweise eine Befehlsfolge von dutzenden Befehlen.

54:20.350 --> 54:24.250
Und die Befehlsfolge, die lassen Sie sich durch ein Makroaufruf

54:25.490 --> 54:26.750
erzeugen, reinschreiben.

54:27.190 --> 54:27.910
Das ist also ein Kürzel.

54:29.170 --> 54:32.650
Der eignet sich übrigens nicht dafür, andere Instruktionen zu

54:32.650 --> 54:36.510
verbergen, was zu Inkonsistenzen führen kann, wenn Sie mal das Makro

54:36.510 --> 54:41.730
benutzen und mal den Aufruf, die Aufrufsfolge selbst hinschreiben und

54:41.730 --> 54:42.450
dabei einen Fehler machen.

54:44.390 --> 54:45.130
Okay, so.

54:46.710 --> 54:50.630
Das war also jetzt das Konzept der virtuellen Maschine oder auch

54:50.630 --> 54:51.550
abstrakter Maschine.

54:51.910 --> 54:52.750
Gibt es dazu Fragen?

54:59.290 --> 55:03.110
Das hat jetzt mit Objektorientierung erstmal, ist orthogonal dazu,

55:04.270 --> 55:08.070
können Sie sowohl objektorientiert als auch ohne Objektorientierung

55:08.070 --> 55:08.670
verwirklichen.

55:09.430 --> 55:11.670
Dann gibt es noch einen Begriff, der wichtig ist.

55:11.810 --> 55:16.050
Das sind die Programmfamilien oder die Softwareproduktlinie.

55:16.890 --> 55:21.230
Früher sagte man übrigens, der Begriff stammt noch von Parnas, er

55:21.230 --> 55:27.170
sprach von Programmfamilies und später dann hat man einen schickeren

55:27.170 --> 55:30.310
Term gefunden, nämlich die Softwareproduktlinie.

55:30.930 --> 55:31.530
Softwareproduktlinie.

55:31.970 --> 55:34.950
Eine Menge von Programmen, die erhebliche Anteile von Anforderungen,

55:35.050 --> 55:38.090
Entwurfsbestandteilen oder Softwarekomponenten gemeinsam haben.

55:38.090 --> 55:42.770
Unterschiedliche, ähnliche Programme, Bestandteile haben.

55:42.990 --> 55:47.830
Denken Sie an die Idee bei den Autos, da ist es genau das gleiche.

55:47.870 --> 55:54.250
Sie haben eine Motorenpalette und Sie haben ein Modularen

55:54.250 --> 55:55.130
Querbaukasten.

55:56.210 --> 56:03.170
Da haben Sie verschiedenste Komponenten, die Sie anderweitig

56:03.170 --> 56:07.070
zusammengestellt mit einer anderen Karosserie als ein neues Fahrzeug

56:07.070 --> 56:07.810
verkaufen können.

56:09.850 --> 56:12.470
Und es ist natürlich klar, dass ich dafür sehr, sehr viel

56:12.470 --> 56:15.810
Entwicklungszeit spare, wenn ich nicht für jedes Modell, das ich

56:15.810 --> 56:19.870
anbiete, in dieser Modellvielfalt von heute, wenn ich da jedes Mal

56:19.870 --> 56:24.890
einen völlig neuen Motor entwickeln muss, sondern aus meiner Palette

56:24.890 --> 56:28.950
von Motoren auswählen kann, sogar den Kunden überlassen kann, wie viel

56:28.950 --> 56:29.750
PS er haben will.

56:31.470 --> 56:34.890
Und die gleiche Idee bei der Produktfamilie beziehungsweise bei der

56:34.890 --> 56:35.770
Softwareproduktlinien.

56:35.850 --> 56:41.410
Sie planen für mehrere Kunden leicht unterschiedliche Varianten eines

56:41.410 --> 56:42.830
Systems auszuliefern.

56:43.510 --> 56:48.270
Und haben jetzt die Möglichkeit, bestimmte Grundkomponenten, die kann

56:48.270 --> 56:51.830
ich mehrfach benutzen, aber nicht nur die Softwarekomponenten selbst,

56:51.930 --> 56:53.790
sondern vielleicht auch die Entwurfsbarstandteile.

56:55.150 --> 56:58.030
Und wenn es noch weiter geht, übrigens Anforderungen zu schreiben, ist

56:58.030 --> 56:59.030
auch sehr aufwendig.

57:00.990 --> 57:05.630
Das sind oft gerne 500.000 oder noch mehr Seiten und Bände, da ist

57:05.630 --> 57:08.370
natürlich auch klar, dass ich sage, ja gut, die Anforderungen sind

57:08.370 --> 57:09.970
eigentlich an der und der Stelle die gleichen.

57:10.650 --> 57:14.850
Die benutze ich erneut in der neuen Version meiner Software.

57:17.010 --> 57:21.390
Das ist kostengünstiger, ein neues Mitglied der Produktfamilie zu

57:21.390 --> 57:25.170
planen, zu entwerfen und schließlich zu implementieren.

57:26.530 --> 57:31.750
Und natürlich auch zu testen, denn fertige Komponenten, die schon

57:31.750 --> 57:33.850
getestet sind, brauche ich nicht erneut zu testen.

57:36.050 --> 57:39.790
Das Ziel ist die Aufnutzung von Gemeinsamkeiten und Wiederverwendung

57:39.790 --> 57:42.450
von Entwürfen, Spezifikationen, Anforderungen, Softwarekomponenten,

57:42.510 --> 57:46.110
Bibliotheken, alles was wir früher schon erzeugt haben, um

57:46.110 --> 57:48.610
Entwicklungs - und Wartungskosten zu reduzieren.

57:49.090 --> 57:54.510
Man spricht übrigens in diesen Produktfamilien oder Produktlinien von

57:54.510 --> 57:55.590
Variationspunkten.

57:56.750 --> 58:00.150
Da gibt es Stellen in der Architektur, wo vorgesehen ist, eine andere

58:00.150 --> 58:04.330
Komponente einzuführen, die sich in Funktionalität oder Plattform

58:04.330 --> 58:06.170
unterscheiden.

58:12.550 --> 58:15.070
Das könnte zum Beispiel eine mobile Variante sein.

58:15.390 --> 58:18.670
Da haben Sie eine mobile Variante und die Datenführung ist nicht mehr

58:19.790 --> 58:22.730
auf dem mobilen Gerät, sondern auf einem Dienstgeber.

58:22.830 --> 58:25.530
Das heißt, jedes Mal, wenn Zugriffe auf diese Daten sind, brauchen Sie

58:25.530 --> 58:31.790
einen Variationspunkt, und wer sagt, an dieser Stelle könntest du eine

58:32.610 --> 58:34.330
Fernübertragung der Daten einfügen.

58:36.230 --> 58:37.030
so geht das.

58:38.530 --> 58:41.150
Sie können auch auf verschiedenen Hardware- und Betriebssystemen

58:41.150 --> 58:41.450
laufen.

58:41.850 --> 58:44.610
Das heißt, es gibt bestimmte Komponenten, die ersetzt werden müssen,

58:44.690 --> 58:46.490
die Betriebssystemen nahe sind.

58:49.270 --> 58:52.630
Es kann sein, dass sie sich im Format von Ein- und Ausgabe

58:52.630 --> 58:56.170
unterscheiden oder sogar im Funktionsumfang.

58:56.170 --> 59:00.010
Es gibt eine Enterprise Edition und es gibt eine Professional Edition

59:00.010 --> 59:01.090
und es gibt eine Home Edition.

59:01.890 --> 59:05.670
Diese Euphemismen für billigere Varianten.

59:11.210 --> 59:14.370
Wie unterscheiden sich jetzt diese Mitglieder einer Programmfamilie?

59:14.490 --> 59:17.550
Naja, sie unterscheiden sich eben in Datenstrukturen und Algorithmen.

59:18.290 --> 59:19.490
Sie unterscheiden sich daran,

59:23.230 --> 59:25.410
dass sie auf unterschiedlichen Plattformen laufen.

59:29.590 --> 59:31.590
Jetzt brauchen wir noch einen kleinen Unterschied.

59:33.530 --> 59:36.810
Unterschied zwischen Allgemeinheit und Flexibilität.

59:37.870 --> 59:40.950
Allgemeinheit heißt, ein Programm ist allgemein, falls es in vielen

59:40.950 --> 59:43.070
Situationen ohne Änderung benutzt werden kann.

59:43.250 --> 59:47.970
Also es läuft sowohl mobil als auch auf dem Dienstgeber, als auch

59:47.970 --> 59:48.550
zentral.

59:50.070 --> 59:54.030
Es läuft auf allen Plattformen, die es gerade so gibt, irgendwie,

59:54.270 --> 59:55.250
schwer zu erreichen.

59:56.950 --> 59:57.670
Das wäre Allgemeinheit.

59:58.970 --> 01:00:02.390
So eine überbordende Allgemeinheit ist meistens mit sehr, sehr hohen

01:00:02.390 --> 01:00:03.610
Entwicklungskosten verbunden.

01:00:04.770 --> 01:00:07.350
Da könnte es sein, dass ich spezielle Compiler schreiben muss, um das

01:00:07.350 --> 01:00:08.450
zu erreichen, zum Beispiel.

01:00:09.410 --> 01:00:13.650
Aber wir sagen, ein Programm ist flexibel, wenn ich es abändern kann,

01:00:14.090 --> 01:00:17.690
sodass es für viele Situationen einsetzbar werden kann.

01:00:18.590 --> 01:00:23.190
Und wir sind eher interessiert an der Flexibilität als an der

01:00:23.190 --> 01:00:24.010
Allgemeinheit.

01:00:24.990 --> 01:00:27.810
Flexibilität heißt, wir haben ein Software-System, das

01:00:27.810 --> 01:00:32.410
zufriedenstehend läuft, für einen bestimmten Benutzerkreis, aber es

01:00:32.410 --> 01:00:35.370
kommen neue Anforderungen heran, eine neue Plattform, also wir es auch

01:00:35.370 --> 01:00:38.410
noch auf dem Gerät haben, dann können wir die Software so abändern,

01:00:38.710 --> 01:00:41.650
dass es auch den neuen Anforderungen genügt.

01:00:44.680 --> 01:00:47.800
Ein flexibler Entwurf muss also änderungsfreundlich sein.

01:00:48.180 --> 01:00:50.940
Und das ist das, worüber wir im Entwurf die ganze Zeit reden,

01:00:51.660 --> 01:00:52.580
Änderungsfreundlichkeit.

01:00:55.060 --> 01:00:56.900
Noch irgendwelche Fragen dazu?

01:01:01.120 --> 01:01:07.100
Das waren also jetzt diese beiden Konzepte, nämlich abstrakte Maschine

01:01:07.100 --> 01:01:10.360
oder virtuelle Maschine und Produktfamilie.

01:01:11.440 --> 01:01:13.980
Jetzt kommt ein anderer Begriff, nämlich der Begriff des

01:01:13.980 --> 01:01:15.220
Architekturstils.

01:01:18.440 --> 01:01:20.920
Architekturstile beschreiben den Grobaufbau eines Gesamtsystems.

01:01:22.660 --> 01:01:26.200
Man könnte auch sagen, sind sehr grobkörnige Entwurfsmuster.

01:01:27.500 --> 01:01:31.520
Und da gibt es jetzt eine ganze Latte davon, die schauen wir uns an,

01:01:31.580 --> 01:01:35.400
die sind übrigens gar nicht mal, sind also unabhängig von

01:01:35.400 --> 01:01:36.640
Objektorientierung oder nicht.

01:01:37.780 --> 01:01:40.320
Da gibt es die Schichtenarchitektur, den Klientdienstgeber,

01:01:40.740 --> 01:01:46.140
Partnernetze, Datenablage, MVC, Fließband, Rahmenarchitektur und

01:01:46.140 --> 01:01:47.460
dienstorientierte Architektur.

01:01:48.720 --> 01:01:51.940
Diese Begriffe tauchen immer wieder auf und die müssen wir kurz

01:01:51.940 --> 01:01:54.880
klären, wie so etwas aussieht, ist aber keine Zauberei.

01:01:57.160 --> 01:01:58.600
Die Schichtenarchitektur.

01:01:58.980 --> 01:02:05.120
Die Schichtenarchitektur sagt, wir haben eine Softwarearchitektur, die

01:02:05.120 --> 01:02:09.400
gegliedert ist in hierarchisch angeordnete Schichten, die Schichten

01:02:09.400 --> 01:02:14.400
sind Mengen von Systemkomponenten, Softwarekomponenten, Module,

01:02:14.540 --> 01:02:18.320
Klassen, Objekte, Pakete, was immer, mit einer wohldefinierten

01:02:18.320 --> 01:02:22.300
Schnittstelle und dann gibt es eine Benutzrelation zwischen den

01:02:22.300 --> 01:02:28.720
Schichten, wobei diese nach Möglichkeit nicht zyklisch ist.

01:02:29.880 --> 01:02:30.480
Beispiel.

01:02:31.540 --> 01:02:34.720
Das wäre eine Illustration einer Schichtenarchitektur.

01:02:34.820 --> 01:02:38.700
Wir haben hier drei Schichten, in den Schichten liegen einzelne

01:02:38.700 --> 01:02:42.480
Komponenten, die können sich untereinander benutzen, wie sie wollen,

01:02:42.680 --> 01:02:45.340
die hier benutzen sich gar nicht, da ist auch nichts eingezeichnet,

01:02:45.880 --> 01:02:48.820
aber die Benutzung läuft immer von oben nach unten, von der höheren

01:02:48.820 --> 01:02:50.020
Schicht zur niedrigeren Schicht.

01:02:52.620 --> 01:02:56.580
Das könnte zum Beispiel die Nutzoberfläche sein, das hier könnte der

01:02:56.580 --> 01:02:59.800
Anwendungskern sein und das unterste die Datenhaltung.

01:03:00.040 --> 01:03:03.040
Eine Drei-Schichten-Architektur und wir erlauben diese Aufrufe in

01:03:03.040 --> 01:03:09.140
diese Richtung, wobei jetzt die Frage ist, ob es erlaubt ist, nur

01:03:09.140 --> 01:03:13.320
seine nächste darunterliegende Schicht zu benutzen, also aufzurufen,

01:03:14.380 --> 01:03:16.960
oder ob ich so einen Aufruf machen kann, der von der obersten Schicht

01:03:16.960 --> 01:03:18.260
bis in die unterste Schicht geht.

01:03:18.900 --> 01:03:22.860
Das ist eine Entwurfsentscheidung, da gibt es keine endgültige Antwort

01:03:22.860 --> 01:03:24.780
Ja oder Nein, das hängt davon ab, was man will.

01:03:25.880 --> 01:03:30.860
Die meisten würden sagen, schöner ist es, wenn diese Schicht nur die

01:03:30.860 --> 01:03:35.100
genau darunterliegende Schicht benutzt, wenn sie trotzdem noch die

01:03:35.100 --> 01:03:37.560
unterste Schicht braucht, dann müsste ich hier eine

01:03:37.560 --> 01:03:41.320
Delegationsfunktion oder Delegationskomponente einfügen, für die

01:03:41.320 --> 01:03:41.860
wenigen Fälle.

01:03:43.660 --> 01:03:46.460
Das ist die sogenannte intransparente Schichtung.

01:03:47.120 --> 01:03:49.720
Die transparente Schichtung sagt, du kannst durch diese Schichten

01:03:49.720 --> 01:03:51.600
durchschauen und auch so einen Aufruf durchführen.

01:04:01.860 --> 01:04:07.040
Also jede Schicht, deren Struktur ist beliebig, aber sollte natürlich

01:04:07.040 --> 01:04:08.160
auch nicht chaotisch sein.

01:04:10.100 --> 01:04:13.280
Bei der intransparenten Schicht, das sagte ich gerade, oder opaque

01:04:13.280 --> 01:04:17.240
layers, da sprechen wir nur von einer Schicht zur nächsten

01:04:17.240 --> 01:04:18.080
darunterliegenden.

01:04:20.940 --> 01:04:25.520
Da ist also das hier nicht erlaubt und der Aufruf nach oben auch

01:04:25.520 --> 01:04:25.820
nicht.

01:04:27.340 --> 01:04:29.560
Das ist also die intransparente Schichtung.

01:04:29.980 --> 01:04:31.840
Ich kann also durch diese Schicht nicht durchschauen.

01:04:33.160 --> 01:04:34.740
Schicht B ist hier intransparent.

01:04:35.920 --> 01:04:39.080
Bei einer transparenten Schichtenreichtum ist es erlaubt, dass ich

01:04:39.080 --> 01:04:42.640
natürlich diese Aufrufe durchführe wie immer, aber auch diesen Aufruf.

01:04:42.760 --> 01:04:43.640
Deswegen der Haken dran.

01:04:44.340 --> 01:04:46.600
Die Umgekehrte ist weiterhin nicht erlaubt.

01:04:49.080 --> 01:04:51.780
Vorteile der Schichtenreichtum, es ist einfach zu verstehen.

01:04:52.420 --> 01:04:54.220
Es gibt eben diese drei Schichten oder vier Schichten.

01:04:55.660 --> 01:04:57.080
Es ist einfach zu testen.

01:04:57.380 --> 01:05:00.360
Ich beginne mit dem Testen der Schicht C und auch mit dem Bau der

01:05:00.360 --> 01:05:00.820
Schicht C.

01:05:01.160 --> 01:05:03.860
Wenn ich Schicht C fertig habe, dann kann ich Schicht B testen.

01:05:04.740 --> 01:05:06.920
Sie wird dann die Schicht C natürlich im Test benutzen.

01:05:07.020 --> 01:05:10.200
Wunderbar, geht aber alles und Schicht A genauso.

01:05:11.300 --> 01:05:14.560
Ich kann aber sogar die Schicht A testen, ohne dass die Schichten B

01:05:14.560 --> 01:05:17.360
und C da sind, wenn ich mir stattdessen Platzhalter besorge.

01:05:18.000 --> 01:05:20.220
Sogenannte Stubs, die eben gar nichts tun.

01:05:20.640 --> 01:05:22.420
Nur den Aufruf entgegennehmen und dann zurückkehren.

01:05:23.700 --> 01:05:26.000
Wie man das testet, werden wir später noch genauer sehen.

01:05:31.620 --> 01:05:35.540
Übersichtliche Struktur, keine zu starke Einschränkung des Entwerfers,

01:05:37.240 --> 01:05:40.940
weil sie noch liberale Strukturierungsmechanismen Möglichkeiten

01:05:40.940 --> 01:05:44.980
innerhalb einer Schicht haben und sie können wiederverwenden, sie

01:05:44.980 --> 01:05:50.300
können eine Schicht austauschen, sie können sie woanders benutzen und

01:05:50.300 --> 01:05:52.760
sie können von unten oder von oben her testen.

01:05:56.280 --> 01:05:58.040
Das war also die Schichtenarchitektur.

01:05:58.980 --> 01:06:01.880
Bei intransparenten Schichten kann es sein, dass es zu leichten

01:06:02.520 --> 01:06:05.320
Effizienzverlusten kommt, wenn Sie Aufrufe haben, die sehr weit nach

01:06:05.320 --> 01:06:07.820
unten durchgereicht werden müssen, ohne dass etwas passiert.

01:06:08.620 --> 01:06:11.660
Dann würde man besser eine transparente Schichtung nehmen, wo man

01:06:11.660 --> 01:06:15.320
gleich den Aufruf machen kann, anstelle 25 mal delegiert zu werden.

01:06:15.640 --> 01:06:18.980
Immer die Parameter runterliefern und dann das Ergebnis wieder

01:06:18.980 --> 01:06:19.480
hochliefern.

01:06:20.420 --> 01:06:22.960
Aber in den meisten Fällen ist das unproblematisch.

01:06:25.060 --> 01:06:26.860
Für Fehlermeldungen ist das das Gleiche.

01:06:26.960 --> 01:06:29.760
Wenn ich dann irgendwo in einer Schicht ganz oben bin und eine

01:06:29.760 --> 01:06:32.340
Fehlermeldung von ganz unten bekomme, muss die natürlich durchgereicht

01:06:32.340 --> 01:06:32.640
werden.

01:06:33.460 --> 01:06:37.480
Aber da hilft uns in diesem Falle moderne Programmiersprachen, wie zum

01:06:37.480 --> 01:06:41.040
Beispiel Java, die einen Catch-Throw-Mechanismus haben, wo ich das

01:06:41.040 --> 01:06:44.880
nicht machen muss, also explizit auch noch die Fehlerbehandlung

01:06:44.880 --> 01:06:48.480
zurückreichen muss, sondern ich warte hier an einer bestimmten Stelle

01:06:48.480 --> 01:06:51.580
auf einen Fehler und wenn der auftritt, dann springt dieses Stück

01:06:51.580 --> 01:06:55.140
Software an, um den Fehler zu behandeln, egal woher er kommt.

01:06:56.000 --> 01:06:58.200
Das macht es also sehr praktisch.

01:07:01.180 --> 01:07:01.880
Okay, gut.

01:07:02.720 --> 01:07:04.060
Hier sind ein paar Beispiele.

01:07:04.280 --> 01:07:06.260
Da gibt es die Dreischicht-Architektur, die habe ich jetzt schon

01:07:06.260 --> 01:07:09.880
dreimal erwähnt, nämlich Benutzer, Schnittstelle, Anwendungskern und

01:07:09.880 --> 01:07:10.440
Datenbank.

01:07:10.900 --> 01:07:13.400
Dann gibt es eine dreistufige Architektur.

01:07:14.120 --> 01:07:17.860
Englisch heißt das jetzt Three-Tier-Architecture, also nichts mit

01:07:17.860 --> 01:07:23.420
Animal zu tun, sondern Tier ist einfach ein anderes Wort für Schicht.

01:07:25.280 --> 01:07:27.720
Eine dreistufige Architektur, bei welcher die Schichten auf

01:07:27.720 --> 01:07:29.060
unterschiedlichen Rechnern laufen.

01:07:30.100 --> 01:07:33.560
Wenn Sie also Three-Tier-Architecture hören, dann wissen Sie, da ist

01:07:33.560 --> 01:07:34.300
irgendwas mobil.

01:07:34.780 --> 01:07:37.500
Da gibt es einen Klienten, auf dem läuft unter Umständen die

01:07:37.500 --> 01:07:40.920
Benutzerschicht und einen Dienstgeber, auf dem läuft die

01:07:40.920 --> 01:07:45.700
Anwendungskern und die Datenhaltung oder Benutzerschicht und

01:07:45.700 --> 01:07:48.520
Anwendungskern sind auf dem einen Gerät und Datenhaltung ist auf dem

01:07:48.520 --> 01:07:49.000
anderen Gerät.

01:07:51.380 --> 01:07:54.420
Also eine dreistufige Architektur oder Three-Tier-Architecture.

01:07:54.960 --> 01:07:57.100
Hier ist zum Beispiel eine vierstufige Architektur.

01:07:57.440 --> 01:07:58.560
Wir haben unten einen Kerner.

01:07:59.820 --> 01:08:01.260
Hier gibt es Grundfunktionen.

01:08:01.800 --> 01:08:05.120
Dann gibt es ein anderes Kern 1, der erweitert die Grundfunktionen

01:08:05.120 --> 01:08:08.040
über zusätzliche Funktionen und schließlich Benutzerschnittstelle.

01:08:08.560 --> 01:08:12.040
Und hier gibt es eine andere Anwendung, die braucht andere

01:08:12.040 --> 01:08:13.260
Zusatzfunktionen.

01:08:13.760 --> 01:08:16.180
Die werden hier drin verwirklicht und dann die Benutzerschnittstelle

01:08:16.180 --> 01:08:16.480
dazu.

01:08:17.440 --> 01:08:23.500
Das wäre zum Beispiel praktisch für eine Programmfamilie oder eine

01:08:23.500 --> 01:08:26.760
Produktlinie mit zwei Ausprägungen.

01:08:27.380 --> 01:08:30.880
Da gibt es den Teil hier, der allen gemeinsam ist.

01:08:31.580 --> 01:08:33.620
Wenn ich also nur einmal implementieren muss.

01:08:38.570 --> 01:08:40.350
Hier kommt noch ein Beispiel, aber das können Sie dann selber

01:08:40.350 --> 01:08:40.690
durchlesen.

01:08:40.790 --> 01:08:42.930
Ich glaube, Sie haben verstanden, was die vier Schichten Architektur

01:08:42.930 --> 01:08:43.170
ist.

01:08:43.650 --> 01:08:45.650
Betriebssystem, die wichtigsten Schichten hatte ich auch schon

01:08:45.650 --> 01:08:46.050
besprochen.

01:08:46.790 --> 01:08:50.190
Protokolltürme bei Datenfernübertragung, Informationssysteme, bauen

01:08:50.190 --> 01:08:54.270
auf Datenbanken auf, sind in der Regel zwei- bis dreischichtig und so

01:08:54.270 --> 01:08:54.550
weiter.

01:08:54.850 --> 01:08:57.130
Ist also sehr, sehr oft benutzt.

01:08:57.870 --> 01:08:59.230
Findet man immer, immer wieder.

01:09:00.310 --> 01:09:02.110
Schichten Architektur also wichtig.

01:09:03.610 --> 01:09:04.370
Dufig und schichtig.

01:09:06.870 --> 01:09:07.130
Genau.

01:09:07.310 --> 01:09:10.990
Was wir noch brauchen, was etwas mit der Schichten Architektur zu tun

01:09:10.990 --> 01:09:11.750
hat, ist Folgendes.

01:09:12.530 --> 01:09:13.870
Ich zeige es Ihnen am besten am Bild.

01:09:14.570 --> 01:09:20.430
Angenommen, das hier ist eine Schicht, da sind 38 Klassen drin.

01:09:21.470 --> 01:09:25.010
Hunderte von Objekten und darüber ist die nächste Schicht, ich habe es

01:09:25.010 --> 01:09:28.310
jetzt nicht als Schicht zusammengefasst, und die macht also Aufrufe

01:09:28.310 --> 01:09:30.190
rein, in diese Schicht rein.

01:09:30.370 --> 01:09:33.610
Und da sagen Sie, das ist mir zu unsicher.

01:09:34.930 --> 01:09:38.010
Die obere Schicht sollte eigentlich nicht jede Komponente hier unten

01:09:38.010 --> 01:09:41.010
ansprechen können, denn das führt unter Umständen zu Fehlern.

01:09:42.270 --> 01:09:44.530
Also setze ich jetzt davor eine Fassade.

01:09:45.850 --> 01:09:51.770
Das heißt, die obere Schicht ruft Aufrufe an, greift auf Aufrufe und

01:09:51.770 --> 01:09:55.110
Objekte zu, die in der Fassade vorhanden sind.

01:09:55.770 --> 01:09:57.410
Die Fassade tut gar nichts.

01:09:57.870 --> 01:10:02.030
Sie delegiert nur weiter, aber sie liefert mir eine definierte und

01:10:02.030 --> 01:10:05.550
engere Schnittstelle als die hier, die hoffentlich alle wichtigen

01:10:05.550 --> 01:10:07.950
Funktionen enthält und nur die, die gebraucht werden.

01:10:08.330 --> 01:10:11.070
Während hier drin natürlich alles Mögliche nach oben geliefert werden

01:10:11.070 --> 01:10:14.730
könnte, was Sie eigentlich als Entwickler hier drin sagen, das sollten

01:10:14.730 --> 01:10:18.050
die Benutzer der Applikationssoftware eigentlich gar nicht benutzen.

01:10:18.450 --> 01:10:20.750
Das können Sie mit einer Fassade verbergen.

01:10:21.930 --> 01:10:24.830
Sie müssen sich also vorstellen, Fassade ist ein Paket, das enthält

01:10:24.830 --> 01:10:30.010
mehrere Klassen und wenn Sie einen Aufruf machen oder eine Instanz

01:10:30.010 --> 01:10:35.690
bilden, dann reicht die Fassade bis einfach durch an die tatsächlich

01:10:35.690 --> 01:10:37.070
benötigten Komponenten.

01:10:42.830 --> 01:10:47.150
Das war also die Fassade, jetzt gehen wir zurück, Entschuldigung,

01:10:50.490 --> 01:10:53.950
bereinigt also oder liefert eine bereinigte oder vereinfachte

01:10:53.950 --> 01:10:54.530
Schnittstelle.

01:10:56.490 --> 01:11:00.530
Ist eine oder mehrere Klassen, die nur zur Verfügung stehen, Elemente

01:11:00.530 --> 01:11:03.610
enthält und an die eigentlichen Elemente in der Schicht delegiert.

01:11:05.830 --> 01:11:08.110
Okay, also eine Verschönerung.

01:11:08.110 --> 01:11:09.590
Soweit so gut, Fragen dazu?

01:11:14.570 --> 01:11:15.530
Okay, nächster.

01:11:16.110 --> 01:11:16.910
Klient-Dienstgeber.

01:11:17.350 --> 01:11:18.710
Klient-Dienstgeber, Client-Server.

01:11:19.410 --> 01:11:23.270
Ganz einfach, Sie haben einen Dienstgeber, der liefert Dienste und Sie

01:11:23.270 --> 01:11:26.310
haben einen Klienten, der ruft diese Dienste auf, aber der Klient ist

01:11:26.310 --> 01:11:27.270
auf einem anderen Rechner.

01:11:28.130 --> 01:11:31.530
Das heißt, in der Regel ist hier diese Anforderung, läuft über ein

01:11:31.530 --> 01:11:35.310
Telekommunikationsnetzwerk, ob das jetzt Funk ist oder Rad, ist egal

01:11:35.310 --> 01:11:38.830
und es gibt in der Regel mehrere Klienten.

01:11:38.830 --> 01:11:42.550
Der Klient-Dienstgeber ist also so, dass Sie einen Dienstgeber haben

01:11:42.550 --> 01:11:46.650
und in der Regel mindestens einen Klienten, also normalerweise eben

01:11:46.650 --> 01:11:47.730
beliebig viele.

01:11:49.170 --> 01:11:54.110
Der Dienstgeber, hier ist man meistens so aufgebaut, dass es einzelne

01:11:54.110 --> 01:11:58.690
Prozesse oder Fäden gibt, die nur darauf warten, eine Anfrage zu

01:11:58.690 --> 01:12:01.930
erhalten und sie auszuführen und das Ergebnis zurückzuspielen an den

01:12:01.930 --> 01:12:02.390
Klienten.

01:12:06.310 --> 01:12:10.550
Das wäre zum Beispiel auch, könnte man auch sehen als eine zweistufige

01:12:10.550 --> 01:12:11.410
Architektur.

01:12:12.630 --> 01:12:15.270
Hier ist die erste Stufe, hier ist die zweite Stufe auf

01:12:15.270 --> 01:12:16.310
unterschiedlichen Maschinen.

01:12:21.860 --> 01:12:24.380
Und natürlich kann der Klient, und deswegen siehst du hier auch noch

01:12:24.380 --> 01:12:28.320
einen Stern, kann der Klient es natürlich auch als nötig empfinden,

01:12:28.620 --> 01:12:30.000
mehrere Dienstgeber anzusprechen.

01:12:31.040 --> 01:12:34.380
Zum Beispiel erstmal ein Dienstgeber, um Adressen zu bekommen und

01:12:34.380 --> 01:12:36.640
einen anderen Dienstgeber, um Bankdetails zu bekommen und einen

01:12:36.640 --> 01:12:41.140
dritten Dienstgeber, um eine Banktransaktion durchzuführen.

01:12:46.560 --> 01:12:50.180
Der Dienstgeber wird also oft benutzt bei Datenbanksystemen auch.

01:12:50.280 --> 01:12:53.580
Das Frontend ist die Benutzeroberfläche für den Benutzer und das

01:12:53.580 --> 01:12:56.140
Backend die Datenbankzugriffe.

01:12:59.360 --> 01:13:02.440
Der Klient führt also vorverarbeitend, nimmt also der Eingaben

01:13:02.440 --> 01:13:07.100
entgegen und gibt die Ausgaben zurück natürlich, verarbeitet unter

01:13:07.100 --> 01:13:12.240
Umständen die Eingaben schon vor, packt sie zusammen und der

01:13:12.240 --> 01:13:14.740
Dienstgeber führt die Datenverwaltung aus, sichert die

01:13:14.740 --> 01:13:19.420
Datenkonsistenz, führt Sicherheitsfunktionen durch.

01:13:23.000 --> 01:13:24.800
In der Regel auf unterschiedlichen Maschinen.

01:13:25.440 --> 01:13:28.260
Es läuft natürlich auch, und das gerade zu Testzwecken, ganz

01:13:28.260 --> 01:13:30.240
praktisch, auch auf einem einzigen Rechner.

01:13:30.360 --> 01:13:32.220
Der Klient und der Dienstgeber auf einem einzelnen Rechner

01:13:32.220 --> 01:13:32.980
funktioniert auch.

01:13:32.980 --> 01:13:35.840
Die kommunizieren dann halt über diese Protokolle, was etwas

01:13:35.840 --> 01:13:38.380
ineffizient ist, aber es würde funktionieren.

01:13:39.660 --> 01:13:42.120
Ein FTP-Dienstgeber ist auch so etwas.

01:13:42.360 --> 01:13:46.220
Ein FTP-Server, zum Beispiel FileZilla, initiiert das Übertragen einer

01:13:46.220 --> 01:13:46.680
Datei.

01:13:47.500 --> 01:13:51.900
Der Dienstgeber reagiert auf die Anfrage des Klienten und empfängt

01:13:51.900 --> 01:13:52.340
bzw.

01:13:52.360 --> 01:13:56.880
sendet die Datei, ob das jetzt eine Bilddatei ist für Instagram oder

01:13:56.880 --> 01:13:58.620
sonst etwas, ist genau so aufgebaut.

01:14:03.180 --> 01:14:03.780
Okay.

01:14:04.720 --> 01:14:06.060
Klient-Dienstgeber, ganz einfach.

01:14:07.940 --> 01:14:10.700
Eng verwandt damit sind die sogenannten Partnernetze.

01:14:11.500 --> 01:14:13.640
Bei Klient-Dienstgeber hatten wir zwei unterschiedliche Rollen,

01:14:13.740 --> 01:14:16.660
nämlich der Anbieter eines Dienstes und der Klient.

01:14:17.500 --> 01:14:21.500
Bei Partnernetzen, oder Englisch peer-to-peer, also Netze unter

01:14:21.500 --> 01:14:25.900
Gleichgestellten, ein Peer ist ein Gleichgestellter, Gleichaltriger.

01:14:27.520 --> 01:14:31.380
In der Schule steht man unter peer-pressure, Druck der Gleichaltrigen.

01:14:34.080 --> 01:14:36.420
Partnernetze sind alle Systeme gleichberechtigt.

01:14:36.680 --> 01:14:39.260
Das heißt, sie sind sowohl Klient als auch Dienstgeber.

01:14:39.920 --> 01:14:42.380
Sie müssen sowohl Dienstgeberfunktionen als auch Klientenfunktionen

01:14:42.380 --> 01:14:42.780
ausführen.

01:14:43.720 --> 01:14:45.560
Das heißt, man könnte auch sagen, der Partner

01:14:49.440 --> 01:14:52.100
brauche ich mehrfach Vererbung aus dem Klient und dem Dienstgeber

01:14:52.100 --> 01:14:52.720
daraus zu machen.

01:14:53.000 --> 01:14:56.700
Wir wissen ja, dass das in Java nicht möglich ist, aus gutem Grunde,

01:14:56.700 --> 01:15:02.120
aber zumindest die Schnittstellen müsste ich an den Partner vererben.

01:15:02.500 --> 01:15:06.100
Wenn ich sie einzeln definiert hätte, ich kann das natürlich als UML

01:15:06.100 --> 01:15:11.400
-Diagramm auch so aufstellen, der Partner, ich hatte hier den

01:15:11.400 --> 01:15:16.180
Anforderer und den Anbieter und dann ist das natürlich hier zu einer

01:15:16.180 --> 01:15:21.460
Schleife verkommen, Anbieter und Anforderer gleichzeitig sein, für

01:15:21.460 --> 01:15:22.400
andere natürlich auch.

01:15:25.080 --> 01:15:28.740
So, der Klientendienstgeber hat also seinen Dienstgeber irgendwo und

01:15:28.740 --> 01:15:32.060
die Klienten greifen zu, der Partnernetze können sich beliebig

01:15:32.060 --> 01:15:35.560
unterhalten und jeder hat sowohl Dienstgeber als auch

01:15:36.280 --> 01:15:41.880
Klientenfunktionalität, was natürlich bedeutet, es gibt keine zentrale

01:15:41.880 --> 01:15:47.800
Kontrolle, die gab es hier, die gibt es natürlich hier nicht mehr, ich

01:15:47.800 --> 01:15:49.920
muss das anderweitig lösen.

01:15:53.860 --> 01:15:56.620
Ich muss das Gesamtverhalten des Systems so bauen, dass es sich selbst

01:15:56.620 --> 01:16:01.680
organisiert, aus der Interaktion zwischen den einzelnen Partnern und

01:16:02.380 --> 01:16:07.380
die einzelnen Partner treffen ihre Entscheidung autonom und verhalten

01:16:07.380 --> 01:16:11.100
sich autonom, sie können sich zum Beispiel abschalten, den Rechner

01:16:11.100 --> 01:16:13.680
ausschalten, zuklappen, nach Hause gehen und es wäre so ein Peer-to

01:16:13.680 --> 01:16:17.140
-Peer -Netzwerk drin, dann fehlt plötzlich ein Knoten, das heißt

01:16:17.140 --> 01:16:21.500
wiederum, dass der einzelnen Partner unzuverlässig sind und ich

01:16:21.500 --> 01:16:25.020
brauche Mechanismen, um diese Unzuverlässigkeit auszugleichen.

01:16:26.340 --> 01:16:30.360
Das mache ich in der Regel so, dass alle Daten, die in dem Partnernetz

01:16:30.360 --> 01:16:34.540
gespeichert sind, jeweils an mehreren Partnern gleichzeitig zur

01:16:34.540 --> 01:16:37.220
Verfügung sind, um die Wahrscheinlichkeit, dass die Daten nicht zur

01:16:37.220 --> 01:16:40.080
Verfügung sind, zu reduzieren.

01:16:42.960 --> 01:16:49.400
Redundanz brauche ich also und natürlich, je größer dieses Netz ist

01:16:49.400 --> 01:16:52.380
und je höher die Redundanz, desto unwahrscheinlicher ist ein Ausfall.

01:16:53.040 --> 01:16:57.140
Aber das bedeutet auch, wenn ich Daten an mehreren Stellen vorhalten

01:16:57.140 --> 01:17:02.300
muss, wenn zum Beispiel der hier neue Daten einspielt, dann muss ich

01:17:02.300 --> 01:17:05.160
sie an mehrere Stellen verteilen, in diesem Netz wahrscheinlich

01:17:05.160 --> 01:17:07.220
zumindest an zwei, wenn nicht sogar an drei.

01:17:09.480 --> 01:17:15.480
Und kennen Sie natürlich auch, BitTorrent ist so ein Netzwerk, da

01:17:15.480 --> 01:17:20.120
können Sie Ihren Rechner als Dienstgeber als auch als Klient anbieten.

01:17:22.200 --> 01:17:28.180
Sie können Dateien anfordern, Sie können Dateien zwischenspeichern und

01:17:28.180 --> 01:17:30.360
Sie können Dateien weiterleiten, weitergeben.

01:17:34.400 --> 01:17:38.060
Auf Netzwerkebene, übrigens auf TCP, IP, gibt es so eine ähnliche

01:17:38.060 --> 01:17:38.620
Situation.

01:17:39.380 --> 01:17:43.140
Da werden die Daten eben anwendungsabhängig auf mehrere Kanäle

01:17:43.350 --> 01:17:43.680
verteilt.

01:17:45.040 --> 01:17:48.660
Domain Name Servers sind auch ein Netzwerk von Partnern eigentlich,

01:17:48.820 --> 01:17:57.000
die Teile der Abbildung von Namen auf IP-Adressen vorhalten, aber

01:17:57.000 --> 01:17:59.780
mehrere dieser Server vorhanden sind, genau, um diese

01:17:59.780 --> 01:18:01.600
Ausfallsicherheit zu bekommen.

01:18:02.100 --> 01:18:05.660
Auch das ist ein DNS-Netzwerk, ist ein Peer-to-Peer-Netz.

01:18:11.690 --> 01:18:17.490
Also, alles relativ klar, denke ich, aber wenn Sie Fragen haben, dann

01:18:17.490 --> 01:18:19.090
stellen Sie mir die Fragen.

01:18:24.850 --> 01:18:25.670
Wir sind gleich soweit.

01:18:26.030 --> 01:18:26.730
Wir haben noch 10 Minuten.

01:18:29.710 --> 01:18:35.030
Die Datenablage, das englische Repository, oder auf Französisch Depot,

01:18:37.990 --> 01:18:41.950
das ist eigentlich, könnte man sagen, ein spezielles Klient

01:18:41.950 --> 01:18:42.730
-Dienstgeber -Modell.

01:18:43.390 --> 01:18:47.470
Da haben Sie eine Datenablage und Subsysteme, die auf das Datenablage

01:18:47.470 --> 01:18:48.090
zugreifen.

01:18:48.650 --> 01:18:50.010
Von den Subsystemen gibt es viele.

01:18:51.330 --> 01:18:54.630
Und diese Subsysteme interagieren über die Datenablage hinweg.

01:18:55.470 --> 01:18:58.770
Beim Klient-Dienstgeber ist es so, dass die Klienten eigentlich völlig

01:18:58.770 --> 01:19:02.850
voneinander unabhängig sind, aber ich kann auch ein solches System

01:19:02.850 --> 01:19:06.330
bauen, wo ich eine Datenbank habe, dort von verschiedenen

01:19:06.970 --> 01:19:14.910
Teilnehmenden -Systemen Daten ablege und damit also auch Kommunikation

01:19:14.910 --> 01:19:17.110
unter den einzelnen Subsystemen erreicht kann.

01:19:23.040 --> 01:19:27.540
Wenn diese Subsysteme auf die Datenablage zugreifen, zum Beispiel mit

01:19:27.540 --> 01:19:32.720
den Fogen erzeuge, setze, hole, suche, dann kann es sein, dass das

01:19:32.720 --> 01:19:35.520
gleichzeitig passiert und dann muss ich diese Gleichzeitigkeit in den

01:19:35.520 --> 01:19:36.100
Griff bekommen.

01:19:36.860 --> 01:19:40.560
Dazu gibt es Mechanismen verschiedener Art, da kann ich zum Beispiel

01:19:40.560 --> 01:19:44.540
Teile der Daten sperren, also ich sage, ich sperre einen Bereich

01:19:44.540 --> 01:19:47.500
meiner Daten, bis sie aktualisiert sind, gebe sie dann wieder zum

01:19:47.500 --> 01:19:52.960
Zugriff frei oder ein wesentlich komplexeren Mechanismus, das ist der

01:19:52.960 --> 01:19:56.960
Transaktionsmechanismus, der sagt, wenn immer ich eine Änderung

01:19:56.960 --> 01:20:01.000
durchführe, in der Datenablage, die mehrere Datenelemente betrifft,

01:20:02.500 --> 01:20:05.780
dann führe ich das in der Transaktion auf und die hat die Eigenschaft,

01:20:05.920 --> 01:20:08.800
dass es von außen so aussieht, dass wenn es mehrere Anfragen

01:20:08.800 --> 01:20:13.080
gleichzeitig gibt, als ob sie hintereinander ausgeführt worden wären,

01:20:14.300 --> 01:20:20.100
wobei der Transaktionsmechanismus eine Optimierung enthält, die sagt,

01:20:20.460 --> 01:20:24.680
wenn sich aber zwei Transaktionen nicht ins Gehege kommen, das heißt,

01:20:24.800 --> 01:20:28.480
unterschiedliche Daten bearbeiten, dann kann ich sie ja auch

01:20:28.480 --> 01:20:32.340
gleichzeitig laufen lassen und ein Transaktionsmechanismus würde

01:20:32.340 --> 01:20:36.220
gerade das feststellen, er würde zum Beispiel zunächst mal annehmen,

01:20:36.340 --> 01:20:39.960
dass alles gleichzeitig laufen darf, aber während es dann feststellt,

01:20:40.240 --> 01:20:43.780
dass es Überlappungen der zugegriffenen Daten gibt und dann eine der

01:20:43.780 --> 01:20:48.060
beiden Transaktionen, die zu der Überlappung geführt haben, anhält,

01:20:48.260 --> 01:20:51.680
zurücksetzt und nachher noch einmal startet.

01:20:55.180 --> 01:20:57.880
Aber Transaktionen werden wir hier nicht näher besprechen.

01:20:58.360 --> 01:21:02.300
Über Transaktionen werden Sie zum einen in Datenbankvorlesungen

01:21:03.160 --> 01:21:06.180
ausführlichst informiert, wie man Transaktionen verwirklicht.

01:21:07.560 --> 01:21:13.380
Es gibt auch sogenanntes Software Transactional Memory, also einen

01:21:13.380 --> 01:21:14.600
transaktionalen Hauptspeicher.

01:21:15.160 --> 01:21:16.980
Das ist eine relativ neue Erfindung.

01:21:19.160 --> 01:21:22.100
Da behandeln Sie den Hauptspeicher eines Rechners nicht ins

01:21:22.100 --> 01:21:25.220
Plattenlaufwerk, sondern den Hauptspeicher eines Rechners wie ein

01:21:25.220 --> 01:21:27.260
System, in dem Sie Transaktionen durchführen müssen.

01:21:30.060 --> 01:21:33.880
Und davon können Sie in einer Vorlesung bei uns hören, nämlich in der

01:21:33.880 --> 01:21:40.020
Vorlesung über Multicore Rechner und Rechnerbündel, da werden Software

01:21:40.020 --> 01:21:43.460
Transaktionen, Software Transaktionaler Speicher behandelt.

01:21:44.860 --> 01:21:47.920
Zunächst einmal merken Sie sich jetzt für diese Vorlesung, dass Sie

01:21:47.920 --> 01:21:50.720
der Datenablage natürlich dafür sorgen müssen, dass es keine

01:21:50.720 --> 01:21:54.240
inkonsistenten Zustände gibt, wenn ich mehrere Subsysteme habe, die

01:21:54.240 --> 01:21:56.120
die Datenablage gleichzeitig bearbeiten.

01:21:59.560 --> 01:22:01.480
Das war die Datenablage.

01:22:04.100 --> 01:22:04.760
Beispiel.

01:22:06.400 --> 01:22:11.560
Ein ganz anderes Beispiel, das sogar ohne Fernzugriff auskommt, und

01:22:11.560 --> 01:22:13.980
das wäre das Beispiel eines Übersetzers.

01:22:15.280 --> 01:22:18.960
Also ein Java-Übersetzer oder C++-Übersetzer.

01:22:20.700 --> 01:22:24.080
Da haben Sie in der Regel für den Übersetzer eine ganz wichtige Ablage

01:22:24.080 --> 01:22:27.560
oder auch zentrale Datenstruktur, könnte man sagen, und das ist der

01:22:27.560 --> 01:22:28.880
sogenannte Symboltabelle.

01:22:29.660 --> 01:22:32.900
Die Symboltabelle wird festgehalten für jeden Bezeichner, was der

01:22:32.900 --> 01:22:33.860
Bezeichner bedeutet.

01:22:34.980 --> 01:22:38.940
Da haben Sie, ist es ein Klassenname, ist es eine Variablenname, ist

01:22:38.940 --> 01:22:42.980
es ein Objektname, was ist es?

01:22:43.360 --> 01:22:45.180
Das wird in der Symboltabelle festgehalten.

01:22:45.900 --> 01:22:48.760
Sie wissen ja auch, es gibt für verschiedene Bezeichnungen, wenn Sie

01:22:48.760 --> 01:22:50.760
einen Bezeichner nehmen, der kann überladen sein.

01:22:51.260 --> 01:22:53.840
Das heißt, die Symboltabelle muss auch mit dem Überladen fertig

01:22:53.840 --> 01:22:58.560
werden, dass für einen Bezeichner mehrere Bedeutungen gibt, mehrere

01:22:58.560 --> 01:22:59.300
Zuordnungen.

01:22:59.300 --> 01:23:01.240
Das macht also die Symboltabelle.

01:23:02.920 --> 01:23:05.260
Dann gibt es den sogenannten Strukturbaum.

01:23:05.380 --> 01:23:09.020
Der Strukturbaum ist ein Baum, das Gesamtstruktur eines Programmes.

01:23:09.500 --> 01:23:15.000
Man würde also sagen, Klasse, Name der Klasse, dann welche Methoden

01:23:15.000 --> 01:23:16.600
gibt es in der Klasse für jede Methode.

01:23:17.420 --> 01:23:21.080
Beweise auf die Symboltabelle, da steht der Name drin, dann eine

01:23:21.080 --> 01:23:24.640
Struktur, die mir angibt, wie viele Parameter die Methode hat, den

01:23:24.640 --> 01:23:29.420
Rückgabetyp, dann eine Anweisung nach der anderen.

01:23:29.940 --> 01:23:31.400
Das steht im Strukturbaum.

01:23:32.040 --> 01:23:35.000
Das schreiben Sie normalerweise als Text hin, um es im Rechner zu

01:23:35.000 --> 01:23:35.560
beschleunigen.

01:23:35.680 --> 01:23:40.540
Bei der Übersetzung wird eben eine konzentrierte, vernetzte Struktur

01:23:40.540 --> 01:23:41.140
aufgebaut.

01:23:42.440 --> 01:23:45.800
Aber auch das ist auch in dieser Ablage, die der Übersetzer braucht.

01:23:46.880 --> 01:23:50.200
Und da gibt es mehrere Komponenten, die diese Ablage zum Teil

01:23:50.200 --> 01:23:51.660
aufbauen, zum Teil benutzen.

01:23:52.260 --> 01:23:57.320
Also zum Beispiel die Syntaxanalyse und die lexikalische Analyse, die

01:23:57.320 --> 01:23:59.740
bauen den Strukturbaum und die Symboltabelle auf.

01:24:00.660 --> 01:24:02.660
Die entziffern gewissermaßen ihr Programm.

01:24:03.380 --> 01:24:06.740
Von der Syntaxanalyse bekommen sie zum Beispiel ihre Syntaxfehler.

01:24:07.480 --> 01:24:11.040
Das kommt hier aus der Syntaxanalyse und die baut den Strukturbaum und

01:24:11.040 --> 01:24:11.720
die Symboltabelle.

01:24:12.900 --> 01:24:16.220
Die Semantikanalyse benutzt auch den Strukturbaum, die sagt nämlich,

01:24:17.240 --> 01:24:19.040
ist die Zuweisung richtig?

01:24:19.880 --> 01:24:22.520
Ist es okay, ein Big Integer auf ein Integer zuzuweisen?

01:24:23.540 --> 01:24:26.780
Und wird Ihnen dann einen semantischen Fehler melden, wenn es nicht

01:24:26.780 --> 01:24:27.360
richtig ist.

01:24:28.360 --> 01:24:31.460
Dann gibt es den Optimierer und den Coderzeuger.

01:24:31.540 --> 01:24:34.780
Der Coderzeuger ist klar, der nimmt den Strukturbaum her und erzeugt

01:24:34.780 --> 01:24:35.220
Befehle.

01:24:36.040 --> 01:24:36.920
JVM Befehle.

01:24:37.800 --> 01:24:41.720
Und der Optimierer wandelt sie um, sodass sie mit weniger Befehlen

01:24:41.720 --> 01:24:43.040
oder schnelleren Befehlen auskommen.

01:24:45.940 --> 01:24:47.240
Die wandeln also um.

01:24:47.540 --> 01:24:52.840
Der hier analysiert, die beiden bauen auf, die hier wandeln um und es

01:24:52.840 --> 01:24:55.200
gibt noch weitere Programme, die Sie damit benutzen werden, wenn Sie

01:24:55.200 --> 01:24:57.420
einen Debugger aufrufen, um Fehler zu finden.

01:24:58.160 --> 01:24:59.840
Da braucht der natürlich die Symboltabelle.

01:25:00.160 --> 01:25:03.280
Wenn Sie sagen, zeigen wir den Wert der Variable X, dann muss der in

01:25:03.280 --> 01:25:06.760
der Symboltabelle nachschauen und sagen, keine Ahnung, welches X er

01:25:06.760 --> 01:25:07.660
gemeint haben könnte.

01:25:08.100 --> 01:25:11.120
Aber die Symboltabelle weiß das und dann kann er mit entsprechender

01:25:11.120 --> 01:25:14.540
Information aus der Symboltabelle diese Variable auffinden.

01:25:14.840 --> 01:25:16.340
Das könnte also der Source-Debugger machen.

01:25:16.340 --> 01:25:23.720
Und ein Struktureditor ist einer, der ähnlich wie in Eclipse bereits

01:25:23.720 --> 01:25:27.460
die Syntax der Sprache kennt, anstelle nur eine reine Zeicheneditor

01:25:27.460 --> 01:25:30.980
-Satz, eine Folge von Zeichen zu sehen.

01:25:31.400 --> 01:25:35.580
Der Struktureditor arbeitet natürlich auch auf einem Strukturbaum und

01:25:35.580 --> 01:25:36.460
an der Symboltabelle.

01:25:37.720 --> 01:25:41.700
Das wäre also auch ein Beispiel für eine Datenablage, nämlich hier der

01:25:41.700 --> 01:25:44.900
Strukturbaum und die Symboltabelle in einem Übersetzer beziehungsweise

01:25:45.980 --> 01:25:47.420
Debugger oder Struktureditor.

01:25:50.000 --> 01:25:51.420
Ganz interessant, finde ich.

01:25:55.460 --> 01:25:56.460
Wir sind gleich so weit.

01:25:57.320 --> 01:25:58.180
Model-View-Controller.

01:26:00.260 --> 01:26:01.980
Das ist jetzt etwas komplizierter.

01:26:03.840 --> 01:26:05.180
Nochmal kurz tief Luft holen.

01:26:05.440 --> 01:26:09.400
Model-View-Controller, das sind die drei Komponenten, die in dieser

01:26:09.400 --> 01:26:12.100
Architektur, in diesem Architekturstil verwandt werden.

01:26:12.600 --> 01:26:17.900
Und zwar der einfachste Teil des Model-View-Controllers ist die View

01:26:17.900 --> 01:26:18.660
oder die Sicht.

01:26:19.400 --> 01:26:21.280
Die gibt Ihnen eine Datenstruktur wieder.

01:26:23.040 --> 01:26:26.200
Dann gibt es das Model oder das Modell oder die zentrale

01:26:26.200 --> 01:26:28.820
Datenstruktur, die ist ähnlich wie bei der Drei-Schichten-Architektur,

01:26:29.040 --> 01:26:31.760
wo die Daten sitzen und die Kernfunktionalität.

01:26:32.680 --> 01:26:33.620
Das nennen Sie Model.

01:26:34.380 --> 01:26:38.760
Und Sie brauchen jetzt, Sie haben jetzt die Situation, wie wir vorhin

01:26:38.760 --> 01:26:43.780
auch hatten, dass diese Datenstruktur sich ändern kann und damit unter

01:26:43.780 --> 01:26:46.260
Umständen sich die Sicht anpassen muss.

01:26:47.260 --> 01:26:54.820
Stellen Sie sich vor, in dem Model sind irgendwie Daten, die Sie

01:26:54.820 --> 01:26:59.680
anzeigen wollen als Balkendiagramm mit 25 Balken.

01:27:00.260 --> 01:27:03.240
Die entsprechenden Prozentsätze, gerade für die Wahl zum Beispiel,

01:27:03.340 --> 01:27:08.420
haben Sie einen Viewer, der gibt Ihnen an, wieviel die SPD, die CDU

01:27:08.420 --> 01:27:10.680
und die FDP an Prozent hatten.

01:27:11.020 --> 01:27:12.880
Das zeigen Sie an als Balkendiagramm.

01:27:13.220 --> 01:27:16.060
Aber das Modell selbst, innen drin, enthält natürlich nur die Zahl.

01:27:18.060 --> 01:27:19.380
Das wäre der Viewer.

01:27:19.620 --> 01:27:23.380
Und dann gibt es den Controller und der Controller steuert die

01:27:23.380 --> 01:27:24.700
Interaktion.

01:27:25.240 --> 01:27:31.240
Der sagt, ob Sie die Farben ändern können, zum Beispiel, oder die

01:27:31.240 --> 01:27:35.040
Zuordnung irgendwelcher Bezeichner zu den Balken, oder ob Sie oben

01:27:35.040 --> 01:27:37.020
drüber die Prozentzahl anzeigen wollen oder nicht.

01:27:37.900 --> 01:27:40.340
Das ist der Controller, der steuert die Interaktion.

01:27:44.520 --> 01:27:49.240
Wenn Sie denken, Sie müssen so, wie für die Europawahl oder so etwas,

01:27:49.300 --> 01:27:53.040
Sie müssen so eine Komponente jetzt bauen, dann würde man als erstes

01:27:53.040 --> 01:27:56.040
einfach so eine große Komponente und all dieses Zeug reinstopfen.

01:27:58.860 --> 01:28:02.880
Aber Sie überlegen sich dann, mit diesem Balkendiagramm, das war

01:28:02.880 --> 01:28:06.300
ziemlich viel Arbeit, würde ich gerne woanders in der nächsten Wahl

01:28:06.300 --> 01:28:10.820
auch wieder benutzen können, oder einem ganz anderen Beispiel, dann

01:28:10.820 --> 01:28:12.300
würden Sie die Dinge gerne trennen.

01:28:13.960 --> 01:28:18.480
Dass Sie nämlich den Gesicht oder die View separat haben vom Modell.

01:28:22.440 --> 01:28:24.340
Deswegen auch Model, View, Controller.

01:28:24.780 --> 01:28:25.740
Das haben wir jetzt besprochen.

01:28:27.720 --> 01:28:31.820
Das Diagramm selbst, das sind meistens Pakete, das soll ein Paketbild

01:28:31.820 --> 01:28:36.780
sein, gibt es den Controller, den View, das Model hat einen Controller

01:28:36.780 --> 01:28:39.140
hoffentlich, der Controller hat ein Model, das ist klar.

01:28:40.500 --> 01:28:45.100
Das Modell ist zum einen ein Melder und hat einen Opponenten, das ist

01:28:45.100 --> 01:28:45.480
die View.

01:28:46.180 --> 01:28:49.800
Und da lassen wir zu, dass es mehrere dieser Views oder Sichten oder

01:28:49.800 --> 01:28:53.200
Anzeigen gibt, deswegen hier ein Stern für den Controller, genauso

01:28:53.200 --> 01:28:56.520
hier ein Stern, aber die View wird nur von einem Controller gesteuert.

01:29:00.100 --> 01:29:02.560
Wir haben also diese drei Komponenten, das ist übrigens ein sehr

01:29:02.560 --> 01:29:06.420
berühmtes, bekanntes Modell, wer von Ihnen hat MVC schon mal gehört

01:29:06.420 --> 01:29:06.880
vielleicht?

01:29:08.080 --> 01:29:12.300
Sehr gut, sehen Sie, das ist bekannt, ausgezeichnet.

01:29:15.880 --> 01:29:20.680
Wir müssen jetzt noch ein paar Kleinigkeiten klären, nämlich die

01:29:20.680 --> 01:29:23.660
bekanntgearbeitete Änderung im Datenmodell, das geht über eine

01:29:23.660 --> 01:29:26.940
bestimmte Redaktion, das heißt die Beobachter, Entwurfsmuster

01:29:26.940 --> 01:29:28.500
Beobachter, bin gleich fertig.

01:29:29.640 --> 01:29:32.460
Den betrachten wir uns noch genauer später.

01:29:36.300 --> 01:29:41.300
In der Regel werden Präsentation und Schaltflächen, also die Sicht und

01:29:41.300 --> 01:29:43.560
der Controller in einer Oberfläche zusammengefasst.

01:29:44.980 --> 01:29:48.400
Daher kann man sie oft grafisch nicht sehr genau unterscheiden.

01:29:48.940 --> 01:29:51.600
Es kann aber auch eine zusätzliche Interaktion geben zwischen der

01:29:51.600 --> 01:29:53.060
Steuerung und der Präsentation.

01:29:55.000 --> 01:29:58.380
Ich kann also mit dem MVC das Modell wiederverwenden in einem anderen

01:29:58.380 --> 01:30:00.320
Kontext, ohne die Benutzerschnittstelle.

01:30:00.760 --> 01:30:03.900
Ich kann die Benutzerschnittstelle, die grafische Anzeige

01:30:03.900 --> 01:30:06.880
wiederverwenden, in einem anderen Kontext, ohne das gleiche Modell.

01:30:08.480 --> 01:30:08.680
Genau.

01:30:10.580 --> 01:30:11.320
Und da hören wir auf.

01:30:12.160 --> 01:30:12.660
Dankeschön.

