18. März 2025

Women in Tech: Liima-Frontend neu gedacht – Migration auf Angular

Bei Puzzle ITC arbeiten viele talentierte Frauen in der Technologie. In dieser Blogpostserie begleiten wir sie auf ihrem Weg. Dieses Mal berichten Clara Llorente Lemm und Berivan Bertagna über die Modernisierung von Liima, einem von Puzzle ITC entwickelten Tool zur Verwaltung und zum Deployment von Applikationen bei der Mobiliar. Sie teilen ihre Learnings mit Extreme Programming (XP), neuen Design-Entscheidungen und dem Einsatz von Angular Signals.

Women in Tech
Agile Teams & Project Management
Allgemein
Design & User Experience
Frauen, die in der Tech Branche tätig sind.

Liima Background

Liima (finnisch für Klebstoff) ist ein Tool zur Verwaltung der Konfiguration und des Deployments von Applikationen. Es ermöglicht die zentrale Verwaltung und automatische Bereitstellung sämtlicher Anwendungen und deren Konfigurationen – über beliebig viele Umgebungen und in unterschiedlichen Versionen.

Liima wurde 2012 im Auftrag der Mobiliar durch Puzzle ITC als Open-Source-Projekt entwickelt und dient der Verwaltung der Middleware-Infrastruktur der Mobiliar. Seit 2014 besteht ein Wartungsvertrag zwischen Puzzle ITC und der Mobiliar.

Ursprünglich wurde Liima als reine Java EE-Applikation mit einem Java-Applikationsserver und einer GUI auf Basis von JavaServer Faces (JSF) und RichFaces umgesetzt.

Liima Migration

Das RichFaces-Framework in Liima wurde nach dem End-of-Life im Juni 2016 nicht mehr gewartet oder unterstützt. Aufgrund von Sicherheitslücken und fehlender Kompatibilität mit neueren JSF-Versionen war ein Update der Java EE-Version sowie des Applikationsservers nicht mehr möglich.

Als Lösung wurde eine Migration von JSF auf Angular beschlossen, um die Sicherheit und Wartbarkeit von Liima langfristig zu gewährleisten. Die Wahl fiel auf Angular, da es innerhalb der Mobiliar als Standard für Frontend-Technologien etabliert ist.

Erste Migrationsarbeiten begannen bereits im November 2016 im Rahmen von Wartungsverträgen. Ab Anfang 2024 wurde der Fokus auf die Migration verstärkt, um endlich signifikante Fortschritte zu erzielen. Puzzle ITC bot der Mobiliar gezielte Unterstützung an, und ab August/September 2024 startete das Team mit der intensiven Umsetzung.

Während der Migration sammelten wir als Team sowohl technische als auch organisatorische Erfahrungen. In diesem Blogpost teilen wir unsere wichtigsten Erkenntnisse und beleuchten die wertvollsten Aspekte des Projekts.

Extreme Programming – Unser Startpunkt

Zu Beginn der Migration haben wir uns für Extreme Programming (XP) entschieden, um besonders kollaborativ zu arbeiten und flexibel auf neue Anforderungen reagieren zu können. Da wir uns von unseren klassischen Wartungsarbeiten entfernten, wollten wir bewusst einen anderen Ansatz wählen – agil, aber ohne starre Scrum-Regeln.

Unser Ziel war es nicht nur, die Technologie zu modernisieren, sondern auch unsere Arbeitsweise zu hinterfragen. Die Migration sollte nicht nur effizient, sondern auch motivierend und dynamisch sein. Uns war wichtig, dass die Arbeit Spass macht und wir dabei «nicht nur das Was ändern, sondern auch das Wie».

XP ist ein schlanker, praxisorientierter Ansatz, der auf fünf zentrale Leitwerte setzt: Einfachheit, Kommunikation, Feedback, Mut und Respekt. Diese Werte spiegeln sich in fünf Regeln wider: Planung, Verwaltung, Design, Entwicklung und Testen. Ein typischer XP-Lebenszyklus umfasst folgende Schritte:

  • Unvollendete Arbeiten aus User Stories ermitteln
  • Die wichtigsten Anforderungen zur Priorität machen
  • Mit der iterativen Planung beginnen
  • Sorgfältig und ehrlich planen
  • In ständiger Kommunikation mit allen Stakeholdern bleiben und das Team unterstützen
  • Das Ergebnis bereitstellen
  • Feedback erhalten
  • Zur iterativen Planungsphase zurückkehren und sie nach Bedarf wiederholen

Aufgrund unserer Projektvorgaben und des Teamrhythmus konnten wir nicht alle XP-Prinzipien vollständig umsetzen. Was jedoch geblieben ist, war die Freiheit, Dinge einfach und schlank anzugehen, kontinuierlich Feedback einzuholen und Entscheidungen gemeinsam und kollaborativ zu treffen – beispielsweise durch Pair Programming.

Das Prinzip der kollektiven Verantwortung für den Code erwies sich als besonders wertvoll. Es  ermöglichte uns, auch jene Bereiche der Migration zu bearbeiten, die zuvor nur einzelnen Teammitgliedern vertraut waren. Wir setzen bewusst auf einfache Lösungen und beziehen frühzeitig Feedback von Kund:innen ein – ein Ansatz, der nicht nur die Codequalität verbessert, sondern auch die Motivation und den Spass an der Arbeit steigert.

Design- Entscheidungen

Die Umstellung von JSF und RichFaces auf Angular eröffnete neue Möglichkeiten für das UX- und UI-Design. Anstatt die bestehenden Komponenten eins zu eins zu übernehmen, nutzten wir die Gelegenheit, das bisherige Konzept zu überdenken und gezielt zu optimieren.

Um eine durchdachte und nachhaltige Lösung zu entwickeln, hielten wir regelmässig Ad-hoc-Meetings, Grooming-Sessions und Planungsrunden ab, in denen wir Software-Design- und Architekturfragen klärten. Bei Bedarf unterstützte uns Claudia Asti mit ihrer UX-Expertise.

Diese Freiheit und Flexibilität ermöglichten es uns, neue Technologien und Best Practices – wie beispielsweise Angular Signals – kennenzulernen und gezielt einzusetzen.

Signals in Angular

Durch die Migration konnten wir wertvolle technische Erfahrungen mit TypeScript und Angular sammeln und neue Ansätze in dieser Technologie erlernen. Besonders spannend war für uns die Einführung von Angular Signals mit Version 17 (veröffentlicht im Jahr 2023).

Seit dem verstärkten Fokus auf die Migration ab September 2024 haben wir gezielt darauf geachtet, Signals sinnvoll und effizient einzusetzen. Da die Migration bereits seit 2016 läuft, ergaben sich einige Refactorings, die uns halfen, besser zu verstehen, wann und wie Signals optimal eingesetzt werden.

Signals sind Wrapper für Werte, die sich ändern können. Der aktuelle Zustand kann dabei jederzeit synchron gelesen werden. Sobald sich ein Wert ändert, benachrichtigt das Signal automatisch Angular, sodass nur die betroffenen UI-Elemente neu gerendert werden.

Ein einfaches Beispiel für ein Signal:

 const name : WritableSignal<string> = signal('Clara');

In diesem Fall erstellt signal('Clara') ein writable signal, das einen String-Wert speichert. Wenn der Wert dieses Signals geändert wird, zum Beispiel durch eine Benutzerinteraktion, benachrichtigt es automatisch Angular und nur die betroffene Komponente wird neu gerendert.

Um den Wert eines Signals zu ändern, können wir .set() oder .update() verwenden:

name.set('Max'); // Setzt den Wert direkt auf 'Max'
name.update(current => current.toUpperCase()); // Ändert den aktuellen Wert zu Grossbuchstaben

Während .set() den Wert direkt ersetzt, ermöglicht .update() eine Veränderung in Abhängigkeit vom vorherigen Wert.

Nebst den writable Signals gibt es auch computed signals, deren Wert aus anderen Signals berechnet wird und nur aktualisiert wird, wenn sich der Wert, von dem sie abhängen, ändert (lazy evaluation). Zum Beispiel:

const greeting : Signal<string> = computed(() => `Hallo, ${name()}`);

Wenn sich name ändert, wird auch greeting neu berechnet und aktualisiert (aber lazy, d.h. erst dann, wenn der Wert gelesen wird).

Durch diese präzise Steuerung müssen nicht mehr ganze Komponentenbäume überprüft werden (wie bei der klassischen Change Detection in Angular), was die Performance erheblich verbessert. Signals und computed Signals ermöglichen eine flexiblere und skalierbarere Reaktivität. Zusammengefasst bieten sie eine schnelle, einfache und effiziente Möglichkeit, die UI bei Änderungen zu aktualisieren.

Signals vs. Observables

Signals und Observables ermöglichen beide Reaktivität in Angular, unterscheiden sich jedoch in ihrer Funktionsweise und den idealen Anwendungsbereichen.

  • Signals sind synchron und eignen sich besonders zur Verwaltung lokaler Zustände innerhalb von Komponenten. Mit der neuen Resource API können sie jedoch auch für asynchrone Daten verwendet werden.
  • Observables sind meist asynchron und ideal für komplexe Datenströme wie HTTP-Anfragen oder WebSockets.

Grundregel:
👉 Für Zustände nutzt man Signals.
👉 Für Events und asynchrone Prozesse eignen sich Observables besser.

Ein wichtiger Unterschied: Wenn sich der Wert eines Signals ändert, aktualisiert Angular automatisch alle abhängigen Signals. Observables hingegen erfordern explizite Subscriptions, die später wieder unsubscribed werden müssen – es sei denn, sie werden mit der AsyncPipe verwendet.

Zusätzlich unterscheiden sich die beiden Konzepte in der Art, wie sie Werte aktualisieren:

– Observables emittieren jeden Wert, sofern nicht anders spezifiziert.
– Signals lösen nur dann eine Änderung aus, wenn sich der Wert tatsächlich verändert (lazy memoization).

Fazit

Die Kombination aus unserem XP-basierten Ansatz und dem gezielten Einsatz moderner Angular-Technologien wie Signals hat sich als äusserst wertvoll erwiesen. Die Migration ist noch nicht abgeschlossen – wir freuen uns darauf, auch in diesem Jahr weiter an diesem Projekt zu arbeiten und neue Herausforderungen zu meistern.

Nützliche Links