IT-Berufe-Podcast Archiv
214 Episoden
60 Minuten
Um Möglichkeiten, Abhängigkeiten in Tests loszuwerden, geht es in der einhundertdreiundvierzigsten Episode des Anwendungsentwickler-Podcasts. TL;DR Mit Test-Doubles ersetze ich Abhängigkeiten beim automatisierten Testen objektorientierter Software, damit du als IT-Azubi einzelne Komponenten schnell und verlässlich prüfen kannst. Fakes bieten vereinfachte Implementierungen; Dummies erfüllen die Rolle eines Platzhalters. Stubs liefern vorgegebene Eingangswerte für Tests am System Under Test, während du mit Mocks dessen Methodenaufrufe an Abhängigkeiten prüfst. Bei Spies hängt die genaue Bedeutung vom Framework ab. Polymorphie und Dependency Injection machen die Objekte austauschbar, ergänzende Integrationstests prüfen das Zusammenspiel der echten Komponenten. Kapitelmarken [00:00:01] Einstieg ins Thema Test-Doubles [00:01:43] Grundlagen und Fokus auf objektorientierte Software [00:02:56] Anforderungen an automatisierte Tests [00:05:18] Unit-Tests und Integrationstests [00:06:23] Infrastruktur als Abhängigkeit im Test [00:08:21] Zusammenarbeit von Objekten und notwendige Abhängigkeiten [00:09:36] Beispiel: Login-Service und Repository [00:11:34] System Under Test und kontrollierte Testdaten [00:14:08] Test-Double als Oberbegriff für Ersatzobjekte [00:15:39] Polymorphie als Voraussetzung [00:16:37] Dependency Injection und testbarer Produktivcode [00:19:42] Mocking-Frameworks erstellen Test-Doubles [00:21:20] Fakes mit vereinfachter Implementierung [00:23:09] Dummies als Platzhalter [00:26:46] Stubs liefern vorgegebene Eingangswerte [00:29:59] Stubs mit Mockito konfigurieren [00:32:48] Queries, Commands und unabhängige Tests [00:36:39] Mocks prüfen ausgehende Methodenaufrufe [00:39:31] Beispiel: E-Mail-Versand mit einem Mock prüfen [00:41:53] Umfangreiche Tests und vermischte Aufgaben [00:43:14] Spies und ihre beiden Definitionen [00:46:20] Die Arten von Test-Doubles im Überblick [00:48:21] Vorteile und Grenzen von Test-Doubles [00:51:01] Framework-Begriffe und Wissen für die Prüfung [00:52:13] Echte Implementierungen und ergänzende Integrationstests [00:54:07] Verschachtelte Doubles und komplexe Test-Setups [00:55:19] Erfahrungen aus der Praxis und Bedeutung für IT-Azubis [00:57:50] Literatur zum Einstieg und weiterführende Episode [00:58:39] Shownotes und Feedback Inhalt Vorweg: Automatisierte Tests gibt es nicht nur für objektorientierte Software, sondern natürlich auch für funktionale, prozedurale usw. Die folgenden Inhalte beziehen sich aber ausschließlich auf die Objektorientierung. In anderen Paradigmen haben die genannten Begriffe evtl. andere Bedeutungen oder die vorgestellten Lösungen funktionieren etwas anders, da es z.B. keine Polymorphie gibt. Grundlagen Automatisierte Tests sollen das Verhalten unseres Systems prüfen und nur fehlschlagen, wenn ein Fehler im Code vorliegt. Sie sollen schnell und wiederholbar sein, damit sie so oft wie möglich ausgeführt werden. Sie sollen immer und überall (auf allen Rechnern/Umgebungen) ausführbar sein. Unit-Tests prüfen das Verhalten einer einzelnen Komponente, z.B. eine Methode, in Isolation. Integrationstests prüfen das Verhalten mehrerer Komponenten, z.B. Objekte, im Zusammenspiel. Integrationstests werden auch Tests genannt, die die Infrastruktur berühren, also z.B. eine Datenbank, das Netzwerk oder das Dateisystem. Die Infrastruktur sollte in Tests nicht berührt werden, da diese schnell Fehler produziert: erwartete Datenbankinhalte können sich ändern, im Dateisystem fehlen Berechtigungen oder das Netzwerk ist nicht verfügbar. Die Isolation von Komponenten ist schon in kleinen Systemen nicht immer einfach. Ein Objekt kann seine Aufgaben fast nie komplett allein erledigen, sondern braucht andere Objekte dafür. Ein Service braucht vielleicht ein Repository, um die zu verarbeitenden Daten aus der Datenquelle zu lesen. Ist kein Repository vorhanden, gibt es vielleicht eine NullPointerException beim Aufruf der zu testenden Methode. Diese Abhängigkeiten machen die Tests schwierig, da das zu testende Objekt nicht korrekt funktioniert, wenn sie nicht vorhanden sind. Somit müssen alle für den konkreten Test benötigten Abhängigkeiten durch diesen bereitgestellt werden. Somit enthält ein Test nicht nur die eigentlich zu testende Komponente, sondern auch noch ihre Abhängigkeiten. Damit klar ist, welche der verschiedenen Komponenten nun eigentlich getestet werden soll, bekommt sie die Bezeichnung System under test (abgekürzt SUT). Beim Test können grundsätzlich die "echten" Komponenten verwendet werden, falls dies möglich und sinnvoll ist. Oder die Komponenten werden durch sog. Test Doubles ersetzt, wie ein Stuntdouble den eigentlichen Schauspieler ersetzt. Test Doubles Test Doubles sind der Oberbegriff für Komponenten, die in Tests verwendet werden, um die Abhängigkeiten des SUT zu ersetzen. Sie sollen vor allem für vorhersagbare Testergebnisse sorgen, indem z.B. immer die gleichen Werte aus dem Speicher zurückgegeben werden und nicht potentiell unterschiedliche Werte aus der Datenbank gelesen werden. Damit das Ganze funktioniert, müssen die echten Komponenten durch die Test Doubles ersetzt werden können. In objektorientierter Software kommt dabei die Polymorphie zum Einsatz. Die Abhängigkeiten müssen also z.B. als Interface oder als (abstrakte) Basisklasse vorliegen, damit die Test Doubles anstelle der echten Komponenten genutzt werden können. Außerdem ist es nötig, dass die Test Doubles dem SUT "untergejubelt" werden können. Es ist also irgendeine Form von Dependency Injection nötig, z.B. Konstruktorparameter oder Setter-Methoden. Sobald das SUT sich selbst seine Abhängigkeiten erzeugt (z.B. mit new), ist ein Test mit Test Doubles schwierig oder gar unmöglich. Das alles hat auch eine Auswirkung auf den Produktivcode. Denn wenn das SUT eine Abhängigkeit als Konstruktorparameter übergeben bekommen muss, wird auch der Produktivcode die echte Komponente so hineingeben müssen. Die Tests haben somit indirekt zur Folge, dass der Code insgesamt modularer wird, was die Softwarequalität erhöht. Zum Erstellen von Test Doubles gibt es verschiedene Frameworks, z.B. Mockito in Java oder Moq für .NET. Fakes Fakes (engl. fake = Fälschung, Imitation) können ohne Framework einfach selbst implementiert werden. Ihre Implementierung ähnelt der echten, ist aber z.B. einfacher/schneller oder gibt nur harte Werte zurück. Beispiel: InMemory-Datenbank statt einer echten verwenden. Dummy Dummies (engl. dummy = Attrappe, Strohmann) sind Platzhalter, deren Funktion im Test eigentlich gar nicht benötigt wird. Sie werden verwendet, um den Compiler zufriedenzustellen, da z.B. ein Objekt als Parameter erwartet wird. Wenn die Funktionalität wirklich überhaupt nicht verwendet (=aufgerufen) wird, kann auch null verwendet werden. Stubs Stubs (engl. stub = Stummel, Stumpf) geben auf Anfragen definierte (=harte) Werte zurück, um das Verhalten des SUT vorhersagbar zu machen oder teure und fehleranfällige Zugriffe auf die Infrastruktur zu vermeiden. Außerdem dienen sie dazu, ansonsten schwer zu produzierende Zustände abzubilden, z.B. das Werfen einer Exception. Stubs werden für in das SUT eingehende Daten verwendet. Beispiel: Ein Repository gibt dem SUT immer den gleichen Datensatz zurück, ohne auf die Datenbank zuzugreifen. Das Verhalten kann parametrisiert werden, z.B. für ID 1 ein bestimmter Datensatz und für andere IDs eine Exception. Beispiel in Mockito: when(repo.getUser(1)).thenReturn(new User("Stefan")); Einsatzgebiete: Dateisystem, DB, Netzwerk usw. Teilt man die Methodenaufrufe seines Systems in Queries (nur lesen, keine Zustandsänderung, Rückgabewert) und Commands (Zustandsänderung, kein Ergebnis als Rückgabewert) auf, verwendet man Stubs für die Queries. Die Tests verwenden "normale" Assertions, um das Ergebnis des SUT zu prüfen (assert in JUnit). Mocks Mocks (engl. mock = Fäschung, Nachahmung) "merken" sich die Methodenaufrufe an ihnen und können im Nachhinein verifizieren, ob ein Methodenaufruf stattfand, wie oft und mit welchen Parametern. Mocks werden für aus dem SUT ausgehende Befehle verwendet. Beispiel: Das SUT soll eine Mail verschicken und dafür am MailServer die Methode send() mit bestimmten Parametern (z.B. Adresse, Betreff) aufrufen. Oftmals müssen die Mocks auch Daten zurückgeben, damit das SUT funktioniert. Eigentlich sollten sie das aber nicht tun. Dies weist auf eine Vermischung von Command und Query hin. Beim Command-Query-Pattern, verwendet man Mocks für die Commands. Die Tests verwenden keine Assertions gegen das SUT, sondern prüfen am Mock, ob die richtigen Methoden aufgerufen wurden (verify in Mockito). Beispiel in Mockito: verify(mailServer).send("stefan@macke", "Hallo Stefan!"); Spy Spies (engl. spy = Spion) sind nicht eindeutig definiert. Ein Spy kann ein Stub mit "Aufzeichnungsfunktion" der Interaktionen (ähnlich zum Mock) sein (siehe Test Double). In Mockito ist ein Spy eine Art Mock zur Aufzeichnung der Interaktionen, aber mit der Möglichkeit der Delegation der Aufrufe an die echte Komponente (siehe Spy). Der Spy "umschließt" also das echte Objekt, kann einzelne Methoden überschreiben und delegiert den Rest an das echte Objekt. Im Nachhinein kann dann noch geprüft werden, welche Methoden aufgerufen wurden. Vor- und Nachteile von Test Doubles Vorteile Tests sind nicht abhängig von änderungsanfälliger Infrastruktur. Tests sind einfacher, da keine komplexe Infrastruktur aufgebaut werden muss. Tests lassen sich jederzeit und überall wiederholbar durchführen. Tests sind schneller, da keine Infrastruktur berührt wird. Der Code wird modularer und Abhängigkeiten werden offensichtlich. Nachteile Das Zusammenspiel der "echten" Komponenten wird nicht getestet. Es sind zusätzliche Integrationstests nötig. Das einfache Erstellen von Test Doubles mit Frameworks führt ggfs. zu komplexen Test-Setups oder Overengineering. Allgemeine Hinweise und Empfehlungen Viele Frameworks (u.a. Mockito) unterscheiden nicht zwischen Stub und Mock....
1 Stunde 30 Minuten
Eine Einführung in die wichtigsten Begriffe rund um Programmierung und Objektorientierung gibt es in der einhundertzweiundvierzigsten Episode des Anwendungsentwickler-Podcasts. TL;DR An Beispielen mit Autos und einem Apfelkuchenrezept zeige ich dir die Grundbegriffe der Programmierung und Objektorientierung, mit denen du als IT-Azubi einsteigen kannst. Du erfährst, wie Compiler und IDE beim Entwickeln helfen, wie Klassen als Baupläne für Objekte dienen und wie du Daten über typisierte Variablen speicherst. Ausdrücke liefern Ergebnisse, während Anweisungen festlegen, was der Computer tun soll. Mit Methoden kannst du Algorithmen unter einem Namen aufrufen und ihnen über Parameter unterschiedliche Werte übergeben. Kapitelmarken [00:00:20] Einstieg und Ziel der Einführung [00:02:02] Voraussetzungen und Fokus auf Java [00:03:45] Compiler und Quelltext [00:06:10] Syntax und Compile-Fehler [00:08:28] Fehlermeldungen lesen und Fehler beheben [00:10:53] IDE als integrierte Entwicklungsumgebung [00:14:26] Java-IDEs und Eclipse im Ausbildungsbetrieb [00:15:49] Objektorientierung und Prüfungsbezug [00:17:00] Objekte mit Eigenschaften und Funktionen [00:19:24] Modelle passend zum Anwendungsfall entwerfen [00:22:03] Eigenschaftswerte und Identität von Objekten [00:22:57] Klassen als Baupläne und Objekte als Instanzen [00:25:37] Datentypen und erlaubte Operationen [00:30:26] Statische Typisierung in Java [00:32:17] Integer und Double [00:33:56] String und Boolean [00:36:32] Klassen als eigene Datentypen [00:39:53] Variablen und benannte Speicherbereiche [00:42:04] Variablen deklarieren mit Datentyp und Bezeichner [00:44:57] Ausdrücke und Konkatenation [00:47:05] Operatoren und Operanden [00:48:51] Unäre, binäre und ternäre Operatoren [00:51:11] Anweisungen und imperatives Programmieren [00:53:28] Ausdrücke innerhalb von Anweisungen [00:55:18] Algorithmen am Beispiel eines Apfelkuchenrezepts [00:58:24] Sequenzen und Verzweigungen [01:00:33] Wiederholungen und kombinierte Abläufe [01:04:10] Algorithmen mit if und Schleifen umsetzen [01:05:38] Methoden als wiederverwendbare Algorithmen [01:08:35] Methoden in Klassen und Objekten [01:10:17] Blöcke und geschweifte Klammern [01:12:52] Größere Programme aus Methoden zusammensetzen [01:14:23] Methodenkopf, Methodenrumpf und Rückgabewerte [01:16:10] Methoden ohne Rückgabewert mit void [01:17:05] Parameter für unterschiedliche Eingaben [01:21:02] Argumente und mehrere Parameter [01:23:38] Rückblick auf die Grundbegriffe [01:28:36] Feedback und Abschluss Inhalt Compiler und IDE Was ist ein Compiler? Ein Compiler übersetzt Sourcecode (z.B. for (int i: numbers)), den ein Mensch schreibt, in Maschinencode (z.B: 00011010 00011010), den ein Computer ausführen kann. Dafür muss der Sourcecode absolut fehlerfrei sein, sonst gibt es Compiler-Fehler. Die einzuhaltenden Regeln werden durch die Syntax der Programmiersprache bestimmt. Zur Syntax gehören Rechtschreibung, Interpunktion und Grammatik. Was ist eine IDE? Eine Integrated Development Environment (integrierte Entwicklungsumgebung) ist eine Software, mit der andere Software entwickelt wird. Sie enthält meist einen Editor und den Compiler. Objekte und Klassen Was ist ein Objekt? Ein Objekt ist ein Ding der realen Welt mit Eigenschaften und Funktionen, z.B. ein Auto mit Eigenschaft Farbe und Funktion fahren. Ein Objekt ist immer nur ein Modell der Realität, das sich je nach Einsatzzweck unterscheiden kann. Beim Auto interessiert sich die Tankstellenanwendung vielleicht nur für das Kennzeichen und die Größe des Tanks, während eine Werkstatt sich für den Kilometerstand und den Hersteller interessiert. Was ist eine Klasse? Eine Klasse ist ein Bauplan für Objekte, in dem festgelegt wird, welche Eigenschaften und Funktionen alle (!) Objekte dieser Klasse haben müssen. Aus einer Klasse können dann mehrere Objekte erzeugt werden, die alle die gleichen Eigenschaften und Funktionen haben, die sich jedoch in den Werten ihrer Eigenschaften unterscheiden können. Beispiel: Die Klasse Auto definiert die Eigenschaft Farbe und die Funktion fahren. Aus dieser Klasse können zwei Objekte erstellt werden, von denen eins den Wert blau für die Farbe hat und das andere den Wert rot. Außerdem kann noch ein weiteres Auto erstellt werden, das ebenfalls blau ist, mit dem anderen blauen Auto aber nichts zu tun hat. Genau wie in der Realität kann es "baugleiche" Autos geben, die trotzdem individuelle Einzelstücke sind. Datentypen und Variablen Was ist ein Datentyp? Ein Datentyp legt fest (und der Compiler prüft): Art der Daten (z.B. Zahlen, Zeichenfolgen, Wahrheitswerte) Länge der Daten (z.B. 32 Bit für Zahlen) Erlaubte Operationen auf den Daten (z.B. Addition für Zahlen oder Konkatenation für Zeichenketten) Nicht erlaubt wären: Ganzzahl a = "Hallo"; ("Hallo" ist keine Ganzzahl) Byte b = 32321; (32321 ist zu groß für ein Byte) true + false (Wahrheitswerte können nicht addiert werden) Verbreitete Datentypen, die es in vielen Programmiersprachen gibt: Integer: Ganzzahlen (meist 32 Bit lang) Double: Gleitkommazahlen String: alphanumerische Zeichenketten Boolean: Wahrheitswerte (true und false) Man kann auch eigene Datentypen definieren. Das wären dann die Klassen, die eine beliebige Kombination aus anderen Datentypen als Attribute enthalten können. Was ist eine Variable? Eine Variable ist ein benannter Speicherbereich, der in einem Programm für die Verarbeitung verwendet werden kann, damit man nicht mit kryptischen Speicheradressen wie 0xA042BC2 arbeiten muss. Variablen haben einen Datentyp und einen Bezeichner, z.B. Integer alterDerPerson (in Java). Der Wert einer Variablen kann während der Programmlaufzeit verändert werden. Ausdrücke, Operationen und Anweisungen Was ist ein Ausdruck (oder eine Expression)? Ein Ausdruck führt bei der Auswertung zu einem Resultat. Beispiele: 1 + 2 (-> 3), (43.2 + 2) * 3 (-> 135.6), "Hallo" + "Welt" (-> "HalloWelt") Was sind Operatoren und Operanden? Operanden sind die Werte, die verarbeitet werden sollen. Operatoren verknüpfen die Operanden zu Ausdrücken. Sie bilden z.B. die arithmetischen Operationen (Addition, Multiplikation usw.) ab. Je nach Typ hat ein Operator einen (unär), zwei (binär) oder drei (ternär) Operanden. 1 + 2 -> 1 und 2 sind die Operanden, die mit dem Operator + (Addition) zum Ausdruck verknüpft werden, dessen Resultat 3 ist. Beispiele für arithmetische Operatoren: +, -, *, /, % Was ist eine Anweisung (oder ein Statement)? In der imperativen Programmierung formulieren wir unsere Programme in Form von Anweisungen oder Befehlen, die der Computer ausführen soll. Beispiele: Wertzuweisungen zu Variablen, Ausgaben, if, for Anweisungen müssen mit Semikolons abgeschlossen werden (in Java). Was ist ein Algorithmus? Ein Algorithmus ist eine Beschreibung zur Lösung eines Problems. Beispiel: Rezept zum Backen eines Apfelkuchens. Löst das Problem eines fehlenden Apfelkuchens! ;-) Algorithmen können beliebig oft wiederholt werden und sollten immer zu einem vorhersagbaren Ergebnis führen (z.B. einem leckeren Apfelkuchen). Algorithmen bestehen aus drei grundlegenden Strukturen: Sequenz: Eine Folge von Anweisungen, die der Reihe nach abgearbeitet werden. Beispiel: schaeleApfel; zerkleinereApfel; legeApfelAufTeig; Verzweigung: Eine Fallunterscheidung, bei der abhängig von einer Prüfung unterschiedliche Anweisungen ausgeführt werden. Beispiel: if (schokostreuselGewuenscht) { fuegeSchokostreuselHinzu; } Wiederholung: Das mehrfache Ausführen der gleichen Anweisung(en). Beispiel: for (Apfel a: aepfel) { schaeleApfel(a); } Blöcke und Methoden Was ist ein Block? Ein Block fasst eine Gruppe aus Anweisungen zusammen und ergibt damit eine neue Anweisung. Ein Block kann grundsätzlich überall verwendet werden, wo auch eine Anweisung erlaubt ist. Ein Block wird an einigen Stellen erwartet, z.B. um den Rumpf einer Schleife oder Verzweigung zu definieren. Blöcke werden in vielen Programmiersprachen in geschweifte Klammern ({}) eingeschlossen. Was ist eine Methode? Eine Methode ist ein wiederverwendbarer, benannter Algorithmus. Der Kopf einer Methode besteht aus: Rückgabewert, Name, Parametern. Der Rückgabewert ist der Datentyp, den die Methode als ihr Ergebnis liefert. Die Parameter sind mehrere Variablen (Datentyp + Name), mit denen die Methode arbeitet. Sie werden vom Aufrufer in die Methode hineingegeben. Der Rumpf enthält die Implementierung als Folge von Anweisungen in einem Block. Die konkreten Werte, die der Aufrufer für die Parameter übergibt (z.B. 5 für den Parameter zahl), heißen Argumente. Nicht jede Methode muss einen Werte zurückgeben, es gibt daher auch void als Pseudo-Rückgabewert. Literaturempfehlungen Eine gute Einleitung in die obigen Themen gibt es in Java ist auch eine Insel von Christian Ullenboom*. * Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Von der Klasse zur Anweisung Datentypen, Typisierung, Variablen und Zuweisungen Ausdrücke, Operanden und Operatoren Zusammenfassung Einstieg für IT-Azubis Für den Einstieg in die Ausbildung zum/zur Fachinformatiker:in Anwendungsentwicklung greife ich auf Beispiele aus dem Alltag zurück. Du brauchst dafür kein Vorwissen. Die technischen Beispiele beziehen sich vor allem auf Java; die Grundbegriffe begegnen dir auch in anderen objektorientierten Sprachen. Objektorientierung gehört außerdem zu den zentralen Themen der IHK-Prüfung. Compiler und Syntax Wenn du Quelltext schreibst, formulierst du Befehle in einer Programmiersprache wie Java. Ein Compiler übersetzt diesen für Menschen lesbaren Source-Code in Maschinencode, den der Computer ausführen kann. Damit der Compiler deinen Code übersetzen kann, musst du die Syntax der Sprache einhalten. Dazu gehören korrekt geschriebene Wörter ebenso wie passende Satzzeichen und die vorgeschriebene Reihenfolge der Sprachbestandteile. Ein vergessenes Semikolon kann bereits einen Compile-Fehler auslösen,...
44 Minuten
Um Ports und Netzwerkprotokolle geht es in der einhunderteinundvierzigsten Episode des Anwendungsentwickler-Podcasts. TL;DR Mit ping prüfe ich, ob ein Ziel im Netzwerk antwortet und Pakete hin und zurück gelangen. Ports adressieren einzelne Dienste auf einem Server, während Netzwerkprotokolle festlegen, welche Befehle und Antworten Client und Server austauschen. Für deine Ausbildung gehören die verbreiteten Portnummern und die Abläufe von HTTP und SMTP zum Grundlagenwissen. Wenn du sensible Daten überträgst, brauchst du verschlüsselte Verbindungen wie HTTPS, weil Inhalte im Klartext unterwegs mitgelesen werden können. Kapitelmarken [00:00:00] Einstieg: Ports und Netzwerkprotokolle [00:00:43] Rückblick auf Routing, private IP-Adressen und NAT [00:01:45] Mit Ping die Erreichbarkeit prüfen [00:03:14] Fehlende Ping-Antworten und mögliche Ursachen [00:04:26] DNS und Routing mit Ping nachvollziehen [00:06:11] Mehrere Dienste unter einer IP-Adresse [00:07:28] Ports und gebundene Serverprozesse [00:08:48] Standardports und Well-Known-Ports [00:10:59] Ports für eigene Anwendungen wählen [00:12:26] Portnummern in der Services-Datei nachschlagen [00:14:04] Wichtige Protokolle und Ports für IT-Azubis [00:17:44] Mehrere Dienste auf meinem Server [00:18:27] SSH-Port ändern und Security by Obscurity [00:21:21] Was ein Netzwerkprotokoll festlegt [00:25:08] HTTP: GET und Statuscodes [00:27:00] SMTP mit Telnet nachvollziehen [00:28:30] SMTP-Ablauf beim Versand einer E-Mail [00:32:05] Warum gemeinsame Protokollstandards erforderlich sind [00:33:38] Textbasierte Protokolle und gefälschte Absenderadressen [00:35:29] Passwörter und Inhalte im Klartext [00:38:34] Sensible Daten über HTTPS übertragen [00:39:21] Rückblick auf Ports und Protokolle [00:42:14] Für die Prüfung vertiefen und weiterführende Links [00:43:10] Feedback und Abschluss der Netzwerkreihe Inhalt Mit dem Kommandozeilentool ping kann getestet werden, ob die Kommunikation zum Ziel über das Netzwerk grundsätzlich möglich ist. Wenn ja, kann man die Adresse dann z.B. auch im Browser aufrufen. Ports Die grundsätzliche Kommunikation steht nun also, aber woher weiß ein Server, welchen Dienst er einem Client anbieten soll (z.B. Mail oder WWW oder eben auf den "Ping" antworten)? Die Lösung sind Ports. Für jeden bekannten Dienst gibt es einen einzelnen Port, der einfach an die IP-Adresse bzw. an den DNS-Namen angehängt werden kann, z.B. google.de:80. Allgemein bekannte Dienste haben verbindlich festgelegte, so genannte well-known Ports bis 1024. Beispiele: HTTP 80, SMTP 25, SSH 22 oder Doom 666. Übrigens: ping benutzt das Protokoll ICMP, das Bestandteil von IP ist und keinen eigenen Port verwendet. Unter Windows gibt es in der Datei C:\Windows\System32\drivers\etc\services eine Liste dieser bekannten Ports. # Copyright (c) 1993-2004 Microsoft Corp. # # This file contains port numbers for well-known services defined by IANA # # Format: # # / [aliases...] [#] # echo 7/tcp echo 7/udp discard 9/tcp sink null discard 9/udp sink null systat 11/tcp users #Active users systat 11/udp users #Active users daytime 13/tcp daytime 13/udp qotd 17/tcp quote #Quote of the day qotd 17/udp quote #Quote of the day chargen 19/tcp ttytst source #Character generator chargen 19/udp ttytst source #Character generator ftp-data 20/tcp #FTP, data ftp 21/tcp #FTP. control ssh 22/tcp #SSH Remote Login Protocol telnet 23/tcp smtp 25/tcp mail #Simple Mail Transfer Protocol ... Protokolle Die Kommunikation steht also jetzt, aber was wird da nun konkret übertragen? Protokoll: Eine Abfolge von definierten Befehlen an den Server und dessen passenden Antworten. Leicht verständlich ist das Protokoll SMTP (Simple Mail Transfer Protocol) zum Versenden von E-Mails. Beispiel: HELO, MAIL FROM, RCPT TO, DATA, Subject: Test, . Mit Hilfe des Kommandozeilenwerkzeugs telnet kann man sich gezielt mit einem Port des Zielservers verbinden und die passenden Befehle zum jeweiligen Dienst ausführen. SMTP verwendet keinerlei Authentifizierung. Daher ist Spam so ein Problem. HTTP (Hypertext Transfer Protocol) verwendet Port 80. Bei HTTP werden andere Befehle verwendet, wichtig ist insb. das GET, mit dem man Ressourcen abrufen kann (also insb. Websites). Als Beispiel, wie wichtig dabei die Verschlüsselung (HTTPS anstatt HTTP) ist, kann man ein kleines Webformular erstellen, das einen Benutzernamen und ein "geschütztes" Passwort abfragt. Schneidet man den Netzwerkverkehr mit, kann man Benutzernamen und Passwort im Klartext mitlesen, auch wenn im Formular im Passwortfeld nur Sternchen zu sehen sind. Literaturempfehlungen Im guten alten IT-Handbuch für Fachinformatiker* werden in Kapitel 4 Netzwerkgrundlagen die meisten hier genannten Inhalte ausführlich erläutert. In meinem Buchclub gehe ich auf die Inhalte auch noch einmal im Detail ein. * Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Port (Protokoll) Internet Control Message Protocol Netzwerkprotokoll Simple Mail Transfer Protocol Hypertext Transfer Protocol Zusammenfassung Mit Ping prüfen, ob dein Ziel antwortet Wenn ich ein Netzwerkproblem untersuche, beginne ich mit ping. Hinter dem Befehl steht die IP-Adresse oder der DNS-Name des Ziels. Eine Antwort zeigt, dass Pakete zum Ziel gelangen und zurückkommen. Ping arbeitet mit dem ICMP-Protokoll. Bei einem DNS-Namen löst dein Client zunächst den Namen in eine IP-Adresse auf. Liegt das Ziel außerhalb des eigenen Netzes, gehen die Pakete über das Gateway beziehungsweise den Router weiter. Eine erfolgreiche Antwort bestätigt damit auch, dass die dafür erforderlichen Schritte funktionieren. Bleibt die Antwort aus, kommen verschiedene Ursachen infrage: Du hast eine falsche IP-Adresse oder einen falschen Namen eingegeben. Die Netzwerkkarte ist fehlerhaft konfiguriert. Der DNS-Name lässt sich nicht auflösen. Eine Firewall blockiert die Pakete. Der Zielserver beantwortet grundsätzlich keine Pings. Aus einer fehlenden Antwort allein lässt sich die Ursache daher schwer bestimmen. Einzelne Dienste über Ports ansprechen Auf meinem Server laufen mehrere Dienste unter derselben IP-Adresse, darunter ein Mailserver und ein Webserver. Über Ports kann eine Anfrage dem passenden Dienst zugeordnet werden. Die jeweiligen Serverprozesse binden sich dafür an einen Port und warten dort auf Anfragen. Eine Portnummer lässt sich mit einem Doppelpunkt hinter die IP-Adresse oder den DNS-Namen schreiben, beispielsweise google.de:80. Ports sind 16 Bit lang, wodurch sich 65.536 verschiedene Nummern ergeben. Wenn zwei Serverprozesse denselben Port beanspruchen, entsteht ein Konflikt. Im beschriebenen Fall kann der zweite Webserver deshalb nicht starten. Für deine eigene Anwendung müssen Client und Server auf dieselbe Portnummer eingestellt sein. Standardports kennen und nachschlagen Für verbreitete Dienste sind feste Portnummern vereinbart. Dadurch weiß ein Client, welchen Port er standardmäßig ansprechen soll. Bei HTTP ist das beispielsweise Port 80. Die ersten 1.024 Ports bilden den Bereich der Well-Known-Ports. Darin sind zahlreiche Dienste festgelegt, wobei zwischen den vergebenen Nummern auch Lücken liegen. Für eine eigene Anwendung kannst du einen Port oberhalb dieses Bereichs wählen, etwa 5000 oder 32000. Auch oberhalb der Well-Known-Ports gibt es bekannte Dienste mit üblichen Portnummern. Unter Windows findest du eine Liste in der Textdatei C:\Windows\System32\drivers\etc\services. Sie liegt im selben Verzeichnis wie die Hosts-Datei und enthält Dienstnamen, Portnummern und Kommentare. Diese Ports gehören zum Grundlagenwissen für dich als IT-Azubi, auch als Fachinformatiker:in Anwendungsentwicklung: | Port | Protokoll oder Dienst | Aufgabe | | --- | --- | --- | | 21 | FTP | Dateien übertragen | | 22 | SSH, Secure Shell | Server administrieren | | 23 | Telnet | Server aus der Ferne verwalten, unverschlüsselt | | 25 | SMTP, Simple Mail Transfer Protocol | E-Mails versenden | | 53 | DNS | Namen in IP-Adressen auflösen | | 80 | HTTP | Websites abrufen | | 110 | POP3, Post Office Protocol | E-Mails abrufen | | 143 | IMAP, Internet Message Access Protocol | E-Mails auf dem Server verwalten und abrufen | | 389 | LDAP, Lightweight Directory Access Protocol | Auf Verzeichnisdienste zugreifen, etwa im Active Directory | | 443 | HTTPS | HTTP-Inhalte verschlüsselt übertragen | | 3389 | Remote Desktop | Windows-Systeme aus der Ferne administrieren | Bei POP3 werden E-Mails im vereinfachten beschriebenen Ablauf abgeholt und anschließend vom Server entfernt. Mit IMAP bleiben sie auf dem Server verfügbar, sodass du von mehreren Clients darauf zugreifen kannst. Als Anekdote gehört Port 666 dazu, den id Software für Doom reservieren ließ. Für die Prüfung stehen die verbreiteten Dienste im Vordergrund. Ihre Ports brauchst du auch, wenn du Netzwerksoftware entwickelst oder in einer Firewall festlegst, welche Verbindungen erlaubt sind. Einen anderen SSH-Port einstellen Auf meinem Server habe ich SSH auf einen anderen Port gelegt. Viele automatisierte Angriffe richten sich zuerst gegen den bekannten Port 22. Wer einen anderen Port verwendet, muss sowohl den SSH-Server als auch die eigenen Clients entsprechend konfigurieren. Das Verstecken eines Dienstes heißt Security by Obscurity. Durch einen Portscan lässt sich der Dienst weiterhin finden. Der SSH-Server braucht deshalb zusätzliche Schutzmaßnahmen, etwa verschlüsselte Verbindungen und ein Passwort. Befehle und Antworten mit Protokollen festlegen Ein Netzwerkprotokoll beschreibt,...
45 Minuten
Um private IP-Adressbereiche und das Routing von Netzwerkpaketen geht es in der einhundertvierzigsten Episode des Anwendungsentwickler-Podcasts. TL;DR An meinem Heimnetz mit einer FRITZ!Box zeige ich dir, wie Geräte mit privaten IPv4-Adressen Daten aus dem Internet empfangen: NAT ersetzt die private Absenderadresse durch die öffentliche Adresse des Routers und ordnet Antworten dem passenden Gerät zu. Durch Routing gelangen Pakete über mehrere Netzwerkknoten zum Ziel, wobei dein Client das Default Gateway per DHCP erfahren kann. Mit Traceroute kannst du diesen Weg nachvollziehen, indem das Programm Pakete mit schrittweise erhöhtem TTL-Wert verschickt. Kapitelmarken [00:00:00] Einführung in das Thema Routing [00:00:32] Rückblick auf DNS und DHCP [00:01:47] Vom Browseraufruf zum Antwortpaket [00:02:43] Warum IPv4-Adressen knapp sind [00:03:38] Private IP-Adressen und ihre Erreichbarkeit [00:05:30] Die privaten IPv4-Adressbereiche [00:09:06] Der vollständige Bereich von 172.16 bis 172.31 [00:10:00] Das Heimnetz am Beispiel der FRITZ!Box [00:11:24] Öffentliche Absenderadresse durch NAT [00:14:37] Zwei IP-Adressen und Network Address Translation [00:16:39] Antworten mithilfe der NAT-Tabelle zuordnen [00:17:54] Einen Internetzugang mit mehreren Geräten teilen [00:19:19] Direkte Erreichbarkeit und Sicherheit [00:20:00] Routing zu Zielen außerhalb des eigenen Netzes [00:22:29] Default Gateway und Netzwerkknoten [00:24:32] Pakete über mehrere Router weiterleiten [00:26:28] Das Default Gateway per DHCP verteilen [00:27:30] Gateway und Router im ISO-OSI-Modell [00:29:59] Aufgaben der FRITZ!Box im Heimnetz [00:30:39] Traceroute und tracert [00:32:43] TTL begrenzt den Weg eines Pakets [00:36:08] Wie Traceroute die Zwischenstationen ermittelt [00:38:52] Warum sich Routen verändern können [00:39:29] Rückblick auf die Netzwerkgrundlagen [00:42:14] Bedeutung für Prüfung und Praxis [00:43:03] Routing bei IPv6 [00:43:21] Ausblick und Feedback Inhalt Private IP-Adressbereiche Da es im aktuellen Standard IPv4 nicht genug IP-Adressen für alle Teilnehmer auf der Welt gibt, muss eine Möglichkeit geschaffen werden, IP-Adressen abgeschlossen vom Internet zu vergeben, um interne Netzwerke betreiben zu können. Es gibt einige fest definierte IP-Adressbereiche, die im Internet nicht verfügbar sind: die privaten IP-Adressbereiche 10.0.0.0, 172.16.0.0 (bzw. genauer 172.16.0.0 bis 172.31.255.255) und 192.168.0.0. Aber wenn sie im Internet nicht verfügbar sind, wie kommt man dann ins Netz? Routing und NAT Es wird ein Gerät benötigt, dass zwischen das private und das öffentliche Netz geschaltet wird: ein Router. Der "übersetzt" quasi zwischen Intra- und Internet. Private IP-Adressen sind im Internet nicht auffindbar (sie werden nicht "geroutet"). Daher ersetzt der Router auf dem Hinweg die private Quell-IP-Adresse des Clients durch seine eigene öffentliche IP-Adresse des Internetanschlusses (z.B. per DSL oder Kabel). An diese kann der Webserver die Antwort auf die Anfrage dann zurückschicken. Wenn dann später die Antwort des Webservers im Router eintrifft, muss dieser die Ziel-IP-Adresse des Pakets wieder auf die private IP-Adresse des Clients setzen und das Paket an diesen weiterleiten. Dafür muss sich der Router "merken", welcher Client welche Anfrage an welchen Server gestellt hat, damit er die Antworten passend zuordnen kann. Dieses Prinzip heißt NAT (Network Address Translation) und ermöglicht mehreren Clients mit verschiedenen privaten IP-Adressen über einem gemeinsamen Router mit einer einzigen öffentlichen IP-Adresse ins Internet zu gelangen. Auch der Router hat meist keine direkte Verbindung zum Zielserver, sondern muss die Pakete auf eine "Reise" durch das Netzwerk schicken, bis es (ggfs. über mehrere weitere Router hinweg) beim Ziel ankommt. Aber woher weiß der Router, an welchen anderen Router er das Paket ggfs. schicken muss? Das Default Gateway ist der "nächste Knoten" im Netzwerk auf dem Weg zur Zieladresse. Dieser wird immer angesprungen, wenn der Zielknoten nicht direkt erreichbar ist. Diese Übersetzung kann man beliebig fortführen. Ein Client muss dazu nur die Adresse seines Routers kennen, der dann wiederum einen Router kennt, der dann das weitere Routing übernimmt usw. Irgendwann landet das Paket bei einem Knoten, der direkt mit dem Ziel kommunizieren kann, und es wird zugestellt. In unserem Heimnetzwerk übernimmt die Fritzbox übrigens mehrere Rollen gleichzeitig: DHCP- und DNS-Server sowie Router und Default Gateway. Gateways müssen nicht immer Router sein, aber de facto sind sie es heute so gut wie immer, da die historische Aufgabe, Netzwerke unterschiedlicher Technologien (z.B. IP und IPX/SPX) miteinander zu verbinden, durch den flächendeckenden Einsatz von IP nicht mehr benötigt wird. Mit dem Kommandozeilentool tracert (oder traceroute unter Linux) kann man den Weg zum Ziel über alle Knoten dazwischen verfolgen. Dazu wird der TTL-Eintrag (Time to live) des IP-Pakets genutzt, den jeder Knoten automatisch herunterzählt. Bei 0 angekommen wird das Paket verworfen. Dabei wird aber eine Info an den Sender mit der Adresse des verwerfenden Knotens geschickt. tracert verschickt nun der Reihe nach Pakete mit TTL 1, 2, 3, 4 usw. und gibt die Adressen der verwerfenden Knoten aus. Literaturempfehlungen Im guten alten IT-Handbuch für Fachinformatiker* werden in Kapitel 4 Netzwerkgrundlagen die meisten hier genannten Inhalte ausführlich erläutert. In meinem Buchclub gehe ich auf die Inhalte auch noch einmal im Detail ein. * Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Private IP-Adresse Router Gateway (Informatik) Netzwerkadressübersetzung Time to Live Zusammenfassung Vom Browser ins Internet Wenn ich eine Adresse im Browser eingebe, liefert DNS die zugehörige IP-Adresse. Mein Client erhält seine eigene IP-Adresse per DHCP, das auch weitere Netzwerkeinstellungen verteilt. Zu Hause übernimmt meine FRITZ!Box diese Aufgaben. Damit eine Webseite im Browser erscheint, müssen die Antworten des Zielservers wieder bei meinem Client ankommen. Dabei spielt die Absenderadresse eine Rolle: Der Server schickt seine Antwort an die IP-Adresse, von der die Anfrage stammt. Private IPv4-Adressen IPv4-Adressen sind 32 Bit lang. Daraus ergeben sich etwas mehr als vier Milliarden mögliche Adressen, die für alle Geräte weltweit mit jeweils eigener öffentlicher Adresse zu knapp sind. In einem privaten Netzwerk kannst du Adressen aus reservierten Bereichen vergeben. Diese werden im öffentlichen Internet nicht weitergeleitet. Weil getrennte Heimnetze oder Firmennetze dieselben privaten Adressen vergeben können, lässt sich daraus kein weltweit eindeutiges Ziel ableiten. Diese Bereiche solltest du für die Praxis und deine Prüfung kennen: 10.0.0.0 bis 10.255.255.255: Die letzten drei Oktette umfassen 24 Bit und damit ungefähr 16 Millionen Adressen. 172.16.0.0 bis 172.31.255.255: Auch ein Teil des zweiten Oktetts gehört zum verfügbaren Bereich. 192.168.0.0 bis 192.168.255.255: Die letzten beiden Oktette umfassen 16 Bit und damit ungefähr 65.000 Adressen. Heimrouter verwenden häufig diesen Bereich. Bei meiner FRITZ!Box lautet die private Adresse beispielsweise 192.168.178.1. Ein Client kann per DHCP die Adresse 192.168.178.2 erhalten. Geräte im selben Netzwerksegment können direkt miteinander kommunizieren, etwa dein Computer mit einem Drucker im WLAN. NAT: Adressen für den Internetzugang übersetzen Damit mein Client Antworten aus dem Internet erhält, übernimmt die FRITZ!Box Network Address Translation, kurz NAT. Im beschriebenen Heimnetz besitzt sie dafür eine private Adresse für das lokale Netzwerk sowie eine öffentliche Adresse vom Internetanbieter. Eine Anfrage und ihre Antwort durchlaufen dabei folgende Schritte: Mein Client übergibt das Paket für den externen Zielserver an die FRITZ!Box. Bevor sie es ins Internet weiterleitet, ersetzt sie die private Absenderadresse durch ihre eigene öffentliche IP-Adresse. In einer internen Tabelle hält sie fest, welchem Client die Anfrage zugeordnet ist. Der Zielserver schickt seine Antwort an die öffentliche Adresse der FRITZ!Box. Anhand ihrer Tabelle ermittelt die FRITZ!Box den passenden Client, trägt dessen private Adresse als Ziel ein und leitet die Antwort ins Heimnetz weiter. Der externe Server sieht dabei die öffentliche Adresse der FRITZ!Box. Die ursprüngliche private Absenderadresse wurde im Paket überschrieben. Wenn mehrere Geräte gleichzeitig auf denselben Dienst zugreifen, muss die FRITZ!Box jede Antwort dem richtigen Gerät zuordnen. So können viele Clients einen Internetzugang mit einer öffentlichen IPv4-Adresse teilen. Das verringert den Bedarf an öffentlichen Adressen. Durch ihre privaten Adressen sind die internen Geräte aus dem öffentlichen Internet heraus nicht direkt erreichbar. Ein Zugriff auf die öffentliche Adresse erreicht zunächst die FRITZ!Box, deren mögliche Sicherheitsfehler weiterhin eine Rolle spielen. Routing und Default Gateway Liegt die Zieladresse außerhalb des eigenen Netzwerksegments, übergibt mein Client das Paket an einen Router. Im Heimnetz übernimmt die FRITZ!Box diese Rolle als Default Gateway, also als nächster Knoten für solche Pakete. Die FRITZ!Box leitet das Paket zum nächsten Router beim Internetanbieter weiter. Über weitere Knoten gelangt es schließlich zum Zielserver. Das Internet lässt sich dabei als Graph vorstellen, dessen Netzwerkgeräte über Verbindungen miteinander verknüpft sind. Dein Client kann die Adresse des Default Gateways per DHCP erhalten. Sobald diese Einstellung vorliegt, weiß er, an welchen Router er Pakete für Ziele außerhalb seines eigenen Netzwerks übergeben soll. Gateway und Router Für die IHK-Prüfung solltest du die Begriffe genauer auseinanderhalten können: Ein Gateway kann zwischen unterschiedlichen Netzwerken beziehungsweise Protokollen übersetzen und auf verschiedenen Schichten des ISO-OSI-Modells arbeiten. Ein Router arbeitet auf OSI-Schicht 3, auf der auch IP angesiedelt ist. ...
1 Stunde 8 Minuten
Meine Erkenntnisse (positiv wie negativ) aus der IHK-Sommerprüfung 2019 teile ich mit euch in der einhundertneununddreißigsten Episode des Anwendungsentwickler-Podcasts. TL;DR Aus meiner Arbeit als Prüfer bei der IHK-Sommerprüfung 2019 gebe ich dir Hinweise für deine Prüfung als Fachinformatiker:in Anwendungsentwicklung. Deine Projektdokumentation braucht nachvollziehbare Entscheidungen und Belege für deine Arbeit, wobei du Vorlagen an dein Projekt anpasst und alle Tätigkeiten sowie Kosten berücksichtigst. Für die Präsentation zählen gut lesbare Folien und der Fokus auf deine eigene Leistung; im Fachgespräch musst du deinen Code und die erwähnten Fachbegriffe erklären können. Zu den gelungenen Beispielen gehören verknüpfte Anforderungen und nachgemessene Zeitersparnisse. Kapitelmarken [00:00:01] Hinweise zum Fachgespräch [00:00:20] Rückblick auf die IHK-Sommerprüfung 2019 [00:02:36] Persönliche Einschätzung und unterschiedliche Prüfungsausschüsse [00:03:42] Natürlich und verständlich schreiben [00:05:00] Dokumentationsvorlagen an das eigene Projekt anpassen [00:08:05] Fehlende Inhalte und Dokumentationen nachweisen [00:10:11] Hinweise aus dem Projektantrag berücksichtigen [00:11:28] Qualität sichern und Tests dokumentieren [00:13:20] Bewertungsbögen und individuelle Noten [00:13:57] Aussagen zur Qualität mit dem Code belegen [00:17:36] Debugging und Softwaretests [00:18:36] Projektkosten und Amortisation berechnen [00:20:02] Laufende Kosten berücksichtigen [00:21:10] Die Perspektive bei der Amortisation wählen [00:22:26] Fehlende Kosten und ungeeignete Schätzgrundlagen [00:24:04] ER-Modelle und Use-Case-Diagramme korrekt erstellen [00:26:44] Alle Tätigkeiten in der Projektzeit einplanen [00:28:14] Aussagekräftige Inhalte für Text und Anhang auswählen [00:31:27] Diagramme mit fachlichem Zweck einsetzen [00:33:00] Artefakte einordnen und lesbaren Code zeigen [00:34:58] Umfang und Gliederung angemessen halten [00:40:54] Abkürzungen, Seitenzahlen und Quellen [00:43:30] Passwörter sicher behandeln und MVC verstehen [00:45:31] Projektpräsentation verständlich gestalten [00:48:05] Unternehmen knapp vorstellen und den eigenen Namen zeigen [00:49:42] Zeitplanung im Vortrag erläutern [00:50:10] Schriftliche Prüfung und Gesamtnote [00:51:03] Wirtschaftliche Grundlagen im Fachgespräch [00:52:01] Den eigenen Code und Sprachmerkmale erklären [00:54:29] Architekturbegriffe und Dependency Injection [00:55:27] Urheberrecht als Thema im Fachgespräch [00:56:21] Datenschutz und verwandte Begriffe [00:57:43] Die eigene Dokumentation vor der Prüfung kennen [00:58:21] Meine Hinweise und der Umgang mit Prüflingen [00:59:46] Gelungene Anforderungen und handgezeichnete Mockups [01:01:06] Anforderungen durch Tickets belegen [01:02:10] Browser-Tabs als Präsentationsidee [01:02:58] Mockup und fertige Oberfläche zeigen [01:03:24] Das Vorgehensmodell begründen [01:04:05] Den Prüfungsort in Beispielen aufgreifen [01:04:52] Zeitersparnisse nachmessen und Amortisation prüfen [01:06:06] Weitere Eindrücke und Anregungen für deine Prüfung [01:07:49] Fragen und Feedback zur Episode Inhalt Projektdokumentation Verwendung unnatürlicher Sprache ("bei dem" statt "beim", "Leerung der Datenbank" statt "Datenbank leeren") Kapitel meiner Vorlage werden ausgefüllt, auch wenn die Inhalte überhaupt nicht sinnvoll sind "Eine Nutzwertanalyse war nicht sinnvoll, deswegen habe ich darauf verzichtet." Identische Inhalte werden gleich mehrfach wiederholt (u.a. aus dem Antrag übernommen), z.B. bei der Projektbegründung und Zieldefinition Wichtige Inhalte fehlen insgesamt viel zu wenig Text (8 Seiten statt 15) Benutzer-/Entwickler-Dokumentation (gibt direkt >10% Abzug), und nein, ein PHP-Doc-Block ohne Inhalt reicht nicht aus trotz explizitem Hinweis der Prüfer im Antrag wurden keine Diagramme erstellt, weil diese "nicht sinnvoll" waren Qualitätssicherung fehlt häufig komplett (abgesehen vom scheinbar obligatorischen "Code-Review") Qualitätssicherung "Die Methoden wurden auf Komplexität geprüft" (sind im Anhang aber >70 Zeilen lang) "Viel Wert auf Clean Code gelegt" (aber doppelter Code, Magic Numbers, harte Pfade, komplexe switches im Anhang) "Die Übertragung muss verschlüsselt erfolgen" (aber alle URLs beginnen mit http) "Code Coverage muss >90% sein" (aber nicht einen Test gezeigt) Debugger/Konsole wird für "Tests" genutzt Fehler in der Wirtschaftlichkeits-/Amortisationsrechnung "Pauschale" für Ressourcennutzung angesetzt, wird aber nicht mit eingerechnet laufende Kosten des Projekts gibt es nicht Kosten des Unternehmens werden Einsparungen des Kunden gegenübergestellt bei der Kostenplanung werden große Kostenverursacher "vergessen" Vergleich mit fiktiven Kosten von einer Website, die Kosten für Apps schätzt Fehler in Diagrammen ERM enthält m:n-Tabellen include vs. extends im Use-Case-Diagramm Aktionen werden nicht in der Zeitplanung berücksichtigt (4h Schulung) Uninteressante Inhalte werden viel zu detailliert dargestellt langweiliger Sourcecode über mehrere Seiten im Anhang, 8 (!) Seiten Mockups und 6 Seiten Quelltext im Anhang Hardware des Arbeitsplatzrechners bis runter auf die RAM-Art und Typ der Grafikkarte erklärt Zeitplanung/Projektaufbau in drei verschiedenen Varianten dargestellt (Gantt, Tabelle, Projektstrukturplan) lächerlich einfache Abläufe mit Diagrammen dargestellt (Sequenzdiagramm mit einmal hin und zurück, Aktivitätsdiagramm mit einer einzigen Verzweigung) teils völlig sinnlose und nicht im Zusammenhang zum Inhalt stehende Komponenten (z.B. Auszug aus pom.xml ohne Erläuterung) minified (!) CSS/JavaScript wird gezeigt Overkill Kostenkalkulation über 3 Seiten mit zig mathematischen Formeln mit Indizes (z.B. KKunde + Kfix) etc. komplette Seite für typographische Konventionen 5 (!) Überschriftenebenen (z.B. "3.1.1.4. a)") Diagramm der Amortisationsrechnung mit mathematischer Software geplottet "wissenschaftliche" Erklärung von Vorgehensmodellen mit Quellennachweis und wörtlichen Zitaten über mehrere Zeilen, aber aus der Wikipedia nervige Kleinigkeiten Abkürzungsverzeichnis nicht sortiert Seitennummerierung fehlerhaft Quellennachweise, die lediglich Links enthalten ohne Bezug zu irgendeinem Inhalt handwerkliche Fehler Passwörter im Klartext in der Applikation speichern oder sogar übers Netzwerk schicken Geschäftslogik im Controller Projektpräsentation viele Frameworks verwendet, aber nur die (nichtssagenden) Logos gezeigt Codebeispiele enthalten TODOs und Hinweise der IDE Rechtschreibfehler auf den Folien winziger Text Grafiken überlagern Textelemente Cliparts verwendet Unternehmen zu lang vorgestellt eigenen Namen nicht genannt und nicht gezeigt Tabelle mit Zeitplanung zeilenweise vorgelesen Fachgespräch GA1 hat viele gute Prüflinge stark runtergezogen Wirtschaftsfragen gehen gar nicht (Stundensatz, Gehaltsabrechnung, brutto/netto, Einzel-/Gemeinkosten, BAB) Sourcecodebestandteile können nicht erläutert werden Nullable Types, Structs, Lambdas, Generics, Typinferenz, Traits, Typisierung der verwendeten Sprache, Type Hints in PHP ===, ??, static, finally, out-/ref-Parameter Architekturen können nicht erläutert werden MVC, Dependency Injection, Domain Driven Design Rechtsform des eigenen Unternehmens kann nicht erläutert werden Urheberrechtshinweis auf eigenem Deckblatt kann nicht erläutert werden Datenschutz vs. Datensicherung vs. Datensicherheit können nicht abgegrenzt werden "Habe ich das so geschrieben?" (Prüfling kennt die eigene Doku nicht) Lichtblicke Zusammenhang zwischen Lasten- und Pflichtenheft hergestellt (baut aufeinander auf) Mockups auf Papier selbst gezeichnet Tickets statt (fiktivem) Lastenheft verwendet Präsentation einer Webanwendung wie Browser-Tabs gestaltet direkter Vergleich des entworfenen Mockups mit der finalen Oberfläche der Webanwendung Entscheidung für ein Vorgehensmodell sauber begründet (Wasserfall, da Anforderungen feststehen) Inhalte der Präsentation auf Prüfungsausschuss individualisiert (als Adresse auf einem Aufkleber die der BBS verwendet) Amortisationsrechnung im Nachhinein durch Vergleich der Planung mit den echten Zeitersparnissen validiert Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Zusammenfassung Meine Erfahrungen aus der Sommerprüfung 2019 Als Prüfer habe ich bei der IHK-Sommerprüfung 2019 Projektdokumentationen gelesen und mündliche Prüfungen begleitet. Daraus nehme ich Beispiele mit, die dir als IT-Azubi bei deiner eigenen Prüfung helfen. Meine Hinweise geben meine persönliche Einschätzung wieder; je nach IHK und Prüfungsausschuss können andere Erwartungen gelten. Die genannten Vorgaben von 15 Seiten Text und 70 Stunden Projektzeit beziehen sich auf den damaligen Prüfungskontext in Oldenburg. Deine Projektdokumentation schreiben Verständlich formulieren und Vorlagen anpassen Schreibe in natürlicher Sprache, die sich leicht lesen lässt. Wörter wie "beim" passen auch in eine Projektdokumentation. Mit aktiven Verben kannst du beschreiben, was du gemacht hast. Meine kostenlose LaTeX-Vorlage auf GitHub hilft dir beim Formatieren. Ihre Beispielkapitel geben dir Anregungen, aus denen du eine passende Struktur für dein Projekt entwickelst. Passe die Reihenfolge der Kapitel an deinen tatsächlichen Ablauf an. Ein Kapitel zur Nutzwertanalyse gehört hinein, wenn du diese Methode im Projekt eingesetzt hast und etwas dazu zeigen kannst. Beschreibe deine Entscheidungen mit ihren Gründen. Wenn mehrere Kapitel nahezu denselben Text enthalten, geht Platz für fachliche Inhalte verloren. Deine Arbeit mit Belegen zeigen Dokumentiere die Methoden, mit denen du dein Projekt geplant und umgesetzt hast. Dazu können UML-Diagramme oder eine EPK gehören, sofern sie zum Projekt passen. Zeige im Anhang, wie du für Anwender:innen und Entwickler:innen dokumentiert hast. Geeignet sind etwa Auszüge aus einer Anleitung oder Screenshots einer mit JavaDoc erzeugten Dokumentation. Ein ausgefüllter Dokumentationsblock mit brauchbaren Informationen
41 Minuten
Um zwei zentrale Technologien der Netzwerkgrundlagen - DNS und DHCP - geht es in der einhundertachtunddreißigsten Episode des Anwendungsentwickler-Podcasts. TL;DR Wenn ich eine Website über ihren Domainnamen aufrufe, liefert DNS (Domain Name System) die passende IP-Adresse. DHCP (Dynamic Host Configuration Protocol) gibt deinem Gerät beim Verbinden mit einem Netzwerk automatisch eine IP-Adresse und weitere Einstellungen, darunter den DNS-Server. Du erfährst, wie DNS-Anfragen über mehrere Server beantwortet werden, welche Folgen zwischengespeicherte Antworten haben und wie du mit nslookup und ipconfig deine Netzwerkeinstellungen prüfst. Für deine Prüfung als Fachinformatiker:in gehören beide Technologien zum Grundlagenwissen; die hier behandelten Inhalte bieten dir einen Einstieg. Kapitelmarken [00:00:01] Einstieg in DNS und DHCP [00:01:05] DNS und das Telefonbuchprinzip [00:03:40] Aufbau und Speicherort der hosts-Datei [00:05:28] Websites lokal mit der hosts-Datei testen [00:06:53] Manipulierte hosts-Dateien als Angriffsweg [00:08:35] Grenzen einer weltweit gepflegten hosts-Datei [00:11:06] Namen über DNS-Server auflösen [00:11:58] DNS-Kaskade und Root-Server [00:13:39] DNS-Caching und Ablaufzeiten [00:16:06] Serverumzüge und alte DNS-Antworten [00:17:33] DNS-basierte Websperren [00:19:05] DNS-Anfragen mit nslookup testen [00:20:18] A- und PTR-Einträge sowie Forward und Reverse Lookup [00:22:58] MX-Einträge für Mailserver [00:24:49] Wie dein Gerät seinen DNS-Server findet [00:26:31] Netzwerkeinstellungen automatisch per DHCP erhalten [00:28:27] Eigene IP-Adresse und eindeutige Vergabe [00:30:12] DHCP und DNS im Internetrouter [00:31:55] Weitere Einstellungen über DHCP verteilen [00:33:51] Netzwerkeinstellungen mit ipconfig prüfen [00:34:37] DHCP-Lease und Adressen erneut vergeben [00:35:21] ipconfig renew und release [00:36:06] Ablauf vom Netzwerkbeitritt bis zur Website [00:38:11] DNS und DHCP als Prüfungsgrundlagen [00:40:06] Literatur zum Einstieg und zum Vertiefen Inhalt DNS Theoretisch können wir auch im Internet surfen, indem wir die IP-Adressen der Websites eingeben, aber das kann sich kein Mensch merken. Daher sind Websites über einen sprechenden Namen, die Domain, erreichbar. Dafür brauchen wir dann aber eine Übersetzung von Domainname in IP-Adresse, damit der Computer kommunizieren kann. Einfachste Möglichkeit: Datei mit Übersetzung von IP in Domain (gibt es tatsächlich: hosts unter Windows z.B. unter C:\Windows\System32\drivers\etc, die Paare aus IP-Adressen und Hostnamen enthält). Dann müsste aber jeder Computer die gesamte Liste aller verfügbaren Domains kennen. Das ist nicht machbar. # Copyright (c) 1993-2009 Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. # # This file contains the mappings of IP addresses to host names. Each # entry should be kept on an individual line. The IP address should # be placed in the first column followed by the corresponding host name. # The IP address and the host name should be separated by at least one # space. # # Additionally, comments (such as these) may be inserted on individual # lines or following the machine name denoted by a '#' symbol. # # For example: # # 102.54.94.97 rhino.acme.com # source server # 38.25.63.10 x.acme.com # x client host # localhost name resolution is handled within DNS itself. # 127.0.0.1 localhost # ::1 localhost 136.243.146.110 macke.it Die Lösung ist DNS (Domain Name System), ein "Telefonbuch" für Websites/IP-Adressen, das auf viele Server verteilt ist. Mit dem Kommandozeilentool nslookup können DNS-Server abgefragt werden. DNS kann kaskadiert werden. Wenn ein Server nicht weiter weiß, fragt er den übergeordneten Server und speichert (cacht) ggfs. das Resultat für die nächste Anfrage. Die letzte Instanz der Kaskade sind die sog. Root-Server. Die sogenannten Websperren gegen "verbotene" Websites funktionieren im Prinzip so, dass einzelne "Telefonbücher" (z.B. die der deutschen Internetprovider) gesäubert werden. Aber man kann sie einfach umgehen, indem man bewusst einen anderen DNS-Server verwendet, der z.B. in einem anderen Land steht. DHCP Zurück zu unserem Aufruf: Der Client ruft eine Adresse im Browser auf und der Server liefert ihm HTML zurück. Aber dazu braucht der Client auch eine IP-Adresse. Die Zieladresse ist dank DNS bekannt, aber man braucht auch eine Quelladresse für den Client. Die kann man selbst vergeben, aber das wird bei mehreren PCs immer schwieriger, da sie eindeutig sein müssen (sonst weiß das Netzwerkpaket der Antwort nicht, wo es hin muss). Die Lösung heißt DHCP (Dynamic Host Configuration Protocol). Das ist ein Dienst, den ein Server (zuhause z.B. die FRITZ!Box*) bereitstellt, der sich dann z.B. die Liste der bereits verwendeten IP-Adressen merkt und keine doppelt vergibt. Außerdem kann man viele weitere Einstellungen (wie z.B. den zu nutzenden DNS-Server) per DHCP an die Clients verteilen. Literaturempfehlungen Im guten alten IT-Handbuch für Fachinformatiker* werden in Kapitel 4 Netzwerkgrundlagen auch DNS und DHCP erläutert. In meinem Buchclub gehe ich auf die Inhalte auch noch einmal im Detail ein. * Für die Prüfungsvorbereitung musst du aber dein Wissen noch vertiefen! Literaturempfehlungen zur Netzwerktechnik evaluiere ich aktuell und reiche sie später nach. Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Domain Name System Root-Nameserver Dynamic Host Configuration Protocol Zusammenfassung DNS: Vom Domainnamen zur IP-Adresse Wenn ich im Browser einen Domainnamen wie google.de eingebe, braucht mein Computer die zugehörige IP-Adresse, um den Server zu erreichen. Das Domain Name System (DNS) stellt diese Verbindung zwischen Namen und Adressen her. Als Bild dafür verwende ich ein Telefonbuch, in dem du zu einem bekannten Namen die passende Nummer nachschlägst. Beim Aufrufen einer Website fragt dein Gerät den konfigurierten DNS-Server nach der IP-Adresse des Domainnamens. Mit der Antwort kann es eine Verbindung zum Zielserver herstellen. Die lokale hosts-Datei Auf deinem Rechner lassen sich Namen und IP-Adressen in der Datei hosts eintragen. Unter Linux liegt sie unter /etc/hosts, unter Windows unter C:\Windows\System32\drivers\etc\hosts. Die Datei hat keine Endung und lässt sich mit einem Texteditor bearbeiten. Jede Zuordnung beginnt mit der IP-Adresse, rechts daneben steht der Name. Zu einer Adresse können mehrere Namen gehören. Für meine Arbeit an einer Website kann ich dort deren Domainnamen auf die IP-Adresse meines lokalen Rechners zeigen lassen. Wenn auf diesem Rechner ein Webserver läuft, erreiche ich die Testversion über den gewohnten Domainnamen. Die öffentlich erreichbare Website bleibt dabei unverändert. Einträge in der hosts-Datei werden bei der Namensauflösung bevorzugt berücksichtigt. Schadprogramme können diese Datei verändern und bekannte Domains auf fremde Server umleiten. Du landest dann etwa auf einer nachgebauten Website, obwohl du den vertrauten Namen eingegeben hast. Auch Websites für Antivirensoftware können auf diese Weise umgeleitet werden, sodass du beim vermeintlichen Download weitere Schadsoftware erhältst. Eine weltweite Liste aller Domains auf jedem einzelnen Rechner würde viel Speicher beanspruchen und müsste laufend gepflegt werden. Neue Domains und geänderte Adressen machen dafür ein verteiltes System erforderlich. DNS-Server und zwischengespeicherte Antworten Kennt der angefragte DNS-Server einen Namen noch nicht, wird die Anfrage über weitere DNS-Server beantwortet. Diese im Podcast als Kaskade beschriebene Folge kann bis zu den Root-Servern reichen. Die beteiligten DNS-Server speichern erhaltene Antworten zwischen. Durch dieses Caching können sie spätere Anfragen schneller beantworten, während weniger weitere Anfragen anfallen. Für gespeicherte Antworten gilt eine einstellbare Ablaufzeit. Als übliche Größenordnung nenne ich 24 bis 48 Stunden. Innerhalb dieser Frist kann der DNS-Server die gespeicherte Adresse zurückgeben; nach Ablauf fragt er erneut nach. Ändert sich zwischenzeitlich die IP-Adresse einer Domain, können deshalb vorübergehend noch alte Antworten ausgegeben werden. Bei meinen Serverumzügen lasse ich den bisherigen Server mindestens drei Tage weiterlaufen. So bleibt die Website auch für Zugriffe erreichbar, die noch zur alten IP-Adresse führen. Während dieser Übergangszeit können zusätzlich Fragen entstehen, etwa wenn auf dem alten Server neue Inhalte angelegt werden, die auf dem neuen fehlen. DNS-Sperren und nslookup Wird ein Domainname aus einem DNS-Server entfernt oder dort gesperrt, bleibt der dahinterliegende Server über seine Adresse erreichbar. Wer die IP-Adresse kennt oder einen anderen DNS-Server abfragt, kann die Website weiterhin erreichen. Eine DNS-Sperre greift damit beim Nachschlagen des Namens. Mit nslookup kannst du in der Kommandozeile selbst eine Domain abfragen und dir die zurückgelieferte IP-Adresse ansehen. Das Werkzeug erlaubt außerdem, einen anderen DNS-Server auszuwählen. Zum Testen verwende ich beispielsweise den Google-DNS-Server mit der Adresse 8.8.8.8. Eintragstypen im DNS In der DNS-Datenbank stehen verschiedene Arten von Einträgen: A: Ordnet einem Domainnamen eine IP-Adresse zu. Das gehört zum Forward Lookup, also zum Nachschlagen vom Namen zur Adresse. PTR: Ordnet einer IP-Adresse einen Namen zu. Dafür gibt es eigene Einträge in der Reverse-Lookup-Zone. MX (Mail Exchange): Gibt an, welche Mailserver für eine Domain zuständig sind. Mehrere Mailserver können mit Prioritäten hinterlegt werden, damit bei einem Ausfall ein weiterer Server angesprochen werden kann. Wenn mehrere Domains auf dieselbe IP-Adresse zeigen, kann eine Rückwärtsabfrage einen anderen Namen liefern als den ursprünglich abgefragten. Für PTR-Einträge wird eine eigene Zuordnung gepflegt. Der Mailserver einer Domain kann auf einem anderen Server laufen als ihre Website....
43 Minuten
Um den Aufbau und die Darstellung von IP-Adressen geht es in der einhundertsiebenunddreißigsten Episode des Anwendungsentwickler-Podcasts. TL;DR An IP-Adressen zeige ich dir, wie Computer ihre Ziele im Netzwerk adressieren und wie du die zugehörigen Zahlen lesen kannst. IPv4-Adressen bestehen aus 32 Bit, die als vier durch Punkte getrennte Dezimalzahlen erscheinen; IPv6-Adressen haben 128 Bit und werden hexadezimal mit Doppelpunkten geschrieben. Mit Zweierpotenzen und den Stellenwerten der Zahlensysteme kannst du Binärzahlen ins Dezimalsystem umrechnen, was du als IT-Azubi auch für die IHK-Prüfung brauchst. Kapitelmarken [00:00:00] Einführung: Aufbau und Darstellung von IP-Adressen [00:00:32] Von der URL zur technischen Adresse [00:02:56] Internet Protocol und seine Versionen [00:03:37] IP-Adressen am Beispiel eines Postpakets [00:06:18] IPv4: 32 Bit und mögliche Kombinationen [00:08:43] Zweierpotenzen für Ausbildung und Praxis [00:10:11] Bitlängen bei Farben, MAC-Adressen und CPUs [00:13:50] IPv6 und der größere Adressraum [00:15:00] IPv4 in vier Dezimalzahlen schreiben [00:17:36] Grundlagen der Stellenwertsysteme [00:20:08] Binärzahlen ins Dezimalsystem umrechnen [00:23:55] Oktette und die Schreibweise von IPv4 [00:26:52] IPv4 als Schwerpunkt der Netzwerkreihe [00:27:23] IPv6 und das Hexadezimalsystem [00:31:38] Hexadezimale Stellenwerte mit Zweierpotenzen berechnen [00:34:20] Vier Bit durch ein Hexadezimalzeichen darstellen [00:36:17] IPv6-Adressen mit Doppelpunkten verkürzen [00:38:48] IPv6: acht Blöcke mit jeweils vier Zeichen [00:39:32] Lernziele für IT-Azubis und Ausblick [00:41:42] Feedback und Shownotes Inhalt IP-Adresse URLs sind für Menschen einigermaßen gut zu verstehen und zu merken, aber Computer kommunizieren leider nicht über URLs, sondern über IP-Adressen. Eine IP-Adresse ist eine 32 Stellen lange Folge von Nullen und Einsen. Das Bit ist die kleinste Informationseinheit der Informatik und kann genau diese beiden Werte annehmen. Also ist eine IP-Adresse 32 Bit lang. Da sich wenige Menschen 32 Stellen lange Zahlen merken können, gibt es eine bessere Schreibweise für IP-Adressen: man spaltet die 32 Bit in 4 x 8 Bit auf und wandelt diese Teile jeweils um in eine Dezimalzahl. Das funktioniert ganz einfach: Jede Stelle einer Binär- bzw. Dualzahl steht von rechts ausgehend für ein Vielfaches von 2. Die Summe der entsprechenden Stellen der Binärzahl malgenommen mit dem Wert der ihnen zugeordneten Zweierpotenzen ergibt die Dezimalzahl. Die minimale Dezimalzahl für eine Stelle der IP-Adresse ist 0. Die maximale Dezimalzahl für eine Stelle der IP-Adresse ist 255. 10101000 (Basis 2) = 168 (Basis 10) 10101000 = 1 * 2^8 + 0 * 2^7 + 1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 0 * 2^3 + 0 * 2^2 + 0 * 2^1 = 128 + 32 + 8 = 168 Literaturempfehlungen Im guten alten IT-Handbuch für Fachinformatiker* werden in Kapitel 4 Netzwerkgrundlagen die meisten hier genannten Inhalte ausführlich erläutert. In meinem Buchclub gehe ich auf die Inhalte auch noch einmal im Detail ein. * Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts IP-Adresse IPv6 Zusammenfassung Wozu Computer IP-Adressen brauchen Wenn du eine Website aufrufst, kannst du dir einen Domainnamen wie google.com merken. Für die Kommunikation mit dem entfernten Computer braucht dein Rechner dessen IP-Adresse. IP steht für Internet Protocol. Ich vergleiche das mit einem Paket, auf dem die Zieladresse steht: Auf dem Weg zur gewünschten Person durchläuft es mehrere Zwischenstationen. Die Adresse gibt vor, wohin es geschickt werden soll. Auch Datenpakete brauchen eine eindeutige Zieladresse, damit sie beim vorgesehenen Computer ankommen. Für Geräte, die du über das Internet erreichen möchtest, muss diese Adresse weltweit eindeutig sein. IPv4: 32 Bit und rund vier Milliarden Möglichkeiten Eine IPv4-Adresse ist 32 Bit lang. Ein Bit ist die kleinste Informationseinheit in der Informatik und kann den Wert 0 oder 1 haben. Wie viele Kombinationen du mit einer bestimmten Zahl von Bits bilden kannst, berechnest du mit 2^n, wobei n für die Anzahl der Bits steht. Jedes zusätzliche Bit verdoppelt die Zahl der Möglichkeiten: Mit einem Bit kannst du zwei Werte darstellen. Zwei Bit ergeben vier Kombinationen: 00, 01, 10 und 11. Bei acht Bit kommst du auf 2^8 = 256 Möglichkeiten. Für 32 Bit ergeben sich ungefähr 4,2 Milliarden mögliche Adressen. Angesichts der weltweit vorhandenen elektronischen Geräte reicht dieser Adressraum für eine eigene Adresse pro Gerät nicht aus. Der Nachfolger IPv6 hat 128 Bit und bietet mit 2^128 einen erheblich größeren Adressraum. IPv4 bleibt für die Praxis und die IHK-Prüfung relevant. In Unternehmen ist es weiterhin verbreitet, während die Umstellung auf IPv6 lange dauert. Deshalb konzentriere ich mich in meiner Reihe zu Netzwerkgrundlagen zunächst auf IPv4. Zweierpotenzen für Ausbildung und Praxis Meinen IT-Azubis empfehle ich, die wichtigen Zweierpotenzen auswendig zu lernen. Wenn du etwa ein Netzwerk für 100 Clients planst, musst du einschätzen können, wie viele Adressen die gewählte Größe erlaubt. Von 2^1 bis 2^10 lauten die Werte: 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 Weitere Bitlängen begegnen dir an verschiedenen Stellen: 16 Bit: 2^16 = 65.536 Möglichkeiten. 24 Bit: ungefähr 16 Millionen Möglichkeiten, etwa bei der Farbtiefe eines JPEG-Bildes. Die RGB-Farbkanäle erhalten jeweils acht Bit und damit 256 Abstufungen pro Kanal. 48 Bit: die Länge einer MAC-Adresse, die ein Hardwaregerät identifiziert. 64 Bit: eine übliche Wortbreite heutiger CPUs. Wie du IPv4-Adressen liest Für die lesbare Schreibweise teilst du die 32 Bit in vier Gruppen mit jeweils acht Bit. Jede Gruppe heißt Oktett und umfasst 256 mögliche Werte. Du rechnest die Gruppen einzeln in Dezimalzahlen um und trennst sie durch Punkte. Ein Beispiel ist 192.168.178.1, eine übliche Adresse einer neu eingerichteten Fritzbox. Diese Schreibweise erleichtert dir das Lesen und Eintragen einer Adresse, etwa in einer Konfigurationsdatei. In den Datenpaketen steht die Adresse als Bitfolge. Binärzahlen ins Dezimalsystem umrechnen Bei einem Stellenwertsystem bestimmt die Basis, welchen Wert jede Stelle hat. Du beginnst rechts mit dem Exponenten null und erhöhst ihn mit jeder Stelle nach links. Im Dezimalsystem mit Basis 10 haben die Stellen die Werte 1, 10, 100, …. Die Zahl 123 kannst du deshalb so ausrechnen: 1 × 100 + 2 × 10 + 3 × 1 = 123 Für das Binärsystem, auch Dualsystem genannt, gilt die Basis 2. Von rechts nach links ergeben sich die Stellenwerte 1, 2, 4, 8, 16, 32, 64, 128, …. Du multiplizierst jede Ziffer mit ihrem Stellenwert und addierst die Ergebnisse. Da die Ziffern entweder null oder eins sind, addierst du die Stellenwerte, an denen eine eins steht: 101 ergibt 4 + 1 = 5. 1101 ergibt 8 + 4 + 1 = 13. 10101000 ergibt 128 + 32 + 8 = 168. Damit kannst du jedes Oktett einer IPv4-Adresse ins Dezimalsystem umrechnen. Die umgekehrte Richtung wird in dieser Einführung noch nicht behandelt. Hexadezimalzahlen und IPv6 Das Hexadezimalsystem hat die Basis 16. Seine Zeichen sind 0 bis 9 sowie A bis F. Nach F folgt beim Weiterzählen 10. Die Stellenwerte lauten von rechts nach links 1, 16, 256, …; die hexadezimale Zahl 100 entspricht daher dem Dezimalwert 256. Mit vier Bit kannst du 16 Werte darstellen. Ein Hexadezimalzeichen steht somit für vier Bit, beispielsweise 0 für 0000 und F für 1111. Eine vollständig ausgeschriebene IPv6-Adresse umfasst 32 Hexadezimalzeichen, aufgeteilt in acht Blöcke mit jeweils vier Zeichen. Zwischen den Blöcken stehen Doppelpunkte. Zusammenhängende Blöcke, die vollständig aus Nullen bestehen, lassen sich durch :: verkürzt schreiben. Beim Lesen ergänzt du dort so viele Nullblöcke, bis die vollständige Länge von 128 Bit erreicht ist. Der Informationsgehalt bleibt erhalten, und über das Netzwerk werden weiterhin dieselben Bits übertragen. Als weiteres Zahlensystem begegnet dir das Oktalsystem mit Basis 8, beispielsweise bei Linux-Dateirechten. Was du für die Ausbildung brauchst Als angehende:r Fachinformatiker:in Anwendungsentwicklung brauchst du diese Grundlagen ebenfalls. Für spätere Subnetting-Aufgaben arbeitest du mit den einzelnen Bitmustern. Dazu gehören Zweierpotenzen und das Umrechnen zwischen Zahlensystemen ebenso wie die Länge und Schreibweise der IP-Adressen. Transkription der gesamten Episode Automatisch erzeugte Transkription der Episode [0:00] Herzlich willkommen zum Anwendungsentwickler-Podcast, dem Podcast rund um die Ausbildung zum Fachinformatiker [0:09] für Anwendungsentwicklung. In dieser Episode geht es um den Aufbau und die Darstellung [0:14] von IP-Adressen. Viel Spaß! [0:20] Hallo und herzlich willkommen zur 137. Episode des Anwendungsentwickler-Podcasts. Mein Name [0:27] ist Stefan Macke und heute geht es weiter mit der kleinen Einführungsreihe zum Thema [0:32] Netzwerkgrundlagen. Letztes Mal hatten wir uns ja schon über einen ganzen Haufen Themen [0:37] unterhalten, die so zur Einführung nötig waren. Insbesondere Internet, Intranet, Website, [0:42] Homepage und die längste Zeit eigentlich über URLs, also die Uniform Resource Locators. [0:48] Das sind ja die Dinger, die wir als Mensch oben in die Browserzeile eingeben, um dann [0:52] auf eine Website zu kommen. Und das hat länger gedauert, als ich erwartet hätte. Ich habe [0:57] intensiv den Aufbau von URLs beschrieben und so weiter und so fort. Hör dir das gerne nochmal [1:01] an, wenn du es noch nicht gehört haben solltest. Denn heute geht es jetzt nahtlos an der Stelle [1:05] weiter, wenn wir jetzt diese URL da eingegeben haben im Browser und jetzt Enter drücken. Dann [1:11] haben wir als Mensch also dort etwas eingegeben, was wir sogar einigermaßen noch nachvollziehen [1:14] können. Auch wenn die URL ja ein technischer Begriff ist und der Aufbau auch ganz viele [1:19] Technik-Bestandteile beinhaltet, muss ich sie als Mensch nicht unbedingt alle verstehen. Und [1:24] ich kann sie mir aber auch einigermaßen gut merken. Denn das, was ich da eingebe, ist nicht ...
47 Minuten
Um den Aufbau von URLs geht es in der einhundertsechsunddreißigsten Episode des Anwendungsentwickler-Podcasts. TL;DR Am Beispiel einer Adresse im Browser führe ich dich in die Netzwerkkommunikation ein. Du erfährst, was Website und Homepage bedeuten und wie dein Browser Inhalte vom Webserver sichtbar macht. Im Mittelpunkt stehen URLs: Ihr Aufbau bestimmt, welche Ressource du ansprichst, welche Parameter du übergibst und welchen Abschnitt der Browser anzeigt. Diese Grundlagen gehören zum Prüfungsstoff deiner IT-Ausbildung. Kapitelmarken [00:00:20] Einstieg in die Netzwerkkommunikation [00:02:48] Eine Website im Browser aufrufen [00:03:53] Website und Homepage [00:06:03] HTML und Rendern im Browser [00:07:17] Client und Server [00:07:51] Internet und Intranet [00:09:28] URLs und ihre Aufgabe [00:11:51] Eine Beispieladresse zerlegen [00:13:11] Schema und Protokoll [00:14:58] Domain und Top-Level-Domain [00:19:48] Domainnamen auswählen und registrieren [00:22:34] Subdomains und Hostnamen [00:25:24] Die Rolle von www [00:27:46] Mehrere Anwendungen auf einem Server [00:30:17] Pfad und Dateiname [00:31:36] PHP und dynamische Inhalte [00:35:03] Parameter als Schlüssel-Wert-Paare [00:38:07] Fragmente und Sprünge innerhalb einer Seite [00:39:39] Hash und Hashtag [00:41:41] URL-Aufbau und Zugangsdaten [00:43:21] Rückblick und Prüfungsrelevanz [00:45:50] Literatur zu Netzwerkgrundlagen Inhalt Use Case Was passiert technisch, wenn der Browser eine Website anzeigt? Übrigens: Unterschied Website/Homepage: Eine Website ist die Gesamtheit an Inhalten des Anbieters, während die Homepage lediglich die Startseite des Angebots bezeichnet. Der Client ruft eine Adresse im Browser auf und der Server liefert HTML zurück, das der Browser rendert (in eine grafische Darstellung umwandelt) und auf dem Client darstellt. Übrigens: Intranet vs. Internet: Der grundsätzliche Vorgang ist derselbe, nur der Webserver steht im internen Netz bzw. ist nur aus dem internen Netz heraus erreichbar. URLs Woher wissen Client und Server, wohin sie ihre Daten schicken müssen? Der Client muss zunächst die Zieladresse kennen. Dies ist meistens ein URL wie z.B. www.google.com URL steht für Uniform Resource Locator. Wie sind URLs aufgebaut? Beispiel: http://blog.macke.it/posts/post.php?id=123#comments Der erste Teil ist das sogenannte Schema oder Protokoll. Davon gibt es mehrere, nicht nur http, sondern z.B. auch noch ftp oder mailto (Pseudo-Protokoll). Die Domain ist hierarchisch von rechts nach links absteigend aufgebaut. Die Top Level Domain ist z.B. de oder com. Danach kommt die eigentliche Domain mit ggfs. Subdomain und Hostname. Das www ist übrigens der Hostname (übliche Bezeichnung des Webservers) und nicht verpflichtend in einem URL! Danach kommt der Pfad, der vergleichbar mit einem Pfad und einer Datei auf einer Festplatte ist. Das php steht für die Programmiersprache PHP, mit der Websites entwickelt werden können. Nach dem Dateinamen können Parameter als Schlüssel/Wert-Paare angegeben werden, um z.B. mit einer physikalischen Datei unterschiedliche Artikel in einem Warenkorb anhand ihrer ID anzeigen zu können. Zuletzt ist noch ein Abschnitt möglich, über den man z.B. direkt auf eine Überschrift mitten auf der aktuellen Seite springen kann. Das Zeichen # heißt übrigens "Hash" und nicht "Hashtag". Benutzername und Passwort zum Zugriff auf die Ressourcen können ebenfalls angegeben werden. Sie werden vor die Domain geschrieben: http://benutzer:passwort@macke.it. Literaturempfehlungen Im guten alten IT-Handbuch für Fachinformatiker* werden in Kapitel 4 Netzwerkgrundlagen die meisten hier genannten Inhalte ausführlich erläutert. In meinem Buchclub gehe ich auf die Inhalte auch noch einmal im Detail ein. * Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Website Homepage Uniform Resource Locator Domain (Internet) Zusammenfassung Vom Browser zum Webserver Für den Einstieg in die Netzwerkkommunikation greife ich eine Situation auf, die du aus dem Alltag kennst: Du gibst eine Adresse im Browser ein und rufst eine Website auf. Dahinter arbeiten verschiedene Komponenten zusammen, damit die Inhalte auf deinem Gerät ankommen und sichtbar werden. Die Reihe soll diesen Weg bis zu HTML und CSS verfolgen. Dazu gehören später auch DNS und DHCP sowie IP-Adressen, Routing und Network Address Translation. Zum Einstieg stehen die grundlegenden Begriffe und der Aufbau von URLs im Mittelpunkt. Website und Homepage Damit du dich als IT-Azubi präzise ausdrücken kannst, brauchst du passende Begriffe: Website: Sie umfasst alle Inhalte eines Webauftritts, die ein Webserver bereitstellt. Dazu gehören einzelne Webseiten und weitere Dateien, etwa die MP3-Dateien meines Podcasts. Homepage: Sie ist die Startseite eines Webauftritts. Du erreichst sie üblicherweise, wenn du dessen Adresse ohne eine bestimmte Unterseite aufrufst. Wie der Browser Inhalte sichtbar macht Beim Aufruf einer Webseite erhält der Browser üblicherweise HTML vom Webserver. Diese Auszeichnungssprache beschreibt, welche Rolle die Inhalte haben. Ein Text kann beispielsweise als Überschrift ausgezeichnet sein; an einer anderen Stelle soll ein Bild erscheinen. Der Browser verarbeitet HTML zusammen mit CSS und stellt daraus die sichtbare Seite dar. Dieses Verfahren heißt Rendern. Dabei erscheinen Bilder an der vorgesehenen Stelle und Text wird entsprechend dargestellt. Für den weiteren Weg verwende ich zwei Begriffe: Mit Client meine ich das Gerät, an dem du sitzt, beispielsweise deinen Laptop oder dein Smartphone. Der Server ist hier der Webserver, der die angefragten Inhalte liefert. Internet und Intranet Über das weltumspannende Internet können Rechner miteinander kommunizieren. Ein Intranet befindet sich üblicherweise innerhalb eines Unternehmens und stellt dort Inhalte für Mitarbeiter:innen bereit. Der Zugriff auf interne Firmendaten wird vom öffentlichen Internet getrennt. Für die hier behandelte Kommunikation gelten in beiden Netzen dieselben grundlegenden Verfahren. Auch die Protokolle und die Inhalte in HTML und CSS kommen in beiden Umgebungen vor. Wozu eine URL dient URL steht für Uniform Resource Locator. Eine URL beschreibt nach einem einheitlichen Aufbau, wo eine Ressource erreichbar ist. Beim Aufruf einer Webseite benennt sie das Ziel und kann genauer festlegen, welchen Inhalt du erhalten möchtest. Als Beispiel verwende ich die Bestandteile dieser Adresse: http://blog.macke.it/posts/post.php?id=123#comments Schema Ganz links steht das Schema, hier http. Es legt fest, wie der Client mit der Adresse umgehen soll. http und https stehen für den Zugriff auf Webinhalte. HTTPS ist die verschlüsselte Variante. mailto: zusammen mit einer E-Mail-Adresse kann das E-Mail-Programm öffnen, damit du eine Nachricht schreiben kannst. ftp steht für das File Transfer Protocol und gehört zum Übertragen von Dateien. Ein Schema kann ein Protokoll bezeichnen. Bei mailto beschreibt es eine Aktion für das passende Programm. In der Beispieladresse trennt :// das Schema vom folgenden Teil. Browser ergänzen HTTP oder HTTPS häufig automatisch, wenn du eine Adresse ohne Schema eingibst. Domain Mit blog.macke.it wird das Ziel benannt. Hinter einer Domain können auch mehrere Server stehen, die Anfragen bearbeiten. Die Hierarchie liest du von rechts nach links: Top-Level-Domain: Im Beispiel ist das it. Domainname: macke steht vor der Top-Level-Domain. Subdomain oder Hostname: Links davon steht hier blog. Zu den länderbezogenen Top-Level-Domains gehören etwa .de für Deutschland und .it für Italien. .tv ist die Länderkennung von Tuvalu. Solche Endungen können auch wegen ihres Namens gewählt werden; meine Domain macke.it greift beispielsweise die Abkürzung für Informationstechnologie auf. Für manche Länderendungen gelten Vorgaben, etwa zum Wohnsitz. Generische Top-Level-Domains sind keinem bestimmten Land zugeordnet. Beispiele sind .com und .net; hinzu kommen Endungen wie .versicherung oder .auto. Neue Top-Level-Domains müssen beantragt und genehmigt werden, wobei hohe Kosten entstehen. Wenn du eine Domain registrieren möchtest, muss die Kombination aus Domainname und Top-Level-Domain noch frei sein. Sie wird eindeutig vergeben. Für die deutschen .de-Domains ist die DENIC zuständig. Bei der Wahl eines Namens spielen auch Markenrechte eine Rolle. Subdomain und Hostname Nachdem du eine Domain registriert hast, kannst du links davon weitere Namen festlegen. Eine Subdomain unterteilt die Domain und kann mehrere Rechner umfassen. Ein Hostname bezeichnet einen konkreten Rechner innerhalb der Domain. Welche Rolle ein Name hat, ergibt sich aus dem jeweiligen Netzwerkaufbau. www ist ein historisch verbreiteter Name für Server, die Webinhalte bereitstellen. Ob eine Website unter diesem Namen erreichbar ist, legt der/die Betreiber:in fest. Für meine Websites richte ich www ein und leite die Anfragen auf die kürzere Adresse weiter, damit Besucher:innen die Seite auch mit diesem Zusatz erreichen. Verschiedene Namen können außerdem mehrere Anwendungen auf einem Server erreichbar machen. Unter blog.macke.it kann beispielsweise WordPress laufen, während wiki.macke.it ein Wiki bereitstellt. Auch unterschiedliche Pfade wie /blog und /wiki können Anwendungen voneinander trennen. Pfad und Dateiname Nach der Domain folgt im Beispiel /posts/post.php. Der Slash / trennt die Teile des Pfads. Damit wird die gewünschte Ressource auf dem Server genauer bezeichnet. Ein solcher Pfad kann einem Verzeichnis und einer Datei auf der Festplatte entsprechen. Bei dynamischen Websites kommen auch virtuelle Pfade vor, die durch Programmcode verarbeitet werden. Der/die Betreiber:in legt fest, wie der Webserver die Adresse behandelt. PHP ist eine verbreitete Programmiersprache für Webanwendungen. Ein PHP-Skript kann Inhalte aus einer Datenbank lesen und daraus HTML erzeugen, das der Browser anschließend darstellt. So lässt sich in einem Blog jeweils der neueste Beitrag anzeigen. Der Pfad dient dabei dazu,...
48 Minuten
Über den Inhalt und die Erstellung eines betrieblichen Ausbildungsplans für Fachinformatiker spreche ich in der einhundertfünfunddreißigsten Episode des Anwendungsentwickler-Podcasts. TL;DR Ich habe meinen betrieblichen Ausbildungsplan nach den Änderungen an den IT-Berufen von 2018 überarbeitet. Darin wird für jeden Inhalt aus dem Ausbildungsrahmenplan festgelegt, was du im Betrieb lernst, wo und mit wem du daran arbeitest, welche Lehrmethode passt und wann das Thema ansteht. Der rechtlich vorgeschriebene Plan hilft dir und deinem/deiner Ausbilder:in, offene Themen zu erkennen und deine Ausbildung zu planen. Für das Erstellen verbinde ich konkrete Beispiele mit vorhandenen Schulungen und Projekten; meine Excel-Vorlagen für Anwendungsentwicklung und Systemintegration stehen zum Herunterladen bereit. Kapitelmarken [00:00:20] Anlass: Den betrieblichen Ausbildungsplan überarbeiten [00:01:44] Excel-Vorlagen für Anwendungsentwicklung und Systemintegration [00:02:31] Die Ausbildungspläne im Überblick [00:02:44] Inhalte des Ausbildungsrahmenplans [00:04:51] Der Rahmenlehrplan für die Berufsschule [00:05:40] Der betriebliche Ausbildungsplan [00:07:36] Wofür der Betrieb den Ausbildungsplan braucht [00:09:23] Individuelle Abläufe und flexible Termine [00:11:28] Vermittelte Inhalte prüfen und festhalten [00:12:36] Rechtliche Grundlagen im Berufsbildungsgesetz [00:14:42] Den Ausbildungsplan als IT-Azubi lesen und prüfen [00:16:57] Vorlagen für den sachlichen und zeitlichen Ablauf [00:18:23] Mit fünf W-Fragen den Ausbildungsplan füllen [00:18:44] Was: Konkrete Inhalte und Technologien festlegen [00:20:30] Wo und wer: Lernorte und zuständige Personen bestimmen [00:21:40] Wie: Passende Lehrmethoden auswählen [00:22:13] Wann: Grundlagen und feste Termine berücksichtigen [00:23:43] Externe Unterstützung einplanen [00:25:14] Zusammenhängende Inhalte gemeinsam vermitteln [00:26:48] Schulungen für IT-Azubis verschiedener Ausbildungsjahre [00:28:16] Den Lernerfolg prüfen [00:29:01] Mein Vorgehen beim Erstellen des Ausbildungsplans [00:33:23] Lernmaterial und offene Aufgaben ergänzen [00:34:39] Zusätzliche Spalten in der Excel-Vorlage [00:37:00] Ein ausgefüllter Eintrag zur IT-Sicherheit [00:38:43] Checkliste für die sachliche Gliederung [00:41:47] Checkliste für die zeitliche Gliederung [00:44:38] Austausch und weiterführende Materialien [00:45:46] Fazit zum betrieblichen Ausbildungsplan Inhalt Begriffsdefinitionen Ausbildungsrahmenplan: Gibt die allgemeinen Inhalte der Ausbildung vor. Er ist bewusst so formuliert, dass er eine lange Gültigkeit hat und nicht ständig aktualisiert werden muss. Er enthält also z.B. keine Programmiersprachen oder Netzwerk-Protokolle. Die aktuelle Version, die 2018 lediglich leicht ergänzt wurde, ist seit dem Jahr 1997 gültig. Der Ausbildungsrahmenplan wird als Teil der Ausbildungsordnung vom Bundesministerium für Bildung vorgegeben (siehe Verordnung über die Berufsausbildung im Bereich der Informations- und Telekommunikationstechnik). Rahmenlehrplan: Er enthält die Inhalte, die in der Berufsschule vermittelt werden müssen. Der Rahmenlehrplan wird von der Kultusministerkonferenz vorgegeben (siehe Rahmenlehrplan Fachinformatiker/Fachinformatikerin). Betrieblicher Ausbildungsplan: Überträgt die allgemeinen Inhalte aus dem Ausbildungsrahmenplan auf das konkrete Ausbildungsunternehmen. Hier werden einzelne Technologien, Schulungen usw. konkreten Zeiten während der dreijährigen Ausbildungszeit zugeordnet. Der betriebliche Ausbildungsplan wird vom Ausbildungsunternehmen erstellt und für jeden Azubi individuell angepasst. Wofür braucht man einen betrieblichen Ausbildungsplan? Die vorgegebenen Inhalte aus dem Ausbildungsrahmenplan müssen durch das Ausbildungsunternehmen innerhalb der drei Jahre der Ausbildung dem Azubi vermittelt werden. Wie genau das erfolgen soll, muss jedes Unternehmen selbst entscheiden. Vielleicht durchläuft der Azubi im ersten Lehrjahr eine Abteilung, die sich mit Netzwerken beschäftigt, und erst im zweiten Jahr kommt er in die Anwendungsentwicklung. Diesen spezifischen Abläufen wird mit dem betrieblichen Ausbildungsplan Rechnung getragen. Das Unternehmen muss sicherstellen, dass alle nötigen Inhalte (was) vermittelt werden, aber wie, wann, von wem und wo kann es selbst entscheiden. Der betriebliche Ausbildunsplan kann sogar für jeden einzelnen Azubi des Unternehmens individuell erstellt werden, wenn das sinnvoll ist, z.B. wenn bestimmte Abläufe in der Ausbildung von Jahr zu Jahr wechseln. Als Ausbilder Für den Ausbilder ist der betriebliche Ausbildungsplan wichtig, damit er sichergehen kann, dass seinen Azubis alle nötigen Kenntnisse des Berufs vermittelt werden, die auch in der Abschlussprüfung abgefragt werden. Außerdem gibt es ganz nebenbei auch eine gesetzliche Vorgabe, nach der jedes Ausbildungsunternehmen verpflichtet ist, einen betrieblichen Ausbildungsplan zu erstellen. Und zwar schon vor Beginn der Ausbildung, da er Teils des Ausbildungsvertrags ist: Ausbildende haben unverzüglich nach Abschluss des Berufsausbildungsvertrages, spätestens vor Beginn der Berufsausbildung, den wesentlichen Inhalt des Vertrages gemäß Satz 2 schriftlich niederzulegen; die elektronische Form ist ausgeschlossen. In die Niederschrift sind mindestens aufzunehmen 1. Art, sachliche und zeitliche Gliederung [Herv. d. Verf.] sowie Ziel der Berufsausbildung, insbesondere die Berufstätigkeit, für die ausgebildet werden soll [...] Quelle: Berufsbildungsgesetz (BBiG), § 11 Vertragsniederschrift, Absatz 1, Satz 2, Nummer 1 Im BBiG wird diesem Plan auch sein Namen gegeben: Auf einen betrieblichen Ausbildungsplan [Herv. d. Verf.] im Sinne von § 11 Absatz 1 Satz 2 Nummer 1 [...] Quelle: Berufsbildungsgesetz (BBiG), § 36 Antrag und Mitteilungspflichten, Absatz 1, Satz 3 Und auch laut Verordnung über die Berufsausbildung im Bereich der Informations- und Telekommunikationstechnik muss jedes ausbildende Unternehmen einen Ausbildungsplan erstellen, der auf dem Ausbildungsrahmenplan zum Fachinformatiker basiert: § 11 (Ausbildungsrahmenplan) Die in § 10 genannten Fertigkeiten und Kenntnisse sollen nach den in Anlage 2 enthaltenen Anleitungen zur sachlichen und zeitlichen Gliederung der Berufsausbildung (Ausbildungsrahmenplan) vermittelt werden. Eine von dem Ausbildungsrahmenplan abweichende sachliche und zeitliche Gliederung des Ausbildungsinhaltes ist insbesondere zulässig, soweit betriebspraktische Besonderheiten die Abweichung erfordern. § 12 (Ausbildungsplan) Der Ausbildende hat unter Zugrundelegung des Ausbildungsrahmenplanes für den Auszubildenden einen Ausbildungsplan zu erstellen. Als Azubi Der Azubi hat auch ein Interesse an einem sinnvollen betriebliche Ausbildungsplan, damit er seine für die Berufspraxis und auch für die Abschlussprüfung nötigen Kenntnisse optimal erlernen kann. Aufeinander aufbauende Themen sollten also z.B. nacheinander und in der richtigen Reihenfolge behandelt werden. Außerdem sollten die schwierigeren Themen vielleicht eher gegen Ende der Ausbildung vermittelt werden. Zuletzt kann der Azubi anhand des betrieblichen Ausbildungsplans auch kontrollieren, ob er in seinem Unternehmen korrekt ausgebildet wird. Woher bekomme ich als Azubi meinen betrieblichen Ausbildungsplan? Deinen betrieblichen Ausbildungsplan bekommst du von deinem Ausbildungsunternehmen. Er muss dir zusammen mit deinem Ausbildungsvertrag ausgehändigt werden (s.o.). Solltest du noch keinen Ausbildungsplan bekommen haben, wende dich an deinen Ausbilder oder eure Personalabteilung. Wie erstelle ich als Ausbilder einen betrieblichen Ausbildungsplan? Die fachlichen Inhalte der Ausbildung sind durch den Ausbildungsrahmenplan (siehe Anlage 2 Teil A ITKTAusbV) vorgegeben. Auch eine mögliche Aufteilung auf die drei Ausbildungsjahre inkl. Vorschlägen für die zeitliche Dauer ist vorgegeben (siehe Anlage 2 Teil B ITKTAusbV). Die ca. 200 einzelnen Punkte müssen also "nur noch" in den betrieblichen Ausbildungsplan überführt werden. Dazu kann man z.B. Excel verwenden (siehe Vorlagen weiter unten). W-Fragen zum Einstieg Zu jedem Punkt aus der Liste sollte man sich grundsätzlich erst einmal einige "W-Fragen" stellen (und beantworten): Was soll vermittelt werden? Das steht zwar im Ausbildungsrahmenplan, aber die bewusst allgemein gehaltenen Formulierungen (z.B. 5.2b Programmierlogik und Programmiermethoden anwenden) müssen teilweise erstmal in die Neuzeit bzw. auf konkrete Technologien übersetzt werden (z.B. Java und C#). Wo wollen wir die Inhalte vermitteln? Bei Unternehmen mit mehreren Standorten oder Abteilungen, die die Azubis durchlaufen, muss z.B. der geeignete Ort für den konkreten Inhalt ausgewählt werden. Wer übernimmt die Vermittlung der Inhalte? Das können Ausbilder, Ausbildungsbeauftragte, Paten, externe Dozenten etc. sein. Wie sollen die Inhalte optimal vermittelt werden? Welche Lehr- und Lernmethoden sollen angewendet werden, z.B. Projektarbeit, Selbststudium, Lehrgespräch. Wann werden die Inhalte am besten vermittelt? In welches Ausbildungsjahr passen die Inhalte am besten und welche vorbereitenden Themen müssen evtl. abgehakt sein? Kritische Bewertung des Ausbildungsplans Zusätzlich bieten sich die folgenden Fragen an, die vielleicht bei der Abarbeitung der großen Liste helfen und zu einem sinnvollen Plan führen: Welche Ausbildungsinhalte kann das Unternehmen selbst vermitteln bzw. vermittelt es vielleicht sogar schon? Hier kann man die konkreten Schulungen oder Projekte zusammentragen (z.B. Einführungsschulung, Datenbank-Training), ihren Zeitbedarf festhalten, eine sinnvolle Reihenfolge der Inhalte festlegen, zuständige Mitarbeiter benennen und die konkreten Einsätze planen. Welche Ausbildungsinhalte kann das Unternehmen nicht selbst vermitteln? Hier sind evtl. externe Schulungen einzuplanen oder gar Kooperationen mit anderen Unternehmen abzuschließen. Alternativ können die fehlenden Inhalte auch in-house aufgebaut werden. ...
34 Minuten
Über die Neuordnung der IT-Berufe in den Jahren 2018 und 2020 spreche ich in der einhundertvierunddreißigsten Episode des Anwendungsentwickler-Podcasts. TL;DR Seit dem 1. August 2018 gehören IT-Sicherheit und der verantwortungsvolle Umgang mit digitalen Medien ausdrücklich zu den Ausbildungsinhalten der IT-Berufe. Für dich als Fachinformatiker:in Anwendungsentwicklung bedeutet das, Sicherheit beim Programmieren von Anfang an mitzudenken; dein Berichtsheft führst du weiterhin auf Grundlage des Berufsbildungsgesetzes. Für die damals geplante Neuordnung 2020 waren weitere Inhalte und eine gestreckte Abschlussprüfung im Gespräch, deren genaue Form zum Zeitpunkt meiner Aufnahme noch offen war. Kapitelmarken [00:00:00] Einstieg in die Neuordnung der IT-Berufe [00:01:09] Ausbildungsordnung von 1997 und technologieunabhängige Inhalte [00:04:09] Anlass für die Vorstudie [00:04:42] Ausbildungszahlen und Frauenanteil [00:06:05] Ergebnisse und Vorschläge der Vorstudie [00:09:57] Geltungsbereich der Änderungen von 2018 [00:11:03] Änderungsverordnung und Vergleichstabelle [00:12:59] Verantwortlich mit digitalen Medien umgehen [00:14:36] IT-Sicherheit, Datenschutz und Urheberrecht [00:18:26] Sicherheit beim Entwickeln von Software [00:19:41] Netzwerke absichern und Angriffe erkennen [00:21:02] Gemeinsame Anforderungen für die IT-Berufe [00:22:08] Berichtsheft und Berufsbildungsgesetz [00:24:29] Geplante Inhalte und Berufsprofile für 2020 [00:26:11] Gestreckte Abschlussprüfung [00:26:52] Fachliche Kompetenzen und selbstgesteuertes Lernen [00:28:35] Einschätzung zum Umfang der geplanten Neuordnung [00:31:22] Quellen und den eigenen Ausbildungsplan prüfen [00:32:50] Newsletter und Checklisten Inhalt Die fünf IT-Berufe (Fachinformatiker der Fachrichtungen Anwendungsentwicklung und Systemintegration, Informatikkaufleute, IT-Systemkaufleute und IT-Systemelektroniker) werden in der Verordnung über die Berufsausbildung im Bereich der Informations- und Telekommunikationstechnik beschrieben. Diese wurde im Jahr 1997 erstellt und ist seitdem nicht angepasst worden, was aber auch nicht unbedingt nötig war. Die Inhalte sind nämlich bewusst so allgemein formuliert, dass man nicht alle zwei Wochen die Verordnung aktualisieren muss, nur weil es gerade mal wieder irgendeinen Trend in der IT-Branche gibt. Anstatt konkrete Programmiersprachen oder Netzwerkprotokolle als Lerninhalt vorzuschreiben, werden allgemeine Formulierungen verwendet wie z.B. (FIAE) 9.1 Kundenspezifische Anpassung und Softwarepflege (§ 10 Abs. 2 Nr. 9.1) 9.1a Anwendungslösungen entsprechend den kundenspezifischen Anforderungen einrichten, konfigurieren und anpassen 9.1b Software an eine veränderte Umgebung anpassen und weiterentwickeln 9.1c Anwendungslösungen mit Hilfe von Applikationssprachen erweitern (FISI) 8.1 Systemkonfiguration (§ 10 Abs. 4 Nr. 8.1) 8.1a Rechner- und Systemarchitekturen sowie Betriebssysteme beurteilen und einordnen 8.1b Betriebssysteme unter Berücksichtigung ihrer Vor- und Nachteile für bestimmte Anwendungsbereiche auswählen und konfigurieren 8.1c Betriebssystemsteuersprachen anwenden Gerade ist übrigens die Rangliste 2018 der Ausbildungsberufe nach Anzahl der Neuabschlüsse beim BIBB erschienen. Der Fachinformatiker ist auf Platz 7 vorgerückt. Das Interesse an unserem Beruf ist also ungebrochen und wächst sogar. Ein Grund mehr, die Berufsinhalte auf den Prüfstand zu stellen. Ergebnisse der Vorstudie zur Novellierung der IT-Berufe Folgende Themen wurden im Rahmen einer Vorstudie (Umfrage bei Arbeitgebern, Schulen, Azubis) als besonders relevant für die Ausbildung identifiziert: Wichtige Inhalte: IT-Security, Industrie 4.0, personale und soziale Kompetenzen Zusammenlegung von Informatikkaufmann und IT-System-Kaufmann Aufteilung der beiden Fachinformatiker in separate Berufe Wahlqualifikationen einführen, um stärker spezialisieren zu können Abschlussprüfung erneuern (gestreckte Prüfung) Novellierung der IT-Berufe zum 01.08.2018 Zum 01.08.2018 wurden die IT-Berufe nun zum ersten Mal überarbeitet. Es sind aber nur ein paar wenige Punkte verändert worden, indem das Stichwort "IT-Sicherheit" ergänzt wurde. Der große Rest ist gleichgeblieben. Für alle Azubis, die ihre Ausbildung am oder nach dem 01.08.2018 begonnen haben, gilt bereits die neue Verordnung! Die konkreten Änderungen habe ich aus der Ersten Verordnung zur Änderung der Verordnung über die Berufsausbildung im Bereich der Informations- und Telekommunikationstechnik übernommen. ALT NEU 3.1f die Auswirkungen des eigenen Kommunikations- und Informationsverhaltens in beruflichen Kontexten erkennen und Strategien zum verantwortungsvollen Umgang mit digitalen Medien anwenden 5.4 Datenschutz und Urheberrecht (§ 10 Abs. 1 Nr. 5.4) IT-Sicherheit, Datenschutz und Urheberrecht (§ 10 Abs. 1 Nr. 5.4) 5.4a Verschlüsselungsverfahren und Zugriffsschutzmethoden anwenden rechtliche Regelungen und betriebliche Vorgaben zur IT-Sicherheit einhalten 5.4b Vorschriften zum Datenschutz anwenden Bedrohungsszenarien und Schadenspotentiale erkennen und bewerten 5.4c Vorschriften zum Urheberrecht anwenden Schutzmechanismen für informations- und telekommunikationstechnische Systeme anwenden 5.4d technische Vorschriften zur Sicherung des Fernmeldegeheimnisses anwenden Vorschriften zum Datenschutz einhalten 5.4e Daten archivieren, nicht mehr benötigte Datenbestände löschen, Datenträger entsorgen Vorschriften zum Urheberrecht einhalten 6.2e Programme unter Berücksichtigung der Wartbarkeit und Wiederverwendbarkeit und Sicherheit erstellen nur für FISIs: 8.2e Angriffsszenarien auf Netzwerke erkennen und bewerten 8.2f Systeme zur IT-Sicherheit in Netzwerken implementieren Man erkennt schnell, dass damit insb. auf die aktuell immer häufiger auftretenden Hacker-Angriffe gegen Netzwerke reagiert werden soll. Aber auch der Datenschutz wurde explizit erwähnt, der inzwischen dank DSGVO aber ja auch deutlich weiter geht als nur das Fernmeldegeheimnis. Wichtig ist, dass die Anpassungen hauptsächlich in den Bereichen vorgenommen wurden, die für alle IT-Berufe identisch sind. Es geht hier also um Grundwissen und nicht um FISI-Spezialwissen. IT-Sicherheit und Datenschutz sind auch für Anwendungsentwickler absolut wichtig und müssen z.B. bei der Programmierung der eigenen Anwendungen berücksichtigt werden. Wenn vom Anwendungsentwickler Passwörter im Klartext in der Datenbank abgelegt werden, kann der Systemintegrator noch so tolle Firewalls davorschalten, die Daten bleiben kompromittierbar! Führen des Berichtshefts Einige gestrichene Paragraphen beziehen sich übrigens auf das Führen des Berichtshefts, insb. der für die beiden Fachinformatiker gültige § 13: Der Auszubildende hat ein Berichtsheft in Form eines Ausbildungsnachweises zu führen. Ihm ist Gelegenheit zu geben, das Berichtsheft während der Ausbildungszeit zu führen. Der Ausbildende hat das Berichtsheft regelmäßig durchzusehen. (§ 13 ITKTAusbV) Das Führen von Ausbildungsnachweisen ist aber selbstverständlich weiterhin Bestandteil der Ausbildung. Nur das dies nun für alle Berufe verbindlich im Berufsbildungsgesetz geregelt wird und nicht mehr in den einzelnen Ausbildungsordnungen: Ausbildende haben Auszubildende zum Führen der Ausbildungsnachweise nach § 13 Satz 2 Nummer 7 anzuhalten und diese regelmäßig durchzusehen. Den Auszubildenden ist Gelegenheit zu geben, den Ausbildungsnachweis am Arbeitsplatz zu führen. (§ 14 (2) BBiG) Auszubildende haben sich zu bemühen, die berufliche Handlungsfähigkeit zu erwerben, die zum Erreichen des Ausbildungsziels erforderlich ist. Sie sind insbesondere verpflichtet, einen schriftlichen oder elektronischen Ausbildungsnachweis zu führen. (§ 13 7. BBiG) Geplante Anpassungen in 2020 Die Überarbeitung (Änderungsverordnung) der IT-Berufe 2018 war erst der Anfang. Im Jahr 2020 sollen weitere Anpassungen vorgenommen werden (Neuordnung). Inhaltlich wird es um Themen wie IT-Security, Virtualisierung, Cloud-Computing, Big Data oder Mobile Computing gehen. (Vgl. Neuordnung der IT-Berufe 2018 und 2020 (offline)) Die Berufe Informatikkaufmann und IT-System-Kaufmann sollen stärker voneinander abgegrenzt werden. Der Informatikkaufmann soll ein neues Profil, eine neue Ausrichtung, neue Inhalte und eine neue Berufsbezeichnung bekommen (der Arbeitstitel ist Datenkaufleute). (Vgl. Zukunft der IT-Berufe: Informationen zum Neuordnungsverfahren) Einführung einer gestreckten Abschlussprüfung, bei der die Zwischenprüfung durch einen ersten Teil der Abschlussprüfung ersetzt wird. Katalog der vorläufigen Fertigkeiten, Kenntnisse und Fähigkeiten (Qualifikationskatalog) für Anwendungsentwickler Vgl. Eckwerte Fachinformatiker/-in Berufsprofilgebende Fertigkeiten, Kenntnisse und Fähigkeiten Planen, Vorbereiten und Durchführen von Arbeitsaufgaben in Abstimmung mit den kundenspezifischen Geschäfts- und Leistungsprozessen Informieren und Beraten von Kunden, Bearbeiten von Anfragen Beurteilen marktgängiger IT-Produkte und kundenspezifischer Lösungen Konzeptionierung und Realisierung von kundenspezifischen Softwareanwendungen Testen und dokumentieren Anwendungen Modifizieren bestehender Anwendungen Einsetzen von Projektplanungs- und Steuerungsinstrume
18 Minuten
Im siebten Wissenshäppchen geht es um das Dependency Inversion Principle. TL;DR Mit dem Dependency Inversion Principle, dem D aus SOLID, richte ich Abhängigkeiten auf abstrakte Schnittstellen aus. Die Geschäftslogik und ihre technischen Komponenten hängen dadurch von Abstraktionen ab, wobei konkrete Implementierungen von außen übergeben werden. So kannst du beispielsweise eine Datenbank austauschen oder im Test durch ein Fake-Objekt ersetzen, während die Geschäftslogik unverändert bleibt. Zusätzliche Schnittstellen und das Zusammensetzen der Objekte erhöhen den Aufwand, weshalb ich passende Stellen für diese Abstraktionen gezielt auswähle. Kapitelmarken [00:00:00] Einstieg ins Dependency Inversion Principle [00:00:50] Definition und Richtung der Abhängigkeiten [00:01:46] Geschäftslogik und Datenbank in der Schichtenarchitektur [00:02:30] Feste Abhängigkeiten beim Testen und Austauschen [00:02:55] Schnittstellen und von außen übergebene Datenbanken [00:04:55] Änderungen an technischen Komponenten entkoppeln [00:05:46] Abhängigkeiten im Test durch Fake-Objekte ersetzen [00:07:06] Ruby-Codebeispiel mit Payroll und Datenbank [00:08:16] Abhängigkeiten durch Konstruktorparameter sichtbar machen [00:09:45] Vorteile und das Open-Closed-Principle [00:10:58] Over-Engineering und YAGNI [00:12:28] Sinnvolle Stellen für Abstraktionen auswählen [00:13:09] Objekte zusammensetzen und Dependency-Injection-Container [00:14:36] Praktische Hinweise zu Schnittstellen und Testbarkeit [00:16:03] Infrastruktur im Test austauschbar machen [00:17:08] Shownotes und Abschluss der SOLID-Reihe Inhalt Das DIP ist das letzte der fünf SOLID-Prinzipien. High level modules should not depend upon low level modules. Both should depend upon abstractions. Oder: Abstractions should not depend upon details. Details should depend upon abstractions. Welche Abhängigkeiten werden hier "umgedreht"? Komponenten, die andere Komponenten benötigen, erzeugen sich diese nicht selbst, sondern bekommen sie von außen hineingegeben. Braucht ein Service beispielsweise ein Repository um arbeiten zu können, erzeugt er es sich nicht selbst, z.B. mit this.repo = new Repository() in seinem Konstruktor, sondern bekommt es stattdessen schon fertig als Parameter übergeben, z.B. public Service(Repository repo). Das heißt, obwohl die Abhängigkeit vom Service zum Repository geht, wird sie "umgekehrt" aufgelöst, indem das Repository dem Service übergeben wird. Erklärung Wenn Komponenten sich ihre Abhängigkeiten selbst erzeugen, sind diese später nur umständlich oder gar nicht mehr austauschbar. Tests von Komponenten, die sich ihre Abhängigkeiten selbst erzeugen, sind schwierig/unmöglich/langsam/fehleranfällig, da die Abhängigkeiten nicht so einfach gegen Fake-Objekte ausgetauscht werden können. Die Abhängigkeiten sind nicht explizit in der API sichtbar. Der obige Service "braucht" ein Repository, aber das sieht man nur, wenn man sich den Quelltext von Service anschaut. Beim Erzeugen eines Services ist dies nicht offensichtlich, weil er sich das Repository "heimlich" selbst erzeugt. Beispiel Um alle Employees zu bezahlen, erzeugt sich die Payroll ihr eigenes MySqlEmployeeRepository. Dadurch wird auch im Test die echte Datenbank verwendet und ein Austauschen gegen eine Oracle-Datenbank erfordert eine Anpassung der Klasse Payroll (vgl. Open Closed Principle). class Payroll def initialize @repo = MySqlEmployeeRepository.new end def pay_employees @repo.find_all.each { |employee| employee.pay } end end class MySqlEmployeeRepository def find_all puts "Accessing the database and reading all employees" [Employee.new] * 10 end end class Employee def pay puts "Thank you for paying me" end end Payroll.new.pay_employees # Accessing the database and reading all employees # Thank you for paying me # ... # Thank you for paying me Statt dieser "harten" und versteckten Abhängigkeit sollte Payroll sich lieber die Implementierung eines Repositorys liefern lassen. Das erfordert nur eine kleine Umstrukturierung des Codes und ermöglicht deutlich einfachere Tests. class Payroll def initialize(repo) @repo = repo end def pay_employees @repo.find_all.each { |employee| employee.pay } end end class MySqlEmployeeRepository def find_all puts "Accessing the database and reading all employees" [Employee.new] * 10 end end class FakeEmployeeRepository def find_all [Employee.new] * 1 end end class Employee def pay puts "Thank you for paying me" end end puts "Production:" Payroll.new(MySqlEmployeeRepository.new).pay_employees puts "Test:" Payroll.new(FakeEmployeeRepository.new).pay_employees # Production: # Accessing the database and reading all employees # Thank you for paying me # ... # Thank you for paying me # Test: # Thank you for paying me Außerdem kann Payroll nun auch ohne Anpassungen (!) mit einer Oracle-Datenbank arbeiten. class OracleEmployeeRepository def find_all puts "Reading employees from Oracle database" [Employee.new] * 100 end end puts "Using Oracle:" Payroll.new(OracleEmployeeRepository.new).pay_employees # Reading employees from Oracle database # Thank you for paying me # ... # Thank you for paying me Vorteile Abhängigkeiten sind explizit sichtbar und können bei geänderten Anforderungen oder in Tests einfach ausgetauscht werden. Neue Funktionalitäten können dem Programm einfacher hinzugefügt werden, da durch die Abhängigkeit von Abstraktionen oftmals auch das OCP umgesetzt wird. Nachteile Ein Problem könnte wieder ein "Overengineering" sein. Es ist wahrscheinlich nicht sinnvoll, jede Kleinigkeit hinter einer Abstraktion zu verbergen. Aber wie entscheidet man, welche Abstraktion sinnvoll ist? Bei vielen Abhängigkeiten wird das Erstellen von Objekten (und damit auch deren Test) schwierig, weil viel Arbeit vorab erledigt werden muss. Hier könnte dann ein DI-Container zum Einsatz kommen. Literaturempfehlungen Wie sollte es anders sein: Auch für das letzte SOLID-Prinzip empfehle ich noch einmal Clean Code* von Uncle Bob. * Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Dependency Inversion Principle ArticleS.UncleBob.PrinciplesOfOod (Artikel von Uncle Bob, Beispiel in C++) Dependency-Inversion-Prinzip – Wikipedia Das Dependency Inversion Principle | Informatik Aktuell (Deutsches Beispiel in C#) Zusammenfassung Abhängigkeiten auf Schnittstellen ausrichten Beim Dependency Inversion Principle (DIP), dem letzten der fünf SOLID-Prinzipien, hängen höher angesiedelte Module wie meine Geschäftslogik und technische Module wie eine Datenbankanbindung von Abstraktionen ab. Die konkreten technischen Details richten sich ebenfalls nach diesen Abstraktionen. Damit wird die Richtung der Abhängigkeiten umgedreht. In einer klassischen Schichtenarchitektur hängt meine Geschäftslogik häufig direkt von einer konkreten Datenbankklasse ab. Steht dort ausdrücklich eine MySQL-Klasse, zieht ein Wechsel zu Oracle Änderungen am Business-Code nach sich. Solche Änderungen können Fehler verursachen. Auch technische Änderungen an der Datenbankklasse können sich bis zur Geschäftslogik auswirken und erneutes Kompilieren erforderlich machen. Eine Datenbank von außen übergeben Für meine Geschäftslogik definiere ich eine Schnittstelle wie IDatabase, die die benötigten Funktionen anbietet. Eine Basisklasse kann ebenfalls als Abstraktion dienen. Die Business-Klasse erhält von außen ein Objekt, das diese Schnittstelle implementiert. Damit kannst du verschiedene Datenbankklassen einsetzen: Eine MySQL-Klasse implementiert die vereinbarte Schnittstelle und stellt die Verbindung zu MySQL her. Für Oracle schreibst du eine weitere Klasse mit derselben Schnittstelle, die du anschließend an die Geschäftslogik übergibst. Die Business-Klasse kennt dabei die gemeinsame Schnittstelle. Solange diese stabil bleibt, können Änderungen an der konkreten Datenbankklasse getrennt bleiben; unter Umständen muss dann nur diese Klasse neu kompiliert werden. Bei einem Interface prüft der Compiler, ob das übergebene Objekt die Schnittstelle implementiert. Geschäftslogik gezielt testen Wenn meine Business-Klasse selbst eine echte Datenbankverbindung erzeugt, braucht ihr Test diese Datenbank ebenfalls. Dadurch können Tests langsam oder fehleranfällig werden und bei fehlender Datenbank scheitern. Mit einer übergebenen Abhängigkeit kannst du im Test ein Fake-Objekt einsetzen, das die passende Schnittstelle anbietet und festgelegte Werte zurückliefert. Auch Stubs oder Mocks können Abhängigkeiten ersetzen. So lässt sich die eigentliche Geschäftslogik gezielt prüfen, während die beteiligten technischen Komponenten durch Testobjekte abgedeckt werden. In meinem Ruby-Beispiel erhält eine Payroll-Klasse, die Mitarbeiter:innen bezahlt, ihre Datenbank von außen. Im Test übergebe ich eine Fake-Datenbank, die genau eine:n Mitarbeiter:in liefert. Ruby hat als dynamisch typisierte Sprache keine Interfaces; das Prinzip funktioniert dort über Objekte, die dieselbe Schnittstelle anbieten. Abhängigkeiten sichtbar machen Über einen Konstruktorparameter mache ich sichtbar, welche Objekte meine Klasse braucht. Du erkennst bereits beim Erzeugen einer Payroll, dass du eine Datenbank bereitstellen musst und in welcher Reihenfolge die Objekte entstehen sollen. Werden benötigte Objekte innerhalb von Methoden erzeugt, musst du diese Methoden lesen, um die Abhängigkeiten zu entdecken. Ein Konstruktorparameter zeigt dir den Bedarf direkt und hilft beim Schreiben von Tests sowie beim Arbeiten am produktiven Code. Bestehenden Code erweitern Durch eine neue Klasse, die das vorhandene Datenbankinterface implementiert, kann meine Payroll auch mit einer weiteren Datenbank arbeiten. Die bestehende Klasse bleibt dabei unverändert. Das unterstützt das Open-Closed-Principle, nach dem sich Verhalten erweitern lässt,...
16 Minuten
Das sechste Wissenshäppchen hat das Interface Segregation Principle als Thema. TL;DR Mit dem Interface Segregation Principle (ISP) halte ich die Schnittstellen, von denen mein Code abhängt, so klein, wie es die jeweilige Aufgabe erlaubt. Am Beispiel von List und Iterable in Java zeige ich dir, wie eine passende Schnittstelle den Zugriff auf Methoden begrenzt und deinen Code für weitere Datenstrukturen öffnet. Kleine Interfaces erleichtern Tests und verringern den Aufwand, wenn sich andere Teile des Codes ändern. Dabei entstehen mehr einzelne Schnittstellen, die sich mit modernen IDEs gezielt finden lassen. Kapitelmarken [00:00:20] Das vierte SOLID-Prinzip: Interface Segregation [00:00:44] Kleine Interfaces und passende Abhängigkeiten [00:01:47] Große Interfaces und das Liskov Substitution Principle [00:02:35] Beispiel: Eine Liste durchlaufen [00:04:12] Iterable als passende Schnittstelle [00:05:25] Fachliche Aufgaben trennen und das Single Responsibility Principle [00:06:42] Mehrere kleine Interfaces in einer Klasse implementieren [00:07:32] Änderungen an ungebrauchten Methoden und erneutes Kompilieren [00:08:55] Einfachere Tests mit kleinen Interfaces [00:10:06] Duck Typing und explizite Abhängigkeiten [00:11:45] Vorteile kleiner Schnittstellen [00:12:46] Mehr Komponenten und der Umgang mit vielen Dateien [00:13:59] Schnittstellen klein halten [00:14:55] Ausblick, Codebeispiel und weiterführende Links Inhalt Das ISP ist das vierte SOLID-Prinzip. The dependency of one class to another one should depend on the smallest possible interface. Im Prinzip kann man das ISP so zusammenfassen: Verwende immer nur die kleinstmögliche Schnittstelle zu deinen Abhängigkeiten. Je mehr Funktionen eine Komponente an ihren Abhängigkeiten aufrufen kann, desto abhängiger wird sie von ihr. Wenn sich diese Funktionen nämlich ändern (z.B. die Signatur einer Methode), muss die nutzende Komponente neu kompiliert werden. Außerdem können Funktionen aufgerufen werden, die die nutzende Komponente weder benötigt, noch anwenden soll, z.B. die clear()-Methode einer Liste, die sie eigentlich nur durchlaufen soll. Zuletzt müssen auch implementierende Klassen von zu großen Interfaces für sie unnötige Methoden implementieren, nur um der Schnittstelle zu entsprechen. Erklärung Zu große Interfaces oder Basisklassen bieten evtl. Zugriff auf verschiedene Funktionalitäten, die nicht zusammengehören (z.B. Repository.getUser() und Repository.getArticle()), oder über das benötigte/erlaubte Verhalten hinausgehen (z.B. Repository.deleteUser()). Komponenten, die von diesen Schnittstellen abhängen, können mit ihnen "zu viel" machen und müssen angepasst (mind. rekompiliert) werden, wenn sich diese ändern, auch wenn sie die geänderte Funktionalität gar nicht nutzen. Komponenten, die die vorgegebenen Schnittstellen anbieten möchten, müssen mehr implementieren, als sie eigentlich wollen (oder dies nicht tun und das LSP mit einer NotImplementedException verletzen). Tests von Komponenten, die Abhängigkeiten auf große Schnittstellen haben, werden schwieriger, da viele eigentlich unnötige Funktionen gestubbt oder gemockt werden müssen. Auch eine "große" Klasse kann mehrere "kleine" Interfaces anbieten und damit wohldefinierte "Fenster" auf ihre Funktionalität anbieten. Beispiel Die Methode printEmployees() im folgenden Beispiel erwartet eine List, obwohl sie diese lediglich durchlaufen können muss. Durch das "zu große" Interface kann sie darüber hinaus jetzt auch die Liste leeren, was für den Aufrufer unschöne Konsequenzen hat. public class ISP { public static void main(String[] args) { List employees = new ArrayList(); employees.add(new Employee("Stefan", "Macke")); employees.add(new Employee("Karl", "Meier")); employees.add(new Employee("Hans", "Georg")); printEmployees(employees); System.out.println(employees.size()); } private static void printEmployees(List employees) { for (var employee : employees) { System.out.println(employee); } employees.clear(); } } // Ausgabe: // Stefan Macke // Karl Meier // Hans Georg // 0 Die Methode sollte stattdessen das kleinstmögliche Interface benutzen, das sie braucht, um ihre Aufgabe erfüllen zu können. In Java wäre das z.B. ´Iterable´: private static void printEmployees(Iterable employees) { for (var employee : employees) { System.out.println(employee); } } Der restliche Code funktioniert wie vorher, aber es sind nun keine modifizierenden Aufrufe mehr möglich, da das kleinere Interface die Methoden nicht anbietet. Dynamisch typisierte Sprachen haben hier einen Vorteil, da sie dank Duck-Typing ohnehin kaum Basisklassen oder gar Interfaces benötigen. Sie rufen einfach nur die Methoden auf, die sie brauchen. Das kann allerdings auch zu impliziten Abhängigkeiten führen, die nicht vom Compiler geprüft werden, da der Zugriff auf die Klasse nicht durch ein Interface "geschützt" ist. Vorteile Kleinere Komponenten machen uns das Entwicklerleben einfach: klare Zuständigkeiten, einfachere Tests, weniger unnötige Abhängigkeiten. Durch klar definierte Schnittstellen wird die fehlerhafte oder unerlaubte Verwendung von Funktionen verhindert. Kleinere Schnittstellen entsprechen dem Single Responsibility Principle. Nachteile Insgesamt steigt die Anzahl der Typen im System durch kleine Schnittstellen an (siehe auch SRP). Literaturempfehlungen Es wird schon langweilig: Auch beim vierten SOLID-Prinzip empfehle ich wieder Uncle Bobs Clean Code*. * Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Interface Segregation Principle ArticleS.UncleBob.PrinciplesOfOod (Artikel von Uncle Bob, Beispiel in C++) Interface-Segregation-Prinzip – Wikipedia Das Interface Segregation Principle (Deutsches Beispiel in C#) Zusammenfassung Was das Interface Segregation Principle bedeutet Wenn ich eine Schnittstelle für meinen Code auswähle, soll sie genau die Methoden anbieten, die er für seine Aufgabe braucht. Das Interface Segregation Principle (ISP) ist das vierte der fünf SOLID-Prinzipien. Es fordert, die Schnittstelle zwischen einer Klasse und ihrer Abhängigkeit möglichst klein zu halten. Für dich bedeutet das: Wähle ein Interface, dessen Methoden zur jeweiligen Aufgabe passen. Jede zusätzliche Methode erweitert die Möglichkeiten des aufrufenden Codes und schafft eine weitere Abhängigkeit. Beispiel: Eine Liste durchlaufen Ich möchte eine Liste mit Mitarbeiter:innen durchlaufen und ihre Daten ausgeben. Erwartet meine Methode dafür das Java-Interface List, erhält sie auch Zugriff auf Methoden wie clear(). Damit könnte sie die übergebene Liste leeren, obwohl ihre Aufgabe lediglich darin besteht, die Elemente zu durchlaufen. Außerdem erschweren die vielen angebotenen Methoden den Überblick. Für diese Aufgabe reicht Iterable aus. Über dessen Methode iterator() erhält mein Code den Iterator, den er zum Durchlaufen braucht. Die Schnittstelle bietet ihm damit genau den passenden Zugriff. Dadurch kann ich auch andere Objekte übergeben, die Iterable implementieren. Eine selbst geschriebene Collection-Klasse muss dafür lediglich die entsprechende Methode anbieten. Mein Code kann so mit weiteren Datenstrukturen arbeiten. Fachlich passende Schnittstellen bilden Bei einem Repository, das Benutzer:innen und Artikel sowie Bestellungen aus der Datenbank lädt, treffen mehrere fachliche Aufgaben zusammen. Code, der eine Bestellung bearbeitet, erhält über eine gemeinsame Schnittstelle möglicherweise auch Zugriff auf Methoden für Benutzer:innen. Solche großen Interfaces können darauf hinweisen, dass das Single Responsibility Principle verletzt wird. Die Methoden gehören dann zu unterschiedlichen Aufgaben und lassen sich auf kleinere Schnittstellen verteilen. Das ISP betrifft auch Basisklassen, die zu viele Funktionen anbieten. Ich kann für die einzelnen Aufgaben eigene Interfaces definieren und sie weiterhin in einer gemeinsamen Repository-Klasse implementieren. Der aufrufende Code erwartet jeweils die fachlich passende Schnittstelle. Sie wirkt wie ein kleines Fenster auf die Klasse, durch das nur die benötigten Methoden sichtbar sind. Was große Interfaces nach sich ziehen Wenn sich eine Methode einer großen Schnittstelle ändert, kann davon auch Code betroffen sein, der andere Methoden dieser Schnittstelle aufruft. Im Repository-Beispiel muss der Code für Artikel unter Umständen erneut kompiliert werden, sobald sich die gemeinsame Schnittstelle für Benutzer:innen ändert. Getrennte Interfaces begrenzen solche Abhängigkeiten und den damit verbundenen Aufwand. Auch die Klasse, die ein Interface implementiert, muss alle vorgegebenen Methoden anbieten. Braucht sie fachlich nur einen Teil davon, entstehen zusätzliche Methoden ohne sinnvolle Aufgabe. Wer dort lediglich Exceptions wirft, riskiert einen Verstoß gegen das Liskov Substitution Principle: Der Compiler erkennt die Methode, beim Aufruf zur Laufzeit scheitert sie. Tests mit kleinen Interfaces Wenn ich eine Abhängigkeit im Test durch einen selbst geschriebenen Stub oder Mock ersetze, muss dieser alle Methoden des Interfaces implementieren. Bei einer großen Schnittstelle entsteht dadurch viel Boilerplate-Code für Methoden, die mein Test gar nicht aufruft. Mit einer kleinen Schnittstelle beschränkt sich diese Arbeit auf die benötigten Methoden. Moderne Mocking-Frameworks können die Methoden automatisch bereitstellen und nehmen dir damit einen Teil dieses Aufwands ab. Duck Typing und sichtbare Abhängigkeiten Beim Duck Typing kann ich einer Methode ein Objekt übergeben, das die aufgerufenen Methoden bereitstellt. Ein ausdrücklich implementiertes Interface ist dafür entbehrlich. Das erleichtert es, passende Objekte zu übergeben. Welche Methoden der aufrufende Code erwartet, lässt sich dabei erst durch einen Blick in den Code erkennen. Fehlt eine davon, zeigt sich der Fehler zur Laufzeit....
27 Minuten
Im fünften Wissenshäppchen geht es um das Liskov Substitution Principle. TL;DR Am Liskov Substitution Principle (LSP) zeige ich dir, worauf du beim Austauschen von Klassen achten musst: Subklassen und Klassen, die ein Interface implementieren, müssen das erwartete Verhalten auch zur Laufzeit einhalten. Unerwartete Exceptions oder Seiteneffekte können bestehenden Code beschädigen, obwohl der Compiler alle geforderten Methoden akzeptiert. An Quadrat und Rechteck wird das greifbar; Unit-Tests helfen dir, solche Fehler zu entdecken. Kleine, passende Interfaces erleichtern es dir, den vereinbarten Vertrag vollständig zu erfüllen. Kapitelmarken [00:00:20] Das dritte SOLID-Prinzip und Barbara Liskov [00:01:11] Austauschbare Klassen und Polymorphie [00:02:01] Was der Compiler bei Methoden prüft [00:03:38] Erwartetes Verhalten zur Laufzeit [00:04:58] Definition des Liskov Substitution Principle [00:06:51] LSP-Verletzung durch eine NotImplementedException [00:09:09] Fehler mit Unit-Tests entdecken [00:10:14] Quadrat und Rechteck als Vererbungsbeispiel [00:14:18] Getrennte Klassen für Quadrat und Rechteck [00:15:07] Ruby-Beispiel: Employee, Developer und Überstunden [00:17:42] Prinzipien bewusst anwenden [00:18:13] Verständlicher Code durch erwartbares Verhalten [00:19:12] Prinzip der geringsten Überraschung [00:20:12] Einschränkungen bei der Vererbung [00:21:19] Unveränderbare Listen und passende Abstraktionen [00:23:02] Zusammenhang mit dem Interface Segregation Principle [00:24:14] Rückblick auf das LSP [00:25:46] Shownotes, Code-Beispiele und Buchempfehlung Inhalt Das LSP ist das dritte der fünf SOLID-Prinzipien. Es wurde 1987 von Barbara Liskov definiert, die ihm auch seinen Namen gab: Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it. Man könnte sagen, dass dies quasi die Grundanforderung ist, um Polymorphie zu ermöglichen. Denn überall dort, wo eine Basisklasse oder ein Interface erwartet wird, müssen auch alle abgeleiteten bzw. implementierenden Klassen erlaubt sein. Dies ist in den heutigen Programmiersprachen auch der Fall und der Compiler prüft dies (statisch). Aber das LSP geht noch einen Schritt weiter und fordert auch zur Laufzeit ein korrektes Verhalten. Erklärung Subklassen müssen sich so verhalten, wie es von ihren Basisklassen erwartet wird. Dies gilt auch für Interfaces und ihre Implementierungen. Statisch ist das kein Problem: Der Compiler prüft, ob alle geforderten Methoden von den Subklassen bzw. implementierenden Klassen angeboten werden. Die korrekte Verhaltensweise der Implementierung in den Subklassen bzw. implementierenden Klassen kann jedoch nicht statisch geprüft werden. Hierfür ist der Entwickler zuständig, um das LSP nicht zu verletzen. Wenn beispielsweise eine Subklasse in einer überschriebenen Methode eine NotImplementedException wirft, anstatt sie zu implementieren, wird das LSP verletzt. Aber auch unerwartete Nebeneffekte der Implementierungen in überschriebenen Methoden verletzten das LSP (Beispiel: Square erbt von Rectangle und setzt beim Aufruf von setA() auch die Seite b auf den gleichen Wert). Beispiel Die Basisklasse Employee gibt die Methode work_overtime() vor, die damit in allen Subklassen (Manager und Developer) zur Verfügung steht. Somit kann das Project gerade noch erfolgreich fertiggestellt werden. class Employee def work_overtime puts "Working in the evening and on weekends..." end end class Manager < Employee end class Developer < Employee end class Project def finish(employees) employees.each { |e| e.work_overtime } "Project done" end end puts Project.new.finish([Manager.new, Developer.new]) # Working in the evening and on weekends... # Working in the evening and on weekends... # Project done Aber was passiert, wenn sich der Developer zwar formell an den "Vertrag" seiner Basisklasse hält, die Methode work_overtime() aber wie folgt überschreibt? class Developer < Employee def work_overtime raise "Sorry, I use XP and adhere to the 40 hour workweek" end end puts Project.new.finish([Manager.new, Developer.new]) # Working in the evening and on weekends... # Traceback (most recent call last): # 4: from ./LSP.rb:23:in `' # 3: from ./LSP.rb:18:in `finish' # 2: from ./LSP.rb:18:in `each' # 1: from ./LSP.rb:18:in `block in finish' # ./LSP.rb:12:in `work_overtime': Sorry, I use XP and adhere to the 40 hour workweek (RuntimeError) Autsch! Das Project ist wohl zum Scheitern verurteilt! ;-) Es hatte ja keine Ahnung, dass man Developer nicht zu Überstunden verdonnern kann, denn das geht ja schließlich bei allen Employees... Vorteile Der Code wird deutlich besser nachvollziehbar, da keine unerwarteten Fehler zur Laufzeit auftreten, obwohl laut Compiler alles ok ist. Klassen verhalten sich so, wie man es von ihnen erwarten würde ("Principle of Least Astonishment"), und überraschen den Entwickler nicht. Nachteile Die Möglichkeiten der Vererbung werden ein wenig eingeschränkt. Literaturempfehlungen Auch beim dritten SOLID-Prinzip empfehle ich wieder Uncle Bobs Clean Code*. * Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Liskov Substitution Principle ArticleS.UncleBob.PrinciplesOfOod (Artikel von Uncle Bob, Beispiel in C++) Liskovsches Substitutionsprinzip – Wikipedia Zusammenfassung Was das Liskov Substitution Principle verlangt Mit dem Liskov Substitution Principle (LSP) behandle ich das dritte SOLID-Prinzip. Es wurde 1987 von der Entwicklerin Barbara Liskov definiert und trägt ihren Namen. "Substitution" bedeutet "Ersatz". Wo dein Code eine Basisklasse erwartet, muss er auch mit einem Objekt einer abgeleiteten Klasse korrekt arbeiten können. Dasselbe gilt für Interfaces und die Klassen, die sie implementieren. Der aufrufende Code soll dabei unabhängig davon bleiben, welche konkrete Klasse er erhält. Für dich als IT-Azubi gehört dieser Zusammenhang zur Polymorphie, die auch in der Abschlussprüfung vorkommt. Das LSP verlangt, dass die austauschbaren Objekte das erwartete Verhalten zur Laufzeit einhalten. Was der Compiler prüft In den betrachteten Sprachen Java und C# prüft der Compiler, ob eine konkrete Klasse die geforderten abstrakten Methoden mit passenden Signaturen implementiert. Fehlen solche Methoden, muss die Klasse selbst abstrakt bleiben oder der Code lässt sich nicht kompilieren. Ob eine Methode fachlich das Erwartete tut, liegt bei dir als Entwickler:in. Eine vorhandene Methode kann zur Laufzeit unerwartete Seiteneffekte auslösen oder eine Exception werfen, die der aufrufende Code gar nicht berücksichtigt. Beispiel: Eine Methode wirft eine Exception In meinem ersten Beispiel überschreibe ich eine abstrakte Methode und hinterlege darin lediglich eine NotImplementedException. Damit ist die Methode für den Compiler vorhanden. Beim Aufrufen erwartet der bestehende Code, dass die vereinbarte Aufgabe ausgeführt wird. Durch die unerwartete Exception kann das Programm abbrechen, wenn eine passende Fehlerbehandlung fehlt. Die Subklasse verletzt damit das LSP. Mit Unit-Tests kannst du solche Fehler entdecken. Ohne Tests zeigt sich das Problem möglicherweise erst beim Ausführen des Programms, wodurch es aufwendiger und teurer wird, den Fehler zu beheben. Michael Feathers bezeichnet Code ohne Unit-Tests als Legacy-Code. Beispiel: Quadrat und Rechteck Für das geometrische Beispiel lasse ich Square von Rectangle erben. Die Klasse Rectangle bietet mit SetA und SetB zwei Setter an, über die sich die beiden Seitenlängen unabhängig voneinander ändern lassen. Ein Quadrat muss gleich lange Seiten behalten. Seine Setter ändern deshalb jeweils beide Werte. Wenn du SetA aufrufst, wird auch B angepasst. Code, der mit Rectangle arbeitet, erwartet beim Setzen von A, dass B unverändert bleibt. Ein entsprechender Unit-Test schlägt mit einem Square fehl. Auch produktiver Code kann durch diesen Seiteneffekt falsche Ergebnisse liefern. Für dieses Modell empfehle ich getrennte Klassen für Quadrat und Rechteck, gegebenenfalls mit einer gemeinsamen Basisklasse für geometrische Formen. Eine direkte Vererbungsbeziehung in umgekehrter Richtung passt ebenfalls nicht zu dem beschriebenen Verhalten. Beispiel: Überstunden im Klassenmodell Im Ruby-Beispiel aus meinen Shownotes erben Manager und Developer von Employee. Über WorkOvertime kann der aufrufende Code Überstunden für alle Mitarbeiter:innen anfordern. Die Klasse Developer folgt im Beispiel der 40-Stunden-Woche aus Extreme Programming und verweigert die Methode mit einer Exception. Dadurch verletzt sie das Verhalten, das der Code von Employee erwartet. Verständlicher Code und weniger Überraschungen Wenn ich mich auf den Vertrag einer Basisklasse oder eines Interfaces verlassen kann, lässt sich mein Code leichter nachvollziehen. Besondere Regeln einzelner Subklassen muss ich dann beim Aufrufen nicht berücksichtigen. Dazu passt das Principle of Least Astonishment, das Prinzip der geringsten Überraschung. Verständlicher Code und erwartbares Verhalten verringern die Wahrscheinlichkeit von Fehlern. Das LSP begrenzt, welches Verhalten du in einer Subklasse verändern darfst. SOLID-Prinzipien verlangen grundsätzlich eine bewusste Entscheidung über ihren Einsatz und den damit verbundenen Aufwand. Beim LSP gewichte ich die Vorteile höher als diese Einschränkung. Passende Interfaces wählen An einer unveränderbaren Liste beschreibe ich ein weiteres Problem: Im Beispiel erwartet der aufrufende Code, über das gewählte Listen-Interface Elemente löschen zu können....
22 Minuten
Mein viertes Wissenshäppchen hat das Open Closed Principle zum Thema. TL;DR Mit dem Open-Closed-Principle (OCP) erweitere ich Software um neue Funktionen, während der bestehende Code unverändert bleibt. Durch Polymorphie und Interfaces kannst du zusätzliche Klassen einbinden; typabhängige Abfragen mit instanceof oder switch weisen auf Stellen hin, die bei jeder neuen Klasse angepasst werden müssen. Das Prinzip senkt das Risiko, Fehler in funktionierenden Code einzubauen. Wie viel zusätzliche Architektur dafür sinnvoll ist, wäge ich anhand der erwarteten Anforderungen und des YAGNI-Prinzips ab. Kapitelmarken [00:00:00] Einstieg in das Open-Closed-Principle [00:00:53] Bedeutung des OCP und Motivation [00:02:42] Ursprung bei Bertrand Meyer [00:03:33] Vererbung und Polymorphie [00:04:27] Grenzen der Vererbung [00:05:41] Das OCP mit Interfaces umsetzen [00:07:14] Typabhängige Abfragen als Code Smell [00:10:34] Replace Conditional with Polymorphism [00:11:16] Beispiel: Tiere durch eigene Methoden beruhigen [00:13:24] Ruby und Duck Typing [00:14:21] Beispiel: Boni für Mitarbeiter:innen berechnen [00:15:43] Vorteile des Open-Closed-Principle [00:17:05] Overengineering vermeiden und YAGNI beachten [00:18:55] Rückblick auf das OCP [00:20:50] Codebeispiele und weiterführende Quellen Inhalt Das OCP ist das zweite der SOLID-Prinzipien. Es wurde vor Robert "Uncle Bob" Martin bereits 1988 von Bertrand Meyer definiert: Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. Ursprünglich ging es darum, durch Vererbung die Anpassung ("modification") bereits bestehender Klassen zu verhindern, indem Subklassen abgeleitet werden, die die vorhandene Funktionalität erweitern ("extension"). Heutzutage ist Vererbung aber eher nicht mehr so gerne gesehen, da es eine starke Kopplung an die Basisklasse zur Folge hat, was das Design inflexibel macht. Stattdessen sollte man besser von vornherein Interfaces mit potentiell verschiedenen Implementierungen einsetzen. Erklärung Bei Änderungen an einem Programm sollen bestehende Komponenten bestenfalls gar nicht angepasst werden müssen, da diese Anpassungen Fehler nach sich ziehen können, die auch das bereits bestehende Verhalten betreffen. Neue Funktionalität wird dem Programm immer durch neue Komponenten hinzugefügt, also z.B. indem neue Klassen oder Methoden ergänzt werden. Fallunterscheidungen auf Basis von Typen (z.B. mit instanceof in Java) oder Enumerations (insb. wenn diese in einem switch verwendet werden) sind oft ein Hinweis auf Verletzung des OCP und sollten durch Polymorphie ersetzt werden. Beispiel class Manager end class Developer end class Payroll def self.calculate_bonus(employee) if employee.is_a?(Manager) return 1000 end if employee.is_a?(Developer) return 500 end end end puts Payroll.calculate_bonus(Manager.new) # 1000 puts Payroll.calculate_bonus(Developer.new) #500 Wenn diese Bonusberechnung um einen neuen Mitarbeitertyp Administrator erweitert werden soll, muss die bestehende Implementierung von calculate_bonus() angepasst werden: def self.calculate_bonus(employee) if employee.is_a?(Manager) return 1000 end if employee.is_a?(Developer) return 500 end if employee.is_a?(Administrator) return 250 end end Stattdessen sollte von Anfang an die Berechnung des Bonuses an die Mitarbeiterklassen delegiert werden. class Manager def bonus 1000 end end class Developer def bonus 500 end end class Payroll def self.calculate_bonus(employee) employee.bonus end end puts Payroll.calculate_bonus(Manager.new) # 1000 puts Payroll.calculate_bonus(Developer.new) # 500 Dadurch ist eine spätere Erweiterung um neue Mitarbeitertypen ohne Anpassung des bisherigen Codes möglich: class Administrator def bonus 250 end end puts Payroll.calculate_bonus(Administrator.new) # 250 In dynamisch typisierten Sprachen (wie im Beispiel Ruby) ist das OCP übrigens meist noch einfacher umzusetzen als in statisch typisierten, da durch das Duck-Typing umfangreiche Klassenhierarchien oder Interfaces unnötig werden. Dies sieht man auch im Beispiel oben: Manager und Developer haben keinerlei Beziehung zueinander. Trotzdem funktioniert der Code, da beide Klassen die Methode bonus() anbieten. Vorteile Bei Erweiterungen der Funktionalität sinkt die Wahrscheinlichkeit, Fehler in den bereits funktionierenden Code einzubauen. Klassen behalten ihre Aufgabe "ein Leben lang". Abhängige Klassen können sich darauf verlassen, dass sich die Funktionalität nicht ändert. Erweiterungen sind ggfs. einfacher zu implementieren, da nicht an mehreren Stellen Code angepasst, sondern "nur" neuer Code geschrieben werden muss. Nachteile Meist ist gar nicht im Voraus bekannt, welche Stellen im Code später einmal erweitert werden müssen. Einfach nur noch mit Abstraktionen zu arbeiten, macht den Code aber schwer verständlich. Außerdem verletzten wir damit das YAGNI-Prinzip. Literaturempfehlungen Da Uncle Bob die SOLID-Prinzipien so schön aufgeschrieben hat, kann ich wieder einmal seinen Klassiker Clean Code* empfehlen. * Links Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Open Closed Principle ArticleS.UncleBob.PrinciplesOfOod (Artikel von Uncle Bob, Beispiel in C++) Open-Closed-Prinzip – Wikipedia SOLID – Das Open Closed Principle | Informatik Aktuell (ausführliche Diskussion der Nachteile, Beispiel in C#) SOLID Design Principles Explained – The Open/Closed Principle with Code Examples (Beispiel in Java) Zusammenfassung Was das Open-Closed-Principle bedeutet Wenn du ein bestehendes System um neue Funktionen ergänzt, sollen seine vorhandenen Komponenten unverändert bleiben können. Das Open-Closed-Principle (OCP) beschreibt dieses Ziel mit "offen für Erweiterungen, geschlossen für Änderungen". Es ist das zweite der fünf SOLID-Prinzipien und steht für das O in SOLID. Jeder Eingriff in funktionierenden Code birgt das Risiko, Fehler einzubauen. Indem ich neue Funktionen in zusätzlichen Klassen unterbringe, bleibt das bisherige Verhalten erhalten. Ursprung und Vererbung Bereits 1988 formulierte Bertrand Meyer das Prinzip. Robert C. Martin griff es später im Zusammenhang mit SOLID auf. Die ursprüngliche Idee setzte auf Vererbung: Eine fertige Basisklasse wird durch Unterklassen ergänzt, die zusätzliche Funktionen mitbringen. Durch Polymorphie kann eine Unterklasse überall dort eingesetzt werden, wo die Basisklasse erwartet wird. In meiner Ausbildung empfehle ich Vererbung dann, wenn vorhandener Code wiederverwendet werden soll. Eine Hierarchie aus der Realität allein ist für mich kein ausreichender Anlass. In Java und C# kann eine Klasse nur von einer einzigen Basisklasse erben, wodurch sie sich eng an diese bindet. Das OCP mit Interfaces umsetzen Für Java und C# bevorzuge ich Interfaces als Grundlage. Eine Klasse kann mehrere Interfaces implementieren. Wenn dein bestehender Code mit einem Interface arbeitet, kannst du passende Klassen austauschen oder ergänzen. Für eine neue Funktion schreibst du eine weitere Klasse, die das erwartete Interface implementiert. Der aufrufende Code arbeitet weiterhin mit derselben Schnittstelle, während die neue Klasse das zusätzliche Verhalten mitbringt. Typabhängige Abfragen als Warnsignal Wenn du konkrete Klassen mit instanceof prüfst und davon abhängig unterschiedliche Aktionen ausführst, deutet das auf einen Verstoß gegen das OCP hin. Solche Fallunterscheidungen können in if-Abfragen oder switch-Anweisungen stecken. In meinem Beispiel bekommt eine Methode ein Objekt vom Typ Tier. Prüft sie ausdrücklich auf Hund und Katze, braucht sie beim späteren Hinzufügen eines Pferd einen weiteren Zweig. Damit musst du bestehenden Code ändern. Je mehr solcher Stellen vorhanden sind, desto mehr Stellen musst du bei einer neuen Tierart bearbeiten. Fallunterscheidungen durch Polymorphie ersetzen Martin Fowler beschreibt in seinem Buch Refactoring das passende Vorgehen als Replace Conditional with Polymorphism. Dabei wandert das typabhängige Verhalten in die jeweiligen Klassen. Für das Beispiel aus einer Tierarztpraxis erhält Tier eine Methode beruhige. Die aufrufende Klasse ruft diese Methode am übergebenen Tier auf. Jede konkrete Tierklasse legt selbst fest, wie das Tier beruhigt wird. Ergänzt du später ein Meerschweinchen mit einer eigenen Methode beruhige, kann der bestehende Aufruf damit arbeiten. Ruby und Duck Typing In meinem Ruby-Beispiel genügt es, dass ein übergebenes Objekt die aufgerufene Methode anbietet. Ruby ist dynamisch typisiert; ein ausdrücklich implementiertes Interface ist dafür entbehrlich. Dieses Konzept heißt Duck Typing. Entscheidend ist, ob das Objekt das benötigte Verhalten bereitstellt. Das Beispiel behandelt Boni für Mitarbeiter:innen. Die jeweiligen Klassen für Manager:innen und Entwickler:innen bestimmen ihren Bonus selbst. Auch Administrator:innen erhalten eine eigene Klasse. Die aufrufende Methode fragt den Bonus über get Bonus ab. Eine zusätzliche Klasse für Reinigungskräfte kann denselben Aufruf mit einer eigenen Bonusberechnung unterstützen. Was dir das Prinzip bringt Weil bestehender Code unverändert bleibt, sinkt das Risiko, dort neue Fehler einzubauen. Klassen behalten ihre Aufgaben und ihr Verhalten, sodass sich aufrufender Code weiterhin darauf verlassen kann. Neue Funktionen lassen sich in zusätzlichen Klassen unterbringen. Dadurch entfällt die Suche nach verstreuten Fallunterscheidungen, die du sonst erweitern müsstest. Aufwand und YAGNI abwägen Bei meinen Beispielen lässt sich leicht vorstellen, welche Klassen später hinzukommen. Im Alltag ist oft unklar, welche Teile eines Systems künftig erweitert werden müssen. Zusätzliche Interfaces und Abstraktionsschichten kosten Aufwand und machen den Code schwerer verständlich. Überflüssige Komplexität kann ihrerseits Fehler begünstigen; außerdem kann der
44 Minuten
Ein Interview mit Julian Hirche zum Thema Ausbildung der Ausbilder (AdA) nach Ausbilder-Eignungsverordnung (AEVO) gibt es in der einhundertdreiunddreißigsten Episode des Anwendungsentwickler-Podcasts. TL;DR Mit Julian Hirche bespreche ich, wie du dich auf das Ausbilden vorbereitest und was dich in der AEVO-Prüfung erwartet. Ein AdA-Kurs vermittelt dir pädagogische Methoden und rechtliche Grundlagen, mit denen du IT-Azubis durch ihre Ausbildung begleitest. An seinem Lehrgespräch zu Bubble Sort zeigt Julian, wie offene Fragen zum selbstständigen Denken anregen. Zum Ausbilden gehören außerdem fachliche und persönliche Eignung sowie die Bereitschaft, auf die Bedürfnisse eines Menschen einzugehen. Kapitelmarken [00:00:00] Thema: Ausbildung der Ausbilder:innen [00:01:47] Julian Hirche und sein Team für Bankensoftware [00:03:14] Manuelle Tests und geplante Testautomatisierung [00:04:26] Julians beruflicher Weg in die IT [00:06:41] C#, WinForms und geplante Weboberflächen [00:09:06] Was AdA und AEVO bedeuten [00:10:55] Die vier Handlungsfelder der Ausbildung [00:11:43] Lehrmethoden und offene Fragen im Lehrgespräch [00:13:00] Abendkurs und praktische Übungen [00:14:16] Vier-Stufen-Methode und Lehrgespräch [00:15:37] Bubble Sort als Thema der praktischen Prüfung [00:17:02] Prüfer:innen in der Rolle eines IT-Azubis [00:17:41] Lehrmethoden passend zur Lerngruppe wählen [00:18:46] Ausbildungsstart und Ausbildungsende gestalten [00:20:13] Rechtliche Grundlagen und Jugendarbeitsschutz [00:21:06] Feedback geben und als Vorbild begleiten [00:22:49] Warum Julian den Ausbilderschein gemacht hat [00:24:19] Persönliche und fachliche Eignung zum Ausbilden [00:26:30] Ablauf der praktischen AEVO-Prüfung [00:28:10] Die Ausbildungssituation auf 15 Minuten abstimmen [00:29:08] Noten und schriftliche Multiple-Choice-Prüfung [00:30:10] Fallbeispiele und Fragen aus der Ausbildungspraxis [00:31:23] Wie vorbereitet sich Julian für die Praxis fühlt [00:31:56] Lehrkräfte und Teilnehmer:innen im AdA-Kurs [00:34:01] Lehrmethoden mit anderen Berufsgruppen erproben [00:35:19] Erfahrungen mit dem Kurs und dem dualen Ausbildungssystem [00:37:41] Was gute Ausbilder:innen ausmacht [00:39:07] Buchtipps: Robert C. Martin und Informatik Macchiato [00:40:37] Clean Code im beruflichen Alltag [00:42:06] Kontakt zu Julian Hirche [00:43:13] Shownotes und Feedback Inhalt Allgemeines zur Person Wie ist dein Name und wo arbeitest du (falls gewünscht)? Julian Hirche, 34 Jahre alt Ich arbeite in Hamburg in einem Unternehmen, das Software für Banken entwickelt. Ich bin dort Teamleiter von 3 Entwicklern und 2 Testern. An welchen Projekten arbeitest du zur Zeit in deinem Tagesjob? Wir erstellen Reports für Banken und haben z.B. eine Drag/Drop-Oberfläche zum "Klicken" von Reports programmiert. Außerdem machen wir Reporting mit SQL und PL/SQL oder Datenexport nach Excel. Wir haben leider noch keine automatische Testabdeckung. Daher gibt es viele manuelle Tests. Wir planen aber, das zu automatisieren. Wir haben "richtige" Tester, die z.B. Akzeptanztests durchführen. Wie bist du zur Informatik bzw. Softwareentwicklung gekommen? Ich programmiere seit ich 8 Jahre alt war. Bin mit dem C64 angefangen. Programmieren fand ich spannender als Spielen. Im Jahr 2000 habe ich die Realschule abgeschlossen und wollte Fachinformatiker werden, habe aber keinen Ausbildungsplatz gefunden. Das Arbeitsamt hat mir eine Ausbildung zum Mechatroniker empfohlen. Danach habe ich dann mehrere Jahre aks Mechatroniker gearbeitet, aber letztlich gekündigt, weil ich in die IT wollte. Welche Ausbildung bzw. welches Studium hast du im Bereich der Informatik absolviert? Ich habe zunächst eine Informatikassistentenausbildung in Wedel absolviert an einer privaten Fachhochschule. Dort habe ich auch viel zusammen mit Bachelor-Studenten gemacht. Mit welcher/n Programmiersprache/n arbeitest du im Alltag? Hauptsächlich C#. Früher auch Java oder PHP. Früher meinte ich mal "Microsoft ist doof", aber inzwischen gefällt mir C# sehr gut. Auch .NET Core unter Linux ist eine tolle Sache. Wir entwickeln aktuell mit React im Frontend. Was ist deine Lieblingsprogrammiersprache und warum? C#, weil man mit ihr viele coole Sachen machen kann. Ausbildereignungsprüfung, AdA und AEVO Was heißen die ganzen Abkürzungen: AdA, AEVO? AEVO ist die Ausbilder-Eignungsverordnung, die insb. die berufs-/arbeitspädagogische Eignung der Ausbilder definiert. AdA steht für Ausbildung der Ausbilder, also den Weg, wie man zum Ausbilder wird (z.B. durch entsprechende Kurse). Wer darf einen Ausbilderschein machen? Welche Voraussetzungen gibt es? Die Person muss persönlich (z.B. keine Vorstrafen) und fachlich (z.B. selbst die Ausbildung gemacht oder 5 Jahre im Beruf gearbeitet) geeignet sein. Warum hast du den Ausbilderschein gemacht? Ich gebe mein Wissen gerne weiter. Ich war schon lange im Internet aktiv und nutze viele Foren. In unserem Betrieb finden wir keine Mitarbeiter, warum also nicht einfach selbst ausbilden? Letztes Jahr haben wir es aber aufgrund von Projekten leider nicht geschafft, jemanden einzustellen. Wie und wo hast du den Ausbilderschein gemacht (z.B. Kurs, Selbststudium)? Ich habe einen Kurs besucht. Über 2 Monate hinweg habe ich in der Abendschule die Inhalte gelernt. Ich hätte alternativ auch 2 Wochen in Vollzeit lernen können. Die Dozenten waren Lehrer an der Schule, die auch in dem Bereich gearbeitet haben. Wir waren 20 Teilnehmer. Ich war der einzige ITler. Die anderen waren aus den Büroberufen oder dem Einzelhandel. Viele haben den Kurs im Rahmen ihrer Meister-Ausbildung gemacht. Braucht man den Schein überhaupt (noch)? Welche gesetzlichen Grundlagen gibt es? Nach AEVO muss ein Unternehmen einen Ausbilder haben, wenn es ausbilden will. Welche Inhalte wurden in deinem Kurs vermittelt? Was hast du gelernt? Was konntest du konkret für deinen Berufsalltag mitnehmen? Die Inhalte haben mit den konkreten Berufen nichts zu tun. Sie sind berufsunabhängig. Wir sind z.B. das komplette BIBB durchgegangen, aber auch das JAschG war wichtig. Auch der Sinn und die Vorteile der Ausbildung wurden besprochen. Es gibt grundsätzlich 4 Handlungsfelder, die man lernt: Ausbildung prüfen, vorbereiten, durchführen und abschließen. Zur Vorbereitung zählen z.B. das Planen der Probezeit, Literatur raussuchen, den ersten Arbeitstag gestalten. Das Abschließen umfasst insb., den Azubi durch die Prüfung zu bringen, aber auch das Erstellen eines Arbeitszeugnisses und die Gestaltung des Arbeitsvertrags bei Übernahme. Beim Durchführen der Ausbildung haben wir uns u.a. die verschiedenen Lehrmethoden angeschaut: 4-Stufen-Modell, Lehrgespräch, Projektarbeit. Aber auch das Feedback geben mit einem Evaluierungsbogen haben wir gelernt, z.B. ob der Azubi wissbegierig und pünktlich ist, wie er mit Kollegen umgeht und ob er sein Arbeitspensum schafft. Das Motivieren von Azubis war auch Bestandteil des Kurses und manchmal ist auch ein wenig Erziehung nötig, wenn die Aubis noch jünger sind. Was hat es mit den Lehrmethoden auf sich? Es geht darum, wie man den Azubis Wissen optimal vermittelt. Für Gruppen aus mehreren Azubis und das Vermitteln von Grundlagen eignet sich evlt. Frontalunterricht. Bei tiefergehenden Themen und mehreren Azubis ist vielleicht eher eine Projektarbeit sinnvoll. Die 4-Stufen-Methode aus Erklären, Vormachen, Nachmachen und Wiederholen ist eine Art Schritt-für-Schritt-Anleitung und heute nicht mehr so gerne gesehen. Es sollen eher in einem Lehrgespräch offene Fragen gestellt werden, über die der Azubi das Problem selbst lösen kann. Diese Gespräche haben wir im Kurs auch mit den anderen Teilnehmern gemeinsam geübt. Ich selbst durfte z.B. von einem Paketierer lernen, wie man Pakete platzsparend packt und verklebt. Aus welchen Teilen besteht die Prüfung? Es gibt einen schriftlichen Teil über 180 Minuten und einen mündlichen über 30 Minuten. Wie läuft die Prüfung konkret ab? Die schriftliche Prüfung ist eine Multiple-Choice-Prüfung mit 70 Fragen mit angegebener Anzahl korrekter Antworten. Ähnlich zur IHK-Prüfung gibt es viele fachliche Fragen z.B. zur Länge der Probezeit. Es gibt auch Fallstudien mit Beispielen: Azubi schafft die Prüfung nicht, wie geht es weiter? Welche Lehrmethoden sind sinnvoll bei einzelnen Berufen? Viele rechtliche Fragen. Die mündliche Prüfung besteht aus einem Rollenspiel über 15 Minuten und einem Fachgespräch über 15 Minuten. Eine Präsentation ist optional auch möglich. Dort müsste man dann zeigen, wie man einen Azubi anlernen würde. Im Kurs haben wir die mündliche Prüfung mit den anderen Kursteilnehmern durchgespielt. Man muss genau auf 15 Minuten kommen, also muss die komplette Lerneinheit dann fertig sein. Als Ergebnis bekommt man ein Zeugnis mit Note. Wie lief deine eigene Prüfung ab? Ich habe in einem Lehrgespräch den Bubble-Sort erklärt. Der Azubi musste den Algorithmus selbst finden. Wer war dein Azubi? Ein Prüfer hat den Azubi gespielt. Würdest du den Ausbilderschein weiterempfehlen? Auf jeden Fall! Der Kurs war für mich sehr lehrreich. Unser duales System der Berufsausbildung in Deutschland ist insg. super und sollte weiterverfolgt werden. Bei uns können nicht nur starke Schüler ausgebildet werden. Haupt- oder Realschule reichen auch für eine tolle Ausbildung. Was macht einen guten Ausbilder aus? Ein guter Ausbilder sollte den Azubi nicht als Ressource oder Maschine ansehen, sondern als Menschen akzeptieren. Es sollte z.B. auch bei privaten Problemen helfen und Empathie zeigen. Aus- und Weiterbildung Welche Quellen kannst du für die Aus- und Weiterbildung im Bereich Programmierung empfehlen und warum? Informatik macchiato*. Hier werden für Schüler oder Studenten gut verständlich Informatikprobleme z.B. mit Bildern erklärt. Was ist dein absolutes Lieblingsbuch mit Bezug zur IT/Programmierung und warum? Robert C. Martin: Clean Code*. Das hat mir persönlich sehr viel gebracht. Ich habe gelernt,...