Programmierprinzipien: Unterschied zwischen den Versionen

aus GlossarWiki, der Glossar-Datenbank der Fachhochschule Augsburg
Zeile 119: Zeile 119:
:⇒ Wartbarkeit
:⇒ Wartbarkeit


Aus diesen Forderungen leiter Bertrand Meyer sech Prinzipien ab, die bei der Entwicklung von Modulen beachtet werden sollten.
Aus diesen Forderungen leitet Bertrand Meyer sechs Prinzipien ab, die bei der Entwicklung von Modulen beachtet werden sollten.


*;Module sind syntaktische Einheiten (Syntactiacal Units): Module sollten unabhängig voneinander übersetzt und in Bibliotheken zur Verfügung gestellt werden können.
*;Module sind syntaktische Einheiten (Syntactiacal units): Module sollten unabhängig voneinander übersetzt und in Bibliotheken zur Verfügung gestellt werden können.
:⇒ Wiederverwendbarkeit  
:⇒ Wiederverwendbarkeit  
:⇒ Korrektheit
:⇒ Korrektheit
Zeile 128: Zeile 128:
:⇒ Wartbarkeit
:⇒ Wartbarkeit


*; Module sollten schlanke Schnittstellen haben (Small interfaces, lean APIs): Module sollten mit so wenig anderern Modulen kommunizieren wie möglich. Schnittstellen sollten nicht mit Funktionalität überfrachtet werden.
*; Module sollten wenige Schnittstellen haben (Few interfaces): Module sollten mit so wenig anderen Modulen kommunizieren wie möglich.
:⇒ Wiederverwendbarkeit
:⇒ Lesbarkeit
:⇒ Wartbarkeit
:⇒ Überprüfbarkeit
 
*; Module sollten schlanke Schnittstellen haben (Small interfaces): Schnittstellen sollten nicht mit Funktionalität überfrachtet sein. Das heißt, zwei Module sollten über möglichst umfangarme Schnittstellen miteinander kommunizieren.
:⇒ Lesbarkeit
:⇒ Lesbarkeit
:⇒ Wartbarkeit
:⇒ Wartbarkeit
Zeile 139: Zeile 145:


*;Informationen sollten in Modulen gekapselt sein ((Daten-)[[Kapselung]], Geheimnisprinzip, encapsulation, information hiding): Jede Information, die nicht notwendig ist, um die Aufgaben bzw. die Funktionalität eines Moduls zu verstehen, sollte von außen nicht zugänglich sein.
*;Informationen sollten in Modulen gekapselt sein ((Daten-)[[Kapselung]], Geheimnisprinzip, encapsulation, information hiding): Jede Information, die nicht notwendig ist, um die Aufgaben bzw. die Funktionalität eines Moduls zu verstehen, sollte von außen nicht zugänglich sein.
:⇒ Wartbarkeit
:⇒ Robustheit
:⇒ Überprüfbarkeit
:⇒ Wiederverwendbarkeit
*; Module sollten sowohl offen, als auch geschlossen sein (Open-closed principle): Module sollten sowohl offen für Veränderungen, als auch abgeschlossen gegenüber Veränderungen sein. Da heißt, ein funktionierendes Modul sollte möglichst nicht mehr verändert werden, aber andererseits sollte es problemlos möglich sein, ein Modul an neue Gegebenheiten anzupassen. In objektorientierten Sprachen wird dies vor allem durch [[Vererbung]], [[Überschreiben|Überschreiben von Methoden]] und die Verwendung von [[Abstrakte Klasse|Abstrakten Klassen]] (insbesondere [[Interface]]s) erreicht.
:⇒ Wiederverwendbarkeit (wenn Module offen sind)
:⇒ Erweiterbar (wenn Module offen sind)
:⇒ Robust (wenn getestete Module geschlossen sind)


Seit den wegweisenden Arbeiten von Bertrand Meyer aus den späten 80er-Jahren wurden weitere Prinzipien entwickelt, die die Definition von Modulen betreffen:


*;[Separation of concerns]]<ref>http://en.wikipedia.org/wiki/Separation_of_concerns</ref>, [[]]:Bei der Modularisierung eines Softwarepakets sollte man darauf achten, dass jede konkrete Aufgabe von genau einem Modul erfüllt wird. Man muss also die „Verantwortlichkeiten“ unter den Modulen aufteilen, sonst gehen die Vorteile der Modularisierung wieder verloren.  
*;[Separation of concerns]]<ref>http://en.wikipedia.org/wiki/Separation_of_concerns</ref>:Bei der Modularisierung eines Softwarepakets sollte man darauf achten, dass jede konkrete Aufgabe von '''genau einem''' Modul erfüllt wird. Man muss also die „Verantwortlichkeiten“ unter den Modulen aufteilen, sonst gehen die Vorteile der Modularisierung wieder verloren.  
*;[[Single responsibility principle]]<ref>http://en.wikipedia.org/wiki/Single_responsibility_principle</ref>:Bei der [[objektorientierten Programmierung]] treibt man die Modularisierung manchmal sogar so weit, dass nicht nur für jede Aufgabe höchstens ein Objekt zuständig ist (Separations of Conerns), sondern dass umgekehrt auch jedes Objekt für genau eine Aufgabe zuständig ist (Single responsibility principle).
*;[[Single responsibility principle]]<ref>http://en.wikipedia.org/wiki/Single_responsibility_principle</ref>:Bei der [[objektorientierten Programmierung]] treibt man die Modularisierung manchmal sogar so weit, dass nicht nur für jede Aufgabe höchstens ein Objekt zuständig ist (Separations of Conerns), sondern dass umgekehrt auch jedes Objekt für genau eine Aufgabe zuständig ist (Single responsibility principle).



Version vom 22. Dezember 2010, 15:30 Uhr

Zweck

Um nützliche und dennoch preiswerte Programme und Anwendungen erstellen zu können, sollte man eine Reihe von Programmierprinzipien beachten.

Bevor die Programmierprinzipen näher beschrieben werden können, werden zunächst die Ziele genannt, die mit diesen Prinzipien erreicht werden sollen.

Ziele

Ziel eines jeden Softwareentwicklungs-Vorhaben sollte die Erstellung von Software sein, die zwei Eigenschaften aufweist:

nützlich (useful)
Die Software sollte für den Benutzer nützlich sein.
preiswert (inexpensive)
Die Software sollte so geringe Kosten und Folgekosten verursachen wie möglich.

Software-Eigenschaften zur Erfüllung der beiden Ziele

Um die beiden vorgenannten Ziele zu erreichen, sollte ein Softwarepaket folgende Eigenschaften haben:

spezifiziert (specified)
Um die Nützlichkeit und die Korrektheit des Softwarepakets beurteilen zu können, sollte eine Spezifikation vorliegen, die detailliert die Aufgaben und Eigenschaften des Paketes beschreibt.
⇒ Nützlichkeit (ist abschätzbar)
korrekt (correct)
Die Implementierung des Paketes sollte korrekt sein, es sollte also die Spezifikation in allen Punkten erfüllen.
⇒ keine Kosten durch falsches oder unerwartetes Verhalten
robust (robust)
Das Softwarepaket sollte auch in abnormalen (nicht-spezifizierten) Situationen stabil laufen.
⇒ keine Kosten durch Inkonsitenzen
⇒ geringe Kosten bei Bedienungsfehlern und Systemausfällen
benutzbar (usable)
Das Softwarepaket sollte einfach zu erlernen und zu benutzen sein.
⇒ Nützlichkeit wird verbessert
⇒ geringe Schulungskosten
⇒ fehlerhafte Nutzung verursacht nur selten Kosten
⇒ keine Kosten durch frustierte Benutzer
sicher (secure)
Unautorisierter Zugriff auf Daten oder Programme sollte unmöglich sein.
⇒ keine Kosten durch Sicherheitsmängel
effizient (efficient)
Das Softwarepakt sollte eine möglichst gute Laufzeit- und Speichereffizienz aufweisen, d.h. die vorhandenen Ressourcen möglichst gut ausnutzen.
⇒ geringe Personalkosten durch geringe Wartezeiten
⇒ geringe Kosten durch geringe Hardwareanforderungen
wartbar (maintainable)
Das Softwarepaket sollte leicht an neue Gegebenheiten angepasst werden können. Fehler sollten leicht behoben werden können (da sie sich nie ganz vermeiden lassen).
⇒ geringe Wartungskosten

Für die Eigenschaft „wartbar“ gibt es drei Spezialfälle, die hier gesondert genannt werden sollen:

kompatibel (compatible)
Das Softwarepaket sollte komaptibel zu bestehenden Systemen sein, es sollte also standardisierte Schnittstellen unterstützen.
⇒ geringe Intergrations- und Anpassungskosten
portabel (portable)
Das Softwarepaket sollte einfach auf neue Systeme portiert werden können.
⇒ geringe Kosten bei Änderung der Ablaufumgebung
erweiterbar (extensible)
Erweiterungen der Spezifikation sollten schnell implementiert werden können.
⇒ geringe Wartungskosten

Programmierprinzipien

Um die vorgenannten Ziele zu erreichen, sollten folgende Programmierprinzipien beachtet werden:

  • Schreibe lesbaren Code (Lesbarkeit, readability)
    Der Programmcode sollte so einfach wie möglich gelesen und verstanden werden können. Das heißt, der Code sollte sauber formartiert werden, es sollten sprechende Bezeichner verwendet werden, es sollten sinnvolle Kommentare eingefügt werden etc.
⇒ Überprüfbarkeit (durch Programmierer und nicht nur durch Compiler u.Ä.) (⇒ Korrektheit, Robustheit)
⇒ Wartbarkeit (da die Programme auch von anderen Programmierern verstanden werden)
⇒ Erweiterbarkeit (da die Programme auch von anderen Programmierern verstanden werden)
  • Verwende eine Programmiersprache und -umgebung, die dich beim Schreiben des Codes unterstützt (Schreibbarkeit, writability)
    Der Programmcode sollte so einfach wie möglich geschrieben werden können. Zum einen sollte es die Programmiersprache ermöglichen, einfachen und eleganten Code zu schreiben. Und zum anderen sollten die Programmwerkzeuge einen bei der Erstellung des Codes möglichst gut unterstützen.
⇒ Korrektheit (Fehler/Warnungen werden von der Programmierungebung zeitnah gemeldet; der Code oder zumindest ein Codegerüst wird automatisch aus der Spezifikation generiert)
⇒ Lesbarkeit (⇒ Überprüfbarkeit, Korrektheit, Robustheit, Wartbarkeit, Erweiterbarkeit)
  • Schreibe überprüfbaren Code (Überprüfbarkeit, veriafiability)
    Die Korrektheit eines Softwarepakets sollte plattformunabhängig sein und automatisch überprüft werden können. Viele Programmierparadigmen und auch Projekttechniken verlangen zu diesem Zweck, dass gleichzeitig mit der Software auch passende Softwaretests implementiert werden. Noch besser ist es, wenn die Semantik des Programmes formal spezifiert und überprüft werden kann (Abstrakte Datentypen, Integritätsbedingungen, ...)
⇒ Korrektheit (insbesondere, wenn die Erfüllung der Spezifikation verifiziert, d.h. formal nachgewisen wird)
⇒ Robustheit (wegen ausführlicher Tests)
⇒ Portierbarkeit (wegen der Plattformunabhängigkeit)
  • Schreibe stetigen Code (Stetigkeit, continuity)
    Schreibe den Code so, dass kleine Änderungen an der Spezifikation auch nur kleine Änderungen am Code zur Folge haben.
⇒ Warbarkeit (insb. Erweiterberkeit)
⇒ Wiederverwendbarkeit, da der Code schnell an neue Gegebenheiten angepasst werden kann
  • Schreibe konfigurierbaren Code (Konfigurierbarkeit, customizability)
    Konstante Werte sollten im Allgemeinen nicht direkt in den Code eingefügt werden, sondern als konstante Werte separat definiert werden (Ausnahme: triviale Konstanten, die sich sicher nie ändern werden, wie z.B. Vergleiche mit dem Wert 0). Konstanten, die das Programmverhalten beeinflussen, sollten im Allgemeinen bei Programmstart aus einer Konfigurationsdatei ausgelesen werden.
⇒ Stetigkeit (⇒ Warbarkeit und Wiederverwendbarkeit)
  • Wiederhole dich nicht (Don't repeat yourself, DRY[1])
    Das Prinzip „Separation of concerns“ kann man noch verallgemeinern: Code sollte nicht dupliziert werden, oder allgemeiner: Jedes Wissenselement muss im System ein einziges Mal, unzweideutig und geeignet repräsentiert werden. Wenn Code mehrfach verwendet wird, liegt ein allgemeineres Prinzip zu Grunde, das explizit ins System eingearbeitet werden sollte. Code ohne Duplikate von Anweisungen wir häufig als dry bezeichnet. Mit to dry code wird der Vorgang bezeichnet, Anweisungs-Duplikate aus dem zugehörigen Code zu entfernen.
⇒ Wartbarkeit (da Änderungen nicht an mehrere fast identischen Stellen vorgenommen werden müssen)
⇒ Lesbarkeit (da weniger Code exitiert)
  • Benutze Schnittstellen zur Kommunikation mit Objekten, Modulen etc. (Interfaces)
    Die Verwendung von Schnittstellen zum Zugriff auf und zur Modifikation von Daten/Informationen (an Stelle eines direkten Zugriffes) ermöglicht es, Code lokal zu ändern, ohne dass dies Auswirkungen auf andere Objekte, Module etc. hat (solange sich die Schnittstellen nicht ändern).
⇒ Lesbarkeit
⇒ Stetigkeit (⇒ Warbarkeit und Wiederverwendbarkeit)
⇒ Überprüfbarkeit
⇒ Modularität

Modularität

Eines der wichtigsten Programmierprinzipien ist die Modularität[2] (modularity). Berdrand Meyer war einer der ersten, der die Bedeutung der Modularität erkannt und beschrieben hat (vgl. Meyer (1997)).

  • Teile und herrsche (Divide et impera, Modularität, modularity)
    Ein komplexes Problem (Vorhaben, Projekt, ...) kann man nur dadurch in den Griff bekommen, dass man es solange in kleinere, möglichst unabhängige Teilprobleme (Teilvorhaben, Phasen, Vorgänge, ...) zerlegt, bis diese lösbar (= beherrschbar) sind. Ein Programm sollte daher modularisiert werden.
⇒ Überprüfbarkeit (⇒ Korrektheit, Robustheit)
⇒ Warbarkeit (insbesondere Erweiterbarkeit)
⇒ Wiederverwendbarkeit (wenn die Module weitgehend unabhängig voneinander sind)
⇒ Lesbarkeit (kann bei extensiver Nutzung auch leiden)

Bertrand Meyer[3] hat insgesamt fünf Anforderungen formuliert, die bei der Definition von Modulen beachtet werden sollten:

  • Modulare Zerlegbarkeit (Modular Decomposability)
    Zerlege in Problem in unterschiedliche, seperat lösbare Teilprobleme.
⇒ Überprüfbarkeit (⇒ Korrektheit, Robustheit)
⇒ Warbarkeit (insbesondere Erweiterbarkeit)
⇒ Lesbarkeit
  • Modulare Zusammenfügbarkeit (Modular Composability)
    Module sollten in möglichst vielen (unterschiedlichen) Situationen/Anwendungen eingesetzt werden können. Das heißt, Module sollten auf unterschiedliche Art und Weise zu neuen Funktionseinheiten zusammengefügt werden können.
⇒ Wiederverwendbarkeit
⇒ Erweiterbarkeit
⇒ Überprüfbarkeit
⇒ Wartbarkeit
⇒ Schreibbarkeit
  • Modulare Verständlichkeit (Modular Understandability)
    Die Aufgaben eines Moduls sollten verstanden werden, ohne dass man viele andere Module kennen muss.
⇒ Überprüfbarkeit (⇒ Korrektheit, Robustheit)
⇒ Wartbarkeit
⇒ Lesbarkeit
  • Modulare Stetigkeit (Modular Continuity)
    Kleine Änderungen an den Anforderungen sollten nur Änderungen an einer geringen Zahl von Modulen zur Folgen haben. Im besten Fall ist nur ein einziges Modul betroffen.
⇒ Stetigkeit
⇒ Warbarkeit (insb. Erweiterberkeit)
⇒ Wiederverwendbarkeit, da der Code schnell an neue Gegebenheiten angepasst werden kann
  • Modulare Robustheit (Modular Protection)
    Ein Modul sollte alle abnormalen Fälle selbst behandeln. Das heißt, es sollte sich nicht darauf verlassen, dass ein anderes Modul die Schnittstellen nur gemäß der Spezifikation verwendet.
⇒ Korrektheit
⇒ Robustheit
⇒ Überprüfbarkeit
⇒ Wartbarkeit

Aus diesen Forderungen leitet Bertrand Meyer sechs Prinzipien ab, die bei der Entwicklung von Modulen beachtet werden sollten.

  • Module sind syntaktische Einheiten (Syntactiacal units)
    Module sollten unabhängig voneinander übersetzt und in Bibliotheken zur Verfügung gestellt werden können.
⇒ Wiederverwendbarkeit
⇒ Korrektheit
⇒ Robustheit
⇒ Überprüfbarkeit
⇒ Wartbarkeit
  • Module sollten wenige Schnittstellen haben (Few interfaces)
    Module sollten mit so wenig anderen Modulen kommunizieren wie möglich.
⇒ Wiederverwendbarkeit
⇒ Lesbarkeit
⇒ Wartbarkeit
⇒ Überprüfbarkeit
  • Module sollten schlanke Schnittstellen haben (Small interfaces)
    Schnittstellen sollten nicht mit Funktionalität überfrachtet sein. Das heißt, zwei Module sollten über möglichst umfangarme Schnittstellen miteinander kommunizieren.
⇒ Lesbarkeit
⇒ Wartbarkeit
⇒ Überprüfbarkeit
  • Module sollten über explizite Schnittstellen kommunizieren (Explicit interfaces)
    Ein Modul sollte nicht über globale Variablen oder andere implizite Kommunikationswege mit anderen Modulen kommunizieren, sondern über explizite Schnittstellen.
⇒ Lesbarkeit
⇒ Wartbarkeit
⇒ Überprüfbarkeit
  • Informationen sollten in Modulen gekapselt sein ((Daten-)Kapselung, Geheimnisprinzip, encapsulation, information hiding)
    Jede Information, die nicht notwendig ist, um die Aufgaben bzw. die Funktionalität eines Moduls zu verstehen, sollte von außen nicht zugänglich sein.
⇒ Wartbarkeit
⇒ Robustheit
⇒ Überprüfbarkeit
⇒ Wiederverwendbarkeit
  • Module sollten sowohl offen, als auch geschlossen sein (Open-closed principle)
    Module sollten sowohl offen für Veränderungen, als auch abgeschlossen gegenüber Veränderungen sein. Da heißt, ein funktionierendes Modul sollte möglichst nicht mehr verändert werden, aber andererseits sollte es problemlos möglich sein, ein Modul an neue Gegebenheiten anzupassen. In objektorientierten Sprachen wird dies vor allem durch Vererbung, Überschreiben von Methoden und die Verwendung von Abstrakten Klassen (insbesondere Interfaces) erreicht.
⇒ Wiederverwendbarkeit (wenn Module offen sind)
⇒ Erweiterbar (wenn Module offen sind)
⇒ Robust (wenn getestete Module geschlossen sind)

Seit den wegweisenden Arbeiten von Bertrand Meyer aus den späten 80er-Jahren wurden weitere Prinzipien entwickelt, die die Definition von Modulen betreffen:

  • [Separation of concerns]][4]
    Bei der Modularisierung eines Softwarepakets sollte man darauf achten, dass jede konkrete Aufgabe von genau einem Modul erfüllt wird. Man muss also die „Verantwortlichkeiten“ unter den Modulen aufteilen, sonst gehen die Vorteile der Modularisierung wieder verloren.
    Single responsibility principle[5]
    Bei der objektorientierten Programmierung treibt man die Modularisierung manchmal sogar so weit, dass nicht nur für jede Aufgabe höchstens ein Objekt zuständig ist (Separations of Conerns), sondern dass umgekehrt auch jedes Objekt für genau eine Aufgabe zuständig ist (Single responsibility principle).



  • Definiere Schnittstellen, die nur selten geändert werden müssen (Dauerhafte Schnittstellen, Stable APIs)
    Jede Schnittstellenänderung (mit Ausnahme von reinen Erweiterungen) hat zur Folge, dass viele Module, Objekte etc. angepasst werden müssen. So ist es z.B. besser, von Anfang an Setter- und Getter-Methoden zu verwenden, wenn eine Sprache (wie z.B. Java) keine echten Attribute unterstützt.
⇒ Lesbarkeit
⇒ Wartbarkeit
    • Benutze standardisierte Schnittstellen (Standard-Schnittstellen, Standardized interfaces): Dies ist die beste Art, für dauerhafte Scnittstellen zu sorgen.
  • Gesetz von Demeter[6] (Law of Demeter, LoD, „Sprich nur zu deinen nächsten Freunden“)
    Ein Objekt sollte nur Methoden von Objektem aufrufen, die es „persönlich“ kennt:
    • Objekte, die in Zustandsvariablen gespeichert sind
    • Objekte, die über direkte direkten Beziehungen zugänglich sind
    • Objekte, die mittels Parametern beim Methodenaufruf übergeben wurden
    • Objekte, die das aktuelle Objekt selbst erzeugt hat
⇒ Wartbarkeit

Quellen

  1. http://en.wikipedia.org/wiki/DRY
  2. Meyer (1997)
  3. Meyer (1997)
  4. http://en.wikipedia.org/wiki/Separation_of_concerns
  5. http://en.wikipedia.org/wiki/Single_responsibility_principle
  6. Karl J. Lieberherr and Ian M. Holland, Assuring Good Style for Object-Oriented Programs, IEEE Software, Volume 6 Issue 5, September 1989, ACM Digital Library

Siehe auch


Dieser Artikel ist GlossarWiki-konform.