Trennung von Bedenken - Separation of concerns

In der Informatik ist Separation of Concerns ( SoC ) ein Entwurfsprinzip, um ein Computerprogramm in verschiedene Abschnitte zu unterteilen. Jeder Abschnitt befasst sich mit einem separaten Anliegen , einer Reihe von Informationen, die den Code eines Computerprogramms betreffen. Ein Anliegen kann so allgemein sein wie "die Details der Hardware für eine Anwendung" oder so spezifisch wie "der Name der zu instanziierenden Klasse". Ein Programm, das SoC gut verkörpert, wird als modulares Programm bezeichnet. Modularität und damit Trennung von Bedenken wird erreicht, indem Informationen in einem Codeabschnitt mit einer klar definierten Schnittstelle gekapselt werden. Kapselung ist ein Mittel zum Verbergen von Informationen . Mehrschichtige Designs in Informationssystemen sind eine weitere Ausführungsform der Trennung von Belangen (zB Präsentationsschicht, Geschäftslogikschicht, Datenzugriffsschicht, Persistenzschicht).

Die Trennung von Bedenken führt zu mehr Freiheitsgraden für einige Aspekte des Entwurfs, der Bereitstellung oder der Verwendung des Programms. Allen gemeinsam ist die erhöhte Freiheit für die Vereinfachung und Wartung des Codes. Wenn Bedenken gut getrennt sind, gibt es mehr Möglichkeiten für Modul-Upgrades, Wiederverwendung und unabhängige Entwicklung. Das Verbergen der Implementierungsdetails von Modulen hinter einer Schnittstelle ermöglicht es, den Codeabschnitt eines einzelnen Anliegens zu verbessern oder zu ändern, ohne die Details anderer Abschnitte kennen zu müssen und ohne entsprechende Änderungen an diesen anderen Abschnitten vornehmen zu müssen. Module können auch verschiedene Versionen einer Schnittstelle bereitstellen, was die Freiheit erhöht, ein komplexes System stückweise ohne zwischenzeitlichen Funktionsverlust aufzurüsten.

Die Trennung von Anliegen ist eine Form der Abstraktion . Wie bei den meisten Abstraktionen bedeutet das Trennen von Bedenken das Hinzufügen zusätzlicher Codeschnittstellen, wodurch im Allgemeinen mehr Code erstellt wird, der ausgeführt werden muss. Trotz der vielen Vorteile gut getrennter Anliegen ist also oft eine Ausführungsstrafe verbunden.

Implementierung

Die von einer Programmiersprache bereitgestellten Mechanismen für die modulare oder objektorientierte Programmierung sind Mechanismen, die es Entwicklern ermöglichen, SoC bereitzustellen. Zum Beispiel können objektorientierte Programmiersprachen wie C# , C++ , Delphi und Java Anliegen in Objekte aufteilen , und architektonische Entwurfsmuster wie MVC oder MVP können Inhalt von Präsentation und die Datenverarbeitung (Modell) von Inhalt trennen . Serviceorientiertes Design kann Anliegen in Services aufteilen . Prozedurale Programmiersprachen wie C und Pascal können Anliegen in Prozeduren oder Funktionen aufteilen . Aspektorientierte Programmiersprachen können Anliegen in Aspekte und Objekte unterteilen .

Auch in vielen anderen Bereichen wie Stadtplanung , Architektur und Informationsdesign ist die Trennung von Belangen ein wichtiges Gestaltungsprinzip . Ziel ist es, komplexe, voneinander abhängige Systeme effektiver zu verstehen, zu entwerfen und zu verwalten, sodass Funktionen wiederverwendet, unabhängig von anderen Funktionen optimiert und vor dem potenziellen Ausfall anderer Funktionen isoliert werden können.

Häufige Beispiele sind die Aufteilung eines Raums in Räume, damit die Aktivität in einem Raum die Personen in anderen Räumen nicht beeinträchtigt, und das Belassen des Ofens in einem Stromkreis und der Beleuchtung in einem anderen, damit die Überlastung durch den Ofen das Licht nicht ausschaltet. Das Beispiel mit Räumen zeigt die Kapselung, bei der Informationen in einem Raum, beispielsweise wie unordentlich er ist, für die anderen Räume nicht verfügbar sind, außer über die Schnittstelle, die die Tür ist. Das Beispiel mit Schaltkreisen zeigt, dass die Aktivität in einem Modul, bei dem es sich um einen Schaltkreis mit angeschlossenen Stromverbrauchern handelt, die Aktivität in einem anderen Modul nicht beeinflusst, sodass jedes Modul nicht daran interessiert ist, was im anderen passiert.

Herkunft

Der Begriff Separation of Concerns wurde vermutlich von Edsger W. Dijkstra in seinem 1974 erschienenen Aufsatz „Über die Rolle des wissenschaftlichen Denkens“ geprägt.

Lassen Sie mich versuchen, Ihnen zu erklären, was nach meinem Geschmack für alles intelligente Denken charakteristisch ist. Das heißt, dass man bereit ist, einen Aspekt des eigenen Themas isoliert um seiner eigenen Konsistenz willen zu vertiefen, immer im Wissen, dass man sich nur mit einem der Aspekte beschäftigt. Wir wissen, dass ein Programm korrekt sein muss und können es nur unter diesem Gesichtspunkt studieren; wir wissen auch, dass es effizient sein sollte und können seine Effizienz sozusagen an einem anderen Tag untersuchen. In einer anderen Stimmung können wir uns fragen, ob und wenn ja: warum das Programm wünschenswert ist. Aber nichts ist gewonnen – im Gegenteil! – wenn man diese verschiedenen Aspekte gleichzeitig angeht. Es ist das, was ich manchmal "die Trennung von Belangen" genannt habe, die, wenn auch nicht perfekt möglich, doch die einzige mir bekannte Technik zur effektiven Ordnung der eigenen Gedanken ist. Das meine ich mit "die Aufmerksamkeit auf einen Aspekt lenken": Es bedeutet nicht, die anderen Aspekte zu ignorieren, es wird nur der Tatsache gerecht, dass der andere Aspekt aus dieser Sicht irrelevant ist. Es ist gleichzeitig ein- und mehrspurig gedacht.

Fünfzehn Jahre später wurde offensichtlich, dass der Begriff Trennung von Interessen zu einer akzeptierten Idee wurde. 1989 schrieb Chris Reade ein Buch mit dem Titel „ Elements of Functional Programming“ , das die Trennung von Anliegen beschreibt:

Der Programmierer muss mehrere Dinge gleichzeitig tun, nämlich

  1. beschreiben, was berechnet werden soll;
  2. organisieren Sie die Berechnungssequenz in kleine Schritte;
  3. organisieren die Speicherverwaltung während der Berechnung.

Reade sagt weiterhin,

Idealerweise sollte sich der Programmierer auf die erste der drei Aufgaben konzentrieren können (beschreiben, was berechnet werden soll), ohne von den beiden anderen, eher administrativen Aufgaben abgelenkt zu werden. Natürlich ist die Verwaltung wichtig, aber wenn wir sie von der Hauptaufgabe trennen, erhalten wir wahrscheinlich zuverlässigere Ergebnisse und können das Programmierproblem durch Automatisierung eines Großteils der Verwaltung lösen.

Die Trennung von Anliegen hat noch weitere Vorteile. Beispielsweise wird die Programmprüfung viel einfacher, wenn Details der Sequenzierung und der Speicherverwaltung im Programm fehlen. Darüber hinaus sollten Beschreibungen des zu berechnenden Gegenstands frei von solchen detaillierten Schritt-für-Schritt-Beschreibungen sein, wenn sie mit unterschiedlichen Maschinenarchitekturen evaluiert werden sollen. Folgen kleiner Änderungen an einem in einem Speicher gehaltenen Datenobjekt können eine unangemessene Beschreibung dafür sein, wie etwas berechnet wird, wenn eine hochgradig parallele Maschine mit Tausenden von Prozessoren verwendet wird, die über die Maschine verteilt sind und eher lokale als globale Speichereinrichtungen.

Die Automatisierung der administrativen Aspekte bedeutet, dass der Sprachimplementierer damit umgehen muss, aber er hat viel mehr Möglichkeiten, sehr unterschiedliche Berechnungsmechanismen mit unterschiedlichen Maschinenarchitekturen zu nutzen.

Beispiele

Internetprotokoll-Stack

Bei der Gestaltung des Internets ist die Trennung von Belangen von entscheidender Bedeutung. Bei der Internet Protocol Suite wurden große Anstrengungen unternommen, um Anliegen in wohldefinierte Schichten zu unterteilen . Dies ermöglicht es Protokolldesignern, sich auf die Bedenken in einer Schicht zu konzentrieren und die anderen Schichten zu ignorieren. Das Application Layer Protocol SMTP zum Beispiel beschäftigt sich mit allen Details der Durchführung einer E-Mail-Sitzung über einen zuverlässigen Transportdienst (normalerweise TCP ), aber nicht im geringsten damit, wie der Transportdienst diesen Dienst zuverlässig macht. Ebenso kümmert sich TCP nicht um das Routing von Datenpaketen, das auf der Internetschicht abgewickelt wird .

HTML, CSS, JavaScript

HyperText Markup Language (HTML), Cascading Style Sheets (CSS) und JavaScript (JS) sind komplementäre Sprachen, die bei der Entwicklung von Webseiten und Websites verwendet werden. HTML wird hauptsächlich für die Organisation von Webseiteninhalten verwendet, CSS wird für die Definition des Inhaltspräsentationsstils verwendet und JS definiert, wie der Inhalt mit dem Benutzer interagiert und sich verhält. Historisch war dies nicht der Fall: Vor der Einführung von CSS übernahm HTML sowohl die Semantik- als auch die Stildefinition.

Fachorientierte Programmierung

Die themenorientierte Programmierung erlaubt es, unterschiedliche Anliegen als separate Softwarekonstrukte gleichberechtigt zu adressieren. Jeder Konzern stellt seine eigene Klassenstruktur bereit, in der die gemeinsamen Objekte organisiert sind, und trägt Zustand und Methoden zum zusammengesetzten Ergebnis bei, wo sie sich überschneiden. Korrespondenzregeln beschreiben, wie die Klassen und Methoden in den verschiedenen Belangen an Stellen, an denen sie interagieren, miteinander in Beziehung stehen, sodass ein zusammengesetztes Verhalten für eine Methode aus mehreren Belangen abgeleitet werden kann. Die mehrdimensionale Trennung von Anliegen ermöglicht es, die Analyse und Zusammensetzung von Anliegen als mehrdimensionale "Matrix" zu manipulieren, in der jedes Anliegen eine Dimension bietet, in der verschiedene Auswahlpunkte aufgezählt werden, wobei die Zellen der Matrix mit den entsprechenden Software-Artefakte.

Aspektorientierte Programmierung

Die aspektorientierte Programmierung ermöglicht es, übergreifende Anliegen als Hauptanliegen zu adressieren. Beispielsweise erfordern die meisten Programme irgendeine Form von Sicherheit und Protokollierung . Sicherheit und Protokollierung sind oft zweitrangige Anliegen, während das primäre Anliegen häufig darin besteht, Geschäftsziele zu erreichen. Beim Entwerfen eines Programms muss seine Sicherheit jedoch von Anfang an in das Design integriert werden, anstatt als zweitrangig behandelt zu werden. Die nachträgliche Anwendung von Sicherheit führt oft zu einem unzureichenden Sicherheitsmodell, das zu viele Lücken für zukünftige Angriffe lässt. Dies kann mit aspektorientierter Programmierung gelöst werden. Beispielsweise kann ein Aspekt geschrieben werden, um zu erzwingen, dass Aufrufe an eine bestimmte API immer protokolliert werden oder dass Fehler immer protokolliert werden, wenn eine Ausnahme ausgelöst wird, unabhängig davon, ob der prozedurale Code des Programms die Ausnahme behandelt oder weitergibt.

Analyseebenen in der künstlichen Intelligenz

In der Kognitionswissenschaft und der künstlichen Intelligenz ist es üblich, sich auf die Analyseebenen von David Marr zu beziehen . Ein Forscher kann sich zu jeder Zeit darauf konzentrieren, (1) was ein Aspekt der Intelligenz berechnen muss, (2) welchen Algorithmus er verwendet oder (3) wie dieser Algorithmus in Hardware implementiert wird. Diese Trennung der Belange ähnelt der Unterscheidung zwischen Schnittstelle /Implementierung im Software- und Hardware-Engineering.

Normalisierte Systeme

In normalisierten Systemen ist die Trennung von Belangen eines der vier Leitprinzipien. Die Einhaltung dieses Prinzips ist eines der Werkzeuge, die dazu beitragen, die kombinatorischen Effekte zu reduzieren, die im Laufe der Zeit in Software, die gewartet wird, eingeführt werden. In normalisierten Systemen wird die Trennung von Belangen durch die Tools aktiv unterstützt.

SoC über Teilklassen

Trennung von Bedenken über geführt und umgesetzt werden Teilklassen .

SoC über Teilklassen in Ruby

bärenjagd.rb
class Bear
  def hunt
    forest.select(&:food?)
  end
end
bear_eating.rb
class Bear
  def eat(food)
    raise "#{food} is not edible!" unless food.respond_to? :nutrition_value
    food.nutrition_value
  end
end
bär_hunger.rb
class Bear
  attr_accessor :hunger
  def monitor_hunger
    if hunger > 50
      food = hunt
      hunger -= eat(food)
    end
  end
end

Siehe auch

Verweise

Externe Links