create mobile friendly website

komplexitaet

Die Komplexität von Softwaresystemen

Komplexität - einfach zu kompliziert?

Softwaresysteme gehören zu den komplexesten Gebilden, die von Menschen geschaffen werden. Ihr Design stellt Entwickler und Architekten häufig vor große Herausforderungen, die ihnen ein hohes Maß an Wissen, Fertigkeiten und Kreativität abverlangen. Gleichzeitig soll die Software aber auch effizient entwickelt werden, schnell und fehlerfrei in den Betrieb gehen und einfach zu warten sein.

Die Reduktion der Komplexität war schon immer ein Kerngedanke, um die Softwareentwicklung effizienter zu gestalten. Auch neuere Architekturansätze, wie z. B. Microservices, versuchen durch die Vermeidung von großen monolithischen Systemen hier anzusetzen. Der vorliegende Artikel betrachtet das Thema Komplexität einmal genauer. Entwicklern und Architekten werden einige Ansatzpunkte an die Hand gegeben, um im Umgang mit Komplexität, die richtigen Entscheidungen treffen zu können und über den Aspekt der Komplexität auch neu aufkommende Architekturansätze bewerten zu können.

Systeme

Bevor konkret auf Softwaresysteme Bezug genommen wird, macht es Sinn, sich zunächst von der systemtheoretischen Seite zu nähern. Das aus dem Altgriechischen stammende Wort „System“ bedeutet übersetzt so viel wie: „aus mehreren Teilen zusammengesetztes Ganzes”. Dabei sind folgende Eigenschaften von Bedeutung:

  • Die Einzelteile stehen in strukturierten Beziehungen zueinander.
  • Zwischen den Einzelteilen findet Interaktion statt.
  • Das System als Ganzes dient einem bestimmten Zweck (Sinn, Aufgabe).

Ein System ist immer zweckbestimmt. Durch die Verbindungen und Interaktionen der Einzelteile wird das System in die Lage versetzt, eine übergeordnete Aufgabe zu er­füllen bzw. einem bestimmten Zweck zu dienen, es realisiert einen mehr oder weniger umfassenden Prozess.

Systeme organisieren sich durch Strukturen, die Muster ihrer Elemente und ihrer Beziehungsgeflechte. Dadurch können sie funktionieren, sich selbst erhalten und ihre charakteristischen Eigenschaften ausbilden.

Jedes System ist per Definition von seiner Umgebung abgrenzbar und so für sich modellhaft isoliert beobachtbar. Das ist eine notwendige Voraussetzung für eine Analyse des Systems. Außerdem unterscheidet man zwei Ebenen eines Systems:

  • Die Makroebene enthält das System als Ganzes.
  • Die Mikroebene: enthält die einzelnen Systemelemente.

Wichtig ist dabei zu verstehen, dass das Systemver­halten auf der Makroebene nicht durch das Verhalten der Elemente auf der Mikroebene erklärt werden kann. Das Ganze ist immer mehr als die Summe seiner Einzelteile. Diese Eigenschaft wird auch als Emergenz bezeichnet.

Ursache und Wirkung

Ein weiterer wichtiger Begriff aus der Systemtheorie ist der der Kausalität. Er bezeichnet die Beziehung zwischen Ursache und Wirkung und beschreibt die Abfolge von Ereig­nissen und Zuständen. Die Elemente der Mikroebene und deren Beziehungen bilden die Zustände eines Systems ab. Ein Ereignis oder Zustand ist Ursache für eine Wirkung, die wiederum weitere Ereignisse oder Zustandswechsel herbeiführen kann.

Für die Analyse eines Systems ist es von herausragender Bedeutung, welche Kenntnis man über die Zusammen­hänge von Ursache und Wirkung besitzt.

Klassifizierung

Nun stellt sich die Frage, was die Komplexität eines Systems ausmacht und wie sich das entsprechende Verhalten beschreiben lässt. Dazu ist es naheliegend die obige Definition heranzuziehen und sich folgende Aspekte genauer anzuschauen:

Anzahl der Einzelteile

Es ist einleuchtend, dass Systeme, die aus vielen Teilen bestehen, schwieriger zu durchschauen sind, als Systeme mit einer geringeren Anzahl von Einzelkomponenten. Außerdem hat die Anzahl der Teile einen direkten Einfluss auf die Anzahl der möglichen Verbindungen bzw. Beziehungen untereinander.

Anzahl der Beziehungen zwischen den Teilen

Je mehr Beziehungen zwischen einzelnen Komponenten eines Systems bestehen, umso mehr Interaktionsmöglichkeiten bestehen und umso mehr Informationen können verarbeitet und ausgetauscht werden. Auch hier gilt, je mehr Beziehungen zwischen den Komponenten existieren, umso schwerer fällt die Analyse eines Systems.

Art der Beziehungen zwischen den Teilen

Den größten Einfluss auf die Analysierbarkeit eines Systems hat aber wohl die Art der vorhandenen Beziehungen. Sie können statisch sein oder sich dynamisch verändern. Strukturell können die Verbindungen lineare Ketten oder komplette Netzwerke ausbilden. Durch die Rückkoppelung von Verbindungen kann außerdem eine zusätzliche Dynamik in das System eingebracht werden.

Kausalität

Das Erkennen von Ursache und Wirkung ist oft das bevorzugte Kriterium, das wir intuitiv wählen, wenn wir über die Einschätzung von Komplexität sprechen. Systeme, von denen wir wissen, wie sie reagieren, empfinden wir als weniger komplex, als solche, deren Verhalten sich uns nicht unmittelbar erschließt.

Planbarkeit und Analysierbarkeit

Eine ähnliche Aussage zur Komplexität wie zur Kausalität lässt sich natürlich auch zur Planbarkeit bzw. Analysierbarkeit machen. Sehen wir uns in der Lage die Funktion bzw. den Zweck eines Systems zu durchdringen, glauben wir es auch leichter planen zu können wir weisen dem System einen geringen Komplexitätsgrad zu.

Gleiches gilt für die Analysierbarkeit. Sind wir in der Lage, das Verhalten eines Systems im Nachhinein zu begründen oder zu erklären, so schreiben wir ihm eine geringere Komplexität zu, als wenn wir das nicht oder nur mit größerem Aufwand erreichen können.

Verhalten

Möchten wir Systeme nun konkret klassifizieren, benötigen wir dafür Kategorien und einen Maßstab für entsprechende Merkmale. Eine Möglichkeit für eine solche Klassifikation stellt die Betrachtung des Verhaltens dar. Beobachtet wird die Reaktion eines Systems auf verschiedene Einfluss­faktoren. Dabei erweist es sich als praktisch, von vier Kategorien auszugehen.

Die Grenzen sind naturgemäß fließend. Die Beispiele geben aber einen groben Anhaltspunkt, um die einzelnen Aspekte in etwa einordnen zu können.

Ist Komplexität vermeidbar?

Bevor wir uns nun speziell den Softwaresystemen zu­wenden, muss noch der Aspekt betrachtet werden, ob Komplexität prinzipiell vermeidbar ist (z. B. gemäß dem KISS-Prinzip). Um diese Frage beantworten zu können, müssen wir überlegen, ob wir es immer mit gleich ge­arteter Kom­plexität zu tun haben oder ob es hier evtl. Unterschiede gibt. Allgemein anerkannt ist, dass es zumindest zwei ver­schiedene Arten von Komplexität gibt, die im Englischen als inherent complexity und accidential complexity bezeichnet werden.

inhärente oder essenzielle Komplexität

Die essenzielle Komplexität bezeichnet die reine, dem eigentlichen Problem innewohnende Komplexität. So gibt es in der Regel für die Lösung eines Problems (sofern diese existiert) immer eine gewisse Vorgehensweise. Der Grad der Komplexität ist nur abhängig vom Problem selbst. Die Bildung eines arithmetischen Mittels weist so sicherlich einen geringeren Komplexitätsgrad auf als beispiels­weise das Finden einer Lösung für eine Differentialgleichung oder das Erstellen eines Flugplans für die Flotte einer Flug­gesellschaft.

unbeabsichtigte Komplexität

Die unbeabsichtigte Komplexität beschreibt dagegen eine Komplexität, die nicht dem Problem direkt zuzuordnen ist, sondern dem konkreten Lösungsansatz. Wir gehen also davon aus, dass es verschiedene Vorgehensweisen gibt, die zur Problemlösung führen und denen ein Komplexitätsgrad zugeschrieben werden kann. Faktoren, die Einfluss auf die unbeabsichtigte Komplexität haben können, werden wir später genauer betrachten. Aus den obigen Ausführungen lassen sich damit zwei Feststellungen treffen, die zu entsprechenden Folgerungen führen:

  1. Inhärente Komplexität ist Teil des eigentlichen Problems und damit unvermeidbar! Versuche einen optimalen Weg zu finden, mit ihr umzugehen!
  2. Unbeabsichtigte Komplexität ist Teil der Problemlösung und damit beinflussbar! Schaffe alle Voraussetzungen, um eine unbeabsichtigte Komplexität zu minimieren!

Cynefin-Framework

Wenden wir uns nun speziell den Softwareprojekten zu. Bezüglich unserer ersten Feststellung gibt es eine gute Nachricht. Die Frage nach dem Umgang mit der evolutionären Natur komplexer Systeme und ihren inhärenten Unsicherheiten (und damit haben wir es bei Software in der Regel zu tun) haben sich auch schon andere Fachbereiche gestellt.

Von Dave Snowden stammt beispielsweise das Cynefin-Framework (Cynefin ist das walisische Wort für Lebensraum [Q1]), das auf Forschungen u. a. aus der System­theorie, den Kognitionswissenschaften und der Psychologie beruht. Das Framework hier im Detail zu erläutern, würde den Rahmen des Artikels sprengen, deshalb soll hier nur auf die für uns wichtige Essenz eingegangen werden.

Der Idee liegt vereinfacht gesagt der Gedanke zugrunde, dass nicht die (inhärente) Komplexität selbst das Problem ist, da wir auf sie keinen Einfluss haben, sondern der Umgang mit ihr. Das Framework führt die Typisierung aus Abbildung 2 ein und zeigt konkrete Handlungsanweisungen zum Umgang mit Systemen der entsprechenden Kategorie auf.

Auf die Softwareentwicklung übertragen, spiegelt sich dies z. B. in den Vorgehensmodellen wieder. So ist es heute fast etabliert, dass man nur noch bei einfachen Systemen nach einem Wasserfall-Modell vorgeht, während man bei komplizierteren Systemen zumindest eine inkrementelle, iterative Vorgehensweise wählt und bei komplexen Systemen fast ausschließlich im agilen Bereich unterwegs ist.

Dem Cynefin-Framework folgend bleibt uns als Entwickler oder Architekt die Aufgabe, zu erkennen, mit welcher Art von Problem wir es zu tun haben und entsprechend zu handeln ― also eine geeignete Vorgehensweise zu wählen.

Komplexität der Problemlösung

Unsere zweite Feststellung, dass die Komplexität der Problemlösung beinflussbar ist, müssen wir etwas genauer unter die Lupe nehmen. Unsere Idealvorstellung ist, dass wir uns bei der Problemlösung ausschließlich um die Bewältigung der inhärenten Komplexität kümmern müssen, dass also keinerlei unbeabsichtigte Komplexität existiert.

Als Entwickler oder Architekt sind wir dabei stets auf der Suche nach geeigneten Lösungen. Wir wenden Strategien an, die wir irgendwann einmal gelernt haben oder deren Anwendung sich bereits in ähnlichen Situationen bewährt hat. Einige Prinzipien wie z. B. die Aufteilung in Teil­probleme oder die Abstraktion von konkreten Problem­stellungen auf allgemeinere leisten uns dabei gute Dienste.

Wir befinden uns jedoch stets in einem Kontext, der bestimmte Optionen bzgl. der Problemlösung eröffnet oder versperrt. Da die Gefahr besteht, dass wir uns dieses Kontextes gar nicht immer bewusst sind, ist es wichtig sich einmal zu vergegenwärtigen, welches die wichtigsten Aspekte sind.

Problemverständnis

Die genaue Kenntnis des Problems ist der zentrale Ansatzpunkt und die wichtigste Voraussetzung für das Finden einer geeigneten Lösung. Das klingt banal und nach einer Selbstverständlichkeit, aber leider kommt es immer wieder vor, dass falsch oder unvollständig verstandene Probleme zu unnötig komplexen oder im schlimmsten Fall zu keiner Lösung führen.

Erst das exakte und vollständige Problemverständnis versetzt uns in die Lage, eine angemessene Lösung zu finden. Nur mit dieser Erkenntnis können wir zwischen inhärenter und unbeabsichtigter Komplexität unterscheiden.

Randbedingungen

Ohne die genauen Randbedingungen zu kennen, ist es nicht möglich eine geeignete Lösung zu finden. Es ist wichtig zu verstehen, dass jede Randbedingung Einfluss auf die Problemlösung und damit auf die unbeabsichtigte Komplexität hat. Randbedingungen stammen aus unterschiedlichen Bereichen. Technische Aspekte sind naheliegende Randbedingungen, allerdings sind rechtliche, politische oder organisatorische Rand­bedingungen mindestens ebenso relevant. Eine besondere Rolle spielen in diesem Zusammenhang die nicht-funk­tionalen Anforderungen, die die Qualität bezüglich Bedienbarkeit, Performance, Wartbarkeit etc. definieren.

Kenntnisse und Fähigkeiten

Lösungsansätze werden von Menschen entwickelt. Daraus folgt auch, dass deren Kenntnisse, Fähigkeiten und Erfahrungen in diese Lösungen einfließen und sie prägen. Darin liegt aber auch die Gefahr, dass bessere Lösungen über­sehen werden können, sofern sie sich den handelnden Personen durch einen Mangel an genannten Eigen­schaften entziehen.

Haben wir uns das Problem klar gemacht und die Anforderungen und Randbedingungen ermittelt, treten wir normalerweise irgendwann in den Prozess der konkreten Lösungsfindung ein. An dieser Stelle müssen wir uns bewusst sein, dass mit den nun folgenden Entscheidungen maßgeblich die Ausprägung der (unbeabsichtigten) Komplexität bestimmt wird.

Die Gefahr lauert hier zum einen in Gestalt des Hammer-Nagel-Syndroms: „Besitzt du als einziges Werkzeug einen Hammer, so sieht jedes Problem nach einem Nagel aus!“ Etwas allgemeiner formuliert lässt sich sagen, dass der
Lösungsansatz stark von den Erfahrungen, Kenntnissen und Fähigkeiten des „Problemlösers“ abhängt. Für einen Architekten bedeutet dies z. B., dass er gut beraten ist, sich ständig Feedback über seine angedachte Lösung von den beteiligten Personen einzuholen. Dieser Personenkreis ist nicht auf das Entwicklerteam beschränkt und umfasst tatsächlich alle Stakeholder vom Management bis zum Betrieb.

Ein solches Vorgehen trägt dem zweiten kritischen Aspekt der Komplexität Rechnung und wird je nach Position, Erfahrung und Wissensstand subjektiv sehr unterschiedlich bewertet. Durch das Feedback lassen sich Wissenslücken schließen und eine allgemein akzeptierte Lösung finden. Das Gesagte kann analog auf die Wahl von Methoden und Werkzeugen (Programmiersprachen, Frameworks, Tools, Vorgehensmodelle, Qualitätsstandards, organisatorische Maßnahmen, etc.) übertragen werden, deren Einfluss auf die unbeabsichtigte Komplexität von großer Bedeutung ist.

Suche nach dem Heiligen Gral

Aus der Sicht des Architekten bzw. Entwicklers ist die Minimierung der unbeabsichtigten Komplexität ein wichtiges Ziel. Einmal vorausgesetzt, dass für ein Problem eine Lösung existiert (und eine Implementierung realistisch ist), gibt es aber unzählige Varianten der Umsetzung. Das Vorhaben, hier die beste Lösung (bzgl. der Minimierung der Komplexität) zu finden, gleicht aber der Suche nach dem Heiligen Gral. Das liegt, wie zuvor erläutert, an der nicht immer eindeutigen Bewertung der Anforderungen und Randbedingungen bzw. an der subjektiven Einschätzung von Komplexität.

Ist es also unmöglich, einen objektiven Maßstab für die Güte eines Systems über die Eigenschaft der Komplexität zu definieren? Tatsächlich ist das mit der Objektivität nicht so einfach - wir haben den Einfluss der Randbedingungen und der subjektiven Einschätzungen gerade erläutert. Trotzdem lässt sich ein pragmatischer Ansatz finden, der uns unter Berücksichtigung der genannten Problematik, die Beurteilung einer Problemlösung auf Basis der Komplexität ermöglicht.

Dazu stellen wir zunächst die wichtigsten Merkmale einer Lösung heraus. Dies kann auf der Grundlage eines Katalogs oder erfahrungsbasiert geschehen. Die Merkmale und deren Auswirkungen lassen sich in der Regel neutral und klar beschreiben. Hier spielt die subjektive Bewertung noch keine Rolle, lediglich eine gewisse Vollständigkeit der entscheidenden Merkmale ist wichtig. Der Softwarearchitekt spricht auch vom Identifizieren der wichtigsten Architekturtreiber.

In einem zweiten Schritt werden die identifizierten Merkmale von allen Beteiligten bewertet. An dieser Stelle fließen die subjektiven Einschätzungen ein. Die Kunst ist es jetzt, eine geeignete Methode für die Gesamtbewertung zu finden. Müssen z. B. die Einschätzungen der Entwickler stärker berücksichtigt werden als die des Betriebes? Oder gibt es für bestimmte Merkmale ein K.-o.-Kriterium? Wie dies aussehen könnte, soll am Beispiel der Microservices kurz angerissen werden.

Microservices

Die Grundidee von Microservices ist es, große, monolithische Systeme zu vermeiden und deren Funktionalität, aufgeteilt nach fachlichen Belangen, in kleineren, autonomen Diensten zur Verfügung zu stellen. Diese Dienste sollen von einem zuständigen Team im Sinne eines „Produktes“ von der Planung bis zum Betrieb betreut werden. Letzteres folgt dem DevOps-Gedanken und soll helfen, optimale Teamstrukturen zu schaffen, um nach­teilige Kommunikationsstrukturen zu vermeiden (Conway’s Law). Dem Team obliegt die völlige Freiheit bei der Wahl der Mittel, insbesondere im Bereich der verwendeten Technologien. Microservices stellen sich in der Regel als verteilte Anwendungen dar, die ihre Funktionalität über HTTP per REST-APIs zur Verfügung stellen.

Schauen wir uns die genannten Eigenschaften an, so sollten in unserem Merkmalkatalog jetzt die Aspekte Strukturierung, Schnittstellen, Kommunikationsmechanismen und Technologien stehen. Das darf und muss durchaus auch detaillierter aufgeschlüsselt werden, so wollen wir später beispielsweise die Einschätzung bezüglich REST oder HTTP von den Beteiligten einfordern.

Abstraktion und Modularisierung

Zwei Teilaspekte der Komplexität von monolithischen Systemen sind sicherlich deren Wartbarkeit und die Schwierigkeit, sie effizient in Continous-Delivery-Prozesse einzubinden. Microservices verfolgen hier in Bezug auf die Strukturierung der Systeme u. a. einen „Teile und Herrsche“-Ansatz. Der Monolith wird aufgebrochen, die enge interne Koppelung gelöst und durch mehrere kleine, jetzt lose gekoppelte Teilsysteme mit definierten Schnittstellen ersetzt. Bezüglich Wartbarkeit und Betrieb haben wir jetzt die Komplexität deutlich verringert. Werfen wir aber einen Blick hinter die Kulissen, wird ersichtlich, dass dies auch Konsequenzen hat.

Schnittstellendesign und Asynchronität

Durch die Verteilung des Gesamtsystems auf auto­nome Services wechselt das zentrale Kommunikationspara­digma. Wir begeben uns direkt auf das Terrain der Asynchronität. Die Koordination der Service-Aufrufe stellt jetzt andere Herausforderungen dar. Es gibt plötzlich Dinge zu berücksichtigen, die in einem Monolithen von unter­geordneter Relevanz waren, wie der Umgang mit Netzwerkverbindungen (z.B. Fehlerbehandlung), Nachrichtentransport oder Lastverhalten.

Eine lose Koppelung schafft zusätzliche Schnittstellen. Im Falle von Microservices (HTTP-basierte REST-API) handelt es sich im übertragenen Sinne um eine Art Remote Procedure Call. Das Schnittstellendesign (z. B. die Granularität) ist ein entscheidender Punkt für deren Effizienz. Schnittstellen sind außerdem empfindlich gegenüber Änderungen, die in der Regel direkt Einfluss auf Nachbarsysteme haben. Die daraus evtl. notwendig werdende Versionierung von Schnittstellen ist ebenfalls ein nicht zu unterschätzender Aspekt.

Technologiezoo

Der Microservices-Ansatz propagiert die freie Wahl der Mittel. Dies hat den großen Vorteil, dass tatsächlich das am besten geeignete Werkzeug für die Lösung eines Problems gewählt werden kann. Es kann eine erhebliche Verein­fachung sein, wenn es z. B. auf der Technologieseite keine Einschränkungen gibt. Bestimmte Programmiersprachen, Frameworks, Datenbanken oder Betriebssysteme etc. liefern in einzelnen Problembereichen einfach die besseren, effizienteren Lösungen als andere.

Viele verschiedene Technologien bedeuten aber auch, dass entsprechendes Know-how verfügbar sein muss. Das stellt wiederum erhöhte Anforderungen bezüglich der Fertigkeiten und Kenntnissen an die Teams. In einigen Bereichen,
häufig bei Querschnittsaspekten wie Reporting, Sicherheit, Transaktionalität, fällt unter Umständen ein mehrfacher Implementierungsaufwand an, da technologieüber­geifende Lösungen hier besonders schwierig werden können. Die analoge Argumentation gilt auch für den Betrieb.

Ist jetzt alles einfacher?

Mit dieser Frage sind wir direkt bei unserem zuvor beschriebenen zweiten Schritt. Wir lassen uns die jeweilige Einschätzung dazu von allen Beteiligten liefern. Die Entwickler empfinden ein asynchrones Kommunikationsmodell über Rechnergrenzen hinweg wahrscheinlich nicht als einfacher, als die synchrone Aufrufsemantik innerhalb eines Monolithen. Der Betrieb ist evtl. nicht begeistert, dass er jetzt mehr und technisch sehr unterschiedliche Umgebungen betreuen muss.

Mangelndes Know-how in einem oder mehreren Bereichen (z. B. Netzwerkinfrastruktur) könnte zudem ein K.-o.-Kriterium sein. Auf der anderen Seite wird es das Management sehr begrüßen, auf neue Anforderungen schneller rea­gieren zu können.

Der entscheidende Punkt ist jetzt, ob man in der Gesamtbewertung unter Berücksichtigung (Gewichtung) aller Aspekte und Beteiligten zu dem Schluss kommen kann, dass die in Betracht gezogene Problemlösung (hier das Architekturmuster Microservices) anderen überlegen ist.

Um auf die Eingangsfrage zurückzukommen, ob jetzt alles einfacher ist, müssen wir jedoch auch in Betracht ziehen, das wir unter Umständen geeignete Lösungen finden, die jedoch tatsächlich auch zu einer erhöhten Komplexität führen. Dies bedeutet, dass wir mit dem beschriebenen Vorgehen zwar die Komplexität als Maßstab benutzen, dies aber nicht zur Minimierung derselben führt.

Bezogen auf unser Microservices-Beispiel sind damit Aussagen, die Microservices als Allheilmittel anpreisen, mindestens genauso unseriös wie jene, die diese pauschal als überschätzten Hype abtun. Microservices haben im Bereich der Systeme, die sehr kurze Entwicklungs- und Deployment-Zyklen umsetzen müssen, sicherlich große Vorteile. Wie wir gesehen haben, wird dies aber zumindest durch eine veränderte, nicht zu unterschätzende Kom­plexität erkauft.

Fazit

Das Streben nach Einfachheit liegt in unserer Natur. Zur Bekämpfung steigender Komplexität haben wir mit Konzepten wie Abstraktion und Modularisierung oder Prinzipien wie z. B. KISS („Keep it simple stupid“) einige wirksame Waffen im Arsenal. Wie beschrieben haben solche Maßnahmen aber immer auch Nebenwirkungen, die es zu identifizieren und zu bewerten gilt.

Für die Bewertung anhand des Kriteriums Komplexität bedarf es Erfahrungen und Know-how sowie die Fähigkeit, die Problemlösung möglichst vollständig im jeweils konkreten Kontext analysieren zu können. Wem das aus der Tätigkeitsbeschreibung des Softwarearchitekten bekannt vorkommt, liegt genau richtig. Es handelt sich hierbei um klassische Architekturarbeit. Dazu gibt es leider keine Alternative und es bleibt dabei: „There is no silver bullet.“

Andreas Flügge
()

Logo ORDIX<sup>®</sup>  news lang

Abbildungen

Die vollständigen Artikel mit allen Abbildungen finden Sie im blätterbaren PDF.Eine Übersicht über alle Artikel sowie das PDF zum Download finden Sie im Inhaltsverzeichnis.

Impressum


Impressum der ORDIX® news 3/2015

Links


[1] Erklärung Cynefin-Framework
[2] Webseite der Object Systems GmbH

Quellen


[Q1] Dave Snowden,
released under CC BY 3.0
[Q2] Fred P. Brooks

Bildnachweis


© istockphoto.com | Open notepad with concept of ... | Maximkostenko