Home Computer Computer Geschichte Site Map counter

Die Entwicklung der Programmiersprachen

Einleitung

"Hardware without Software is Noware". Was dieser Satz bedeutet, merken Sie schnell, wenn Sie einen Computer ohne vorinstalliertes Betriebssystem benutzen. Trotzdem wird bei der Geschichte des Computers die Entwicklung der Software - die sich auch in immer leistungsfähigen Programmiersprachen ausdrückt gerne übergangen. Dieser Artikel soll Abhilfe schaffen. Eine ausführlichere Darstellung der Geschichte einiger Programmiersprachen findet sich auch auf dieser Website.

Die Anfänge: Programmierer als „Drahtstöpsler“

Seit es Computer gibt, müssen diese auch programmiert werden. Bei den ersten Computern war dies nur durch Hardwareverbindungen möglich. Dazu wurden die Computer programmiert, in dem zwischen den einzelnen Verbindungen Leitungen geschlossen wurden. So bei dem allerersten Computern ENIAC und MANIAC. In einem Bericht 1947 über ENIAC heißt es: "Dieser Computer kann die Flugbahn eines Geschosses, die in zweieinhalb Sekunden durchlaufen wird, in eineinhalb Sekunden berechnen. Die Programmierung dauert eineinhalb Tage". Es ist leider nicht übermittelt ob dies satirisch oder ernst gemeint war. Der Speicher diente nur als Datenspeicher, der die Eingabedaten für die Berechnung zur Verfügung stellte. Aufgabe von ENIAC war es Geschosstabellen zu berechnen. Das bedeutet er musste ein und dieselbe Berechnung mit wechselnden Winkeln, Winden, Lufttemperaturen und Drücken machen und dabei eine Tabelle erstellen, wie weit das Projektil fliegt. Weder ENIAC, MARK II noch die Rechner von Zuse waren im heutigen Sinne programmierbar, sondern die Hardwareverdrahtung legte die Funktion fest, daher waren sie auch wirkliche "Computer" im engeren Sinn, da sie nur Berechnungen durchführen konnten. Vorher war die Bezeichnung "Computer" für eine stupide Rechenarbeit z.B. in der Astronomie üblich und es gab eine Zeitlang auch den Beruf eines "Computers".

Aus dieser Zeit stammt auch der erste Bug: es war eine Motte, die zwischen die Röhren eines Rechners geriet, und dadurch einen Kurschluss verursachte. Seitdem bezeichnet man Programmfehler als "Bug": englisch für Käfer. Diese Bezeichnung hat sich sehr lange gehalten, denn noch in den und späten siebziger Jahren hieß das Programm zum Debuggen im Betriebssystem CP/M "DDT", das war die Abkürzung von Disk Debugging Tool. Gleichzeitig gab es aber auch der Name eines damals populären Insektizids.

Natürlich war die Hardwareverdrahtung von Rechnern auf Dauer nicht nur um mühsam, sondern beschränkte die Möglichkeiten der Programmierung doch sehr. So waren z.B. Verzweigungen kaum möglich. Nachdem man aber entdeckt hatte, dass man über einen Speicher Programme ablegen konnte, und damit die Rechner steuern konnte, begann das erste "Richtige" Programmieren von Rechnern. Die Idee wurde jahrzehntelang dem Mathematiker John von Neumann zugeschrieben, doch ist dies mittlerweile umstritten. Anstatt von einer "von Neumann Architektur" zu sprechen redet man heute von "speicherprogrammierten Rechnern". John von Neumann schlug schon 1945 vor, dass die Steuerung des Computers und die Daten in einem gemeinsamen Speicher liegen. Das war damals ein Diskussionentwurf für die Entwucklung von ENIAC, der jedoch nicht gefolgt wurde. Der EDVAC dessen Enztwucklung 1946 begann und 1949 abgeschlossen wurde, war der erste speicherprogrammierbare Computer.

Zuallererst wurden die Daten in binärer Form eingegeben. Das heißt, man legte Schalter für eine Eins um, oder ließ sie in Ausgang Stellung für eine 0. Natürlich war dies keine sehr elegante Methode. Auch der allein erste PC – der Altair 8800 hatte zuerst nur die Möglichkeit über mit solche Kippschalter Daten Eingegebenen.

Das Hexadezimalsystem und Maschinensprache

Der nächste Schritt war diesen Vorgang zu vereinfachen. Obgleich damals es noch nicht Rechner mit standardisierten Bitbreiten wie 8, 16, 32, 48 oder 64 Bit gab, sondern man jeweils die Bitbreite nach den technischen Möglichkeiten wählte bürgerte sich bald das Byte als grundlegende Einheit ein. Ein Byte kann man aber in zwei "Nibbeln" à 4 Bit mit zerlegen. Damit man ein solches Nibbel in einer einzigen Ziffer ausdrücken konnte besann man sich auf das Hexadezimalsystem. Bei dem Hexadezimalsystem kommen zu den Grundzahlen des Zehnersystems 0 bis 9 auch noch die Buchstaben A bis F. Sie stehen für die Werte 10 bis 15. Damit kann man mit einer Stelle Werte von 0 bis 15 ausdrücken. Mit zwei Stellen ist der Wert eines Bytes anzugeben. Jede weitere vordere Stelle entspricht 16 n-1 (n: Stellennummer von hinten). So hat der Wert " 3A5F " folgenden dezimalen Wert: ( 3 × 4096) + (10 × 256) + (5 × 16) + 15 = 14943 im Dezimalsystem.

Hexadezimalzahlen gibt es auch heute noch, je nach Sprachen haben Sie eine besondere Notation, in C z.B. durch Vorstellen von "0x", in Pascal durch ein "$", in manchen BASIC Dialekten durch ein "&" und in Assembler durch ein "H" am Ende.

Mit diesem System war es nun möglich die Eingabearbeit erheblich zu vereinfachen. Denn anstatt acht Schaltern mussten nur noch zwei Zahlen eingegeben werden. Trotzdem sehr benutzerfreundlich war dies nicht, wer wusste denn schon, was hinter den einzelnen Werten stand?

Assembler

Die allererste Programmiersprache im heutigen Sinn war daher Assembler: ein Assembler ist nichts anderes als ein Programm welches für die Befehle, die ein Computer versteht - und deren Befehlsworte jeweils einen bestimmten Code haben - Worte vorsieht, die sich ein Mensch merkten kann. Assembler ist daher für jeden Prozessor spezifisch. Dies ist heute vielleicht nicht mehr so von Bedeutung, da es nur noch wenige Prozessoren gibt, die weit verbreitet sind, doch in der Frühzeit des PCs gab es sehr viele Rechner mit unterschiedlichen Prozessoren. Jeder hatte eine eigene Programmiersprache. Manchmal waren diese sogar unterschiedlich, obwohl die Prozessoren zueinander kompatibel waren.

Ein Beispiel: die folgenden Bytes (alles in hexadezimal)

21 00 10 11 00 20 19 22 00 30

sagen wohl niemanden etwas. Sie stehen für die folgenden Befehle des Prozessors Z80:

21 00 10 LD HL, 1000H
11 00 20 LD DE, 2000H
19 ADD HL, DE
22 00 30 LD (3000H), HL

Das ist schon besser verständlich, in Normalsprache heißt es Folgendes:

- Lade den Wert 1000H in das Prozessorregister HL
- Lade den Wert 2000H in das Prozessorregister DE
- Addiere die beiden Register HL und DE, das Ergebnis ist danach in HL
- Speichere das Ergebnis in der Speicherstelle 3000 im Speicher ab.

Das Ganze ist also eine einfache Ganzzahladdition. Sie hätten wahrscheinlich geschrieben "Ergebnis = &1000+&2000". So benötigt schon eine Addition 4 Rechenschritte, zum Trost ist aber schon ein Z80 Prozessor (obgleich schon veraltet) so schnell, dass er 250.000 dieser Rechenschritte (bei 4 MHz Takt) pro Sekunde ausführen kann. (H und & stehen für die Notation der hexadezimalen Zahlen in Assembler und BASIC). Weiterhin bietet der Assembler an, für Speicherzellen Namen zu vergeben und Adressen für Sprünge zu berechnen, sodass er auch hier eine Erleichterung brachte.

Assembler hielt sich relativ lange. Denn mit Assembler konnte man das Maximum aus dem Rechner herausholen. In Zeiten, wo Speicherkapazität und Rechenleistung noch begrenzt waren, war dies ein wichtiges Kriterium. Allerdings ist auch bei Assembler ein grundlegendes Problem noch nicht gelöst: das Testen der Programme. Zum Testen musste man mit einem speziellen Programm das zu untersuchende Programm laden und an der Stelle, wo man den Fehler vermutete Haltepunkte setzen oder schrittweise den Programmablauf verfolgen. Besonders komfortabel war dies nicht. Zudem konnten selbst dann noch Befehle den ganzen Rechner zum Absturz bringen. Ein Nachteil war weiterhin, dass es nicht den Assembler gab - und auch heute noch gibt. Er ist spezifisch für jeden Prozessor. So hat ein Pentium einen anderen Befehlssatz als ein Power PC Prozessor oder ein Alpha Chip. Ja es gibt sogar kleine - aber in bestimmten Gebieten wichtige - Unterschiede in einer Familie z.B. zwischen den Prozessoren Pentium 4, Pentium III und Athlon, was die Fließkommabefehle angeht.

Höhere Programmiersprachen

Sehr bald gab es daher die ersten höheren Programmiersprachen. Höhere Programmiersprache daher, weil es eine künstliche Sprache war, die sich nicht mehr an den Eigenheiten des verwendeten Rechners orientierte. Mitte der ab fünfziger Jahre kamen die ersten beiden höheren Programmiersprachen FORTRAN und COBOL auf den Markt. Noch waren die Computer in ihrer Leistung sehr beschränkt, sodass man diese Programmiersprache als spezialisierte Programmiersprachen bezeichnen kann. Spezialisiert daher, weil man bestimmte Probleme sehr gut in FORTRAN lösen konnte, während für andere Probleme COBOL eher geeignet ist. FORTRAN eignet sich hervorragend für Berechnungen, wie sie im naturwissenschaftlichen Bereich vorkommen und wurde daher auf Computern eingesetzt, die in der Forschung genutzt wurden. Bis heute hat es sich bei Supercomputern gehalten, denn zahlreiche Algorithmen für technische und naturwissenschaftliche Simulationen wurden zuerst in FORTRAN entwickelt. Auch heute werden Rechner wie die Cray (links) vor allem in FORTRAN programmiert.

COBOL dagegen hatte den Schwerpunkt auf die Verarbeitung von Daten gesetzt. Damit eignete sich diese Sprache für geschäftliche Aufgaben wie die Buchhaltung oder die Verwaltungen von Bankkonten. COBOL setzte sich dank der Marktmacht von IBMs Rechnern durch. COBOL ist eine Sprache für die Lösung wirtschaftlicher Probleme auf IBM Rechnern (wie dem populären System 360 rechts). Dank der Verbreitung der IBM Großrechner ist auch heute noch 70% aller Software in COBOL geschrieben - denn Software wird nur verbessert selten neu erfunden.

Mit den höheren Programmiersprachen kamen auch zwei unterschiedliche Konzepte zum Einsatz, die wesentlich für den Komfort beim Programmieren waren. Das allererste Konzept war das des Compilers. Ein Compiler ist ein Programm, welches einen Quelltext (eine Textdatei mit den Befehlen die man ausführen lassen möchte) in ein ausführbares Maschinenprogramm übersetzt. Der Compiler untersucht das ganze Programm und erzeugt daraus den Maschinencode. Entdeckt er Fehler, so meldet er diese den Benutzer. Dies geht solange, bis der Compiler keine Fehler mehr findet. Das Programm wird dann ausgeführt, und wenn es einfachere Fehler gibt, so erhält man eine Fehlermeldung, bei größeren Fehlern kann wiederum der ganze Computer abstürzen ohne Meldung. Das Schreiben der Programme erfolgte in einem Editor, das Übersetzen dagegen durch den Compiler. Damit hantierte man immer mit mindestens zwei Programmen, es konnten durch das Hinzufügen anderer Programmteile oder das Debuggen leicht 3 oder 4 sein.

Um das Programmieren einfacher und komfortabler zu machen und die Fehlersuche zu erleichtern hatte man daher den Interpreter in den sechziger Jahren entwickelt. Man verzichtete dabei auf Geschwindigkeit und gewann Komfort. Bei einem Interpreter ist das Programm, welches den Quelltext übersetzt mit dem Editor integriert. Der Quelltext wird nicht auf einmal übersetzt und ein ausführbares Programm erzeugt, sondern dies geschieht erst zur Laufzeit. Treten Fehler auf, so kann der Benutzer das Programm anhalten und diese Stelle im Editor untersuchen, wo der Fehler lag und ihn sofort beheben. Der Interpreter hat immer die volle Kontrolle über das Programm. Daher ist diese Methode bequemer. Der Nachteil ist das man wesentlich mehr Speicher benötigt (Interpreter, Editor, Quelltext und Programm teilen sich den Speicher) und zum Zweiten, dass man einen Programmteil, der 1000-mal durchlaufen wird, auch 1000-mal übersetzt, während die Compiler diesen nur einmal übersetzen müssen.

Eine zweite Anwendung des Interpreters war auch die Programmiersprachen maschinenunabhängig zu gestalten und nur geringe Anpassungen an unterschiedliche Computer vornehmen zu müssen. Dieses Konzept findet man bei BASIC, Pascal (der ursprünglichen Version) und Java. Dazu übersetzt ein Compiler den Quelltext in einem sogenannten Zwischencode oder Pseudocode. Dieser ist einfacher als der Quelltext und enthält grundlegendere einfachere Instruktionen. Dieser Zwischencode wird dann von einem Interpreter interpretiert. Der springende Punkt ist, dass der Compiler unabhängig von dem Rechner sein kann, auf welchem das Programm laufen soll. Nur der Interpreter - er hat einen einfacheren Code ausführen - muss jeweils an den Computer angepasst werden.

Eine Sprache für alle und weitere Abstraktionen

Den ersten höheren Programmiersprachen folgten bald weitere: LISP zur Bearbeitung von Listen und KI Programmierung, APL als Umsetzung der mathematischen Operationen in eine Programmiersprache oder BASIC als Lernsprache. Sehr bald gab es richtige Stammbäume wie "xx" stammt von "yy" ab.

Die vielen Programmiersprachen bedeuteten aber auch: Das Problem für Aufgabe × einen Spezialisten zu finden der Programmiersprache y beherrscht und auf dem Rechner z einen Compiler für y zu haben ... Kurzum: Mitte der sechziger Jahre gingen an verschiedenen Fronten die Suche nach einer universellen Programmiersprache los. Universell heißt, das sie geeignet war jedes Problem zu lösen, das bedeutete eine breite Basis von Befehlen und Datentypen. Der erste Versuch kam von IBM - PL/1 sollte die erste Universalsprache werden. IBM war damals schon marktbeherrschend und wahrscheinlich wäre das auch gelungen, wäre PL/1 für die damaligen Rechner nicht einfach zu groß und umfangreich gewesen.

Für die meisten heutigen prozeduralen Programmiersprachen spielt aber ALGOL eine wichtige Rolle. Algol setzte sich nie breit durch, ist aber der Ahne aller heutigen prozeduralen Programmiersprachen. Der Unterschied zu FORTRAN und COBOL war der Gedanke der strukturierten Programmierung. Man sollte die Probleme lösen ohne wild im Code herum zu springen durch die GO TO's von FORTRAN, BASIC und COBOL. Dies wurde gelöst durch elementare Schleifentypen und das Blockkonzept. Dieses haben alle Sprachen die nach Algol kamen übernommen. Algol erschien 1960.

Später kam Pascal. Pascal war eigentlich keine Sprache die als Programmiersprache für große Anwendungen gedacht war sondern eine Lehrsprache, aber durch die gute Lesbarkeit, die strenge Syntax die wenig Freiheiten und Fehler erlaubte wurde Sie zu einer wichtigen Sprache. Leider gab es in dem ursprünglichen Pascal wenige Dinge, die man für hardwarenaheZzugriffe brauchte. Da es eine Lehrsprache sein sollte, störte dies nicht, jedoch beim praktischen Einsatz. Bedenkt man, welchen Erfolg Pascal durch den Turbo Pascal Compiler auf dem PC hatte, so kann man sich ungefähr vorstellen, wo wir heute wären, wenn es einen solchen Compiler von Anfang an gegeben hätte. Pascal setzte den Gedanken der strukturierten Programmierung bei Daten fort. Es war nun möglich eigene Datentypen zu erschaffen und zusammengehörende Daten zu einem Record zusammenzufassen. Dadurch wurde das Programm erheblich besser lesbar und wartbar.

Später kam C. C hat einige Vorteile gegenüber den damals etablierten Sprachen gehabt: Der Sprachkern war klein, alles, was rechnerspezifisch war, wurde in Bibliotheken ausgelagert und C war schnell durch seine Maschinennähe. C war gedacht als "Superassembler": maschinennah, schnell und mit vielen Freiheiten (aber auch Verantwortung) für den Programmierer. Der eigentliche Siegeszug von C war aber die Verknüpfung mit UNIX. In dem Maße wie UNIX sich verbreitete sich auch C.

Modula entstand aus Pascal und setzte die Strukturierung von Daten und Code weiter fort: Basis war das Modul: Eine Einheit aus Daten und Code das man als Programmierer als Blackbox nutzen konnte und sich nicht um die Implementierung im Detail kümmern konnte. Modula hat sich kaum durchgesetzt denn inzwischen war die Konkurrenz schon groß. Im PC-Bereich übernahm Turbo-Pascal das Konzept von Modula als Units und so gab es keinen Grund auf Modula umzusteigen und bei größeren Rechnern dominierten schon C, FORTRAN und COBOL.

Zuletzt sollte man noch ADA erwähnen. Wenn es eine Supersprache gibt, dann ist es ADA. Die Sprache ist außerordentlich umfangreich und komplex, sie hat heute nur einen Einsatzort, den aber in fester Hand: Als Standardsprache des US-Militärs und auch für Entwicklungen die auf militärischen Ursprüngen basieren (die Flugsoftware von Ariane 5, die den Fehlstart beim ersten Flug verursachte, war in ADA geschrieben). Sie wird daher an Unis gelehrt, leider teilt die Wirtschaft diese Vorliebe für ADA nicht.

C setzte sich jedoch auf breiter Front durch, zuerst verbreitete sich UNIX in der mittleren Datentechnik, ab Ende der siebziger Jahre tauchten die ersten Minicomputer auf - Rechner unterhalb der Großrechner, die auch für kleine Forschungsinstitute bezahlbar waren und später Workstations. Auf diesen setzten sich UNIX und C durch. Auf den Großrechnern hielten sich noch lange COBOL und FORTRAN - vor allem aber auch, weil man schon etliche Software in diesen Sprachen hatte, die man weiterentwickelte. Der Y2K (Jahr 2000) Bug ist ein typischer COBOL-Bug, denn alle anderen Sprachen speichern Zahlen nicht als BCD Ziffern (pro Stelle 1 Byte) sondern binär. Später wurde C/C++ als Standardsprache für Windows auch auf dem PC der Standard.

Die Annäherung der Sprachen

Auch wenn in den achtziger Jahren noch neue Sprachen auftauchten, wie OCCAM für die Entwicklung vor parallelen Programmen, Smalltalk für objektorientiertes Programmieren etc. begannen zwei wichtige Trends: Der erste war, das man endlich aufhörte dauern neue Sprachen zu kreieren sondern begann das Fehlende aus den schon existierenden Sprachen zu übernehmen, der Zweite war die objektorientierte Programmierung.

Der erste Trend war der: Fehlte in einer Sprache etwas, so konnte man früher hoffen, das ein Gremium nach langen Jahren der Beratung einen neuen Standard verabschiedete, der dann irgendwann neue Möglichkeiten enthielt oder man schrieb eine neue Sprache. Zahllose Varianten entstanden so als Hybride z.B. Comal als Zwitter von BASIC und Pascal. Zumindest auf den PCs, wo der Zieluser der freie Programmierer war, der meistens nicht 20,30 Jahre alte Programme pflegen musste begann nun aber die Annäherung.

Ein Beispiel wie dies geht zeigt die Version von Pascal von Borland: Turbo Pascal. Turbo Pascal war schon seit 1983 erfolgreich, weil der Compiler nicht nur schnell war, sondern auch die Möglichkeiten von C teilweise hatte: Man konnte auf den Speicher des Rechners direkt zugreifen und Assemblercode einfügen. Später übernahm Turbo Pascal von Modula das Modulkonzept, von Smalltalk das Prinzip des objektorientierten Programmierens, von C++ das Konzept der Exception Behandlung. Umgekehrt näherten BASIC Dialekte sich Pascal an - mit Prozeduren und Funktionen, Blöcken, deklarierten Variablen etc. Immer mehr gerieten exotischere Programmiersprachen ins Hintertreffen und durch den expandierenden Markt der kleineren und mittleren Rechner verloren auch die Großrechner mit COBOL und FORTRAN an Bedeutung. Für COBOL war die Entwicklung von SQL - einer Abfragesprache für Datenbanken der Anfang vom Ende - Mittels SQL konnte man Abfragen tätigen, die Anwendung konnte aber in einer anderen Sprache programmiert sein, sie musste nur SQL Befehle kreieren und die Daten wieder entgegennehmen.

Für FORTRAN wurde zum Verhängnis, das es nicht parallelisierbar ist - seit Anfang der neunziger Jahre bestehen Supercomputer aus zahlreichen kleinen Prozessoren, bei denen die alten FORTRAN Programme nicht die Rechenleistung herausholen können, die in der Möglichkeit der Parallelverarbeitung steckt.

Objektorientiertes Programmieren

Das objektorientierte Programmieren hebt die klassische Trennung zwischen Daten und Code auf. Ein klassisches Programm verarbeitet Daten. Wenn sich diese ändern, muss man auch den Code anpassen. Das macht es sehr schwierig Code von einem Programm in einem anderen wieder zu verwenden. Beim objektorientierten Programmieren gibt es dies nicht. Auf die Daten wird mit Prozeduren und Funktionen zugegriffen und Daten und Code bilden eine Einheit. Ändern sich die Daten, so kann man dieselben Prozeduren aufrufen, muss jeweils nur die interne Verarbeitung ändern. Die immer gleichen Dialoge und Elemente von Windows wären ohne dies nicht möglich. Im Prinzip finden wir einen solchen Ansatz schon bei Modula, nur hat man dort versäumt festzulegen, dass jeder Datentyp nur mit eigenen Methoden ansprechbar ist.

Als erste Programmiersprache beherrschte dies Ende der siebziger Jahre Smalltalk, die wie andere revolutionäre Erfindungen (Netzwerk, grafische Benutzeroberfläche) im XEROX-Parc entwickelt wurden. Smalltalk kennt wie JAVA nur das Objekt und ebenfalls wie JAVA das Konzept der virtuellen Maschine. Damit sollte ein Programm auf jedem Rechner laufen können, ohne portiert zu werden. Ende der achtziger Jahre tauchten Objekte dann auch bei Turbo Pascal auf und C wurde zu C++ - der objektorientierten Variante. Heute ist objektorientiertes Programmieren weit verbreitet, Windows ist z.B. in C++ geschrieben. Anders als bei Smalltalk kann man bei C++ und Objekt Pascal aber auch prozedural programmieren.

Visuelles Programmieren

Das entscheidende Grundproblem beim Programmieren ist meistens die Bedienung durch den Benutzer. Einfach gesagt: Je benutzerfreundlicher das Ganze sein soll desto schwieriger wird das Ganze. Viele Programme (auch von dem Autor) unter DOS waren sehr benutzerunfreundlich, weil je mehr Freiheiten der Benutzer hatte, desto mehr Fehler musste man abfangen, auf desto mehr Arbeit hatte man mit der Auswertung der Eingaben. Die ersten Windows Programmierumgebungen setzten dem die Krone auf, einige zig Befehle um alles festzulegen, bevor überhaupt etwas auf dem Bildschirm erschien. Nun kamen Komponenten auf, die direkt die objektorientierte Programmierung nutzten. Eine Komponente ist ein Stück Programmcode mit Eigenintelligenz über die implementierten Funktionen kann ich auf ihn zugreifen und Daten übergeben. So kann ich mit einem Befehl einen "Öffnen" Dialog aufrufen. Sie können dann mit diesem durch die Festplatte navigieren, die Dateien nach verschiedenen Kriterien sich ansehen und zuletzt eine Datei anwählen - alles das macht diese Komponente - erst nach dem Klick auf "OK" bekommt mein Code wieder eine Meldung ob sie eine Datei ausgesucht haben und wie diese heißt. Kurzum Komponenten machen das Leben sehr viel einfacher.

Das Internet und JAVA

Java ist eine Ausnahme - eigentlich war seit Anfang der siebziger keine völlig neue Sprache mehr erfolgreich gewesen. Smalltalk führte z.B. das objektorientierte Programmieren ein, aber andere Sprachen wie C++ übernahmen es, und setzten sich durch. Eine Ausnahme ist Java. Der grundlegende Gedanke bei Java ist eine noch größere Portabilität als C. Ursprünglich sollten Mikrocontroller, von denen es sehr viele Typen gibt, in Java programmiert werden. Zudem sollte Java über das Internet auf den Rechner übertragen werden und dadurch waren der Sprache Grenzen gesetzt hinsichtlich dessen, was die Sprache auf dem Gastrechner darf. Niemand würde sich ein Java Applet auf seinen Rechner laden, wenn er befürchten müsste, dass das Programm auf seinem Rechner Unfug macht. Dies ist bei Java nicht der Fall. Auch kann eine Java Programm mal nicht einfach Klassen auf dem Rechner durch eigene ersetzen, ein Java läuft in einem abgeschotteten Bereich und sonst nirgendwo.

Grundgedanke war es, Anfang der neunziger Jahre einfach eine Sprache zu haben, in der Anpassungen für verschiedene Mikrocontroller möglich waren – damit bei Änderungen der Hardware nicht dauernd die Software neu entwickelt werden muss. Später erkannte man das man, damit auch die ideale Sprache für das Internet hat, auf das auch verschiedenen Rechner mit verschiedenen Betriebssystemen zugreifen können. Java ist z.B. in vielen Handys präsent. Manche Handys lassen sich sogar vom Anwender programmieren.

Java wird in einen Bytecode compiliert, der auf dem Gastrechner zuerst geprüft und dann interpretiert wird. Dadurch ist Java langsamer als C oder andere kompilierende Sprachen. Das verhinderte bisher auch die Entwicklung von Netzcomputern - kleinen Rechnern, die ihre Software übers Internet beziehen und bei denen nur ein Java Interpreter werkelt während die eigentliche Software und die Daten auf einem sicheren Server arbeiten - wohl der Traum jedes Windows Systemadministrators - keine Selbstinstallationen von Anwendern.

Java dürfte noch eine große Zukunft haben - die Entwicklung von alternativen Surftools wie Web Pads oder Geräten mit Internetanschluss (der Kühlschrank der automatisch Bestellungen zum Auffüllen veranlasst) steht schließlich erst am Anfang. Für größere Anwendungen, die nicht nur Applets sind und die nur auf einem Rechner laufen, arbeitet man auch mit echt kompilierten Java Code. In dieser Umgebung ist Java eine so universelle Programmiersprache wie C++ oder Pascal, es gibt hier keine Restriktionen. Auch dies ist einmalig: Je nach Einsatzgebiet leitet man eine Anwendung von der Basisklasse Applet ab und hat die Schutzmechanismen - oder eben nicht und kann dann "normale" Anwendungen entwickeln, ohne auf eine zweite Sprache zurückgreifen zu müssen.

Java steht hier nur stellvertretend für einen Trend: Die interpretierenden Sprachen sind durch Internet wieder am Vormarsch. Der Grund: Jeder möchte über das Internet heute Business machen. Dazu müssen in der Regel Datenbanken irgendwie angesprochen werden. Doch hier gibt es ein Problem: Irgendwie muss man von einer HTML-Seite an die Datenbank herankommen. Sei es um die Börsenkurse zu visualisieren oder eine Bestellung zu machen oder sich als zahlender Benutzer zu verifizieren. Ein Binärfile, das ausgeführt wird, akzeptieren weder Nutzer (wer weiß schon was das anrichtet?) noch Provider (welche Sicherheitslücken reißt es auf?). und so gibt es heute eine Reihe von Scriptsprachen für aktive Inhalte. Von Erweiterungen für Browser (Javascript) über speziell für diesen Zweck kreierte Sprachen (PHP) zu UNIX Tools (Perl) und allgemeinen Programmiersprachen (Python).

Wenn eine interpretierte Sprache zu langsam wird, so setzen sich oft „Just in Time“ (JIT) Compiler durch. Das sind Compiler, die den Quelltext während der Ausführung in Maschinensprache übersetzen und beim nächsten Aufruf derselben Programmierzeile, z.B. in einer Schleife diese ausführen. Alternativ kann auch der Quelltext übersetzt werden, bevor er beim ersten Mal ausgeführt wird. Wegen der immer größeren Benutzung von Javascript für Webseiten hat sich bei vielen Browsern inzwischen ein solcher JIT-Compiler durchgesetzt, um die Geschwindigkeit des Seitenaufbaus zu erhöhen.

Regelorientierte Sprachen

Eigentlich könnte das Leben doch so einfach sein. Heute programmieren die meisten Programmierer die Lösung eines Problems bis auf Befehlsebene herunter. Das nennt man prozedurale Sprachen. Doch es gibt auch Sprachen, die anders funktionieren: regelbasierende Sprachen. Hier wird einer Sprache die Regel gegeben, die dem Problem zugrunde liegt, d.h. die Abhängigkeiten, die aufzulösen sind. Dies macht dann die Programmiersprache selbst. Für einige Probleme - insbesondere im Bereich der KI war dies ideal. Sprachen wie Prolog, LISP oder Natural finden sich auch in diesem Umfeld. Aber es gibt keine Alternative, wenn man nur mal einfache Berechnungen oder Daten verarbeiten will - dass löst man mit prozeduralen Sprachen immer noch einfacher. Als Weiteres waren die regelbasierenden Sprachen lange Zeit nur interpretiert, was die Geschwindigkeit stark herabsetzte. Seit Ende der achtziger Jahre die KI-Forschung nach eine Blüte langsam einschlummerte ist es still um diese Sprachen geworden.

Datenbank und Anwendungssprachen

Schon immer eine Bedeutung hatten Datenbanksprachen. Mit dem Aufkommen von Datenbanksystemen brauchte man bei diesen zuerst Programmiersprachen um sie abzufragen, derartige Sprachen lehnten sich an bekannte Vorbilder an und hatten oft mächtige Befehle um Daten zu bearbeiten, für diesen Zweck waren sie maßgeschneidert. Ein bekanntes Beispiel dafür ist die Sprache von DBase, da dieses PC Programm sehr populär war und andere auf ihm aufbauten. Aus dem Großrechnerbereich kommt SQL, das auch auf dem PC Einzug gehalten hat.

Auch andere Anwendungen haben nach und nach Sprachen implementiert, zuerst nur als Makrosprachen um Befehle wieder abspielen zu können oder die Flexibilität zu erhöhen, dann durch integrierte Pakete auch zum Datenaustausch zwischen Anwendungen. Den bisherigen Höhepunkt hat VBA erreicht Visual BASIC for Applications verbindet Microsoft-Anwendungen untereinander - MS Office mit Outlook und Windows. So kann ein E-Mail Attachment sich auch selbstständig über Outlook weiterverbreiten, bevor es ihre Daten auf dem Rechner löscht.

Wird es einmal die Universalsprache geben?

Nein! Zum einen gib es schon heute - mal abgesehen von der Syntax zu viele unterschiedliche Lösungsansätze, Prolog arbeitet z.B. lösungsorientiert und hat noch immer eine wichtige Rolle in der KI-Forschung. Zum anderen ist eine Sprache je mehr sie kann auch um so komplizierter. Überzeugende Konzepte setzen sich aber durch, wie schon die Vergangenheit gezeigt hat. Es ist allerdings damit zu rechnen, dass die wichtigen Sprachen weniger werden. Als der Autor anfing zu programmieren gab es z.B. noch Forth, eine sehr kleine und schnelle Sprache, sie ist heute weitgehend verschwunden. BASIC ist von einer Einstiegssprache - in den achtziger lächelte von jedem Homecomputer einen ein "READY" eines BASIC Interpreters an - zu einer Applikationssprache geworden und Pascal, damals auch noch populär wird nur noch von Embaccadero weiterentwickelt und nur auf den PCs von Bedeutung.

Bestimmte Universalsprachen konnten sich jedoch durch Firmendruck oder Verordnung durchsetzen. So entwickelte IBM PL/1 als erste Universalsprache. Sie fand auch weite Verbreitung auf den vielen eingesetzten IBM Rechnern, aber nicht darüber hinaus und mit der schwindenden Marktmacht von IBM sank auch die Bedeutung von PL/1. Immerhin: Das erste Programm welches Gary Kildall entwickelte (Erfinder von CP/M) war eine PL/1 Implementierung für den 8080 Prozessor.

ADA wurde seitens des US-Verteidigungsministeriums eingeführt. Ziel war der Ersatz der vielen Spezialsprachen in den elektronischen Systemen des Militärs und auch naheliegenden Bereichen wie Satelliten und Trägerraketen. Dies wurde auch erreicht, so ist die Flugsoftware der Ariane 5 oder der Raumsonde SOHO in ADA geschrieben, außerhalb dieses Bereiches (und der Luftfahrt) konnte sie sich aber nicht durchsetzen.

Technisch betrachtet ist es heute eigentlich nicht mehr notwendig eine Universalsprache zu haben, ja sogar die Forderung das jemand mehrere Programmiersprachen sprechen muss (und natürlich dann nicht jede gleich gut) wäre nicht notwendig. Ein Compiler macht ja nichts anderes als einen Programmtext in Code umzuwandeln. Der schwierige Teil ist es heute optimale schnelle Programme zu erzeugen, um die Prozessoren optimal auszunutzen. Das hängt immer weniger von dem Quellcode ab oder der Sprache, da Compiler für sich schon optimieren. Wer heute in C schreibt:

i=i+1;
j=j*4;

kann davon ausgehen, dass dies genau den gleichen Code ergibt wie die Variante:

i++;
j=<<2;

Obgleich schwerer zu lesen wäre der Parser (der Teil des Compilers, der den Text erkennt) austauschbar, so könnte ein Compiler mit mehreren Programmiersprachen gefüttert werden. Dies gibt es schon in Ansätzen. Noch weiter geht Borland bei der Produktpalette von CBuilder und Delphi: Beide verwenden eine gemeinsame Bibliothek und so kann man in Delphi mittels eines Schalters Dateien für ein C-System erzeugen und im CBuilder kompilierte Delphi Units. Damit ist bei einem großen Projekt es völlig egal, wer in welcher Sprache arbeitet. In einfacherer Form kann man aber in jede Programmiersprache Routinen aus anderen einbinden. Wie schön wäre es, wenn dieses Konzept weiterentwickelt wird und auch von anderen Firmen aufgegriffen wird oder man sogar zwischen Sprachen standardisierte Schnittstellen schaffen würde?

In Wirklichkeit sieht es natürlich anders aus: Keine Firma wird ein Programm mit mehreren Programmiersprachen entwickeln, außer es ist zwingend notwendig. Denn was macht man, wenn der Delphi-Programmierer kündigt und man den Rest in C hat? Trotzdem ist die Zusammenarbeit mancher Programmiersprachen oft zwingend notwendig. Java ist noch für vieles zu langsam, kann aber native Maschinensprache aus C einbinden - z.B. für die am häufigsten benutzten Low Level Routinen. Visual BASIC erzeugt ebenfalls so langsamen Code, dass Komponenten für Visual BASIC in C++ entwickelt werden. Für ganz hardwarenahe Programmierung oder höchste Geschwindigkeit ist auch heute noch das Einfügen von Assembler gang und gäbe.

Generationen von Programmiersprachen

Ab und zu findet man die Bezeichnung "Programmiersprache der 4.ten Generation". Was hat es damit auf sich?

Gerade das Prädikat "4.te Generation" ist allerdings sehr umstritten. Andere meinen, das eine Sprache der 4.ten Generation objektorientiert ist eine grafische (visuelle) Möglichkeit Code zu erstellen existieren muss.

Epilog: Wann ist eine Programmiersprache erfolgreich?

Betrachtet man sich, welche der vielen Programmiersprachen heute Marktbedeutung haben - vielleicht am einfachsten gemessen, was man können muss, um eine Stelle zu bekommen, so sind von den vielen Dutzend Programmiersprachen nur eine Handvoll erfolgreich gewesen. Man ist nun verleitet dies, auf die Sprache selbst zurückzuführen - den Sprachumfang oder die Benutzerfreundlichkeit, aber dies ist nur ein Aspekt. Nein, wenn man es sich richtig ansieht, so sind in den letzten 30-40 Jahren nur Sprachen erfolgreich geworden, die es geschafft haben sich mit neuen Anwendungen durchzusetzen.

Bis zum Beginn der strukturierten Programmierung - als Erstes versucht mit ALGOL, hatten sich schon FORTRAN im wissenschaftlichen Bereich und COBOL im kaufmännischen Bereich etabliert. Dies ist auch so geblieben, denn selbst heutige neue Programme basieren im wesentlichen auf Algorithmen, die man schon in den fünfzigern entwickelt hat, nur sind diese Rechner - Großcomputer und Superrechner heute nicht mehr das große Marktsegment wie früher.

Von der folgenden Generation der strukturierten Programmiersprachen setzten sich bald 3 Sprachen durch: BASIC als Einstiegssprache, Pascal als Lehrsprache, aber auch schon professionelle Programmiersprache und C, weil es mit UNIX verknüpft war. Im PC-Bereich spielten zuerst BASIC und Pascal die Hauptrolle. Jeder Heimcomputer, in den achtziger Jahren hatte, einen kleinen BASIC Interpreter im ROM und Turbo Pascal war für viele Entwickler die Standardsprache auf den IBM PC Kompatiblen. UNIX war und ist dagegen das Betriebssystem für Minicomputer und Workstations. Da UNIX weitgehend in C geschrieben ist, setzte sich so C im Bereich der Rechner aus die zwischen einem PC und einem Großrechner standen. Wahrscheinlich wurde auch Windows zuerst auf einer UNIX-Maschine entwickelt, denn die Windows API hat C-Konventionen bei der Parameterübergabe. Zum Verhängnis von Pascal wurde sicher, das Borland, die den besten Pascal Compiler hatten, zu spät und halbherzig eine Windows Version herausbrachten. BASIC starb dagegen still und leise mit den Heimcomputern aus, die zum Programmieren gekauft wurden. BASIC und Pascal spielen heute in der professionellen Anwendungsentwicklung keine große Rolle, auch wenn es wie den Autor, noch viele Entwickler gibt, die sie einsetzen,

Java ist ein weiteres Beispiel für eine Sprache, die sich mit Computern durchsetzte, Java ist zwar eine schöne Sprache aber fürchterlich langsam. Eine IDE wie Borlands JBuilder vollständig in JAVA geschrieben ist geeignet, 1 GHz Prozessoren auf 386 er Performance zu reduzieren. Aber Java ist plattformunabhängig und Programme können von einem Browser aus ausgeführt werden, wobei Java nicht so viel Schaden anrichten kann wie z.B. Active X Controls. Damit hat sich Java mit dem Internet durchgesetzt. Wenn Java aber zu einer vollwertigen Programmiersprache werden soll, dann muss es auch schnelle Stand-alone Lösungen geben mit echtem binären Code.

Bei dieser Marktdurchsetzung spielte nicht die Qualität der Programmiersprache oder ihr Alter eine Rolle sondern durchsetzen konnte sich eine Sprache, weil sie fest mit einem Betriebssystem oder einer neuen Anwendung wie dem Internet verknüpft war. Es geht dabei nicht um rationelle Gesichtspunkte. So ist C erheblich fehleranfälliger als Pascal, weil es keine strenge Syntax gibt, die Fehler abfängt. Auch war Java durchaus nicht die erste objektorientierte Sprache - dies gebührt Smalltalk die 20 Jahre vor Java entstand, aber es war die einzige Sprache, die zum Internet passte, auch wenn sie eigentlich für die Programmierung von Embedded Controllern gedacht war.

Heute muss eine neue Programmiersprache sehr viel können, um gegen schon etablierte Produkte zu bestehen. Im Prinzip muss eine Sprache drei wesentliche Eigenschaften haben:

Vollständigkeit: Sie muss sich für jedes Problem eignen. Dass Java so erfolgreich wurde, liegt sicher auch daran, dass diese Sprache schon in der ersten Version Bibliotheken für Netzwerkprotokolle und Klassen für grafische Oberflächen hatte. Gleichzeitig kann man mit derselben Sprache aber auch das Betriebssystem eines Handys programmieren.

Mächtigkeit: Anders als früher kostet heute die Software mehr als die Hardware. Eine neue Sprache sollte daher dem Benutzer es ermöglichen, mit wenigen Instruktionen viel zu erreichen. In Smalltalk kann man z.B. mit einer Abfrage aus einer Liste von Objekten alle herausziehen die eine bestimmte Eigenschaft haben. Woanders ist hier eine Fallabfrage fällig, wenn es überhaupt möglich ist. Je mächtiger eine Sprache ist desto effektiver ist ein Programmierer. Dies gilt allerdings nur, wenn man den Sprachumfang überblicken kann. So ist C++ zwar eine Sprache, die sehr leistungsfähig ist, jedoch so komplex, dass man viel Einarbeitungszeit investieren muss. Würde C++ heute neu erscheinen, so wäre das ein K.O. Kriterium.

Sicherheit: Auch wenn sich manche Programmierer für Halbgötter halten, sie sind doch Menschen und Menschen machen Fehler. Die Chance einen solchen zu finden werden immer geringer, je größer Softwarepakete werden. So leben Microsoft Word Benutzer schon seit 11 Jahren damit, dass diese Software bei großen Dokumenten das Layout zerstört oder abstürzt. Sicherheit bedeutet bei Programmiersprachen zum einen umfangreiche Checks beim Übersetzen. Hier kommt es auf die Sprachspezifikation an. Wenn man wie in C Zuweisungen in IF Abfragen zulässt, hat man eine Fehlerquelle. Wichtiger sind aber Checks zur Laufzeit. So erkennt Pascal Zugriffe auf nicht existente Elemente eines Arrays, C dagegen nicht. Im einfachsten Fall stürzt das Programm bei einer solchen Aktion ärgerlicher sind falsche Ergebnisse oder die Ausnutzung dieses Mankos durch Wurmprogrammierer (sogenannte Buffer-Overflow Attacken auf Webserver).

Interpretierte Sprachen wie Java, Perl, Python, PHP oder Ruby sind heute so beliebt, weil der Interpreter viel mehr Möglichkeiten hat, derartige Prüfungen zur Laufzeit auszuführen. Das diese langsamer als compilierte Sprachen ist akzeptabel, wenn wie heute die Hardwarekosten ständig sinken.

Programmierer und ihre Vorlieben

Programmierer sind merkwürdige Menschen. Sie können über Programmiersprachen streiten, wie Philosophen über ihre Lieblingstheorie. Das hängt auch zusammen. Programmieren bedeutet geistige Überlegungen in Befehle einer Sprache umzusetzen. Nahezu jeder Programmierer hält sich für etwas besonderes und die meisten misstrauen Programmen die nicht von ihnen stammen. Sie investieren lieber 3 Mannmonate um diese neu zu schreiben, als mit den Fehlern der alten zu leben.

Besonders eklatant zeigt sich dies bei Programmiersprachen. Der für den Autor tiefere Grund, warum sich C und C++ so durchgesetzt haben ist der das es damit möglich ist Programme zu schreiben, die kryptisch, kurz und unverständlich sind. Sie sprechen damit die Seele vieler Programmierer an, die gelobt werden wollen für ihre Programmkünste, aber dies doch, ohne das sie jemand übernehmen kann. Da die meisten Programmierer eine Vorliebe für kurze Ausdrücke haben stehen Sprachen hoch im Kurs wie C, C++, Smalltalk oder APL die es erlauben kurz und prägnant zu schreiben. Während es Sprachen mit längeren Ausdrücken oder einer Syntax wie COBOL - die man fast ohne Ausbildung verstehen kann - schwerer haben.

So ist es üblich, das Programmierer sich gegenseitig die Sprachen madigmachen: "COBOL - für denkfaule Programmierer", "LISP: so lustig ohne Klammern wie Beuys ohne Hut", "C: Sprache für profilneurotische Machoprogrammierer", "Pascal: für Ordnungsfanatiker mit aufgeräumten Schreibtisch".

Auch das hat sicher die Bestrebungen für eine gut verständliche Sprache aufgehalten. Deren gab es nicht wenige: COBOL, Algol, Pascal, ADA ... Alle sind mehr oder weniger daran gescheitert, das Programmierer sich im Allgemeinen als Genies sehen, denen keine Fehler passieren und die sich von stark strukturierten und leicht verständlichen Sprachen in ihrem schöpferischen Drang gebremst sehen.

Allerdings ist nach Ansicht des Autors (bekennender Delphi Programmierer) es kein Zufall das Windows in C und C++ programmiert ist und so schöne blaue Bildschirme produziert ...

Programmiersprachen als Selbstverwirklichung

Erstaunlich ist, das auch in den letzten Jahren neue Programmiersprachen entstanden. Eigentlich gibt es schon für alles eine Programmiersprache. Viele sind natürlich nicht universell. Eine logische Folge wäre das Fehlende im Sprachumfang zu ergänzen. Hier schlägt jedoch das Problem "Standard" zu. Sieht man wie langsam sich Sprachen wie COBOL, FORTRAN und C im Laufe der Zeit weiter entwickelt haben, dann versteht man, warum oftmals neue Sprachen entstehen, anstatt alte zu ergänzen. Denn Letzteres heißt, dass ein Komitee in dem unzählige Vertreter, mit noch mehr Eigeninteressen einen gemeinsamen Nenner finden müssen. Dazu gibt es noch Firmen, die selbst existierende Standards ignorieren, weil sie nicht von Ihnen stammen, und lieber neue Sprachen schaffen. Prominentestes Beispiel ist hier Microsoft.

Welche Folgen das hat, zeigt sich beim Thema aktive HTML Inhalte, d.h., eine HTML-Seite soll entweder auf Benutzeraktionen reagieren oder Daten aus Datenbanken liefern oder wird sogar erst bei Aufruf generiert. Das Internet ist erst seit 1994/95 im Bewusstsein der Öffentlichkeit aufgetaucht und trotzdem gibt es für dieses Problem schon eine ganze Latte von Programmiersprachen: Java, Javascript, JScript, VB Script, C#, Pearl, PHP, Python, ActiveX. Und als Web Designer müssen sie alle kennen, weil jede Firma eine andere Lösung gewählt hat ...

Nicht unschuldig daran sind aber auch Größen in der Informatik, die neue Sprachen kreiert haben, anstatt alte zu verbessern. Prominentes Beispiel: Niklaus Wirth. Schöpfer von Pascal, Modula und Oberon. Modula erweiterte Pascal um das Konzept der Schnittstelle und des Moduls. Oberon ist eine Pascal ähnliche Sprache mit objektorientiertem Ansatz. Beide sind heute bedeutungslos. Dagegen erfolgreich ist Objekt Pascal: eine Erweiterung des Pascal Standards der Firma Borland. Auch hier in den Schritten Modul (1987 als Unit Konzept eingeführt) und Objekt (1989 eingeführt). Aber eben keine neue Sprache. Jeder Borland Compiler verdaut auch die alten Programme noch.

Heute ist es kein Problem mehr eine Programmiersprache - zumindest der einfacheren Art - selbst zu entwickeln. Der Autor hat in vier Wochen zur Steuerung eines Messdatenerfassungssystems eine Programmiersprache samt Editor und Debugger entwickelt, die in etwa das Niveau von Turbo Pascal 3.0 oder eines BASIC Interpreters hatte. Auch dies ist eine Erklärung für die zahlreichen Programmiersprachen.

Artikel zuletzt geändert; 19.9.2012


Zum Thema Computer ist auch von mir ein Buch erschienen. "Computergeschichte(n)" beinhaltet, das was der Titel aussagt: einzelne Episoden aus der Frühzeit des PC. Es sind Episoden aus den Lebensläufen von Ed Roberts, Bill Gates, Steve Jobs, Stephen Wozniak, Gary Kildall, Adam Osborne, Jack Tramiel und Chuck Peddle und wie sie den PC schufen.

Das Buch wird abgerundet durch eine kurze Erklärung der Computertechnik vor dem PC, sowie einer Zusammenfassung was danach geschah, als die Claims abgesteckt waren. Ich habe versucht ein Buch zu schreiben, dass sie dahingehend von anderen Büchern abhebt, dass es nicht nur Geschichte erzählt sondern auch erklärt warum bestimmte Produkte erfolgreich waren, also auf die Technik eingeht.

Die 2014 erschienene zweite Auflage wurde aktualisiert und leicht erweitert. Die umfangreichste Änderung ist ein 60 Seiten starkes Kapitel über Seymour Cray und die von ihm entworfenen Supercomputer. Bedingt durch Preissenkungen bei Neuauflagen ist es mit 19,90 Euro trotz gestiegenem Umfang um 5 Euro billiger als die erste Auflage. Es ist auch als e-Book für 10,99 Euro erschienen.

Mehr über das Buch auf dieser eigenen Seite.

Hier geht's zur Gesamtübersicht meiner Bücher mit direkten Links zum BOD-Buchshop. Die Bücher sind aber auch direkt im Buchhandel bestellbar (da ich über sehr spezielle Themen schreibe, wird man sie wohl kaum in der Auslage finden) und sie sind natürlich in den gängigen Online-Plattformen wie Amazon, Libri, Buecher.de erhältlich.

© des Textes: Bernd Leitenberger. Jede Veröffentlichung dieses Textes im Ganzen oder in Auszügen darf nur mit Zustimmung des Urhebers erfolgen.

Sitemap Kontakt Neues Hier werben Bücher vom Autor Buchempfehlungen Top 99