Archiv der Kategorie: Development

Microservices don’t like thinking in conventional entities

I recently had one of these special AHA-moments in a workshop held by Udi Dahan, CEO of Particular. In his example he was using the classic entity of a customer.

To realise microservices means cutting functionality in a clean way and to transfer it into separate pillars (or silos). Each silo has to have the responsibility over it’s own data, on which it builds the respective business processes. So far, so good. But how can we realise this for our typical customer, who’s model is shown in the screenshot? Different properties are needed or changed by different microservices.

If the same entity is used in all pillars, there needs to be a respective synchronisation between all microservices. This results in a considerable impact on scalability and performance. In an application with lots of parallel changes of an entitiy the failing of the business processes will increase – or lead to inconsistencies in the worst case.

Conventional Customer

conventional entity of a customer

Udi suggests the following modelling

New Customer

Customer is modelled with independent entities

To identify which data belongs together, Udi suggests an interesting approach:

Ask the operating department if changing a property has a consequence for another property.

Would changing the last name of customer have an influence on the price calculation? Or on the way of marketing?

Now we need to solve the problem of aggregation, for example if I want to show different data from different microservices in my view. In a classic approach we would have a table with following columns:

ID_Customer ID_MasterData ID_Marketing ID_Pricing

This leads to the following two problems:

  1. The table needs to be extended if a new microservice is added
  2. If a microservice covers the same functionality in the form of data, you would have to add multiple columns for each microservice and allow NULL values as well

An example for the second point could be a microservice which covers the matter of payment methods. In the beginning you could only use credit cards and debit charges. Then Paypal. Bitcoin soon after. The microservice would have different tables on which the respective data for the payment method would be stored. In the aggregated table shown above it would be necessary to fill a separate column for each payment method the customer is using. If he doesn’t use it, a NULL value would be written. As you can see: This sucks.

Another approach is much more convenient for this. Which one this is and how it’s realised technically you can find on the GitHub repository of Particular.

 

Microservices mögen kein Denken in klassischen Entitäten

Einen ganz besonderen AHA Moment hatte ich kürzlich in einem Workshop bei Udi Dahan, CEO von Particular. In seinem Beispiel ging es um die klassische Entität eines Kunden.

Microservices zu realisieren bedeutet Fachlichkeiten sauber schneiden und in eigenständige Silos (oder Säulen) packen zu müssen. Jedes Silo muss dabei die Hohheit über die eigenen Daten besitzen, auf denen es die zugehörigen Geschäftsprozesse abbildet. Soweit so gut. Doch wie lässt sich dies im Falle eines Kunden bewerkstelligen, der klassischerweise wie im Screenshot zu sehen modelliert ist? Unterschiedliche Eigenschaften werden von unterschiedlichen Microservices benötigt bzw. verändert.

Wird die gleiche Entität in allen Silos verwendet, muss es eine entsprechende Synchronisierung zw. den Microservices geben. Das hat erhelbiche Auswirkungen auf Skalierbarkeit und Performance. In einer Applikation mit häufig parallelen Änderungen an einer Entität wird das Fehlschlagen von Geschäftsprozessen zunehmen – oder im schlimmsten Fall zu Inkonsistenzen führen.

Klassische Kundeentität

Klassische Kundeentität

 

Udi schlägt die folgende Modellierung vor:

Neue Modellierung eines Kunden

Der Kunde wird durch unabhängige Entitäten modelliert

Zur Identifikation, welche Daten zusammengehören, schlägt Udi einen Interessanten Ansatz vor:

Fragt die Fachabteilung, ob das Ändern einer Eigenschaft Auswirkung auf eine andere Eigenschaft hat. 

Würde das Ändern des Nachnamens einen Einfluss auf die Preiskalkulation haben? Oder auf die Art der Marketings?

Nun gilt es noch das Problem der Aggregation zu lösen, sprich wenn ich in meiner Anzeige unterschiedliche Daten unterschiedlicher Microserivces anzeigen möchte. Klassischerweise würde es jetzt eine Tabelle geben, die die Spalten

 

ID_Kunde ID_Kundenstamm ID_Bestandskundenmarketing ID_Preiskalkulation

 

besitzt. Das führt aber zu 2 Problemen:

  1. Die Tabelle muss immer erweitert werden, wenn ein neuer Microservices hinzugefügt wird.
  2. Sofern ein Microservices die gleiche Funktionalität in Form unterschiedlicher Daten abdeckt, müssten pro Microservices mehrere Spalten hinzugefügt und NULL Werte zugelassen werden.

Ein Beispiel für Punkt 2 wäre ein Microservices, der das Thema Bezahlmethoden abdeckt. Anfangs gab es beispielsweise nur Kreditkarte und Kontoeinzug. Dann folgte Paypal. Und kurze Zeit später dann Bitcoin. Der Microservices hätte hierzu mehrere Tabellen, wo er die individuelle Daten für die jeweilige Bezahlmethode halten würde. In oben gezeigter Aggregationstabelle müsste aber für jede Bezahlmethode, die der Kunde nutzt, eine Spalte gefüllt werden. Wenn er sie nicht benutzt, würde NULL geschrieben werden. Man merkt schon: Das stinkt.

Ein anderer Ansatz ist da deutlich besser geeignet. Welcher das ist und wie man diesen technischen realisieren kann, könnt ihr im GitHub Repository von Particular nachschauen.

 

Quellen zu Defensives Design und Separation of Concerns sind jetzt online

Den Quellcode zu meinen Vorträgen auf den Karlsruher Entwicklertagen und der DWX sind jetzt online:

  • Zu Super Mario Kata mit Fokus auf Defensivem Design geht es hier.
  • Zur Prüfsummen Kata mit fokus auf Separation of Concerns gelangt ihr hier.

Auf beiden Seiten findet ihr auch die Links zu den PowerPoint Folien. Im Juli 2018 werde ich den Code der Prüfsummen Kata noch in Form von Iterationen veröffentlichen und beide Talks als YouTube Video freigeben.

IMG_20180627_145405

Defensives Design Talk auf der DWX

Ihr wollt Teile davon in euren Vorträgen verwenden, ihr wollt ein Training zu dem Thema oder ich soll dazu in euerer Community einen Vortrag halten, dann kontaktiert mich über die auf GitHub genannten Kanäle.

Kausale Ketten: Gründe für das Scheitern von Softwareprojekten

Auf dieser Github Page habe ich begonnen die Problemen in Softwareprojekten, die uns täglich begegnen, genauer zu analysieren, um diese vermeiden bzw. beheben zu können.

In Gesprächen mit Teilnehmern meiner Workshops werden mir regelmäßig Symptome geschildert, von denen ich der Meinung bin, dass die Ursache wie so oft tiefer liegt.

Tituliert habe ich das als kausale Ketten und orientiere mich dabei an folgendem Schema:

  • Was ist das wahrgenommene Problem, also das Symptom
  • Wie kam es dazu, also die Verlaufsbetrachtung
  • Warum kam es dazu, was ist die Ursache

Zudem suche ich nach nachvollziehbaren Beispielen, um die Theorie zu untermauern.

Ich verstehe die Seite als Anreiz zum Nachdenken. Alle „Thesen“ sollen als Einstieg in eine lebendige Diskussion dienen.

Gebt mir gerne Feedback in Form von Pull Requests.

Workshop: Conquer your Codebase – Bewährter Clean Code aus der Praxis (Materialien)

Einen herzlichen Dank an alle Teilnehmer des Workshops am vergangenen Freitag beim Developer Open Space 2017. Trotz des völlig unterschiedlichen Backgrounds – von Ruby, über PHP, zu Java oder gar nicht objektorientierte Sprachen wie JavaScript – war ebenso alles vertreten wie vom Azubi bis hin zum Entwickler mit 20-jähriger Berufserfahrung.

IMG_20171013_132904

Einer von vielen mutigen Freiwilligen

Den Code zur Super Mario Kata gibt es hier. Beachtet die neuen Anforderungen (9-12), die ich auf dem Heimweg im Zug noch hinzugefügt habe. Damit einhergehend habe ich noch ein Refactoring des Konzepts ‚Leben‘ durchgeführt, sodass keine Actions bzw. Funcs mehr an die Methoden übergeben werden müssen. Gleichfalls fällt das Branching-Statement raus und es ergibt sich eine nahezu völlig flexible Möglichkeit zur Erstellung von Spielmodi. Die Tests sind nun ebenfalls alle umgesetzt, was wir gegen Ende hin aufgrund von Zeitmangel ausgelassen haben. Eine Testmethode hat in der Regel eine Zeile und wie schon im Workshop erwähnt: Was gut zu testen ist, ist in der Regel auch eine saubere Lösung.

IMG_20171013_132938

20 Teilnehmer mit unterschiedlichen Backgrounds

Derjenige, der noch eine Lösung mit dem Command-Pattern umsetzt und dadurch das Anpassen bestehender Klassen völlständig vermeidet, erhält von mir einen Gutschein für unsere Trainings. Damit kann er kostenlos an jedem beliebigen 3-tägigen Workshop in unseren Karlsruher Büros teilnehmen (Fahrt- und Übernachtungskosten sind ausgeschlossen).

Alle, die über den Workshop bloggen oder twittern, erhalten darüber hinaus noch einen 30% Rabattcode. Einfach Link schicken, dann kriegt er diesen per Mail.

tweet-workshop

Ein Teilnehmer versucht sich in einer Lösung mit Java statt C#

Weiterführende Links

  • Das erwähnte Video zu Enumeration mit Verhalten könnt ihr hier anschauen.
  • Danke an Tim für den Link zum Case Converter für Visual Studio.
  • Außerdem lege ich euch die Reactive Extensions ans Herz, die es für unterschiedliche, gängige Programmiersprachen gibt.
  • Git Snippet
  • Wer noch ein wenig üben möchte, kann dies mit der erweiterten FizzBuzz Kata tun.
  • Blog Post über die Migration von NHibernate zu EntityFramework in 3 Tagen.

 

Demnächst geht ein Video mit dem theoretischen Teil (Why-How-What) online, in dem ich nochmal die Zusammenhänge zw. „schlechtem Code“ und den Gründen dafür erläutere. Wer automatisch informiert werden will, wenn es veröffentlich wird, abonniert einfach meinen Blog oder schickt mir eine Nachricht.

 

 

Workshop: Conquer your Codebase – Bewährter Clean Code aus der Praxis

Am Developer Open Space 2017 halt ich einen 1-tägigen Workshop zu obigem Thema. In reduzierter, kompakter Form werde ich dazu bewährte Inhalte aus meinem 3-tägigen Seminar nehmen und die Ursachen für folgende Probleme adressieren:

  • Unverständlicher bzw. schlecht wartbarer Code
  • Bugs
  • Skalierungsprobleme
  • Go Live Probleme
  • Verpasste Deadlines und lange Entwicklungszeiten

 

Wir werden uns anschauen wie es dazu kommen kann, z.B. weil

  • die Infrastruktur nicht wiederverwendbar ist,
  • die Domänenlogik nicht erweiterbar ist,
  • eine falsche Nutzung der API möglich ist,
  • der Code nicht ausdrucksstark ist,
  • oder starke Abhängigkeiten bestehen.

 

Wir werden das Open Closed Principle genauer besprechen und Seperation of Concerns am konkreten Beispiel umsetzen. Speziell für Freunde der Objektorientierung werde ich je nach verfügbare Zeit praktische Lösungen zur Vermeidung von If-Else-Zweigen und NULL-Checks zeigen.

 

Ein Laptop mit Visual Studio oder Visual Studio Code und .NET 4.6 wären wünschenswert. Prinzipiell ist der Workshop aber für alle Entwickler des objektorientierten Paradigmas geeignet, da bis auf Delegaten (Action/ Func) und Erweiterungsmethoden kaum Sprachspezifika verwendet werden. Darüber hinaus können Teilnehmer auch ohne Hardware beiwohnen, weil wir beim Live Coding am Präsentations-PC mit Code Monkey Runden arbeiten werden.

Gerne dürfen die Teilnehmer mir vorab Fragen und Probleme z.B. hier in Form von Kommentaren oder per E-Mail zukommen lassen.

Git History Commit Redos für Workshops

Mit diesem Snippet, das ich in meinen Workshops verwende, könnt ihr die Commits eines Branches vom ersten bis zum letzten Interaktiv durchsteppen, um so jede Änderung mit den Teilnehmern zu besprechen. Das ist vor allem dann nützlich, wenn das Live Coding mehr ablenkt oder die Zeit ein wenig knapp ist:

Blog Post

GIT_EDITOR=true git rebase -i --root -x 'git diff --name-only HEAD~1..HEAD;git show --oneline --no-patch; printf "Return for next commit"; read;clear'

 

Beim ersten Commit gibt es noch eine kleine Fehlermeldung, da versucht wird auf den vorherigen Commit zuzugreifen, den es beim 1 Commit logischerweise nicht geben kann.

Git History Commit Redo

Git History Commit Redo- First Commit

 

Ab dem zweiten Commit werden dann sowohl die Commit Message als auch alle alle geänderten Dateien angezeigt.

Git History Commit Redo

Git History Commit Redo – Next Commit

 

Am Schluss kommt noch diese Meldung.

Git History Commit Redo

Git History Tracking – Finished

 

Beachtet bitte, dass dies nur bei einer linearen Historie funktioniert, da es sich um einen Rebase handelt und dass ihr hierfür am besten einen Test-Branch abzweigt, um nicht ggf. Änderungen noch einzubauen, die dann im Master-Branch landen.

Programmieraufgaben für Bewerber

Ich habe in diesem Post beispielhaft eine unserer Programmieraufgaben herausgezogen, die kürzlich unser neuer Mitarbeiter Hr. Jörg Weißbecker gelöst hat. In der Regel ist das Ziel ein möglichst hochwertiges Ergebnis zu programmieren, das z.B. die Prinzipien OCP und SoC solide umsetzt.

Zeitdruck ist an der Stelle völlig sekundär, sodass die Bewerber die Aufgaben immer von zuhause in aller Ruhe entwickeln können. Sie erhalten dann von mir nach jeder Iteration die nächste Anforderung übermittelt.

Am Ende besprechen wir das Ergebnis, sprich sie stellen ihren Gedankengang vor, reflektieren Probleme und stellen sich meinen Fragen.

 

Allgemeines vorab:

  • Es ist keine Oberfläche notwendig, es genügt eine Konsolenanwendung
  • Welche Bibliotheken genutzt werden, ist freigestellt
  • Das Schreiben von Tests ist optional
  • Aber: Setzte das objektorientierte Paradigma so gkonsequent als möglich um (!)

 

Iteration 1: Entwickeln Sie ein Programm, welches prüft, ob 2 Dateien identisch sind. Beispiel für den Aufruf:

Dublettenfinder.exe file1.txt file2.txt

 

Iteration 2: Statt 2 Dateien sollen jetzt 2 Ordnerpfade übergeben werden, für welche das Programm prüft, ob das Ordnerpaar Dubletten enthält. Wenn ja, soll es pro Dublette die Dateipfade gruppiert ausgeben. Beispiel:

Hash: xyxzasdfadsf

  • Datei1: c:\abc.pdf
  • Datei2: d:\efg.pdf

 

Iteration 3: Es soll möglich sein eine Liste von Verzeichnissen zu übergeben, sodass beliebig viele Verzeichnisse verglichen werden können. Außerdem sollen, sofern vorhanden, auch die Unterverzeichnisse geprüft werden.

 

Iteration 4: Fügen Sie bitte eine optionale Konfigurationsmöglichkeit hinzu, um nur bestimmte Dateitypen vergleichen zu können, sodass entweder alle Dateitypen, genau einen Dateityp oder n-Dateitypen verglichen werden können.

 

Iteration 5: Machen Sie den Algorithmus austauschbar, sodass der Identitätscheck z.B. anhand von Sha256 Hashwerten oder Bildanalyse durchgeführt werden kann.

 

Iteration 6: Nutzen Sie einen IoC Container, um dynamisch beim Start der Anwendung alle vorhandenen Algorithmen zu laden und dann vom User in der Konsole auswählen zu lassen. Jeder Algorithmus soll in einer eigenen Assembly liegen. Machen Sie dann eine Assembly für MD5 und Sha256.

 

Die  Lösung zu diesem Zeitpunkt müsste sich Fragen bzgl. der Erweiterung der folgenden 2 Änderungen stellen:

  • Lösche Dubletten anhand eines bestimmten Patterns, z.B. alle in Verzeichnis ‚xy‘ oder mit Dateinamen, die ‚yz‘ enthalten.
  • Ermögliche die Erkennung von doppelten Bildern anhand der Bilderkennung und nehme immer die beste Auflösung.

 

Kürzlich gab es in der dotnetpro einen Artikel von Stefan Lieser, welcher eine recht ähnliche Kata gelöst hat. Die Lösung von Herrn Weißbecker befindet sich hier.

Angular Starthilfe – 2-tägiger Workshop in Leipzig

Zur Unterstützung des Developer Open Space 2017 bieten wir allen Teilnehmern, die uns eine Kopie ihres Tickets an schulung@co-IT.eu zukommen lassen, die Teilnahme an unserem 2-tägigen Angular 4 Workshop zum reduzierten Preis von 1250€ an.

Das Training ist vom 11-12. Oktober in Leipzig und damit direkt vorm #devspace selbst, sodass eine separate Anfahrt nicht notwendig ist. In unserem Firmenprofil könnt ihr euch vorab über uns informieren.

Angular_full_color_logo.svg

Für alle diejenigen, die meinen Blog lesen und nicht zur Veranstaltung gehen können, habe ich ebenfalls eine spezielle Aktion: Wer mir als erstes an die oben genannte E-Mail-Adresse eine Nachricht mit dem Titel „ich blogge“ schreibt und darin seinen Blog verlinkt, der erhält ebenfalls einen Rabattcode.

Die Anmeldung ist ab sofort auf Eventbrite freigeschaltet.

Angular Fundamentals Workshop in Karlsruhe

Zur Unterstützung des NOSSUED Software Entwicklungs Open Space bieten wir den ersten 2 Teilnehmern, die uns eine Kopie ihres Tickets an schulung@co-IT.eu zukommen lassen, die Teilnahme an unserem 3-tägigen Angular 4 Fundamentals Workshop kostenlos an.

Das Training ist vom 11-13. Juli in unseren modernen, klimatisierten Büros mit höhenverstellbaren Tischen im Herzen von Karlsruhe. Unser Firmenprofil verrät euch mehr.

Angular_full_color_logo.svg

Für alle diejenigen, die meinen Blog lesen und nicht zum #nossued gehen können, habe ich ebenfalls eine spezielle Aktion: Wer mir als erstes an die oben genannte E-Mail-Adresse eine Nachricht mit dem Titel „ich blogge“ schreibt und darin seinen Blog verlinkt, der darf auch kostenlos an der Schulung teilnehmen.

Schneller zur besseren Webseite mit einer Business Analyse

Für unseren größten Kunden die heco gmbh haben wir eine Business Analyse durchgeführt, um vor der anstehenden Neuentwicklung die richtigen Entscheidungen treffen zu können. Wie wichtig die Informationen über Markt, Mitbewerber, Anwender und Kunden sind und welche Schlussfolgerungen sich daraus ziehen lassen, zeige ich in diesem Video:

Während dies bei „normalen“ (im Sinne von offline bzw. intern) Software-Projekten schon eher Usus ist, kann man davon bei Web-Projekten  noch lange nicht sprechen. Meiner Erfahrung nach spielen hier Aussehen und „etwas auf die Leinwand bringen“ die erste Geige. Eine schier riesige Zahl an Feature-Wünschen, die man auf anderen Seiten gesehen hat, lässt die Stakeholder träumen.
 

Der Langsamste, der sein Ziel nicht aus den Augen verliert, geht noch immer geschwinder, als jener, der ohne Ziel umherirrt. – Lessing

 

Aus unserer Sicht ist es elementar sich die Zeit zu nehmen, um sich als Dienstleister in die Domäne des Kunden einzuarbeiten. Denn viele hoch priorisierte Wünsche sind eher nice-to-have Anforderungen. Oder schlimmer: Das „Warum“ ist gar nicht geklärt und das Produkt bzw. die Webseite wird am eigentlichen Zweck vorbei entwickelt. Da wird dann auch mal der Wunsch nach einem News-System laut, obwohl im Jahr nur 1-2 Neuigkeiten auf der Webseite eingepflegt werden sollen. Dabei wäre es unter Umständen geradezu eine Revolution in der Branche, würde man im Gegensatz zu den Mitbewerbern Echtzeitbestände und -preise auf der Webseite anbieten.

Um richtig priorisieren und die Technologie auswählen zu können, ist deshalb ein solides Know How der Domäne des Kunden notwendig, denn sonst verbaut man sich schnell Möglichkeiten, die dann teuer und langwierig umgebaut werden müssen. Setze ich beispielsweise auf SignalR, so kann ich jedem Besucher, der ein bestimmtes Produkt geöffnet hat, Änderungen am Bestand aktiv mitteilen. Auf der anderen Seite muss ich mir nicht unnötig Komplexität ins Projekt holen, wenn der Bestand von vor 2 Stunden völlig ausreichend ist. Oder wenn der Besucher gar nicht in der Lage ist bestimmt Funktionen zu bedienen (ja, das gibt es durchaus => kenne deine Anwender).

Viel Spaß mit dem Video, auch wenn es etwas lang wurde. Daran merkt man aber schon wie weitreichend das Thema ist. Schreibt mir in die Kommentare, ob ihr auch schon zu solchen Projekten gestoßen seid, bei denen das fehlende Domänenwissen zu Entwicklungsproblemen führte.

Interview zu AngularJS mit Gregor Woiwode und Johannes Hoppe am Developer Open Space 2015

Wir nehmen wie immer gerne Feedback mit. Gregor und Johannes könnt ihr über die in den Show Notes verlinkten Webseiten kontaktieren. Ich bin sicher, dass Input für das Buch gerne aufgenommen und ggf. eingefügt wird.

Docker Session am NET Open Space Süd 2015

Aus aktuellem Anlass (Workshop am devspace2015) das Video zu Docker, in welchem Alexander Zeitler uns in einer Live Demo das Ökosystem vorstellt.

Alexander Zeitler stellt Docker vor.

Durch Klicken gelangt ihr zum Video.

Open Closed Principle mit 2 Zeilen Code

In meinem Video zu 60 Minuten mit der Pfadfinderregel war ich noch die Lösung zu Castle.Windsor schuldig. In diesem Webcast zeige ich wie die CollectionResolver-Funktionalität genutzt werden kann, um nachträglich hinzugefügte Implementierungen automatisch im Container zu registrieren.

Dadurch kann das OCP vollständig eingehalten werden, da lediglich eine neue Klasse hinzugefügt werden und der restliche Code nicht angefasst werden muss. Den Code habe ich hier zur Verfügung gestellt. Fragen und Feedback einfach in die Kommentare.

public class Installer : IWindsorInstaller
{
/// <summary>
/// Performs the installation in the <see cref="T:Castle.Windsor.IWindsorContainer" />.
/// </summary>
/// <param name="container">The container.</param>
/// <param name="store">The configuration store.</param>
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Kernel.Resolver.AddSubResolver(new Castle.MicroKernel.Resolvers.SpecializedResolvers.CollectionResolver(container.Kernel));
container.Register(Components().ToArray());
}
private static IEnumerable<IRegistration> Components()
{
//have a look at https://github.com/castleproject/Windsor/blob/master/docs/registering-components-by-conventions.md
yield return Classes //non abstract classes; you could also use Types.* for more choices
.FromThisAssembly() //should be clear
.IncludeNonPublicTypes() //since my implementations are internal, only the interface is public
.BasedOn<IFoo>() //every class that implements this interface
.WithService.Base() //also possible: .WithServiceFromInterface()
.LifestyleTransient();
yield return Component
.For<IBar>()
.ImplementedBy<Bar>()
.LifestyleTransient();
}
}

Durch Klicken auf das Bild geht es zum Video

Durch Klicken auf das Bild geht es zum Video

Die großen 4: Pfadfinderregel, Wirtschaftlichkeit, Clean Code, SOLID Principles

Was ist damit gemeint? Gemäß der Pfadfinderregel soll ein Entwickler Code immer besser hinterlassen, als er ihn vorgefunden hat. Clean Code oder guter Code ist häufig dann erreicht, wenn das Mindestmaß an essentiellen Code Prinzipien umgesetzt ist. Das sind die sogenannten SOLID Principles. Jedoch ist guter Code kein Selbstzweck, sondern dient dem größeren Ziel der Wirtschaftlichkeit.

Im folgenden Video zeige ich an einem Praxisbeispiel, wie ich bei einem bestehendem, eher unwichtigem Projekt vorgegangen bin. Timeboxed in 1h so viel refaktorisieren und den Code verbessern wie möglich. Dabei gehe ich auf Prinzipien wie DRY und OCP ein und zeige Techniken wie DI, sowie Tools wie den IoC Container Castle Windsor.

Feedback nehme ich wie immer gerne mit. Wenn ihr mehr von solchen Videos sehen wollt, schreibt mir das in die Kommentare, damit ich weiß: Hier lohnt es sich mehr zu machen.

Zum YouTube Video

Durch Klicken auf das Bild geht es zum Video

Build Server endlich ohne DevExpress

DevExpress ist leider alles andere als vorbildlich, was den Einsatz auf Build Servern angeht. Weder bietet das Unternehmen NuGet Packages, noch lässt sich die Lizenzprüfung auf dem Build Server deaktivieren.

Mit einem kleinen Trick lässt sich aber die Installation umgehen. Hierzu ruft ihr den Installer auf dem Build Server/Agent auf, loggt euch mit euren Daten an dem unten aufgeführten Screenshot ein und brecht nach erfolgreichem Login ab einfach ab.

DevExpress Login Dialog

Damit wurden mehrere Registry Einträge geschrieben, die leider maschinenspezifisch sind. Diese findet ihr hier:

  • HKLM\SOFTWARE\Classes\Licenses378852D-D597-4A32-B6D9-680A16A3CDA6\***
  • HKLM\SOFTWARE\Classes\Licenses\6F0F8269-1516-44C6-BD30-0E90BE27871C\***

Wenn ihr in den Projekten dann DLL-Referenzen aus einem Repository-Verzeichnis verwendet oder euch eigene NuGet Packages baut, benötigt ihr in Zukunft keine Installation mehr. Das gilt auch für Developer, die nicht an der UI mitentwickeln.

Wohin mit den Queries, Repositories und UnitOfWorks in meinen Anwendungsschichten

Am vergangenen .NET Open Space gab es eine Session namens „Repositories oder ORM“. Den Titel fand ich ein wenig unglücklich gewählt. Nutzt man nämlich einen OR-Mapper, so verwendet man implizit Repositories. Zumindest ist das beim Entity Framework der Fall. Dort entspricht der DbContext nämlich der UnitOfWork und die darauf implementierte generische Set-Methode liefert die Repositories zu allen Datenbank-Entitäten.

Grob gesagt sollte pro Geschäftsvorfall (aus Sicht der UI) ein DbContext erzeugt, darauf alle Änderungen und Abfragen ausgeführt und im Anschluss per Commit in einer Transaktion ausgeführt werden. Die Transaktion findet implizit statt, sodass ihr sicher sein könnte, dass entweder alles in die Datenbank geschrieben wurde oder nichts.

Nun wurde die Frage gestellt wie mit Abfragen zu Verfahren ist: Sollte man in allen Layern auf die Repositories zugreifen und dann per LINQ beliebig filtern? Ich bin der Meinung, dass man dies tunlichst unterlassen sollte. Stattdessen nutze ich in der Regel eine der zwei Möglichkeiten (welche sich beide gut zum Testen eigenen):

  • Eine dedizierte Repository-Implementierung, die intern die Abfragen kapselt. Das könnte zum Beispiel die Klasse ‚Rechnungen‘ mit der Methode ‚AlleMitDatumGrößerAls(DateTime datum)‘  sein. Idealerweise mappt das Repository ‚Rechnungen‘ dabei die Entitäten auf Business Objekte. AutoMapper kann in dem Fall viel Schreibarbeit abnehmen.
  • Sollten mehrere Repositories die gleiche Abfrage verwenden, so bietet es sich an die Query in eine eigene Klasse dafür zu extrahieren. Zum Beispiel die Klasse ‚FindeBenutzerMitId‘, welche im Konstruktor die Id übergeben bekommt. Auf der UnitOfWork lässt sich dann die Query z.B. in der Form ausführen: ‚uow.ExecuteQuery(new FindeBenutzerMitId(1))‘. Dafür muss allerdings erst die UnitOfWork um einen solchen Mechanismus erweitert werden. Ich hatte diesen Ansatz vor ein paar Jahren in diesem Video beschrieben.

Leider ist ein Blog Beitrag ungeeignet um ein solch komplexes Thema in der notwendigen Tiefe zu besprechen. Ziel war es daher nur Denkanstöße zu geben und eine Diskussion zu starten. Wer nützliche Ressourcen zu dem Thema hat oder wer andere Ansätze verfolgt, kann diese gerne in die Kommentare schreiben.

Paket vs. NuGet

Am vergangenen .NET Open Space haben einige Teilnehmer nach Erfahrungen zu Paket, der mehr oder weniger neuen Alternative zu NuGet. Mein Statement möchte ich an dieser Stelle für alle festhalten:

Wir haben unser ERP-System mit ca. 70 Projekten vor über 6 Monaten umgestellt und sind sehr zufrieden damit. Warnen muss ich lediglich vor 3 Punkten, die einem bewusst sein müssen:

  • Paket ist nicht in Visual Studio integriert und muss daher über die Kommandozeile ausgeführt werden. Eine Integration ist auch nicht geplant. (Aktualisiert: Ein entsprechendes GitHub Projekt steht zur Verfügung)
  • Jedes NuGet Package, welches die install.ps1 aufruft, funktioniert ggf. nicht richtig nach der Installation mit Paket. Das ist z.B. bei PostSharp der Fall, was ich hier beschrieben habe. Der geneigte Leser möge bitte bei PostSharp für das offene Issue dazu voten.
  • NET Core Projekte erlauben keine Assembly Referenzen mehr, sodass Paket nicht verwendet werden kann.

Die Gründe für einen Abgang von NuGet sind vielfältig und wurden vom Entwicklerteam selbst beschrieben. Mit annähernd allen Problemen räumt Paket auf. Um nur zwei davon zu nennen:

  • Mit dem Updaten von packages werden die Projektdateien nicht mehr verändert. Stattdessen werden lediglich 2 Dateien von Paket selbst aktualisiert. Damit gehören Merge-Konflikte der Vergangenheit an.
  • Einen Abhängigkeitsgraphen bekommt man ebenfalls mitgeliefert. Daraus lässt sich schnell schließen welches Package ein anderes in welcher Version referenziert.

Eine Frage beim Open Space war, ob sich damit auch das gleiche Package in unterschiedlichen Versionen einbinden lässt. Nein, das ist nicht der Fall, was aber nichts mit NuGet oder Paket zu tun hat. Das ist der Tatsache geschuldet, dass ein .NET Prozess eine Assembly nur in genau einer Version laden kann. Zum Lösen dieses Problems bedarf es also immer Binding Redirects. In NuGet 3 soll zumindest ein Feature zum einfachen Konsolidieren unterschiedlicher Versionen eingebaut sein.

Mit NuGet 3 soll ohnehin ein großes Redesign stattfinden, sodass ein näherer Blick darauf ratsam ist. Im Team Blog finden sich einige nützliche Ressourcen.

Ich wollte den Blog Post kurz halten, deshalb habe ich nicht alle Vorteile aufgezählt. Wenn aber ein Leser der Meinung ist, dass noch etwas unbedingt genannt werden soll, dann einfach in die Kommentare posten.

Nachgefragt – Interview mit Daniel Marbach zu MSpec

In einem Online Interview habe ich Daniel Marbach zur Zukunft des Open Source BDD Frameworks MSpec befragt. Herausgekommen ist eine Aufnahme, die es jetzt auf YouTube gibt. Die Fragen wurden nicht vorab abgesprochen, um ein authentisches statt ein werbelastiges Gesprächs zu führen.

 

image

Auf das Bild klicken um zum Video zu gelangen

 

An dieser Stelle möchte ich noch die Community aufrufen sich an der Weiterentwicklung zu beteiligen. Open Source Projekte leben von freiwilligen Helfern und Daniel macht da eine sehr gute Arbeit und ein tolles Produkt!

Fragen

  • Machine.Specifications
  • Was ist eigentlich ein BDD Framework
  • Stärken
  • Schwächen
  • Roadmap
  • Wie steht es um die Zukunftssicherheit
  • Tipps und Tricks
  • Ergänzende Frameworks
  • Gute Tests

 

Show Notes

How to get the PostSharp package running with Paket

Recently, I reported some difficulties that I‘ve experienced with the PostSharp NuGet package when I was using the new package manager Paket. I tracked the problem down to the ‚install.ps1‘ script which is executed by NuGet after adding PostSharp to a project. This PowerShell script (located under packages\PostSharp\tools) patches your project file. Since this behaviour is already proclaimed from the pulpit by NuGet, I hope that PostSharp is going to remove that asap. Until then, you can execute the script manually or patch the csproj-File by yourself.

In order to do that, insert the following 2 snippets at the the position shown in the screenshots:

   1: <DontImportPostSharp>True</DontImportPostSharp>

 

image

 

Don’t forget to change the relative path to your PostSharp package in the following snippet:

   1: <Import Project="..\..\packages\PostSharp\tools\PostSharp.targets" Condition="Exists('..\..\packages\PostSharp\tools\PostSharp.targets')" /> 

   2: <Target Name="EnsurePostSharpImported" BeforeTargets="BeforeBuild" Condition="'$(PostSharp30Imported)' == ''">

   3: <Error Condition="!Exists('..\..\packages\PostSharp\tools\PostSharp.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://www.postsharp.net/links/nuget-restore." />

   4: <Error Condition="Exists('..\..\packages\PostSharp\tools\PostSharp.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://www.postsharp.net/links/nuget-restore." />

 

image

 

I also recommend you to activate the following PostSharp Option in Visual Studio:

image

Interview mit Daniel Marbach mitgestalten

Am 18. März wird mir Daniel Marbach ein Video Interview zu dem BDD-Framework Machine.Specifications geben. Ein kleiner Vorgeschmack gefällig?

Wodurch hebt sich MSpec von anderen BDD-Frameworks ab?

oder

Welche Features sind gerade in der Pipeline?

oder

Welche anderen Frameworks ergänzen MSpec gut?

Das Video veröffentliche ich dann auf meinem YouTube Channel. Ihr könnt die Richtung des Gesprächs mitgestalten, indem ihr mir rechtzeitig eure Fragen in die Kommentare postet.

Nachgefragt – Clean Code Interview mit Ralf und Stefan

In einem Online Interview habe ich Ralf Westphal und Stefan Lieser, die Gründer der Clean Code Developer School, zum Thema Clean Code befragt. Herausgekommen ist eine Aufnahme, die es jetzt auf YouTube gibt. Die Fragen wurden nicht vorab abgesprochen, um eine Gesprächsatmosphäre zu schaffen, wie es sie bei einer Kaffeepause gibt.

Es war ein toller Gedankenaustausch. Danke nochmal ihr zwei!

Zum Video

Zum Video

Fragen

  • Wenn ihr euch für eine Konferenz entscheiden müsstet, welche wäre das?
  • Community vs. Freizeit: Wie ist das vereinbar
  • Wann ist Clean Code noch sinnvoll und wann verschlimmbessere ich nur noch?
  • Macht Clean Code Sinn, wenn die Kollegen nicht mitziehen?
  • Wird das Schreiben von gutem Code mit der Zeit einfacher?
  • Ist guter Code relativ?
  • Was erwartet ein Arbeitgeber, wenn er Clean Code in der Stellenausschreibung aufführt?
  • Was kann ich von einem Bewerber erwarten, wenn er Clean Code in der Stellenausschreibung aufführt?
  • Verschiedene Ansätze für bessere Architektur, z.B. Flow Design
  • Brauche ich für Flow Design einen IoC Container?

Für die Zukunft sind weitere Interviews geplant:

  • Mit Daniel Marbach zu Machine.Specifications
  • Mit Tilman Börner zur dotnet pro
  • Mit Steffen Forkmann zur paket

Falls ihr noch Ideen habt, dann schreibt sie in die Kommentare.

PostSharp reports broken references when using Paket

If you use Paket instead of NuGet (why? therefore!) you will experience the following difficulties:

imageGiven is the following Solution/Project. It contains a paket.references file containin just one line “PostSharp”, which is

The PostSharp Assembly is added when you your “paket.references” file in the project directory containing just one line “PostSharp”. If you execute “paket install” in your command promt, paket adds PostSharp as reference to the project and modifies the csproj accordingly.

The next time you run a build, PostSharp comes up with this dialog:

postsharp

Since the VisualStudio PostSharp plugin detects a reference to PostSharp.dll, it expects a packages.config which it can’t find. If you don’t agree, the solution builds successfully but the code won’t be modified by PostSharp.

imageIf you agree, PostSharps adds a packages.config and replaces the existing PostSharp reference with the newest stable one (which probably is not the version you have specified in Paket!).

I posted this on Twitter. The Paket maintainers can’t handle this and PostSharp won’t change this behaviour.

image

image

image

So by now, I don’t see any solution except that Paket users can ask PostSharp to change this behaviour.

//Edit: Have a look at the comments. The unsolved problem is that you have to execute the „install.ps1“. Paket doesn’t do that but NuGet will also remove this feature in a future release.

Konsequente Objektorientierung – Die besseren Methodenparameter

Kürzlich habe ich eine Lösung zugeschickt bekommen, die folgende Methode enthielt.

   1: public bool compare(string item1, string item2)

   2: {

   3:     if (item1 == null || item2 == null)

   4:         return false;

   5:  

   6:     //more code

   7: }

 

In diesem Webcast möchte ich einen Ansatz zeigen, den ich als gute Alternative zu obigem Code sehe. Dabei setze ich konsequent auf Objektorientierung zur Trennung der Aspekte.

Was ist denn bitte ein C# Experte?

Die Bezeichnungen Senior Developer, Solution Architect und wie sie alle heißen sollen andeuten, dass es sich um jemanden mit Erfahrung handelt. In dem ein oder anderen Bewerbungsschreiben lese ich dann auch gerne “Experte”. Für mich sind das aber – und ich denke der Leser stimmt mir zu – alles relative Aussagen. Vor allem in Anbetracht der Produkt- und Themenvielfalt in der Programmierung.

Sicherlich kennt (wohlgemerkt: kennt, nicht kann) kein .NET Experte alle Programmiersprachen. Dann brechen wir das weiter runter. Sicherlich kennt kein C# Experte alle .NET Klassen. Ok, dann brechen wir es nochmal weiter runter. Sicherlich kennt kein C# BCL Experte die ganzen Facetten der Klasse String (Anmerkung: Wenn ein Leser dies anzweifelt, dann möge er sich diesen Artikel zu Gemüte führen).

Von daher tue ich mich logischerweise schwer, wenn ich von solchen Jobtiteln lese. Nichtsdestotrotz habe ich eine unsere Stellenausschreibungen genauso tituliert. Damit wollte ich ausdrücken, dass wir nach Kandidaten suchen, die sich schon längere Zeit mit der Materie beschäftigen. Ein wenig präziser schreibe ich: “Mindestens 5-jährige Berufserfahrung”. Erfahrung bedeutet nicht gleich tiefgreifende Kompetenz oder überragendes Know How. Ich hoffe der geneigte Leser stimmt mir zu. Aber für ein ganz grobes Profil und die Vermeidung völlig ungeeigneter Bewerbungen (wenn denn überhaupt so viele da wären…) muss das reichen.

Jetzt stellt sich mir die Frage wie sich ein sagen wir mal ausbaufähiges Fundament feststellen lässt. Krisztina nennt in ihrem Blogbeitrag ‘Are you nerd enough to code with us’ z.B. Clean Code, SOLID, TDD, etc.. Klar ist, dass mit den eigenen Ansprüchen vorsichtig umgegangen werden sollte. 100%ige Profiltreffer oder Kandidaten, die uns stark ähneln, gibt es nicht. Ganz abgesehen davon gingen bei einer homogenen Abteilung die Benefits des Melting Pots verloren. Den Mehrgewinn durch Vielfalt. Was suche ich also? Ich versuche es beispielhaft an der deutschen Sprache festzumachen: Wer unserer Sprache mächtig ist (Grammatik, Rechtschreibung, Umfang), der wäre für mich ein geeigneter Kandidat, wenn es darum ginge unseren schönen badischen Dialekt zu erlernen.

Und dabei setzt nun meine eigentliche Frage an: Woran mache ich es fest, dass jemand besagtes solides Fundament beherrscht. Im übertragenen Sinne die deutsche Sprache. Letzteres ist übrigens genauso schwierig zu prüfen, wie ersteres. Hier ein paar Beispiele, die ich zur Diskussion stelle:

  • Ist das Schlüsselwort ‘yield’ bekannt?
  • Worauf soll ich achten, wenn ich Programmcode gemäß dem Don’t Repeat Yourself-Prinzip analysiere
  • Wozu dient das MVVM Entwurfsmuster im Kontext von WPF

Klar ist, dass die Fragen zum Themenschwerpunkt des Bewerbers passen sollten. Jemand, der bisher nur Backend-Code geschrieben hat, kennt sich verständlicherweise nicht mit WPF und MVVM aus. Nach 5 Jahren Entwicklung sollte aber jeder Entwickler (sogar PHP Developer Zwinkerndes Smiley) das DRY-Prinzip kennen.

Was meint ihr? Wie lotet ihr das aus? Habt ihr auch die Situation, bei der ihr denkt: Also die Bewerbung hat überhaupt nicht gepasst? Eione kleine Bitte noch: Fachkräftemangel ist ein Thema für sich. Darum geht es mir in diesem Artikel nicht. Wer sich dafür interessiert, findet dieses Video vielleicht interessant.

Where YouTrack 6 still lacks

  • Single Sign-on in a Windows Domain: Vote for this here
  • Print sprint cards: Vote for this here (or enhance the whole agile board)
  • Support of Skype IM for notifications: Vote for this here
  • Support of enum type fields as a dop-down in order to implement the Fibonacci sequence: Vote for this here
  • Summarize states into one column in Agile Board so that showing open and reopened issues is possible: Vote for this here

Testen von Datenbankabfragen – Es geht auch einfach

In diesem Screencast zeige ich wie selbst Abfragen mit mehreren Bedingungen und Sortierungen einfach getestet werden können. Unter der Haube kommt das Entity Framework zum Einsatz. Davon kriegt man dank Dependency Injection aber nichts mit.

Die erwähnte Webcast Serie, sowie weiteren Beispielcode und das Projekt auf Github gibt es hier. Feedback oder Fragen nehme ich gerne entgegen. Wenn ihr wollt, dass ich die Serie fortsetze, sprecht mich über einen Kanal eurer Wahl an.

Bessere Enumerations in NET

Ist euch der Smell von typischen Enumerations auch schon in die Nase gestiegen? In diesem Webcast zeige ich eine Alternative zu den typischen Enums in NET. Damit können das Open Closed Principle und Separation of Concerns besser umgesetzt werden, was meiner Meinung nach zu einer höheren Kohäsion führt.

 

Weiterführende Links:

 

Wie haltet ihr es mit Enums? Arbeitet ihr schon auf diese Weise? Wollt ihr mehr Webcasts zu Clean Code?

Flexibles Bootstrapping durch Composition

In diesem Webcast zeige ich unseren Kompositions-Ansatz für das Bootstrapping. Die Interfaces sind schmal, die Implementierungen überschaubar, das Ganze ist flexibel und lässt sich gut testen.

Hier der gezeigte Code:

   1: public class BootstrapperContext

   2: {

   3:     public BootstrapperContext()

   4:     {

   5:         AppConfig = new ApplicationConfig();

   6:         Container = new WindsorContainer();

   7:     }

   8:  

   9:     public IWindsorContainer Container { get; private set; }

  10:     public ApplicationConfig AppConfig { get; private set; }

  11: }

   1: public interface IAmABootstrapperAction

   2: {

   3:     void Execute(BootstrapperContext context);

   4: }

 

   1: public interface IAmABootstrapperComposition

   2: {

   3:     IEnumerable<IAmABootstrapperAction> Actions { get; }

   4: }

 

   1: public class BootstrapperExecutor

   2: {

   3:     public static void StartupApplication(IAmABootstrapperComposition bootstrapperComposition)

   4:     {

   5:         var exceptionMessage = "Beim Starten der Anwendung ist ein Fehler aufgetreten. Bitte den Support kontaktieren.\n\n";

   6:  

   7:         if (bootstrapperComposition.Actions == null || !bootstrapperComposition.Actions.Any())

   8:         {

   9:             throw new BootstrapperException(exceptionMessage, new ArgumentOutOfRangeException("Auf dem Bootstrapper waren keine Actions definiert"));

  10:         }

  11:  

  12:         var context = new BootstrapperContext();

  13:  

  14:         var time = TimedAction.Run(() =>

  15:                                    {

  16:                                        foreach (var action in bootstrapperComposition.Actions)

  17:                                        {

  18:                                            var actionName = action.GetType().Name;

  19:                                            SiAuto.Main.LogMessage(string.Format("{0} gestartet", actionName));

  20:  

  21:                                            var timeTaken = TimedAction.Run(() => { ExecuteAction(action, context, exceptionMessage); });

  22:  

  23:                                            SiAuto.Main.LogMessage(string.Format("{0} in {1} erfolgreich durchgeführt",

  24:                                                                                 actionName,

  25:                                                                                 timeTaken.Format())

  26:                                                );

  27:                                        }

  28:                                    });

  29:     }

  30:  

  31:     private static void ExecuteAction(IAmABootstrapperAction action, BootstrapperContext context, string exceptionMessage)

  32:     {

  33:         try

  34:         {

  35:             action.Execute(context);

  36:         }

  37:         catch (Exception ex)

  38:         {

  39:             SiAuto.Main.LogException(string.Format("Fehler beim Bootstrapping: {0}", ex.GetFullExceptionMessage()), ex);

  40:             throw new BootstrapperException(string.Format("{0}{1}", exceptionMessage, ex.GetFullExceptionMessage()), ex);

  41:         }

  42:     }

  43: }

 

Welchen Ansatz verfolgt ihr?

Fragen oder Feedback könnt ihr mir gerne als Kommentar hinterlassen.

Was wollt ihr über Coding Dojos wissen?

Ich schreibe aktuell an einem Artikel zu dem Thema. Für mich sind Coding Dojos ein effektives Mittel um aktiv die kontinuierliche Verbesserung voranzutreiben. Das ist mir sehr wichtig, denn es geht viel Potential verloren, indem Wissensmanagement nur passiv abläuft. Wer sich z.B. den eigenen Code von vor 3 Jahren anschaut, wird hoffentlich feststellen, dass er heute besser entwickelt. Dieser Prozess vollzog sich quasi nebenbei. Meine Intension ist deshalb aktiv Werkzeuge zu testen und nutzen, um Verbesserungen forcierter anzugehen.

Coding Dojos sind in dem Kontext ein erprobtes Mittel. Weitere habe ich in diesem Artikel bzw. in der unten stehenden Grafik aufgelistet:

 

image

 

Den geneigten Leser würde ich bitten mir auf Twitter, Facebook oder am besten hier in die Kommentare mitzuteilen, welche Erfahrungen er mit Coding Dojos gemacht hat, wo Probleme liegen, was Erfolge waren und was er gerne in einem Artikel dazu lesen würde. Zur Anregung kann diese kleine MindMap dienen:

image

%d Bloggern gefällt das: