So, was machen wir hier? Die Veranstaltung SD3 ist Teil
des Softwareentwicklungszykluses, den unser Fachbereich für die verschiedenen Studiengänge anbietet.
Der dritte Teil dieses Zykluses ist zweigeteilt. Einerseits in das Programm Logikprogrammierung,
dass das, was jetzt stattfindet und in dem Slot davor
hat Frau Dreschler die funktionale Programmierung behandelt.
Gleich zu Beginn will ich möchte mit einer kleinen demografischen Umfrage anfangen.
Wer von Ihnen hat schon die funktionale Programmierung absolviert
Bitte? Okay. Okay, gut, also wer hat es schon gemacht?
Vergangenheit, ja? Gut, wer ist gerade dabei, das zu machen?
Okay, dann wird dieses Angebot offensichtlich sehr gut angenommen.
Früher war das alternativ, man konnte das eine machen oder das andere machen.
Das zeigt sich auch bis heute noch im Veranstaltungskonzept.
Da müssen wir das vermutlich mal irgendwann überdenken. Dadurch,
dass das alternativ war, war das Grundkonzept immer so,
dass wir den größten Teil der Veranstaltung,
also so ungefähr elf Termine, dem wir jeweiligen Hauptparadigma gewittet haben.
Also in unserem Fall der Logikprogrammierung und dann drei Termine oder
zweieinhalb Termine oder wie auch immer die Zeit hinkam,
dem jeweils anderen Paradigma gewidmet haben.
Sodass man also zwei Fliegen mit einer Klappe schlagen kann in
einem und zwar dem Hauptparadigma, sie dahin zu bringen,
dass sie auch aktiv in der Lage sind,
Software in diesem Rahmen zu entwickeln.
Und in dem zweiten Paradigma passive Kenntnisse zu vermitteln.
Ich werde das zum Schluss dann so machen,
dass wir mit den Mitteln der Logikprogrammierung einen Interpreter fürs Geam schreiben und dadurch erstens kennenlernen,
wie man Metaprogrammierung in der Logikprogrammierung machen kann.
Und zweitens, aus dieser Sicht der Implementierung die Grundkonzepte der
funktionalen Programmierung nochmal Revue passieren lassen kann.
Wenn ich davon ausgehen kann, dass 80 Prozent,
nein, es waren mehr, deutlich mehr als 90 Prozent,
bereits die funktionale Programmierung absolviert haben oder die es gerade tun,
kann ich mich dort natürlich entsprechend kurz fassen.
Gut, ich nehme an, Sie haben SE1,
SE2 alle absolviert. Da geht es um Zustands- und objektorientierte
Programmierung und dann in SE3 dieser Split
Üblicherweise gibt es auch Praktika zu den verschiedenen Veranstaltungen.
In diesem Jahr sind wir leider nicht in der Lage,
unser Logikprogramm aus, was heißt in diesem Jahr,
zu diesem Zyklus, sind wir nicht in der Lage,
das Logikprogrammierungspraktikum anzubieten,
weil wir einfach nicht mehr die Lehrkapazität dafür haben.
Ich hoffe, dass wir das im Jahr drauf wieder machen können.
Aber das hängt natürlich von verschiedenen Rahmenbedingungen ab,
auf die ich wenig Einfluss habe. Worum geht es hier
? Sie sollen ein alternatives Programmierparadigma kennenlernen. Ach so,
ja, und da gleich die Frage vorneweg,
ist das für Sie überhaupt alternativ?
Ja oder nein? Also wer ist schon mal mit Logikprogrammierung
im Rahmen des Schulunterrichts beispielsweise in Berührung gekommen
Oh, das sind doch erstaunlich wenige. Gut,
dann ist es also tatsächlich für die Masse der Teilnehmer hier
ein alternatives Programmierparadigma. Und ich sage es gleich vorneweg,
es ist die etwas andere Art zu programmieren.
Also jeder Versuch, von den Dingen oder die Denkweise,
die sie bisher gewöhnt sind in der Softwareentwicklung,
eins zu eins auf die Logikprogrammierung übertragen zu wollen, geht daneben.
Ich kann die nur eine Empfehlung geben, lehnen Sie sich entspannt zurück.
Lassen Sie sich auf ein neues Erlebnis ein,
versuchen Sie nicht Ihre Weltsicht auf die Logikprogrammierung draufzudrücken.
Versuchen Sie, die Sicht der Dinge, die ich hier vortrage,
auf sich wirken zu lassen und ein alternatives Paradigma zu lernen.
Und hinterher können sie dann hingehen und die Querbezüge herstellen.
Aber wenn man gleich von Anfang an anfängt, die Querbezüge herzustellen,
wird man scheitern. Das habe ich in vielen Fällen erlebt,
wo Studierende nicht bereit waren, ihre bisher liebgewordene Weltsicht,
die ja nicht falsch ist. Es geht ja darum,
dass man hier mal was anderes kennenlernt und das praktiziert,
was üblicherweise als Thinking Outside the Box bezeichnet wird.
Also mal auszubrechen aus seinem gewohnten Denkschema,
sich auf eine neue Erfahrungswelt einzulassen und hinterher Revue passieren zu lassen,
bringt mir das was oder bringt mir das nichts.
Also zu sehen, dass es auch eine andere Sicht auf
die Dinge der Welt gibt
Ja. Gut, die Logikprogrammierung ist, oder das,
was mir die Sache immer sehr reizvoll macht, ist,
dass sie Grundwerkzeuge des Informatikers in expliziter Form zur Verfügung stellt.
Im Lang der Dinge werden sie mitkriegen,
wir starten mit so etwas wie einer relationalen Datenbank.
Typischerweise ist die Informatikunterricht immer anders aufgebaut. Als erstes befasst man sich damit,
wie man in einer Programmiersprache, früher ist das eben Pascal gewesen,
heutzutage ist es Java oder was auch immer, programmiert.
Und hinterher befasst man sich dann mit relationalen Datenbanken.
Das ist ein den Kopfstellen der Verhältnisse. Denn während die Programmiersprachen
Thuring mächtige Werkzeuge sind, sind die relationalen Datenbanken sehr eingeschränkte Werkzeuge,
die sich auch die relationale Algebra eingeschränkt sind.
Und insofern macht die Informatik hier etwas, was für meine Begriffe widersinnig ist.
Sie fängt mit dem Komplizierten an und geht dann zum Einfachen über.
Jede andere Disziplin geht mal in die Physik in die Chemie und so weiter,
fängt mit dem Einfachen an und geht zum Komplizierten vor.
Und diesen Weg wollen wir hier in der Veranstaltung auch pflegen.
Also wir fangen mit dem einfachen Begriff an und erweitern ihn
dann sukzessive, um immer neue Elemente.
Gleich eine Warnung vorneweg, wenn sie am Anfang den Eindruck haben,
das ist ja alles Pillepalle, ist der Eindruck nicht falsch.
Ich fange mit sehr einfachen Sachen an. Sie werden sich
fragen, was hat das überhaupt mit Programmierung zu tun?
Und wir werden Schritt für Schritt neue Elemente hinzunehmen.
Und wir werden insgesamt nur zwei Schritte machen.
Also der Weg ist nicht sonderlich lang.
Aber der Anstieg der Lernkurve wird sehr steil.
Er ist sehr flach am Anfang, wird dann extrem steil.
Und wenn sie sich am Anfang nicht auf dieser flachen Strecke darauf einlassen,
diese Denkwelt aufzusaugen und in gewisser Weise zu internalisieren,
werden sie den steilen Anstieg nicht schaffen.
Also es ist typischerweise so in dem Augenblick,
wo ich die Rekursion in ihrer vollen Schönheit einführe,
Fühlen die meisten oder haben die meisten von ihnen das Gefühl,
dass der Teppich unter den Füßen weg ist.
Und das kann man vermeiden,
indem man erstmal mit dem elementaren Handwerkzeug sich vertraut macht,
sodass man in der Denkwelt drin ist und dann kann man
den steilen Anstieg auch schaffen.
Gut, also ich hatte damit angefangen, wir steigen ein
mit dem Begriff der relationalen Datenbank und erweitern den sukzessive.
Wir werden eine Operation kennenlernen,
die sich Unifikation nennt und die eigentlich nichts anderes ist
als eine Zweiseitiggericht,
ein zweiseitig gerichtetes Pattern-Matching
Und dies ist eine sehr mächtige Operation,
die angewendet auf die Eintragung einer relationalen Datenbank, wird es,
und deine Zunahme eines Deduktionsschrittes, wird es uns erlauben,
dann Turing mächtiger Programme zu schreiben.
Und auf die Art und Weise haben wir die Grundbausteine
der Informatik in der Hand. Wir können sie beobachten.
Wir haben so etwas wie Nicht-Determinismus an der Hand.
Wer von Ihnen ist vertraut mit Nicht-Determinismus? Also wem ist
das bisher schon mal begegnet?
Wem ist das Wort
Das sind relativ wenige. Das wird eine der zentralen Begriffe der Logikprogrammierung
sein, wo sie sich von dem Gedanken verabschieden müssen.
Es gibt immer nur ein Ergebnis. Sondern es wird typischerweise viele Ergebnisse geben,
im Ernstfall unendlich viele Ergebnisse. Und wir werden lernen müssen,
wie wir mit unendlich vielen Ergebnissen umgehen können,
wie wir die beschreiben können, wie wir damit rechnen können.
Und das hat auch zur Folge,
dass es nicht nur am Ende der Berechnung mehrere Ergebnisse geben kann,
sondern auch zwischendurch mehrere Ergebnisse geben kann,
aus denen der Prolog-Interpreter die richtigen oder angemessenen raussuchen muss.
Und diese Denkungsart, dass ein Rechnungsergebnis nicht immer eindeutig
speziell ist, das ist in der Logikprogrammierung fest eingebaut.
In jedem anderen Paradigma muss ich das implementieren. Hier ist
es der Grundmechanismus der Abarbeitung schlechthin. Und damit muss man
vertraut werden. Und wie man damit vertraut werden kann,
habe ich schon angedeutet,
wir gucken uns erst die einfachen Sachen an und machen kleine Fortschritte,
ehe wir dann die großen Schritte uns vornehmen.
Gut, natürlich, wir reden über Softwareentwicklung.
Im Endeffekt sollen sie in der Lage sein,
programmtechnische Aufgaben zu lösen und Programme selbst zu entwickeln.
Und das ist dann im Wesentlichen Gegenstand der Übungen,
wo es darauf ankommt,
dass sie selbst Lösungen erarbeiten
Und ich habe es schon angedeutet, wir haben viele Werkzeuge
und Grundbegriffe der Informatik hier in expliziter Form in der Hand.
Das heißt also, wir haben eine Brücke zu den formalen Grundlagen der Informatik,
wie sie sonst eigentlich nur in wenigen Programmierparadigmen zur Verfügung steht.
Also für alle Leute, die Schwierigkeiten haben mit den Grundlagen,
mit den formalen Grundlagen der Informatik.
Und da könnte der Weg über die Logikprogrammierung
ein Hilfsmittel sein mit diesen Schwierigkeiten fertig zu werden und sich
etwas mir anzufreunden mit den formalen Grundlagen der Informatik,
weil man hier eben das am lebenden Objekt studieren kann
Man kann ein Programm schreiben und kann sehen, wie verhält sich dieses Programm.
Also wir werden solche Sachen wie reguläre Grammatiken, endliche Automaten und dergleichen.
Wir werden Dinge wie kontextfreie Grammatiken hier als elementares Werkzeug
in die Hand nehmen und damit spielen können. Ja,
und dann können wir an diesen Beispielen uns angucken,
wie verhält sich das,
was sind die Konsequenzen von irgendwelchen Änderungen auf der Modellierungsebene
auf das Verhalten des Systems und so weiter und so fort.
Für mich ist das immer hilfreich gewesen,
wenn es darum ging,
theoretische Konzepte der Informatik verstehen zu müssen
Gut, was haben wir hier alles? Einerseits die Vorlesung,
da sitzen wir gerade, ich werde Konzepte erklären,
Begriffe erklären, ich werde Zusammenhänge, versuchen zwar Deutlichen,
ich werde Beispiele in großer Zahl durchdiskutieren.
Ich erwarte von Ihnen auch, dass Sie im Selbststudium das,
was hier behandelt wird, vertiefen, in der Literatur nachschlagen,
dass Sie technische Details klären, das wird Voraussetzung für die Übung,
insbesondere sein,
dass Sie dann eben in Vorbereitung auf den Übungstermin
auch praktische Programmierübungen absolvieren und dass Sie dies in Lerngruppenarbeit durchführen
Notwendigkeit zur Kommunikation über programmiertechnische Artefakte in der Informatik ist ja, glaube ich, unumstritten.
Und das wollen wir hier auch pflegen, sowohl in den Übungssitzungen selbst,
auch in der Vorbereitung darauf, dass man Lösungsalternativen diskutiert.
Das ist eines der Hauptanliegen, was ich habe. Nie ist es so,
dass es in der Informatik eine Lösung für ein Problem gibt.
Es gibt immer ein ganzes Spektrum von Lösungen. Und die Kunst
des Informatikers besteht darin, diese zu bewerten und zu beurteilen.
Welche ist, aus welcher Sicht besser geeignet als die andere?
Und da gibt es verschiedene Sichten. Man kann das
unter Effizienzgesichtspunkten unter Verständlichkeitsgesichtspunkten unter Komplexitätsgesichtspunkten und so weiter betrachten.
Und solche Diese verschiedenen Sichten auszudiskutieren, das ist Ziel der Übung
auch dabei. Ich werde dann auch in der Übung,
wenn wir dann dazu übergehen,
dass wir keine Muster lösen oder eigentlich das übergehen,
die Übungen sind immer üblicherweise so organisiert,
dass wir keine Musterlösungen veröffentlichen zu den Übungsaufgaben, sondern gut gelungenen Lösungen.
Also Lösungen, die Sie beitragen und wo die Übungsgruppenbetreuer der Meinung sind,
jawohl, hier, das ist gut gemacht,
das ist gut begründet,
was hier gemacht worden ist und so weiter,
dass wir die dann zur Verfügung stellen als Muster für
die Nacharbeitung
Sind wir bei der Übung. Die Übung ist im Gegensatz zu SE1,
SE2, keine Übung am Rechner, sondern wir erwarten jetzt,
dass die Arbeit am Rechner praktisch in der Vorbereitungsphase zur Übungsgruppensitzung passiert.
Die Übungen sind im Wesentlichen dazu da,
um Verständnisprobleme zu klären, um ihre Lösungen vorzustellen,
um Lösungsalternativen zu diskutieren und die am gelungensten Übungen in meiner Erinnerung sind immer diejenigen gewesen,
wo ich sagen konnte,
ich habe hier zwei Lösungen bekommen,
die fand ich richtig gut,
die gucken wir uns mal an und dann habe ich
die Lösung des Professors dagegen gehalten und jetzt vergleichen wir mal
Und wenn dann zum Schluss rausgekommen ist,
dass die Lösung des Professors gar nicht die intelligenteste gewesen ist,
dann fand ich die Übung besonders gut gelungen.
Und dann macht es Spaß, wenn man tatsächlich soweit gekommen ist,
dass man über den Dingen steht und Dinge miteinander vergleichen kann.
Das ist das Ziel des Ganzen. Gut,
und ich bin natürlich immer daran interessiert,
dass ich Ihre Meinung zu dem ganzen Unternehmen hier erfahre,
also Anregungen, Kritik, was sollte man anders machen,
was könnte man besser machen.
Aha, jetzt erst Puten, das ist zu spät.
Ja, die Übungen,
wir haben
sechs Übungsgruppen eingerichtet
Ja, wir haben sechs Übungsgruppen eingerichtet,
die haben sich ein bisschen geändert, weil wir gesehen haben,
dass die Nachfrage nicht ganz mit dem Angebot zusammenpasste.
Deshalb ist die eine Übungsgruppe hier vom Mittwochvormittag,
auf Mittwochnachmittag verlegt worden. Die Zahlen,
die hier hinten stehen, sind die Anzahl der Studierenden,
die sich eingetragen haben für diese Übungsgruppen.
Ich würde mal sagen, wir sind fast gleich verteilt,
also viel besser kriegt man es nicht hin.
Kleine Modifikationen sind durchaus noch möglich. Wer also der Meinung ist,
dass er lieber in einen anderen Termin gehen möchte,
kann dies
mit dem Betreffenden Übungsgruppenbetreuer klären
Aber versuchen sie jetzt nicht in die Übungsgruppen einzudringen,
die bereits eine größere Teilnehmerzahl haben.
Das sind teilweise auch theoretische Angaben, die mit dem Themen anzahlen,
die dann tatsächlich an Studierenden dort auftreten, nicht ganz übereinstimmen müssen.
Also da kann es am Anfang eine Phase des Zurechtrüttelns geben,
bis sie das geklärt hat.
Aber im Prinzip ist das alles nicht in Eisen gegossen,
das kann man modifizieren
Gibt es jemanden, der noch keine Übungsgruppe abgekriegt hat?
Also zwei oder drei Leute haben mir eine Mail geschrieben,
ich habe da keinen Überblick, vier.
Können Sie ganz kurz das Problem nochmal verdeutlichen?
Worum geht es? Stine hat dicht gemacht, ja?
Stine hat keine Vereinigkeit, obwohl in zwei Euro Gruppen halt weiter sind.
Ja, ja, ja, ja, ja,
ja, gut. Aber das macht keinen Sinn,
das über Stine zu klären, das klären wir direkt.
Und das wird dann entsprechend nachgetragen im Studiumbüro.
Können Sie mal kurz angeben, wo Sie hingehen wollten?
Das wird sehr perfekt.
Das Gleiche und ich habe noch zwei Arme gesehen,
wo, aber hier war das ja.
Dienstag, ach, das Ziel. Ja, gut,
das passt auch. Okay, Micha König, das sieht schlecht aus.
Gut, wir haben, aber das kriegen wir hin.
Das sollte machbar sein. Die Probleme sind nicht unüberwindbar. Ja,
wir haben vier Personen, die mit dem Übungsbetrieb beteiligt sind.
Zwei davon sind hier. Das eine ist Micha König,
der sitzt da hinten, Mitarbeiter im Rechenzentrum,
der eine oder andere wird ihn schon mal kennengelernt haben
Der also diese beiden Gruppen hier macht und der zweite bin ich,
Felix Lindner und Timo Baumann sind heute hier nicht anwesend.
Etwas Kryptisches, die Angabe in Stine zu dieser zusätzlichen Übungsgruppe.
Dort steht nämlich P06 und wer sich wundert, was P06 ist.
Hier kommt die Erklärung, es ist Raum Nummer 6 in
Pavillon Nummer 3. Wer damit immer noch nicht zufrieden ist,
hier gibt es einen Lageplan, wo fangen wir an?
Hier unten ist die Bushaltestelle. Hier in diesem Haus ist
der Bäckerladen drin, wo ist die leckeren Brötchen gibt.
Sie gehen hier hinter, sie gehen durch die Pförtnerlogische
hier durch,
schleichen sich an Hinterhaus
D, sorry, Hinterhaus D, links hierher rum,
gehen noch an Haus E vorbei und dieses Haus hier hinten ist Haus P3.
Und in diesem Raum, Haus P3, sollte es einen Raum geben,
der 06 heißt und da findet die Übungsgruppe statt.
Also am äußersten Ende des Campus hier hinten,
das ist die Wasserfilteranlage. Also wenn Sie da gelandet sind,
dann war das ein Überschießen.
Okay,
soviel zu den Übungsgruppen
Die ersten Übungen finden also in der nächsten Woche statt,
weil es wenig Sinn macht, da vorher schon Termine anzusetzen.
Die Übungsaufgaben für diesen Termin liegen hier vorne auf dem Tisch.
Die sind im Wesentlichen, beschränken sich darauf,
dass sie nochmal rekapitulieren, was eigentlich der Begriff Funktion und
was der Begriff Relation in der Mathematik bedeutet.
Denn darauf müssen wir aufbauen und auf diesem Unterschied zwischen Funktionen und Relation
basiert der gesamte Unterschied zwischen dem Funktionalen und relationalen Paradigma.
Und dafür ist wesentlich auch, oder nein, mein Problem besteht darin,
dass sie durch 13 Jahre Schulbildung und vermutlich ein Jahr lang
universitäre Mathematikausbildung, funktional versaut sind.
Die Mathematik hat Ihnen immer ein Bild vorgegaukelt, das Berechnungsergebnisse eindeutig sind.
Das ist das Wesen einer Funktion. Ich kann zu gegebenen
Attribut werden, kann ich immer eindeutig einen Funktionswert ermitteln.
Das definiert eine Funktion. Und das ist ein Vorgaukeln einer
Einfachheit über die Welt, die tatsächlich nicht gegeben ist.
Die Welt ist nicht eindeutig, sie ist hochgradig mehrdeutig.
Und diese Mehrdeutigkeit der Welt wird durch den Relationsbegriff
relativ gut abgefangen
Deshalb müssen wir erst mal überlegen, was heißt es eigentlich
über Relationen zu reden und was unterscheidet Relationen von Funktionen.
Und die zweite Aufgabe besteht dann darin,
dass sie einfach mal ein Prolog-Interpreter in Betrieb nehmen.
Das können sie zu Hause auf ihrem Rechner machen.
Sie können es auch in den Pool rechnen im Informatikum machen.
Die Sinn dieser Übung besteht darin,
dass sie die technischen Schwierigkeiten, die dabei auftreten,
nicht dann haben, wenn es ernst wird.
Das soll also in einem Vor, in einer Vorübung passieren.
Und sie sollen mal darüber spekulieren, was macht dieses System eigentlich so?
Wer also vorher nie ein Logikprogrammierungsprob-System gesehen hat,
wird erst mal ratlos davor stehen,
was passiert dir eigentlich
Und da habe ich ihn auf dem Zettel ein paar Ausdrücke angegeben,
mit denen sie mal anfangen können zu experimentieren.
Und ich habe ihnen ein paar Fragen vorgegeben, wo sie versuchen können,
darüber zu spekulieren, was für Datentypen liegen hier vor,
was machen diese Operatoren und so weiter und so fort.
Und in der Übung können wir uns dann darüber unterhalten,
ob die Schlüsse, die sie daraus gezogen haben,
richtig sind oder nicht richtig sind.
Was ich erreichen will, ist ganz einfach,
dass sie unbefangen an ein solches System herangehen und sich mal überlegen,
welche Eingaben kann ich denn machen und was sagen wir diese Eingaben über das Verhalten des Systems.
Das ist in vielen, das ist ein interaktives System,
das hat also einen Interaktionsprompt, sie kriegen sofort die Antwort darauf,
mehr oder weniger selbsterklärend, aber sie können versuchen,
daraus Schlüsse zu ziehen, was wohl dahinter den Kulissen abgelaufen ist.
Gut, alle weiteren Übungsaufgaben gibt es dann bei uns
auf der Arbeitsbereichsseite oder vielleicht sollte ich lieber Kosten stellen,
Seite neuerdings sagen. Sie hangeln sich am besten durch,
indem sie bei der Informatik auf die Liste der Arbeitsbereiche gehen
und dort den Arbeitsbereich NAZ für natürlich sprachliche Systeme anwählen.
Und da gibt es auf der linken Seite ein Navigationsmenü unter
Lehrveranstaltung oder Courses, ist dort die Logikprogrammierung aufgeführt oder
SC3-Logikprogrammierung steht da
Gut, sie sollen die Aufgaben dann am Rechner unbetreut lösen.
Die Lösungen, die sie erarbeitet haben,
sollen dokumentiert werden und in der Übungsgruppe abgegeben werden,
sollen abgegeben werden und werden dann in der Übungsgruppe diskutiert.
Sie können sich gleich von Anfang an dran gewöhnen,
dass die Abgabe in Form eines ausführbaren Programms passiert.
Das wird auf den ersten beiden Blättern nicht immer so
ohne weiteres klappen. Dann ist auch ein PDF-File angebracht,
aber spätestens ab dem dritten Übungsblatt wird eigentlich nichts anderes als
ausführbare Programme mehr
Notwendig sein und dann macht es keinen Sinn, irgendwelche Textdokumente zu formatieren.
Alles, was man haben will, ist, dass man
ihre Lösung sofort ins System einlesen kann und damit experimentieren kann.
Also die Form der Abgabe wird üblicherweise einkommentiert das Programm sein.
Und in den Kommentaren können sie natürlich alles das reinschreiben,
was notwendig ist, um die Arbeitsweise des Programms zu verstehen,
um das Verhalten zu verstehen und so weiter.
Gut, die Abgabe der Lösung immer elektronisch.
Ansonsten müssten wir vom Papier abtippen, das will keiner machen.
Und ich würde sie auch bitten,
immer schön zu signalisieren, wo sie die Meinung sind,
dass sie die Aufgaben dann auch gerne in der Übungsgruppe
vortragen wollen
Wie gesagt, Arbeit in Lerngruppen ist, äh,
möglich und auch erwünscht. Die Teilnahme an der Übung,
die erfolgreiche Teilnahme, wird durch einen Übungsschein nachgewiesen.
Dieser Übungsschein ist keine Prüfungsvoraussetzung. Er ist aber
eine Studienleistung und sie können das Modul nur abschließen,
wenn sie diese Studienleistung erbracht haben.
Ja, und die Kriterien sind die üblichen regelmäßig aktive Teilnahme.
Da gibt die Universität immer die Maßzahl von 85 Prozent der
Termine vor. Und sie müssen mindestens 50 Prozent der möglichen
Punkte erreichen
Und da in der Vergangenheit oftmals ein Irrtum auch dadurch aufgekommen ist,
dass am Anfang ja die Übungsaufgaben sehr einfach sind und man damit,
ich hatte ja schon angedeutet,
wir fangen mit einer sehr flachen Lernkurve an,
die sich dann aber drastisch steigert,
dass man ja da am Anfang mit den einfachen Übungsaufgaben schon
die 50 Prozent sammeln kann und danach seine Tätigkeit in der Übung einstellt.
Deshalb gibt es also einen Gradienten hier auf der Punktzahl.
Wir fangen also mit einer relativ kleinen Zahl von Punkten an,
zehn eben und wir steigern das dann bis auf 30 Punkte
pro Zettel und das bleibt dann konstant bis zum Ende der Veranstaltung,
sodass man insgesamt 310 Punkte erreichen kann
Von denen braucht man 50 Prozent. Und jeder einzelne,
das gilt jetzt nicht für die Gruppen,
sondern jeder einzelne Teilnehmer ist, wird es erforderlich sein,
dass er mindestens zweimal Lösungsvorschläge vor der Gruppe präsentiert.
Wobei nicht alle Aufgaben für die Präsentation geeignet sind.
Das muss man auch in Rechnung stellen. Die Software,
die wir benutzen, ist das sogenannte SWI-Prolog,
ein Open-Source-System von der Universität von Amsterdam.
Interessanterweise von dem Sozialwissenschaftlichen Institut,
das heißt SWI
Und das kann man sich runterladen. Das gibt es für die verschiedenen Plattformen
. Da können sie das zu Hause installieren und benutzen.
Das hat ein integriertes Objektsystem. Da werden wir mal
einen kleinen Blick reinwerfen. Wir werden auch diskutieren,
warum das Objektsystem nicht so hundertprozentig da drauf passt.
Und alles das, was SWI-Prolog kann, ist ausreichend für diese Lehrveranstaltung.
Wer immer Blut geleckt hat und tiefer in die Materie eindringen
will, dem sei Sixus-Prolog empfohlen.
Das ist eine Entwicklung von deinem schwedischen Institut
Und hat eine ganze Reihe von Features, ich erzähle nicht
im Einzelnen erläutern werde. Wir haben immer die Lizenz gekauft
für dieses System und die erlaubt uns Studentenlizenzen kostenlos weiterzugeben.
Also wer immer Interesse an einer solchen Lizenz hat,
bitte bei Michael König melden und dann wird er ihnen den Download-Key dafür geben.
Gut, das ist so viel zur Software, zur Literatur.
Da gibt es eine ganze Reihe von Sachen,
die mehr oder weniger aktuell sind.
Das Schöne an Prolog ist, dass es sich seit
seiner Erfindung und wann
ist denn das gewesen
Irgendwann über das Jahr 1970 herum, praktisch so gut wie gar nicht geändert hat.
Wenn man das mal kontrastiert mit anderen Programmiersprachen,
die heftige Varianten produziert haben,
von denen die eine nicht mit den anderen kompatibel ist,
ist Prolook eigentlich eine erstaunlich stabile Sprache.
Das initiale System gut nicht das allererste von Kölmerauer,
aber das zweite von Warren aus Edinburgh ist so stabil,
dass es auch heute immer noch benutzt wird.
Eine grundlegende Syntax hat sich, sie ist auch einfach genug,
das kommt noch dazu.
Aber an diesem hat sich bis heute eigentlich wenig geändert.
Das Ganze ist irgendwann mal ISO standardisiert worden und
dieser ISO-Standard wird heutzutage von allen Systemen benutzt
Damit ist eine gemeinsame Basis verfügbar. Die Programme sind also
hochgradig portabel zwischen den verschiedenen Produktsystemen. Und da spiegelt sich
auch in der Literatur wieder, viel ändert sich da nicht.
Und die guten Bücher sind immer noch gute Bücher,
auch wenn sie schon vor zehn Jahren erschienen sind.
Und sehr zu empfehlen, für den Einstieg ist auf
jeden Fall immer noch der Clocks and Malish.
Das ist eines der ersten und auch immer noch eines der
besten Bücher dafür. Und die anderen,
die ich hier angegeben habe, sind eher für Leute,
die zusätzlich noch irgendetwas darüber erfahren wollen.
Also der Bratgo beispielsweise das Letzte,
wenn man eher sich an Verfahren der Künstlichen Intelligenz orientiert,
dann ist der
eine gute Empfehlung
Sterling und Chapiro haben eher so die Fortgeschrittenen Programmiertechniken in der Logikprogrammierung abgedeckt.
Und der Glocksinn ist eher so eine Art Ratgeber für den Alltag der Logikprogrammierung.
Grundsätzlich gibt es eine ganze Reihe von Büchern,
auch das Internet ist voll von Manuskripten,
die mal gedruckt worden sind und dann nie wieder gedruckt worden
sind oder nie gedruckt worden sind,
die auch aber nicht schlecht sind.
Also suchen sie einfach mal in dem Bibliotheksbestand und darüber hinaus
nach entsprechender Literatur. Und wenn sie irgendwas Schönes gefunden haben,
verraten sie es mir bitte
Das ist das Programm, was ich hier absolvieren will.
Wir haben gerade Punkt Nummer eins abgeschlossen, deshalb steht da
hier nicht mit drauf. Wir unterhalten uns als zweites über Programmierparadigmen,
um einordnen zu können, was heißt es über,
oder wie positioniert sich die Logikprogrammierung im Vergleich zur Funktionalen,
zur imperativen Programmierung im Vergleich zur Objekt- oder orientierten Programmierung und so weiter.
Wenn wir das getan haben, gibt es stritt drei,
vier und fünf, das sind genau die drei Schritte,
die ich vorhin schon angedeutet habe.
Wir führen den Begriff der relationalen Datenbank ein. Wir erweitern im zweiten Schritt,
indem wir die Implikation mit hinzunehmen, die logische Implikation,
das Ganze zur deduktiven Datenbank und in einem dritten Schritt nehmen
wir rekursive Datenstrukturen mit hinzu und dann sind wir auf der Ebene der Turing-Mächtigkeit.
Bis dort, den haben wir bereits eine vollständige Programmiersprache,
mit der alles programmierbar ist, was man programmieren möchte. Es ist allerdings eine Sprache,
die noch nicht wirklich gut handhabbar ist und deshalb gibt es eine Reihe von zusätzlichen Leistungen,
dass Datentypen, die man mit den Mitteln der rekursiven Datenstrukturen sehr leicht aufbauen kann,
die aber dann etwas hölzern zur Benutzung sind,
dass man für die spezielle syntaktische Notationsweisen einführt,
das sind verkettete Listen und verkettete Listen werden wir dann dahin erweitern,
dass wir über aktive Datenstrukturen reden
Werden hier zu dem Punkt kommen, wo der Unterschied zwischen Daten und Programmen
vollständig verschwindet. Wir können dem Ding nicht mehr ansehen,
ob es ein Programm oder ein Datenelement ist.
Und die aktiven Datenstrukturen sind der Weg dorthin. Also Daten
bekommen eine prozedurale Bedeutung. Das wird das Ziel sein,
wo wir dorthin gehen wollen. Und dann sieht man schon,
dass die Logikprogrammierung eine Sichtweise auf Programmierung mitbringt, die nicht alltäglich ist,
die also alltägliche Gewohnheiten in Frage stellt und schließlich sogar aufhebt.
Wir müssen uns angucken, was Prädikate in der Logikprogrammierung sind,
die mit der Logik der dogischen Basis an sich nichts zu tun haben,
die also entweder außerhalb der Logik sind,
also beispielsweise Ride-Befehle
Ein Reitbefehl hat in der Logik nichts zu suchen. Das ist ein Nebeneffekt,
der irgendwo auf dem Papier oder auf der Konsole eine Auswirkung zeigt.
Das sind extra logische Prädikate, metalogische Prädikate, sind dann solche,
die auf den logischen Ableitungsprozess drauf schauen und mir sagen,
was passiert jetzt erst eigentlich?
In welchem Zustand ist dieser Prozess? Hat die Variable einen Wert,
hat sie keinen Wert? Welche Alternativen existieren und so weiter
? Das sind metalogische Prädikate und metalogische Prädikate,
das ist insbesondere das, was wir dann zur Metaprogrammierung brauchen werden.
Dann müssen wir nämlich auf andere Programme raufschauen und müssen sagen,
was mit diesem Programm jetzt im Einzelnen passieren soll.
Das ist dann der Punkt, wo wir nicht nur Das
habe ich ja gar nicht erwähnt.
Wir können also in der Sprache die Syntax verändern,
aber wir können auch die Semantik auf den Kopf stellen,
über die Meta-Programmierung. Und das ist dann der Punkt,
wo auch dem Letzten der Teppich unter den Füßen weggezogen ist.
Wenn ich also anfange, Interpreter zu schreiben,
die meine Programmiersprache in anderer Weise abarbeiten,
als dies ursprünglich vielleicht mal gedacht gewesen ist.
Und das brauchen wir aber, wenn wir Interpreter für
neue Programmiersprachen entwickeln und in der Sprache schreiben wollen.
Dann wollen wir mithilfe eines Prolog-Interpreters beispielsweise Skim-Programm abarbeiten.
Das wird das Ziel sein,
wo wir hier in der funktionalen Programmierung Punkt Nummer 11
dann hinkommen
Gut, Prädikate, höhere Ordnung sind immer solche,
die andere Prädikate als Input oder Output erzeugen,
als Input verwenden oder als Output erzeugen.
Wir werden uns im Wesentlichen die angucken, die andere Prädikate
als Input nehmen und sie in irgendeinen Berechnungsprozess einbringen.
Gut, und das ist dann eigentlich auch das gesamte Programm,
was wir hier absolvieren wollen. Okay,
damit können wir also einsteigen und uns als allererstes über die Frage unterhalten,
was ist eigentlich ein Programmierparadigma und da werde ich die Fragen
ansprechen,
was sind Verarbeitungsmodelle
Was ist der Begriff der Abstraktion? Da unterscheidet nämlich die
verschiedenen Verarbeitungsmodelle. Was heißt es, ein Programmierstil zu pflegen?
Und wie hängen Programmierstile mit Verarbeitungsmodellen zusammen?
Und dann ein paar Alleinstellungsmerkmale der Logikprogrammierung diskutieren.
Und hier gibt es immer so einen kleinen Appetizer ganz links.
Das ist mal ein Versuch, die drei grundlegenden Paradigmen gegenüberzustellen.
Hier ist die objektorientierte Programmierung nicht dabei,
weil sie für meine Begriffe kein separates Paradigma darstellt,
sondern eine Ansatz ist, wie ich komplexe komplexe Software strukturieren muss oder kann.
Was ich schon darin zeigt, dass ich objektorientierte Programmierung
sowohl im Imperativen als auch im Funktionalen Paradigma betreiben kann.
Sie ist sogar im funktionalen Paradigma entstanden und dann erst ins
Objekt orientiert, äh, ins Imperative Paradigma gewechselt.
Deshalb habe ich hier eine rein emperative Sprache genommen,
das ist Pascal in diesem Falle, wo ich jetzt eine Funktion definiere,
die Member heißt, die nichts anderes macht,
als dass sie aus einer Liste die Elemente überprüft,
ob ein Element in der Liste enthalten ist.
Das ist also hier imperativ als Vorschleife implementiert. Hier ist es funktional,
dass wir an die meisten von denen kennen,
das ist Scheme, implementiert und hier unten ist die Implementation
als Logikprogramm
Da wollen wir händen. Und jetzt geht es erst mal darum,
was sind eigentlich die Dinge, die Logikprogrammierung von den anderen unterscheidet.
Also wir haben sogenannte berechnungsuniverselle Verarbeitungsmodelle. Das sind die drei,
die ich jetzt gerade erwähnt habe, imperativ funktional und logikbasiert.
Und wir haben in der Informatik es mit eingeschränkten Verarbeitungsmodellen zu tun.
Also das ist so etwas wie die relationalen Datenbanken.
Und ich habe schon angekündigt, dass das Konzept der
relationalen Datenbanken ein Teil des logikbasierten Modells ist.
Und da sieht man schon,
das Ding ist offensichtlich von seiner Leistungsfähigkeit her nicht so,
als dass es ein Substitut für eine vollständig ausgebaute Programmiersprache ist
Andere eingeschränkte Verarbeitungsmodelle sind sowas wie Tabellenkalkulation und sie können
sich überlegen, was immer sie wollen.
Da gibt es jede Menge für unterschiedliche Zwecke,
so was wie verschiedene Sorten von Automaten, endliche Automaten und so weiter.
Die können ganz bestimmte Sachen, sie können aber nicht allgemein
jede Programmieraufgabe lösen. Imperative Programmierung ist dadurch gekennzeichnet,
dass ich Anweisungsfolgen habe und diese Anweisungsfolgen verändern den internen Zustand des Automaten.
Oder aber veranlassen ein Aufgabeoperation
Das hat man eben hier an dieser Stelle,
dass in dieser Vorschleife hier eine Variable eingeführt wird und diese
Variable wird in jeder Iteration auf einen neuen Wert gesetzt.
Und damit ist dieser Test hier zustandsabhängig,
nämlich er hängt von dem Wert von ihm ab und in
Abhängigkeit von diesem Wert wird dann entweder die Schleife verlassen und
ein Rückkehrwert ausgegeben oder es wird weiter die Schleife durchlaufen.
Und zustandsbasierte Programmierung hat eine ganz gewaltiges Problem und dieses gewaltige Problem ist,
dass sich die Korrektheit eines Programms nur unter Rückgriff auf den Zustand,
in dem sich das Programm befindet,
beantworten kann
Ich muss also bei allen Fragen, wenn es darum geht,
macht das Programm das, was es soll, immer fragen,
ja, in welchem Zustand befindet sich das Programm?
Wenn ich aber jetzt, beispielsweise im Debugging bin,
ist es äußerst schwierig festzustellen, in welchem Zustand ist das Programm eigentlich?
Dann muss ich mir also sozusagen alle internen Variablen,
die es veraltet, angucken, welche Werte haben sie?
Und erst dann kann ich sagen, ja,
gegeben diesen Zustand, müsste jetzt eigentlich dieses Ergebnis erzeugt werden.
Deshalb ist es der Versuch, mit der deklarativen Programmierung
diese Zustandsabhängigkeit zurückzudrängen oder gar völlig zu beseitigen.
Und das wird ein zentrales Thema dieser Veranstaltung sein,
inwieweit gelingt das?
Oder wo gelingt es nicht mehr
Und in der Funktionalen Programmierung gelingt das schon recht gut,
indem man nämlich hier nur noch lokale Variablen zulässt,
die auf dem Kellerspeicher gehalten werden, auf dem Stack des Systems.
Und deshalb gar keine Zustandsabhängigkeit mehr existiert. Also vom Aufruf
der Funktion bis zur Rückgabe des Funktionswertes passieren rein lokale Operationen,
die für einen gegebenen Input immer genau den gleichen Output erzeugen.
Das ist ein wichtiger Aspekt von Deklarativität,
dass diese Abhängigkeit vom Zustand und von Seiteneffekten weitgehend zurückgedrängt ist.
In der emperativen Programmierung ist eben der Notnagel,
um die negativen Auswirkungen der Zustandsabhängigkeit zu beseitigen.
Da ist die Antwort drauf, Objektorientierung,
mit ihren Techniken wie Kapselung und dergleichen mehr.
Dass ich also die Möglichkeiten auf den Zustand des Systems zu verändern,
dass ich die stark einschränke und dass ich die in Klassen oder besser in Objektinstanzen kapsele.
Gut, und der dritte Punkt ist natürlich dann
die Logikprogrammierung in der Logikprogrammierung geht es darum,
dass wir durch logische Deduktionen die Zugehörigkeit von Wertekombinationen zu einer Relation überprüfen.
Und wir können dort in diesem Prozess Wertebindungen herstellen und
diese Wertbindung werden dann unsere Berechnungsergebnisse seien.
Wenn wir also hier oder der wesentliche Unterschied zur funktionalen Programmierung
besteht darin, dass die funktionale Programmierung immer gerichtet ist.
Eine Funktion ist immer über einen Wertebereich definiert und bildet in
einen Bildbereich ab. Dort ist das Ergebnis zu finden.
Ich kann in der Regel nicht diesen Prozess umkehren,
dass ich sage, hier ist der Funktionswert,
was sind die Argumentbelegungen,
die ich hineingeben muss,
damit dieser Funktionswert herauskommt
Dafür brauche ich die Umkehrfunktion. Und die ist nicht in jedem Falle verfügbar.
In der Logikprogrammierung wird es darum gehen, diese richtungsabhängigkeit aufzuheben.
Also nicht nur Nebeneffekte beseitigen, sondern auch die Richtungsabhängigkeit aufzuheben,
sodass ich also eine Relation in jeder Richtung benutzen kann.
Wenn Sie eine relationale Datenbank beispielsweise haben,
nehmen wir mal sowas, eine Person mit ihrer Geburtsdatum.
Dann können Sie sowohl fragen, was ist das Geburtsdatum dieser Person,
aber Sie können auch umgekehrt fragen, welche Personen haben dieses Geburtsdatum?
Das ist in der Relation nirgendwo spezifiziert,
in welche Richtung die Berechnung ablaufen wird.
Das nennen wir Richtungsunabhängigkeit und das wird das Ziel der Logikprogrammierung
sein.
Ich komme dann gleich mit Beispielen
Gut, also, objektorientiertes Modell über Message Passing im Original realisiert.
Über Message Passing kann ich den internen Zustand von Objekten verändern.
Und ich kann Objekte hierarchisch strukturieren und Eigenschaften von übergeordneten Projekten ändern.
Und die Zustandsänderung der Objekte, die kann ich entweder
imperativ oder funktional definieren. Und man kann darüber nachdenken,
warum die Logikprogrammierung da nicht mit drin auftaucht.
Warum es keine elegante Lösung dafür gibt, Logikprogrammierung,
objektorientiert zu erweitern.
Das Thema können wir später nochmal diskutieren
Dann gibt es so etwas wie das konstruent basierte Modell. Eigentlich,
man kann es auch auffassen als eine Erweiterung der Logikprogrammierung,
um Konstruenz-Satisfiction, wo ich also in der Lage bin,
nur unter Angabe von Bedingungen, die zwischen Werten bestehen müssen,
mögliche Wertebelegungen für Variablen zu berechnen.
Stellen Sie sich beispielsweise Stundenplanproblem vor. Sie haben Bedingungen zum gleichen Zeitpunkt
, können nicht zwei verschiedene Lehrveranstaltungen in einem Raum stattfinden.
Eine Person kann nicht zwei verschiedene Lehrveranstaltungen besuchen oder abhalten und
so weiter und so fort.
Das sind Bedingungen, die für mögliche Lösungen formuliert werden können.
Und dann sage ich nur, wusch,
und das System soll mir ausrechnen,
was ist eine Lösung für dieses Problem
Ohne, dass ich erst spezifizieren muss, ja,
probiere erst dieses, probiere dann jenes und mache dann drittens dies.
Ja, also auch der Versuch, möglichst wenig Informationen durch den Programmierer
zu spezifizieren und dem System möglichst viel eine Lösung zu überlassen.
Es gibt dann zahlreiche eingeschränkte Verarbeitungsmodelle, hatte ich schon angekündigt,
endliche Automaten, reguläre Grammatiken, reguläre Ausdrücke.
Das ist das, was Sie in FGI 1 etwa kennengelernt haben.
Tabellenkalkulationsprogramme hatte ich schon erwähnt, werden hier nirgendwo explizit behandelt.
Markabsprachen, die typischerweise ohne eine Semantik daherkommen,
weil es eben reine Sonntags ist,
das ist das Wesen einer Markabsprache,
die im Einzelfalle aber mit einer Semantik versehen werden
Die aber dann auch typischerweise eingeschränkt ist, keiner ist bisher auf die Idee gekommen,
berechnungsuniverselle Programmiersprachen mithilfe von der XML-Ausdrücken zu beschreiben.
Relationale Datenbanken, auch schon erwähnt, werden in GDB behandelt. Und diese Sicht,
dass man unterschiedliche Verarbeitungsmodelle hat und diese Verarbeitungsmodelle realisiert und kombiniert
und einbaut in übergeordnete Verarbeitungsmodelle, das ist eigentlich das,
was in der künstlichen Intelligenz über die letzten Jahrzehnte hinweg
massiv und sehr intensiv betrieben worden ist.
Da gibt es also ganze Bücher zu dem Thema
Ja, wenn wir über Logikprogrammierung sprechen,
müssen wir über den Begriff der Abstraktion reden,
weil nämlich das allererste, was man irgendwo mal finden wird,
die Informationen sein wird, dass Logikprogramme,
die ein Programmierungsproblem auf sehr abstraktem Niveau beschreiben.
Und die Frage ist, was heißt das eigentlich?
Was macht man da? Oder was unterscheidet das von einem
weniger abstrakten, einer weniger abstrakten Ebene?
Und die zweite Frage ist, dass man oftmals das Vorurteil findet,
dass Abstraktion etwas ist,
was das Verständnis verhindern kann
Ich möchte dagegen die These setzen, dass Abstraktion das ist,
was uns Verständnis überhaupt erst ermöglicht.
Und ich werde das versuchen, durch Beispiele zu erläutern.
Also wenn wir etwa von der zugrunde liegenden Hardware abstrahieren,
dann kommen wir zu dem Begriff der abstrakten Maschine.
Wir werden auch in der Logikprogrammierung von einer abstrakten Maschine reden,
die nämlich genau die Abarbeitung eines Logikprogramms übernimmt.
Und diese abstrakte Maschine unterscheidet sich von der Basis-Hardware,
die wir also kaufen im Laden,
ziemlich dramatisch
Diese Basis-Hardware, das ist da unten angegeben,
ist durch eine Architektur bestimmt,
die nach wie vor im Wesentlichen der sogenannten von Neumann-Architektur folgt,
mit Speicher und Prozessor und so weiter und so fort.
Und die abstrakte Maschine muss also erst auf der tatsächlich vorliegenden Hardware implementiert werden.
Da ist also ein System dazwischen, ein Interpreter, der genau diese Abbildung vornimmt.
Und wir müssen jetzt die elementar, der Pfeil,
den kann man in der anderen Richtung auch lesen,
man könnte genauso gut sagen,
die abstrakten Operationen oder komplexen Operationen der abstrakten Maschine müssen jetzt
auf dieser Basis-Hardware realisiert werden
Und das abstrakte Speichermodell, ich hatte schon angesprochen,
funktionale Programmierung hat als abstraktes Speichermodell den Stack.
Der hat nur sehr bedingt etwas mit dem realen Speicher zu tun.
Wir werden sehen, dass in der Logikprogrammierung das Speichermodell so
weit abstrahiert ist, dass der Speicherbegriff nirgendswo mehr auftaucht.
Wir wissen überhaupt nicht. Und wir haben keinerlei Möglichkeiten,
auf den Speicher zuzugreifen. Wir wissen nicht,
wo das System irgendetwas verwaltet. Da hat der normale Anwendungsprogrammierer
überhaupt keinen Zugang dazu
Und dies ist also eine Sicht von Abstraktion. Wir haben
die Hardware da unten und wir wollen jetzt ein anderes Verarbeitungsmodell auf
dieser Hardware realisieren und dafür brauchen wir einen Abbildungsprozess von den
konkreten Operationen im Hardware-System und hin zu den komplexen Operationen der abstrakten Maschine.
Und hier unterscheiden sich jetzt die verschiedenen Paradigmen ziemlich massiv.
Wenn ich also die elementaren Datentypen angucke, dann unterscheiden sie
sich noch nicht so sehr. Also sowohl in,
ich habe jetzt nur diese drei Paradigmen hier angegeben,
die haben alle irgendwie das,
was elementar auf der Welt der Maschine zur Verfügung steht,
das reichen sie durch.
Also wenn es eben Zeichenketten gibt, dann werden Zeichenketten zur Verfügung gestellt,
wenn es Bitstrinks gibt, dann werden Bitstrinks zur Verfügung gestellt,
Intecheril zahlen und was es da alles noch so gibt.
Die deutlichen Unterschiede sind eher auf der Ebene der Anweisungslogik.
Die emperativen Sprachen sind noch sehr, sehr stark am zugrunde liegenden Hardwaremodell orientiert.
Dort gibt es eben einen zentralen Befehl und der Gib
den Namen für das ganze Paradigma her, die Wertezuweisung.
Daher kommt der Name, setze eine Speicherzelle auf einen Wert.
Das geht in der funktionalen Programmierung nicht mehr ohne Weiteres.
Ich weiß nicht mehr, wo die Speicherzellen sind.
Alles, was ich machen kann, ist kann,
ich kann Bindungen auf dem Stack hervorrufen.
Das ist die Lab-Umgebung. Die haben sie,
die meisten von ihnen schon mal kennengelernt. In der Logik
basierten Programmierung werden sie nicht mal mehr einen Zuweisungsbefehl haben.
Es gibt keine Möglichkeit, eine Vagable mit einem Wertzufall
zu sehen.
Das ist das Privileg des Programmiersystems
Und da wir wissen, dass diese Wertzuweisung,
die nämlich den Zustand der Maschine verändert,
dass die eine wesentliche Quelle für Programmierfehler ist,
resultiert also bei der Logikprogrammierung im Umkehrschluss daraus,
diese Fehlerquelle ist vollständig weg.
Ich kann den Zustand der Maschine nicht mehr verändern.
Ich habe die technischen Mittel, dafür stehen wir
gar nicht mehr zur Verfügung. Was sich verändern kann,
ist natürlich die relationale Datenbank des Systems,
die kann ich manipulieren,
aber nicht
den Speicher
Das ist übrigens auch, sie erinnern, also alle,
die dich schon mal mit Skim gesehen hatten,
das ist die Klasse der berühmten Bang-Funktionen.
Set Bang, die also hart auf den Speicher zugreifen,
dort irgendetwas verändern. Und die heißen nicht ohne Grund,
Set Bang, als Warnsignal dafür, wenn du die verwendest,
produzierst du inhärent unsicheren Code.
Steuerstrukturen, das emperative Modell geht nicht ganz so weit,
dass es die Steuerstrukturen auf der Hardware repliziert,
denn dort wird alles mit Sprungbefehlen erledigt.
Die sind weitgehend beseitigt, aber immerhin gibt es so etwas wie bedingt
Anweisungen und bedingt Anweisungen sind die Grundlage für konditionale und Schleifenkonstrukte.
Also dort sieht man die Hardware-Strukturen auch relativ gut.
In der funktionalen Programmierung ist das schon stark zurückgedrängt. Dort haben wir entweder Rekursionen,
die es auf der Maschinenebene überhaupt nicht gibt oder Funktionen höherer Ordnung,
die es auf der Maschinenebene auch nicht gibt.
Und extrem wird das also sein, in der logikbasierten Programmierung,
wo wir auch die Rekursion zur Verfügung haben,
wo wir aber große, große Teile der Steuerung,
wie das Programm abgearbeitet wird,
wieder dem System überlassen
Wo wir als Nutzer gar nicht rankommen oder nur mit großem Aufwand rankommen.
Gut, okay, das geht also so weiter,
das gilt für das Speichermodell,
das wird auf der Ebene der emperativen Programmierung fast eins zu eins durchgereicht bei der funktionalen Programmierung,
gibt es eine gewisse Abstraktion dazwischen.
Sie ist wieder extrem bei der Logikprogrammierung. Und ich habe das schon angesprochen,
Verarbeitungsrichtung, Imperative Programmierung, reicht genau das durch,
was die Hardware ermöglicht.
Funktionale Programmierung ist in der Hinsicht beschränkt auf die funktionale Verarbeitungsrichtung,
also vom Argumentwert zum Funktionswert.
Und die Logik basierte versucht an der Stelle weckt,
Versucht an die Stelle wegzukommen von der Richtungsabhängigkeit hin zu einer
relationalen Sicht auf die Welt, wo ich nur noch spezifiziere,
welche Zusammenhänge sind zwischen den Bajablen eigentlich gegeben und den Rest möge bitte die Maschine übernehmen.
Gut, also was ist nun Abstraktion? Abstraktion,
nachdem wir die ganze Zeit darüber geredet haben,
heißt nichts anderes als ich hebe bestimmte Merkmale eines Objekts
als relevant hervor und ich unterdrücke andere Merkmale,
die ich glaube vernachlässigen zu können.
Und dieses, ich glaube, vernachlässigen zu können,
ist ein hochgradiger subjektiver Faktor.
Unterschiedliche Leute werden unterschiedliche Dinge als wichtig oder unwichtig deklarieren
Und insofern eine wesentliche Quelle für Missverständnisse einer Art.
Auf der anderen Seite ist sie das zentrale Hilfsmittel,
was wir haben, um Komplexität zu reduzieren.
Wenn wir also über Hörsaal Phil C reden,
dann können wir durch die Abstraktion auf den Begriff des Hörsaals
mit dem Namen über dieses Ding hier reden.
Wir müssen nicht darüber reden, wo sich das geografisch befindet.
Wir müssen nicht darüber reden, wie viele Stühle hier drin sind.
Wir müssen nicht darüber reden, ob der Fußboden gereinigt ist oder nicht.
All dies sind Details, die wir weg abstrahieren,
weil wir sie für den konkreten Zusammenhang,
wo findet die Lehrveranstaltung statt,
einfach nicht brauchen
Wir brauchen also dieses, dass wir Menschen einen Namen geben,
dass wir also ab sofort über Hans Meyer reden können,
ist eine wichtige Abstraktionsleistung. Ansonsten müssten wir immer beschreiben,
wen meinen wir denn da eigentlich, über den wir reden?
Und das kann beliebig komplex werden. Dann ist es der Mann,
der gestern, und du weißt schon vorgestern auch und aber,
ja, und wir können sagen, Hans Meyer kommt heute.
Es ist eine zentrale Kulturleistung des Menschen,
aber es ist eben aufgabenbezogen,
also für bestimmte Aufgaben brauche ich
andere Abstraktionen
Und das ist interessant,
insofern ist also auch nicht der Kampf der Paradigmen,
ist funktionale Programmierung besser als imperative Programmierung oder objektorientierte Programmierung,
besser als Logikprogrammierung, sondern man muss umgekehrt fragen,
für welche Aufgaben ist welches Paradigma besonders gut geeignet.
Das ist die richtige Fragestellung. Es ist subjektiv und deshalb
gibt es also zahlreiche Missverständnisse. Das will ich
an verschiedenen Beispielen erläutern. Das hier sind zwei Städte,
das sollen hier ungefähr der Umriss von Hamburg sein.
Das ist ungefähr der Umriss von Berlin,
wovon ich auch schon abstrahiert habe, sind die tatsächlichen Größenverhältnisse Berlin,
ist zu klein dargestellt.
Was ist die Entfernung zwischen Hamburg und Berlin
Gut, sie geben einen Intervall an. Warum? Okay,
gut, das ist also eine praktische, am praktischen Reiseverhalten orientiert, ja?
Ja, das ist ein Schlagzentrum. Ja, genau. Also,
und damit haben wir die wesentlichen Probleme auch schon benannt.
Es gibt keine Entfernung zwischen zwei Städten. Städte sind
flächige Ausdehnungen, Entfernungen kann ich nur zwischen Punkten ermitteln.
Ich kann über die Entfernung zwischen zwei Städten nicht sprechen,
wenn ich nicht abstrahiere, dass davon abstrahiere,
dass die Stadt eine flächige Ausdehnung hat.
Ich muss sie zu einem Punkt idealisieren und das ist Abstraktion.
Sonst kann ich darüber nicht reden. Und das muss man
sich mal auf der Zunge zergehen lassen. Das sind Abstraktionsleistungen
im täglichen Leben, mit denen wir ganz natürlich umgehen.
Und keiner stellt die Frage, das ist zu abstrakt,
das verstehe ich nicht. Im Gegenteil,
ich muss es abstrahieren, damit ich es überhaupt verstehen kann.
Ansonsten geht es nicht. Es gibt unendlich viele Entfernungen zwischen
diesen beiden Städten. Ich könnte nicht über Entfernungen sprechen,
wenn ich nicht zu dieser Abstraktion in der Lage wäre.
So rum war dein Schuh draus. Kulturleistung, Handel,
ursprünglich hat man Ware gegen Ware ausgetauscht. Heute tauscht man
Ware gegen Verrechnungseinheiten aus. Es wird nicht mal mehr
irgendwie Geldscheine oder irgend so etwas. Also dann habe ich Materialwert,
heißt, ich muss den Klumpen Gold hinlegen und das Gold wurde ausgewogen,
ob es auch genügend viel Gold ist,
um als Gegenwert für die Kuh beispielsweise herzuhalten.
Nominalwert war der Geldschein. Da wurden Geldscheine oder Münzen ausgetauscht,
deren aktueller Wert drastisch geringer ist als ihr Nominalwert.
Also der Papierwert eines 100-Euro-Scheins ist vernachlässigbar gegenüber dem Wert,
den wir diesem Ding zumessen. Und das ist eine Kulturleistung,
da haben sich Menschen darüber geeinigt, dass man so vorgehen sollte.
Und heutzutage schieben wir nur noch Bits zwischen Rechnern hin und
her, wenn wir unsere Kreditkarte da abgeben.
Das heißt also, es ist immer abstrakter geworden von dem
konkreten Ware gegen Ware,
heutzutage Ware gegen Bit
Und wir überlassen es, der dahinter liegenden Infrastruktur dafür Sorge zu tragen,
dass auf den entsprechenden Konten imaginäre Einheiten verrechnet werden.
Die haben keinen materiellen Gegenpol mehr. Abstraktion als Quelle von Missverständnissen, Maßeinheiten zum Beispiel.
Wenn ich also einen Wetterbericht habe, der mir sagt,
heute sind 45 Grad draußen, was heißt das dann?
Es ist wirklich so heiß oder ist es vielleicht
ein anderes Maßsystem im Leben gemessen wird?
Solange ich die Maßeinheiten nicht angebe,
habe ich
ein Problem
Der Verlust einer dieser Marssonnen, das ist eines der Probleme,
dessen Beispiele für sichere oder unsichere Programmierung ist, darauf zurückzuführen,
dass sie eine emetrischen Systeme und die anderen im Ja-System gemessen haben.
Und leider Gottes gibt es da ungefähr zehn Prozent Abweichung dazwischen
und das hat dazu geführt, dass die Sonne abgestürzt ist.
Die ist hinter dem Mars verschwunden und auf der anderen Seite nie wieder vorgekommen.
Also, aber es ist etwas, was von wir abstrahieren.
Wer von uns programmiert wirklich so typsicher, dass er in
jedem Fall die Zahlen im Rechner mit ihrer Maßeinheit versieht.
Hand aufs Herz,
wer macht das
Wir nehmen immer an, die Abstraktion, die wir verwenden,
dass wir die Maßeinheit einfach weglassen, die wird schon konkret sein.
Und alle werden verstehen, was ich hier mache. Leider nein,
in wichtigen Fällen verstehen es andere Leute anders und schon haben wir ein Problem.
Also, weglassen von den Informationen, abstrahieren von Informationen kann sich als Problem herausstellen.
Wenn ich also einfach nur ein Geschwindigkeitsschild habe,
da steht 30 am Straßenrand,
dann muss ich den geografisch kulturellen Umkreis kennen, indem ich mich bewege,
sind das jetzt 30 Stundenkilometer oder 30 Meilen pro Stunde,
die ich fahren darf.
Und selbst wenn es Meilen sind,
müsste ich noch genauer fragen, welche Meilen sind es denn?
Möglicherweise sind Seemeilen gemeint
Gut, es gibt also in der Softwareentwicklung auch Fälle von Abstraktionen.
Also ich versuche vom Einzelfall zu abstrahieren. Das ist mit
dem Begriff der Wiederverwendbarkeit verbunden. Ich möchte Programme schreiben,
die nicht nur für den Einzelfall gelten, sondern die immer wieder benutzbar sind.
Der Gedanke der Bibliotheken basiert darauf, dass ich davon Gebrauch mache.
Dann muss ich eben versuchen, es so allgemein zu machen,
dass die Details des Einzelfalls da nicht mehr drin auftauchen.
Denn ansonsten geht es nicht wieder zu verwenden. Also Abstraktion als
ganz normale natürliche Aufgabenbestellung des Programmierers oder Abstraktion von irrelevanten Aspekten,
dass ich eben gegeben hier diesem Hörsaal,
wenn ich ein Raumverwaltungsprogramm mache, nicht aufführen muss,
dass dieser Hörsaal acht Fenster hier oben hat.
Möglicherweise muss ich das machen, wenn ich von dem Verwaltungsprogramm auch erwarte,
dass ich den Aufwand kalkulieren kann, wie teuer wird es wohl,
wenn ich hier ein Fensterputzer reinschicke.
Das könnte eine andere Aufgabe sein, die plötzlich diese Information
relevant erscheinen lässt. In anderen Kontexten ist sie völlig irrelevant.
Abstraktion von der Hardware hatten wir schon hauptsächlich zur Komplexitätsreduktion.
Wenn wir wirklich auf der Ebene der Hardware programmieren müssten,
wären wir nicht in der Lage,
derartige Systeme zu bauen,
wie wir sie heutzutage haben
Und das ist eigentlich mein Beispiel immer,
wenn ich hingehe und jemandem erklären muss, was macht Informatik einzigartig?
Und von Zeit zu Zeit stehe ich vor dieser Aufgabe,
dass ich Schülern erklären soll, was macht Informatik eigentlich faszinierend?
Wissen Sie, was ich dann erkläre? Dann erkläre ich,
dass das Wachstum der Systeme, mit denen wir umgehen,
Speichergröße, Rechengeschwindigkeit, irgendwo in der über 30 Größenordnung sich bewegt hat.
Und exponentiell wächst, wann immer wir ein solches Wachstum in
anderen Bereichen der Realität haben, dann ist es eine Katastrophe.
Wenn das in der Medizin passiert, dann haben wir
eine Epidemie oder eine Pandemie vorliegen und wir müssen alles tun,
um dieses Wachstum einzudämmen
Es ist da, wogegen wir wachsen, wogegen wir kämpfen müssen.
Wenn wir das in der Physik haben, dann ist es eine Atombombenexplosion.
Oder der Reaktor explodiert gerade. Dann ist genau die Kontrolle des Reaktors
außer Kontrolle geraten und wir müssen versuchen, das Unglück einzudämmen.
Es ist in allen Fällen eine Katastrophe, wenn das passiert.
Die Informatik hat dieses Wachstum jetzt über vier oder fünf
Jahrzehnte stabil durchgehalten, ohne dass eine Katastrophe eingetreten ist.
Und wir haben es nur deshalb geschafft,
weil wir Abstraktionsebenen eingezogen haben,
auf denen wir über diese Geräte da reden können,
ohne uns um die Details da unten noch kümmern zu müssen
Ich glaube, mit Sicherheit sagen zu können,
es gibt keinen Menschen auf der Welt,
der vollständig versteht, was in diesem Rechner eigentlich abläuft.
Wir haben uns Hilfswerkzeuge geschaffen, dass wir eben über Programmiersprachen,
über Betriebssysteme und dergleichen reden, sodass wir von all dem,
was da drunter abläuft, Mikroprogrammierung und so weiter,
dass wir davon vollständig abstrahieren können.
Das müssen wir nicht mehr wissen. Und wenn wir es nicht hätten,
könnten wir also mit solchen Apparaten überhaupt nicht arbeiten. Gut, ja,
Abstraktion durch Generalisierung, ich komme jetzt zu den Methoden,
die wir anwenden können, um zu abstrahieren.
Ich muss mal schauen, von hier kann ich die Uhr
nicht erkennen, was ist denn das?
Die zeigt aber auch merkwürdige Dinge an, ja?
Bitte? Okay. Da müssen wir das anders machen.
Ja, also, wie kann ich abstrahieren?
Ich kann abstrahieren, indem ich generalisiere. Das ist eben
Abstraktion vom Einzelfall. Es würde sehr, sehr mühsam sein,
wenn ich also die Funktion FSX Quadrat, beispielsweise hinschreiben muss,
durch eine Auflistung der entsprechenden Belegung für X und des Funktionswertes,
der sich daraus ergibt.
Das wäre nicht
so richtig schön
Ich kann das funktional machen, indem ich eben eine Funktion definiere,
die mir genau diesen Zusammenhang berechnet, aber nicht aufzählt.
Und genau das Gleiche werden wir in der relationalen Programmierung machen.
Wir können aufschreiben, was ist ein Vogel?
Also ein Amsel, ein Star, eine Maise.
Und wir können aufschreiben, eine Amsel kann fliegen,
ein Star kann fliegen, eine Maise kann fliegen.
Das ist nichts anderes als eine relationale Datenbank, was hier steht.
Mit zwei Relationen, zwei trivial einfachen Relationen,
die nämlich genau nur ein Attribut haben.
Und wir können darüber eine Generalisierung formulieren,
die sah, alles kann fliegen,
was ein Vogel ist
Und dann haben wir sofort ein Problem. Solche Generalisierung sind fehlerbehaftet, sind Dennis,
was wir hier nicht drin haben, sind all die Ausnahmen.
Pinguine, Straußen und so weiter. Da müssen wir uns überlegen,
können wir den Mechanismus der relationalen Abstraktion so erweitern,
dass wir die Ausnahmen spezifizieren und nicht die Regelfälle.
Denn es gibt wesentlich weniger Vögel,
die nicht fliegen können als Vögel, die fliegen können.
Es ist wesentlich einfacher, alle aufzuzählen, die es nicht können,
als die aufzuzählen, die es können.
Und das wird eine der Sachen sein,
die wir uns dann im Zusammenhang mit der Manipulation des Suchraumes
in der Logikbranierung
Abstraktion durch Vergröberung. Wir lassen Sonder- und Ausnahmefälle weg,
haben wir eben gemacht, dass wir den Vogel,
bei den Vögeln, die, die nicht fliegen können,
einfach ignoriert haben, um uns die Arbeit ein bisschen zu vereinfachen.
Wir lassen die Maßeinheiten weg, haben wir schon diskutiert.
Wir lassen Ausgabeinformationen weg. Wir geben Ergebnisse auf dem Bildschirm
aus oder wo auch immer, ohne genau zu spezifizieren,
was das da eigentlich ist.
Dann vergröbern und vereinfachen wir aber immer mit dem Risiko,
dass das schief geht und dass das jemand falsch interpretiert,
was er dort sieht
Ein Weg ist tatsächlich auch sehr, sehr populär in der Informatik.
Kommentare über das, was ich mir gedacht habe oder das,
was ich mir gerade nicht gedacht habe, wären typischerweise auch weggelassen.
Das ist auch eine Abstraktion durch Vergröberung und etwas sehr Fahrlässiges.
Aber all das passiert immer in Abhängigkeit von der Relevanz für eine Aufgabenstellung.
Also immer überlegt sich irgendjemand, muss ich das jetzt unbedingt
machen oder muss ich das jetzt nicht machen?
Oder aber er ist ignorant. Er hat einfach nicht dran gedacht,
dass man das vielleicht dazu liefern müsste,
weil es Missverständnisse sonst geben könnte.
Und diese Relevanzbewertung sind also hochgradig subjektiv. Entweder denkt jemanden,
das wird schon nicht so wichtig sein,
oder er hat schlicht wirklich dran gedacht.
Und das ist das zentrale Problem der Informatik
Wie komme ich mit der Abstraktion? Ich muss abstrahieren,
es geht nicht anders. Ich muss die Abstraktionsleistung bringen,
aber wie kann ich so abstrahieren,
dass die negativen Auswirkungen nicht dominant werden?
Dass sie also nicht das ganze Ziel in Frage stellen.
Und das Problem, was wir hier haben, ist,
dass wir Arbeitsteilung haben. Die Leute,
die ein Problem entwickeln, das sind die hier unten,
die haben also einen Anwendungsbereich vorliegen und müssen sich davon ein Modell machen.
In dem Modell steht also beispielsweise drin, ja,
was ist wichtig für diesen Anwendungsbereich?
Da können die ersten Fehler passieren. Da können Vereinfachungen vorgenommen
werden. Und dann muss das Modell wieder noch umgewandelt werden
in ein Programm. Bei diesem Schritt fallen beispielsweise Maßeinheiten weg
Weil ich eben davon ausgehe, ich rede nur über Meta.
Also sind alle Entfernungsangelb, aber alle Distanzangaben in Metern
oder in Kilometern oder was auch immer.
Dann habe ich aber Personen, die mit diesem Programm umgehen sollen.
Die haben also, die geben Nachrichten ein in das System.
Die haben ein Anwendungsproblem. Sie müssen aus dem Anwendungsproblem eine
Beschreibung extrahieren für dieses Problem, also beispielsweise eine Person mit Attributen charakterisieren.
Und sie müssen das in eine Eingabenachricht umwandeln.
Auf beiden Schritten können Abstraktionen, sind Abstraktionen nötig und
es können Fehler und Missverständnisse entstehen
Und genau das Gleiche auf der Ausgabeseite, da erscheint eine Nachricht.
Ich muss diese Nachricht verstehen und ich muss sie abbilden auf
mein Verarbeitungsproblem, was ich habe.
Und überall werden hier Abstraktionen vorgenommen und hier müssen Interpretationen vorgenommen werden.
Das ist sozusagen dann das Gegenstück davon. Da muss die
fehlende Information wieder ergänzt werden. Da muss ich eben davon ausgehen,
aha, ich denke mal, die werden diese Angabe hier in Metern gemeint haben.
Genau weiß ich es aber nicht. Und da das verschiedene
Personen sind, die hier an dem Ende sitzen,
ist diese Abbildung dazwischen das Wesentliche.
Und die kann ich nur erreichen durch zwischenmenschliche Kommunikation.
Es ist der einzige Weg,
wie ich es erreichen kann
Und deshalb ist Dokumentation, Schulung und dergleichen im Software-Bereich so wesentlich.
Ich muss die Abstraktionsintention, die hier zugrunde liegen,
die muss ich sowohl dahin kommunizieren, als auch dorthin kommunizieren.
Wenn ich das nicht mache, ist das Chaos vorprogrammiert.
Das ist die Krux der gesamten Informatik. Und das ist immer
das Problem, wenn es heißt, die EDV hat versagt.
Dann hat nicht die EDV versagt, sondern dann sind diese Kommunikationspfade
gestört gewesen. Es ist nicht gelungen, diese Intention,
die hier darunter lag, nach da oder nach dort zu transportieren.
Und dann sind verschiedene Leute da,
die ein unterschiedliches Bild von der Welt haben,
ein unterschiedliches Bild davon haben,
was ein solches System eigentlich macht und dann aneinander vorbeiarbeiten
Andere Formen von Abstraktionen ist die durch Verbergen.
Ich habe also so etwas wie eine Bit-Repräsentation auf dem Rechner.
Nichts anderes gibt es als Bit-Repräsentation da drin. Nichts anderes ist
alles als Bit repräsentiert. Ich kann dieser Bit-Repräsentation nicht ansehen,
was es eigentlich ist, was es bedeuten soll.
Also ist das hier eine ganze Zahl oder ist es
ein Buchstabenpaar oder ist es eine Speicheradresse oder ein Maschinenbefehl?
Ich sehe es nicht. Ich habe also auf der,
auf der reinen Bit-Ebene ein massives einen massiven Grad an Abstraktionen erreicht,
auch übrigens eine wesentliche Quelle für Verarbeitungsfehler,
dass nämlich der blinde Zugriff auf diese Speicheradresse unter einer falschen Interpretation,
dann zu einem Segmentation Falt führt.
Weil ich eben plötzlich einen Pointer habe,
der nie als Pointer gemeint gewesen ist.
Und da hat man auch wieder das Problem der Abstraktion,
aber andererseits, wir haben nichts anderes als diese Bits.
Wo diese Mantik der Bits ergibt sich immer erst aus
ihrer Verwendung, in den Bits selber steckt keine drin
Das ist also Abstraktion durch Verbergen. Wir versuchen also,
diese hochgradige Abstraktion, die wir dort unten haben,
vom Nutzer zu verbergen und haben dann eben überhaupt erst die Voraussetzung dafür,
dass wir mit dieser Hardware auch zuverlässig umgehen können.
Beispiele dafür sind also etwa Go-To-Concident Harmful, wie gesagt,
die gesamte Steuerung des Programms auf der Maschinenebene funktioniert über Sprungbefehle.
Irgendwann, und das ist schon sehr lange her,
ist Ezgar Deixtra mal auf die Idee gekommen,
dass an diesen Sprungbefehlen ein gewaltiges Verständnisproblemen dranhängt,
weil ich eben dem Programm nicht mehr entnehmen kann,
wie ich in einen bestimmten Teil des Codes gekommen bin.
Weil Sprungbefehle gehen munter durch den gesamten Text hindurch und ich kann nicht mehr sagen,
bin ich jetzt dorthin gekommen,
weil ich von oben mich dort hineingearbeitet habe oder bin ich
von der Seite über den Sprungbefehl da reingekommen,
aus unterschiedlichen Zuständen bin ich jetzt in einem Stück Programmtext gelandet.
Und dann hängt die Interpretation dessen, was dieser Programmtext verursacht,
davon ab, was in der Vergangenheit passiert ist.
Und dieses Go-Tofa, die Sprungbefehle,
die vernebeln mir gerade die Sicht darauf,
wie bin ich eigentlich in einem bestimmten Zustand geraten
Und die wesentliche Erkenntnis war, und deshalb gibt es heutzutage
keine Programmiersprachen mehr, die noch einen Kulturbefehl hatten.
Ich bin noch groß geworden damit, dass Kulturbefehle in jeder Programmiersprache
drin waren und dass man auf die Art und Weise Schleifenkonstrukte programmiert hat.
Auf der Assembler-Ebene hat man es auch heute noch, ja.
Aber die höheren Programmiersprachen haben alle gar keinen Go-To-Befehl mehr.
Und extra Deixtra hat 68, letztes Jahrhundert erkannt,
dass man sie ihr eigentlich gar nicht braucht.
Dass man es immer umwandeln kann in einem Programm,
was kein Go-To enthält. Das ist also eine Möglichkeit der
Hardware, die da ist.
Ich kann
die Go-To-Befehle benutzen
Aber ich mache es nicht. Da steht ein Verbotsschild,
das sagt, tu es nicht. Es ist schlecht, es ist gefährlich.
Und das ist eigentlich ein wesentlicher Teil des Fortschrittes der Informatik,
dass man erkannt hat, was man alles nicht tun soll.
Irgendwann hatten wir mal einen Gast im Kolocviium, der gesagt hat, naja,
bestimmt hat die Informatik in den letzten Jahren ja noch viel bessere Möglichkeiten entdeckt,
dieses Problem zu lösen.
Falsch. Der wesentliche Fortschritt der Informatik besteht darin,
dass sie waren und Verbotsschilder aufgestellt hat und gesagt hat,
tue dies nicht, tue jenes nicht,
mach das nicht,
weil es sind gefährliche Dinge
Gut, ein solches gefährliches Ding ist eben die Werdemanipulation.
Ich hatte schon darauf hingewiesen,
dass die Berechnungsergebnis eben vom Zustand eines Programms abhängig ist,
dass es nicht so groß wie das Problem,
was da oben steht.
Dort ist es die Frage, wie bin ich überhaupt in den Zustand gekommen?
Hier unten ist es die Frage nur, in welchem Zustand befinde ich mich?
Und weil dieser Zustand zum Entwicklungszeitpunkt nicht sichtbar ist,
ich weiß nicht, wie das Programm in bestimmte Zustände gerät,
möglicherweise auch durch externe Einflüsse.
Auch das kann sein. Deshalb gibt es Seiteneffekte und
die Seiteneffekte sind also im Hinblick auf die Programmiersicherheit
ein Problem
Und objektorientierte Programmierung ist ein Weg, damit fertig zu werden.
Er hatte schon gesagt, dort werden nämlich die Zustandsänderungen nur über wohldefinierte Schnittstellen erlaubt.
Und an den Schnittstellen vorbeiprogrammieren kann ich nicht mehr.
Ein Verbotsschild oder besser gesagt ein Zaun, der dort aufgebaut wurde
, hier nicht weitergehen. Es ist gefährlich. Man lässt
den Programmierer nicht mehr selbst an die Repräsentation ran,
sondern Zugriff nur über die Schnittstellen und Einschränkung auf lokale Gültigkeitsbereiche,
dass ich also globale Effekte damit ringern kann.
In der funktionalen Programmierung ist es, dass die Wertemanipulationsmöglichkeiten zurückgedrängt werden.
Das ist also explizites Kennzeichen der gefährlichen Operationen, Set-Bang.
Aber ich habe immer noch nicht lokale Gültigkeitsbereiche und eines der
zentralen Probleme in der funktionalen Programmierung war ja immer rauszukriegen,
was ist eigentlich der Gültigkeitsbereich eines Namens?
Ja, und auf die Art und Weise habe ich auch wieder
noch Konfliktpotenzial und das verschwindet hier in der Logikprogrammierung vollständig.
Wertemanipulation geht gar nicht mehr. Es ist ein Privileg des Verarbeitungsmodells,
der Programmierer kommt an die Werte selber nicht aktiv ran und
ich habe extrem lokale Gültigkeitsbereiche,
das werden wir
schon sehen
Meine Klaus, wir teilen das Programm in Klauseln auf und
eine Variable ist immer nur lokal in dieser Klausel gültig.
Und Klauseln sind sehr überschaubare Einheiten, sodass also globale Effekte da nicht auftreten können.
Also wir versuchen, das Problem, was wir dort haben,
zu verbergen, das ist immer die Idee dabei.
Also zusammenfassend, Abstraktion ist ein wesentliches Element der Softwareentwicklung,
wir kommen nicht umhin, erst wenn wir abstrahieren,
kriegen wir kompakte, überschaubare Problemlösungen,
kann aber leicht zur Fehlerquelle werden und erfordert deshalb Sorgfalt und Disziplin.
Und das ist eine Botschaft, die immer unbequem ist.
Also sowohl in der Entwicklung, aber auch in der Dokumentation.
Denn die Dokumentation ist genau dieser zwischenmenschliche Kommunikationsprozess, der wesentlich ist.
Und insbesondere, und jetzt kommen wir in ein Paradox hinein.
Ich muss dies insbesondere für die Dinge machen,
die ich als irrelevant betrachte. Solange ich explizit darüber nachdenke,
was wohl irrelevant sein mag, mag das funktionieren.
Aber es sind eben auch die Sachen, an die ich
nicht gedacht habe. Das heißt, ich muss das dokumentieren,
woran ich
nicht gedacht habe
Ja, und das stellen Sie sich mal vor,
wie das über die Bühne gehen kann.
Auf jeden Fall brauche ich die Fähigkeit des Hineinversetzens in den Adressaten.
Und das ist eine wesentliche Fähigkeit, die sie erwerben müssen,
dass sie oberster Grundsatz ist, so dumm, wie es kommt,
kann man nicht denken. Es wird immer Menschen geben,
die ein Ding anders sehen, als sie es gesehen haben.
Und sie müssen dieses Anderssehen vorhersagen können. Ich erinnere mich genau,
als diese Veranstaltung noch im ersten Semester lokalisiert war,
da hat man in der ersten Übung immer solche Sachen,
was ist ein Algorithmus, was ist ein Programm und so weiter.
Und zu der Frage, was ist ein Algorithmus?
Gab es dann, also haben wir uns immer überlegt,
man muss Dinge aus dem Alltagsleben irgendwie algorithmisch beschreiben,
also hat man sowas wie Zähneputzen oder wie Binden einer Schleife
Und was kam als Antwort heraus? Wie bindet man
eine Schleife? Es gibt Duschleifen vor Schleifen und Waldschleifen.
Man kann nicht so dumm denken, wie der Leser eines,
einer Aufgabe, die es tatsächlich interpretieren kann.
Es muss nicht sein, aber es kann sein,
dass jemand mit seiner persönlichen Interpretation herkommt.
Und die ist nicht dumm gewesen, ja,
in dem Kontext, wir reden über Programmierung.
Ja, da ist es naheliegend über Schleifenkonstrukte in der Programmierung
zu reden und nicht über die Schleifen,
die ich am Schuh habe
Gut, ja, also hier unten, die Intention muss
irgendwie dokumentiert werden und dafür hat man zahlreiche Formen entwickelt.
Programmkommentare sind das Wichtigste sicherlich, darüber werden wir uns öfter unterhalten.
Handbücher, Gebrauchsanweisungen, Schulungen und was auch immer da zur
Verfügung steht. Jetzt kommen wir tatsächlich zur relationalen Abstraktion.
Was macht jetzt die Abstraktion in der relationalen Programmierung aus?
In der Logikprogrammierung. Das, was die Logik,
Logikprogrammierung versucht oder ansatzweise tut, ist,
dass sie nicht nur von solchen Sachen wie Hardware und dergleichen abstrahiert,
sondern dass sie vom Algorithmusbegriff abstrahiert.
Der Algorithmusbegriff wird klassischerweise immer als der fundamentale Begriff der Informatik
angesehen. Das als allererstes mal geklärt wird,
was ist eigentlich ein Algorithmus und wie komme ich eigentlich dazu?
Ein Algorithmus in einem Sprach umzusetzen und dann von einer Maschine
ausführen zu lassen. Hier versucht man, dass man auch
den Algorithmusbegriff nicht mehr in den Mittelpunkt stellt.
Wie geht das überhaupt? Klassischerweise ist der Algorithmus also immer
irgendeine Form von Beschreibung, meistens auch noch parmetisierbar,
dass man verschiedene Sachen einstellen kann für irgendeinen dynamischen Ablauf.
Also Zähneputzen binden einer Schulschleife und so weiter.
Ich habe Eingabedaten oder einen Zustand, der vorher existiert.
Ich habe einen prozeduralen Ablauf in einer bestimmten Reihenfolge und dann
habe ich Ausgabedaten oder einen Zustand, der nach der Verarbeitung existiert.
Also die Schleife ist gebunden oder die Zähne sind sauber.
Und die Logikprogrammierer, Logikprogramme lassen jetzt im Prinzip beliebige Verarbeitungsrichtungen zu.
Also dieser prozedurale Ablauf, der klassischerweise von den Eingaben zu
den Ausgaben führt, der dieser Unterschied wird aufgehoben.
Es ist nicht mehr klar, was Eingabedaten sind und was
Ausgabedaten sind. Das wird erst festgelegt,
wenn ich das ganze Ding verwenden will
Zum Entwicklungszeitpunkt soll das noch beliebig sein. Das ist eine der Zielstellungen dabei.
Das habe ich vorhin als Richtungsunabhängigkeit bezeichnet und das wird ein zentrales Thema sein.
Wenn ich also in der funktionalen Programmierung diese Member-Funktion hier habe mit einem Element,
was ich suche und ob es in der Liste enthalten ist,
dann kann ich das immer nur aufrufen,
indem ich das Ding mit einem Element und einer Liste versorge.
Anders geht es nicht. Und dann wird es mir
den Funktionswert liefern und der Funktionswert ist eben ein False,
wenn die Liste leer ist oder ist ein Truh,
wenn die das erste Element Der Liste, sorry,
das erste Element der Liste, gleich dem gesuchten Element ist,
dann ist es wahr.
Und ansonsten muss ich eben im Rest der Liste weitersuchen.
Einfaches kleines Scream-Programm. Also, die einzige Abbildung,
wie ich das Ding verwenden kann, es,
ich gebe ein Element vor,
ich gebe eine Liste vor und ich kriege einen der beiden Wahrheitswerte heraus.
Ich rufe also auf, ist A-Element der leeren Liste und
ich kriege ein False heraus, ist B, ein Element der Liste
A-B-C. Ich kriege ein True heraus. Ich frage es D,
ein Element der Liste A-B-C und ich kriege ein False heraus.
Was anderes kann ich damit nicht machen.
Anders in der Logikprogrammierung
Ich nehme ein Prädikat und sage, dass erst,
dass ich hier hinten eine Listen-Notation, das erste Element einer Liste
hinten vor diesem senkrechten Strich steht immer das erste Element.
Das erste Element der Liste ist gleich dem, was hier vorn steht.
Sogenannte Co-Referenz. Die Details kommen später alle noch ganz ausführlich.
Das ist jetzt nur um einen ersten Eindruck zu bekommen.
Also entweder das erste Element ist das Gesuchte, dann bist du fertig.
Oder aber das erste Element ist nicht das Gesuchte,
dann musst du in der Restliste nachschauen,
ob dann das gesuchte Element in der Restliste enthalten ist.
Das ist das Programm. Das beschreibt nur diese beiden Fälle
entweder Ist es das erste Element oder ist es Element der Restliste?
Nichts anderes wird hier beschrieben und alles andere ist dem System überlassen.
Das kann ich jetzt genauso aufrufen, wie das funktionale Programm.
Ich kann also ein Element vorgeben, eine Liste vorgeben
und ich kriege einen Wahrheitswert raus.
Also, wenn ich in das Prolog-System eingebe,
ist A-Element der leeren Liste, sagt mir das Prolog-System Falls.
Was heißen soll? Nein. Ich frage ist B-Element
dieser Liste ABC und ich kriege ein Truh heraus.
Oder ich frage jetzt D-Element dieser Liste und ich kriege ein Falls heraus.
Jetzt kommt aber der entspringende Punkt. Das ist alles noch
wie in der funktionalen Programmierung. Jetzt kommt der springende Punkt
. Ich kann andere Aufrufrufvarianten dieses Prädikats verwenden.
Nämlich in diesem Fall, ich gebe eine Liste vor und
ich möchte
das Element wissen
Also, ich rufe das jetzt auf,
mit der leeren Liste, die habe ich vorgegeben.
Aber hier gebe ich jetzt eine Variable an und ich sage mir,
welche Elemente sind in der leeren Liste enthalten?
Und er sagt mir, falls, was heißen soll,
ich konnte keine finden. Ich kann das Gleiche mit einer
richtigen Liste aufrufen, also einer gefüllten Liste und frage,
welche Elemente sind denn in der Liste ABC enthalten?
Und die erste Antwort, die lautet, das Element A.
Und wenn ich dieses Semikole und da steht hier dafür,
geben Sie mir Alternativen oder gib mir Alternativen.
Gibt es noch weitere Lösungen für diese Fragestellung?
Und er kommt mit der zweiten Lösung heraus,
ihr habt B es auch in der Liste enthalten
Und wenn ich wieder nach einer alternativen Frage,
sagte er mir, auch C ist da drin enthalten,
jetzt kommt ein kleiner Clou, dass das System schon erkannt hat,
ein viertes Element gibt es nicht.
Und deshalb ihr gar keine Interaktionsmöglichkeit mehr anbietet.
Manchmal kann ich auch dann wieder noch nach Alternativen fragen und
dann würde er mir im letzten Schritt sagen, nein,
weiterer habe ich nicht gefunden.
Also eine zweite Variante, die jetzt das als Input nimmt,
die zweite Argument und das erste Argument als Output betrachtet.
Wie gesagt, im ersten Falle nicht gesagt,
aber im ersten Falle sind beide Argumente Inputargumente.
Ich muss sowohl das Element vorgeben als auch die Liste.
Jetzt habe ich nur noch die Liste vorgegeben,
nicht mehr das Element.
Und ich kriege das Element als Ausgabeinformation
Beziehungsweise scheitern natürlich auch, wenn es keine Antwort darauf gibt,
dann kriege ich wieder einen Wahrheitswert draus.
Aufruf Variante 3 ist, ich gebe ein Element vor
und frage, in welchen Listen ist das enthalten?
Und ich kriege als erste Antwort die Antwort, ja,
es ist da, wo das erste Element der Liste ist.
Wenn ich nach Alternativen frage, kriege ich die Antwort,
es ist die Liste, die USA als zweites Element enthalten ist.
Sowohl über das erste Element als auch über die weiteren Elemente kann ich nichts aussagen.
Wenn ich wieder nach Alternativen frage, kriege ich die Antwort,
ja, Es könnte auch das dritte Element der Liste sein.
Es könnte auch das vierte Element der Liste sein.
Soll hier andeuten, ich habe nicht nach weiteren Möglichkeiten gefragt.
Es ist das erste Beispiel, was wir sehen,
wo wir unendlich viele Antworten kriegen.
Denn natürlich gibt es keine Obergrenze für die Länge einer Liste.
Wann immer ich nach einer weiteren alternativen Frage werde ich eine weitere Alternative kriegen?
Modulo, der Hauptspeicher, der Hardware-Ressourcen des Systems.
Wenn der Hauptspeicher irgendwann mal voll ist, ist er voll,
dann bricht das System zusammen. Aber im Prinzip geht es erst mal,
ja, wir sind ja nicht auf genau die drei Antwort,
das könnte das erste Element sein, das könnte das letzte Element sein,
das könnte irgendwo bitte.
Das gucken wir uns noch an. Wenn wir da uns genauer mit Unterspezifikation befassen.
In diesem Falle nein, aber in einigen Fällen geht es.
Das kann man tatsächlich machen. Also die Antwort ist,
es wird in einigen Fällen die Möglichkeit geben,
mit einem Ausdruck unendlich viele Ergebnisse zu beschreiben.
Das wird der interessante Fall sein.
Und der wird uns des Öfteren über den Weg laufen.
Und wir haben auch die Möglichkeit zu sagen,
ich gebe dir gar nichts vor,
zähle mir bitte alle Elementen und die zugehörigen Listen auf.
Das geht auch, liefert in diesem Falle aber keine
sonderlich interessanten Ergebnisse.
Deshalb habe ich
das hier rausgelassen
Also, was hier passiert ist, Logikprogrammiere,
Logikprogramme implementieren keinen konkreten Algorithmus,
der von einer Eingabe zu einer Ausgabe führt,
sondern sie versuchen, die Beziehungen zwischen Ein- und Ausgabe zu beschreiben.
Und da ich die Beziehungen kenne, kann ich sowohl von,
zwischen Ein- und Ausgabe, zwischen verschiedenen Argumenten zu beschreiben.
Und wenn ich die Beziehungen kenne,
kann ich im Idealfalle, nicht immer klappt das,
von dem einen Argument auf das andere schließen oder von dem anderen auf das erste.
Und das ist genau die Sichtweise, die die relationalen Datenbanken
auch zugrunde legen. Das heißt also,
Logikprogramme kodieren nicht das individuelle Lösungsverfahren, sondern das Wissen,
was ich brauche,
um die Lösung zu finden
Das Finden der Lösung. Das soll bitte schön das System machen,
das soll nicht der Programmierer aufschreiben. Kai von Look,
das ist ein Kollege von der Fachhochschule, sorry von der,
von der Hochschule für Angewandte Wissenschaft oder University of Applied Science in Hamburg,
der hat das in die schönen Worte gefasst.
Logikprogrammierung heißt, sagen, wie es ist,
nicht sagen, was zu tun ist, sondern sagen,
wie die Welt beschaffen ist.
Und das heißt, im Allgemeinen Fall sind solche Logikprogramme dann richtungsunabhängig.
Das heißt, ich muss zum Entwicklungszeitpunkt nicht spezifizieren,
wie ich sie später mal gebrauchen will,
in welcher Richtung.
Wir haben das eben
eine Member-Prädikat gesehen
So, das heißt aber auch, dass die algorithmischen Details,
wie ich jetzt die einzelnen Elemente da finde,
die stehen in dem Programm gar nicht drin,
aber irgendwo müssen sie sein.
Ja, es ist ja keine Magie, die hier passiert.
Und die stecken jetzt also im Verarbeitungsmodell drin oder mit anderen
Worten in der abstrakten Maschine, die unser Programm abarbeitet.
Und das hat Bopo Kowalski dann, das ist der Erfinder von Edinburgh Prologe,
das ist die Syntax, die wir auch heute noch verwenden.
Das hat er in die griffige Formel gebracht,
dass ein Algorithmus eigentlich aus zwei Sachen besteht.
Das eine ist die Logik, das ist das,
was die Zusammenhänge zwischen den einzelnen Bajablen beschreibt und der Steuerinformationen,
die sagt, wie soll ich in welcher Reihenfolge was machen,
damit ich ein Ergebnis finde.
Und Die Kontrolle, die Steuerung, die wird weg, abstrahiert.
Die wandert in die abstrakte Maschine hinein. Das ist ein
universelles Programmschema, was abgearbeitet, was immer abgearbeitet wird.
Und damit müssen wir uns als erstes befassen, wie werden Prolog-Programme eigentlich abgearbeitet?
Das müssen wir als erstes lernen. Und dann müssen wir lernen,
wie wir jetzt verschiedene Sorten von Beziehungen zwischen Argumentstellen aufschreiben können,
also wie unser Programm aussieht, damit diese abstrakte Maschine das Ganze verarbeiten kann.
Also nochmal als Merksatz,
Verarbeitungsrichtung steht üblicherweise oder typischerweise nicht im Programm drin,
sondern wird
erst beim Aufruf eines Programms
tatsächlich festgelegt
Und das wird eine der Konsequenzen sein. Wir müssen also
nicht immer nur sagen, hallo, hier ist das Programm.
Sondern wir müssen dazu sagen, in welchem Aufruf Varianten kann dieses Programm
auch verwendet werden? Also dieses Member-Programm, was Verfügung hat,
gesehen haben, kann in jeder Beliebigenaufrufrichtung verwendet werden.
Da muss ich nicht, da muss ich keine Einschränkungen vorgeben.
Wir werden aber immer sehr wach sein müssen,
um zu gucken, unter welchen Bedingungen sind dort Einschränkungen erforderlich,
dass irgendeine Verarbeitungsrichtung plötzlich nicht mehr geht.
Und man muss zu jedem Programm dazu sagen,
in welchen Aufruf Varianten darf es
tatsächlich verwendet werden
Testen, beispielsweise wird auf die Art und Weise erheblich komplexer,
als es in der emperativen oder funktionalen Welt ist.
Okay, es gibt dann noch eine ganze Reihe von
hybriden Modellen, dass man verschiedene Verarbeitungsmodelle miteinander kombiniert.
Es ist sehr oft der Fall,
dass man emperative Verarbeitung mit Elementen der funktionalen Programmierung koppelt.
Es ist sehr oft der Fall,
dass man ein emperatives mit objektorientiert koppelt,
aber auch funktionales mit objektorientiert koppelt,
dass man funktionale Elemente in dieses logikorientierte Paradigma einbaut,
das werden wir kennenlernen
Weil wir sonst nicht vernünftig auch Athmetik betreiben können,
dass man funktional mit relational koppelt gibt, ist,
dass man logikbasiert und konstrent basiert,
koppelt und so weiter und so fort.
Also viele Programmiersprachen sind tatsächlich hybride Angelegenheiten oder Twitter,
die die Charakteristika von verschiedenen Welten kennen.
Also wir müssen immer unterscheiden zwischen der reinen Welt der Logikprogrammierung und
der realen Welt der Umsetzung in einer Programmiersprache wie Prolog.
Also Prolog hat nicht nur Logikprogrammierungselemente, sondern auch funktionale Elemente
an bestimmten Stellen
Und das bringt uns dazu, dass wir über Programmierstile reden.
Wir können also da solche Verarbeitungsmodelle, auch Twitter sind,
eben hybride Modelle sein können,
kann man verschiedene Programmierstile in einem Verarbeitungsmodell kombinieren.
Und das heißt also, jedes Verarbeitungsmodell begründet einen bestimmten Programmierstil,
ist aber nicht auf diesen eingeschränkt.
Ich kann in der Logikprogrammierung auch imperativ programmieren.
Wir hatten mal den Fall in einem Praktikum,
wo ein Student bis zum Schluss versucht hat,
imperative Programme mit den Mitteln der Logikprogrammierung
zu schreiben
Der war dann völlig isoliert, hat in der Ecke gesessen und seitenweise,
wirklich seitenweise, richtige Stapel von Programmcode erzeugt.
Er war nicht in der Lage, mit jemandem zu kommunizieren,
was er dort eigentlich treibt.
Und im Endeffekt war das sozusagen eine Art Sackgasse,
die da beschritten worden ist, die nicht zum Erfolg geführt hat.
Also wir können gerne diskutieren, wie man imperativ programmiert im Prolog,
aber es ist nicht produktiv, das zu tun.
Was man idealerweise machen sollte, ist,
weil eben bestimmte Programmiersprachen bestimmte Programmierstile besonders fördern,
sollte man eigentlich immer gucken,
was ist mein Verarbeitungsproblem
Welches Verarbeitungsmodell ist besonders gut geeignet mit diesem Verarbeitungsproblem umzugehen?
Dann die Frage ist, was ist der richtige Programmierstil gegeben, dieses Verarbeitungsmodell?
Und dann kann man die Frage stellen, welche Programmiersprache sollte ich eigentlich wählen?
So würde in meinen Augen die ideale Welt aussehen.
Leider ist die Welt nicht ideal, sondern real.
Und die Frage, welche Programmiersprache nehme ich?
Ist immer die, die zuerst gestellt wird.
Die ist durch zahlreiche Faktoren bedingt. Einerseits,
was kenne ich, was habe ich an Legacy Code,
also was an Altlasten in irgendeinem Kontext vorliegen,
die weitergeentwickelt werden müssen, die eingebaut werden müssen,
für Qualifikationen habe ich vorliegen und so weiter.
Also in den meisten Fällen wird das Ganze umgekehrt aufgezäumt,
dass man mit der Programmiersprache anfängt und dann sich zum Verarbeitungsproblem
weiter hangelt mit dem Risiko des Scheiterns.
Ich habe schon eine Bachelorarbeit betreut, die hat mit der Programmiersprache angefangen.
In diesem Fall war es keine universelle, sondern eine eingeschränkte.
Es stand am Anfang fest, ich will Mindmaps verwenden für das Problem.
Und ich habe drei Monate lang vergeblich versucht zu erklären,
es gibt ein Mismatch zwischen Mindmaps und dem Verarbeitungsproblem.
Das wurde nicht ernst genommen. Zum Schluss stand die Erkenntnis
der Bachelorarbeit,
so geht es nicht
Ja, also, dieser Gang des Nachdenkens ist eigentlich der zu bevorzugende,
nur leider Gottes ist er oftmals nicht anzuwenden.
In diesem Fall war es also klar,
die Vorgabe der Mindmaps kam von dem Unternehmen,
aus dem
die Aufgabe stammte
Okay, hier als Überblick jetzt nochmal, oh nein,
kein Überblick mehr.
Ich sehe gerade, meine Zeit ist abgelaufen.
Der Überblick kommt dann also nächsten Freitag und bis dahin
wünsche ich Ihnen ein schönes Wochenende und eine erfolgreiche Woche