Eigenschaften und Unterscheidung von Programmiersprachen – IT-Berufe-Podcast #182

Eigenschaften und Unterscheidung von Programmiersprachen – IT-Berufe-Podcast #182

Um Eigenschaften und Unterscheidungsmerkmale von Programmiersprachen geht es in der einhundertzweiundachzigsten Episode des IT-Berufe-Podcasts. Inhalt Was ist eine Programmiersprache? Programmiersprache: „Eine Programmiersprache ist eine formale Sprach...
1 Stunde 42 Minuten

Beschreibung

vor 2 Jahren

Um Eigenschaften und Unterscheidungsmerkmale von
Programmiersprachen geht es in der einhundertzweiundachzigsten
Episode des IT-Berufe-Podcasts.
Inhalt Was ist eine Programmiersprache?

Programmiersprache: „Eine Programmiersprache ist eine formale
Sprache zur Formulierung von Datenstrukturen und
Algorithmen, d.h. von Rechenvorschriften, die
von einem Computer ausgeführt werden können.“ [Herv. d. Verf.]

Bausteine von Algorithmen: Sequenz,
Verzweigung (z.B. if, switch, aber auch Pattern
Matching), Wiederholung (GOTO, Schleifen,
Rekursion)

Turing-complete: „[…] die Eigenschaft einer
Programmiersprache oder eines anderen logischen Systems,
sämtliche Funktionen berechnen zu können, die eine universelle
Turingmaschine berechnen kann.“



Demnach sind keine Programmiersprachen: HTML/XML
(Auszeichnungssprache), CSS (Stylesheet-Sprache), SQL
(Datenbankabfragesprache).
Sprache vs. Plattform vs. Ökosystem

Programmiersprachen bringen meistens „eingebaute“ („native“)
Funktionen mit, die direkt in der Syntax der
Sprache formuliert werden können:


Ein-/Ausgabe-Befehle, um Daten verarbeiten zu können

Deklaration von Variablen zum Speichern von Informationen

mathematische Funktionen wie Addition, Multiplikation usw.

Steueranweisungen für Verzweigung und Wiederholung

Möglichkeiten zur Programmunterteilung (z.B. Funktionen,
Subprogramme)

Einbinden von (externen) Bibliotheken zur Wiederverwendung



Viele Programmiersprachen bringen außerdem noch eine umfangreiche
Bibliothek an vorgefertigten Implementierungen
(z.B. in Form von Klassen in objektorientierten Sprachen) mit.
Diese Bibliothek ist bei der Einarbeitung in eine neue Sprache
meist schwieriger/langwieriger zu lernen als die Syntax. Oftmals
teilen sich mehrere Programmiersprachen die Bibliotheken einer
gemeinsamen Plattform, z.B. der JVM bei Java und
Kotlin bzw. .NET bei C# und Visual Basic.


Darüber hinaus existiert meist auch noch ein ganzes
Ökosystem rund um die Sprache/Plattform:


Build-Tools, z.B. Maven, Gradle

Dependency-Management, z.B. NPM, RubyGems

Test-Frameworks, z.B. JUnit

weitere Frameworks und Libraries, z.B. Spring, Jakarta EE,
Rails, Blazor

Klassifizierung/Einsatzzweck(e)

Im Alltag sind die Identifikation und Auswahl einer für das
jeweilige „Realweltproblem“ passenden Sprache wichtig. Viele
Programmiersprachen haben Schwerpunkte bei ihrem
Einsatz, weil sie für bestimmte Einsatzzwecke optimiert wurden
oder dafür viele vorgefertigte Lösungen mitbringen.


Einsatzzweck: Webanwendung (z.B. PHP), App (z.B. Swift),
Desktop-Anwendung (z.B. C#), Server-Anwendung (z.B. Java)

Frontend (browserseitig) vs. Backend

Scriptsprachen: geringer Programmieraufwand für schnell
sichtbare Ergebnisse, oft Interpretersprachen mit dynamischer
Typisierung und laxer Syntaxprüfung (z.B. Semikolons optional),
Beispiele: PowerShell, PHP

Web-Programmiersprachen: bringen meist umfangreiche
Bibliotheken und Frameworks für Webanwendungen mit, oftmals auch
Scriptsprachen, Beispiele: PHP, Ruby, Python

Programmierparadigma

Ein Programmierparadigma gibt die grundsätzliche Art und
Weise vor, wie mit einer Programmiersprache entwickelt
wird. Es definiert grundlegende Herangehensweisen und Prinzipien
bei der Softwareentwicklung, aber auch ganz konkrete syntaktische
Vorgaben. So legt es z.B. fest, mit welchen Konstrukten das
Programm hauptsächlich arbeitet (z.B. Objekte in der
Objektorientierung bzw. Funktionen in der funktionalen
Programmierung als sogenannte „First Class Citizens“), wie
Programme modularisiert werden sollten und auf welche Art und
Weise Algorithmen vorzugsweise formuliert werden sollten
(„idiomatische Programmierung“).


Viele Programmiersprachen sind heutzutage sogenannte
Multiparadigmensprachen, bieten also Konzepte
aus mehreren Paradigmen an, z.B. Objektorientierung und
funktionale Programmierung. Meist haben sie aber ein
definierendes Paradigma, z.B. Objektorientierung bei Java.
Imperativ vs. Deklarativ

Grundsätzlich kann man die imperative und deklarative
Programmierung unterscheiden. Während bei der imperativen
Programmierung (von lat. „imperare“ – befehlen) exakt
vorgegeben wird, in welcher Reihenfolge der Computer welche
Befehle wie ausführen muss, gibt man bei der deklarativen
Programmierung (von lat. „declarare“ – erklären)
lediglich vor, welches Ergebnis am Ende erreicht sein soll, und
lässt den Computer den Weg dorthin selbst finden.


Beispiel:
// imperativ for (int i = 0; i < list.getSize(); i++) {
System.out.println(list.get(i)); } // deklarativ
list.forEach(System.out::println); Konkrete Programmierparadigmen

unstrukturiert: Einsatz von GOTO führte dazu, dass konkrete
Programmabläufe nicht mehr nachvollzogen werden konnten

strukturiert: Verzicht auf GOTO und Einsatz von
Kontrollstrukturen wie if und while

prozedural: Programme werden in kleine, wiederverwendbare
Einheiten („Prozeduren“) aufgespalten

funktional: (mathematische) Funktionen bilden den Kern dieser
Vorgehensweise, Higher Order Functions, Immutability und
Rekursion als wichtige Merkmale

objektorientiert: Objekte kapseln Eigenschaften und
Funktionen zu einer Einheit, Vererbung und Polymorphie als
wichtige Merkmale

logisch: Programmierung auf Basis der mathematischen
Aussagenlogik

Compiler vs. Interpreter

Compiler: Übersetzt Quellcode in Maschinen- oder Bytecode,
bevor das Programm ausgeführt wird.

JIT-Compiler: Just-In-Time-Compiler übersetzen z.B. Teile
des Bytecodes zur Laufzeit in Maschinencode, um die
Performance zu erhöhen.



Interpreter: Interpretiert den Quellcode Zeile für Zeile und
übersetzt ihn während der Ausführung in Maschinencode.

Typisierung

statisch vs. dynamisch

statisch: Datentypen stehen schon zur Compile-Zeit fest.

dynamisch: Datentypen werden erst zur Laufzeit geprüft.



stark vs. schwach: eher ein Spektrum („stärker/schwächer
typisiert“) als eine harte Einteilung

stark: keine Typumwandlung möglich oder nur explizit
(„Cast“, (int)3.5)

schwach: implizite Typumwandlungen durch die Sprache,
z.B. if (1) { ... }



Beispiele für alle Kombinationen

statisch/stark: Java

> cat .\Main.java class Main { public static void
main(String[] args) { double d = 1.5; int i = d; } } > javac
.\Main.java .\Main.java:6: error: incompatible types: possible
lossy conversion from double to int int i = d; ^ 1 error

statisch/schwach: C

> cat test.c #include int main() { int i =
1; if (i) { printf("Hallo\n"); } return 0; } > gcc test.c -o
test > ./test Hallo

dynamisch/stark: Ruby

> cat .\test.rb i = 1 s = "a" puts i + s > ruby
.\test.rb ./test.rb:3:in `+': String can't be coerced into Integer
(TypeError) from ./test.rb:3:in `'

dynamisch/schwach: PHP

> cat test.php $i = "asdf"; if ($i) { echo "Hallo\n"; }
> php test.php Hallo Syntax

Syntaktisch gibt es eigentlich nur die Unterscheidung zwischen
Sprachen, die ähnlich zu C sind (insb. Klammern, Schlüsselwörter,
Datentypen) oder eben nicht.


Beispiel Java (C-ähnlich):
void pruefePerson(int alter) { if (alter >= 18) {
System.out.println("volljährig"); } }

Beispiel Ruby:
def pruefePerson(alter) puts "volljährig" if alter >= 18 end
Grafisch vs. textuell

Die weitaus meisten Programmiersprachen sind textuelle Sprachen,
aber es gibt auch grafische Programmiersprachen, bei denen die
Algorithmen „zusammengeklickt“ werden können. Ein Beispiel ist
Scratch.
Abstraktionsniveau/Sprachhöhe

1GL: Maschinensprache, Nullen und Einsen

2GL: Assembler, etwas abstrakter, aber immer noch kryptisch,
an bestimmte Prozessoren gebunden

3GL: moderne Hochsprachen wie C, Java usw.

4GL: Sprachen mit Fokus auf einen bestimmten
Anwendungsbereich, Ziel: wenig Code für häufig benötigte
Funktionen, Beispiele: Natural, ABAP

General Purpose vs. Domain Specific

General Purpose Language (GPL): Kann eingesetzt werden, um
beliebige Probleme zu lösen, verwendet aber eine allgemeine
Syntax. Beispiele: Java, C#, PHP etc.

Domain Specific Language (DSL): Kann nur Probleme eines genau
abgegrenzten Bereichs lösen, verwendet dafür aber eine perfekt
passende Syntax. Es gibt interne (fachliche APIs der eigenen
Komponenten) und externe (komplett separate Programmiersprachen
mit Compiler usw.).

Weitere Unterscheidungsmöglichkeiten

Portabilität/Laufzeitumgebung: hardwarenah (C, C++) vs.
virtuelle Maschine (Java, C#)

Managed vs. unmanaged: Manuelle Speicherverwaltung (C) vs.
Garbage Collector (Java, C#)

Performance/Speicherverbrauch: Durch die Kombination mehrerer
der obigen Eigenschaften können sich deutliche Unterschiede bei
der Performance einzelner Sprachen ergeben. So ist ein Programm
in C, das speziell für die konkrete Laufzeitumgebung kompiliert
wurde, sicherlich schneller als ein Java-Programm, das auf einer
virtuellen Maschine interpretiert und ausgeführt wird. Aber das
ist immer noch schneller als ein JavaScript-Programm, das
zunächst noch interpretiert werden muss.

Beispiele für Programmiersprachen

Diese Liste ist nicht vollständig!


Web

PHP: sehr verbreitete Web-Programmiersprache mit viel
Unterstützung für übliche Anforderungen (z.B. Zugriff auf
Query-String usw.)

Ruby: Basis von Ruby on Rails und geschaffen, um
Entwickler:innen glücklich zu machen

Python: gerade im KI-Umfeld stark verbreitet

JavaScript: bislang die einzige (!) Programmiersprache
für das Frontend im Browser

Typescript: statisch typisierte Alternative zu JavaScript



Enterprise

Java: großes Ökosystem, Langlebigkeit,
Abwärtskompatibilität, sehr performant

C#: stark verbreitet für Windows-Anwendungen

COBOL: alte, aber immer noch in vielen großen Unternehmen
eingesetzte 4GL-Sprache für klassische Business-Anwendungen

ABAP: Programmiersprache von SAP

VBA: Makrosprache für Microsoft Office



App

Kotlin: Standardsprache für Android-Anwendungen, läuft
wie Java auf der JVM

Swift: Standardsprache für iOS-Anwendungen, „Nachfolger“
von Objective-C



Hardware

Assembler: immer noch bei hochperformanten Anwendungen im
Einsatz (z.B. Spiele)

C: Basis vieler eingebetteter Systeme und Betriebssysteme

C++: objektorientierter Aufsatz auf C



Funktional

Haskell: die funktionale Programmiersprache, in der
realen Welt nicht allzu verbreitet

F#: funktionale Sprache für .NET

Lisp: Urvater der modernen funktionalen
Programmiersprachen

Elixir: basiert auf Erlang und ist stark bei
nebenläufiger Programmierung



Logisch

Prolog: Programmierung mit Prädikatenlogik, Backtracking
usw.



Literatur

*


Seven Languages in Seven Weeks: A Pragmatic Guide to Learning
Programming Languages (Pragmatic Programmers) (Affiliate)*
Links

Permalink zu dieser Podcast-Episode

RSS-Feed des Podcasts

Turing-Vollständigkeit (Wikipedia)

Programmiersprache (Wikipedia)

Einführung in Build-Werkzeuge

Unit-Tests – Häufige Fragen im Fachgespräch

Java EE 7 (Lernzielkontrolle)

HTML

Buchclub: Handbuch für Fachinformatiker (Teil 9: XML)

Buchclub: Handbuch für Fachinformatiker (Teil 7: HTML und
CSS)

SQL – Häufige Fragen im Fachgespräch

Variablen und Operatoren (Lernzielkontrolle)

Algorithmen und Methoden (Lernzielkontrolle)

Objektorientierung Teil 1 (Lernzielkontrolle)

Markus Amshove über Domänenspezifische Sprachen

Kommentare (0)

Lade Inhalte...

Abonnenten

15
15