Frohe Weihnachten! 18.12.2014

Simone Franz
Simone Franz, Marketing Manager

Liebe Flurfunk-Leser,

wir wünschen Ihnen eine wunderschöne Weihnachtszeit und im neuen Jahr viele schöne und glückliche Augenblicke.
Und, dass wir in dieser schnelllebigen Zeit uns immer wieder Freiräume für die schönen Dinge des Lebens und Zeit füreinander nehmen.

Etikett_groß_02

Ich wünsche dir Zeit
Ich wünsche dir nicht alle möglichen Gaben.
Ich wünsche dir nur, was die meisten nicht haben:
Ich wünsche dir Zeit, dich zu freun und zu lachen,
und wenn du sie nützt, kannst du etwas draus machen.

Ich wünsche dir Zeit für dein Tun und dein Denken,
nicht nur für dich selbst, sondern auch zum Verschenken.
Ich wünsche dir Zeit – nicht zum Hasten und Rennen,
sondern die Zeit zum Zufriedensein können.

Ich wünsche dir Zeit – nicht nur so zum Vertreiben.
Ich wünsche, sie möge dir übrigbleiben
Als Zeit für das Staunen und Zeit für Vertraun,
anstatt nach der Zeit auf der Uhr nur zu schaun.

Ich wünsche dir Zeit, nach den Sternen zu greifen,
und die Zeit um zu wachsen, das heißt um zu reifen.
Ich wünsche dir Zeit, neu zu hoffen, zu lieben.
Es hat keinen Sinn, diese Zeit zu verschieben.

Ich wünsche dir Zeit, zu dir selber zu finden,
jeden Tag, jede Stunde als Glück zu empfinden.
Ich wünsche dir Zeit, auch um Schuld zu vergeben.
Ich wünsche dir: Zeit zu haben zum Leben!

Weihnachtliche Grüße vom gesamten eXpert Team und einen guten Rutsch in das Neue Jahr!

Weiter geht es mit dem Flurfunk ab dem 12. Januar 2015.

Share |

Dezember Office Day & Fränkische Weihnachtsfeier 12.12.2014

Svenja Henß
Svenja Henß, Senior Assistant

Wir konnten es kaum erwarten, aber letzten Freitag war es endlich soweit: Der letzte Office Day des Jahres und anschließend unsere fränkische Weihnachtsfeier standen auf dem Programm.

Nachdem alle eXperts in Würzburg auf der Steinburg angekommen waren und eingecheckt hatten, ging es auch schon los.

ShowTime” war angesagt und wurde vorgestellt! Smiley

Im SDX-Showcase "ShowTime" adaptieren unsere eXperts Technologien und Produkte für Enterprise-Lösungen auf Basis der Microsoft Plattform mit multiplen Frontends für iOS, Android und Windows.
Fachlich handelt es sich um eine Zeit-/Leistungserfassung mit Microsoft CRM als Backend; technisch sind multiple Frontends (Windows 8 App, Cordova Hybrid App, Xamarin Cross-Platform App, Responsive Web App), eine Enterprise-Architektur im Backend (mit CQRS-Pattern) inklusive Security (OAuth) sowie BI-Aspekte implementiert.

Danach informierte Matthias über die Personalentwicklung diesen Jahres. Werner beendete den Vormittag mit seinem Rückblick auf ein sehr erfolgreiches Jahr 2014!

Nach der Mittagspause und dem leckeren Buffet ging es am Nachmittag mit technischen Vorträgen weiter.

Die Weihnachtsfeier startete mit dem gemeinsamen Glühweinempfang auf der Panorama-Terrasse – wirklich eine beeindruckende Aussicht. Und während unseres Abendessens bekamen wir dann noch überraschend Besuch vom fränkischen Ehepaar Herrmann & Hermine, die uns die Eigenheiten der Franken und die Vorzüge des fränkischen Weins näher brachten. Zwinkerndes Smiley

Bild1Bild2Bild3Bild4Bild5Bild6bild7Bild8Bild9Bild10Bild11Bild12Bild13Bild14Bild15Bild16Bild17bild18

Share |

SSAS: regelmäßiges ProcessFull in Cubes 11.12.2014

Viktor Ewert
Viktor Ewert, Principal BI eXpert
Generell ist es sinnvoll einen SSAS Cube inkrementell (ProcessAdd, ProcessUpdate) zu verarbeiten, da dies Zeit spart. Bei den Dimensionen gibt es aber eine Besonderheit, die man beachten sollte. Bei allen inkrementellen Verarbeitungsmethoden (Insert, Delete, Update) bleiben alle bestehenden Dimensionseinträge bestehen und werden nur als gelöscht bzw. inaktiv markiert.

Dies kann dazu führen, dass die Cube-Dateien auf einem SSAS-Server sehr groß werden. Erst ein ProcessFull auf den Dimensionen sorgt dafür, dass nur noch die aktuellen Daten gespeichert bleiben.

Folgender Blogeintrag beschreibt das Problem im Detail:  http://byobi.com/blog/2013/07/why-you-need-to-routinely-processfull/
Share |

LINQ Coding Guidelines #4–Mapping von Daten separieren 09.12.2014

Alexander Jung
Alexander Jung, Chief eXpert

Mit dem letzten Beitrag hatte ich Einrückungen und Umbrüche adressiert. Die dort verwendeten Beispiele kann man aber noch deutlich durch eine weitere Maßnahme verbessern…

Empfehlung:
Mapping von Daten sollte aus LINQ-Ausdrücken herausgehalten werden.

 

Nochmal zur Erinnerung die Beispiele:

   1: public ApiExpert Get(int id)
   2: {
   3:     return this.db.eXperts
   4:         .Where(x => x.Id == id)
   5:         .ToArray()  
   6:         .Select(x => new ApiExpert
   7:         {
   8:             Id = x.Id,
   9:             IsAdmin = x.IsAdmin,
  10:             Name = x.Name,
  11:             CustomerResponse = x.CustomerStatements.Select(c =>
  12:                 new KeyValuePair<string, string>(c.Id.ToString(CultureInfo.InvariantCulture), c.Statement)
  13:                 )
  14:         })
  15:         .FirstOrDefault();
  16: }
  17: public IEnumerable<ApiExpert> Get()
  18: {
  19:     return this.db.eXperts
  20:         .Select(x => new ApiExpert
  21:         {
  22:             Id = x.Id,
  23:             IsAdmin = x.IsAdmin,
  24:             Name = x.Name,
  25:         });
  26: }

Sowie:

   1: IQueryable<AllocationTimeSpan> allTimeSpans = _context
   2:     .AllocationSet
   3:     .OfType<Allocation>()
   4:     .Select(a => new AllocationTimeSpan
   5:     {
   6:         From = a.AllocatedFrom,
   7:         To = a.AllocatedTo,
   8:         Status = (Status)(a.Status),
   9:         AvailableMDRatio = a.AvailableMDRatio
  10:     })
  11:     .Distinct()
  12:     .OrderBy(ts => ts.From);

Beiden Beispiele ist gemein, dass der Ausdruck nicht von der Abfragelogik, sondern vom Mapping der Daten dominiert wird. Das ist aus mehreren Gründen schlecht:

  • In der Regel ist die Abfragelogik wichtiger für das Verständnis, als die Details des Mappings
  • Das Mapping wird im Detail ausimplementiert (also das “wie”), anstatt einfach (deklarativ!) das “was” hinzuschreiben.
  • Die Details des Mappings werden so normalerweise redundant über den Code verteilt. Das ist natürlich bei Änderungen alles andere als wartungsfreundlich.
  • Sollte es unterschiedliche Mappings geben – zum Beispiel weil in unterschiedlichen Kontexten unterschiedliche Ausschnitte der Daten benötigt werden – ist das im Code nicht erkennbar.

Leider ist es so, dass Microsoft das ganz gerne in seinen Beispielen vormacht, die meisten Entwickler finden das also nicht sonderlich problematisch. Das heißt aber nicht, dass man es nicht besser machen könnte…

Zum Beispiel durch die Einführung von Mapper-Klassen, die sich dediziert um das Mapping der Daten kümmern:

   1: static class ExpertsMapper
   2: {
   3:     public static ApiExpert MapToUIForList(this eXperts x)
   4:     {
   5:         return new ApiExpert
   6:         {
   7:             Id = x.Id,
   8:             IsAdmin = x.IsAdmin,
   9:             Name = x.Name,
  10:         };
  11:     }
  12:  
  13:     public static ApiExpert MapToUIForDetails(this eXperts x)
  14:     {
  15:         return new ApiExpert
  16:         {
  17:             Id = x.Id,
  18:             IsAdmin = x.IsAdmin,
  19:             Name = x.Name,
  20:             CustomerResponse = x.CustomerStatements.Select(c => new KeyValuePair<string, string>(c.Id.ToString(CultureInfo.InvariantCulture), c.Statement))
  21:         };
  22:     }
  23: }

Konsequent im ersten Beispiel eingesetzt:

   1: public ApiExpert Get(int id)
   2: {
   3:     return this.db.eXperts
   4:         .Where(x => x.Id == id)
   5:         .ToArray()
   6:         .Select(x => x.MapToUIForDetails())
   7:         .FirstOrDefault();
   8: }
   9: public IEnumerable<ApiExpert> Get()
  10: {
  11:     return this.db.eXperts.Select(x => x.MapToUIForList());
  12: }

Damit lassen sich die genannten Probleme in den Griff bekommen:

  • Die Abfrage ist auf die Logik reduziert, nicht die Details des Mappings.
  • Die Logik des Mappings ist zentralisiert kann bei Änderungen leichter angepasst werden.
  • Durch die Namensgebung der Methoden wird die Intention klar.

 

Wenn das Mapping der Daten komplexer wird, etwa weit Unterabfragen ins Spiel kommen, Nullwerte geprüft oder Datentypen umgewandelt werden müssen, wird der Gewinn noch deutlicher.

Allerdings gibt es eine Grenze dort, wo der LINQ-Provider Informationen verliert. Ist das ein durchgängiger LINQ-Ausdruck, kann der Provider das womöglich über JOINs effizienter abhandeln, als wenn jedes Mapping eine separate Abfrage ausführt. Ob ein Feld mehr oder weniger abgefragt wird ist aber i.d.R. kein Problem.

Share |

WCF BehaviorExtension konfigurieren in 4.5 04.12.2014

Alexander Kabisch
Alexander Kabisch, Principal eXpert

In WCF kann man über Behaviors das Verhalten eines WCF Services anpassen. Man kann vorgefertigte Behaviors nutzen oder selber welche implementieren. Leider musste man bisher die Versionsnummer in der App.config mit angeben.
Sobald man eigene Behaviors benutzt hat und die Versionsnummer seines Projektes hochgezählt hat, musste man alle Konfigurationen nachziehen.

Dies hat sich mit 4.5 erledigt! Man muss den Fully Qualified Name nicht mehr angeben es reicht der nicht qualifizierte!

Share |

Power BI App für iPad und iPhone kommt “bald” 03.12.2014

Viktor Ewert
Viktor Ewert, Principal BI eXpert
Nachdem bereits im November 2012 die Power BI App für diverse Plattformen (Windows, Android, iOS) angekündigt wurde (Microsoft’s Mobile BI Solution für iOS, Android und Windows), und die App auch im August 2013 im Windows Store bereitgestellt wurde (Power BI App für Windows 8/RT im Windows Store verfügbar), kommt demnächst auch die iOS App.

Interessenten können sich für eine Preview unter folgendem Link anmelden: http://microsoft-news.com/microsoft-is-going-to-release-power-bi-ios-app-soon/
 
Power BI ist eine touch optimierte Business Intelligence App. In folgenden Beiträgen wird Power BI detaillierter beschrieben:
 
 
Share |

LINQ Coding Guidelines #3–Einrückungen und Umbrüche 02.12.2014

Alexander Jung
Alexander Jung, Chief eXpert

Eigentlich DAS Standardthema, wenn’s um Coding Guidelines geht: Wo breche ich Zeilen um und wie rücke ich ein?

Empfehlung:
* LINQ-Ausdrücke sollten konsequent und einheitlich umgebrochen werden.
* Unterausdrücke sollten einheitlich eingerückt werden.
* Die Einrückungstiefe sollte dem Standard im restlichen Code entsprechen.

 

Man sollte meinen, dass sich das Thema nach jahrzehntelanger Grundsatzdiskussion und automatischer Code-Formatierung in modernen IDEs von selbst erledigt hätte. Aber weit gefehlt.

Als extremes Beispiel der Anfang des RayTracers:

image

Einrückungstiefen von 1, 4, 5, 7 und noch mehr Zeichen. Umbrüche in einzelnen Unterausdrücken und Funktionsaufrufen. Und der Rest der Methode wird nicht besser.

Ebenso ein typischer Vertreter:

   1: public ApiExpert Get(int id)
   2: {
   3:     return this.db.eXperts
   4:         .Where(x => x.Id == id)
   5:         .ToArray()
   6:         .Select(x => new ApiExpert
   7:                         {
   8:                             Id = x.Id,
   9:                             IsAdmin = x.IsAdmin,
  10:                             Name = x.Name,
  11:                             CustomerResponse = x.CustomerStatements
  12:                                                     .Select(c =>
  13:                                                         new KeyValuePair<string, string>(
  14:                                                             c.Id.ToString(CultureInfo.InvariantCulture),
  15:                                                             c.Statement))
  16:                         })
  17:         .FirstOrDefault();
  18: }

Willkürliche Einrückungen. Umbrüche, die sich nicht an der Logik der Abfrage orientieren. Man hat den Eindruck, der Quelltext flüchtet zum rechten Bildschirmrand.

 

Die gleiche Methode wird gleich besser lesbar…

   1: public ApiExpert Get(int id)
   2: {
   3:     return this.db.eXperts
   4:         .Where(x => x.Id == id)
   5:         .ToArray()  
   6:         .Select(x => new ApiExpert
   7:         {
   8:             Id = x.Id,
   9:             IsAdmin = x.IsAdmin,
  10:             Name = x.Name,
  11:             CustomerResponse = x.CustomerStatements.Select(c =>
  12:                 new KeyValuePair<string, string>(c.Id.ToString(CultureInfo.InvariantCulture), c.Statement)
  13:                 )
  14:         })
  15:         .FirstOrDefault();
  16: }

… wenn sich die Einrückungstiefe am Standard (4 Zeichen) orientiert, und wenn man beim Unterausdruck auf Umbrüche verzichtet.

 

Ein weiteres Beispiel aus der Praxis:

   1: IQueryable<AllocationTimeSpan> allTimeSpans = _context.AllocationSet.OfType<Allocation>().Select(a => new AllocationTimeSpan
   2: {
   3:     From = a.AllocatedFrom,
   4:     To = a.AllocatedTo,
   5:     Status = (Status)(a.Status),
   6: }).Distinct().OrderBy(ts => ts.From);

Durch die Umbrüche dominiert das Mapping der Daten anstatt der Abfragelogik. Bricht man hingegen an den einzelnen Operationen um, wird die Logik gleich deutlicher, die Kette der Aufrufe offensichtlich:

   1: IQueryable<AllocationTimeSpan> allTimeSpans = _context
   2:     .AllocationSet
   3:     .OfType<Allocation>()
   4:     .Select(a => new AllocationTimeSpan
   5:     {
   6:         From = a.AllocatedFrom,
   7:         To = a.AllocatedTo,
   8:         Status = (Status)(a.Status),
   9:         AvailableMDRatio = a.AvailableMDRatio
  10:     })
  11:     .Distinct()
  12:     .OrderBy(ts => ts.From);

 

Leider unterstützt einen die Code-Formatierung im Visual Studio bei der Formatierung von LINQ-Ausdrücken nicht immer so ganz ideal. Aber wenn man sich an ein oder zwei Eigenheiten gewöhnt hat (z.B. den Lambda-Ausdruck in einem Select in der gleichen Zeile zu beginnen, statt in die nächste Zeile zu rücken), dann kann man auch damit gut lesbaren Code produzieren – wenn man das will.

Share |

Mathematische Operationen mit Nullable-Types 27.11.2014

Max Jäger
Max Jäger, Senior eXpert
Value-Types können per Definition nicht null sein. Sie können jedoch durch die Klasse System.Nullable gewrappt werden – C# erlaubt eine verkürzte Darstellung mit Fragezeichen nach dem Typ –, sodass einer Variablen nun auch der Wert null zugewiesen werden kann. Doch wie verhält sich eine solche Variable bei mathematischen Operationen, wie z. B. einer Multiplikation?

Wir haben beispielsweise drei Variablen des gleichen Typs, die wir miteinander multiplizieren möchten, von der jedoch eine nullable ist.

   1: int a = 20;
   2: int b = 30;
   3: int? c = null;
   4:  
   5: int? result = a * b * c;

Nun stellt sich die Frage, was bei der Berechnung als Ergebnis herauskommt.

Eine erste Annahme könnte sein, dass eine Exception geworfen wird. Das passiert jedoch nicht. Eine zweite Annahme könnte sein, dass anstatt null der Wert 0 angenommen wird. Auch das passiert nicht. Null ist nicht definiert, und somit kann kein bestimmter Wert angenommen werden - auch nicht 0.

Führen wir generell mathematische Operationen mit Variablen unterschiedlicher Typen durch, so ist das Ergebnis immer vom Typ des "größeren" Typs (int + long = long, etc.). Ist ein Typ davon jedoch Nullable, so wird das Ergebnis immer vom Type Nullable des "größeren" Typs sein (int? + long = long?, etc.).

Dies gibt auch schon einen Hinweis auf das Ergebnis unserer Multiplikation: das Ergebnis ist null, sobald auch nur eine Variable null ist.

Eine funktionierende Variante des oben angegebenen Codes könnte folgendermaßen aussehen, sofern die Variable c nicht in die Berechnung mit eingehen soll, wenn sie null ist:

   1: int? result = c.HasValue
   2:  ? (a * b * c.Value)
   3:  : (int?)(a * b);

Soll ein bestimmter Default-Wert verwendet werden, lässt sich dies folgendermaßen durchführen:

   1: int result = a * b * c.GetValueOrDefault(1);

Bei mathematischen Berechnung mit über Nullable gewrappten Datentypen ist somit Vorsicht geboten, um keine unerwarteten Werte zu erhalten.

Eine detaillierte Darstellung der Verarbeitung von Nullable-Typen findet sich hier.

Share |