WEBVTT

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

00:09.870 --> 00:10.830
ausdruckt.

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

00:21.120 --> 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.340 --> 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.640 --> 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.720 --> 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.610 --> 01:39.710
Auch nicht.

01:40.330 --> 01:41.170
5.000?

01:42.750 --> 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.060 --> 02:04.360
Genau richtig.

02:05.220 --> 02:09.280
Big Integer ist ein sogenanntes Immutable oder unveränderbares,

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

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

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

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

02:26.080 --> 02:26.300
Genau.

02:27.020 --> 02:27.820
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:38.300
eine Summe zuweisen und das alte wird dann der Speicherbereinigung

02:38.300 --> 02:40.600
übergeben, dass es dann irgendwann mal abbrennt.

02:40.600 --> 02:41.120
Genau.

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

02:43.540 --> 02:46.260
Haben Sie offenbar schon mal benutzt oder haben Sie es schon gesehen?

02:50.940 --> 02:51.500
Ausgezeichnet.

02:51.900 --> 02:53.920
So, dann gehen wir...

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

03:06.650 --> 03:09.130
Das Nächste ist dann die Entwurfsphase.

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

03:12.730 --> 03:14.590
Ich gehe mal schon auf Folie 64.

03:16.850 --> 03:20.910
So, also erst mal...

03:20.910 --> 03:22.690
Mal das ausprobieren.

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

03:29.570 --> 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:56.690 --> 04:01.110
Der Vorteil ist, solange die Signatur, also die Schnittstelle des

04:01.110 --> 04:06.410
Moduls gleich bleibt, kann ich dieses Modul ersetzen durch ein neues,

04:06.570 --> 04:10.730
neue 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:19.590 --> 04:23.810
Die eleganteste Technik dafür sind immer diese Zugriffsfunktionen,

04:23.890 --> 04:27.950
deswegen die Set- und Get-Funktionen unter anderem, aber es gibt auch

04:27.950 --> 04:31.430
andere Geheimnisse, die ich haben könnte, außer Datenstrukturen und

04:31.430 --> 04:31.970
Algorithmen.

04:31.970 --> 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.510 --> 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.730
gestellt.

04:50.110 --> 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.870
unterschiedlich implementiert sind.

05:00.870 --> 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.430 --> 05:15.390
Und jetzt sagte ich Ihnen ja, oder der Herr Landhäuser sagte Ihnen

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

05:24.350 --> 05:28.230
Objektorientierung anwendbar ist, angewendet werden muss.

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

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

05:40.070 --> 05:40.410
Vorläufer.

05:40.530 --> 05:41.170
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.310 --> 05:49.910
Denken Sie an das Objektpunkt.

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

05:52.370 --> 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.290 --> 06:02.590
Das ist ein schwerer Nachteil des Moduls, des Modulkonzeptes.

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

06:06.810 --> 06:07.490
Implementierung.

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

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

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

06:23.200 --> 06:27.000
neuen Punkt anlegt und vielleicht Existierende löscht.

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

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

06:34.460 --> 06:38.020
mit Initialisierungsparametern, geht das beim Modul nicht.

06:38.320 --> 06:40.540
Aber es ist natürlich auch programmierbar.

06:43.560 --> 06:47.060
Und bei den objektorientierten Sprachen kann ich hergehen und sagen,

06:47.060 --> 06:52.720
ich trenne Klasse von Objekt, erkläre nur die Klasse und instanziere

06:52.720 --> 06:54.140
die Klasse mehrfach.

06:56.280 --> 06:59.680
Oder auch, ich kann auch die Schnittstelle, wenn ich nur eine

06:59.680 --> 07:03.080
Schnittstelle angegeben habe, mehrfach instanzieren, auch das geht,

07:03.600 --> 07:06.720
mehrfach implementieren sogar, auch das geht im Modul nicht.

07:11.260 --> 07:14.660
Also eine Schnittstelle kann durch eine oder mehrere Klassen

07:14.660 --> 07:17.740
implementiert werden und von diesen Klassen können mehrere Objekte

07:17.740 --> 07:18.440
erzeugt werden.

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

07:26.340 --> 07:30.060
Sie in einer objektorientierten Sprache sind und garantieren wollen,

07:30.160 --> 07:36.480
dass es nur eine einzelne Instanz gibt, dann gibt es ein spezielles

07:36.480 --> 07:40.860
Entwurfsmuster dafür, das heißt das Einzelstück oder Singleton, mit

07:40.860 --> 07:43.540
denen können Sie das auch erreichen, dass es nie möglich sein wird,

07:43.600 --> 07:46.680
von einer Klasse mehr als ein einziges Objekt anzulegen.

07:47.240 --> 07:50.960
Das geht ziemlich einfach, indem man sich merkt, in einer Variablen,

07:51.120 --> 07:54.760
ob es ein solches Element schon gibt und wenn nicht, dann gebe ich

07:54.760 --> 07:59.700
einfach das einzelne Objekt im Konstruktor wieder zurück.

08:00.240 --> 08:01.360
Dann gibt es immer nur eines.

08:01.740 --> 08:03.220
Werden wir sehen, wie man das genau programmiert.

08:05.420 --> 08:11.760
Das andere, was ich natürlich bei O-Sprachen habe, ist, dass wenn ich

08:11.760 --> 08:16.140
eine Schnittstelle vorgegeben habe und sie mehrfach implementiere, in

08:16.140 --> 08:21.400
zwei, drei Klassen, dann benutzen diese Implementierungen die gleichen

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

08:25.340 --> 08:27.400
Im Modul kann ich das auch nicht erreichen.

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

08:31.920 --> 08:35.540
aber eine unterschiedliche Implementierung ist, zum Beispiel, wir

08:35.540 --> 08:39.840
hatten das Hohlzeichen-Funktion und die Verschieber-Hohlezeichen

08:39.840 --> 08:40.380
-Funktion.

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

08:45.140 --> 08:50.940
ausdenken für die Hohlezeichen-Funktion, die dann angibt, aus welcher

08:50.940 --> 08:52.480
Instanzierung es jetzt stammt.

08:52.940 --> 08:57.300
Auch das kann ich in der objektorientierten Programmiersprache elegant

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

09:02.380 --> 09:06.260
Klasse oder des Objektes voranstellen und schon ist die Geschichte

09:06.260 --> 09:06.760
fertig.

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

09:13.020 --> 09:15.720
in einer Programmiersprache wie C, auf diese Art und Weise

09:15.720 --> 09:17.040
modellieren.

09:17.240 --> 09:20.220
In objektorientierten Sprachen hätten sie stattdessen VS oder

09:20.220 --> 09:21.980
Verschieber -Punkt-Hohlezeichen.

09:24.460 --> 09:34.440
Okay, dann kommt noch ein wichtiger Punkt, die sogenannte Benutzt

09:34.440 --> 09:35.060
-Relation.

09:35.940 --> 09:39.900
Die Benutzt-Relation ist sehr wichtig, dass sie in einer bestimmten

09:39.900 --> 09:43.100
Struktur aufgebaut ist, nämlich hierarchisch, sodass ich ein

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

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

09:51.200 --> 09:52.320
erste Mal testen kann.

09:52.820 --> 09:58.160
Dazu ist es erforderlich, dass diese Benutzt-Relation hierarchisch

09:58.160 --> 09:58.360
ist.

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

10:02.760 --> 10:04.780
Ich habe einige davon aufgezählt hier.

10:06.360 --> 10:11.660
Delegiert an ist die Relation, die sagt, wenn ein Aufruf ankommt an

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

10:16.280 --> 10:18.120
gleichen Parametern an ein anderes.

10:18.640 --> 10:21.160
Das ist Delegiert an-Relation.

10:22.480 --> 10:26.700
Ist ein, das ist die Relation der Klassen-Hierarchie.

10:27.160 --> 10:28.160
Das kennen sie schon.

10:28.520 --> 10:31.620
Hat eins, das ist die Aggregations-Relation.

10:32.040 --> 10:33.500
Enthält hat ein.

10:34.200 --> 10:36.400
Enthält ein ist das gleiche.

10:36.940 --> 10:40.580
Greift zu auf, das ist die Zugriffs-Relation.

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

10:46.280 --> 10:49.740
Ist privilegiert zu, das ist eine Privilegierungs-Relation, die sagt,

10:50.200 --> 10:53.920
darf auf etwas zugreifen, darf eine bestimmte Funktion sehen,

10:54.060 --> 10:58.180
benutzen, eine bestimmte Klasse oder Objekt sehen und benutzen.

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

11:03.780 --> 11:09.600
der Wichtigkeit der Sicherheit könnte sich das demnächst ändern.

11:09.600 --> 11:13.640
Dass es geschicktere Programmiersprachen gibt, die einen besseren

11:13.640 --> 11:14.280
Schutz bieten.

11:14.900 --> 11:17.620
Dann natürlich die Relation ruft auf.

11:18.340 --> 11:21.280
Eine Methode X ruft eine Methode Y auf.

11:23.280 --> 11:28.120
Die Inverse ist dann aufgerufen von, benutzt, das ist die, die wir

11:28.120 --> 11:31.160
jetzt definieren wollen, und stellt Betriebsmittel bereit.

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

11:36.220 --> 11:38.780
auf eine Fernzugriffsschnelle bereitstellt.

11:40.120 --> 11:42.540
So, all diese Relationen gibt es.

11:42.780 --> 11:46.980
Wir interessieren uns im Entwurf besonders für die Benutz-Relation

11:46.980 --> 11:48.480
oder Uses-Relation.

11:49.740 --> 11:51.000
Die definieren wir jetzt.

11:51.100 --> 11:54.680
Wir sagen, eine Programmkomponente A, was immer das ist, Klasse,

11:54.820 --> 12:01.180
Methode, Typ, Variable, benutzt Programmkomponente B, genau dann, wenn

12:01.180 --> 12:06.180
A für den korrekten Ablauf die Verfügbarkeit einer korrekten

12:06.180 --> 12:07.760
Implementierung von B erfordert.

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

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

12:20.540 --> 12:25.860
die Verfügbarkeit ist ein allgemeineres Konzept.

12:25.860 --> 12:27.240
Beispiele dafür.

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

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

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

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

12:55.460 --> 12:59.200
aufgerufene Komponente tatsächlich richtig funktioniert.

12:59.660 --> 13:03.020
Das klingt jetzt ein bisschen komisch, aber hier ist ein Beispiel.

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

13:12.220 --> 13:16.280
passiert, ist, dass das Betriebssystem Ihr Programm aufruft, mit einem

13:16.280 --> 13:17.360
Aufruf an Main.

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

13:24.520 --> 13:25.400
implementiert ist?

13:26.580 --> 13:27.320
Nein, es ist nicht.

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

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

13:33.900 --> 13:38.860
Das Betriebssystem ist bewusst so geschrieben, dass es fehlerhafte

13:38.860 --> 13:39.840
Programme überlebt.

13:40.820 --> 13:44.860
Und es braucht auch gar nichts von diesen fehlerhaften Programmen oder

13:44.860 --> 13:46.560
auch von den richtigen Anwendungsprogrammen.

13:47.180 --> 13:49.040
Es ist nur da, um es aufzurufen.

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

13:54.120 --> 13:55.460
tatsächlich erfordert.

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

14:01.240 --> 14:04.620
erfolgt, aber eine korrekte Implementierung des Aufrufs gar nicht mal

14:04.620 --> 14:05.580
erforderlich ist.

14:10.900 --> 14:13.300
A legt eine Instanz eines Typs von B an.

14:13.420 --> 14:15.240
Auch das ist eine Benutzrelation.

14:15.980 --> 14:19.180
Ich habe meine Klasse und lege eine Instanz davon an.

14:19.860 --> 14:21.900
Dann benutzt A natürlich diese Klasse B.

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

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

14:32.880 --> 14:34.780
Elementes, das wir benutzen.

14:34.840 --> 14:37.300
Zum Beispiel die Methode, die wir aufrufen wollen, die Klasse, die wir

14:37.300 --> 14:41.260
instanzieren wollen, die Instanzvariablen vom Namen her, die Konstante

14:41.260 --> 14:42.480
vom Namen her.

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

14:47.320 --> 14:47.820
aufrufen.

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

14:56.120 --> 14:58.660
Zum Beispiel gibt es in einem Betriebssystem

14:58.660 --> 15:03.120
Unterbrechungsbehandlungsroutinen, die bei bestimmten Ereignissen

15:03.120 --> 15:08.160
automatisch ausgeführt werden, die natürlich ihr Programm ausgelöst

15:08.160 --> 15:11.220
hat, aber nie per Namen aufgerufen hat.

15:12.100 --> 15:16.460
Zum Beispiel, angenommen, Sie lesen von einer Datei.

15:16.880 --> 15:20.100
Da gibt es eine Funktion, die liest einen ganzen Block einer Datei

15:20.100 --> 15:20.340
ein.

15:20.340 --> 15:22.640
Sagen wir 4 KB auf einmal.

15:23.780 --> 15:28.240
Die Datei müssen Sie dazu vorher aufgeöffnet haben zum Lesen und Sie

15:28.240 --> 15:30.660
rufen jetzt die Funktion read auf.

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

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

15:44.160 --> 15:48.660
Nachdem die Rotationsgeschwindigkeit einer Platte, von der Sie lesen,

15:49.400 --> 15:52.840
verglichen mit der Geschwindigkeit Ihres Rechners, sehr, sehr langsam

15:52.840 --> 15:55.280
ist, im Bereich von Millisekunden.

15:56.200 --> 15:59.440
Was jetzt passiert ist, dass Ihr Programm eigentlich angehalten wird

15:59.440 --> 16:02.800
und der Rechner sich die Gelegenheit nimmt und sagt, bis die

16:02.800 --> 16:06.940
Plattenrotation so weit ist, dass die Beiz da ist und ich sie ablesen

16:06.940 --> 16:09.460
kann, kann ich auch ein anderes Programm laufen lassen.

16:10.780 --> 16:13.000
Dadurch entsteht dieses Multiprogramming.

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

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

16:31.340 --> 16:32.240
Inneren des Rechners.

16:32.420 --> 16:36.140
Tatsächlich gibt es einen Unterbrechungsvektor und der verursacht,

16:36.320 --> 16:42.460
dass bei der nächsten Instruktionsausführung automatisch die

16:42.460 --> 16:45.800
Unterbrechungsbehandlungsroutine ausgeführt wird, die sagt, aha, die

16:45.800 --> 16:46.740
Daten sind ja da.

16:47.260 --> 16:51.120
Jetzt kann ich sie in den Benutzerbereich kopieren und das gestoppte

16:51.120 --> 16:54.520
Programm wieder weiterrechnen lassen.

16:55.780 --> 16:58.140
Diese Unterbrechungsbehandlungsroutine, auf die es mir ankommt, hat

16:58.140 --> 16:59.920
Ihr Programm aber nie aufgerufen.

17:00.380 --> 17:03.800
Auch nicht das Programm, das bis in das Betriebssystem hinein ging und

17:03.800 --> 17:05.440
Read aufgerufen hat.

17:05.440 --> 17:09.740
Die Unterbrechungsbehandlungsroutine wird über den Umweg der

17:09.740 --> 17:14.000
Unterbrechung, des Unterbrechungsmechanismus angesteuert.

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

17:19.640 --> 17:24.180
Komponente B, wenn sie zunächst mal, nennt man mal an, den Namen

17:24.180 --> 17:28.580
dieses Elements kennen, sodass es benutzt werden kann, aber es gibt

17:28.580 --> 17:32.700
auch eine Ausnahme, nämlich Unterbrechungsroutinen, die automatisch

17:32.700 --> 17:36.740
angesteuert werden über den Unterbrechungsmechanismus.

17:37.420 --> 17:39.660
Auch dann spricht man von einer Benutzung.

17:39.880 --> 17:45.300
Denn die Lesefunktion könnte nicht korrekt funktionieren, wenn es

17:45.300 --> 17:50.560
keine korrekt implementierte Unterbrechungsmethode oder Funktion im

17:50.560 --> 17:53.460
Betriebssystem gäbe, die indirekt aufgerufen wird.

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

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

18:09.600 --> 18:12.800
Es gibt erstens mehr und zweitens ist nicht jeder Aufruf eine

18:12.800 --> 18:13.320
Benutzung.

18:20.590 --> 18:24.090
Die Benutztrelation, Sie wissen ja, das ist jetzt eine Relation, die

18:24.090 --> 18:28.170
können wir jetzt so gestalten, dass sie eine totale Ordnung ist.

18:28.170 --> 18:31.950
Das A benutzt B, B benutzt C, C benutzt D und so fort.

18:32.530 --> 18:34.050
Es kann auch eine Halbordnung sein.

18:34.150 --> 18:37.990
Das heißt, es kann sein, dass es Verzweigungen in dieser

18:37.990 --> 18:39.470
Benutzrelation gibt.

18:39.910 --> 18:42.070
Es kann auch sein, dass sie zyklisch ist.

18:42.210 --> 18:45.470
Nur die zyklische Benutzrelation wollen wir nach Möglichkeit

18:45.470 --> 18:46.010
vermeiden.

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

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

18:59.890 --> 19:02.370
Betriebssystem auf diese Art und Weise aufgebaut wurde.

19:03.010 --> 19:06.150
Dann das Maltics Betriebssystem hat auch eine hierarchische

19:06.150 --> 19:07.030
Benutzrelation.

19:07.430 --> 19:08.250
Was ist Maltics?

19:08.610 --> 19:10.590
Maltics ist ein Vorläufer von Unix.

19:11.370 --> 19:15.110
Unix ist so eine abgeschwächte Kopie von Maltics, könnte man sagen.

19:15.230 --> 19:17.190
Und Linux ist eine Kopie von Unix.

19:17.770 --> 19:21.250
Also Maltics, Unix, Linux sind sehr eng verwandt.

19:22.190 --> 19:27.490
Die ISO-OSI-Protokollsuiten, das sind die Protokollsuiten, die sie

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

19:31.990 --> 19:36.410
Auch die sind übrigens in Schichten, also in einer Totalordnung

19:36.410 --> 19:37.070
aufgebaut.

19:38.130 --> 19:42.230
Benutzt die oberste Schicht die darunter liegende Schicht, die

19:42.230 --> 19:44.410
wiederum benutzt eine tiefer liegende Schicht.

19:45.230 --> 19:47.310
DCP-IP-Protokollsuiten genauso.

19:47.310 --> 19:52.610
Drei-Schichten-Architektur ist sehr bekannt, die wird immer gerne

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

19:58.070 --> 20:02.190
Schicht für die Datenhaltung, typischerweise ein Datenbanksystem,

20:03.050 --> 20:07.550
einem Applikationskern, der die Grundfunktionen zur Verfügung stellt

20:07.550 --> 20:12.130
und einer Benutzungsschnittstelle, die das Ansteuern der

20:12.130 --> 20:17.410
Kernfunktionen, des Applikationskerns über Menüs und Knöpfe und so

20:17.410 --> 20:18.490
weiter ermöglicht.

20:20.410 --> 20:24.150
Die Benutzungsschnittstelle benutzt natürlich den Applikationskern und

20:24.150 --> 20:27.710
der Applikationskern holt sich seine Daten aus der Datenhaltung, er

20:27.710 --> 20:31.370
fordert also eine korrekte Implementierung der Datenhaltung.

20:38.200 --> 20:40.220
Fragen Sie Ihren Nachbarn, er soll etwas leiser reden.

20:43.860 --> 20:44.520
Danke.

20:50.220 --> 20:53.760
Wenn wir also jetzt ein System entwerfen, wollen wir eine

20:53.760 --> 20:57.640
Benutzrelation gestalten, unter welchen Gesichtspunkten.

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

21:01.660 --> 21:05.120
einzelnen Komponenten voneinander abhängen lassen in der

21:05.120 --> 21:05.880
Benutzrelation.

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

21:12.960 --> 21:13.580
benutzen kann.

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

21:15.740 --> 21:16.400
implementieren.

21:16.940 --> 21:18.160
Das ist offensichtlich.

21:18.920 --> 21:21.580
B allerdings soll nicht umgekehrt A benutzen.

21:22.200 --> 21:23.520
Wir wollen keine Zyklen haben.

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

21:28.920 --> 21:32.720
B dadurch nicht komplexer wird, dadurch dass es A nicht benutzen darf.

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

21:37.640 --> 21:38.120
enthält.

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

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

21:51.060 --> 21:52.480
in der A nicht vorkommt.

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

22:00.010 --> 22:02.030
Für Sie gilt das Gleiche.

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

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

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

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

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

22:28.030 --> 22:28.290
haben.

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

22:33.910 --> 22:36.050
Das sind also die Grundregeln.

22:36.770 --> 22:42.670
Dann sollten wir eine Benutzrelation für A einsetzen.

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

22:49.190 --> 22:52.670
Benutz -Hierarchie, weil sie dann eben eine hierarchische Stufung hat,

22:53.210 --> 22:56.090
das heißt eine Halbordnung oder sogar eine Totalordnung.

22:56.930 --> 22:58.030
Warum ist das wichtig?

22:59.630 --> 23:04.670
Schauen Sie sich erst einmal dieses Geflecht von Benutzrelationen an.

23:05.450 --> 23:07.590
Die Pfeile hier bedeuten benutzt.

23:07.930 --> 23:12.030
Also das D benutzt das C, das A benutzt das C, das B benutzt das C.

23:12.130 --> 23:16.630
Und Sie sehen, dass es hier einen Zyklus gibt, dass nämlich das B, das

23:16.630 --> 23:19.310
E und das F benutzt und das F wiederum das B.

23:20.410 --> 23:24.430
Ich habe das ausgekreuzt, weil es eigentlich wenigstens eine dieser

23:24.430 --> 23:27.070
Relationen, wahrscheinlich die da hier, nicht geben sollte.

23:27.630 --> 23:30.510
Was ist der Nachteil, wenn es solche Zyklen gibt?

23:30.630 --> 23:34.210
Es gibt also hier einen Zyklus und hier einen Zyklus und hier nochmal

23:34.210 --> 23:34.850
einen Zyklus.

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

23:39.630 --> 23:43.450
ruft das F auf und das F ruft umgekehrt wieder das B auf.

23:43.450 --> 23:47.530
Denken Sie sich das B, E und F seien Pakete oder Klassen.

23:49.210 --> 23:50.950
Worum geht, ist das ungeschickt.

23:51.090 --> 23:54.350
Das ist ungeschickt, weil Sie keines dieser Module hier,

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

23:58.430 --> 23:59.550
alles schon funktioniert.

24:00.030 --> 24:03.890
Wir können das E nicht testen, das F nicht testen, wenn Sie das B

24:03.890 --> 24:05.230
nicht und das E nicht haben.

24:06.250 --> 24:08.450
Das gilt aber auch für alle anderen Knoten.

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

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

24:21.530 --> 24:23.070
und 70er Jahren baute.

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

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

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

24:41.570 --> 24:44.110
everything works, weil man nichts testen konnte.

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

24:48.410 --> 24:49.550
gab es den großen Knall.

24:50.770 --> 24:52.410
Es hat nämlich überhaupt nichts funktioniert.

24:53.250 --> 24:56.730
Man musste das Gesamtsystem laden, in einem Riesensystem nach Fehlern

24:56.730 --> 25:01.950
suchen und das erschwert eben die Fehlersuche und das Testen ungemein,

25:01.950 --> 25:04.690
wenn es diese zyklischen Abhängigkeiten gab, wenn man nicht einen

25:04.690 --> 25:07.850
Subkomponent herausnehmen kann und sie für sich testet.

25:08.350 --> 25:11.450
Deswegen vermeiden wir diese Zyklen nach Möglichkeit.

25:13.290 --> 25:15.250
Benutzte Relationen zyklenfrei gestalten.

25:16.110 --> 25:19.010
Wenn Sie jetzt schon ein bisschen programmiert haben, sagen Sie, aber,

25:19.130 --> 25:20.690
aber, aber, da gibt es doch Fälle.

25:21.370 --> 25:25.150
Jawohl, es gibt Fälle, wo die Benutzte Relation zyklisch aussieht.

25:25.990 --> 25:27.370
Und hier ist so ein Fall.

25:28.710 --> 25:31.190
Man nennt das die Callbacks oder die Rückrufe.

25:31.930 --> 25:35.930
Die Rückrufe bestehen so, kann ich so illustrieren, dass Sie hier eine

25:35.930 --> 25:38.390
Benutzerschnittstelle, sagen wir Swing, geschrieben haben.

25:39.270 --> 25:42.390
Hier ist der Anwendungskern, da sind die Funktionen und die

25:42.390 --> 25:45.890
Benutzerschnittstelle ruft natürlich den Anwendungskern auf.

25:46.810 --> 25:49.930
Daher benutzt natürlich die Benutzerschnittstelle den Anwendungskern.

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

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

25:57.870 --> 26:00.290
Aber jetzt gibt es auch diese Rückrufe.

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

26:05.030 --> 26:10.630
Benutzerschnittstelle eine Klasse an Objekte anlegen können, zum

26:10.630 --> 26:11.590
Beispiel für die Maus.

26:12.810 --> 26:17.070
Und in dieser Funktion, in der Maus-Klasse, den sogenannten

26:17.070 --> 26:20.010
MouseListener, haben Sie mehrere Funktionen.

26:20.010 --> 26:22.070
Zum Beispiel eine heißt MouseClicked.

26:23.030 --> 26:27.150
Und diese MouseClicked-Funktion hätten Sie gerne aufgerufen,

26:30.410 --> 26:33.790
wenn ein bestimmtes Ereignis eintritt.

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

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

26:47.810 --> 26:50.950
kann sein, dass Sie an mehreren Stellen der Benutzerschnittstelle so

26:50.950 --> 26:54.630
eine Klasse mit mehreren Funktionen übergeben müssen an den

26:54.630 --> 26:57.970
Anwendungskern, worauf der Anwendungskern sagt, wenn das und das

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

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

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

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

27:14.630 --> 27:16.870
etwas geändert hat, dann wollen Sie, dass natürlich in der

27:16.870 --> 27:19.250
Benutzerschnittstelle dieses Bild neu gezeichnet wird.

27:20.510 --> 27:23.630
Diese Zeichenfunktion oder die Anzeigefunktion müssen Sie jetzt der

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

27:29.450 --> 27:32.550
muss der Anwendungskern diesen Aufruf tätigen.

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

27:36.690 --> 27:39.430
Zeichenfunktion selbst, ist ja hier drin in der Benutzerschnittstelle.

27:41.170 --> 27:44.530
Also habe ich hier nicht, habe ich hier doch einen Zyklus und der ist

27:44.530 --> 27:45.430
böse.

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

27:49.470 --> 27:56.030
beim Betriebssystem, dass Ihre Anwendungsprogramm aufruft.

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

27:59.170 --> 28:00.550
korrekten Implementierung abhängig.

28:00.930 --> 28:04.090
Es sagt eigentlich, naja, was immer du rechnen willst, wir rechnen

28:04.090 --> 28:04.350
mal.

28:04.950 --> 28:08.170
Aber ich gehe deswegen nicht in die Knie, nur weil dein Programm,

28:08.290 --> 28:10.090
sagen wir, einen Überlauf oder einen Unterlauf enthält.

28:11.530 --> 28:15.190
Genauso ist es hier, dieser Rückruf, der sagt, zeige ich mir ein neues

28:15.190 --> 28:19.730
Bild, da sagt der Anwendungskern, mir ist das Bild völlig egal.

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

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

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

28:33.470 --> 28:38.130
Der Anwendungskern sagt, zeichne mal, ruf dich auf, aber ist deine

28:38.130 --> 28:39.170
Verantwortung hier drin.

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

28:42.910 --> 28:44.770
korrekten Implementierung der Benutzerschnittstelle.

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

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

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

28:58.750 --> 29:02.550
aber bei näherem Hinsehen eine wichtige Eigenschaft der

29:02.550 --> 29:05.950
Benutztrelation nicht enthält, nämlich die Abhängigkeit von einer

29:05.950 --> 29:07.370
korrekten Implementierung.

29:08.650 --> 29:11.990
Auch eine fehlerhafte Implementierung würde der Anwendungskern

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

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

29:19.290 --> 29:21.450
gar nicht, stoße es nur an.

29:22.450 --> 29:24.410
Okay, hat man das verstanden?

29:26.370 --> 29:28.530
Okay, gut, dann machen wir weiter.

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

29:35.030 --> 29:35.830
ausgeschrieben.

29:36.270 --> 29:37.730
Das kann ich jetzt also überspringen.

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

29:43.910 --> 29:46.230
ein bisschen Historie dazu.

29:47.090 --> 29:50.190
Wir hatten also über das Geheimnisprinzip gesprochen, oder meine

29:50.190 --> 29:51.790
Mitarbeiter hatten es Ihnen erklärt.

29:52.710 --> 30:01.350
Das hat das Erste, ein gewisser Panas, David Leuge Panas, formuliert,

30:01.690 --> 30:04.990
etwa 1972.

30:05.330 --> 30:08.810
So alt ist dieses Konzept schon, hat aber heute noch seine Gültigkeit,

30:08.890 --> 30:11.430
wie Sie gesehen haben, in objektorientierten Sprachen kommt es noch

30:11.430 --> 30:15.530
vor, ein bisschen implizit, wird nicht viel darüber geredet, aber ich

30:15.530 --> 30:18.910
habe darüber geredet jetzt ausführlich, oder meine Mitarbeiter.

30:20.310 --> 30:24.230
Hat noch andere Beiträge geleistet, modulare Softwarearchitektur, zum

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

30:27.230 --> 30:27.790
auch von ihm.

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

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

30:41.750 --> 30:43.830
Systeme sauber programmiert.

30:43.830 --> 30:51.650
Es gab ein Buch, das hieß Structured Programming, wie man

30:51.650 --> 30:52.810
strukturiert, programmiert.

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

30:59.830 --> 31:00.890
Programmieren im Großen.

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

31:09.770 --> 31:10.250
Erleuchtung.

31:10.250 --> 31:15.830
So ein Aha-Erlebnis, jetzt ist es klar, so muss man das machen.

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

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

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

31:30.450 --> 31:31.310
Software ändern muss.

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

31:36.650 --> 31:37.850
Software immer ändern müssen.

31:39.310 --> 31:40.950
Das ist einfach Fakt.

31:42.190 --> 31:44.570
Erst ab Version 3.0 sind die Benutzer zufrieden.

31:45.890 --> 31:49.450
Und dann gibt es Wettbewerber, da muss ich noch mehr hineinstopfen in

31:49.450 --> 31:52.450
die Software, noch besser machen, noch schöner machen und mobil machen

31:52.450 --> 31:54.350
und grafisch machen und dies und jenes.

31:56.610 --> 31:58.650
Erfolgreiche Software wird permanent geändert.

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

32:04.190 --> 32:07.870
Okay, jetzt gehen wir...

32:10.170 --> 32:14.350
Übrigens, ich zeige Ihnen kurz, der erste Artikel...

32:16.410 --> 32:18.110
Hier drin formuliert er das.

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

32:21.130 --> 32:24.090
criteria to be used in decomposing systems into modules.

32:24.190 --> 32:24.890
Das ist von 1972.

32:25.790 --> 32:28.930
Aber eigentlich ist ein besserer Artikel von 1979, der es

32:28.930 --> 32:29.770
verständlicher ist.

32:29.770 --> 32:32.650
Designing software for ease of extension and contraction.

32:33.230 --> 32:34.630
Genau das, was wir brauchen.

32:34.990 --> 32:36.450
Software muss immer erweitert werden.

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

32:39.350 --> 32:41.390
Ich muss eine abgespeckte Version liefern können.

32:42.010 --> 32:46.190
Oder eine Teilmenge des Systems woanders einbauen, in einem anderen

32:46.190 --> 32:46.590
Produkt.

32:48.790 --> 32:52.270
Also wenn Sie das noch genauer lesen wollen, auch das finden Sie

32:52.270 --> 32:53.230
garantiert am Internet.

32:53.770 --> 32:56.110
Designing software for ease of extension and contraction.

33:06.330 --> 33:11.390
Ein lustiger Artikel, auch von ihm, ist a rational design process.

33:11.590 --> 33:13.310
How and why to fake it.

33:15.110 --> 33:21.250
Warum ein rationaler Entwurfsprozess, wie man den herbeischwindet.

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

33:29.090 --> 33:30.070
kreativer Prozess.

33:30.650 --> 33:33.190
Kreative Prozesse gehen in Sprüngen vorhanden.

33:33.270 --> 33:35.590
Es fällt Ihnen was auf, dann sagen Sie, ach, das muss ich so und so

33:35.590 --> 33:35.870
machen.

33:36.030 --> 33:37.070
Ich denke, das passt so.

33:38.470 --> 33:40.990
Dann lösen Sie einen Teil dieser Aufgabe, der Entwurfsaufgabe.

33:41.090 --> 33:43.330
Dann gehen Sie zum anderen Teil über und dann sagen Sie, ach, das war

33:43.330 --> 33:43.650
Mist.

33:44.170 --> 33:45.950
Ich muss das nochmal anders machen.

33:46.010 --> 33:47.070
Ganz anders, ganz anders.

33:47.250 --> 33:49.950
Das mache ich jetzt mit 25 Modulen anstelle von 17.

33:50.610 --> 33:53.150
Und mit der Schnittstelle und dann nehme ich noch diese Komponente und

33:53.150 --> 33:55.650
sage, ist eigentlich auch nicht so gut.

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

34:03.070 --> 34:03.770
Entwurf gelangen.

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

34:09.230 --> 34:15.810
an, alle diese Irrtümer nachzuerleben.

34:16.170 --> 34:19.390
Als erstes habe ich mir gedacht, ich mache es so und so und so und so.

34:19.470 --> 34:20.530
Dann klären Sie den ganzen Mist.

34:20.950 --> 34:22.230
Aber das war alles nicht gut.

34:23.490 --> 34:24.290
Vergessen Sie es.

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

34:29.190 --> 34:35.590
und erklären Sie genau den, ohne die Fehler oder Fehlschläge, die Sie

34:35.590 --> 34:36.310
hinnehmen mussten.

34:39.110 --> 34:41.850
Dokumentation des Entwurfs sieht natürlich jetzt für Sie in der

34:41.850 --> 34:45.550
objektorientierten Zeit aus, dass Sie UML-Diagramme, Klassendiagramme

34:45.550 --> 34:49.250
liefern und diese Klassendiagramme dokumentieren, erklären, was die

34:49.250 --> 34:52.550
Funktionen sind und deren Geheimnisse natürlich.

35:00.290 --> 35:04.970
Das hier, das lassen wir jetzt mal aus, aber das müssen Sie nicht

35:04.970 --> 35:05.910
lesen.

35:07.450 --> 35:13.530
Parnas ist dann hergegangen und hat gesagt, jetzt probiere ich das mal

35:13.530 --> 35:13.890
aus.

35:14.030 --> 35:15.350
Und zwar an einem richtigen System.

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

35:25.310 --> 35:29.370
eines Düsenjägers, komplett neu strukturiert, mit dem Prinzip, den er

35:29.370 --> 35:32.830
genannt hatte, nämlich hierarchische Benutzrelation, Geheimnisprinzip

35:32.830 --> 35:34.130
bei den Modulen.

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

35:41.190 --> 35:44.730
Das ist inzwischen natürlich außer Dienst gestellt, das ist inzwischen

35:44.730 --> 35:45.650
ein älteres Flugzeug.

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

35:49.970 --> 35:55.130
Anforderungsdokument dieser Flugsoftware da und dort bestellen konnte.

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

36:01.470 --> 36:02.050
interessieren.

36:03.010 --> 36:04.170
Ich habe die bestellt.

36:04.950 --> 36:07.810
Ein dickes Buch, da ist alles drin.

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

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

36:15.410 --> 36:15.970
einem anderen Land.

36:17.450 --> 36:17.830
Wie kam?

36:18.550 --> 36:19.830
Ich glaube, ich habe sie noch irgendwo.

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

36:23.930 --> 36:24.190
war.

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

36:30.070 --> 36:33.910
Flugsoftware, die Steuerungssoftware, die Knöpfe, Sie können sich

36:33.910 --> 36:37.410
anschauen, wie der Steuerknüppel aussieht, in allen Details.

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

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

36:42.250 --> 36:43.870
Schwierigkeiten bei der nächsten Einreise.

36:48.530 --> 36:51.970
Das ist eine Methode, die funktioniert und die Sie eigentlich schon im

36:51.970 --> 36:56.410
Programmieren 1 gewissermaßen implizit mitbekommen haben.

36:58.570 --> 37:00.530
Jetzt sprechen wir über den objektorientierten Turf.

37:00.530 --> 37:02.030
Wir müssen jetzt gar nicht mehr viel sagen.

37:03.690 --> 37:07.370
Objektorientierte Turf sagt lediglich, das geheime Prinzip bleibt

37:07.370 --> 37:07.910
erhalten.

37:08.590 --> 37:11.250
Wir haben Schnittstellen, die Verbergen Entwurfsentscheidungen, wie

37:11.250 --> 37:13.690
beim Modul, die veränderbar bleiben sollen.

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

37:21.430 --> 37:23.190
sind natürlich die Klassen und das Paket.

37:23.650 --> 37:26.730
Im Paket werden mehrere Klassen zusammengefasst, die gemeinsamen

37:26.730 --> 37:28.150
Entwurfsentscheidungen kapseln.

37:29.250 --> 37:34.590
In der Regel brauchen Sie, um so etwas Äquivalentes wie ein

37:34.590 --> 37:37.890
Modulkonzept zu haben, mehrere Klassen.

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

37:45.130 --> 37:46.670
Drei, vier oder mehr Klassen.

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

37:51.970 --> 37:52.950
Modul betrachten.

37:53.610 --> 37:54.890
Was kommt jetzt hinzu?

37:54.890 --> 37:58.970
Anstelle des Modulführers, der für jedes einzelne Modul sagt, was die

37:58.970 --> 38:01.670
Geheimnisse des Moduls und seine Schnittstellen sind, seine

38:01.670 --> 38:04.080
Funktionen, steht jetzt der Paket- und Klassenführer.

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

38:09.070 --> 38:12.670
Paketdiagramm mit erläuterndem Text, der die Entwurfsentscheidungen

38:12.670 --> 38:13.410
dokumentiert.

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

38:19.390 --> 38:23.170
den Weg gemacht haben, wieder zu keulen.

38:26.190 --> 38:29.390
Genau, und das Analog zu den Modul-Schnittstellen sind natürlich die

38:29.390 --> 38:32.330
Schnittstellen der Klassen auch offensichtlich, oder aber abstrakte

38:32.330 --> 38:36.110
Klassen oder ganz abstrakte Klassen, nämlich Schnittstellen.

38:37.050 --> 38:37.890
So weit, so gut.

38:37.970 --> 38:39.370
Das haben wir auch längst verstanden.

38:40.170 --> 38:44.750
Der interne Entwurf besteht darin, dass Sie die Benutzrelation auf der

38:44.750 --> 38:48.490
Ebene von Paketen darstellen, nicht auf einzelnen Klassen, sondern auf

38:48.490 --> 38:49.510
der Ebene der Pakete.

38:50.170 --> 38:53.370
Innerhalb eines Paketes muss die Benutzrelation keineswegs

38:53.370 --> 38:56.310
hierarchisch sein, ist es oft nicht möglich.

38:59.250 --> 39:04.150
Und der Feinentwurf liefert jetzt, genau wie beim anderen Entwurf

39:04.150 --> 39:07.670
auch, noch Beschreibung der Datenstrukturen und Algorithmen, eventuell

39:07.670 --> 39:10.450
auch noch Pseudocode, wenn wir in Assembler programmieren.

39:12.870 --> 39:15.530
Allerdings haben Sie jetzt beim objektorientierten Entwurf mehr

39:15.530 --> 39:16.070
Möglichkeiten.

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

39:19.870 --> 39:20.390
schon gesehen.

39:20.390 --> 39:24.390
Sie können mehrfach Implementierung von einer einzelnen Schnittstelle

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

39:32.750 --> 39:37.810
Sie haben die Vererbung, die Polymorphie und die Möglichkeit der

39:37.810 --> 39:39.410
mehrfach Implementierung einer Schnittstelle.

39:40.350 --> 39:46.310
Das geht in C-artigen Sprachen ohne Objektorientierung schwerlich.

39:49.570 --> 39:58.530
Okay, so, erstaunlicherweise diese wenigen Zusätze, diese Polymorphie

39:58.530 --> 40:01.670
und die Vererbung und die Schnittstellenimplementierung und die

40:01.670 --> 40:07.010
Instanzierung, ermöglicht es jetzt, ganz neue Architekturen und

40:07.010 --> 40:11.350
Strukturen zu beschreiben, die in anderen, ohne diese Möglichkeiten,

40:12.250 --> 40:13.930
schwierig darzustellen.

40:14.010 --> 40:15.730
Und diese Struktur nennt man Entwurfsmuster.

40:16.610 --> 40:19.390
Diese Entwurfsmuster werde ich jetzt in den folgenden Vorlesungen

40:19.390 --> 40:19.850
behandeln.

40:19.990 --> 40:23.510
Das ist also eigentlich das Wissen, das aus der Objektorientierung

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

40:28.130 --> 40:29.090
aus der Objektorientierung.

40:29.210 --> 40:33.570
Wir werden heute einige sehen, die können Sie natürlich auch in C oder

40:33.570 --> 40:35.770
ähnlichen Sprachen verwirklichen.

40:38.510 --> 40:41.850
Gut, wir machen also jetzt Entwurfsmuster und Architekturstile, dabei

40:41.850 --> 40:43.810
die Architekturstile als nächstes.

40:48.540 --> 40:49.980
Auch wieder zur Historie.

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

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

41:01.600 --> 41:05.580
heute ist, und ist ein Pionier auf dem Gebiet der modularen,

41:05.640 --> 41:06.620
objektorientierten Software.

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

41:08.980 --> 41:09.760
geschrieben.

41:09.860 --> 41:17.620
Ada ist eine nicht ganz objektorientierte Sprache, aber bei den

41:17.620 --> 41:20.860
wiederverwendbaren Bibliotheken hat er Klassenbibliotheken für C++

41:20.860 --> 41:25.100
geschrieben und seine Bücher hatten einen sehr großen Einfluss

41:25.100 --> 41:27.980
darüber, wie man objektorientiert programmiert.

41:29.000 --> 41:31.680
Grady Butch, also ein Name, den man sich merken kann.

41:36.860 --> 41:40.480
Vielleicht haben Sie mal die Möglichkeit, etwas von ihm zu lesen.

41:44.000 --> 41:49.690
So, als nächstes kommen jetzt die Architekturstile dran.

41:50.750 --> 41:56.710
Die sind noch meistens weniger objektorientiert, aber ich glaube,

41:56.790 --> 42:02.090
jetzt wird es langsam interessant, weil man jetzt Entwurfsmuster haben

42:02.090 --> 42:07.170
oder Strukturen, Entwurfsstrukturen, die recht hilfreich sind.

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

42:12.450 --> 42:14.210
virtuelle Maschine erst nur als Begriff.

42:15.190 --> 42:19.130
Virtuelle Maschine, der Begriff ist sicher schon über den Weg

42:19.130 --> 42:23.310
gelaufen, denn es gibt die JVM, die Java Virtual Machine.

42:23.730 --> 42:25.750
Aha, aber was soll das eigentlich sein?

42:26.130 --> 42:27.850
Bis jetzt hatten Sie den Namen gehört.

42:28.310 --> 42:33.590
Man sagt jetzt einfach, eine virtuelle Maschine ist eine Menge von

42:33.590 --> 42:37.630
Softwarebefehlen und Objekten, die auf einer darunterliegenden

42:37.630 --> 42:40.810
abstrakten oder virtuellen Maschine aufbauen und diese ganz oder

42:40.810 --> 42:42.130
teilweise verdecken können.

42:46.140 --> 42:49.800
Eine Menge von Softwarebefehlen und Objekten, das ist das Wichtige.

42:50.600 --> 42:54.200
Wir könnten auch sagen, heutige Terminologie RP, Application

42:54.200 --> 42:59.800
Programming Interface, die auf einer darunterliegenden Maschine

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

43:04.060 --> 43:07.080
ganz oder teilweise verdecken, werden wir sehen, wann wir das machen

43:07.080 --> 43:07.340
müssen.

43:10.440 --> 43:15.540
Diese virtuelle Maschine baut also auch auf etwas auf, benutzt es

43:15.540 --> 43:18.880
also, und da wollen wir natürlich auch dafür sorgen, dass diese

43:18.880 --> 43:20.600
Benutzrelation zyklenfrei ist.

43:21.680 --> 43:26.720
Beispiele, die Java JVM, die hatte ich schon erwähnt.

43:27.200 --> 43:28.760
Was ist diese JVM eigentlich?

43:28.760 --> 43:35.020
Diese JVM liefert eine Menge von Befehlen, Softwarebefehlen, zum

43:35.020 --> 43:38.000
Beispiel zum Addieren von Zahlen, zum Anlegen von Objekten, zum

43:38.000 --> 43:41.320
Aufrufen von Methoden und so fort.

43:42.540 --> 43:48.080
Und diese Befehle sind implementiert als Befehlsreihenfolgen in der

43:48.080 --> 43:51.080
darunterliegenden Maschine auf ihrem PC zum Beispiel.

43:51.660 --> 43:54.560
Oder aber sie werden durch ein anderes Programm interpretiert.

43:55.580 --> 44:00.120
Also die JVM ist klarerweise eine virtuelle Maschine.

44:00.420 --> 44:04.440
Sieht so aus wie ein Rechner, hat Befehle, Grundbefehle zum

44:04.440 --> 44:11.020
Manipulieren von Daten, aber sie existiert nicht richtig als Hardware,

44:11.720 --> 44:15.920
weil es normalerweise keine, es gibt nur wenige Hardware

44:15.920 --> 44:19.060
-Implementierungen von Java, die sich übrigens auch gar nicht

44:19.060 --> 44:19.820
durchgesetzt haben.

44:19.820 --> 44:21.520
Das wäre so eine.

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

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

44:33.040 --> 44:35.480
Sie programmieren in der Programmiersprache Java.

44:36.500 --> 44:41.260
Sie schreiben nie einen Maschinenbefehl und auch keinen JVM-Befehl,

44:41.260 --> 44:47.520
sondern der Übersetzer nimmt ihr Java-Programm, übersetzt es in eine

44:47.520 --> 44:50.260
Folge von JVM-Befehlen.

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

44:56.400 --> 44:59.460
ja, diese JVM-Befehle verstehe ich, die kann ich jetzt wieder

44:59.460 --> 45:05.060
übersetzen in Befehlsfolgen auf der zugrunde liegenden, echten, nicht

45:05.060 --> 45:06.920
-virtuellen, also der realen Maschine.

45:08.260 --> 45:09.960
So, was gibt es noch für Beispiele?

45:11.500 --> 45:12.020
Betriebssystem.

45:12.920 --> 45:16.740
Stellen Sie sich vor, Sie bekämen Ihren PC, einen Laptop oder sonst

45:16.740 --> 45:17.980
was ohne Betriebssystem.

45:19.060 --> 45:20.040
Ganz nackt.

45:21.620 --> 45:26.340
Dann haben Sie nur die Maschinenbefehle, die es gibt, einige

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

45:29.780 --> 45:30.160
bekommen.

45:31.720 --> 45:33.620
Und dann ist das Leben ziemlich schwer.

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

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

45:40.680 --> 45:42.220
Es gibt ja kein Programm, das das macht.

45:42.880 --> 45:50.180
Das Betriebssystem hingegen liefert diese zusätzlichen Funktionen, zum

45:50.180 --> 45:52.580
Beispiel eine Datei zu öffnen und zu lesen, zu schreiben, zu

45:52.580 --> 45:56.960
schließen, eine Netzwerkverbindung zu öffnen, Datenpakete zu

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

45:59.660 --> 46:01.500
verloren gehen unterwegs oder kaputt gehen.

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

46:05.800 --> 46:09.120
Funktionen, die die nackte Hardware nicht hat.

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

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

46:17.580 --> 46:23.620
letztendlich abgebildet auf Befehlsfolgen, die sie implementieren.

46:23.940 --> 46:27.120
Auf der tatsächlichen, richtigen, wirklichen Maschine.

46:28.840 --> 46:29.840
Anwendungskern ist auch so.

46:31.240 --> 46:34.800
Ich hatte hier oben was gesagt, das ist ganz oder teilweise verdecken.

46:36.820 --> 46:40.740
Die JVM verdeckt komplett den Befehlssatz.

46:41.520 --> 46:44.220
Die brauchen den nicht des Rechners.

46:44.480 --> 46:47.460
Wenn Sie den Befehlssatz auch noch benutzen würden, aus Java heraus,

46:47.560 --> 46:50.620
was übrigens geht, dann müssen Sie sehr, sehr viele Details kennen.

46:52.440 --> 46:54.520
Man nennt das auch das Window to Hell.

46:55.960 --> 46:58.980
Das Fenster in die Hölle, wenn Sie aus einer höheren

46:58.980 --> 47:03.840
Programmiersprache heraus die Befehle der grundlegenden Architektur

47:03.840 --> 47:04.180
benutzen.

47:04.340 --> 47:06.960
Übrigens, dann haben Sie auch noch den Nachteil, dass es nur auf der

47:06.960 --> 47:09.720
Maschine funktioniert, für die Sie es geschrieben haben und auf der

47:09.720 --> 47:11.500
vom Nächsten nicht mehr.

47:12.060 --> 47:13.520
Vom Hersteller unterschiedlich.

47:15.260 --> 47:16.340
Das ist also eine Verdeckung.

47:16.920 --> 47:20.380
Das Betriebssystem verdeckt davon aber weniger.

47:20.380 --> 47:26.260
Das Betriebssystem erlaubt es weiterhin, ein Programm, das in

47:26.260 --> 47:27.700
Assembler geschrieben wird, auszuführen.

47:27.800 --> 47:30.500
Das heißt, die Maschinenbefehle sind weiterhin sichtbar.

47:32.020 --> 47:36.220
Allerdings gibt es dabei im Betriebssystem privilegierte Befehle.

47:38.980 --> 47:41.960
Und diese privilegierten Befehle, wenn Sie die in Ihr

47:41.960 --> 47:47.240
Maschinenprogramm einfügen würden, würden Sie entweder eine Ausnahme

47:47.240 --> 47:51.240
erzeugen und das Programm abstoppen oder aber total ignoriert werden.

47:53.420 --> 48:03.980
Manche dieser der vom Betriebssystem verdeckten Befehle haben zum

48:03.980 --> 48:06.420
Beispiel zu tun mit dem Zugriff auf Platten.

48:08.040 --> 48:12.520
In Ihrem Anwendungsprogramm dürfen Sie den Zugriff auf Platten nur

48:12.520 --> 48:15.200
über die entsprechenden Systemaufrufe steuern, aber Sie dürfen nicht

48:15.200 --> 48:17.300
direkt das Gerät ansteuern.

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

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

48:29.780 --> 48:33.240
Das Betriebssystem verbirgt nur einen Teil dieses Befehlssatzes,

48:33.340 --> 48:36.040
nämlich nur die privilegierten Befehle.

48:41.480 --> 48:45.500
GUI-Bibliotheken, also Bibliotheken für grafische Benutzeroberflächen,

48:45.600 --> 48:46.040
sind ähnlich.

48:47.760 --> 48:52.920
Wir geben Ihnen eine komplexe Funktionalität vor, nämlich Fenster und

48:52.920 --> 48:57.000
Knöpfe und Menüs und Rollbalken und was es da alles gibt.

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

49:01.020 --> 49:03.020
macht die GUI-Bibliothek direkt für Sie.

49:03.920 --> 49:06.420
Und da, wo die GUI-Bibliothek arbeitet, zum Beispiel in einem

49:06.420 --> 49:08.560
Rollbalken, können Sie auch nicht hineinschreiben.

49:09.720 --> 49:11.980
Es ist also auch ein Teil davon verdeckt.

49:15.780 --> 49:18.860
Okay, das war also die Idee der virtuellen Maschine.

49:19.660 --> 49:21.300
Und jetzt benutzen wir das.

49:24.360 --> 49:28.140
Das ist die abstrakte Maschine oder virtuelle Maschine.

49:28.300 --> 49:30.240
Das ist also das, was ich jetzt mündlich erklärt habe, nochmal

49:30.240 --> 49:31.600
skizziert.

49:33.740 --> 49:36.520
Natürlich sollten die Befehle, die die abstrakte Maschine zur

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

49:39.640 --> 49:44.880
können, siehe Java-Programmiersprache, siehe JVM, sehr universell

49:44.880 --> 49:48.320
einsetzbar sein für die Zwecke, die man vorhat.

49:53.260 --> 49:56.540
Beispiel, das Betriebssystem, das ich Ihnen sagte, das macht also die

49:56.540 --> 49:59.620
Kommunikation, die Kommandosprache, die generagrafische Benutzung, die

49:59.620 --> 50:03.020
Datenhaltung auf Hintergrundspeicher, also Platte, CD, DVD,

50:04.540 --> 50:05.920
Speicherstift und so weiter.

50:06.340 --> 50:08.400
Es bietet einen sogenannten virtuellen Speicher.

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

50:12.340 --> 50:15.960
unbegrenzten, ewig langen Hauptspeicher von einem ganzen Terabyte oder

50:15.960 --> 50:19.300
so etwas, wenn in Wirklichkeit die Rechner vielleicht nur einige

50:19.300 --> 50:28.100
Gigabyte enthält und die Abbildung des Gesamtadressraumes auf Ihren

50:28.100 --> 50:31.980
Hauptspeicher, der ja viel kleiner ist, übernimmt auch wieder das

50:31.980 --> 50:32.600
Betriebssystem.

50:34.500 --> 50:37.080
Ihr Gesamtarbeitsspeicher eines Programmes, wenn er sehr groß wird,

50:37.080 --> 50:39.400
muss dann natürlich auf die Platte ausgelagert werden.

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

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

50:45.780 --> 50:46.700
rausgeschrieben werden.

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

50:51.840 --> 50:53.500
Seitenaustausch.

50:55.540 --> 50:58.380
So, und eine der grundlegenden Funktionen ist auch die

50:58.380 --> 50:59.160
Prozessverwaltung.

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

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

51:07.580 --> 51:10.400
permanent irgendwas zu tun haben oder gerade warten.

51:11.260 --> 51:14.140
Das ist nicht nur Ihr Applikationsprogramm, sondern alles Mögliche an

51:14.140 --> 51:14.380
Dienstprogrammen.

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

51:20.160 --> 51:24.440
auf mehreren Kernen, wer jetzt gerade laufen darf, wie lange, was dann

51:24.440 --> 51:27.660
passiert, wenn er stoppt, das ist die Prozessverwaltung, die ist

51:27.660 --> 51:29.040
natürlich auch im Betriebssystem drin.

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

51:33.840 --> 51:35.860
virtuellen Maschinen sehen.

51:36.440 --> 51:40.780
Als allererstes, die unterste ist die Hardware selbst, als nächstes

51:40.780 --> 51:44.200
käme die Prozessverwaltung, die bietet Ihnen dann die Möglichkeit,

51:44.320 --> 51:45.820
Prozesse zu starten und anzuhalten.

51:46.960 --> 51:49.740
Darüber liegt dann der virtuelle Speicher, der dafür sorgt, dass Sie

51:49.740 --> 51:51.540
einen virtuellen großen Speicherplatz haben.

51:51.940 --> 51:55.120
Und darüber kommen dann die Datenhaltung und die Kommunikation.

51:56.280 --> 52:01.680
Und als letztes die Benutzerschicht mit entweder einer Kommandosprache

52:03.140 --> 52:06.880
oder einer grafischen Benutzeroberfläche oder beides.

52:12.540 --> 52:16.180
Genau, das hatte ich auch schon gesagt, diese privilegierten Befehle,

52:16.260 --> 52:18.820
wenn Sie sie benutzen in Ihrem Programm, in dem nicht privilegierten

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

52:24.160 --> 52:25.620
Das hatten wir auch besprochen.

52:28.120 --> 52:33.280
Sie können auch sagen, ich habe ein System zur Behandlung

52:33.280 --> 52:34.260
elektronischer Post.

52:35.960 --> 52:38.140
Auch dafür kann ich eine API schreiben.

52:39.060 --> 52:42.160
Denken Sie mal nicht unbedingt an Ihren grafischen Postklienten,

52:43.360 --> 52:45.540
sondern an die Grundfunktion, die Sie dafür brauchen.

52:46.160 --> 52:49.640
Und das macht natürlich die darunterliegenden Protokolle, Kufferung

52:49.640 --> 52:52.640
und Stricklung der Botschaften, Zusammensetzung von langen

52:52.640 --> 52:56.660
Nachrichten, Quittierungen, Fehlerbehandlungen, Kommunikation mit dem

52:56.660 --> 52:59.620
Dienstgeber und so weiter, sodass ein zuverlässiger

52:59.620 --> 53:00.980
Nachrichtenaustausch entsteht.

53:02.540 --> 53:05.660
Wer von Ihnen hat schon mal mit Makros gearbeitet?

53:07.420 --> 53:10.840
Makros, Makros 1, 2, 3, 4...

53:10.840 --> 53:14.740
Also es sind nicht sehr viele, ist auch nicht verwunderlich, denn

53:14.740 --> 53:19.140
Makros nimmt man hauptsächlich in Assemblerprogrammen her, aber auch

53:19.140 --> 53:20.380
noch in C übrigens.

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

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

53:32.540 --> 53:33.780
Stelle einzusetzen per Namen.

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

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

53:41.060 --> 53:43.460
dieser Text an der Stelle eingepflanzt.

53:45.520 --> 53:48.720
Ist gelegentlich ganz praktisch.

53:50.400 --> 53:54.440
Zum Beispiel, auch wenn Sie in Assembler programmieren, haben Sie

53:54.440 --> 54:00.060
sicher Makros, die die Befehle einflechten, den Prozeduraufruf und

54:00.060 --> 54:01.760
Rückkehr liefern.

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

54:06.180 --> 54:10.520
und den Rückgabewert Platz vorhalten und Sie müssen die

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

54:15.260 --> 54:18.860
Das ist also typischerweise eine Befehlsfolge von einem Dutzend

54:18.860 --> 54:19.340
Befehlen.

54:20.360 --> 54:24.800
Und die Befehlsfolge, die lassen Sie sich durch ein Makroaufruf

54:24.800 --> 54:26.740
erzeugen, reinschreiben.

54:27.160 --> 54:27.900
Das ist also ein Kürzel.

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

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

54:36.520 --> 54:41.200
benutzen und mal den Befehl, den Aufruf, die Aufrufsfolge selbst

54:41.200 --> 54:42.460
hinschreiben und dabei einen Fehler machen.

54:46.690 --> 54:50.640
Das war also jetzt das Konzept der virtuellen Maschine oder auch

54:50.640 --> 54:51.540
abstrakter Maschine.

54:51.900 --> 54:52.760
Gibt es dazu Fragen?

54:59.300 --> 55:03.100
Das hat jetzt mit Objektorientierung erstmal, ist orthogonal dazu,

55:04.260 --> 55:08.080
können Sie sowohl objektorientiert als auch ohne Objektorientierung

55:08.080 --> 55:08.660
verwirklichen.

55:08.660 --> 55:11.680
Dann gibt es noch einen Begriff, der wichtig ist.

55:11.800 --> 55:16.680
Das sind die Programmfamilien oder die Softwareproduktlinie.

55:16.920 --> 55:21.220
Früher sagte man übrigens, der Begriff stammt noch von Parnas, der

55:21.220 --> 55:27.160
sprach von Program Families und später dann hat man einen schickeren

55:27.160 --> 55:30.320
Term gefunden, nämlich die Softwareproduktlinie.

55:32.000 --> 55:34.960
Eine Menge von Programmen, die erhebliche Anteile von Anforderungen,

55:35.040 --> 55:38.080
Entwurfsbestandteilen oder Softwarekomponenten gemeinsam haben.

55:38.580 --> 55:42.760
Unterschiedliche, ähnliche Programme, die Bestandteile haben.

55:43.000 --> 55:47.840
Denken Sie an die Idee bei den Autos, da ist es genau das gleiche.

55:47.880 --> 55:52.900
Sie haben eine Motorenpalette und Sie haben einen, wie heißt das bei

55:52.900 --> 55:55.120
VW, den modularen Querbaukasten.

55:56.220 --> 56:02.760
Da haben Sie verschiedenste Komponenten, die Sie anderweitig

56:02.760 --> 56:07.060
zusammengestellt mit einer anderen Karosserie als ein neues Fahrzeug

56:07.060 --> 56:07.800
verkaufen können.

56:09.820 --> 56:12.480
Und es ist natürlich klar, dass ich dafür sehr, sehr viel

56:12.480 --> 56:15.800
Entwicklungszeit spare, wenn ich nicht für jedes Modell, das ich

56:15.800 --> 56:19.880
anbiete, in dieser Modellvielfalt von heute, wenn ich da jedes Mal

56:19.880 --> 56:24.900
einen völlig neuen Motor entwickeln muss, sondern aus meiner Palette

56:24.900 --> 56:28.940
von Motoren auswählen kann, sogar den Kunden überlassen kann, wie viel

56:28.940 --> 56:29.740
PS er haben will.

56:31.300 --> 56:34.500
Und das ist die gleiche Idee bei der Produktfamilie, beziehungsweise

56:34.500 --> 56:35.700
bei der Softwareproduktlinie.

56:35.820 --> 56:41.420
Sie planen für mehrere Kunden, leicht unterschiedliche Varianten eines

56:41.420 --> 56:45.940
Systems auszuliefern und haben jetzt die Möglichkeit, bestimmte

56:45.940 --> 56:50.740
Grundkomponenten, die kann ich mehrfach benutzen, aber nicht nur die

56:50.740 --> 56:52.680
Softwarekomponenten selbst, sondern vielleicht auch die

56:52.680 --> 56:53.800
Entwurfsbestandteile.

56:55.120 --> 56:58.020
Und wenn es noch weiter geht, übrigens Anforderungen zu schreiben, ist

56:58.020 --> 56:59.040
auch sehr aufwendig.

57:01.260 --> 57:04.880
Das sind oft gerne 500.000 oder noch mehr Seiten und Bände.

57:05.540 --> 57:08.360
Da ist natürlich auch klar, dass ich sage, gut, die Anforderungen sind

57:08.360 --> 57:09.980
eigentlich an der und der Stelle die gleichen.

57:10.620 --> 57:14.840
Die benutze ich erneut in der neuen Version meiner Software.

57:17.040 --> 57:21.400
Es ist kostengünstiger, ein neues Mitglied der Produktfamilie zu

57:21.400 --> 57:25.200
planen, zu entwerfen und schließlich zu implementieren.

57:26.340 --> 57:31.760
Und natürlich auch zu testen, denn fertige Komponenten, die schon

57:31.760 --> 57:33.840
getestet sind, brauche ich nicht erneut zu testen.

57:35.980 --> 57:39.780
Das Ziel ist die Aufnutzung von Gemeinsamkeiten und Wiederverwendung

57:39.780 --> 57:42.440
von Entwürfen, Spezifikationen, Anforderungen, Softwarekomponenten,

57:42.500 --> 57:43.020
Bibliotheken.

57:43.320 --> 57:46.920
Alles, was wir früher schon erzeugt haben, um Entwicklungs- und

57:46.920 --> 57:48.600
Wartungskosten zu reduzieren.

57:48.600 --> 57:54.500
Man spricht übrigens in diesen Produktfamilien oder Produktlinien von

57:54.500 --> 57:55.620
Variationspunkten.

57:56.600 --> 58:00.160
Da gibt es Stellen in der Architektur, wo vorgesehen ist, eine andere

58:00.160 --> 58:04.340
Komponente einzuführen, die sich in Funktionalität oder Plattform

58:04.340 --> 58:06.820
unterscheiden.

58:12.420 --> 58:15.080
Das könnte zum Beispiel eine mobile Variante sein.

58:15.400 --> 58:18.660
Da haben Sie eine mobile Variante und die Datenführung ist nicht mehr

58:18.660 --> 58:22.740
auf dem mobilen Gerät, sondern auf einem Dienstgeber.

58:22.880 --> 58:25.500
Das heißt, jedes Mal, wenn Zugriffe auf diese Daten sind, brauchen Sie

58:25.500 --> 58:31.800
einen Variationspunkt, der sagt, an dieser Stelle könntest du eine

58:31.800 --> 58:33.940
Fernübertragung der Daten einfügen.

58:38.320 --> 58:41.140
Sie können auch auf verschiedenen Hardware- und Betriebssystemen

58:41.140 --> 58:41.460
laufen.

58:41.840 --> 58:44.600
Das heißt, es gibt bestimmte Komponenten, die ersetzt werden müssen,

58:44.660 --> 58:46.480
die Betriebssystemen nahe sind.

58:49.140 --> 58:52.620
Das kann sein, dass sie sich im Format von Ein- und Ausgabe

58:52.620 --> 58:56.180
unterscheiden oder sogar im Funktionsumfang.

58:56.760 --> 59:00.260
Es gibt eine Enterprise Edition, es gibt eine Professional Edition, es

59:00.260 --> 59:01.100
gibt eine Home Edition.

59:01.880 --> 59:05.680
Diese Euphemismen für billigere Varianten.

59:11.320 --> 59:14.360
Wie unterscheiden sich jetzt diese Mitglieder einer Programmfamilie?

59:14.360 --> 59:17.540
Na ja, sie unterscheiden sich eben in Datenstrukturen und Algorithmen.

59:18.260 --> 59:19.460
Sie unterscheiden sich daran,

59:23.360 --> 59:25.380
dass sie auf unterschiedlichen Plattformen laufen.

59:29.660 --> 59:31.580
Jetzt brauchen wir noch einen kleinen Unterschied.

59:33.600 --> 59:36.800
Unterschied zwischen Allgemeinheit und Flexibilität.

59:37.920 --> 59:40.960
Allgemeinheit heißt, ein Programm ist allgemein, falls es in vielen

59:40.960 --> 59:43.080
Situationen ohne Änderung benutzt werden kann.

59:43.080 --> 59:47.960
Also es läuft sowohl mobil als auch auf dem Dienstgeber, als auch

59:47.960 --> 59:48.540
zentral.

59:50.280 --> 59:54.040
Es läuft auf allen Plattformen, die es gerade so gibt, irgendwie.

59:54.380 --> 59:55.240
Es ist schwer zu erreichen.

59:56.860 --> 59:58.260
Das wäre Allgemeinheit.

59:58.940 --> 01:00:02.380
So eine überbordende Allgemeinheit ist meistens mit sehr, sehr hohen

01:00:02.380 --> 01:00:03.620
Entwicklungskosten verbunden.

01:00:04.680 --> 01:00:07.360
Da könnte es sein, dass ich spezielle Compiler schreiben muss, um das

01:00:07.360 --> 01:00:08.440
zu erreichen, zum Beispiel.

01:00:09.360 --> 01:00:13.680
Aber wir sagen, ein Programm ist flexibel, wenn ich es abändern kann,

01:00:14.080 --> 01:00:17.700
sodass es für viele Situationen einsetzbar werden kann.

01:00:18.600 --> 01:00:23.220
Und wir sind eher interessiert an der Flexibilität als an der

01:00:23.220 --> 01:00:24.000
Allgemeinheit.

01:00:24.940 --> 01:00:27.820
Flexibilität heißt, wir haben ein Software-System, das

01:00:27.820 --> 01:00:32.400
zufriedenstehend läuft für einen bestimmten Benutzerkreis, aber es

01:00:32.400 --> 01:00:35.240
kommen neue Anforderungen heran, eine neue Plattform, als würde es

01:00:35.240 --> 01:00:36.320
auch noch auf dem Gerät haben.

01:00:36.320 --> 01:00:40.640
Dann können wir die Software so abändern, dass es auch den neuen

01:00:40.640 --> 01:00:42.160
Anforderungen genügt.

01:00:45.250 --> 01:00:47.810
Ein flexibler Entwurf muss also änderungsfreundlich sein.

01:00:48.190 --> 01:00:50.910
Und das ist das, worüber wir im Entwurf die ganze Zeit reden.

01:00:52.050 --> 01:00:52.570
Änderungsfreundlichkeit.

01:00:55.310 --> 01:00:56.890
Noch irgendwelche Fragen dazu?

01:01:00.650 --> 01:01:07.090
Das waren also jetzt diese beiden Konzepte, nämlich abstrakte Maschine

01:01:07.090 --> 01:01:10.370
oder virtuelle Maschine und Produktfamilie.

01:01:11.130 --> 01:01:13.990
Jetzt kommt ein anderer Begriff, nämlich der Begriff des

01:01:13.990 --> 01:01:15.230
Architekturstils.

01:01:18.270 --> 01:01:21.310
Architekturstile beschreiben den Grobaufbau eines Gesamtsystems.

01:01:22.550 --> 01:01:26.170
Man könnte auch sagen, sind sehr grobkörnige Entwurfsmuster.

01:01:26.990 --> 01:01:29.990
Und da gibt es jetzt eine ganze Latte davon.

01:01:30.450 --> 01:01:31.510
Die schauen wir uns an.

01:01:31.590 --> 01:01:36.310
Die sind übrigens gar nicht mal unabhängig von Objektdehontierung oder

01:01:36.310 --> 01:01:36.630
nicht.

01:01:37.770 --> 01:01:40.330
Da gibt es die Schichtenarchitektur, den Klient-Dienstgeber,

01:01:40.730 --> 01:01:46.130
Partnernetze, Datenablage, MVC, Fließband, Rahmenarchitektur und

01:01:46.130 --> 01:01:47.450
dienstorientierte Architektur.

01:01:48.750 --> 01:01:51.930
Diese Begriffe tauchen immer wieder auf und die müssen wir kurz

01:01:51.930 --> 01:01:53.190
klären, wie so etwas aussieht.

01:01:53.290 --> 01:01:54.770
Ist aber keine Zauberei.

01:01:57.470 --> 01:01:58.590
Die Schichtenarchitektur.

01:01:59.170 --> 01:02:05.130
Schichtenarchitektur sagt, wir haben eine Softwarearchitektur, die

01:02:05.130 --> 01:02:07.750
gegliedert ist in hierarchisch angeordnete Schichten.

01:02:08.030 --> 01:02:14.130
Das sind also Mengen von Systemkomponenten, Softwarekomponenten,

01:02:14.170 --> 01:02:17.710
Module, Klassen, Objekte, Pakete, was auch immer, mit einer

01:02:17.710 --> 01:02:18.930
wohldefinierten Schnittstelle.

01:02:19.990 --> 01:02:22.690
Und dann gibt es eine Benutzrelation zwischen den Schichten.

01:02:26.170 --> 01:02:28.730
Wobei diese nach Möglichkeit nicht zyklisch ist.

01:02:29.950 --> 01:02:30.470
Beispiel.

01:02:31.530 --> 01:02:34.250
Das wäre eine Illustration einer Schichtenarchitektur.

01:02:34.810 --> 01:02:38.690
Wir haben hier drei Schichten, in den Schichten liegen einzelne

01:02:38.690 --> 01:02:39.450
Komponenten.

01:02:40.490 --> 01:02:42.470
Die können sich untereinander benutzen, wie sie wollen.

01:02:42.670 --> 01:02:45.330
Die hier benutzen sich gar nicht, da ist auch nichts eingezeichnet.

01:02:45.850 --> 01:02:48.830
Aber die Benutzung läuft immer von oben nach unten, von der höheren

01:02:48.830 --> 01:02:50.010
Schicht zur niedrigeren Schicht.

01:02:52.510 --> 01:02:56.570
Das könnte zum Beispiel die Nutzoberfläche sein, das hier könnte der

01:02:56.570 --> 01:02:59.200
Anwendungskern sein und das unterste die Datenhaltung.

01:02:59.990 --> 01:03:03.050
Eine Drei-Schichten-Architektur und wir erlauben diese Aufrufe in

01:03:03.050 --> 01:03:03.630
diese Richtung.

01:03:04.570 --> 01:03:09.930
Wobei jetzt die Frage ist, ob es erlaubt ist, nur seine nächste

01:03:09.930 --> 01:03:13.310
darunterliegende Schicht zu benutzen, also aufzurufen.

01:03:14.170 --> 01:03:16.950
Oder ob ich so einen Aufruf machen kann, der von der obersten Schicht

01:03:16.950 --> 01:03:18.250
bis in die unterste Schicht geht.

01:03:18.830 --> 01:03:22.870
Das ist eine Entwurfsentscheidung, da gibt es keine endgültige Antwort

01:03:22.870 --> 01:03:24.790
ja oder nein, das hängt davon ab, was man will.

01:03:25.890 --> 01:03:30.870
Die meisten würden sagen, schöner ist es, wenn diese Schicht nur die

01:03:30.870 --> 01:03:32.890
genau darunterliegende Schicht benutzt.

01:03:33.350 --> 01:03:36.950
Wenn sie trotzdem noch die unterste Schicht braucht, dann müsste ich

01:03:36.950 --> 01:03:40.030
hier eben eine Delegationsfunktion oder Delegationskomponente

01:03:40.030 --> 01:03:40.510
einfügen.

01:03:40.990 --> 01:03:41.850
Für die wenigen Fälle.

01:03:43.730 --> 01:03:46.450
Das ist die sogenannte intransparente Schichtung.

01:03:46.450 --> 01:03:49.710
Die transparente Schichtung sagt, naja, du kannst doch diese Schichten

01:03:49.710 --> 01:03:51.450
durchschauen und auch so einen Aufruf durchführen.

01:04:01.970 --> 01:04:07.030
Also jede Schicht, deren Struktur ist beliebig, aber sollte natürlich

01:04:07.030 --> 01:04:08.100
auch nicht chaotisch sein.

01:04:10.170 --> 01:04:13.270
Bei der intransparenten Schicht, das sagte ich gerade, oder opaque

01:04:13.270 --> 01:04:17.250
layers, da sprechen wir nur von einer Schicht zur nächsten

01:04:17.250 --> 01:04:18.070
darunterliegenden.

01:04:20.790 --> 01:04:25.510
Da ist also das hier nicht erlaubt und der Aufruf nach oben auch

01:04:25.510 --> 01:04:25.790
nicht.

01:04:27.370 --> 01:04:29.550
Das ist also die intransparente Schichtung.

01:04:29.970 --> 01:04:31.830
Ich kann also durch diese Schicht nicht durchschauen.

01:04:33.110 --> 01:04:34.750
Die Schicht B ist hier intransparent.

01:04:35.970 --> 01:04:39.070
Bei einer transparenten Schichtneigte durch ist es erlaubt, dass ich

01:04:39.070 --> 01:04:42.630
natürlich diese Aufrufe durchführe wie immer, aber auch diesen Aufruf,

01:04:42.730 --> 01:04:43.670
deswegen der Haken dran.

01:04:44.310 --> 01:04:46.590
Die umgekehrte ist weiterhin nicht erlaubt.

01:04:49.130 --> 01:04:51.770
Vorteile der Schichtneigtür, es ist einfach zu verstehen.

01:04:52.470 --> 01:04:54.230
Es gibt eben diese drei Schichten oder vier Schichten.

01:04:55.530 --> 01:04:57.090
Es ist einfach zu testen.

01:04:57.370 --> 01:05:00.350
Ich beginne mit dem Testen der Schicht C und auch mit dem Bau der

01:05:00.350 --> 01:05:00.810
Schicht C.

01:05:01.170 --> 01:05:03.590
Wenn ich Schicht C fertig habe, dann kann ich Schicht B testen.

01:05:04.750 --> 01:05:07.450
Die wird dann die Schicht C natürlich im Test benutzen, wunderbar,

01:05:07.530 --> 01:05:10.190
geht aber alles und Schicht A genauso.

01:05:10.990 --> 01:05:14.550
Ich kann aber sogar die Schicht A testen, ohne dass die Schichten B

01:05:14.550 --> 01:05:17.350
und C da sind, wenn ich mir stattdessen Platzhalter besorge,

01:05:17.970 --> 01:05:21.190
sogenannte Stubs, die eben gar nichts tun, nur den Aufruf

01:05:21.190 --> 01:05:22.590
entgegennehmen und dann zurückkehren.

01:05:23.730 --> 01:05:26.010
Wie man das testet, werden wir später noch genauer sehen.

01:05:31.130 --> 01:05:34.890
Also übersichtliche Struktur, keine zu starke Einschränkung des

01:05:34.890 --> 01:05:40.230
Entwerfers, weil Sie noch liberale Strukturierungsmechanismen,

01:05:40.390 --> 01:05:44.130
Möglichkeiten innerhalb einer Schicht haben und Sie können

01:05:44.130 --> 01:05:46.730
wiederverwenden, Sie können eine Schicht austauschen, Sie können sie

01:05:46.730 --> 01:05:52.730
woanders benutzen und Sie können von unten oder von oben her testen.

01:05:56.290 --> 01:05:58.050
Das war also die Schichtenarchitektur.

01:05:58.990 --> 01:06:01.870
Bei intransparenten Schichten kann es sein, dass es zu leichten

01:06:01.870 --> 01:06:05.330
Effizienzverlusten kommt, wenn Sie Aufrufe haben, die sehr weit nach

01:06:05.330 --> 01:06:07.810
unten durchgereicht werden müssen, ohne dass etwas passiert.

01:06:08.630 --> 01:06:11.670
Dann würde man besser eine transparente Schichtung nehmen, wo man

01:06:11.670 --> 01:06:15.330
gleich den Aufruf machen kann, anstelle 25 mal delegiert zu werden,

01:06:15.570 --> 01:06:18.990
immer die Parameter runterliefern und dann das Ergebnis wieder

01:06:18.990 --> 01:06:19.490
hochliefern.

01:06:20.410 --> 01:06:22.950
Aber in den meisten Fällen ist das unproblematisch.

01:06:25.070 --> 01:06:26.870
Für Fehlermeldungen ist das das Gleiche.

01:06:26.970 --> 01:06:29.750
Wenn ich dann irgendwo in der Schicht ganz oben bin und eine

01:06:29.750 --> 01:06:32.350
Fehlermeldung von ganz unten bekomme, muss die natürlich durchgereicht

01:06:32.350 --> 01:06:32.650
werden.

01:06:33.470 --> 01:06:37.470
Aber da hilft uns in diesem Falle moderne Programmiersprachen wie zum

01:06:37.470 --> 01:06:41.030
Beispiel Java, die einen Catch-Throw-Mechanismus haben, wo ich das

01:06:41.030 --> 01:06:44.890
nicht machen muss, also explizit auch noch die Fehlerbehandlung

01:06:44.890 --> 01:06:48.470
zurückreichen muss, sondern ich warte hier an einer bestimmten Stelle

01:06:48.470 --> 01:06:51.590
auf einen Fehler und wenn der auftritt, dann springt dieses Stück

01:06:51.590 --> 01:06:53.610
Software an, um den Fehler zu behandeln.

01:06:53.610 --> 01:06:55.130
Egal woher er kommt.

01:06:56.070 --> 01:06:57.650
Das macht es also sehr praktisch.

01:07:01.190 --> 01:07:01.870
Okay, gut.

01:07:02.710 --> 01:07:04.070
Hier sind ein paar Beispiele.

01:07:04.270 --> 01:07:06.270
Da gibt es die Dreischichtenarchitektur, die habe ich jetzt schon

01:07:06.270 --> 01:07:09.890
dreimal erwähnt, nämlich Benutzer, Schnittstelle, Anwendungskern und

01:07:09.890 --> 01:07:10.430
Datenbank.

01:07:10.870 --> 01:07:13.390
Dann gibt es eine dreistufige Architektur.

01:07:14.130 --> 01:07:17.870
Englisch heißt das jetzt Three-Tier-Architecture, also nichts mit

01:07:17.870 --> 01:07:18.790
Animal zu tun.

01:07:21.550 --> 01:07:23.410
Tier ist einfach ein anderes Wort für Schicht.

01:07:25.290 --> 01:07:27.710
Eine dreistufige Architektur, bei welcher die Schichten auf

01:07:27.710 --> 01:07:29.410
unterschiedlichen Rechnern laufen.

01:07:30.090 --> 01:07:33.550
Wenn Sie also Three-Tier-Architecture hören, dann wissen Sie, da ist

01:07:33.550 --> 01:07:34.310
irgendwas mobil.

01:07:34.770 --> 01:07:37.510
Da gibt es einen Klienten, auf dem läuft unter Umständen die

01:07:37.510 --> 01:07:40.910
Benutzerschicht und einen Dienstgeber, auf dem läuft die

01:07:40.910 --> 01:07:45.710
Anwendungskern - und die Datenhaltung oder Benutzerschicht und

01:07:45.710 --> 01:07:48.530
Anwendungskern sind auf dem einen Gerät und Datenhaltung ist auf dem

01:07:48.530 --> 01:07:49.010
anderen Gerät.

01:07:51.350 --> 01:07:54.430
Also eine dreistufige Architektur oder Three-Tier-Architecture.

01:07:54.930 --> 01:07:57.090
Hier ist zum Beispiel eine vierstufige Architektur.

01:07:57.450 --> 01:07:58.550
Wir haben unten einen Kerner.

01:07:59.850 --> 01:08:01.250
Hier gibt es Grundfunktionen.

01:08:01.830 --> 01:08:05.110
Dann gibt es den Anwendungskern 1, der erweitert die Grundfunktionen

01:08:05.110 --> 01:08:08.050
über zusätzliche Funktionen und schließlich Benutzerschnittstelle.

01:08:08.550 --> 01:08:12.050
Und hier gibt es eine andere Anwendung, die braucht andere

01:08:12.050 --> 01:08:13.270
Zusatzfunktionen.

01:08:13.550 --> 01:08:16.170
Die werden hier drin verwirklicht und dann die Benutzerschnittstelle

01:08:16.170 --> 01:08:16.470
dazu.

01:08:17.490 --> 01:08:23.490
Das wäre zum Beispiel praktisch für eine Programmfamilie oder eine

01:08:23.490 --> 01:08:26.770
Produktlinie mit zwei Ausprägungen.

01:08:27.370 --> 01:08:30.870
Da gibt es den Teil hier, der allen gemeinsam ist.

01:08:31.610 --> 01:08:33.610
Wenn ich also nur einmal implementieren muss.

01:08:38.620 --> 01:08:40.340
Hier kommt noch ein Beispiel, aber das können Sie dann selber

01:08:40.340 --> 01:08:40.700
durchlesen.

01:08:40.800 --> 01:08:42.940
Ich glaube, Sie haben verstanden, was die vier Schichten Architektur

01:08:42.940 --> 01:08:43.160
ist.

01:08:43.720 --> 01:08:45.640
Betriebssystem, die wichtigsten Schichten hatte ich auch schon

01:08:45.640 --> 01:08:46.040
besprochen.

01:08:46.740 --> 01:08:50.200
Protokolltürme bei Datenfernübertragung, Informationssysteme, bauen

01:08:50.200 --> 01:08:54.280
auf Datenbanken auf, sind in der Regel zwei- bis dreischichtig und so

01:08:54.280 --> 01:08:54.520
weiter.

01:08:55.020 --> 01:08:59.240
Ist also sehr, sehr oft benutzt, findet man immer, immer wieder.

01:09:00.320 --> 01:09:02.120
Schichten Architektur, also wichtig.

01:09:03.600 --> 01:09:04.380
Dufig und schichtig.

01:09:06.900 --> 01:09:11.000
Was wir noch brauchen, was etwas mit der Schichten Architektur zu tun

01:09:11.000 --> 01:09:11.740
hat, ist Folgendes.

01:09:12.480 --> 01:09:13.880
Ich zeige es Ihnen am besten am Bild.

01:09:14.500 --> 01:09:21.540
Angenommen, das hier ist eine Schicht, da sind 38 Klassen drin und

01:09:21.540 --> 01:09:25.000
hunderte von Objekten und darüber ist die nächste Schicht, ich habe es

01:09:25.000 --> 01:09:28.580
jetzt nicht als Schicht zusammengefasst, und die macht also Aufrufe in

01:09:28.580 --> 01:09:30.180
diese Schicht rein.

01:09:30.380 --> 01:09:33.620
Und da sagen Sie, das ist mir zu unsicher.

01:09:34.980 --> 01:09:38.020
Die obere Schicht sollte eigentlich nicht jede Komponente hier unten

01:09:38.020 --> 01:09:41.740
ansprechen können, denn das führt unter Umständen zu Fehlern.

01:09:41.740 --> 01:09:44.520
Also setze ich jetzt davor eine Fassade.

01:09:45.860 --> 01:09:51.760
Das heißt, die obere Schicht ruft Aufrufe an, greift auf Aufrufe und

01:09:51.760 --> 01:09:55.120
Objekte zu, und auf Klassen zu, die in der Fassade vorhanden sind.

01:09:55.920 --> 01:10:00.520
Die Fassade tut gar nichts, sie delegiert nur weiter, aber sie liefert

01:10:00.520 --> 01:10:04.540
mir eine definierte und engere Schnittstelle als die hier, die

01:10:04.540 --> 01:10:07.100
hoffentlich alle wichtigen Funktionen enthält und nur die, die

01:10:07.100 --> 01:10:07.940
gebraucht werden.

01:10:07.940 --> 01:10:11.060
Während hier drin natürlich alles Mögliche nach oben geliefert werden

01:10:11.060 --> 01:10:14.720
könnte, was Sie eigentlich als Entwickler hier drin sagen, das sollten

01:10:14.720 --> 01:10:18.020
die Benutzer der Applikationssoftware eigentlich gar nicht benutzen.

01:10:18.440 --> 01:10:20.780
Das können Sie mit einer Fassade verbergen.

01:10:21.940 --> 01:10:24.820
Sie müssen sich also vorstellen, Fassade ist ein Paket, das enthält

01:10:24.820 --> 01:10:30.000
mehrere Klassen, und wenn Sie einen Aufruf machen oder eine Instanz

01:10:30.000 --> 01:10:35.680
bilden, dann reicht die Fassade das einfach durch an die tatsächlich

01:10:35.680 --> 01:10:37.240
benötigten Komponenten.

01:10:42.820 --> 01:10:46.540
Das war also die Fassade, jetzt gehen wir zurück.

01:10:50.460 --> 01:10:53.960
Bereinigt also, oder liefert eine bereinigte oder vereinfachte

01:10:53.960 --> 01:10:54.520
Schnittstelle.

01:10:56.460 --> 01:11:00.540
Ist eine oder mehrere Klassen, die nur zur Verfügung stehen, Elemente

01:11:00.540 --> 01:11:03.620
enthält und an die eigentlichen Elemente in der Schicht delegiert.

01:11:05.820 --> 01:11:07.440
Okay, also eine Verschönerung.

01:11:08.120 --> 01:11:09.580
Soweit so gut, Fragen dazu?

01:11:14.420 --> 01:11:16.940
Okay, nächster, Klient-Dienstgeber.

01:11:17.380 --> 01:11:21.300
Klient-Dienstgeber, Client-Server, ganz einfach, Sie haben einen

01:11:21.300 --> 01:11:24.160
Dienstgeber, der liefert Dienste, und Sie haben einen Klienten, der

01:11:24.160 --> 01:11:27.280
ruft diese Dienste auf, aber der Klient ist auf einem anderen Rechner.

01:11:28.140 --> 01:11:31.520
Das heißt, in der Regel läuft diese Anforderung über ein

01:11:31.520 --> 01:11:34.960
Telekommunikationsnetzwerk, ob das jetzt Funk ist oder Draht, ist

01:11:34.960 --> 01:11:38.680
egal, und es gibt in der Regel mehrere Klienten.

01:11:38.680 --> 01:11:42.920
Klient-Dienstgeber ist also so, dass Sie einen Dienstgeber haben und

01:11:42.920 --> 01:11:46.620
in der Regel mindestens einen Klienten, also normalerweise eben

01:11:46.620 --> 01:11:47.740
beliebig viele.

01:11:49.120 --> 01:11:53.720
Der Dienstgeber hier ist dann meistens so aufgebaut, dass es einzelne

01:11:53.720 --> 01:11:58.680
Prozesse oder Fäden gibt, die nur darauf warten, eine Anfrage zu

01:11:58.680 --> 01:12:01.940
erhalten und sie auszuführen und das Ergebnis zurückzuspielen an den

01:12:01.940 --> 01:12:02.500
Klienten.

01:12:05.980 --> 01:12:10.540
Das könnte man zum Beispiel auch sehen als eine zweistufige

01:12:10.540 --> 01:12:11.240
Architektur.

01:12:12.640 --> 01:12:15.280
Hier ist die erste Stufe, hier ist die zweite Stufe auf

01:12:15.280 --> 01:12:16.320
unterschiedlichen Maschinen.

01:12:21.930 --> 01:12:24.390
Und natürlich kann der Klient, und deswegen siehst du hier auch noch

01:12:24.390 --> 01:12:28.330
einen Stern, kann der Klient es natürlich auch als nötig empfinden,

01:12:28.670 --> 01:12:29.990
mehrere Dienstgeber anzusprechen.

01:12:30.870 --> 01:12:34.370
Zum Beispiel erstmal einen Dienstgeber, um Adressen zu bekommen und

01:12:34.370 --> 01:12:36.750
einen anderen Dienstgeber, um Bankdetails zu bekommen und einen

01:12:36.750 --> 01:12:41.790
dritten Dienstgeber, um eine Banktransaktion durchzuführen.

01:12:46.650 --> 01:12:50.170
Der Enddienstgeber wird also oft benutzt bei Datenbanksystemen auch.

01:12:50.270 --> 01:12:53.570
Das Frontend ist die Benutzeroberfläche für den Benutzer und das

01:12:53.570 --> 01:12:56.130
Backend die Datenbankzugriffe.

01:12:59.430 --> 01:13:02.990
Ihr Klient führt eine Vorverarbeitung, nimmt aus der Eingaben entgegen

01:13:02.990 --> 01:13:07.450
und gibt die Ausgaben zurück natürlich, verarbeitet unter Umständen

01:13:07.450 --> 01:13:12.850
die Eingaben schon vor, packt sie zusammen und der Dienstgeber führt

01:13:12.850 --> 01:13:17.830
die Datenverwaltung aus, sichert die Datenkonsistenz, führt

01:13:17.830 --> 01:13:19.150
Sicherheitsfunktionen durch.

01:13:22.830 --> 01:13:24.810
In der Regel auf unterschiedlichen Maschinen.

01:13:24.810 --> 01:13:28.250
Es läuft natürlich auch, und das gerade zu Testzwecken, ganz

01:13:28.250 --> 01:13:30.970
praktisch, auch auf einer einzigen Rechner der Klient und der

01:13:30.970 --> 01:13:32.970
Dienstgeber auf einem einzelnen Rechner funktioniert auch.

01:13:33.330 --> 01:13:35.830
Die kommunizieren dann halt über diese Protokolle, was etwas

01:13:35.830 --> 01:13:37.990
ineffizient ist, aber es würde funktionieren.

01:13:39.650 --> 01:13:42.130
Ein FTP-Dienstgeber ist auch so etwas.

01:13:42.410 --> 01:13:46.230
Ein FTP-Server, zum Beispiel FileZilla, initiiert das Übertragen einer

01:13:46.230 --> 01:13:46.670
Datei.

01:13:47.510 --> 01:13:51.910
Der Dienstgeber reagiert auf die Anfrage des Klienten und empfängt

01:13:51.910 --> 01:13:52.390
bzw.

01:13:52.390 --> 01:13:56.870
sendet die Datei, ob das jetzt eine Bilddatei ist für Instagram oder

01:13:56.870 --> 01:13:58.630
sonst etwas, ist genau so aufgebaut.

01:14:04.310 --> 01:14:06.070
Klient-Dienstgeber, ganz einfach.

01:14:07.910 --> 01:14:10.710
Eng verwandt damit sind die sogenannten Partnernetze.

01:14:11.510 --> 01:14:13.650
Bei Klient-Dienstgeber hatten wir zwei unterschiedliche Rollen,

01:14:13.750 --> 01:14:16.670
nämlich der Anbieter eines Dienstes und der Klient.

01:14:17.430 --> 01:14:21.490
Bei Partnernetzen oder Englisch Peer-to-Peer, also Netze unter

01:14:21.490 --> 01:14:25.910
Gleichgestellten, ein Peer ist ein Gleichgestellter, Gleichaltriger.

01:14:27.530 --> 01:14:30.690
In der Schule steht man unter Peer-Pressure, der Druck der

01:14:30.690 --> 01:14:31.410
Gleichaltrigen.

01:14:34.070 --> 01:14:36.410
Partnernetze sind alle Systeme gleichberechtigt.

01:14:36.670 --> 01:14:39.270
Das heißt, sie sind sowohl Klient als auch Dienstgeber.

01:14:39.930 --> 01:14:42.330
Sie müssen sowohl Dienstgeberfunktion als auch Klientenfunktion

01:14:42.330 --> 01:14:42.790
ausführen.

01:14:43.710 --> 01:14:50.030
Das heißt, man könnte auch sagen, der Partner muss, da brauche ich

01:14:50.030 --> 01:14:52.530
mehrfach Vererbungen aus dem Klient und dem Dienstgeber draus zu

01:14:52.530 --> 01:14:52.730
machen.

01:14:53.010 --> 01:14:56.750
Wir wissen ja, dass das in Java nicht möglich ist, aus gutem Grunde,

01:14:56.970 --> 01:15:02.110
aber zumindest die Schnittstellen müsste ich an den Partner vererben.

01:15:02.510 --> 01:15:06.110
Wenn ich sie einzeln definiert hätte, ich kann das natürlich als UML

01:15:06.110 --> 01:15:09.390
-Diagramm auch so aufstellen, der Partner, Sie erinnern sich, ich

01:15:09.390 --> 01:15:15.130
hatte hier den Anforderer und den Anbieter und dann ist das natürlich

01:15:15.130 --> 01:15:16.990
hier zu einer Schleife verkommen.

01:15:18.610 --> 01:15:22.390
Anbieter und Anforderer gleichzeitig sein, für andere natürlich auch.

01:15:25.490 --> 01:15:28.870
Der Klientendienstgeber hat also seinen Dienstgeber irgendwo und die

01:15:28.870 --> 01:15:29.630
Klienten greifen zu.

01:15:29.770 --> 01:15:34.030
Partnernetze können sich beliebig unterhalten und jeder hat sowohl

01:15:34.030 --> 01:15:36.250
Dienstgeber als auch Klientenfunktionalität.

01:15:37.310 --> 01:15:43.450
Was natürlich bedeutet, es gibt keine zentrale Kontrolle, die gab es

01:15:43.450 --> 01:15:43.710
hier.

01:15:45.610 --> 01:15:49.930
Die gibt es natürlich hier nicht mehr, ich muss das anderweitig lösen.

01:15:53.290 --> 01:15:56.630
Ich muss das Gesamtverhalten des Systems so bauen, dass es sich selbst

01:15:56.630 --> 01:16:00.710
organisiert, aus der Interaktion zwischen den einzelnen Partnern.

01:16:01.450 --> 01:16:07.090
Und die einzelnen Partner treffen ihre Entscheidung autonom und

01:16:07.090 --> 01:16:08.070
verhalten sich autonom.

01:16:08.330 --> 01:16:11.530
Sie können sich zum Beispiel abschalten, den Rechner ausschalten,

01:16:11.650 --> 01:16:14.210
zuklappen, nach Hause gehen und es wäre so ein Peer-to-Peer-Netzwerk

01:16:14.210 --> 01:16:16.510
drin, dann fehlt plötzlich ein Knoten.

01:16:16.590 --> 01:16:21.370
Das heißt wiederum, dass die einzelnen Partner unzuverlässig sind und

01:16:21.370 --> 01:16:24.970
ich brauche Mechanismen, um diese Unzuverlässigkeit auszugleichen.

01:16:26.330 --> 01:16:30.350
Das mache ich in der Regel so, dass alle Daten, die in dem Partnernetz

01:16:30.350 --> 01:16:34.530
gespeichert sind, jeweils an mehreren Partnern gleichzeitig zur

01:16:34.530 --> 01:16:37.230
Verfügung sind, um die Wahrscheinlichkeit, dass die Daten nicht zur

01:16:37.230 --> 01:16:39.270
Verfügung sind, zu reduzieren.

01:16:42.910 --> 01:16:44.170
Redundanz brauche ich also.

01:16:46.430 --> 01:16:50.590
Und natürlich, je größer dieses Netz ist und je höher die Redundanz,

01:16:50.690 --> 01:16:52.390
desto unwahrscheinlicher ist ein Ausfall.

01:16:53.030 --> 01:16:57.130
Aber das bedeutet auch, wenn ich Daten an mehreren Stellen vorhalten

01:16:57.130 --> 01:17:02.310
muss, wenn zum Beispiel der hier neue Daten einspielt, dann muss ich

01:17:02.310 --> 01:17:04.030
sie an mehrere Stellen verteilen.

01:17:04.270 --> 01:17:06.970
In diesem Netz wahrscheinlich zumindest an zwei, wenn nicht sogar an

01:17:06.970 --> 01:17:07.210
drei.

01:17:09.150 --> 01:17:15.490
Und kennen Sie natürlich auch, BitTorrent ist so ein Netzwerk, da

01:17:15.490 --> 01:17:18.430
können Sie Ihren Rechner als Dienstgeber, als auch als Klient

01:17:18.430 --> 01:17:20.130
anbieten.

01:17:22.690 --> 01:17:28.170
Sie können Dateien anfordern, Sie können Dateien zwischenspeichern und

01:17:28.170 --> 01:17:30.370
Sie können Dateien weiterleiten, weitergeben.

01:17:34.330 --> 01:17:38.050
Auf Netzwerkebene, übrigens auf TCP, IP gibt es so eine ähnliche

01:17:38.050 --> 01:17:38.610
Situation.

01:17:39.410 --> 01:17:43.130
Da werden die Daten eben anwendungsabhängig auf mehrere Kanäle

01:17:43.130 --> 01:17:43.670
verteilt.

01:17:45.090 --> 01:17:48.930
Domain Name Server sind auch ein Netzwerk von Partnern eigentlich, das

01:17:48.930 --> 01:17:56.970
DNS, die Teile der Abbildung von Namen auf IP-Adressen vorhalten, aber

01:17:56.970 --> 01:18:01.110
mehrere dieser Server vorhanden sind, genau um diese Ausfallsicherheit

01:18:01.110 --> 01:18:01.590
zu bekommen.

01:18:02.090 --> 01:18:05.650
Auch das ist ein DNS-Netzwerk, ist ein Peer-to-Peer-Netz.

01:18:11.760 --> 01:18:17.500
Also alles relativ klar, denke ich, aber wenn Sie Fragen haben, dann

01:18:17.500 --> 01:18:18.520
stellen Sie mir die Fragen.

01:18:24.820 --> 01:18:25.660
Wir sind gleich soweit.

01:18:26.000 --> 01:18:26.720
Wir haben noch zehn Minuten.

01:18:29.100 --> 01:18:35.060
Die Datenablage, das englische Repository oder auf Französisch Depot.

01:18:37.400 --> 01:18:41.940
Das ist eigentlich, könnte man sagen, ein spezielles Klient

01:18:41.940 --> 01:18:42.720
-Dienstgeber -Modell.

01:18:43.440 --> 01:18:47.480
Da haben Sie eine Datenablage und Subsysteme, die auf die Datenablage

01:18:47.480 --> 01:18:48.080
zugreifen.

01:18:48.700 --> 01:18:53.160
Von den Subsystemen gibt es viele und diese Subsysteme interagieren

01:18:53.160 --> 01:18:54.640
über die Datenablage hinweg.

01:18:54.640 --> 01:18:58.760
Beim Klient-Dienstgeber ist es so, dass die Klienten eigentlich völlig

01:18:58.760 --> 01:19:02.840
voneinander unabhängig sind, aber ich kann auch ein solches System

01:19:02.840 --> 01:19:06.340
bauen, wo ich eine Datenbank habe, dort von verschiedenen

01:19:06.340 --> 01:19:14.900
Teilnehmenden -Systemen Daten ablege und damit also auch Kommunikation

01:19:14.900 --> 01:19:17.140
unter den einzelnen Subsystemen erreichen kann.

01:19:23.030 --> 01:19:27.550
Wenn diese Subsysteme auf die Datenablage zugreifen, zum Beispiel mit

01:19:27.550 --> 01:19:32.710
den Fugen erzeuge, setze, hole, suche, dann kann es sein, dass das

01:19:32.710 --> 01:19:35.510
gleichzeitig passiert und dann muss ich diese Gleichzeitigkeit in den

01:19:35.510 --> 01:19:36.090
Griff bekommen.

01:19:36.870 --> 01:19:40.550
Dazu gibt es Mechanismen verschiedener Art, da kann ich zum Beispiel

01:19:40.550 --> 01:19:44.550
Teile der Daten sperren, dass ich sage, ich sperre einen Bereich

01:19:44.550 --> 01:19:47.490
meiner Daten, bis sie aktualisiert sind, und gebe sie dann wieder zum

01:19:47.490 --> 01:19:48.150
Zugriff frei.

01:19:49.330 --> 01:19:52.970
Oder es gibt einen wesentlich komplexeren Mechanismus, das ist der

01:19:52.970 --> 01:19:56.970
Transaktionsmechanismus, der sagt, wenn immer ich eine Änderung

01:19:56.970 --> 01:20:01.010
durchführe in der Datenablage, die mehrere Datenelemente betrifft,

01:20:02.450 --> 01:20:05.310
dann führe ich das in einer Transaktion auf und die hat die

01:20:05.310 --> 01:20:08.250
Eigenschaft, dass es von außen so aussieht, dass wenn es mehrere

01:20:08.250 --> 01:20:12.370
Anfragen gleichzeitig gibt, als ob sie hintereinander ausgeführt

01:20:12.370 --> 01:20:19.370
worden wären, wobei der Transaktionsmechanismus eine Optimierung

01:20:19.370 --> 01:20:24.050
enthält, die sagt, wenn sich aber zwei Transaktionen nicht ins Gehege

01:20:24.050 --> 01:20:28.210
kommen, das heißt unterschiedliche Daten bearbeiten, dann kann ich sie

01:20:28.210 --> 01:20:32.110
ja auch gleichzeitig laufen lassen und ein Transaktionsmechanismus

01:20:32.110 --> 01:20:35.950
würde gerade das feststellen, er würde zum Beispiel zunächst mal

01:20:35.950 --> 01:20:39.050
annehmen, dass alles gleichzeitig laufen darf, aber während des

01:20:39.050 --> 01:20:42.450
Laufens dann feststellt, dass es Überlappungen der zugegriffenen Daten

01:20:42.450 --> 01:20:45.690
gibt und dann eine der beiden Transaktionen, die zu der Überlappung

01:20:45.690 --> 01:20:51.830
geführt haben, anhält, zurücksetzt und nachher noch einmal startet.

01:20:55.170 --> 01:20:57.870
Aber Transaktionen werden wir hier nicht näher besprechen.

01:20:58.370 --> 01:21:02.310
Über Transaktionen werden Sie zum einen in Datenbankvorlesungen

01:21:02.310 --> 01:21:06.190
ausführlichst informiert, wie man Transaktionen verwirklicht.

01:21:07.670 --> 01:21:12.950
Es gibt auch sogenanntes Software Transactional Memory, also einen

01:21:12.950 --> 01:21:14.590
transaktionalen Hauptspeicher.

01:21:15.350 --> 01:21:16.990
Das ist eine relativ neue Erfindung.

01:21:19.310 --> 01:21:22.090
Da behandeln Sie den Hauptspeicher eines Rechners nicht ins

01:21:22.090 --> 01:21:25.230
Plattenlaufwerk, sondern den Hauptspeicher eines Rechners wie ein

01:21:25.230 --> 01:21:27.250
System, in dem Sie Transaktionen durchführen müssen.

01:21:30.010 --> 01:21:33.890
Und davon können Sie eine Vorlesung bei uns hören, nämlich in der

01:21:33.890 --> 01:21:38.570
Vorlesung über Multicore-Rechner und Rechnerbündel.

01:21:38.950 --> 01:21:43.450
Da werden Software Transaktionaler Speicher behandelt.

01:21:45.010 --> 01:21:47.930
Zunächst einmal merken Sie sich jetzt für diese Vorlesung, dass Sie

01:21:47.930 --> 01:21:51.490
der Datenablage dafür sorgen müssen, dass es keine inkonsistenten

01:21:51.490 --> 01:21:54.970
Zustände gibt, wenn ich mehrere Subsysteme habe, die die Datenablage

01:21:54.970 --> 01:21:56.130
gleichzeitig bearbeiten.

01:21:58.850 --> 01:22:01.490
Okay, das war die Datenablage.

01:22:04.030 --> 01:22:05.070
Datenablagenbeispiel.

01:22:06.190 --> 01:22:11.550
Ein ganz anderes Beispiel, das sogar ohne Fernzugriff auskommt, und

01:22:11.550 --> 01:22:17.790
das wäre das Beispiel eines Übersetzers, also ein Java-Übersetzer oder

01:22:17.790 --> 01:22:18.970
C++ -Übersetzer.

01:22:20.630 --> 01:22:24.090
Da haben Sie in der Regel für den Übersetzer eine ganz wichtige Ablage

01:22:24.090 --> 01:22:26.610
oder auch zentrale Datenstruktur, könnte man sagen.

01:22:27.150 --> 01:22:28.870
Und das ist die sogenannte Symboltabelle.

01:22:29.670 --> 01:22:32.890
Die Symboltabelle wird festgehalten für jeden Bezeichner, was der

01:22:32.890 --> 01:22:33.850
Bezeichner bedeutet.

01:22:35.050 --> 01:22:40.730
Ist es ein Klassenname, ist es eine Variablenname, ist es ein

01:22:40.730 --> 01:22:42.950
Objektname, was ist es?

01:22:43.330 --> 01:22:45.150
Das wird in der Symboltabelle festgehalten.

01:22:45.570 --> 01:22:49.950
Wir wissen ja auch, wenn Sie einen Bezeichner nehmen, der kann

01:22:49.950 --> 01:22:50.750
überladen sein.

01:22:51.270 --> 01:22:53.830
Das heißt, die Symboltabelle muss auch mit dem Überladen fertig

01:22:53.830 --> 01:22:58.550
werden, dass es für einen Bezeichner mehrere Bedeutungen gibt, mehrere

01:22:58.550 --> 01:22:59.330
Zuordnungen.

01:22:59.810 --> 01:23:01.230
Also das macht die Symboltabelle.

01:23:03.010 --> 01:23:05.250
Dann gibt es den sogenannten Strukturbaum.

01:23:05.390 --> 01:23:09.010
Der Strukturbaum ist ein Baum, das Gesamtstruktur eines Programmes.

01:23:09.010 --> 01:23:15.430
Man würde also sagen, Name der Klasse, dann welche Methoden gibt es in

01:23:15.430 --> 01:23:16.610
der Klasse für jede Methode.

01:23:16.870 --> 01:23:21.090
Den Beweis auf die Symboltabelle, da steht der Name drin, dann eine

01:23:21.090 --> 01:23:24.390
Struktur, die mir angibt, wie viele Parameter die Methode hat, dann

01:23:24.390 --> 01:23:29.430
den Rückgabetyp, dann eine Anweisung nach der anderen.

01:23:29.870 --> 01:23:31.410
Das steht im Strukturbaum.

01:23:32.050 --> 01:23:35.010
Das schreiben Sie normalerweise als Text hin, um es dem Rechner zu

01:23:35.010 --> 01:23:35.570
beschleunigen.

01:23:35.570 --> 01:23:40.530
Bei der Übersetzung wird eben eine konzentrierte, vernetzte Struktur

01:23:40.530 --> 01:23:41.130
aufgebaut.

01:23:42.630 --> 01:23:45.810
Aber auch das ist auch in dieser Ablage, die der Übersetzer braucht.

01:23:46.930 --> 01:23:50.210
Und da gibt es mehrere Komponenten, die diese Ablage zum Teil

01:23:50.210 --> 01:23:51.670
aufbauen, zum Teil benutzen.

01:23:52.310 --> 01:23:57.310
Also zum Beispiel die Syntaxanalyse und die lexikalische Analyse, die

01:23:57.310 --> 01:23:59.730
bauen die Strukturbaum- und die Symboltabelle auf.

01:24:00.670 --> 01:24:02.650
Die entziffern gewissermaßen ihr Programm.

01:24:02.650 --> 01:24:06.730
Von der Syntaxanalyse bekommen sie zum Beispiel ihre Syntaxfehler.

01:24:07.430 --> 01:24:11.050
Das kommt hier aus der Syntaxanalyse und die baut den Strukturbaum und

01:24:11.050 --> 01:24:11.730
die Symboltabelle.

01:24:13.070 --> 01:24:16.210
Die Semantikanalyse benutzt auch den Strukturbaum, die sagt nämlich,

01:24:16.750 --> 01:24:19.030
naja, ist die Zuweisung richtig?

01:24:19.870 --> 01:24:24.150
Ist es okay, ein Big Integer auf ein Integer zuzuweisen und wird Ihnen

01:24:24.150 --> 01:24:27.350
dann einen semantischen Fehler melden, wenn es nicht richtig ist.

01:24:28.290 --> 01:24:31.470
Dann gibt es den Optimierer und den Coderzeuger.

01:24:31.470 --> 01:24:34.830
Der Coderzeuger ist klar, der nimmt den Strukturbaum her und erzeugt

01:24:34.830 --> 01:24:41.310
JVM -Befehle und der Optimierer wandelt sie um, sodass sie mit weniger

01:24:41.310 --> 01:24:43.070
Befehlen oder schnelleren Befehlen auskommen.

01:24:46.230 --> 01:24:50.770
Die wandeln also um, der hier analysiert, die beiden bauen auf, die

01:24:50.770 --> 01:24:54.270
hier wandeln um und es gibt noch weitere Programme, die sie damit

01:24:54.270 --> 01:24:57.070
benutzen werden, wenn sie einen Debugger aufrufen, um Fehler zu

01:24:57.070 --> 01:24:59.870
finden, da braucht der natürlich die Symboltabelle.

01:24:59.870 --> 01:25:03.290
Wenn sie sagen, zeigen wir den Wert der Variable X, dann muss der in

01:25:03.290 --> 01:25:07.130
der Symboltabelle nachschauen, keine Ahnung, welches X er gemeint

01:25:07.130 --> 01:25:10.550
haben könnte, aber die Symboltabelle weiß das und dann kann er mit

01:25:10.550 --> 01:25:14.290
entsprechender Information aus der Symboltabelle diese Variable auch

01:25:14.290 --> 01:25:14.550
finden.

01:25:14.870 --> 01:25:16.350
Das könnte also der Source Debugger machen.

01:25:16.870 --> 01:25:23.710
Und ein Struktureditor ist einer, der ähnlich wie in Eclipse bereits

01:25:23.710 --> 01:25:30.190
die Syntax der Sprache kennt, anstelle nur eine reine Folge von

01:25:30.190 --> 01:25:33.550
Zeichen zu sehen, der Struktureditor arbeitet natürlich auch auf einem

01:25:33.550 --> 01:25:36.490
Strukturbaum und einer Symboltabelle.

01:25:37.730 --> 01:25:41.710
Das wäre also auch ein Beispiel für eine Datenablage, nämlich hier der

01:25:41.710 --> 01:25:44.210
Strukturbaum und die Symboltabelle in einem Übersetzer,

01:25:44.390 --> 01:25:47.390
beziehungsweise Debugger oder Struktureditor.

01:25:49.870 --> 01:25:51.330
Ganz interessant, finde ich.

01:25:55.530 --> 01:25:56.470
Wir sind gleich so weit.

01:25:57.290 --> 01:25:58.190
Model-View-Controller.

01:26:00.250 --> 01:26:01.990
Das ist jetzt etwas komplizierter.

01:26:03.550 --> 01:26:06.350
Nochmal kurz tief Luft holen, Model-View-Controller.

01:26:06.750 --> 01:26:10.370
Model-View-Controller, das sind die drei Komponenten, die in diesem

01:26:10.370 --> 01:26:12.070
Architekturstil verwandt werden.

01:26:12.930 --> 01:26:17.910
Und zwar, der einfachste Teil des Model-View-Controllers ist die View

01:26:17.910 --> 01:26:18.650
oder die Sicht.

01:26:19.450 --> 01:26:21.290
Die gibt Ihnen eine Datenstruktur wieder.

01:26:22.910 --> 01:26:26.210
Dann gibt es das Model oder das Modell oder die zentrale

01:26:26.210 --> 01:26:28.810
Datenstruktur, die ist ähnlich wie bei der Drei-Schichten-Architektur,

01:26:28.830 --> 01:26:31.770
da wo die Daten sitzen, und die Kernfunktionalität.

01:26:32.670 --> 01:26:33.610
Das nennen Sie Model.

01:26:34.370 --> 01:26:39.410
Und Sie haben jetzt die Situation, wie wir vorhin auch hatten, dass

01:26:39.410 --> 01:26:44.650
diese Datenstruktur sich ändern kann und damit unter Umständen sich

01:26:44.650 --> 01:26:46.230
die Sicht anpassen muss.

01:26:47.450 --> 01:26:54.810
Stellen Sie sich vor, in dem Model sind irgendwie Daten, die Sie

01:26:54.810 --> 01:26:59.690
anzeigen wollen, als Balkendiagramm mit 25 Balken.

01:27:00.130 --> 01:27:03.250
Die entsprechenden Prozentsätze, gerade für die Wahl zum Beispiel,

01:27:03.370 --> 01:27:08.430
haben Sie einen Viewer, der gibt Ihnen an, wie viel die SPD, die CDU

01:27:08.430 --> 01:27:10.690
und die FDP an Prozent hatten.

01:27:11.310 --> 01:27:12.290
Das zeigen Sie an als Balkendiagramm.

01:27:12.290 --> 01:27:16.070
Aber das Modell selbst, innen drin, enthält natürlich nur die Zahl.

01:27:18.110 --> 01:27:19.370
Das wäre als der Viewer.

01:27:19.630 --> 01:27:23.390
Und dann gibt es den Controller, und der Controller steuert die

01:27:23.390 --> 01:27:24.130
Interaktion.

01:27:25.190 --> 01:27:30.460
Der sagt, ob Sie die Farben ändern können, zum Beispiel der Balken,

01:27:30.930 --> 01:27:34.670
oder die Zuordnung irgendwelcher Bezeichner zu den Balken, oder ob Sie

01:27:34.670 --> 01:27:36.990
oben drüber die Prozentzahl anzeigen wollen oder nicht.

01:27:37.910 --> 01:27:40.290
Das ist der Controller, der steuert die Interaktion.

01:27:42.510 --> 01:27:43.110
Genau.

01:27:44.290 --> 01:27:52.410
Wenn Sie denken, Sie müssen so eine Komponente bauen, dann würde man

01:27:52.410 --> 01:27:55.230
als erstes einfach eine große Komponente und all dieses Zeug

01:27:55.230 --> 01:27:56.050
reinstopfen.

01:27:58.670 --> 01:28:02.890
Aber Sie überlegen sich dann, mit diesem Balkendiagramm, das war

01:28:02.890 --> 01:28:06.310
ziemlich viel Arbeit, würde ich gerne woanders in der nächsten Wahl

01:28:06.310 --> 01:28:10.830
auch wieder benutzen können, oder einem ganz anderen Beispiel, dann

01:28:10.830 --> 01:28:12.330
würden Sie die Dinge gerne trennen.

01:28:14.130 --> 01:28:18.470
Dass Sie nämlich den Gesicht oder die View separat haben vom Modell.

01:28:22.330 --> 01:28:24.330
Deswegen auch Model, View, Controller.

01:28:24.770 --> 01:28:25.730
Das haben wir jetzt besprochen.

01:28:27.470 --> 01:28:31.830
Das Diagramm selbst, das sind meistens Pakete, das soll ein Paketbild

01:28:31.830 --> 01:28:32.130
sein.

01:28:32.130 --> 01:28:34.430
Dann gibt es den Controller, den View, den Model.

01:28:34.770 --> 01:28:38.070
Das Model hat einen Controller hoffentlich, der Controller hat ein

01:28:38.070 --> 01:28:39.130
Model, das ist klar.

01:28:40.630 --> 01:28:45.090
Das Modell ist zum einen ein Melder und hat einen Opponenten, das ist

01:28:45.090 --> 01:28:45.490
die View.

01:28:46.190 --> 01:28:49.810
Und da lassen wir zu, dass es mehrere dieser Views oder Sichten oder

01:28:49.810 --> 01:28:50.530
Anzeigen gibt.

01:28:50.710 --> 01:28:53.710
Deswegen hier ein Stern, für den Controller genauso, hier ein Stern,

01:28:53.930 --> 01:28:56.510
aber die View wird nur von einem Controller gesteuert.

01:28:57.270 --> 01:29:01.810
Ja, wir haben also diese drei Komponenten.

01:29:01.870 --> 01:29:04.110
Das ist übrigens ein sehr berühmtes, bekanntes Modell.

01:29:04.450 --> 01:29:06.770
Wer von Ihnen hat MVC schon mal gehört, vielleicht?

01:29:08.090 --> 01:29:12.290
Sehr gut, sehen Sie, das ist bekannt, ausgezeichnet.

01:29:15.910 --> 01:29:20.690
Wir müssen jetzt noch ein paar Kleinigkeiten klären, nämlich die

01:29:20.690 --> 01:29:22.530
bekanntgearbeitete Änderung im Datenmodell.

01:29:22.530 --> 01:29:26.970
Das geht über eine bestimmte Redaktion, das heißt Entwurfsmuster

01:29:26.970 --> 01:29:27.550
Beobachter.

01:29:27.990 --> 01:29:28.490
Ich bin gleich fertig.

01:29:30.010 --> 01:29:32.390
Den betrachten wir uns noch genauer später.

01:29:36.530 --> 01:29:41.310
In der Regel werden Präsentation und Schaltflächen, also die Sicht und

01:29:41.310 --> 01:29:44.110
der Controller in einer Oberfläche zusammengefasst.

01:29:45.050 --> 01:29:48.410
Daher kann man sie grafisch nicht sehr genau unterscheiden.

01:29:48.890 --> 01:29:51.610
Es kann aber auch eine zusätzliche Interaktion geben zwischen der

01:29:51.610 --> 01:29:53.070
Steuerung und der Präsentation.

01:29:54.990 --> 01:29:58.390
Ich kann also mit dem MVC das Modell wiederverwenden, in einem anderen

01:29:58.390 --> 01:30:00.330
Kontext, ohne die Benutzerschnittstelle.

01:30:00.750 --> 01:30:03.910
Ich kann die Benutzerschnittstelle, die grafische Anzeige,

01:30:04.030 --> 01:30:07.350
wiederverwenden, in einem anderen Kontext, ohne das gleiche Modell.

01:30:08.150 --> 01:30:08.670
Genau.

01:30:10.310 --> 01:30:11.310
Und da hören wir auf.

01:30:12.170 --> 01:30:12.670
Dankeschön.

