entwickler.de https://entwickler.de PHP, JavaScript, Windows Development Fri, 29 May 2020 07:18:14 +0000 de-DE hourly 1 https://wordpress.org/?v=4.8.3 4 Best Practices, um User-Feedback sinnvoll in den Entwicklungsprozess einfließen zu lassen https://entwickler.de/online/ux/agile-user-feedback-ux-best-practices-579935391.html https://entwickler.de/online/ux/agile-user-feedback-ux-best-practices-579935391.html#respond Fri, 29 May 2020 05:58:39 +0000 https://entwickler.de/?p=579935391 Immer häufiger setzen Developer auf Agilität und mehrere Entwicklungszyklen, um schnell ein Produkt auf den Markt zu bringen. Dabei ist es entscheidend, die Rückmeldung von Nutzern einzuholen, um das Produkt zu optimieren, Erwartungen zu erfüllen und Schwachstellen frühzeitig zu schließen.

Der Beitrag 4 Best Practices, um User-Feedback sinnvoll in den Entwicklungsprozess einfließen zu lassen ist auf entwickler.de erschienen.

]]>
Immer häufiger setzen Developer auf Agilität und mehrere Entwicklungszyklen, um schnell ein Produkt auf den Markt zu bringen. Dabei ist es entscheidend, die Rückmeldung von Nutzern einzuholen, um das Produkt zu optimieren, Erwartungen zu erfüllen und Schwachstellen frühzeitig zu schließen.

Viele Unternehmen sind bei der Forschung und Entwicklung bereits im Dialog mit ihren Kunden und lassen sich von deren Ideen und Anregungen inspirieren. Beispielsweise können LEGO-Fans über die Seite LEGO Ideas eigene Designs entwerfen, die LEGO bei entsprechender Unterstützung durch die Community prüft und gegebenenfalls in die Produktion aufnimmt. Der Vorteil liegt klar auf der Hand: Die Unternehmen erkennen schneller und besser die Vorlieben und Bedürfnisse ihrer Kunden und können in die richtige Richtung weiterarbeiten, anstatt Ressourcen in Features zu investieren, die vielleicht kaum genutzt würden. Das bringt die Unternehmen ihren Zielgruppen näher und stärkt Kundenbindung, Markentreue und Engagement.

Diese positiven Effekte lassen sich auch auf die Softwareentwicklung übertragen, vor allem da Produkte heute in agilen Prozessen immer schneller und in immer besserer Qualität verfügbar sein müssen. Darum lösen DevOps-Konzepte konventionelle Entwicklungsmodelle zunehmend ab, benötigen aber zahlreiche Prozessoptimierungen. Daher kann man immer häufiger der Trend zum Shift Left beobachten, also zum möglichst frühen Testen und zyklischen Entwickeln. Entscheidend bei dieser Vorgehensweise ist eine sehr gute Kooperation von Developern, Testern, Product Ownern und Business-Analysten. Damit in dieser Gemengelage Entwickler zielgerichtet arbeiten können und nicht an der Fülle der Resonanzen zu ersticken drohen, sind gut funktionierende Workflows und Feedbacksysteme der Schlüssel zum Erfolg. Vier Best Practices haben sich in meinem Entwicklerteam bei Finastra, wo wir Anwendungen für den Finanzbereich entwickeln, besonders bewährt.

webinale – the holistic web conference

Diversity matters – Onlinemarketing 2020

mit Astrid Kramer (Astrid Kramer Consulting)

Das Recht auf Privatsphäre – eine Chance für UX

mit Lutz Schmitt (Lutz Schmitt Design & Consulting)

The Revenge of Structured Data

mit Stephan Cifka (Performics Germany GmbH)

Pufferzone: Business-Analysten vermitteln zwischen Usern und Entwickeln

Wir versuchen, in jeder Testphase die Kommunikation mit den Nutzern so offen wie möglich zu gestalten. Dabei haben wir sehr gute Erfahrungen damit gemacht, einen speziellen Ansprechpartner, etwa einen Business-Analysten, zu etablieren. Er fungiert als Bindeglied zwischen Usern und Entwicklern, definiert Ziele und kann rechtzeitig Problematiken erkennen. Dafür sammelt, strukturiert und priorisiert er einerseits das Feedback der User. Andererseits kann er den Nutzern erläutern, welche Punkte beispielsweise bei einer Banking-App realisierbar sind und welche Schwierigkeiten bereiten könnten. Auf diese Weise kann der Business-Analyst Erwartungen managen sowie das User-Feedback vorfiltern und eine Strategie für die Realisierung kreieren, während das Developer-Team sich direkt auf die Entwicklung der wesentlichsten Features konzentrieren kann. Das spart wertvolle Zeit und Ressourcen, damit wir schneller valide Ergebnisse erlangen.

Wichtig ist, Business-Analysten von Beginn an einzubeziehen. Denn häufig kommen sie erst an Bord, wenn der Entwicklungsprozess schon in vollem Gange ist und bereits Probleme im Austausch mit den Usern aufgetreten sind. Unter diesen Umständen ist es selbst für erfahrene Business-Analysten schwierig, die Anforderungen von Usern und Entwicklern in Balance zu bringen.

Community-Gruppen: User helfen Usern

Wenn viele Nutzer an unterschiedlichen Standorten oder von verschiedenen Organisationen verteilt testen, ergibt es Sinn, Collaboration-Tools einzurichten. Das können zum Beispiel geschlossene Chatgruppen oder Nutzerforen sein. Über die Foren kann man das Feedback auch gleich vorsortieren und bündeln, sodass Fehler oder Feature-Wünsche nicht unnötig vielfach reportet werden. Developer können sich auf diese Weise besser auf die Entwicklung konzentrieren, ohne ständig aktiv Feedback einholen zu müssen. Gleichzeitig gibt die lebhafte Beteiligung an Diskussionen einen Einblick, welche Features besonders stark nachgefragt werden und deshalb Vorrang haben sollten. Außerdem können die Nutzer in solchen Gruppen in einen direkten Austausch untereinander treten und sich häufig gegenseitig Hilfestellung bieten.

Bei uns haben sich User-Communities als eine sehr effiziente Art erwiesen, bei größeren Testgruppen auch mit wenig Zeiteinsatz wertvolle Informationen zusammenzutragen. Wichtig ist es jedoch, dass User auch Priorisierungen vergeben können, beispielsweise für Störfälle. Und bei dringenden oder komplexeren Anliegen, Fragen und Problemen sollten Business-Analysten oder Developer unbedingt in den direkten Austausch mit den Nutzern treten.

Echtzeit: Usability-Tests tracken Nutzerverhalten

Bei herkömmlichen UX-Tests bittet man Tester auf der Grundlage verschiedener Designs, ihre Vorlieben bei der Navigation wiederzugeben. Die Schwierigkeit ist jedoch, diese Vorgehensweise zu skalieren. Viel effizienter und effektiver kann man Nutzerpräferenzen heute mit der Hilfe von Online-Tools tracken. Das geht nicht nur in Echtzeit, sondern vermittelt auch noch zusätzliche Eindrücke, beispielsweise über die präzise Anordnung von Funktionen. Wenn etwa auffällt, dass der Nutzer wiederholt in die obere rechte Ecke einer Online-Banking-Website zurückkehrt, ist er vielleicht auf der Suche nach einem Weg, sich auszuloggen. Dann sollten Entwickler diese Möglichkeit vielleicht prominenter zur Verfügung stellen und dies durch gezielte Tests verifizieren. Genauso verhält es sich, wenn ein User immer wieder über einen bestimmten Bereich fährt. Eventuell vermisst er dann ein Live-Feature, das er von einer anderen Oberfläche her kennt.

Über das Live-Tracking können Developer solche Nutzerverhalten viel schneller analysieren, entsprechende Design-Änderungen implementieren und direkt die Reaktion ablesen. Die gesamte UX-Entwicklung wird dadurch beschleunigt und noch nutzerzentrierter.

Checkpoints: Mehr Flexibilität für agile Projekte

In der agilen Softwareentwicklung sind definierte Ziele und fokussierte Sprints inzwischen Standard. Mitunter kann es dabei jedoch schwierig sein, diese mit kurzfristigen Kundenanforderungen in Einklang zu bringen. Aus diesem Grund hat es sich bei unseren Projekten als sinnvoll erwiesen, neben dem größeren Meilenstein eines festen Sprints kleine Etappenziele oder Checkpoints ebenfalls für jedes Projektintervall festzusetzen. Denn während Sprintziele in der Regel unverändert bleiben, können Teilziele auch mal angepasst oder verschoben werden. Nehmen wir als Beispiel ein Szenario, bei dem ein Kunde ein Projekt gegenüber seinem Vorgesetzten präsentieren muss und dafür ein bestimmtes Feature benötigt. Das Feature ist vielleicht nicht als Ziel eines Sprints festgelegt, aber als Checkpoint kann man es innerhalb eines solchen trotzdem berücksichtigen und rechtzeitig realisieren.

Auf diese Weise kann man Kundenbedürfnisse flexibler einbeziehen und umsetzen. Statt die gesamte Projektplanung zeit- und ressourcenintensiv zu überarbeiten, lassen sich Teilziele einfach justieren. Bei unserer Entwicklung von Finanzapplikationen hat es sich bewährt, nicht mehr als fünf dieser kleinen Etappenziele innerhalb eines Entwicklungsintervalls auszugeben. Andernfalls würde sich das Team zu sehr auf die Checkpoints anstelle des Sprintziels fokussieren.

Fazit: Feedback lohnt sich

Die schnellere und bessere Umsetzung von Nutzeransprüchen optimiert die User Experience sichtlich und kann einen entscheidenden Wettbewerbsvorteil bringen. Aber das ist nicht das einzige Argument für die direkte Einbeziehung des User-Feedbacks. Die offene Kommunikation zeugt auch von absoluter Kundenorientierung. Sie bildet Vertrauen, stärkt die Loyalität und ist letztendlich das beste Verkaufsargument.

Der Beitrag 4 Best Practices, um User-Feedback sinnvoll in den Entwicklungsprozess einfließen zu lassen ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/ux/agile-user-feedback-ux-best-practices-579935391.html/feed 0
Long-Running-Workflows als Serverless Functions in Azure https://entwickler.de/online/cloud/long-running-workflows-azure-579935403.html https://entwickler.de/online/cloud/long-running-workflows-azure-579935403.html#respond Fri, 29 May 2020 05:36:59 +0000 https://entwickler.de/?p=579935403 Azure Functions bringen viele Eigenschaften mit, die einem die Arbeit erleichtern. Für länger laufende Prozesse sind sie allerdings weniger gut geeignet. Hier helfen Durable und Entity Functions weiter.

Der Beitrag Long-Running-Workflows als Serverless Functions in Azure ist auf entwickler.de erschienen.

]]>
Azure Functions bringen viele Eigenschaften mit, die einem die Arbeit erleichtern. Für länger laufende Prozesse sind sie allerdings weniger gut geeignet. Hier helfen Durable und Entity Functions weiter.

Serverless Functions [1] sind aus meiner Sicht eine großartige Erweiterung von Microsoft Azure, die sich nicht umsonst zunehmend größerer Beliebtheit erfreut. Die Gründe: Man muss sich weder um die Auswahl der richtigen Anzahl und Größe von Servern kümmern noch um die Konfiguration des Autoscalings. Schon gar nicht ist man damit beschäftigt, virtuelle Maschinen aktuell zu halten. APIs in der Cloud kommen durch die Serverless-Technologie wie der sprichwörtliche Strom aus der Steckdose. Auch dort steckt eine gewaltige Ingenieursleistung dahinter, immer die richtige Menge Strom zum richtigen Zeitpunkt anzubieten. So ist es auch mit Serverless Functions. Man verpackt seinen Code, übergibt ihn Microsoft und lässt es deren Problem sein, die notwendige Infrastruktur für die gerade anstehende Last bereitzustellen. Nach dem sogenannten Consumption Plan zahlt der Nutzer für das, was er tatsächlich verbraucht, und die Kosten fallen sogar auf null, wenn gerade niemand die Cloud-Software nutzt [2].

Die zweite Besonderheit von Azure Functions ist das Programmiermodell: Es ist Event-getrieben. Events können dabei einerseits die üblichen HTTP Requests sein, falls das zu entwickelnde API ein Web-API sein soll. Es gibt aber auch eine große Anzahl anderer Events, auf die man reagieren kann [3]. Hier einige Beispiele:

  • Eine Datei wird auf den Blob Storage hochgeladen.

  • Eine Datenänderung geschieht in Cosmos DB.

  • Eine Nachricht kommt von einem IoT-Gerät.

  • Über den Service-Bus kommt eine Nachricht von einem anderen Microservice.

  • Ein Timer informiert darüber, dass ein eingestellter Zeitpunkt erreicht wurde.

Das Konzept von Azure Functions passt daher perfekt, wenn man eine Software in Form lose gekoppelter Microservices aufbauen möchte.

Wozu Durable Functions?

Die klassischen Azure Functions haben zwei Eigenschaften, die man beim Design berücksichtigen muss. Erstens müssen sie ihre Aufgabe in relativ kurzer Zeit erledigen. Das Standard-Timeout sind fünf Minuten (Functions mit HTTP-Trigger müssen sogar in knapp vier Minuten antworten), bei Bedarf kann es auf bis zu zehn Minuten erhöht werden [4]. Zweitens sind Serverless Azure Functions stateless. Der Entwickler muss sich selbst um das Speichern von State kümmern, beispielsweise in anderen Azure-PaaS- oder Serverless-Diensten wie Azure SQL Database oder Cosmos DB.

Aufgrund dieser beiden Einschränkungen sind Azure Functions für lange laufende Prozesse nicht gut geeignet. Stellen Sie sich vor, Ihre Serverless Function soll während der Ausführung mit einem Benutzer über einen Slack-Bot kommunizieren. Es ist nicht vorhersagbar, wie schnell der Benutzer reagiert. Es können Minuten oder sogar Stunden vergehen. Eine Function würde mit großer Wahrscheinlichkeit in ein Timeout laufen.

In solchen Situationen helfen Durable Functions und Entity Functions. Sie sind dafür konzipiert, lange zu laufen und sich um das State-Management selbst zu kümmern. Wir konzentrieren uns nun auf diese Varianten der Azure Functions und gehen davon aus, dass Sie als Leserin oder Leser grundlegendes Wissen über die klassischen Azure Functions haben. Falls Ihnen diese Erfahrung fehlt, empfehle ich das Durcharbeiten eines entsprechenden Tutorials, wie man es zum Beispiel unter [5] findet.

BASTA! 2020

Entity Framework Core 5.0: Das ist neu

mit Dr. Holger Schwichtenberg (www.IT-Visions.de/5Minds IT-Solutions)

Memory Ownership in C# und Rust

mit Rainer Stropek (timecockpit.com)

Softwarearchitektur nach COVID-19

mit Oliver Sturm (DevExpress)

Delphi Code Camp

Delphi Language Up-To-Date

mit Bernd Ua (Probucon)

TMS WEB Core training

mit Bruno Fierens (tmssoftware.com bvba)

Programmieren mit Durable Functions

Mit Durable Functions implementiert man lange laufende Workflows. Im Gegensatz zu anderen Workflowtools wird dafür aber keine eigene deklarative Sprache (z. B. domänenspezifische Sprache (DSL), XML, JSON) verwendet, sondern ganz normales C# (Azure Functions unterstützt auch andere Programmiersprachen, hier beschränken wir uns aber auf C#). Aus der Codestruktur lässt sich der Ablauf des Workflows gut ablesen. Die einzelnen Aktivitäten des Workflows, die eventuell länger dauern könnten, sind hinter await-Aufrufen versteckt.

Das allein ermöglicht es aber noch nicht, lange laufende Workflows in C# zu programmieren. Azure Functions sind serverless. Die Serverlandschaft, auf der Ihr C#-Code läuft, kann sich daher ständig ändern. Es kommen Server dazu oder der Server, auf dem eine Workflowinstanz gerade ausgeführt wird, fällt weg. Wie gehen Durable Functions damit um? Die Antwort auf diese Frage scheint auf den ersten Blick absurd: Durable Functions werden immer wieder von Beginn an ausgeführt.

Die einzelnen Aktivitäten innerhalb des Workflows müssen aus diesem Grund deterministisch sein. Das bedeutet, dass sie bei jedem Durchlauf einer Workflowinstanz bei gleichen Eingabeparametern das gleiche Ergebnis liefern müssen. Entsprechend dem Event-Sourcing-Pattern speichert die Durable Functions Runtime jede Aktion einer Workflowinstanz und deren Ergebnis automatisch in Azure Storage ab. Startet die Function einer Workflowinstanz später von vorn, wird vor dem Aufruf der jeweiligen Aktion geprüft, ob sie bei einem früheren Durchlauf der Instanz schon einmal ausgeführt wurde. Falls ja, wird die Aktion nicht erneut durchgeführt, sondern ihr zuvor ermitteltes Ergebnis wird gelesen und zurückgegeben. Dadurch schadet es nichts, dass immer wieder von vorn begonnen wird. Die schon durchgeführten Aktionen werden quasi übersprungen.

Viele C#-Funktionen sind nicht von Haus aus deterministisch. Man denke an die aktuelle Uhrzeit, die Erzeugung einer neuen GUID, externe Web-APIs, Zufallszahlen etc. Solche APIs dürfen in Durable Functions nicht verwendet werden. Ihr API bietet Alternativen mit ähnlicher Funktionalität an, die mit der Durable Functions Runtime kompatibel sind [6].

Entspannt abwarten

Listing 1 enthält ein Beispiel für eine Durable Function, die das Human Interaction Application Pattern [7] implementiert. Abbildung 1 stellt den Ablauf als Sequenzdiagramm dar.

Abb. 1: Sequenzdiagramm zu Listing 1

Abb. 1: Sequenzdiagramm zu Listing 1

In unserem Szenario sendet eine Verkehrsüberwachungskamera Geschwindigkeitsübertretungen über ein HTTP-Web-API an eine normale Azure Function (SpeedViolationRecognition). Diese Funktion überprüft die Genauigkeit, mit der das Fahrzeugkennzeichen erkannt wird. Ist diese nicht hoch genug, brauchen wir die Hilfe eines Menschen, der sich das aufgenommene Bild ansieht und das erkannte Kennzeichen prüft. Die Interaktion mit dieser Person könnte über ein Messaging-System wie Slack erfolgen (im Beispielcode dieses Artikels nur angedeutet). Da nicht absehbar ist, wie rasch die Person reagieren wird, steckt die Interaktionslogik in einer Durable Function (ManuallyApproveRecognition). Sie sendet die Bitte nach manueller Kennzeichenkontrolle an Slack und wartet darauf, dass Slack die Antwort über eine Web-API-Funktion (ProcessSlackApproval) zurückliefert. Über ein Event (ReceiveApprovalResponseEvent) wird die Durable Function über das Eintreffen der Antwort informiert und die Geschwindigkeitsübertretung kann fertig verarbeitet werden (StoreSpeedViolation).

Beachten Sie beim Durchsehen des Codes insbesondere die Orchestration ID, die an verschiedenen Stellen eingesetzt wird. Sie identifiziert die Workflowinstanz eindeutig. Mit ihr wird in den Event-Sourcing-Tabellen in Azure Storage gefiltert. Abbildung 2 zeigt den Zusammenhang zwischen HTTP-Web-API, der Orchestration ID und den Tabellen in Azure Storage.

Abb. 2: Event-Source-Tabelle in Azure Storage

Abb. 2: Event-Source-Tabelle in Azure Storage



using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
 
namespace DurableFunctions
{
  # region Data Transfer Objects
  /// <summary>
  /// Represents a speed violation recognized by a traffic camera
  /// </summary>
  public class SpeedViolation
  {
    /// <summary>
    /// ID of the camera that has recognized the vehicle
    /// </summary>
    public int CameraID { get; set; }
 
    /// <summary>
    /// License plate number as recognized by the camera
    /// </summary>
    public string LicensePlateNumber { get; set; }
 
    /// <summary>
    /// Accuracy of license plate recognition (value between 0 and 1)
    /// </summary>
    public double RecognitionAccuracy { get; set; }
 
    /// <summary>
    /// Measured speed of the vehicle
    /// </summary>
    public decimal SpeedKmh { get; set; }
  }
 
  /// <summary>
  /// Represents a request for manual approval of license plate read
  /// </summary>
  public class ApprovalRequest
  {
    /// <summary>
    /// ID or the long-running orchestration handling the approval process
    /// </summary>
    public string OrchestrationInstanceID { get; set; }
 
 
    /// <summary>
    /// Data about the speed violation to approve
    /// </summary>
    public SpeedViolation SpeedViolation { get; set; }
  }
 
  /// <summary>
  /// Represents a response of a user concerning a license plate read
  /// </summary>
  public class ApprovalResponse
  {
    /// <summary>
    /// ID or the long-running orchestration handling the approval process
    /// </summary>
    public string OrchestrationInstanceID { get; set; }
 
    /// <summary>
    /// True if license plate read has been confirmed, otherwise false
    /// </summary>
    public bool Approved { get; set; }
  }
  # endregion
 
  public class TrafficSpeedViolation
  {
    /// <summary>
    /// Web API handling incoming speed violations recognized by traffic cameras
    /// </summary>
    /// <returns>
    /// OK if license plate read accuracy was ok, otherwise tracking data for
    /// long-running orchestration handling manual approval of license plate read.
    /// </returns>
    [FunctionName(nameof(SpeedViolationRecognition))]
    public async Task<HttpResponseMessage> SpeedViolationRecognition(
      [HttpTrigger(AuthorizationLevel.Anonymous, "post")]HttpRequestMessage req,
      [DurableClient] IDurableOrchestrationClient starter,
      ILogger log)
    {
      // Get speed violation data from HTTP body
      var sv = JsonSerializer.Deserialize<SpeedViolation>(await req.Content.ReadAsStringAsync());
 
      // Check if read accuracy was not good enough
      if (sv.RecognitionAccuracy < 0.75d)
      {
        log.LogInformation($"Recognition not accurate enough, starting orchestration to ask human for help");
 
        // Start durable function for manual approval process
        string instanceId = await starter.StartNewAsync(nameof(ManuallyApproveRecognition), sv);
 
        // Return status object with instance ID and URLs for status monitoring
        return starter.CreateCheckStatusResponse(req, instanceId);
      }
 
      // Read accuracy was ok, than store it (assumption: storing speed
      // violation is pretty fast, i. e. a matter of seconds).
      await StoreSpeedViolation(sv, log);
      return new HttpResponseMessage(HttpStatusCode.OK);
    }
 
    private const string ReceiveApprovalResponseEvent = "ReceiveApprovalResponse";
 
    /// <summary>
    /// Web API receiving responses from Slack API
    /// </summary>
    /// <returns>
    /// OK if approval was ok, BadRequest if approval is unknown or no longer running
    /// </returns>
    [FunctionName(nameof(ProcessSlackApproval))]
    public async Task<HttpResponseMessage> ProcessSlackApproval(
      [HttpTrigger(AuthorizationLevel.Anonymous, "post")]HttpRequestMessage req,
      [DurableClient] IDurableOrchestrationClient orchestrationClient,
      ILogger log)
    {
      // Get approval response from HTTP body
      var slackResponse = JsonSerializer.Deserialize<ApprovalResponse>(await req.Content.ReadAsStringAsync());
 
      // Get status based on orchestration Id
      var status = await orchestrationClient.GetStatusAsync(slackResponse.OrchestrationInstanceID);
      if (status.RuntimeStatus == OrchestrationRuntimeStatus.Running || status.RuntimeStatus == OrchestrationRuntimeStatus.Pending)
      {
        log.LogInformation("Received Slack response in time, raising event");
 
                // Raise an event for the given orchestration
                await orchestrationClient.RaiseEventAsync(slackResponse.OrchestrationInstanceID,
                    ReceiveApprovalResponseEvent, slackResponse.Approved);
                return new HttpResponseMessage(HttpStatusCode.OK);
            }
 
            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        }
 
        /// <summary>
        /// Durable function handling long-running approval process
        /// </summary>
        [FunctionName(nameof(ManuallyApproveRecognition))]
        public async Task<bool> ManuallyApproveRecognition([OrchestrationTrigger] DurableOrchestrationContext context)
        {
          // Get speed violation data from orchestration context
          var sv = context.GetInput<SpeedViolation>();
 
          // Call activity that sends approval request to Slack. Note that this
          // activity will not await the human's response. It will only wait until
          // message will have been sent to Slack.
          await context.CallActivityAsync(nameof(SendApprovalRequestViaSlack), new ApprovalRequest
          {
            OrchestrationInstanceID = context.InstanceId,
            SpeedViolation = sv
          });
 
          // We want the human operator to respond within 60 minutes. We setup a
          // timer for that. Note that this is NOT a regular .NET timer. It is a
          // special timer from the Durable Functions runtime!
          using var timeoutCts = new CancellationTokenSource();
          var expiration = context.CurrentUtcDateTime.AddMinutes(60);
          var timeoutTask = context.CreateTimer(expiration, timeoutCts.Token);
 
          // Wait for the event that will be raised once we have received the           // response from Slack.
          var approvalResponse = context.WaitForExternalEvent<bool>(ReceiveApprovalResponseEvent);
 
          // Wait for Slack response or timer, whichever comes first
          var winner = await Task.WhenAny(approvalResponse, timeoutTask);
 
          // Was the Slack task the first task to complete?
          if (winner == approvalResponse && approvalResponse.Result)
          {
            // License plate read approved -> Store speed violation
            await context.CallActivityAsync(nameof(StoreSpeedViolation), sv);
          }
 
          if (!timeoutTask.IsCompleted)
          {
            // All pending timers must be completed or cancelled before the             // function exits.
            timeoutCts.Cancel();
          }
 
          return winner == approvalResponse && approvalResponse.Result;
    }
 
    [FunctionName(nameof(SendApprovalRequestViaSlack))]
    public Task SendApprovalRequestViaSlack([ActivityTrigger] ApprovalRequest req, ILogger log)
    {
      log.LogInformation($"Message regarding {req.SpeedViolation.LicensePlateNumber} sent to Slack " +
        $"(instance ID {req.OrchestrationInstanceID}!");
 
      // Todo: Send data about speed violation to Slack via Slack REST API.
      // Not implemented here, just a demo.
 
      return Task.CompletedTask;
    }
 
    [FunctionName(nameof(StoreSpeedViolation))]
    public Task StoreSpeedViolation([ActivityTrigger] SpeedViolation sv, ILogger log)
    {
      log.LogInformation($"Processing speed violation from camera {sv.CameraID}" +
        $"for LP {sv.LicensePlateNumber} ({sv.SpeedKmh} km/h)");
 
      // Todo: Add code for processing speed violation
      // Not implemented here, just a demo.
 
      return Task.CompletedTask;
    }
  }
}

Entity Functions

Erst vor wenigen Monaten wurden die Azure Durable Functions um eine neue Art von Funktionen erweitert: die Entity Functions. Während sich bei den bisherigen Durable Functions (aka Orchestrator Functions) der State implizit durch den Kontrollfluss und die lokalen Variablen im C#-Code ergibt, wird er bei Entity Functions explizit gespeichert.

Das Prinzip lässt sich am leichtesten an einem Beispiel erklären. Listing 2 enthält ein Durable Entity, das ein Verfahren wegen Geschwindigkeitsübertretung repräsentiert (SpeedViolationLawsuit). Es verwendet die Class-based Syntax. Alternativ würde auch eine Function-based Syntax angeboten, wobei Microsoft in C# die Variante mit Klassen empfiehlt [8]. Man muss keinen Code schreiben, um die Instanzen dieser Klasse zu persistieren. Die Durable Functions Runtime speichert den State der Instanzen als JSON Blobs in Azure Storage. Das Aussehen des JSON lässt sich mit den üblichen C#-Attributen für die JSON-Serialisierung beeinflussen.

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using System;
using System.Threading.Tasks;
 
namespace DurableFunctions
{
  /// <summary>
  /// Represents a speed violation lawsuite
  /// </summary>
  public class SpeedViolationLawsuit
  {
    public SpeedViolation SpeedViolation { get; set; }
 
    public string Driver { get; set; }
 
    public decimal? Fine { get; set; }
 
    public bool Paid { get; set; }
 
    public void SetSpeedViolation(SpeedViolation sv) => SpeedViolation = sv;
 
    public void StoreDriver(string driver) => Driver = driver;
 
    public async Task SetFine(decimal fine)
    {
      if (string.IsNullOrEmpty(Driver))
      {
        throw new InvalidOperationException();
      }
 
      // Simulate an async operation (e. g. for I/O)
      await Task.Delay(1);
 
      Fine = fine;
    }
 
    public void MarkAsPaid()
    {
      if (!Fine.HasValue)
      {
        throw new InvalidOperationException();
      }
 
      Paid = true;
    }
 
    public void Delete()
    {
      // Note how we access the current entity
      Entity.Current.DeleteState();
    }
 
    [FunctionName(nameof(SpeedViolationLawsuit))]
    public static Task Run([EntityTrigger] IDurableEntityContext ctx)
    {
      // When creating a new entity, make sure it is marked as not paid
      if (!ctx.HasState)
      {
        ctx.SetState(new SpeedViolationLawsuit
        {
          Paid = false
        });
      }
 
      return ctx.DispatchAsync<SpeedViolationLawsuit>();
    }
  }
}

Listing 3 zeigt, wie man aus normalen und Durable Functions heraus mit den Durable Entities umgeht. In ManuallyApproveRecognition sieht man, wie eine neue Entity erzeugt wird. In unserem Szenario wäre das beispielsweise dann der Fall, wenn in der Durable Function der Benutzer die Kennzeichenerkennung bestätigt hat. GetLawsuite zeigt, wie man den State der Durable Entity mit Hilfe ihrer ID (in unserem Fall eine GUID) lesen kann. SetDriver ist schließlich ein stark vereinfachtes Beispiel für das Aufrufen einer Methode, die den State der Entity verändert. Ich empfehle jedem, der mit Durable Entities experimentiert, analog zu Abbildung 2 einen Blick in den Azure Storage zu werfen, um ein tieferes Verständnis dafür zu bekommen, wie Azure Functions den State tatsächlich speichern.

public async Task<bool> ManuallyApproveRecognition(
  [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
  // ...
 
  // Create a new instance of a speed violation lawsuite
  var entityId = Guid.NewGuid();
  var lawsuitId = new EntityId(nameof(SpeedViolationLawsuit), entityId.ToString());
 
  // Store data of speed violation in new entity
  await context.CallEntityAsync(lawsuitId, nameof(SpeedViolationLawsuit.SetSpeedViolation), sv);
 
  // ...
}
 
[FunctionName(nameof(GetLawsuite))]
public async Task<IActionResult> GetLawsuite(
  [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "lawsuite/{entityKey}")] HttpRequestMessage req,
  string entityKey,
  [DurableClient] IDurableEntityClient client,
  ILogger log)
{
  // Get state of speed violation lawsuite using its Id (GUID)
  var svl = await client.ReadEntityStateAsync<SpeedViolationLawsuit>(
    new EntityId(nameof(SpeedViolationLawsuit), entityKey));
 
  // Return current state of lawsuite
  return new OkObjectResult(svl);
}
 
[FunctionName(nameof(SetDriver))]
public async Task<IActionResult> SetDriver(
  [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "lawsuite/{entityKey}/setDriver")] HttpRequestMessage req,
  string entityKey,
  [DurableClient] IDurableEntityClient client,
  ILogger log)
{
  var driverName = JsonSerializer.Deserialize<string>(await req.Content.ReadAsStringAsync());
 
  // Send one-way message to lawsuite entity (not processing result)
  await client.SignalEntityAsync(
    new EntityId(nameof(SpeedViolationLawsuit), entityKey),nameof(SpeedViolationLawsuit.StoreDriver), 
    driverName);
 
  return new StatusCodeResult((int)HttpStatusCode.Accepted);
}

Fazit

Durch Durable Functions wurde der Anwendungsbereich von Azure Functions deutlich erweitert. Die bisherigen Einschränkungen bei den Ausführungszeiten fallen weg. Das Task-basierte Programmiermodell und async/await eignen sich gut zur Abbildung von Workflows. Der C#-Code lässt sich angenehm lesen und spiegelt den Inhalt der Workflows gut wider. Auch komplexe Anwendungsfälle wie die parallele Ausführung mehrerer Teilprozesse (aka Fan out/Fan in) oder die Einbindung von Menschen in lange laufende Workflows sind kein Problem.

Bis vor wenigen Monaten war es jedoch schwierig, mit den Durable Functions das Aggregatorpattern umzusetzen. Dabei kommen Daten, die eine logische, adressierbare Entität betreffen, über einen längeren Zeitraum von verschiedenen Quellen und müssen gesammelt werden. Genau für solche Anwendungsfälle eignen sich die neuen Durable Entities.

Neben den funktionalen Erweiterungen von Azure Functions vernachlässigt Microsoft auch die technische Weiterentwicklung nicht: Die aktuelle Azure Functions Runtime erlaubt bereits die Verwendung von .NET Core 3.1. Auch der Betrieb von Functions in Kubernetes wird unterstützt [9].

Man sieht, dass Microsoft die Entwicklung von Azure Functions flott vorantreibt. Die Plattform ist aus meiner Sicht eine interessante Option für alle, die auf lose gekoppelte Microservices und Event-getriebene Cloud-Lösungen setzen.

 

Der Beitrag Long-Running-Workflows als Serverless Functions in Azure ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/cloud/long-running-workflows-azure-579935403.html/feed 0
Einführung in die funktionale Softwarearchitektur https://entwickler.de/online/development/funktionale-softwarearchitektur-video-sperber-579935383.html https://entwickler.de/online/development/funktionale-softwarearchitektur-video-sperber-579935383.html#respond Fri, 29 May 2020 05:32:52 +0000 https://entwickler.de/?p=579935383 Funktionale Programmierung (FP) verbreitet sich inzwischen auch in Deutschland immer weiter. Die Produktivitätssteigerungen durch FP sind schon lange bekannt, die Entwicklungstechnologien ausgereift. Allerdings führt sie auch zu Änderungen in der Softwarearchitektur. Was funktionale Softwarearchitektur eigentlich ist und welche Aspekte dabei von Bedeutung sind, erklärt Michael Sperber in seiner Session auf der JAX 2019.

Der Beitrag Einführung in die funktionale Softwarearchitektur ist auf entwickler.de erschienen.

]]>
Funktionale Programmierung (FP) verbreitet sich inzwischen auch in Deutschland immer weiter. Die Produktivitätssteigerungen durch FP sind schon lange bekannt, die Entwicklungstechnologien ausgereift. Allerdings führt sie auch zu Änderungen in der Softwarearchitektur. Was funktionale Softwarearchitektur eigentlich ist und welche Aspekte dabei von Bedeutung sind, erklärt Michael Sperber in seiner Session auf der JAX 2019.

FFP bedeutet unter anderem auch fundamentale Änderungen in der Softwarearchitektur: Die Verwendung unveränderlicher Daten und reiner Funktionen steht diametral der allgegenwärtigen Verwendung gekapselter, veränderlicher Zustände in OO-Architekturen gegenüber, was zu größerer Flexibilität und Robustheit der entstehenden Software führt.

In seiner Session auf der JAX 2019 gibt Michael Sperber einen Überblick über die wichtigsten Aspekte funktionaler Architektur: unveränderliche Daten, Funktionen, Typen, Entwurf und Umsetzung von Domänen- mit Kombinatormodellen, DDD und wichtige Architekturmuster.

Der Speaker
Michael Sperber is CEO of the Active Group in Tübingen, Germany. Mike specializes in functional programming and has been an internationally recognized expert in the field: He has spoken at the top conferences in programming languages, authored many papers on the subject as well as several books. Moreover, he is an expert on teaching programming.

 

API Conference
Sheen Brisals

Modularizing your API with Domain Storytelling

Henning Schwentner (WPS – Workplace Solutions)

Software Architecture Camp

Modul Funar – Funktionale Softwarearchitektur

mit Dr. Michael Sperber (Active Group GmbH)

Der Beitrag Einführung in die funktionale Softwarearchitektur ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/development/funktionale-softwarearchitektur-video-sperber-579935383.html/feed 0
Best Practices: Systematische Nutzung des npm-Paketmanagers https://kiosk.entwickler.de/windows-developer-magazin/windows-developer-magazin-6-2020/es-kommt-nicht-nur-auf-die-letzte-meile-an/ https://kiosk.entwickler.de/windows-developer-magazin/windows-developer-magazin-6-2020/es-kommt-nicht-nur-auf-die-letzte-meile-an/#respond Thu, 28 May 2020 10:00:49 +0000 https://entwickler.de/?p=579935266 Der npm-Paketmanager hat das Leben zahlreicher Entwickler deutlich vereinfacht. Auch wenn es immer wieder Sicherheitsprobleme gab, so steht der Paketmanager doch für eine wahre Erfolgsgeschichte. Folgt man einigen Best Practices, lässt es sich noch komfortabler damit arbeiten.

Der Beitrag Best Practices: Systematische Nutzung des npm-Paketmanagers ist auf entwickler.de erschienen.

]]>
Der npm-Paketmanager hat das Leben zahlreicher Entwickler deutlich vereinfacht. Auch wenn es immer wieder Sicherheitsprobleme gab, so steht der Paketmanager doch für eine wahre Erfolgsgeschichte. Folgt man einigen Best Practices, lässt es sich noch komfortabler damit arbeiten.

Der Beitrag Best Practices: Systematische Nutzung des npm-Paketmanagers ist auf entwickler.de erschienen.

]]>
https://kiosk.entwickler.de/windows-developer-magazin/windows-developer-magazin-6-2020/es-kommt-nicht-nur-auf-die-letzte-meile-an/feed 0
Stack Overflow Survey 2020: Rust und JavaScript weiter an der Spitze https://entwickler.de/online/development/stackoverflow-survey-2020-579935514.html https://entwickler.de/online/development/stackoverflow-survey-2020-579935514.html#respond Thu, 28 May 2020 09:58:11 +0000 https://entwickler.de/?p=579935514 Die mit Spannung erwartete Umfrage der Stack Overflow-Plattform wurde veröffentlicht. Während JavaScript weiterhin die verbreitetste Sprache bleibt, erfreut sich Rust unter seinen Anwendern der größen Beliebtheit. Bei der Frage nach der best bezahlten Technologie können sich Go-Entwickler freuen.

Der Beitrag Stack Overflow Survey 2020: Rust und JavaScript weiter an der Spitze ist auf entwickler.de erschienen.

]]>
Die mit Spannung erwartete Umfrage der Stack Overflow-Plattform wurde veröffentlicht. Während JavaScript weiterhin die verbreitetste Sprache bleibt, erfreut sich Rust unter seinen Anwendern der größen Beliebtheit. Bei der Frage nach der best bezahlten Technologie können sich Go-Entwickler freuen.

Die erstmals 2011 erschienene jährliche Stack Overflow Developer Survey wurde für das Jahr 2020 veröffentlicht. Die von 65.000 Entwicklern aus 186 Ländern eingeholten Daten berücksichtigen dabei allerdings nicht die Zeit der Corona-Krise, sondern wurden bereits im Februar erhoben. Wie bereits in den letzten Jahren gibt die Umfrage Auskunft über die beliebtesten bzw. unbeliebtesten Technologien der Teilnehmer und welche zukünftig als interessant betrachtet werden.
Darüberhinaus lassen sich aus den Antworten Trends zu beliebten Tools ablesen und in welchen Bereichen durchschnittlich wie viel Gehalt gezahlt wird.

Stack Overflow Survey: Programmiersprachen und Frameworks

Zum bereits achten Mal in Folge sichert sich JavaScript die Goldmedaille für die verbreitetste Programmiersprache. Insgesamt 67,7% der Befragten gaben an, die Skriptsprache zu nutzen. Da an gleicher Stelle auch Markup-Sprachen als Antwort möglich waren, landet HTML, bzw. CSS auf dem zweiten Platz. Es folgen SQL, Python und Java.

Quelle: https://insights.stackoverflow.com/survey/2020

Ein eindeutiges Bild zeigt sich im Bereich der meist genutzten Web Frameworks. Mit 43,3% liegt jQuery deutlich vor dem zweitplatzierten React.js. Es folgen Angular mit 25,1%, ASP.NET mit 21,9% und Express mit 21,2%. Im Vergleich mit vergangenen Umfragen kann jQuery zwar seinen Platz an der Spitze verteidigen, der Abstand zu den Verfolgern wird allerdings merklich weniger.

Unter den verwendeten Plattformen dominieren weiterhin Linux (55%) auf dem ersten und Windows (53,1%) auf dem zweiten Platz, dahinter reihen sich Docker, AWS, Android und MacOS ein.

Neben der Frage nach den tatsächlich verwendeten Technologien, lohnt sich ein Blick auf die Technologien, die sich unter Entwicklern großer Zufriedenheit erfreuen und welche als interessant für
eine zukünftige Beschäftigung angesehen werden.

International JavaScript Conference

Effective Microservices Architecture In Node.js

by Tamar Stern (Palto Alto Networks)

React Components And How To Style Them

by Jemima Abu (Telesoftas)

Angular Camp 2020

Als Online- oder Präsenztraining!

Das 360°-Intensivtraining mit Angular-Koryphäe Manfred Steyer
Präsentiert von Entwickler Akademie


Einen beinahe erdrutschartigen Sieg kann Rust einfahren. Mit 86,1% zufriedener Entwickler liegt die Multiparadigmen-Systemprogrammiersprache uneinholbar vorne. Dadurch zeichnet sich folgendes Bild: Rust wird nur von einem Bruchteil der Teilnehmer aktiv und regelmäßig verwendet (5,1%), erfreut sich in diesem Kreise allerdings der allerhöchsten Beliebtheit.

Ein knappes Rennen liefert sich TypeScript und Python um den zweiten Platz. Denkbar knapp konnte sich TypeScript am Ende mit 67,1% zu 66,7% durchsetzen und überholt den Vorjahreszweiten. Es folgen Kotlin, Go und Julia.

Quelle: https://insights.stackoverflow.com/survey/2020

Interessiert sind Entwickler laut den gesammelten Daten besonders am Erlernen von Python, JavaScript und Go.

Was zahlt sich aus? Die best bezahlten Technologien

Eine weitere wichtige Kategorie der Umfrage beschäftigt sich mit dem durchschnittlichen Einkommen der jeweiligen Programmiersprachen. Weltweit gesehen teilen sich hier zwei Sprachen den ersten Platz mit 76.000$: Perl und Scala. Für Perl liefern die Verfasser der Umfrage auch direkt eine mögliche Erklärung mit, gehört die Sprache doch mit zu den unter Entwicklern unbeliebtesten. Ein Engpass an Experten könnte eine mögliche Ursache für das hohe Durchschnittsgehalt sein. Auch den dritten Platz teilen sich mit Go und Rust zwei Sprachen (jeweils 74.000$). Abgeschlossen wird die Top 5 mit Ruby (71.000$).

Quelle: https://insights.stackoverflow.com/survey/2020

Die gesamte Stack Overflow Survey 2020 findet sich auf der offiziellen Webseite.

Der Beitrag Stack Overflow Survey 2020: Rust und JavaScript weiter an der Spitze ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/development/stackoverflow-survey-2020-579935514.html/feed 0
Gemeinsam mehr erreichen https://entwickler.de/online/development/cqrs-ddd-579935366.html https://entwickler.de/online/development/cqrs-ddd-579935366.html#respond Thu, 28 May 2020 05:58:42 +0000 https://entwickler.de/?p=579935366 Die Verbreitung der Akronyme CQRS und DDD nimmt seit einigen Jahren stetig zu: Vor allem im Kontext von Microservices begegnet man den beiden Konzepten immer häufiger. Was steckt dahinter?

Der Beitrag Gemeinsam mehr erreichen ist auf entwickler.de erschienen.

]]>
Die Verbreitung der Akronyme CQRS und DDD nimmt seit einigen Jahren stetig zu: Vor allem im Kontext von Microservices begegnet man den beiden Konzepten immer häufiger. Was steckt dahinter?

CQRS steht für Command Query Responsibility Segregation und bezeichnet die strikte Trennung der Schreib- und der Lesevorgänge einer Anwendung beziehungsweise eines API. In der klassischen Anwendungsarchitektur wird die mittlere Ebene, die typischerweise über ein API verfügt, als eine in sich geschlossene Einheit gesehen, auf die vom UI aus zugegriffen wird. CQRS schlägt stattdessen vor, die Aktionen des Benutzers ganz klar zu kategorisieren:

  • Auf der einen Seite stehen Commands, die eine Intention des Benutzers ausdrücken und zumeist eine Zustandsänderung innerhalb der Anwendung nach sich ziehen. Da sie die Intention ausdrücken, sollten sie nicht mit Create, Update und Delete benannt werden. Diese Verben bezeichnen nämlich technische Implikationen, nicht fachliche Absichten. In der Fachsprache tauchen üblicherweise andere, domänenspezifische Begriffe auf, die sich in den Commands entsprechend wiederfinden sollten.

  • Auf der anderen Seite stehen Queries, die den aktuellen Zustand der Anwendung abfragen, ihn aber nicht ändern. Queries entsprechen also reinen Lesevorgängen, wohingegen Commands das Schreiben in einer Anwendung repräsentieren.

Viel mehr als das ist CQRS zunächst einmal nicht. Es sagt insbesondere nichts über die konkrete Implementierung aus, auch nicht über die Struktur der Datenhaltung. CQRS gibt noch nicht einmal vor, wie das API strukturiert und seine Routen benannt sein sollten: Wichtig ist einzig und allein, dass das Schreiben vom Lesen getrennt wird – auf welche Art auch immer.

CQRS in einem API implementieren

Eine einfache Möglichkeit, CQRS in einem API zu implementieren, besteht darin, sich gedanklich von REST zu verabschieden und stattdessen nur noch POST und GET einzusetzen. POST steht dabei aus naheliegenden Gründen für schreibende Vorgänge (also für Commands), GET wird hingegen zum Lesen (also für Queries) verwendet. Da die Semantik wie Anlegen, Ändern oder Löschen von Dingen nun nicht mehr über das HTTP-Verb ausgedrückt wird, muss die eigentliche Aktion Bestandteil des URL werden.

Queries beziehen sich immer auf den aktuellen Stand und entsprechen vom Verb her letztlich immer dem Lesen. Bei ihnen genügt deshalb eine substantivische Beschreibung, welche Daten des Zustands gelesen werden sollen.

Bevor man beginnt, ein API zu implementieren, lohnt es sich, eine Liste der gewünschten Commands und Queries zu erstellen und zumindest für einen Moment über ihre Benennung nachzudenken. Das wiederum funktioniert natürlich nur in einem gegebenen fachlichen Kontext. Deshalb wird im weiteren Verlauf des Artikels eine einfache To-do-Listen-Anwendung als Beispiel verwendet, wie man sie beispielsweise aus dem Projekt TodoMVC [1] kennt.

Doch selbst das genügt noch nicht, um festzulegen, welche Commands und Queries man benötigt. Dafür muss nämlich zuerst noch mehr Klarheit bezüglich der tatsächlichen Funktionalität geschaffen werden. Abbildung 1 zeigt das dazu passende UI:

  • Der Anwender soll sich neue Aufgaben notieren können, wobei eine Aufgabe lediglich aus einer Beschreibung besteht.

  • Die Beschreibung einer Aufgabe soll sich auch im Nachhinein noch ändern lassen.

  • Aufgaben können, wenn sie erledigt wurden, vom Anwender abgehakt werden.

  • Das Abhaken einer Aufgabe soll sich zurücknehmen lassen. Das ist beispielsweise dann relevant, wenn eine Aufgabe fälschlicherweise oder aus Versehen abgehakt wurde.

  • Gelegentlich erübrigen sich Aufgaben im Lauf der Zeit auch von selbst. Sie sind zwar hinfällig, aber genau genommen nicht erledigt. Insofern wäre es falsch, sie abzuhaken. Vielmehr sollen solche Aufgaben verworfen werden können.

  • Zu guter Letzt soll es für den Anwender möglich sein, erledigte beziehungsweise hinfällige Aufgaben zu archivieren. Solche Aufgaben sollen dann zwar nicht gelöscht werden, über das UI aber nicht mehr sichtbar sein.

Abb. 1: UI der To-do-Anwendung

Abb. 1: UI der To-do-Anwendung

Wie bereits erwähnt empfiehlt es sich an der Stelle, nicht aus Gewohnheit auf Create, Update und Delete zu setzen, sondern Begriffe zu suchen, die auch in der Fachlichkeit enthalten sind. Das führt dazu, dass das API und die Fachlichkeit näher aneinanderrücken, was das Verständnis der Verwendern für das API wiederum verbessert: Man muss nicht eine fachliche und eine technische Sprache und das Mapping zwischen beiden lernen – es genügt, wenn man sich in der Fachsprache auskennt.

Commands und Queries definieren

Das Command zum Notieren einer neuen Aufgabe sollte also nicht Create Task heißen, denn Create ist von seiner Bedeutung her zu weit weg von „notieren“ (abgesehen davon handelt es sich bei der Anwendung um eine To-do- und nicht um eine Taskliste, weshalb auch das Wort Task unpassend ist). Deutlich besser wäre daher z. B. Note Todo.

Auch das Bearbeiten einer Aufgabe ist nicht einfach nur ein Update Todo, da Update ein Wort ist, das einen technischen Vorgang beschreibt, aber keinen fachlichen. Besser, weil inhaltlich treffender, wäre hier etwa Edit Todo. Spätestens beim Abhaken, dem Verwerfen und dem Archivieren merkt man sehr deutlich, wie unpassend Update und Delete sind: Während das eine viel zu unspezifisch ist, trifft das andere genau genommen in keinem einzigen Fall zu – schließlich sollen die verschiedenen Aktionen rückgängig gemacht werden können, und beim Archivieren ist sogar explizit gefordert, dass die Aufgabe zwar nicht mehr angezeigt, aber eben nicht gelöscht wird. Würde man sich hier mit dem klassischen Vokabular begnügen, hätte man lauter Update Todo-Commands, die man nicht voneinander unterscheiden könnte und die deshalb ziemlich beliebig wären.

Passender wären zum Beispiel Tick Off Todo, Resume Todo und Discard Todo zum Abhaken, Fortsetzen und Verwerfen von Aufgaben. Zum Archivieren schließlich könnte man das naheliegende Archive Todo verwenden. Benennt man nun die Routen des API entsprechend, hat man ein sprechendes API, bei dem man sich nicht über die (am Ende doch nur mangelhafte) Zuordnung von HTTP-Verben zu fachlichen Aktionen Gedanken machen muss, und das sich – wenn man die Fachlichkeit kennt – intuitiv verwenden lässt:

POST /note-todo
POST /edit-todo
POST /tick-off-todo
POST /resume-todo
POST /discard-todo
POST /archive-todo

Alle diese Formulierungen stehen bereits im Imperativ, also in der Befehlsform, was hervorragend die Tatsache widerspiegelt, dass es sich um Commands handelt: Der Anwender beauftragt den Computer bzw. die Anwendung damit, etwas für ihn zu erledigen, was den Zustand der Anwendung verändert. Genau das trifft die zuvor beschriebene Erklärung eines Commands in CQRS. Es repräsentiert die Intention des Anwenders und verändert den Zustand der Anwendung.

Die Queries lassen sich nach diesen Vorüberlegungen deutlich einfacher formulieren. Da das Verb bei ihnen festgeschrieben ist, genügt wie bereits erwähnt eine substantivische Beschreibung dessen, was zu lesen ist. Im einfachsten Fall ist das eine Liste aller noch nicht archivierten Aufgaben, unabhängig von ihrem sonstigen Zustand. Selbstverständlich könnte man noch weitere Sichten auf die Daten definieren, aber da eine To-do-Liste selten Tausende von Einträgen enthält, kann man es sich an der Stelle auch einfach machen und eine einzige Liste für alles verwenden und sie gegebenenfalls auf dem Client filtern: GET /todos

Und die Datenhaltung?

Damit ist nun das API gemäß CQRS definiert. Die Implementierung eines Clients dürfte relativ einfach vonstattengehen und auch der Server dürfte nicht allzu schwierig umzusetzen sein. Interessant ist an der Stelle höchstens noch die Frage nach der Datenhaltung. Sollte man, wenn man statt REST auf ein CQRS-basiertes API setzt, eine klassische relationale Datenbank zum Speichern von Daten verwenden?

Auf den ersten Blick spricht nichts dagegen. Ein erster Entwurf für ein Datenmodell könnte vorsehen, dass es eine Tabelle namens Todos gibt. Die Commands würden auf den einzelnen Datensätzen dieser Tabelle agieren und die Query würde alle Datensätze zurückgeben, die nicht als archiviert markiert wurden. Die einzige Herausforderung an der Stelle ist das Mapping von fachlichen auf technische Konstrukte: So würde in der Datenbank das Note Todo beispielsweise einem INSERT entsprechen, alle anderen Commands hingegen einem UPDATE.

Den aktuellen Anforderungen würde dieser Ansatz genügen, doch wäre er nicht besonders ausbaufähig. Insbesondere für das Reporting ist dieses Vorgehen nicht besonders gut geeignet, da keinerlei historische Informationen aufbewahrt werden. Gerade bei einer To-do-Liste könnte es aber interessant sein, gewisse Statistiken aus den Daten zu ermitteln. Beispielsweise könnte man folgende Fragen beantworten wollen:

  • Wie viel Zeit vergeht zwischen dem Notieren und dem Abhaken einer Aufgabe?

  • Wie häufig wird eine Aufgabe editiert, bevor sie abgehakt wird?

  • Wie viele Aufgaben werden verworfen, obwohl sie zuvor mindestens dreimal editiert wurden?

  • Wie häufig wird innerhalb von 30 Sekunden das Abhaken rückgängig gemacht?

Diese Liste ließe sich endlos fortsetzen. Das Erschreckende daran ist, dass sich keine einzige dieser Fragen ohne Weiteres beantworten ließe, weil die Datenbasis diese Informationen nicht enthält. Theoretisch hätte man diese Informationen aber speichern können – schließlich sind alle Aktionen, nach denen gefragt wird, irgendwann passiert. Warum liegen sie dann nicht vor?

Das Problem liegt darin begründet, dass das beschriebene Vorgehen die Historie verliert. Editiert ein Anwender beispielsweise eine Aufgabe mehrfach, lassen sich die einzelnen Bearbeitungsschritte nicht mehr nachvollziehen. Schlimmer noch: Es lässt sich noch nicht einmal mehr nachvollziehen, wann oder ob die Aufgabe überhaupt jemals editiert wurde. Selbstverständlich kann man das in den Griff bekommen, indem man ein Feld für einen Zeitstempel der letzten Aktualisierung einfügt. Doch auch das hilft noch nicht in allen Fällen, da sich die einzelnen Bearbeitungsstände nicht separat abrufen lassen. Hierzu müsste man entweder eine ganze Reihe von Feldern oder gleich eine neue Tabelle anlegen.

Da man nicht weiß, welche Datenabfragen zukünftig gestellt werden, kann man die Tabellen nicht auf die entsprechenden Antworten optimieren. Man sammelt daher entweder zu viele oder zu wenige Daten, ganz sicher aber stets die falschen. Werden dann Fragen wie die oben genannten gestellt, lassen sie sich – wenn überhaupt – nur mit Glück beantworten. In der Regel wird die Antwort auf jede dieser Fragen lauten, dass man zunächst Code schreiben müsse, der die dafür relevanten Daten erfasst und speichert. Anschließend müsse man lediglich noch ein paar Wochen oder Monate warten, und schon könne man die gewünschte Auswertung liefern. Dass das alles andere als befriedigend ist, liegt auf der Hand.

Vom Status quo zu Domain Events

Was man also braucht, ist eine andere Art der Datenspeicherung: Anstatt den aktuellen Zustand zu speichern, sollte man die einzelnen Veränderungen speichern, die zum Status quo geführt haben. Das klingt zunächst danach, als ob man die eingegangenen Commands sammeln sollte. Commands haben jedoch die Eigenschaft, dass eine Anwendung sie ausführen oder verweigern kann. Aus der reinen Tatsache, dass ein Command an ein API geschickt wurde, lässt sich noch nicht folgern, dass es auch erfolgreich ausgeführt wurde. Viel interessanter als das reine Command ist also die Reaktion darauf: Was wurde von der Anwendung in fachlicher Hinsicht entschieden, sozusagen als Reaktion auf das Command? Diese Reaktionen sind schnell identifiziert, da sie sich – zumindest im vorliegenden Beispiel – originär auf die Commands abbilden lassen. Das muss jedoch nicht bei jeder Anwendung so sein und insbesondere bei komplexeren Anwendungen ist das Vorgehen nicht mehr ganz so einfach:

  • Eine Aufgabe wurde notiert.

  • Eine Aufgabe wurde editiert.

  • Eine Aufgabe wurde abgehakt.

  • Eine Aufgabe wurde fortgesetzt.

  • Eine Aufgabe wurde verworfen.

  • Eine Aufgabe wurde archiviert.

Es fällt auf, dass alle diese Formulierung in der Vergangenheitsform stehen. Das hat den einfachen Grund, dass es sich hierbei um Fakten handelt, die als Reaktion auf ein Command entstanden sind. Diese Dinge sind passiert und es gibt nichts auf der Welt, das man tun könnte, um diese Ereignisse ungeschehen zu machen. Natürlich lässt sich eine Gegentransaktion ausführen, doch die reine Tatsache, dass ein Ereignis einmal stattgefunden hat, ist unumkehrbar. Der Effekt lässt sich ausgleichen – das Ereignis an sich nicht.

Diese Ereignisse werden als Domain Events bezeichnet und sie lassen sich in einer immer weiterwachsenden Liste von Ereignissen speichern. Dafür eine Datenbankstruktur aufzusetzen, ist sehr simpel: Außer INSERT und SELECT wird nichts benötigt. Wie das API bei CQRS reduziert man an der Stelle nun also die Datenbank auf einfaches Schreiben und Lesen. Als Ergebnis erhält man eine Liste, die der im Listing 1 ähnelt. Zusätzlich zu den bereits beschriebenen Informationen enthält sie außerdem noch eine id-Spalte, damit man mehrere Aufgaben unterscheiden kann, und eine order, mit der sich die Reihenfolge der Events in Bezug auf eine Aufgabe ermitteln lässt.

id    eventType         order    timestamp		payload
1     todoNoted		1         29.12.2019 19:05	{ description: 'go shoping' }
1     todoEdited	2         29.12.2019 19:07	{ description: 'go shopping' }
1     todoTickedOff     3         02.01.2019 10:13	{}
1     todoArchived      4         02.01.2019 13:49	{}

Speichert man Domain Events auf diese Weise, kann man nicht nur den aktuellen Zustand einer Aufgabe wieder ermitteln, sondern auch die zuvor angesprochenen Fragen beantworten:

  • Wie viel Zeit vergeht zwischen dem Notieren und dem Abhaken einer Aufgabe? Anders formuliert: Wie viel Zeit liegt zwischen dem todoNoted und dem todoTickedOff Event? Die Antwort lässt sich anhand des Timestamp rasch ermitteln: Zwischen den beiden Domain Events sind 3 Tage, 15 Stunden und 8 Minuten vergangen. Berechnet man diese Differenz für mehrere Aufgaben, kann man außerdem angeben, wie viel Zeit üblicherweise im Durchschnitt pro Aufgabe vergeht.

  • Wie häufig wird eine Aufgabe editiert, bevor sie abgehakt wird? Anders formuliert: Wie viele todoEdited Events gibt es nach dem todoNoted Event, aber vor dem zugehörigen todoTickedOff Event? Die Antwort für die Beispielaufgabe lautet 1.

  • Wie viele Aufgaben werden verworfen, obwohl sie zuvor mindestens dreimal editiert wurden? Anders formuliert: Wie viele Aufgaben weisen mindestens drei todoEdited und außerdem auch ein todoDiscarded Event auf? Im vorliegenden Beispiel trifft das nicht zu, weshalb die Antwort 0 lautet.

  • Wie häufig wird innerhalb von 30 Sekunden das Abhaken rückgängig gemacht? Anders formuliert: Bei wie vielen Aufgaben folgt innerhalb von 30 Sekunden ein todoResumed Event auf ein todoTickedOff Event? Da in dem Beispiel kein todoResumed Event enthalten ist, liegt die Häufigkeit bei 0.

Diese Art der Datenspeicherung nennt man Event Sourcing, weil Domain Events als Quelle genutzt werden, um Informationen zu ermitteln. Eine Datenbank, die wie die zuvor beschriebene Liste funktioniert, nennt man Event Store. Es liegt auf der Hand, dass man CQRS und Event Sourcing unabhängig voneinander nutzen kann – immerhin kam Event Sourcing in der Beschreibung von CQRS zunächst nicht vor und selbstverständlich lassen sich auch Ereignisse in einer Liste speichern, ohne dass das damit verbundene API nach CQRS strukturiert sein muss. Aber man kann die beiden Konzepte eben auch wunderbar miteinander verbinden.

Wenn man so vorgehen möchte, resultieren Commands also letztlich in Domain Events, die in einem Event Store gespeichert werden. Zum Auslesen müssen die Domain Events wieder abgespult werden. Dieser Vorgang wird als Replay bezeichnet. Allerdings gibt es dabei auch einen gravierenden Haken: Je mehr Events gesammelt und gespeichert werden, desto länger dauert es, ein Replay durchzuführen, da die Anzahl der Events zunehmend größer wird.

Allerdings gibt es einen einfachen Ausweg. Da Domain Events per Definition niemals geändert oder gelöscht werden, ergibt ein Replay bis zu einem bestimmten Zeitpunkt immer dasselbe Ergebnis. Um beim obigen Beispiel zu bleiben: Es spielt für den Replay der ersten drei Events keine Rolle, ob danach noch weitere Events kommen oder nicht – und wenn ja, wie viele. Das wiederum bedeutet, dass sich das Ergebnis eines Replays problemlos cachen lässt. Ein solcher zwischengespeicherter Wert wird beim Event Sourcing als Snapshot bezeichnet. Statt einen Replay stets von Anfang an durchführen zu müssen, kann man daher auf einen Snapshot zurückgreifen und muss nur noch die seither aufgetretenen Events abspielen, um auf den aktuellen Stand zu kommen. Werden solche Snapshots regelmäßig geschrieben, lässt sich damit eine nahezu lineare Performance erzielen. Außerdem lässt sich das Konzept dazu nutzen, Views vorzuberechnen: Schreibt man stets nach jedem Event einen neuen Snapshot, hat man jederzeit den aktuellen Zustand der Anwendung griffbereit und kann ihn präsentieren.

Semantik und Struktur von Domain Events

Da CQRS und Event Sourcing zwei technisch geprägte Konzepte sind, lösen sie auch ausschließlich technische Probleme. Die Semantik und Struktur von Domain Events ergibt sich jedoch weder aus dem einen noch aus dem anderen – ob Events also sinnvoll modelliert sind und fachlich relevante Daten enthalten, wird durch CQRS und Event Sourcing nicht beeinflusst. Die beiden Mechanismen beschreiben lediglich, wie sich Daten auf Basis von Events speichern und wie sich fachlich sprechende APIs entwickeln lassen. Woher kommt also die Semantik? Beziehungsweise wie geht man beim Entwurf einer Anwendung vor, um sicherzugehen, dass die verwendeten Commands und Events auch tatsächlich das abbilden, was der Fachlichkeit nützt?

Das ist aus naheliegenden Gründen keine technische Frage, weshalb sie sich auch nicht technisch beantworten lässt. Stattdessen benötigt man ein Konzept, um fachliche Konzepte bereits beim Entwurf und während der Entwicklung zu verstehen, zu greifen und in Code zu implementieren. Genau hier kommt der Ansatz Domain-driven Design (DDD) ins Spiel: DDD ist eine Methodik, um in einem interdisziplinären Team ein gemeinsames Verständnis und eine gemeinsame Sprache für die Fachlichkeit zu entwickeln. DDD rückt also, anders als beispielsweise Test-driven Design (TDD) kein technisches Artefakt in den Fokus, sondern die Fachlichkeit und deren Verständnis.

Dadurch kommunizieren unter anderem Fachexperten, Entwickler und Designer frühzeitig miteinander und bekommen auf diesem Weg ein gemeinsames Verständnis der zu entwickelnden Thematik. Die gemeinsame Sprache, die in DDD als Ubiquitous Language bezeichnet wird, vereinfacht die Kommunikation in den späteren Phasen der Entwicklung spürbar. Obwohl die Begriffe dieser Sprache von der modellierten Fachdomäne abhängen, folgen sie doch gewissen Regeln.

So gibt es in DDD beispielsweise wie in CQRS Commands, die die Wünsche der Anwender darstellen. Domain Events hingegen sind die von der Anwendung als Reaktionen auf die Commands geschaffenen Fakten, die nicht mehr veränderlich sind und deshalb in der Vergangenheitsform stehen. Das klingt inzwischen bereits vertraut, obwohl es unabhängig von CQRS und Event Sourcing entstanden ist. Die gemeinsame Logik der Commands und Events ist in sogenannten Aggregates gekapselt, die zudem auch den Zustand der Anwendung in logische Einheiten kapseln. Eine der Besonderheiten von DDD ist, dass es nicht die Daten der Anwendung in den Mittelpunkt rückt, sondern die Prozesse. Warum das wichtig ist, hat Steve Yegge sehr anschaulich in seinem lesenswerten Blogeintrag „Execution in the Kingdom of Nouns“ [2] beschrieben.

Gemeinsam mehr erreichen

Obwohl DDD unabhängig von CQRS und Event Sourcing entstanden ist und sich daher unabhängig von diesen beiden Ansätzen einsetzen lässt, ergänzen sich die drei Konzepte hervorragend. Dabei wird den Events eine tragende Rolle zuteil: In DDD fungieren sie als fachliche und semantische Grundlage für die Modellierung. In Event Sourcing legt bereits der Name nahe, dass es ebendiese Events sind, die es als Veränderungen zu speichern gilt. Und in CQRS dienen Events schließlich der Synchronisation von Schreib- und Leseseite. Abbildung 2 stellt den Zusammenhang zwischen DDD, Event-Sourcing und CQRS an Hand des Datenflusses einer Anwendung grafisch dar. Im Write Model, also der Schreibseite der Anwendung, verwendet man DDD, um eingehende Commands zu verarbeiten und sie in Domain Events zu transformieren. Diese Events legt man anschließend mit Hilfe von Event Sourcing in einen Event Store. Danach werden die Events für die Synchronisation der Schreib- und der Leseseiten, die in einer CQRS-Anwendung existieren, an das Read Model übertragen. Dort interpretiert man die Events und aktualisiert die zu lesenden Views gemäß den individuellen Anforderungen.

Abb. 2: Zusammenhang zwischen DDD, Event Sourcing und CQRS

Abb. 2: Zusammenhang zwischen DDD, Event Sourcing und CQRS

Auf diese Art fügen sich die drei Konzepte wie Puzzleteile zu einem großen Ganzen zusammen. Als Ergebnis erhält man einen Ansatz zum Entwickeln von Anwendungen, der sich nah an der Fachlichkeit bewegt, hervorragende Analysemöglichkeiten bietet, und der sich außerdem gut skalieren lässt. Dank des Einsatzes von DDD ist von Vornherein ein interdisziplinäres Team involviert, weshalb auf diesem Weg in kürzerer Zeit bessere Software gelingt.

Fazit

Selbstverständlich gibt es zu jedem der drei einzelnen Konzepte, CQRS, Event Sourcing und DDD, noch weitaus mehr zu schreiben. Insbesondere gibt es, bedingt durch die andere Art der Architektur, eine Reihe von Sonderfällen, die man zwar nicht alle im finalen Code berücksichtigen muss, denen man sich aber zumindest bewusst sein sollte. Folgt man während der Entwicklung von Software diesen Konzepten, erhält man als Ergebnis eine Reihe von Vorteilen gegenüber klassischer Architektur und einem herkömmlichen Vorgehensmodell – man hat aber eben auch mit einer anderen Art von Problemen zu kämpfen.

Ob die Vor- oder die Nachteile überwiegen, muss für jede Anwendung einzeln bewertet werden. Tendenziell lässt sich aber sagen, dass es kein Vorgehen gibt, das keinerlei Probleme mit sich brächte, man durch den Einsatz von CQRS und Co. aber zumindest eine ganze Reihe üblicher Probleme lösen kann – was insbesondere im Bereich der Datenauswertung praktisch ist. Auch die Tatsache, dass DDD zu einem besseren Verständnis der Fachlichkeit bei allen Beteiligten führt, ist ein enormer Gewinn: Wer schreibt schließlich bessere Software als der, der nicht nur technisch, sondern auch fachlich weiß, was er tut?

 

Der Beitrag Gemeinsam mehr erreichen ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/development/cqrs-ddd-579935366.html/feed 0
Req4Arcs: BDD und/oder Domain Storytelling https://entwickler.de/online/agile/kolumne-req4arcs-bdd-agile-579935357.html https://entwickler.de/online/agile/kolumne-req4arcs-bdd-agile-579935357.html#respond Thu, 28 May 2020 05:52:02 +0000 https://entwickler.de/?p=579935357 In den letzten Folgen haben wir Ihnen Optionen für die Darstellung und Klärung funktionaler Anforderungen aufgezeigt. Eingestiegen sind wir über Geschäftsprozesse und haben anschließend die Granularität in kleinen Schritten bis zu User Stories verfeinert [1]. In der letzten Folge haben Sie dann einige Aspekte des Knowledge Crunchings aus dem Domain-driven Design kennengelernt, insbesondere Event Storming und die Ubiquitous Language [2]. Nun stellen wir Ihnen noch eine dritte Perspektive für funktionale Anforderungen vor, nämlich Beispiele.

Der Beitrag Req4Arcs: BDD und/oder Domain Storytelling ist auf entwickler.de erschienen.

]]>
In den letzten Folgen haben wir Ihnen Optionen für die Darstellung und Klärung funktionaler Anforderungen aufgezeigt. Eingestiegen sind wir über Geschäftsprozesse und haben anschließend die Granularität in kleinen Schritten bis zu User Stories verfeinert [1]. In der letzten Folge haben Sie dann einige Aspekte des Knowledge Crunchings aus dem Domain-driven Design kennengelernt, insbesondere Event Storming und die Ubiquitous Language [2]. Nun stellen wir Ihnen noch eine dritte Perspektive für funktionale Anforderungen vor, nämlich Beispiele.

Der Untertitel dieser Kolumne deutet unsere Intention an: Statt uns auf möglicherweise schwer verständliche Abstraktionen zu verlassen, versuchen wir durch möglichst konkrete Beispiele die wesentlichen (nicht alle!) Funktionen des Systems zu illustrieren.

Anforderungen durch Beispiele

Traditionelle Analyse- oder Modellierungsmethoden haben lange versucht, Sachverhalte (in unserem Fall: funktionale Anforderungen) ganzheitlich und gesamthaft (generisch) zu erfassen, unter Berücksichtigung von sowohl Normal- als auch Sonderfällen. Heraus kamen oftmals abstrakte Modell- oder Textkonstrukte. Bei denen besteht das große Risiko, dass Entwicklungsteams die Intention dieser Modelle nicht gut verstehen – und deswegen ihre eigene (und vermutlich fehlerhafte) Interpretation dieser Modelle in Quellcode implementieren.

Ein Beispiel für eine solche abstrakte Anforderung aus der Domäne Schulwesen:

Das System soll registrierten Schülerinnen und Schülern on- und offline den Zugriff auf Stunden-, Vertretungs- und Klausurpläne inklusive der Raumzuordnung erlauben.

In dieser Domäne Schulwesen ändern sich Vertretungs- und Raumpläne sehr häufig, weil Krankheiten oder Raumänderungen eben kurzfristig und ungeplant auftreten. Ein Offlinezugriff auf Vertretungspläne ergibt daher nur eingeschränkt Sinn. Hingegen sind Stundenpläne über Monate lang fix – die können wir prima dezentral speichern und natürlich offline anzeigen. Solche Details lassen sich oft nur schwer abstrakt formulieren. Alternativ dazu könnte eine Beschreibung auch anhand konkreter Beispiele erfolgen:

„Lea öffnet die App und sieht, dass am heutigen Dienstag der Matheleistungskurs um 10 Uhr in Raum R42 stattfindet und von Frau Yildiz vertreten wird. Franz hat kein Datenvolumen mehr, und sieht in der App, dass der Matheleistungskurs um 10 Uhr stattfindet, ohne Info zum Raum oder Lehrperson.“

Die Grundlagen für Spezifikationen anhand von Beispielen stammen von Ward Cunningham, der schon 1996 dazu publizierte. Den Begriff Specification by Example hat (laut Wikipedia) Martin Fowler im Jahr 2004 geprägt. Die erste ausführliche Darstellung präsentierte Gojko Adzic in seinem Buch „Specification by Example“ [3]. Wir haben Abbildung 1 daran angelehnt: Ausgehend von Businesszielen ermitteln Sie unbedingt Scope und Kontext Ihres Systems. Anschließend können Sie im Team kollaborativ einige Schlüsselbeispiele für die Funktionalität Ihres Systems beschreiben, die dann letztlich Grundlage für eine mögliche ausführbare Spezifikation darstellen (dazu weiter unten mehr). Mit „kollaborativ“ sind interaktive Workshops gemeint, in denen Fachexpert*innen aus erster Hand Beispiele fachlicher Abläufe schildern, sowie Entwicklungsteams, die Fragen dazu stellen und Feedback geben. Für komplexe fachliche Abläufe werden Sie sicher mehrere Personen benötigen, um Beispiele von Anfang bis Ende erarbeiten zu können.

Abb. 1: Spezifikation mit Beispielen (nach [4])

Abb. 1: Spezifikation mit Beispielen (nach [3])

Wie Sie in Abbildung 1 erkennen, dienen beispielhafte Spezifikationen auch als Grundlage für ausführbare Spezifikationen. Aber lassen Sie uns einen Schritt nach dem Nächsten gehen und zuerst einmal klären, wie Beispiele überhaupt aussehen könnten.

Beispiele im DDD: Domain Storytelling

Eine recht junge Kombination von Domain-driven Design und beispielhafter Spezifikation ist unter dem Namen Domain Storytelling (DS) in den Fokus gerückt: Stefan Hofer hat diesen Ansatz aus dem etablierten Werkzeug-Material-Ansatz der Hamburger Software-Engineering Schule entwickelt und damit eine sehr geschickte Kombination aus Diagrammen und Beispielen geschaffen. Im Domain Storytelling werden Beispiele mit einfachen Symbolen zu grafischen Geschichten aufbereitet, die im Team gemeinsam (kollaborativ) erarbeitet werden. Die Abbildungen 2 und 3 zeigen kleine Beispiele (passend zu den oben genannten verbalen Beschreibungen aus der Domäne Schulwesen).

Abb. 2: Domain Story „Offline-Auskunft“

Abb. 2: Domain Story „Offline-Auskunft“

Abb. 3: Domain Story „Online-Auskunft“

Abb. 3: Domain Story „Online-Auskunft“

Wir empfehlen Ihnen den ausgezeichneten Artikel zu Domain Storytelling von Stefan Hofer und Henning Schwentner – darin finden sich auch ein etwas größeres Beispiel und einige methodische Hinweise zum praktischen Einsatz.

Wir (Peter und Gernot) sind zwischen Bildern und Text hin- und hergerissen und haben keine eindeutige Präferenz. Manche unserer Stakeholder kommen prima mit textuellen Beispielen zurecht, andere mögen lieber grafische Notationen. Ein kurzer Domain-Storytelling-Workshop – eine bis zwei Stunden – kann Ihnen helfen, hier Klarheit zu schaffen.

Beispiele als ausführbare Spezifikation

Insbesondere finden wir an Beispielen nützlich, dass wir diese Art von Spezifikationen automatisiert ausführen (testen!) können: Beispiele in Form von Testfällen werden schon seit langer Zeit als Grundlage für Tests verwendet – da liegt es doch nahe, sie auch für die Klärung von Anforderungen heranzuziehen. An Test-driven Development (TDD) haben Sie sich als Architekt*in hoffentlich schon vor Jahren gewöhnt, da beschreiben Sie das Verhalten letztlich endlich auch exemplarisch. Diesen Gedanken hat Dan North schon 2009 weitergedacht, nämlich in Richtung ausführbarer Spezifikationen: Dan hat BDD (Behavior-driven Development) erstmalig 2009 auf einer Konferenz vorgestellt und als technische Lösung dazu JBehave gebaut. Mittlerweile gibt es mit YatSpec, Cucumber, Jasmine und Squish eine Reihe von Alternativen für unterschiedliche Programmiersprachen. Grundidee ist immer, Anforderungen in einer einfachen DSL exemplarisch zu beschreiben, die ein BDD Framework dann ausführen kann.

Fazit

Konkrete Beispiele können helfen, funktionale Anforderungen besser zu verstehen oder zu erklären als abstrakte Modelle das können. Mit Beispielen bekommen Sie niemals vollständige Spezifikationen, aber das ist in vielen Fällen auch gar nicht nötig. Technische Optionen wie Behavior-driven Development und/oder Domain Storytelling helfen, beispielhaft und anschaulich funktionale Anforderungen zu klären. BDD bringt zusätzlich die Option mit, Anforderungen als ausführbare(!) Spezifikation ständig auf ihre Einhaltung hin prüfen zu können.

Und als kleiner Ausblick: In den nächsten Folgen gehen wir das Thema Qualitätsanforderungen an, bei dem wir dann wiederum von Beispielen profitieren werden. Bis dahin möge die Macht guter Anforderungen mit Ihnen sein!

Links & Literatur

[1] Hruschka, Peter; Starke, Gernot: „Req4Arcs Kolumne: Vom Umgang mit funktionalen Anforderungen“, Java Magazin 5/2019.

[2] Hruschka, Peter; Starke, Gernot: „Req4Arcs Kolumne: Anforderungen mit DDD klären“, Java Magazin 6/2019.

[3] Adzic, Gojko: Specification by Example : How Successful Teams Deliver the Right Software”. Manning, New York, 2011.

Der Beitrag Req4Arcs: BDD und/oder Domain Storytelling ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/agile/kolumne-req4arcs-bdd-agile-579935357.html/feed 0
DevOps im Konzern: Autonomie von DevOps-Teams vs. Betriebssicherheit https://entwickler.de/online/agile/devops-autonomie-devops-teams-vs-betriebssicherheit-video-579935348.html https://entwickler.de/online/agile/devops-autonomie-devops-teams-vs-betriebssicherheit-video-579935348.html#respond Thu, 28 May 2020 05:34:14 +0000 https://entwickler.de/?p=579935348 Aus Sicht eines DevOps-Teams ist für eine hohe angestrebte Geschwindigkeit hohe Autonomie bei allen Architektur- und Implementierungsentscheidungen notwendig. Aus Sicht der DB Systel, die den stabilen IT-Betrieb der Deutschen Bahn sicherstellen soll, ist die Forderung nach Autonomie jedoch ein Risiko. Welche Lösungen es hierfür gibt, erläutern Johannes Dienst & Thomas Kappatsch in ihrer Session auf der JAX 2019.

Der Beitrag DevOps im Konzern: Autonomie von DevOps-Teams vs. Betriebssicherheit ist auf entwickler.de erschienen.

]]>
Aus Sicht eines DevOps-Teams ist für eine hohe angestrebte Geschwindigkeit hohe Autonomie bei allen Architektur- und Implementierungsentscheidungen notwendig. Aus Sicht der DB Systel, die den stabilen IT-Betrieb der Deutschen Bahn sicherstellen soll, ist die Forderung nach Autonomie jedoch ein Risiko. Welche Lösungen es hierfür gibt, erläutern Johannes Dienst & Thomas Kappatsch in ihrer Session auf der JAX 2019.

Zur Lösung dieses Konfliktes findet man daher in der Industrie häufig Ansätze, bei der Betriebseinheiten zentral betreute CI/CD-Pipelines bereitstellen. Während die mit dieser Lösung verbundene Automatisierung eine gute Kontrolle von Betriebsaspekten mit sich bringt, stellt die damit auch verbundene notwendige Standardisierung von Architekturaspekten häufig eine zu starke Einschränkung der Autonomie von DevOps-Teams dar.

In diesem Talk gehen Johannes Dienst und Thomas Kappatsch darauf ein, wie die DB Systel ihren DevOps-Teams durch Verortung der Betriebsverantwortung in den DevOps-Teams eine optimale Autonomie gewährt und gleichzeitig die Risiken für Stabilität, Datenschutz und Compliance kontrolliert. Sie geben Ihnen auch einen Einblick in den Alltag eines DevOps-Teams der DB Systel, aus Sicht eines Betroffenen. Wir stellen dar, wie hohe Autonomie und umfängliche Verantwortung eine völlig neue Arbeitsweise erfordern.

Der Speaker
Johannes Dienst ist Softwarearchitekt und Clean Coder aus Leidenschaft bei der DB Systel GmbH. Sein Tätigkeitsschwerpunkt liegt im Bereich der Enterprise Architecture Integration.
Thomas Kappatsch ist seit 1999 in der IT in zentralen IT-Einheiten von Enterprises wie der Dresdner Bank, Commerzbank und Deutsche Bahn beschäftigt und in ständig wechselnden Rollen als Entwickler, Teamleiter, Projektleiter, Architekt oder Enterprise Architect tätig. Zur Zeit ist er IT-Chefarchitekt bei der DB Systel und treibt als Enabler und Evangelist das Thema DevOps in die Deutsche Bahn. Er entwickelt und publiziert CI/CD-Lösungen für DevOps-Teams der Deutschen Bahn.

Der Beitrag DevOps im Konzern: Autonomie von DevOps-Teams vs. Betriebssicherheit ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/agile/devops-autonomie-devops-teams-vs-betriebssicherheit-video-579935348.html/feed 0
Women in Tech: „Lasst euch von niemand einreden, dass ihr irgendwas nicht könnt“ https://entwickler.de/online/karriere/women-in-tech-sappli-579935377.html https://entwickler.de/online/karriere/women-in-tech-sappli-579935377.html#respond Wed, 27 May 2020 10:13:59 +0000 https://entwickler.de/?p=579935377 In unserer Artikelserie „Women in Tech“ stellen wir inspirierende Frauen vor, die erfolgreich in der IT-Branche Fuß gefasst haben. Heute im Fokus: Isabell Sippli, Senior Technical Staff Member, IBM Hybrid DevOps & Management.

Der Beitrag Women in Tech: „Lasst euch von niemand einreden, dass ihr irgendwas nicht könnt“ ist auf entwickler.de erschienen.

]]>
In unserer Artikelserie „Women in Tech“ stellen wir inspirierende Frauen vor, die erfolgreich in der IT-Branche Fuß gefasst haben. Heute im Fokus: Isabell Sippli, Senior Technical Staff Member, IBM Hybrid DevOps & Management.

Die Tech-Industrie wird von Männern dominiert – so weit, so schlecht. Doch langsam, aber sicher bekommt der sogenannte Boys Club Gesellschaft von begabten Frauen: Immer mehr Frauen fassen in der Branche Fuß.

Aus diesem Grund wollen wir hier spannenden und inspirierenden Frauen die Möglichkeit geben, sich vorzustellen und zu erzählen, wie und weshalb sie den Weg in die Tech-Branche gewählt haben. Aber auch Themen wie Geschlechtervorurteile, Herausforderungen oder Förderungsmöglichkeiten kommen zur Sprache.

Unsere Woman in Tech: Isabell Sippli

Isabell-SippliIsabell Sippli widmete sich bereits während ihres Computer-Science-Studiums unter anderem den Themen Machine Learning und Künstliche Intelligenz. Nach ihrem Abschluss begann sie ihre Karriere als Software Engineer bei IBM , wurde Team Lead eines internationalen Teams, Lead Developer sowie Speakerin auf diversen internationalen Konferenzen. Aktuell arbeitet sie als Senior Technical Lead eines größeren Entwickler-Teams bei IBM.

Seit wann besteht Interesse für Tech und wie hast du die ersten Kontakte zum Tech-Themenbereich geknüpft?

Ich habe mein Interesse für Tech in der Oberstufe entdeckt – in einer Informatik AG. Außerdem waren meine Eltern immer sehr progressiv im Bezug auf neue Technologien – ich hatte als eine der Ersten meiner Klasse Zugriff auf einen Computer zu Hause und auch relativ früh Internetzugang. So habe ich nach und nach Freude am Ausprobieren entdeckt.

Das Informatikstudium hat mich gereizt, weil ich verstehen wollte, wie mein Computer im Hintergrund funktioniert und weil ich „richtig“ Programmieren lernen wollte. Ich war mir aber sehr unsicher ob das zu mir passt. Mit der Unsicherheit bin ich offen umgegangen – und habe meinen Eltern erklärt, dass ich große Lust habe, das Studium zu beginnen, es aber sein kann, dass ich eventuell einen anderen Weg einschlage. Nach dem ersten Praktikum war mir dann aber klar, dass das genau mein Ding ist =)

Wie verlief dein Weg bis zum jetzigen Job? Welche unterschiedlichen Karrierewege hast du eingeschlagen?

Nach mehreren Praktika und Werkstudententätigkeiten habe ich 2007 bei IBM im Germany R&D Labor als Software-Testerin angefangen. Nach einem halben Jahr bin ich dann in die Entwicklung gewechselt (damals war das noch strikt getrennt), und habe 5 Jahre hauptsächlich in Java/JEE entwickelt. Dort hatte ich auch erste kleine Führungsaufgaben, zum Beispiel als Implementation Lead für Features. Als ich das Gefühl hatte, nicht mehr wachsen zu können, bin ich in auf eine kundennahe Stelle gewechselt. Dort war ich als Lead Architektin verantwortlich für die Implementierung verschiedener Private Clouds bei europäischen Kunden und habe sowohl im Pre- als auch im Postsales gearbeitet. Die Zeit war sehr reiseintensiv und lehrreich.

Nach knapp 2 Jahren bekam ich ein Angebot im Stabsteam eines technischen Executives zu arbeiten und habe dort ein Jahr lang verschiedene Technologien auf ihre Produktreife und Eignung für das damalige Portfolio evaluiert. Anschließend bin ich in meinen jetzigen Wirkungsbereich gewechselt, als Architektin für ein neues SaaS-Produkt. Sukzessive habe ich mehr und mehr Verantwortung übernommen (mehr Components, größere Teams).

Seit 2017 bin ich Senior Technical Staff Member und als leitende Architektin für ein großes Entwicklungsteam verantwortlich.

Gab es Menschen, die dich auf deinem Weg gefördert haben? Hast du Vorbilder?

Ja, einige. Ich habe 2 (männliche) Mentoren innerhalb der IBM, die mich bestärkt haben, bestimmte Schritte zu gehen, und mir immer wieder die richtigen Fragen gestellt haben, um meinen Weg selbst zu finden. Dabei waren auch wichtige Türöffner, und ohne diese wäre ich jetzt nicht wo ich heute bin.

Steine hat man mir nicht in den Weg gelegt – Im Gegenteil.

Ich hatte das Glück, immer sehr unterstützende Manager und Mentor/innen zu haben, die mich gefördert und gefordert haben.

Ich habe einige Vorbilder, sowohl weiblich als auch männlich. Dazu gehören Kolleginnen, die es wunderbar geschafft haben, Familie und Führungsaufgabe zu vereinen, sowie eine Kollegin, selbst technische Executive, die mich im Besonderen mit ihrer Weitsicht, Freundlichkeit, technischer Kompetenz und bodenständiger Grundeinstellung beeindruckt.

Wie sieht ein typischer Arbeitstag in deiner aktuellen Position aus? Entwickelst du auch selbst?

Ich bin Senior Technical Staff Member im Bereich IT Operations Management. Ich habe die technische Leitung eines Software Produktes (mehr hier), das heißt ich gebe technische Leitlinien an meine Entwicklungsteams und diskutiere Lösungsansätze mit meinen Peers und Teams, erstelle Prototypen um Machbarkeit zu analysieren, spreche viel mit Kunden um deren Anforderungen zu verstehen und analysiere den Markt. Ich verbringe viel Zeit in Webkonferenzen, habe aber auch immer wieder ruhige Stunden um mich in technische Problem einzuarbeiten, weiter zu lernen und einfach auch mal mit Technologie zu spielen.

Ich habe am Anfang meiner Karriere ausschließlich programmiert, das ist aber mit meinen veränderten Verantwortlichkeiten weniger geworden. Trotzdem bleibe ich dran, mein letztes Projekt war ein kleines Command Line Tool in GO, um die Verwendung einer REST API einfacher zu machen.

Warum gibt es so wenige Frauen in der Tech-Branche? Welche Hürden müssen Frauen heute immer noch überwinden?

Darüber denke ich immer wieder nach, aber ich habe keine allumfassende Antwort. Ich glaube aber, dass die Sozialisierung von Jungen und Mädchen schon sehr früh in eine bestimmte Richtung drifted, und dass es zu wenig weibliche Vorbilder gibt. Ich finde, es passieren viele tolle Dinge, wie z. B. gender-neutrale Spielsachen, Girls Day, diese Interview-Serie, etc.

Allerdings brauchen Frauen je nach Hintergrund mehr Mut sich auf die Tech-Branche einzulassen, ungewöhnliche Wege zu gehen, und zu sich selbst sowie ihrer Herangehensweise zu stehen.

International JavaScript Conference

Effective Microservices Architecture In Node.js

by Tamar Stern (Palto Alto Networks)

React Components And How To Style Them

by Jemima Abu (Telesoftas)

Angular Camp 2020

Als Online- oder Präsenztraining!

Das 360°-Intensivtraining mit Angular-Koryphäe Manfred Steyer
Präsentiert von Entwickler Akademie


Welche Klischees/Stereotypen sind dir in Bezug auf „Women in Tech“ schon begegnet? Welche Probleme ergeben sich daraus?

Ich möchte betonen, dass ich in der glücklichen Lage bin, mit relativ wenig davon konfrontiert worden zu sein – da bin ich aber eher die Ausnahme.
Was mir begegnet ist:

  • „Frauen und Informatik, was willst denn du hier?“
  • „Du siehst gar nicht aus wie eine Informatikerin.“
  • „Du wirst nur gefördert weil du eine Frau bist.“
  • „Kinder und technische Karriere lassen sich nicht vereinbaren.“

Das ist rational gesehen alles Quatsch, aber emotional fühlt sich das manchmal nicht so an. Daraus entstehende Probleme sind aus meiner Sicht vor allem Abschreckung sowie Verunsicherung, was zum Ausbremsen junger weiblicher Talente.

Zum Thema Vereinbarkeit – es gibt in unserer Branche, in meiner Wahrnehmung zum Glück abnehmend, immer wieder eine „Workaholic Hero Culture“. Der Mythos vom ständig erreichbaren Techie, der jedes Problem lösen kann, egal zu welcher Uhrzeit. Davon lassen sich meiner Meinung nach einige Frauen abschrecken, weil sie schon vorab keine Vereinbarkeit mit Familie sehen.

Es mag solche Anforderungen geben, aber ich kenne viel mehr Jobs, die sich ganz wunderbar mit einem ausgewogenen Privatleben vereinbaren lassen.

Vor allem die flexiblen Arbeitszeiten, sowie das Homeoffice machen mir den Alltag sehr viel leichter.

Ich habe einen kleinen Sohn, und arbeite momentan 85%, mein Mann Vollzeit. In Nicht-Corona-Zeiten funktioniert das mit einer Kita prima, gerade ist es ein bisschen schwieriger und anstrengender, aber sicher deutlich einfacher als in anderen Branchen. Ich freu mich trotzdem, wenn die Kitas wieder aufmachen =)

Und warum sollten mehr Frauen in der Tech-Branche arbeiten? Würde unsere Welt anders aussehen, wenn mehr Frauen in MINT-Bereich arbeiten würden?

Weil es eine tolle, ständig wachsende und sich wandelnde Branche ist – ich könnte mir keinen spannenderen Arbeitsplatz vorstellen. Es gibt so viele Möglichkeiten zu lernen und sich zu entwickeln. Es gibt viele Studien, die zeigen, dass männlich-weiblich gemischte Teams besser performen, und deshalb sind mehr Frauen für alle ein Gewinn.

Ich weiß nicht, ob die Welt anders aussehen würde, aber unsere Branche wäre bunter, und die Ergebnisse sicher vielfältiger. Auch kann ich nicht einschätzen, wie Teams ganz ohne Frauen anfühlen, wenn ich teilnehme ist es ja kein reines Männer Team mehr. Ich habe allerdings von Kollegen Rückmeldungen erhalten, dass durch meine Anwesenheit mehr Ruhe einkehrt und insgesamt ein freundlicherer Umgang herrscht. Vorteile sehe ich für alle – und insbesondere für die Frauen, die sich dadurch die tollen Chancen innerhalb unserer Branche erschließen könnten. Ich glaube aber nicht, dass nur bestimmte Bereiche von Innovationen profitieren können. Wir sollten aufhören, bestimmte Bereiche als rein weiblich oder männlich zu betrachten.

Die Diversity-Debatte wird erst zu Ende sein, wenn für alle, egal welchen Geschlechts, Hautfarbe, sexueller Orientierung, Herkunft, gleiche Chancen zum Einstieg und Aufstieg bestehen – und es wird dauern bis das flächendeckend erreicht ist. IBM ist hier sicherlich Vorreiter und ich habe mich noch nie benachteiligt gefühlt, aber wenn man sich ein bisschen mit dem Thema beschäftigt, findet man schnell dunkle Flecken.

Tipps und Tricks

Traut euch, und seid neugierig! Sucht euch Vorbilder und Mentoren, und baut euch ein Netzwerk von Vertrauenspersonen auf. Verliert nie die Neugier und die Leidenschaft am Lernen, seid flexibel, und investiert in euch durch ständige Weiterbildung. Lasst euch von niemand einreden, dass ihr irgendwas nicht könnt – probiert es aus, und macht euch selbst ein Bild.

Man muss kein Hardcore-Techie sein, um in der Tech-Branche erfolgreich zu sein.

Und auch nicht schon von Kind auf Programmieren können. Ich habe in der Oberstufe zum ersten Mal programmiert, in einer AG, und bin dann relativ kalt ins Studium gestartet. Was ich da gelernt habe (aus den Kursen, in der Zusammenarbeit mit Kommilitonen, und in Praktika) hat für einen super Start ins Berufsleben gereicht. Voraussetzungen sind aus meiner Sicht Freude an Problemlösungen und Knobeln. Eine generelle Affinität zu Computern und das Interesse zu verstehen, wie Technik funktioniert, ist sehr hilfreich. Ich verbringe zum Beispiel meine Freizeit eher selten vor dem Bildschirm – sondern lieber mit meiner Familie, Freunden oder beim Yoga oder Reiten.

Der Beitrag Women in Tech: „Lasst euch von niemand einreden, dass ihr irgendwas nicht könnt“ ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/karriere/women-in-tech-sappli-579935377.html/feed 0
Laravel ORM im Einsatz: Was mit Eloquent ORM möglich ist https://kiosk.entwickler.de/entwickler-magazin/entwickler-magazin-3-2020/laravel-orm-im-einsatz/ https://kiosk.entwickler.de/entwickler-magazin/entwickler-magazin-3-2020/laravel-orm-im-einsatz/#respond Wed, 27 May 2020 10:00:40 +0000 https://entwickler.de/?p=579935263 Eloquent, das ORM (Object-relational Mapping) von Laravel, erleichtert die Kommunikation mit einer Datenbank ungemein. Anhand eines JSON API für ein Buchverleihtool zeigen wir, was man damit anstellen kann – komplett unabhängig vom dahinterliegenden Datenbanksystem.

Der Beitrag Laravel ORM im Einsatz: Was mit Eloquent ORM möglich ist ist auf entwickler.de erschienen.

]]>
Eloquent, das ORM (Object-relational Mapping) von Laravel, erleichtert die Kommunikation mit einer Datenbank ungemein. Anhand eines JSON API für ein Buchverleihtool zeigen wir, was man damit anstellen kann – komplett unabhängig vom dahinterliegenden Datenbanksystem.

Der Beitrag Laravel ORM im Einsatz: Was mit Eloquent ORM möglich ist ist auf entwickler.de erschienen.

]]>
https://kiosk.entwickler.de/entwickler-magazin/entwickler-magazin-3-2020/laravel-orm-im-einsatz/feed 0
Unter der Haube: Wie funktionieren neuronale Netze? https://entwickler.de/online/machine-learning/neuronale-netze-einfuehrung-video-henkelmann-579935272.html https://entwickler.de/online/machine-learning/neuronale-netze-einfuehrung-video-henkelmann-579935272.html#respond Wed, 27 May 2020 05:42:18 +0000 https://entwickler.de/?p=579935272 Jahrelang nur akademische Kuriosität und jetzt in aller Munde: neuronale Netze. Was es damit auf sich hat, wie sie funktionieren und was es dabei zu beachten gilt, erklärt Christoph Henkelmann (DIVISIO GmbH) in seiner Session auf der JAX 2019.

Der Beitrag Unter der Haube: Wie funktionieren neuronale Netze? ist auf entwickler.de erschienen.

]]>
Jahrelang nur akademische Kuriosität und jetzt in aller Munde: neuronale Netze. Was es damit auf sich hat, wie sie funktionieren und was es dabei zu beachten gilt, erklärt Christoph Henkelmann (DIVISIO GmbH) in seiner Session auf der JAX 2019.

Man liest viel darüber, wie angeblich Gehirne nachgebaut werden und der KI-Hype ist auf dem Höhepunkt. Aber was ist ein neuronales Netz wirklich? Was heißt es, wenn ein neuronales Netz „lernt”? Und was haben Tensoren damit zu tun? Christoph Henkelmann erklärt am Beispiel eines Standard-Multilayer-Netzwerks, wie ein neuronales Netz Voraussagen macht und wie es trainiert wird. Dabei werden die wichtigsten Schritte sowohl durch Formeln als auch durch Code erläutert.

Der Speaker
Christoph Henkelmann hat an der Universität Bonn Informatik studiert, wo er seine erste Bekanntschaft mit künstlicher Intelligenz und maschinellem Lernen machte. Dieses Thema hat ihn neben seiner Tätigkeit als Entwickler, Softwarearchitekt und Berater im Mobile- und Serverbereich immer begleitet. Als Mitgründer und technischer Geschäftsführer der DIVISIO GmbH aus Köln kann er sich nun voll auf den Einsatz von KI im geschäftlichen Umfeld konzentrieren, wobei ihm seine Erfahrung im Java Enterprise Bereich hilft, Theorie und Praxis zu verknüpfen.

 

Der Beitrag Unter der Haube: Wie funktionieren neuronale Netze? ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/machine-learning/neuronale-netze-einfuehrung-video-henkelmann-579935272.html/feed 0
AIOps: Auf dem Weg zum echten KI-Assistenten https://entwickler.de/online/machine-learning/aiops-ki-ai-machine-learning-579935279.html https://entwickler.de/online/machine-learning/aiops-ki-ai-machine-learning-579935279.html#respond Wed, 27 May 2020 05:11:59 +0000 https://entwickler.de/?p=579935279 AIOps ist eines der neuesten technologischen Schlagworte, das in der IT-Branche an Fahrt gewinnt. Die Gründe dafür sind vielfältig, eines steht allerdings fest: AIOps ist das Sprungbrett für eine Technologie, die es so zuvor noch nicht gegeben hat – ein echter Künstliche-Intelligenz-Assistent. Dieser beantwortet Fragen auf Augenhöhe mit einem menschlichen Netzwerk-Experten. Er geht außerdem proaktiv Herausforderungen an, die er erkennt.

Der Beitrag AIOps: Auf dem Weg zum echten KI-Assistenten ist auf entwickler.de erschienen.

]]>
AIOps ist eines der neuesten technologischen Schlagworte, das in der IT-Branche an Fahrt gewinnt. Die Gründe dafür sind vielfältig, eines steht allerdings fest: AIOps ist das Sprungbrett für eine Technologie, die es so zuvor noch nicht gegeben hat – ein echter Künstliche-Intelligenz-Assistent. Dieser beantwortet Fragen auf Augenhöhe mit einem menschlichen Netzwerk-Experten. Er geht außerdem proaktiv Herausforderungen an, die er erkennt.

AIOps (Künstliche Intelligenz gepaart mit Operations) bezieht sich auf Algorithmen, die IT-Operations-Teams einsetzen, um der wachsenden Komplexität der Daten und Vernetzung Herr zu werden. Gleichzeitig soll AIOps den anhaltenden Druck auf die IT-Budgets mildern. AIOps-Lösungen nutzen die gleiche Art von Machine Learning und fortschrittlichen Analyse-Tools, die bei Google Maps oder den vorausschauenden Fahrpreismodellen von Uber zum Einsatz kommen. IT-Abteilungen werden damit in die Lage versetzt, Probleme zu antizipieren und zu beheben, bevor die Anwender sie überhaupt bemerken.

Im selbstheilenden KI-Netzwerk der Zukunft erhalten Nutzer eine konstante Leistung. Die wertvollen IT-Ressourcen können dann verantwortungsvollere Aufgaben übernehmen, anstatt sich mit Support-Tickets herumzuschlagen.

Das Konzept AIOps bietet ein spannendes Potential hinsichtlich der Geschwindigkeit und Zuverlässigkeit drahtloser Netzwerke. Sie sind mittlerweile so unverzichtbar wie Wasser, Strom und Licht. Organisationen bauen unternehmenskritische Services für Verbraucher und Mitarbeiter darauf auf, damit sie in der heutigen mobilen und App-getriebenen Welt bestehen können. Daher müssen diese Netzwerke vorhersehbarer, messbarer und einfacher zu managen sein als jemals zuvor.

Dies bedeutet aber auch, dass Firmen einen transparenten Einblick in und umsetzbare Erkenntnisse aus den Petabytes an Daten benötigen, die durch ihre drahtlosen Netzwerke fließen. Nur dann sind sie in der Lage, ihre Infrastruktur in Echtzeit aktiv und automatisch anzupassen, um Ausfälle zu vermeiden, Leistungsspitzen abzufedern und die Performance zu optimieren. CIOs müssen verstehen, welches die richtigen Schritte sind, um AIOps als Grundlage für ein KI-basiertes, selbstständig agierendes Netzwerk zu nutzen. Die folgenden fünf Prioritäten sollten Firmen im Auge behalten.

1. Die Weichen für eine echte KI stellen

Ähnlich wie KI-Systeme für autonom fahrende Fahrzeuge oder zur Diagnose von Krankheiten wird die echte KI während des IT-Betriebs intelligenter. Der Grund dafür: Sie analysiert im Laufe der Zeit immer mehr Daten und verbessert so ihre Fähigkeiten zu einer autonomen Kontrolle und Reparatur des Netzwerks.

Einige Lösungen, die derzeit auf dem Markt sind und als KI bezeichnet werden, sind eher umfassendere Anwendungen zur Datenerfassung oder Applikationen, die hohe Mengen an Daten verarbeiten. Sie sind bestens dafür geeignet, Statistiken zu sammeln und zu analysieren. Allerdings fehlen ihnen die grundlegenden KI-Technologien für ein selbstständig agierendes KI-Netzwerk. Organisationen sollten darauf achten, dass sie ihre AIOps-Plattform vor der Implementierung genau unter die Lupe nehmen, um zu gewährleisten, dass sie über alle notwendigen Komponenten verfügt. Dazu gehören unter anderem:

  • Daten-Pipeline unterstützt Daten aus verschiedenen Quellen
  • KI-Primitives bieten die Möglichkeit, den Daten-Domänen-Wissen hinzuzufügen
  • Bibliothek an Data-Science-Algorithmen: Deep Learning ist Teil der Toolbox
  • Eine Benutzeroberfläche, dank derer jeder Anwender die Lösung nutzen kann – und so für die Demokratisierung der Daten sorgt

CIOs müssen den Unterschied kennen und eine Strategie festlegen, bei der AIOps ein integraler Bestandteil eines autonomen Netzwerks ist.

2. Daten-Harmonisierung

KI benötigt saubere, integrierte Daten, damit Unternehmen Vorteile daraus ziehen können. Ein System mit künstlicher Intelligenz muss aus den Daten lernen und sie analysieren – nur dann kann es seine Aufgabe erfüllen. Ist die Vielzahl der unterschiedlichen Geräte im Unternehmen (WLANs, WANs, Router und Firewalls) nicht in der Lage, Daten auszutauschen und zu korrelieren, verfehlt die KI-Plattform ihre Wirkung.

3. Die richtigen Funktionen gewährleisten

AIOps erfordert eine deutliche Neuausrichtung der IT-Teams – von einem Command-Line-Paradigma für die Konfiguration von Boxen hin zu einem API-Programmiermodell-Paradigma. Nur so lassen sich aus Daten umsetzbare Erkenntnisse generieren.

Traditionell wurden die meisten Netzwerk-Administratoren darin geschult, Boxen zu konfigurieren. Für AIOps reicht dies nicht aus, die Technologie erfordert eine umfangreichere Expertise: IT-Teams müssen in der Lage sein, Daten aus der Vielzahl von Boxen zu übernehmen und dann die künstliche Intelligenz in einem gemeinsamen, interoperablen Format anzuwenden. Für CIOs und andere Führungskräfte ist es wichtig, diesen Unterschied zu verstehen und bei der Suche, Einstellung und (Um-)Schulung neuer Mitarbeiter entsprechend zu berücksichtigen. Vor allem ist eine umfangreiche Entwicklungskompetenz notwendig.

4. Verständnis dafür, dass AIOps nur eine verteilte Software-Cloud-Architektur ist

Die erste Generation der Cloud Managed Endpoint-Technologie wird heute noch häufig eingesetzt und besteht im Wesentlichen aus lokalen Controllern mit einer eingebetteten Software-Architektur. Diese Lösungen vereinfachten die Bereitstellung und Verwaltung von drahtlosen Netzwerken, indem sie eine embedded Architektur nutzte. Das autonome KI-Netzwerk der Zukunft hingegen benötigt eine verteilte Cloud-Software-Architektur. Damit lassen sich neue KI-Modelle schnell hinzufügen.

Organisationen, die AIOps implementieren und nutzen möchten, benötigen eine verteilte Microservices-Architektur. Diese wendet die Algorithmen in verschiedenen Teilen des Netzwerks an und bietet damit eine unternehmensübergreifende Visibilität. Darüber hinaus lassen sich neue Funktionen schnell implementieren.

5. Die Cloud akzeptieren

Während Unternehmen für Vertrieb, Personal, Finanzen und andere Geschäftsfelder bereits in die Cloud gewechselt sind, hat das Netzwerk die Cloud zögerlicher angenommen. CIOs sollten aber erkennen, dass die Cloud der beste Freund von AIOps ist. Sie bietet die notwendige skalierbare Infrastruktur, um verwertbare Erkenntnisse aus den Daten zu gewinnen, die über drahtlose Netzwerke laufen.

Indem Unternehmen diese fünf Schritte befolgen, können sie die Möglichkeiten nutzen, die AIOps bietet. Damit lassen sich autonome Netzwerke aufbauen, die einfacher zu bedienen und besser zu nutzen sind.

Der Beitrag AIOps: Auf dem Weg zum echten KI-Assistenten ist auf entwickler.de erschienen.

]]>
https://entwickler.de/online/machine-learning/aiops-ki-ai-machine-learning-579935279.html/feed 0