@LaTino: Nein ich meinte, dass ich Agile/Lean wenn möglich immer verwenden würde.
Ich grenze das Folgende mal auf Software ein, die von Menschen bedient wird.
Der Kunde ist nicht unbedingt der Nutzer,. Das heißt irgendein Manager oder Projektleiter trifft Entscheidungen und ein Sachbearbeiter nutzt das Ding dann. Oder ein Endkunde für eine SaaS Projekt oder auch nur einfach ein Besucher einer Webseite. Und hier gibt es eine riesige Lücke, weil der Projektleiter einfach nicht wissen kann, was die beste Alternative ist. Soll der Button jetzt grün oder blau sein? Hat uU. einen großen Effekt auf die Conversion. Da hilft Erfahrung auch nicht viel weiter.
Diese Wissenslücke kann der Projektleiter zum Beispiel schließen indem er vor dem eigentlichen Projekt Prototypen baut und sie an Nutzer testet. Aber die besten Tests sind am richtigen Produkt. Agile Entwicklung sorgt für kontinuierliches Feedback durch den Kunden und Lean Development schließt die Feedback Lücke zum Endnutzer. Um die langfristige Zufriedenheit des Kunden zu garantieren, sehe ich keine Alternative.
Mich würde mal interessieren, wie ihr ein Projekt als "erfolgreich" bewertet. Aus IT Sicht mag es ja ausreichen, wenn der Auftraggeber zufrieden ist, aber das heißt ja erstmal gar nichts.
Ich sehe nämlich nicht, dass irgendeine Expertenkommission in der Lage wäre Anforderungen richtig abzuschätzen. Wie soll man als Abteilungsleiter beim Arbeitsamt wissen, wie Daten am besten einzupflegen sind, wenn man das selbst kaum noch selber machen muss? Man kann auch nicht von sich auf andere Benutzer schließen, obwohl dass viele Manager leider versuchen. Das heißt ohne ein Prozess mit kontinuierlichen Experimenten ist die Gefahr einfach extrem groß, dass man in die falsche Richtung rennt (oder das neue Produkt einfach nicht so gut wird wie erwartet).
ich verstehe einfach nicht, wie man NICHT Agile/Lean arbeiten will.
Ich schließe jetzt mal Software für den Eurofighter oder technische Integrationsprojekte hier aus, da mag vll. Agile wirklich nicht so gut funktionieren, habe aber auch noch keine SW für den Eurofighter geschrieben (ist wahrscheinlich besser so).
Ich brauche in manchen Fällen eine Entkopplung und asynchrone Kommunikation. z.B. mit RabbitMq oder Kafka oder Azure Service Bus. In dieser asynchronen Kommunikation können auch Menschen beteiligt sein, weil sich manche Buchungsschritte und Fehlerbehandlungen (noch) nicht automatisieren lassen.
Das heißt im Kern habe ich eine Art ProcessManager der auf Events reagiert und daraufhin Events auslöst. Diese Events müssen jetzt von verschiedenen Services behandelt werden.
Ein Teil der Events sind im Prinzip an einem bestimmten Empfänger gerichtet, der auch mal Offline sein kann, z.B. Amadeus-Flug-Buchungssystem, andere Events werden z.B. von mehreren Services konsumiert. Beispielsweise wird wenn eine Buchung abeschlossen wird, eine Email versendet, eine Rechnung verschickt, ein Report aktualisiert und die Information an das Accounting System geschickt.
Ich könnte z.B. einfach Kafka oder EventStore für die asynchrone Kommunikation verwenden, müsste dann aber für die synchrone Kommunikation auch noch mit gRPC arbeiten. Die Frage ist, ob ich das auch irgendwie abstrahieren kann, bspw.
1. Ich kann natürlich ein Art Adapter schreiben, der beide Kommunikationsprotokolle für die Microservices kapselt. Wenn alle Services mit der gleichen Sprache arbeiten, kann ich das ja einfach als NuGet zur Verfügung stellen.
2. Ich könnte auch nur auf asynchrone Kommunikation setzen. Request / Reply ist aber nicht so einfach. Evtl. muss ich dann mit temporären Queues arbeiten, Timeouts werden schwieriger usw.
Ich finde gRpc auch super und die Proto Files sind klasse, aber wie kann damit asynchrone Kommunikation machen? Ich meinte nicht Async I/O (Async Task usw.) sondern im Prinzip Messaging mit Queues / MessageBus usw.
wir planen testweise ein neues Buchungssystem auf der Basis von Microservices. Das wird erstmal ein Spiel und Testprojekt und es ist unklar, ob es jemals zum Einsatz kommen wird. Unser System muss Hotelbuchungen, Flüge, Mietwagen und Zusatzprodukte bedienen können. Außerdem natürlich noch mehrere Payment Provider usw.
Ein großes Problem unseres aktuellen Systems ist, dass es synchron arbeitet, d.h. der Benutzer klickt "Jetzt buchen" und dann kommt ein Spinner und wir haben 1 Minute alles abzuschließen. Das ist erstmal relativ wenig Zeit, wenn viele Produkte im Warenkorb sind. Außerdem gibt es immer mal wieder Fehler und Produkte können auch ausverkauft sein. Deshalb soll es in Zukunft asynchron arbeiten. Das heißt der Benutzer bekommt sofort eine Antwort "Buchung wird bearbeitet" und dann später eine Email, wenn alles abgeschlossen wird. Dadurch können wir auch manuell eingreifen und Alternativen anbieten, z.B. ein besseres Zimmer, falls das die Provision erlaubt.
Ein Teil der Kommunikation zwischen Services ist synchron (= Request/Response), z.B:
* Zahlung beginnen (generiert vll. nur einen Deeplink zu Paypal etc.)
* Produkt validieren (sind die Eingaben gültig etc.)
Ein Teil der Kommunikation auch asynchron (= Messaging):
Jetzt wäre es super, wenn man das Kommunikationsprotokoll relativ kompakt halten könnte. Habt ihr Erfahrung mit irgendwelchen Alternativen die im Prinzip beide Kommunikationsmuster abdecken? z.B. Akka.NET, Orleans. Was sind da eure Erfahrungen?
Du musst dir aber dann überlegen, ob du Commands asynchron verarbeiten kannst - auch im Client - und wie dann (hast du ja erwähnt) Antworten verarbeitet werden. Was ist z.B. wenn Commands abgelehnt werden, weil die Validierung fehlschlägt? z.B. Uniqueness Constraints?
Das ist dann aber vom Client her motiviert und nicht vom Server.
Aus der Perspektive des Servers geht es bei den Queues v.a. um die sequentielle Verarbeitung. Wenn dein Client auf das die Bearbeitung des Commands wartet hat er ja auch eine Erwartung an die Verarbeitungsgeschwindigkeit, dann kannst du alte Commands auch einfach wegwerfen, egal ob dein Server crasht oder nicht.
Kurz: Ich würde mir genau überlegen ob du synchrone oder asynchrone Command-Verarbeitung willst.
Falls ihr noch keine Aggregate Roots habt, ist es wirklich das wichtigste diese Konsistenz Grenzen zu definieren und dann hat man auch fast schon die Aggregate Roots.
Du brauchst aber keine Queue pro Aggregate Root, das wäre eine krasse Partitionierung. Die Queue verringert in erster Linie die Anforderungen an transaktionale Änderungen der Datenbank (und natürlich ein bisschen Last). Falls du das ganze Aggregate Root transaktional speichern kanns, kannst du es auch einfach mit einem Retry versuchen.
Das hängt auch damit zusammen was ihr noch innerhalb eines Commands macht. Falls z.B. noch mit Externen Systemen kommuniziert wird geht es fast nicht ohne Queues (auch in CQRS würde man das oft sequentiell verarbeiten, aber eher dann in den Event Handlern oder Process Managern).
Commands sequentiell zu verarbeiten ist absolut normal und auch durchaus notwendig. Immerhin ist CQRS ja gerade ein Pattern für Collaboration.
Wichtig ist es v.a. Aggregate Roots gut zu wählen. Die wichtigste Bedingung ist Konsistenz: Choosing Aggregate Boundaries – Consistency. In einem Buchungssystem können z.B. Buchungen für ein Hotel nicht Parallel verarbeitet werden. Das heißt du machst aus einem Hotel ein Aggregate Root und verarbeitest die Commands für dieses Hotel sequentiell.
Ich würde bloß nicht locken sondern eher über Queues nachdenken und dann überlegen, wie du partitionierst. Am besten über AggregateId % NumPartitions oder pro Stadt in dem sich das Hotel befindet. Das funktioniert aber nur auf Aggregate Ebene, falls deine Operationen übergreifend sind würde ich das über einen ProcessManager abbilden (=Saga) und dann die EventHandler partitionieren.
Btw: Genau dafür gibt es ja auch den CommandBus, es ist einfach das Dispatching zu ändern.
Klar, kann man. Aber danach habe ich gar nicht gefragt. Google benutzen kriege ich schon einigermaßen hin ;). Vielleicht habe ich mich aber auch ein bisschen unklar ausgedrückt.
Ich hatte auf Erfahrungsberichte gehofft, z.B.
1. Habt ihr OData mit einem Data Provider verwendet, der kein Linq unterstützt? Wie groß ist dabei der Aufwand?
2. Habt ihr OData mit einem dynamischen Model verwendet und wie ist eure Erfahrung?
3. Wie groß ist die Adaption von OData? Wie außerhalb des MS Umfelds?
4. Wie stark musstet ihr OData einschränken?
5. Hattet ihr schon mal Probleme im Produktionsbetrieb weil Abfragen zu lange gedauert haben?
6. ...
Mir sind die Implikationen von OData noch nicht ganz klar. Und der Aufwand und Komplexität um einen guten Abstraktionsgrad zu erreichen scheinen mir doch relativ groß zu sein. Die Spezifikation ist ja auch so umfangreich, dass Implementierungen schon sehr unterscheidlich sein können.
Ich habe noch nicht mit OData gearbeitet und auch noch kein Service direkt verwendet, der OData unterstützt (also wahrscheinlich indirekt mit irgendwelchen Azure Client Libraries), bin aber daran interessiert, wie ihr das mit dem $filter handelt.
Bisher hatte ich Service Methoden, dich ich 100% kontrollieren konnte. Das heißt ich kenne die verschiedenen Optionen und kann den kompletten Kontrollfluss kontrollieren. Zum Beispiel Datenbankabfragen optimieren. Mit OData kommt viel Flexibilität ins Spiel und damit auch die Gefahr, dass sehr langsame Abfragen abgesetzt werden müssen.
Grenzt Ihr die Filter Möglichkeiten so ein, dass ihr nur Abfragen ermöglicht, die unproblematisch sind oder lebt ihr einfach mit dem Risiko?
Wie löst ihr das Mapping auf die Datenbank? In diesem Thread scheint es auch keine richtig gute Antwort zu geben: oData und die 3-Schichten-Architektur
Ich habe im Grund genommen die gleiche Aussage bzgl. TDD gemacht. Kleinere Module in Projekten helfen auch enorm bei TDD. Lange Build Zeiten kann man einfach nicht immer verhindern.
Ich finde die Build Zeit sehr wichtig - gerade für TDD - und würde dafür auch einige Kompromisse eingehen.
Wenn man seine Anwendung modularisiert, geht es auch immer darum, kleine Hürden aufzubauen, diese Modularisierung nicht zu umgehen. Diese werden aber zumindest in großen Projekten sehr häufig umgangen, zum Beispiel mit Aufrufen auf die Datenbank. Ich persönlich finde die Hürden bei mehreren Projekten aber so niedrig, dass man auch darauf verzichten kann. (Da sind mehrere Solutions und Micro Services besser geeignet wie ich finde).
Für mich sind Projekte aber vor allem eine Möglichkeit mich auf ein Problem zu fokussieren. Pro Projekt würde ich auch ein Projekt für die Tests anlegen und hat dann beides sehr nahe beieinander. Das reduziert die Build Zeit für die Tests drastisch und zur Not kann man ja auch alle anderen Projekte in Visual Studio vorübergehend deaktiveren.
Außerdem werden größere Refaktorisierungs leichter. Hierbei hat man bei wenigen Projekten oftmals das Problem dass für einige Stunden erstmal gar nichts mehr funktioniert. Das Projekt buildet nicht mehr und Tests kann ich auch nicht laufen lassen. Habe ich viele Projekte angelegt, kann ich mich von unten nach oben durcharbeiten und Etappenweise das Refactoring implementieren.
ich hatte vor einigen Jahren ein OpenSource Project für Silverlight und Windows Phone (http://imagetools.codeplex.com/). Das hat sehr viel Spaß gemacht und ich hätte mal wieder Lust was zu bauen.
Ich hoffe sehr, das ASP.NET Core Erfolg hat. Insbesondere die einfache Runtime und Cross Plattform ist vielversprechend und vielleicht wird es ja auch vermehrt für kleinere Seiten eingesetzt. Daher liegt es für mich nahe, was in diese Richtung zu bauen. Ich hätte 2 Ideen und hätte gerne Feedback.
Die Zielgruppe sind jeweils kleinere und mittelgroße Projekte
1. Backend Tools
In meiner alten Position haben wir viele Module selber gebaut, wie zum Beispiel Caching oder bestehende Module integriert, wie zum Beispiel ASP.NET Identity. Das Problem war dabei, dass wir selten eine Oberfläche dafür hatten und es auch kein System gab, dass man einfach integrieren konnten. Deshalb haben wir ein Mini MVC Framework auf Basis von Microsoft Owin gebaut, dass einfach in bestehende Anwendungen integriert werden kann. Dies UI Module sind im Prinzip kleine Angular Apps. Die Inspiration dazu hat http://hangfire.io/ geliefert.
Vorteile:
* Sehr leicht in Windows Service, API und Frontends einsetzbar
* Wenig Abhängigkeiten (nur Owin und JSON.NET)
* Man muss nicht das ganze Packet verwenden, sondern nur was man braucht
Nachteile:
* Bei Microservices gibt es evtl. viele Stellen, bei denen man Sachen verwalten muss
Ich habe ein Screenshot eines Administrations Modules mal angehängt. Die aktuelle Implementierung hat auch einige Probleme. Basis Auth nervt zum Beispiel ein bisschen. Trotzdem war das System sehr hilfreich für uns weil wir einige Microservices gebaut haben, die dann mit wenig Aufwand ihre eigenen Administrations Tools spendiert bekommen haben. Bei einer neuen Implementierung würde ich evtl. die Daten von mehreren Services aggregieren wollen und Systeme bauen, mit denen ein Service als Provider für andere Services dienen kann. Beispiel: Je nach Szenario sollen die Texte für API und Web Frontend getrennt sein oder zusammen verwalten werden. Da jedes Module eh API's zur Administration zur Verfügung stellen muss, kann ServiceA auch für ServiceB Texte bereitstellen.
2. Headless CMS
Meine ASP.NET/Core Anwendungen haben natürlich sehr viel Domain spezifischen Code, für den es kein fertiges Modul gibt. Allerdings bin ich es Leid dauernd irgendwelchen banalen CRUD Lösungen zu bauen. Die Idee ist ein ASP.NET Core Modul zu bauen, dass ein Headless CMS bereitstellt (analog zu: https://www.contentful.com/features/). Ich möchte keinen App Builder bauen, sondern eine Lösung liefern, um ein Teil der Anwendung zu realisieren. z.B. Blog Posts, Content Element, Übersetzungen usw.
Um diese Module zu realisieren braucht man nicht Einstein sein, trotzdem ist es zeitaufwendig all die Repositories und Services zu entwickeln. Außerdem muss eine UI gebaut werden und all die kleinen Features, die in der Summe dann doch kostspielig sind.
Im Prinzip könnte man beide Projekte in ein gemeinsames Projekt integrieren. Allerdings ist meine Zeit natürlich begrenzt.
Ich hätte gerne Feedback zu beiden Ideen. Würdet ihr sowas einsetzen? Falls nicht, warum? Habt ihr vielleicht andere Ideen?
Was soll eine Db Sicht sein? Für eine DB ist eher wichtig, dass der Primary Key nicht null sein darf, dass es nicht mehr als X Columns gibt usw. Alles andere sind Business Regeln, die (aus gutem Grund) auch in der Datenbank durchgesetzt werden.
Für mich persönlich funktioniert es übrigens besser, wenn ich richtige Business Objekte in das Repository packe. Da ist der Aufwand aber wirklich deutlich höher, weil diese nicht immer 1:1 auf die DB gemappt werden können.
Klar, wenn du Typen hast die du in deinem ganzen Modul oder sogar Anwendung verwenden willst, ist das eine super Sache. Beispielsweise Vectoren in einem Game (man könnte ja auch float[3] verwenden ;)
Aber um 200 Zeilen Code zu verbessern, sind 400 Zeilen für Datentypen (inkl. Equals, HashCode, operatoren, ToString usw. ) vielleicht ein bisschen unverhältnismäßig.
So wie ich das sehe, brauchst du globale Konfliktfreie Sortierregeln (Also nicht sowas wie "a" vor "b" und "b" vor "a"). Falls sowohl die Listen selbst, als auch die Einträge innerhalb der Listen vorsortiert sind, kannst du das vorgeschlagene OrderDictionary<char, char> verwenden.
Implementiere doch einfach nen IComparer<char> und dann kannst du sowas machen:
var uniqueValues = new HashSet<char>();
foreach (var list in lists) {
foreach (var value in list) {
uniqueValues.Add(list);
}
}
var orderedUnique = uniqueValues.OrderBy(x => x, new MyComparer()).ToList();
Das kann man z.B. verwenden, wenn man in requirejs und co Abhängigkeiten zwischen Javascript Module definiert. Dann ist die Frage, in welcher Reihenfolge man diese im Browser und Node.JS laden muss. In jeder Liste ist dann einfach jedes Element von seinen Nachfolgern abhängig. Wenn du alle Elemente in eine solche Struktur bringt, kannst du es durch eine Topologische Sortierung jagen:
z.B. so
class ItemWithDependencies {
public char Item {get;set;}
public HashSet<char> Dependencies {get;set;}
}
Dictionary<char, ItemWithDependencies> items = ...;
foreach (var list of lists)
{
for (int i = 0; i < list.Count; i++)
{
var item = list[i];
ItemWithDependencies itemWithDependencies = null;
if (!items.TryGetValue(item out itemWithDependencies)) {
itemWithDependencies = new ItemWithDependencies { Item = item };
items.Add(item, itemWithDependencies);
}
for (int j = i + 1; j < list.Count; j++) {
itemWithDependencies.Dependencies.Add(list[j]);
}
}
}
SortByTopology(items);
Ich meinte eher, dass die Reihenfolge nicht erhalten bleibt. Zumindest wenn es über ein internes Array realisiert wird. OrderedDictionary sollte die Reihenfolge erhalten, SortedDictionary sortiert nach dem Key (bzw. dem Comparer).
A HashSet<T> collection is not sorted and cannot contain duplicate elements. If order or element duplication is more important than performance for your application, consider using the List<T> class together with the Sort method.
Das Problem ist, dass Interfaces nur ein Typescript Konzept sind um Typsicherheit zu verbessern. Im erzeugten Javascript existieren die aber nicht mehr. Wenn du also Typemoq nur ein Interface übergeben würdest, hätte es keine Informationen mehr über die zu mockenden Funktionen.
Deshalb kann man in Angular2 auch Interfaces nicht direkt im Service Container über provide registrieren und darüber Abhängigkeiten auflösen.
Allerdings braucht man Interfaces auch weniger. Du kannst nämlich eine Klasse als Mockup verwenden. TypeMoq tauscht dann einfach die Methoden aus. Das geht sehr leicht, es sei denn du hast einen komplexen Constructor mit Dependencies. Dann müsstest du TypeMoq alle Parameter übergeben. Was du dann zum Beispiel machen kannst ist:
class Foo { }
class Bar implements Foo {}
Damit kannst du dir eine neue Klasse erstellen, die nichts macht, die du aber dann Typemoq übergeben kannst. wenn du es brauchst.