Connect with us

Entwicklung & Code

Projektmanagement: Darf das Product Backlog sichtbar sein?


Moin.


Escape the Feature Factory: Stefan Mintert

Escape the Feature Factory: Stefan Mintert

(Bild: 

Stefan Mintert

)

Stefan Mintert arbeitet mit seinen Kunden daran, die Unternehmenskultur in der Softwareentwicklung zu verbessern. Das derzeit größte Potenzial sieht er in der Leadership; unabhängig von einer Hierarchieebene.

Die Aufgabe, dieses Potenzial zu heben, hat er sich nach einem beruflichen Weg mit einigen Kurswechseln gegeben. Ursprünglich aus der Informatik kommend, mit mehreren Jahren Consulting-Erfahrung, hatte er zunächst eine eigene Softwareentwicklungsfirma gegründet. Dabei stellte er fest, dass Führung gelernt sein will und gute Vorbilder selten sind.

Es zeichnete sich ab, dass der größte Unterstützungsbedarf bei seinen Kunden in der Softwareentwicklung nicht im Produzieren von Code liegt, sondern in der Führung. So war es für ihn klar, wohin die Reise mit seiner Firma Kutura geht: Führung verbessern, damit die Menschen, die die Produkte entwickeln, sich selbst entwickeln und wachsen können.

Für Heise schreibt Stefan als langjähriger, freier Mitarbeiter der iX seit 1994.

Neulich haben wir in unserem eigenen Team darüber gesprochen, ob das Product Backlog innerhalb einer Firma öffentlich sichtbar sein darf. Da wir als externe Berater, POs und Coaches mit verschiedenen Kundenteams zu tun haben, hat jeder von uns andere Erfahrungen gemacht. Deshalb war es gar nicht so einfach, eine gemeinsame Antwort zu finden.

Nach dem Gespräch habe ich folgende Sichtweise: Es sollte das Ziel sein, dass das Product Backlog und damit die Arbeitspakete des/der Entwicklerteams für jede Person im Unternehmen einsehbar sein sollen. Vorbehalte gegen diese Transparenz können sein:

  • ein unbestimmtes Gefühl des Teams, sich nicht in die Karten schauen zu lassen,
  • die Sorge, sich angreifbar zu machen,
  • die Angst vor häufigen Eingriffen in den Arbeitsablauf.

Alle drei Punkte rechtfertigen aus meiner Sicht, das Backlog vertraulich zu behandeln. Allerdings ist mit jedem einzelnen Punkt auch eine Erkenntnis verbunden: Hier muss sich etwas ändern.

Wenn sich Teams dadurch angreifbar machen, dass jemand sehen kann, woran sie arbeiten, stimmt etwas nicht. Vielleicht hat die Person die Priorisierung oder die Roadmap nicht verstanden. Das kann man hinterfragen und klären.

Vielleicht wird aber auch die Rolle des Product Owners, der das Backlog maßgeblich verantwortet, nicht ausreichend respektiert.

Egal, was zu den Vorbehalten gegen die Transparenz anzuführen ist: Die Ursachen müssen erkannt und ausgeräumt werden.

Hat man das geschafft, dann darf das Product Backlog sichtbar sein. Ob es überhaupt sinnvoll ist, den Stakeholdern jedes kleine Bugticket und jede technische Aufgabe zu zeigen, ist eine andere Frage. Eine Darstellung des Entwicklungsfortschritts über Meilensteine, Epics oder (echte) User Stories dürfte in der Regel besser und ausreichend sein.

Im Podcast Escape the Feature Factory greife ich ausgewählte Themen des Blogs auf und diskutiere sie mit einem Gast. Durch den Austausch lerne ich eine zweite Perspektive kennen. Wenn Du auch daran interessiert bist, findest Du den Podcast bei Spotify, Deezer, Amazon Music und Apple Podcasts. Wenn Du die Themen, die ich im Blog anspreche, in Deiner Firma verbessern möchtest, komm’ in unsere Leadership-Community für Softwareentwicklung.


(rme)



Source link

Entwicklung & Code

Die Produktwerker: Product Backlog Management ist mehr, als man denkt


Viele Teams sehen das Product Backlog als Pflichtprogramm – doch es ist laut Scrum Guide eine der Kernaufgaben des Product Owners und kann zur Zentrale für Klarheit, Wirkung und Zusammenarbeit werden. In dieser Folge erklären Tim Klein und Oliver Winter, was gutes Product Backlog Management wirklich ausmacht:

  • Warum scheitern viele Backlogs? Sie sind überfrachtet, ohne Zielorientierung, mit fehlendem Fokus und unzureichender Kommunikation.
  • Wie hilft ein klares Product Goal über drei bis sechs Monate? Es vereinfacht die Priorisierung und kontroverse Gespräche mit Stakeholdern.
  • Warum sollte Kommunikation angepasst und nicht austauschbar sein – etwa visuelle Boards statt reiner Jira-Listen?
  • Priorisieren mit Klarheit: Vision, Strategy, Outcome Roadmap und Product sowie Sprint Goals als Entscheidungsorientierung.
  • Weniger Ballast, mehr Fokus: Mut zum Ausmisten sorgt für Klarheit und Produktivität.

Kurz gesagt: Product Backlog Management ist nicht nur Priorisieren – es ist ein strategisches Werkzeug für echte Wirkung.

Die aktuelle Ausgabe des Podcasts steht auch im Blog der Produktwerker bereit: „Die Produktwerker: Warum Product Backlog Management mehr ist, als du denkst„.


Product Owner Days, Konferenz in Köln, 2. und 3. April 2025

Product Owner Days, Konferenz in Köln, 2. und 3. April 2025

(Bild: deagreez/123rf.com)

So geht Produktmanagement: Auf der Online-Konferenz Product Owner Day von dpunkt.verlag und iX am 13. November 2025 können Product Owner, Produktmanagerinnen und Service Request Manager ihren Methodenkoffer erweitern, sich vernetzen und von den Good Practices anderer Unternehmen inspirieren lassen.


(mai)



Source link

Weiterlesen

Entwicklung & Code

TypeScript 5.9 sorgt für minimalistische tsconfig.json-Dateien


Microsoft hat Version 5.9 seiner Programmiersprache TypeScript veröffentlicht. Darin finden sich einige neue Features wie verschlankte und aktualisierte tsconfig.json per --init-Flag. Unter der Haube arbeitet das TypeScript-Team weiterhin am Umsetzen der nativen Portierung nach Go, die jedoch nicht in das aktuelle Release einfließt.

Der TypeScript-Compiler kann mit dem --init-Flag eine tsconfig.json-Datei innerhalb des aktuellen Projektverzeichnisses erstellen. Wie das TypeScript-Team ausführt, sei diese Datei jedoch über die letzten Jahre hinweg so weit angewachsen, dass die meisten Developer den Großteil ihres Inhalts direkt löschten. Dazu zählten zahlreiche auskommentierte Einstellungen mitsamt Beschreibungen.

Die Datei ist daher nun entschlackt und soll besser auf die aktuellen Nutzerbedürfnisse abgestimmt sein. So enthält sie unter anderem die Einstellung, dass --target auf esnext (ESNext, die nächste Version des ECMAScript-Standards) gesetzt ist.

In TypeScript 5.9 sieht eine mit tsc --init – ohne Verwendung zusätzlicher Flags – generierte tsconfig.json wie folgt aus:


{
  // Visit  to read more about this file
  "compilerOptions": {
    // File Layout
    // "rootDir": "./src",
    // "outDir": "./dist",

    // Environment Settings
    // See also _modules
    "module": "nodenext",
    "target": "esnext",
    "types": [],
    // For nodejs:
    // "lib": ["esnext"],
    // "types": ["node"],
    // and npm install -D @types/node

    // Other Outputs
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true,

    // Stricter Typechecking Options
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,

    // Style Options
    // "noImplicitReturns": true,
    // "noImplicitOverride": true,
    // "noUnusedLocals": true,
    // "noUnusedParameters": true,
    // "noFallthroughCasesInSwitch": true,
    // "noPropertyAccessFromIndexSignature": true,

    // Recommended Options
    "strict": true,
    "jsx": "react-jsx",
    "verbatimModuleSyntax": true,
    "isolatedModules": true,
    "noUncheckedSideEffectImports": true,
    "moduleDetection": "force",
    "skipLibCheck": true,
  }
}


TypeScript 5.9 bringt darüber hinaus Support für das ECMAScript-Proposal Deferring Module Evaluation durch die neue Syntax import defer. Sie erlaubt das Importieren eines Moduls, ohne dieses und seine Dependencies sofort auszuführen. Das soll Entwicklerinnen und Entwicklern mehr Kontrolle verschaffen. Das Proposal befindet sich derzeit auf der vorletzten Stufe zur Fertigstellung, „Stage 3 (Candidate)„.

Neben weiteren Updates ist auch ein Preview-Feature mit an Bord: Expandable Hovers. In Visual Studio Code erscheinen Informationen zum TypeScript-Code, wenn Entwickler mit der Maus darüber hovern. Diese Infos lassen sich nun ausklappen, um weitere Details anzuzeigen. Die neue Funktion läuft unter den Namen Expandable Hovers oder Quick Info Verbosity.


Wie ausführlich die Infos beim Hovern über TypeScript-Code in VS Code erscheinen, lässt sich nun einstellen.

Wie ausführlich die Infos beim Hovern über TypeScript-Code in VS Code erscheinen, lässt sich nun einstellen.

Wie ausführlich die Infos beim Hovern über TypeScript-Code in VS Code erscheinen, können Developer nun einstellen.

(Bild: Microsoft Developer Blog)

Die Entwicklung des neuen Features in Zusammenarbeit mit dem VS-Code-Team lässt sich auf GitHub mitverfolgen: Im TypeScript-Repo und im VS-Code-Repo befinden sich entsprechende Pull Requests.

Weitere Ausführungen zu den Updates in TypeScript 5.9 liefert Microsofts Entwicklerblog.

Die Portierung des TypeScript-Compilers und weiterer Komponenten in die Programmiersprache Go startete Anfang dieses Jahres und soll eine bis zu zehnfache Beschleunigung des Compilers erlauben. In TypeScript 7.0 soll die native Go-Implementierung abgeschlossen sein – doch zunächst einmal wird TypeScript 6.0 erscheinen. Diese Version soll Entwicklerinnen und Entwicklern als Wendepunkt dienen, um ihre Codebasen für TypeScript 7.0 fit zu machen.

Zwar können im nächsten Release neue Features und Updates enthalten sein, doch der Fokus wird klar auf der Vorbereitung auf Version 7.0 liegen, erklärt das TypeScript-Team. Es geht davon aus, dass sich die meisten Projekte ohne größere Hürden auf die Version 6.0 – die mit TypeScript 5.9 vollständig API-kompatibel sein soll – aktualisieren lassen.

Neue Infos zu TypeScript 7.0 sollen bald folgen. In Form von Native Previews lässt sich eine Vorschau darauf bereits in Visual Studio Code ausprobieren und in Projekten installieren.


(mai)



Source link

Weiterlesen

Entwicklung & Code

Angular Signals: Elegante Reaktivität als Architekturfalle


Mit Angular 17 hielten Signals 2023 offiziell Einzug in das Framework. Sie versprechen eine modernere, klarere Reaktivität: weniger Boilerplate-Code, bessere Performance. Gerade im Template- und Komponentenbereich lösen sie viele Probleme eleganter als klassische Observable-basierte Ansätze.


Nicolai Wolko

Nicolai Wolko

Nicolai Wolko ist Softwarearchitekt, Consultant und Mitgründer der WBK Consulting AG. Er unterstützt Unternehmen bei komplexen Web- und Cloudprojekten und wirkt als Sparringspartner sowie Gutachter für CTOs. Fachbeiträge zur modernen Softwarearchitektur veröffentlicht er regelmäßig in Fachmedien und auf seinem Blog.

Statt Subscriptions, pipe() und komplexen Streams genügen nun wenige Zeilen mit signal(), computed() und effect(). Der Code wirkt schlanker, intuitiver und näher am User Interface (UI).

Da liegt die Idee nahe: Wenn Signals im UI überzeugen, warum nicht auch in der Applikationslogik? Warum nicht RxJS vollständig ersetzen? Ein Application Store ohne Actions, Meta-Framework und Observable: direkt, deklarativ, minimalistisch.

Ein Ansatz, der im Folgenden anhand eines konkreten Fallbeispiels analysiert und kritisch hinterfragt wird. Anschließend wird behandelt, in welchen Kontexten sich Signals sinnvoll einsetzen lassen.

Auf den ersten Blick besitzt dieses Beispiel einen klar strukturierten Architekturansatz. Doch der Wandel beginnt unauffällig. RxJS bleibt zunächst außen vor. Das UI reagiert flüssig, der Code bleibt übersichtlich. Komplexe Streams, verschachtelte Operatoren oder eigenes Subscription Handling entfallen. Stattdessen kommen Signals zum Einsatz. Es liegt nahe, diese unkomplizierte Herangehensweise auch für die Applikationslogik zu übernehmen. Im folgenden Beispiel übernimmt ein ProductStore die Zustandslogik. Signals organisieren Kategorien, Filter und Produktdaten – reaktiv und direkt.


@Injectable({ providedIn: 'root' })
export class ProductStore {
  private allProducts = signal([]);
  readonly selectedCategory = signal('Bücher');
  readonly onlyAvailable = signal(false);

  readonly productList = computed(() => {
    return this.allProducts().filter(p =>
      this.onlyAvailable() ? p.available : true
    );
  });

  selectCategory(category: string) {
    this.selectedCategory.set(category);
  }

  toggleAvailabilityFilter() {
    this.onlyAvailable.set(!this.onlyAvailable());
  }

  constructor(private api: ProductApiService) {
    effect(() => {
      const category = this.selectedCategory();
      const onlyAvailable = this.onlyAvailable();
      this.api.getProducts(category, onlyAvailable).then(products => {
        this.allProducts.set(products);
      });
    });
  }
}


Die Struktur überzeugt zunächst durch Klarheit. Die Komponente konsumiert productList direkt, ohne eigene Logik. Der Store verwaltet den Zustand, Signals sorgen für die Weitergabe von Änderungen.

Doch mit der nächsten Anforderung ändert sich das Bild: Bestimmte Produkte sollen zwar im Katalog verbleiben, aber im UI nicht mehr erscheinen. Da auch andere Systeme die bestehende API verwenden, ist eine Anpassung nicht möglich. Stattdessen liefert das Backend eine Liste freigegebener Produkt-IDs, anhand derer das UI filtert.


@Injectable({ providedIn: 'root' })
export class ProductStore {
  // [...]

  readonly backendEnabledProductIds = signal>(new Set());

  readonly productList = computed(() => {
    return this.allProducts().filter(p =>
      this.onlyAvailable() ? p.available : true
    ).filter(p => this.backendEnabledProductIds().has(p.id));
  });

  constructor(private api: ProductApiService) {
    effect(() => {
      const category = this.selectedCategory();
      const onlyAvailable = this.onlyAvailable();
      this.api.getProducts(category, onlyAvailable).then(products => {
        this.allProducts.set(products);
      });
    });

    effect(() => {
      this.api.getEnabledProductIds().then(ids => {
        this.backendEnabledProductIds.set(new Set(ids));
      });
    });
  }

  // [...]
}


Nach außen bleibt die Architektur zunächst unverändert. Die Komponente enthält weiterhin keine eigene Logik, Subscriptions sind nicht notwendig, und die Reaktivität scheint erhalten zu bleiben. Im Service jedoch nimmt die Zahl der effect()s zu, Abhängigkeiten werden vielfältiger, und die Übersichtlichkeit leidet.

Nach und nach wandert Logik in verteilte effect()s, bis ihre Zuständigkeiten kaum noch greifbar sind. Aus einem überschaubaren ViewModel entsteht ein Gebilde mit immer mehr impliziten Reaktionen – eine Entwicklung, die ein waches Auge für Architektur erfordert.

Das Setup wirkt zunächst unspektakulär. Die Produktliste wird über ein computed() erstellt, gefiltert nach Verfügbarkeit und den vom Backend freigegebenen IDs. Zwei effect()s laden die Daten.

Der Code wirkt aufgeräumt und lässt sich modular erweitern. Doch der nächste Feature-Wunsch stellt das System auf die Probe: Die Stakeholder möchten wissen, wie oft bestimmte Kategorien angesehen werden. Die Entwicklerinnen und Entwickler entscheiden sich für einen naheliegenden Ansatz. Eine Änderung der Kategorie löst ein Tracking-Event aus. Ein effect() scheint dafür perfekt geeignet – unkompliziert und ohne erkennbare Nebenwirkungen:


effect(() => {
  const category = this.selectedCategory();
  this.analytics.trackCategoryView(category);
});


Schnell eingebaut, kein zusätzlicher State, keine neue Subscription. Eine Reaktion auf das bestehende Signal, unkompliziert und ohne erkennbare Nebenwirkungen. Doch damit verlässt der Code den Bereich kontrollierter Reaktivität.

Die Annahme ist klar: Ändert sich die Kategorie, wird ein Tracking ausgelöst. Was dabei leicht zu übersehen ist: Signals reagieren nicht auf Bedeutung, sondern auf jede Mutation. Auch wenn set() denselben Wert schreibt oder zwei Komponenten nacheinander dieselbe Auswahl treffen, passiert zwar technisch etwas, semantisch aber nicht. Das Ergebnis sind doppelte Events und verzerrte Metriken, ohne dass der Code einen Hinweis darauf gibt. Alles sieht korrekt aus.

Das Tracking erfolgt unmittelbar im selben Ausführungstakt (Tick), ohne Möglichkeit zur Entkopplung. Wenn parallel ein weiterer effect() ausgelöst wird – etwa durch ein zweites Signal –, fehlt jegliche Koordination.

Die Reihenfolge ist nicht vorhersehbar, und das UI kann in einen inkonsistenten Zustand geraten: Daten werden mehrfach geladen, Reaktionen überschneiden sich, Seiteneffekte sind nicht mehr eindeutig zuzuordnen. Mit jedem zusätzlichen effect() steigt die Zahl impliziter Wechselwirkungen. Was wie ein reagierendes System wirkt, ist längst nicht mehr entscheidungsfähig.

In einem Kundenprojekt führte genau dieser Zustand dazu, dass ein effect() mehrfach pro Sekunde auslöste. Nicht wegen einer echten Änderung, sondern weil derselbe Wert mehrfach gesetzt wurde. Das UI zeigte korrekte Daten, aber das Backend war mit redundanten Anfragen überlastet.

effect() wirkt wie ein deklarativer Controller: „Wenn sich X ändert, tue Y.“ Doch in Wirklichkeit ist es ein reaktiver Spion. Er beobachtet jedes Signal, das gelesen wird, unabhängig von der semantischen Bedeutung. Er feuert sogar dann, wenn niemand es erwartet. Und er ist nicht koordiniert. Jeder effect() lebt in seiner eigenen Welt, ohne zentrale Regie.

Was als architektonische Vereinfachung begann, endet in einer Blackbox aus Zuständen, Reaktionen und Nebenwirkungen. Mit jedem weiteren Feature wächst diese Komplexität. Es gibt keinen großen Knall, aber eine zuvor elegant erscheinende Struktur driftet leise auseinander.



Source link

Weiterlesen

Beliebt