Frameworks

Was ist ein Framework? & Wann wird es eingesetzt?

Wie schon bei den Libraries erwähnt, wirken Framewors im ersten Moment ähnlich zu einer Library. Frameworks sind aber sozusagen eine Struktur/Grundgerüst mit vorgefertigten verschiedenen Materialien, mit dem du dir dein Projekt selbst einfach und schnell aufbauen kannst. Zusätzlich gibt es noch einen weiteren entscheidenden Unterschied, und zwar die sogenannte "inversion of control" (Steuerungsumkehr).

Wird eine Library verwendet ist man selbst für den Ablauf der Anwendung verantwortlich. Das heißt man legt selbst fest, wann und wo die Library aufgerufen werden soll.

Bei einem Framework ist dies selbst für den Ablauf verantwortlich. Es gibt zwar Platz um eigenen Code einzubringen, entscheidet aber selbst wann dieser aufgerufen wird.

Hier ist ein Beispiel mit jQuery (einer Bibliothek) und Vue.js (einem Framework):

Stell dir vor, wir möchten eine Fehlermeldung anzeigen, wenn ein Fehler vorliegt. In unserem Beispiel klicken wir auf eine Schaltfläche und tun so, als ob ein Fehler auftritt.

Mit jQuery:

Code_jQuery

Hier verwenden wir jQuery. Wir sagen dem Programm genau wo wir es brauchen. Das heißt nicht, dass für jQuery-Funktionen bestimmte Eingaben nicht erforderlich sind, wenn wir sie aufrufen, aber jQuery selbst ist eine Bibliothek dieser Funktionen. Wir sind verantwortlich.

Mit Vue.js:

Code_Vue.js freecodecamp.org

Bei Vue.js müssen wir sozusagen die Lücken füllen. Der Vue-Konstruktor ist ein Objekt mit bestimmten Eigenschaften. Es sagt uns was es braucht und Vue.js entscheidet dann wann es es braucht. Vue kehrt die Steuerung des Programms um. Wir stecken unseren Code rein und Vue übernimmt die Verantwortung.

Frameworks für individuelle Problemstellungen

Frameworks bieten einen Basis-Bausteinkasten und nehmen somit Einfluss auf die Design-Struktur unseres Programms. Es gibt für viele Einsatzmöglichkeiten passende Framework-Typen:

Web-Frameworks:
mit Zuschnitt auf die Entwicklung und Programmierung dynamischer Web Sites und Web Applikationen
Application Frameworks:
als Programmier-Gerüst für Anwendungen mit spezifischen Strukturen und Funktionen
Komponenten-Frameworks:
mit speziellem Umgebungsrahmen für die Programmierung und finale Einbindung von Programm-Paketen
Coordination Frameworks:
mit der Möglichkeit der Einrichtung von Geräte-Interaktionen, das heißt einer Abfolge zu steuernder Ablaufschritte
Domain Frameworks:
als Programmier-Rahmen für definierte Problembereiche
Class Frameworks:
mit der Aufgabenstellung einer Zusammenfassung von „Klassen“ und „Methoden“, im Sinne einer optimalen Unterstützung des Programmierers bei der Implementierung spezifischer Anwendungen
Test Frameworks:
zum Testen entwickelter Software Programme. Als klassische Beispiele sind „Selenium oder Cypress“ für den Test von Web Applikationen und „JUnit“ für den Test von Modulen zu nennen
Wofür werden Js-Frameworks verwendet?
  • Webseiten erstellen
  • Front-End App Entwicklung
  • Back-End App-Entwicklung
  • Hybride App-Entwicklung
  • Ecommerce Anwendungen
  • Modulare Skripte bauen, zum Beispiel Node.js
  • DOM manuell aktualisieren
  • Automatisieren von sich wiederholenden Aufgaben mit Templates und 2-Wege-Bindung
  • Videospiele entwickeln
  • Bildkarussells erstellen
  • Codes testen und debuggen
  • Module bündeln

Auf dieser Seite findest du viele verschiedene Frameworks.

Angular:

Angular ist ein Anwendungsdesign-Framework und eine Entwicklungsplattform zum Erstellen effizienter und anspruchsvoller Single-Page-Apps. Zudem wird es nicht mit JavaScript, sondern Typescript aufgebaut.

Was kann Angular?
  • Es ist ein komponentenbasiertes Framework zum Erstellen skalierbarer Webanwendungen
  • Es ist eine sammlung gut intergierter Bibliotheken, die viele Funktionen abdecken. Wie bspw. Routing, Formularverwaltung, Client-Server-Kommunikation usw.
  • Es hat eine Reihe von Entwicklertools, mit denen der Code einfacher entwickelt, erstellt, getestet und aktualisiert werden kann
Hier sind Beispiele und Insights aus dem Tour of Heroes Tutorial von Angular:

Kapitel 1

Im ersten Kapitel geht es um die Grundstruktur des Helden-Editors:
  • Mit der CLI (Command Line Interface) wurde als erstes die HeroesComponent angelegt.
  • In der app.component.html wurde die HeroesComponent eingetragen um diese anzeigen zu lassen. Die AppComponent ist sozusagen die Anzeige für alle Componenten. Wenn hier eine Component eingetragen wird kann über den CLI Befehl "ng serve" diese auf dem lokalen Server angezeigt werden.
  • Durch die UpperCasePipe im <h2> in der heroes.component.html werden die Heronamen immer in Großbuchstaben geschrieben.
  • Durch ngModel wurde eine Verbidnung von hero.name mit der Textbox hergestellt. ([(ngModel)] ist die bidirektionale Datenbindungssyntax von Angular.) Das heißt hier fließen die Daten in beide Richtungen, sodass die hero.name Eigenschaft an die Textbox und wieder zurück gegeben werden kann.
  • Durch den Import von "FormsModule" im AppModule kann die ngModel Direktive aufgerufen werden. Das heißt hierdurch wird das App-Modul erstellt und dies enthält dann alle Abhängigkeiten und Komponenten. Durch laden des Moduls wird der AppComponent gestartet.

Kapitel 2

Im zweiten Kapitel geht es um die Liste der Heroes die ausgewählt werden können:
  • Durch eine Mock-Datei "mock-heroes.ts" wurde eine Liste an Heroes generiert.
  • Damit die Nutzer:innen einen Hero auswählen kann wird diese Liste angezeigt. Hierfür wurde "*ngFor" verwendet. Dies ist eine "Repeater-Direktive" von Angular ähnlich wie eine For-Schleife wiederholt er in hier das Host-Element für jedes Element in der Liste. <li> ist das Host-Element. Die Klasse heroes enthält die Liste der "Helden" aus der HeroesComponent Klasse. Das aktuelle Heldenobjekt ist in "hero" enthalten und wird durch das *ngFor für jede Iteration in der Liste angezeigt.
  • (click)="onSelect(hero)" ist ein Besipiel für die event binding Syntax von Agular. Hier wird ein Klick-Event auf einen Hero vorgenommen. Das Event wird in der heroes.component.ts als Methode definiert (event handler). Zunächst soll kein Hero ausgewählt sein, bis der/die Nutzer:in auf einen Hero klickt.
  • Mit "*ngIf" in der heroes.component.html wird nun definiert, wann ein Hero ausgewählt (selectedHero) ist und wann nicht. Ebenfalls wie bei *ngFor ist *ngIf ähnlich der If-Bedingung. Sprich wenn kein Hero ausgewählt ist zeige keine Details an, ist ein Hero ausgewählt zeige die Details des Hero's.
  • Als letztes wurden Klassenanbindungen (class binding) zu den jeweiligen Elementen die eine andere Klasse haben sollen wenn sie bspw. ausgewählt sind, hinzugefügt. Im heroes.componen.css wurden hierfür Styles für die verschiedenen States der Hero's angelegt.

Kapitel 3

Im dritten Kapitel geht es darum verschiedene Teile einer Componente auszulagern um für jede Funktion/Darstellung einzelne Feature-Componenten zu haben:
  • Es wurde eine neue Componente erstellt mit dem Namen "hero-detail.component". Diese dient der Anzeige der Herodetails, hier wurde also lediglich der Detailpart aus der hero.component in eine extra Komponente ausgelagert.
  • [hero]="selectedHero" ist ein Angular "property binding", das heißt es wurde der HeroesComponent die Kontolle über die untergeordnete Hero-DetailComponent gegeben. Es sollte somit also jedesmal wenn auf einen Hero geklickt wird das property binding aktualisiert und die Details zu dem Hero angezeigt werden.
  • Damit die Hero-DetailComponent weiß welcher Hero gemeint ist wird "@Input() hero?: Hero;" in die hero-detail.component.ts hinzugefügt. Somit werden Daten zwischen den Eltern- und Kind-Komponenten geteilt. --> Über @Output kann die Kind-Komponente Daten an die Eltern-Komponente schicken.

Kapitel 4

Im vierten Kapitel geht es darum verschiedene Services bereit zu stellen. Diese Services können alle Anwendungsklassen benutzen um Helden zu erhalten. Anstatt diesen Dienst über das Stichwort "new" zu erstellen, wird dies über die Angular "dependency injection" im Konstruktor der HeroesComponent eingefügt:
  • Zunächst wird ein Angular Service erstellt mit dem Namen "hero.service.ts". Durch hinzufügen der heroService Parameter im Konstruktor der HeroesComponent mit "constructor(private heroService: HeroService) {}" werden diese injiziert. Wenn Agular jetzt eine HeroesComponent erstellt, setzt das Dependency Injection system die heroService Parameter als Instanz des HeroServices.

    @Injectable

    Injectables markieren die Klasse als "Teilnehmer" des Dependency Injection systems. Das heißt der Injektor erstellt Dependencies (Abhängigkeiten) und verwaltet einen Container mit dependency instances die er nach Möglichkeit wiederverwenden kann. Ein provider ist ein Objekt, das einem Injektor mitteilt, wie eine dependency abgerufen oder erstellt wird. Damit in Angular die Dienste aufgerufen werden können müssen diese im Konstruktor der Komponente aufgerufen werden. Injectable and Dependency Injection
  • Der Konstuktor sollte so wenig wie möglich machen, deshalb wird mit getHeroes() im ngOnInit Lifecycle-Hook aufgerufen. Angular soll dann, nach dem er eine Instanz für die HeroesComponent konstruiert hat, ngOnInit() aufrufen.
      
        ngOnInit() { 
          this.getHeroes(); 
        }
        
  • Da wir gerade eine Mock-Datei mit "Scheinhelden" haben lassen sich diese synchron abrufen. Dies soll jedoch in Zukunft asynchron ablaufen, wenn bspw. die Daten über eine Remote-Server abgerufen werden. Somit benötigen wir einen asynchrone Signatur umd diese in Zukunft asynchron abgrufen zu können. Die getHeroes() Methode wird deshalb zu einer Beobachtbaren Methode gemacht:
    
        import { Observable, of } from 'rxjs';
    
        getHeroes(): Observable<Hero[]> {
          const heroes = of(HEROES);
          return heroes;
        }
                    
    of(HEROES) gibt nun ein Observable<Hero[]> zurück, der einen einzelnen Wert ausgibt, nämlich das Array von Scheinhelden. Die HeroService.getHeroes Methode hat bisher Hero[] zurückgegeben. Nun gibt sie Observable<Hero[]> zurück. Das muss so auch noch in der HeroesComponent angepasst werden. Deshalb wird die getHeroes() mit einem subscribe ergänzt:
    
        getHeroes(): void {
          this.heroService.getHeroes()
              .subscribe(heroes => this.heroes = heroes);
        }
                    
    Mit dieser Version der getHeroes() Methode wird auf das Observable gewartet, welches den Array jetzt oder in einigen Minuten ausgibt. Mit der subscribe() Methode wird nun das ausgegebene Array an den Callback übergeben der die heroes Eigenschaft der Komponente festlegt.

    Observables

    Observables (dt. beobachtbar)
    Ein Observer - zu Deutsch Beobachter - behält etwas im Auge und reagiert auf mögliche Änderungen. Möchte ein anderer Anwendungsteil vom Observer über die Änderungen am Observable informiert werden, kann er sich an diesem dazu an- (subscribe) und auch wieder abmelden (unsubscribe). Ein Observable kann dabei abstrakt einfach als Daten-Stream betrachtet werden. Dadurch sind diese auch flexibel einsetzbar und es können beispielsweise mehrere Observables verknüpft oder zusammengefasst werden. Das Prinzip ähnelt stark dem Observer-Pattern und nennt sich Reactive Programming. Angular nutzt als Basis dazu die Observables der ReactiveX Architektur (kurz: RxJS).

    RxJS

    RxJS ist eine Bibliothek für die reaktive Programmierung mit Observables, um die Erstellung von asynchronem oder callback-basiertem Code zu vereinfachen.

  • Services sind eine Möglichkeit, Informationen zwischen Klassen auszutauschen, die sich nicht kennen. Zusätzlich wurde noch der "message.service.ts" erstellt. Der MessageService injiziert an zwei Stellen. Inject in HeroService, der den Dienst zum Senden einer Nachricht verwendet. Inject in MessagesComponent, die diese Nachricht anzeigt und auch die ID anzeigt, wenn der Benutzer auf einen Helden klickt.
  • Damit die Message angezeigt werden kann wurde eine MessageComponent erstellt. Diese gibt aus welcher Hero angeklickt wurde und welche ID er hat. Diese können über den "clear messages" Button gelöscht werden.

Kapitel 5

Im fünften Kapitel geht es darum zwischen zwei Ansichten über das Angular Routing-Module zu wechseln. Es geht also um eine erweiterte Navigation innerhalb der Seite und die verschiedenen Abhängigkeiten dieser zueinander:
  • Der/Die Nutzer:in kann dann wie folgt in der Anwendung navigieren: Navigationsschaubild Tour of Heroes
  • Wie auf der Grafik zu sehen wurde eine weitere Komponente erstellt, das Dashboard. Auf dem Dashboard werden "Top Heroes" angezeigt. Genau wie in der HeroesComponent sollen hier die Details der Heroes angezeigt werden, wenn der/die Nutzer:in auf einen "Top Hero" klickt.
  • Routing

    Das Routing in Angular hilft uns, von einer Ansicht zur anderen zu navigieren, während Benutzer:innen Aufgaben in Web-Apps ausführen. Der Angular-Router ist ein Kernstück der Angular-Plattform. Angular bietet eine vollständige Routing-Bibliothek mit der Möglichkeit, mehrere Router-Ausgänge, verschiedene Pfadanpassungsstrategien, einfachen Zugriff auf Routenparameter und route guards (Routenwächter) zum Schutz vor unbefugtem Zugriff auf Komponenten.
    Ein Router funktioniert wie folgt:
    • er liest die Browser-URL, zu der der/die Benutzer:in navigieren möchte
    • er wendet eine URL-Umleitung an (sofern eine definiert ist)
    • er findet heraus, welcher Router-Zustand der URL entspricht
    • er führt die Guards aus, die im Routerstatus definiert sind
    • er löst die erforderlichen Daten für den Routerstatus auf
  • Im Tutorial wird ein neues Routing-Module erstellt, um im späteren Verlauf zwischen dem Dashboard (kommt noch) und der Heroes Seite zu wechseln. Das Module wird app-routing.module.ts genannt. Es gibt zwei typische Elemente:

    path: eine Zeichenfolge, die mit der URL in der Adressleiste des Browsers übereinstimmt.

    component: die Komponente, die der Router erstellen soll, wenn er zu dieser Route navigiert.
      
        const routes: Routes = [
          { path: 'heroes', component: HeroesComponent }
        ];
        
    In der app.component.html wird die <app-heroes> durch <router-outlet> ausgetauscht. Zusätzlich wird ein routerLink hinzugefügt.
                      
        <a routerLink="/dashboard">Dashboard</a>
        <a routerLink="/heroes">Heroes</a>
                      
                    
  • Damit die verschiedenen Komponenten untereinander verknüpft sidn, werden mehrere routerLinks gesetzt. Dieser verknüpft auch die Detailansicht sowohl mit dem Dashboard als auch mit der HeroesComponent.
Zurück