Peter Bucher - Mein Experiment, meine Spielereien, meine Welt...   ·   Stefan Falz   ·   Jürgen Gutsch   ·   Golo Roden   ·   ASP.NET Zone   ·   Microsoft ASP.NET
Willkommen bei ASP.NET Zone. Anmelden | Registrieren | Hilfe

ASP / ASP.NET MVP 2010

Anfang Jahr erhielt ich eine Email von Microsoft, das ich für das Jahr 2010 renominiert wurde :)

Das freut mich ungemein und ich möchte mich bei den Betreibern und Moderatoren von ASP.NET Zone und myCSharp bedanken.
Diese Auszeichnung durfte ich jetzt schon das vierte Mal in Folge entgegennehmen, wobei 4 meine Lieblingszahl ist :)

Sicherlich finde ich die Zeit auch mal in Konstanz beim .NET Stammtisch Konstanz / Kreuzlingen vorbeizuschauen und einen Vortrag zu halten.

Auf ein erfolgreiches Jahr 2010!

Eingetragen von Peter Bucher | 5 Kommentare
Abgelegt unter: , , ,

this oder kein this

Am 13. Oktober 2008 haben Golo Roden und ich unter dem Titel Noch Fragen, Roden? Ja, Bucher! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen.

Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. Januar 2010, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

this oder kein this

So wohl Golo wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Golos Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema.

Generell ist es sinnvoll, wenn ohne weiteres Zutun gleich erfasst werden kann, ob es sich um eine lokale, statische oder instanzbehaftete Variable handelt.
Aus diesem Grund gibt es Konventionen, wie etwas auszusehen hat, sei dies mit Pascal- (fooBar) / Camel-Casing (FooBar) oder durch Prä- / Postfixe (m_foo, foo_m).

Im Allgemeinen hat es sich bei mir so entwickelt, dass ich mich immer mehr zu der empfohlenen Microsoft Konvention hin bewegt habe, was die Einarbeitung in andere Projeke um einiges leichter macht,
da diese Konvention häufig – wenn auch teilweise abgeändert – verwendet wird.

Im aktuellen Streitgespräch geht es darum, ob this verwendet wird / nicht verwendet wird und wo es verwendet wird.

this wird zwanghaft benötigt, um auf die Referenz auf sich selber, in die Hand zu bekommen.
Beispielsweise wenn in einer User-Klasse eine .Save-Methode angeboten wird, die ihrerseits aber einen Service benutzt um sich speichern zu lassen:


public class User
{
    public void Save()
    {
        ServiceLocator
                .Resolve<IUserService>()
                .Save(this);
    }
}

Erweiterungsmethoden benutzen this als Kennzeichnung:


static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    foreach (var item in source)
    {
        action(item);
    }
}

Bei einer Indexerdeklaration wird this auch benötigt:

public User this[sring index]
{
   get { return this._list[index]; }
   set { this._list[index] = value; }
}

Ein andere Stelle wo this benutzt werden muss, ist beim angeben von zusätzlichen Konstruktoren von sich selbst, die auch noch aufgerufen werden sollen:


public class UserService
{
    private readonly IRepository<User> _userRepository; 

    public UserService() : this(new XmlUserRepository())
    {
       
    }
    public UserService(IRepository<User> userRepository)
    {
         _userRepository = userRepository;
    }
}

Im ersten Konstruktor wird angegeben, das auch der zweite Konstruktor mit einem Parameter aufgerufen werden soll.

Wenn die Instanzvariable “_userRepository” keinen Unterstrich hätte – also “userRepository” – müsste this verwendet werden, damit der Kompiler zwischen Instanzvariable und Argument unterscheiden kann, also:


private readonly IRepository<User> userRepository;
public UserService(IRepository<User> userRepository)
{
    this.userRepository = userRepository;
}

Zu Anfang habe ich das Präfix “_” vor einer Instanzvariable benutzt, so kann man – auch im Intellisense – ohne Probleme auswählen und unterscheiden, da alle schön gruppiert sind.

In Visual Studio 2005 gab es allerdings kein Intellisense bei der Eingabe von “_test” im Code-Editor.
Ich habe dort “this._test” genutzt, denn es ist ja ein Instanzmember und mit der Eingabe von “this.” gab es dann Intellisense.

Ab Visual Studio 2008 gibt es bereits bei der Eingabe von “_” Intellisense, somit wäre “this” überflüssig. Allerdings habe ich mir angewöhnt, this überall anzugeben, wo sich etwas auf die Instanz bezieht.

Also für Methodenaufrufe auf der Instanz (in der Regel protected oder private Methoden), Eigenschaften sowie Instanzfelder.
Es ist so möglich auf den ersten Blick zu unterscheiden und erfassen, was eine lokale Variable ist, was ein statisches Feld / Konstante. Oder doch eine Instanzvariable?.

Was meint ihr dazu?

Eingetragen von Peter Bucher | 0 Kommentare
Abgelegt unter: , ,

InternalsVisibleToAttribute und signierte Assemblies: So funktionierts garantiert.

Stellt euch vor, ihr habt zwei Assemblies:

  • MyProject.Core
  • MyProject.Core.Tests

Im Core-Projekt gibt es Typen, die nicht öffentlich gemacht werden sollten, allerdings für die UnitTests zugänglich sein sollen.
Nun, das ist ein kleines Problem, wenn man das Attribut “InternalsVisibleTo” kennt, mithilfe folgender Dekleration in der AssemblyInfo.cs des MyProject.Core-Projekts kann dies einfach erledigt werden:

[assembly: InternalsVisibleTo("MyProject.Core.Tests”)]


Das macht sogar sehr viel Sinn, denn sonst können Kollisionen und Verwechslungen der Extensionmethods beim Endbenutzer vorkommen.

Soweit, so gut. Die Typen der MyProject.Core-Assembly sind jetzt in der MyProject.Core.Tests-Assembly sichtbar.
Müssen die Projekte jedoch signiert sein, kommt es zu einem grösseren Problem.

In mehreren Blogs sind die nötigen Schritte beschrieben, jedoch werden da wichtige Punkte nicht genannt, die einem zur Verzweiflung treiben können.
Die sind wie folgt:

  • Alle involvierten Assemblies müssen signiert werden.
  • Der PublicKey muss vom Projekt bezogen werden, bei dem die Internals sichtbar werden sollen, in unserem Fall also das MyProject.Core.Tests-Projekt.

Nach einer weiteren Suche bin ich schlussendlich auf einem (selbsternannten) Newbie-Blog fündig geworden.
Noch später sties ich dann auf die folgende Anleitung, die eigentlich alles beinhaltet, sodass ich nicht alles im Detail niederschreiben muss, trotzdem die wichtigen Punkte nennen kann und vorallem die Lösung wieder einmal finde:

Also, beachtet die oben stehenden zwei Punkte und haltet euch an folgende Anleitung:

Eingetragen von Peter Bucher | 2 Kommentare

Reflection – Fluch oder Segen?

Am 13. Oktober 2008 haben Golo Roden und ich unter dem Titel Noch Fragen, Roden? Ja, Bucher! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen.

Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. Dezember 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

Reflection – Fluch oder Segen?

So wohl Golo wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Golos Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema:

 

Reflection?

Reflection, Reflexion bzw. Introspektion macht es möglich, Programme wie Daten zu behandeln und so Informationen über Typen / Member abzurufen und auch zu setzen.

Eine Einführung zu Reflection findet sich bspw. hier, und auf myCSharp.de findet sich ein super ausführlicher und tiefgehender Artikel, der auf jeden Fall lesenswert ist.
Darüber hinaus ist es per Reflection möglich, eine späte Bindung in jeglicher Hinsicht zu erreichen. Sei dies das dynamische Laden einer Assembly oder auch das dynamische Aufrufen einer Methode zur Laufzeit.
Damit lassen sich Service Locator und Dependency Injection Container - also Systeme zur Entkoppelung - umsetzen, die je nach Konfiguration eine andere Assembly mitsamt ihren Typen lädt.

Ein praktischer Anwendungsfall wäre ein Serialisierungsmechanismus, der Objekthierarchien bspw. in XML-Form abspeichern kann.
Mithilfe von Reflection können die zu speichernden Typen in Form einer Instanz von System.Reflection.Type abgefragt werden.

Ein Type Objekt macht alles verfügbar, was zu einem Typen gehört, seien dies Methoden, Attribute, Eigenschaften oder gar Felder.

Kleines Beispiel:

int count = 2012;
Type typeOfCount = count.GetType(); // Oder: typeof(int)
Console.WriteLine(typeOfCount);

Ausgabe ist die Stringrepräsentation des Types der mit dem Alias int verknüpft ist, also: “System.Int32”.

Schluss ist damit noch lange nicht, es ist genau so möglich Code zur Kompile- oder Laufzeit dynamisch zu erstellen.
Das .NET Framework bietet die hierzu nötigen Klassen im Namensraum System.Reflection.Emit bereit.

Die Anwendung dieser API ist jedoch relativ umständlich und komplex, dafür extrem mächtig.

 

Segen?

Reflection und Bibliotheken die darauf aufbauen birgen ein riesen Potential und ungeahnte Möglichkeiten.
Die Anwendung ist extrem einfach und viele Features im .NET Framework selber bauen auch auf Reflection auf.

Also auf jeden Fall ein Segen… auf der einen Seite.

 

Fluch?

Auf der anderen Seite kann es auch zu einem Fluch werden, denn mit Reflection kann viel Humbug getrieben werden.
Zum einen ist die Ausführung von Code der Reflection nutzt, um einiges langsamer, was zu Performanceproblemen führen kann, zum anderen kann so auch die Mauer der Zugriffsmodifizierer umgangen werden, da es ohne viel Aufwand möglich ist, auch private Members einer Klasse auszulesen.

Zudem können Probleme auftreten, wenn die Umgebung in der eine Anwendung läuft, zuwenig Rechte hat. Das kann dazu führen, das eine Anwendung überhaupt nicht, oder nur eingeschränkt lauffähig ist, in restriktiven Umgebungen.

Über das dynamische Laden von Assemblies kann es zu Sicherheitsproblemen kommen, falls die geladenen Assemblies schädlichen Code enthalten.

Allerdings lassen sich viele der geschilderten Probleme umgehen bzw. beheben.
Caching – dafür gibt es auch schon diverse, fertige APIs, die auch neben Caching noch weitere Verbesserungen für Reflection bringen.

Alle anderen Probleme brauchen eine vorsichtige und sparsame Verwendung von Reflection.
Mein Credo dabei ist: So viel wie nötig, so wenig wie möglich. Denn sehr vieles geht auch ohne Reflection, kann aber mit Reflection nachgebaut werden.

 

System.Linq.Expressions

Mit der Einführung von LINQ und in dessen Zuge auch dem neuen Namensraum System.Linq.Expressions gibt es eine weitere und einfachere Möglichkeit, Code dynamisch zu generieren und vorallem auch zu analysieren.

Zum einen ist es mit LINQ und den Expression Trees möglich, Lambda Ausdrücke, die in eine Methode eingespiesen werden, auseinander zu nehmen und zu analysieren.
In .NET selber wird das bspw. verwendet, um LINQ abfragen zu parsen und diese anschliessend in ein SQL-Statement zu überführen.

Zumindest laut meinem Wissen, ist es mit dem Expressions-API nur möglich, Methoden dynamisch zu generieren und zu kompilieren. Das ist eine Einschränkung, die allerdings für viele Anwendungsfälle nicht weiter tragisch ist, damit lässt einfach schon relativ viel realisieren.

Das Expressions-API nutzt intern auch Reflection und schlussendlich auch die Klassen aus dem Namensraum System.Reflection.Emit.

Beispiele mit dem Expressions-API:

Addieren von zwei Zahlen per statischem Code.
private void AddPlain()
{
  int one = 1;
  int two = 2;

  int result = one + two;
}

Addieren von zwei Zahlen, die Methode wird dynamisch zusammengebaut.
private static void AddWithExpressions()
{
  ConstantExpression numberOneExpression = Expression.Constant(2);
  ConstantExpression numberTwoExpression = Expression.Constant(3);

  BinaryExpression addExpression = Expression.Add(numberOneExpression, numberTwoExpression);

  var lambdaExpression = Expression.Lambda<Func<int>>(addExpression);
  Func<int> methodDelegate = lambdaExpression.Compile();

  int result = methodDelegate();
}


Funktion zum Addieren von zwei Zahlen per statischm Code.
private static int AddFunctionPlain(int left, int right)
{
  return left + right;
}

Funktion zum Addieren von zwei Zahlen dynamische generiert.
private static Func<int, int, int> GenerateAddFunction()
{
  ParameterExpression leftParameter = Expression.Parameter(typeof(int), "left");
  ParameterExpression rightParameter = Expression.Parameter(typeof(int), "right");

  BinaryExpression addExpression = Expression.Add(leftParameter, rightParameter);

  var lambdaExpression = Expression.Lambda<Func<int, int, int>>(addExpression, leftParameter, rightParameter);
  Func<int, int, int> methodDelegate = lambdaExpression.Compile();

  return methodDelegate;
}

Wie man sehen kann, ist die Nutzung von Expressions zum dynamische Generieren von Methoden für Ihre Mächtigkeit immer noch relativ einfach zu nutzen.

 

Fazit

Das war ein kurzer Rundflug durch Reflection und verwandte Gebiete, in dem ich versucht habe, die Vorteile, Möglichkeiten sowie auch Gefahren aufzuzeigen.
Reflection ist genial, aber nur wenn es sinngemäss und mit Vorsicht eingesetzt wird.

Also: Fluch und Segen :)

Wann IEnumerable nutzen, wann ICollection und wieso überhaupt IList?

Es gibt einige Mengen- /  Auflistungstypen in .NET.

Ein kleine Auswahl:

Früher gab es nur nicht generische bzw. keine stark typisierte Collections, die heute nicht mehr verwendet werden sollten,
da immer explizit gecastet werden muss, was umständlich ist und Performance kostet.

Hierfür zitiere ich gerne herbivore aus myCSharp:

ArrayList gehört in die Mottenkiste und sollte wie alle untypisierten Collections aus System.Collections nicht mehr benutzt werden. Verwende stattdessen List<T> und alle anderen typisierten Collections aus System.Collections.Generic.

Ich möchte hier allerdings nicht die verschiedenen Auflistungstypen im Detail anschauen, sondern herausfinden, wann welcher konkreter Typ oder gar das Interface in einer Signatur verwendet werden sollte.

Ein kleines Beispiel:


public void PrintNamesToConsole(List<string> names)
{
    foreach(string name in names)
    {
        Console.WriteLine(name);
    }
}

Dieser Code verwendet List<T> als Argumenttyp, es besteht also eine Abhängigkeit darauf,
d.h. jeder Aufrufer muss hier eine List<T> übergeben, alles andere funktioniert nicht.
Beispielsweise kann hier kein Array übergeben werden, oder eine Collection.

Wenn dann innerhalb der Methode, die das Argument entgegennimmt, nicht einmal
auf spezifische Methoden / Eigenschaften des konkreten Types (List<T>) zugegriffen wird,
ist das noch ein grösser Nachteil, denn man erkauft sich eine Abhängigkeit, ohne das man sie eigentlich benötigt.

Hört sich komisch an?
Eigentlich ist es relativ leicht, wenn wir uns mal die verschiedenen Schnittstellen betrachten, worauf die Auflistungen in .NET aufbauen.

Der eigentliche Kern ist die Schnittstelle IEnumerable bzw. der typisierte Bruder IEnumerable<T>, wobei dort T den Typ der enthaltenen Elemente angibt.

IEnumerable:

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

IEnumerable<T>:

public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

Das Interface IEnumerator sieht dann so aus:
(Die generische Implementation IEnumerator<T>, hat zusätzlich eine Eigenschaft vom Typ T über die Eigenschaft Current).


public interface IEnumerator
{
    bool MoveNext();
    object Current { get; }
    void Reset();
}

Anhand der Beispiele ist zu sehen, das IEnumerable / IEnumerable<T> und die dazugehörige Schnittstelle für den
Enumerator beschreibt, das Elemente durchlaufen werden können. Nicht mehr und nicht weniger.

Das Beispiel von oben, könnte wie folgt umgeschrieben werden, um die kleinste Abhängigkeit zu haben und trotzdem
alle Anforderungen funktionieren, denn es muss ja nur eine Auflistung durchlaufen werden, nicht mehr und nicht weniger.

public void PrintNamesToConsole(IEnumerable<string> names)
{
    foreach(string name in names)
    {
        Console.WriteLine(name);
    }
}

Man beachte den geänderten Argumenttyp, der jetzt viel genereller ist.
Jetzt kann die Methode ein string[], eine List<T>, … entgegennehmen, einfach alles das die Schnittstelle IEnumerable<T> implementiert.

Wird eine Unterstützung in der Art von <Auflistung>.Count gefordert, kann die Schnittstelle ICollection<T> angegeben werden, die eine solche Eigenschaft nativ mitbringt.
Zusätzlich beschreibt das Interface (Erst ab der generischen Variante), das ein Element hinzugefügt, die Auflistung geleert, zurückgeben kann ob ein Element exisitert und Elemente entfernt werden können.

Durch LINQ to Objects können praktisch alle Operationen, wie bspw. Anzahl Elemente abfragen, sortieren, filtern, Zugriff über Index, damit und auf dem IEnumerable<T> Typen gemacht werden.
LINQ to Objects ist schnell, sehr schnell sogar. Wird jedoch die höchste Leistung benötigt und bspw. sehr häufig auf die .Count-Eigenschaft zugegriffen,
ist es besser, wenn eine native Unterstützung einer solchen Eigenschaft vorliegt.

LINQ to Objects arbeitet bei Count ungefähr so:

  • Versuche die Auflistung nach ICollection<T> zu casten.
  • Wenn das klappt, rufe die .Count-Eigenschaft ab und gib das Ergebnis zurück.
  • Wenn es nicht klappt, durchlaufe alle Einträge in der Auflistung, zähle die Anzahl zusammen und gib das Ergebnis zurück.

Das Interface IList<T> selber implementiert ICollection<T> – kann also alles auch – jedoch gibt es zusätzlich noch die Möglichkeit nativ per Index zu arbeiten. Also Elemente indexiert abfragen, ein Element an einem bestimmten Index löschen / einfügen.

In den meisten Fällen reicht es also, wenn IEnumerable<T> als Argumenttyp bzw. Rückgabetyp angegeben wird und in den anderen Fällen jeweils das Interface ICollection<T> / IList<T>, je nachdem was benötigt wird.

Es ist zu beachten, das IList<T> nicht alles beschreibt, was List<T> implementiert, bspw. gibt es dann keine Find- / FindAll-Methode, sowie auch keine native Implementierung für das Sortieren.
Mit LINQ to Objects tritt das allerdings in den Hintergrund und so kann man sich im Code von Abhängigkeiten zu den konkreten Auflistungstypen lösen.

Wieso soll man sich überhaupt lösen?

Umso genereller die Argument- oder Rückgabetypen sind, desto flexibler ist die API und es wird nicht mehr öffentlich gemacht, als schlussendlich verwendet wird.
Zusätzlich ist die Abhängigkeit zu einem konkreten Typ weg, was bedeutet das bspw. anstelle einer List<T> einfach irgend eine andere Implementierung von IEnumerable<T> empfangen / zurückgegeben werden kann.

So kann bspw. später eine Auflistung implementiert werden, die bei einem bestimmten Ereignis wie bspw. das Entfernen eines Eintrages, einen Event auslöst, ohne den Argumenttyp zu ändern.

Folgend noch ein paar sehr interessante Beiträge zum Thema:

Fehler verstecken leicht gemacht

Mit Try / Catch / Finally können in .NET Fehler behandelt werden.
Eigentlich eine gute Sache, allerdings sollte man aufpassen wo und wie man Fehler behandelt.

Vielerorts kann gelesen werden, dass das Fangen einer Allgemeinen Exception nicht gut sei, aber wieso ist das so?

Da ich es auch schon selber praktisch mehrmals erlebt habe, was das für schlimme Auswirkungen haben kann, ist es für mich nicht so schwer, diese Frage zu beantworten.

Ich möchte dies anhand eines kleinen, nachvollziehbaren Beispiel erläutern.

Gegeben ist folgender Code:


protected void Page_Load(object sender, EventArgs e)
{
    try
    {
        this.GridView1.DataSource = <DataSource>;
        this.GridView1.RowDataBound += GridView1_RowDataBound;
        CommandField deleteField = new CommandField
                   {
                     ShowDeleteButton = !this._recordsAreReadOnly,
                     DeleteText = “Löschen”,
                     DeleteImageUrl = "delete.png",
                     ButtonType = ButtonType.Image
                   };

         GridView1.Columns.Add(deleteField);
        // zusätzlichen Code…
        this.GridView.DataBind();
    }
    catch(Exception ex)
    {
        this.Logger.Log(ex);
    }
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if(e.Row.RowType == DataControlRowType.DataRow)
    {
        // zusätzlicher Code…
        ImageButton deleteButton = e.Row.FindControlRecursive<ImageButton>(c => c.CommandName == “Delete”);
        deleteButton.CssClass = “button_delete”;
        // zusätzlicher Code…
    }
}

Dieser Code, läuft - wie er jetzt da steht - ohne Probleme, solange die Daten nie als readonly gekennzeichnet werden.
Wird jetzt allerdings der Code erweitert, gibt es ein höchst merkwürdiges Verhalten, das ich mir zuerst überhaupt nicht erkären konnte.

Folgende Änderung:


ShowDeleteButton = !this._recordsAreReadOnly,

wird zu:


ShowDeleteButton = !this._recordsAreReadOnly && <Sicherheitsabfrage ob gelöscht werden darf>,

Der erste Teil der Bedingung liefert mit der Negation schlussendlich true und die Sicherheitsabfrage false, was ausgewertet dann einem false entspricht.
Somit werden die Löschen-Buttons nicht dargestellt. Gut. Eigentlich genau das was ich wollte.

Jedoch – und jetzt kommt der Haken – wird jetzt nur noch ein Datensatz im GridView angezeigt, anstelle von den zwei die in der Datenquelle vorhanden sind.

Im ersten Moment kam mir das ziemlich merkwürdig vor, da ich auch nirgendwo nochmals auf die Bedingung zugreifen und vor allem, weil auch kein Fehler geworfen wurde.

Kurz nachdem ich den Debugger angeworfen und kurz in den EventHandler “GridView1_RowDataBound” reingeschaut habe, kam es mir in den Sinn:

Böses Try / Catch, ein Fehler wurde versteckt, ohne das ich es gemerkt habe.

Was ist denn genau passiert?

Nun, da über die komplette Page_Load-Methode ein Try / Catch Konstrukt gespannt ist, das generell alle Fehler abfängt (Nicht behandelt, sondern eben “verschluckt”), bekomme ich den Fehler nicht zu Gesicht und der Code läuft in einem inkonsistenten Zustand weiter.

Der Eventhandler wird angemeldet und durch den GridView1.DataBind() Aufruf, läuft auf der Eventhandler selber im Scope von besagtem Try / Catch, sodass die NullReferenceException, die eigentlich geworfen werden sollte, verschluckt wird.

Das hat dann dazu geführt, dass das GridView “irgendwie” noch halb fertig gerendert wird und man nichts vom Fehler mitbekommt, sondern eben nur einen Datensatz halb fertig gerendert wird.

Ich hoffe das dieses Beispiel ein wenig Klarheit bringt und vor allem euch aufweckt, Exception Handling mit Bedacht einzusetzen und nicht an einem solch komischen Verhalten zu verzweifeln.

Zusatz / Fazit:
Wie man sehen kann, ist der Scope (Wirkungsbereich) von Try / Catch um die ganze Page_Load-Methode gelegt.
Dies kann Sinn machen, jedoch nicht in der Mehrzahl der Fälle, wie auch in diesem Fall.

Meiner Meinung nach, und so steht es auch in den meisten Büchern, sollten Fehler punktuell abgefangen werden, nur dort wo man ihn auch behandeln kann und der Scope sollte möglichst klein gehalten werden, damit das Problem auch schnell identifiziert ist.

Die unbehandelten Fehler kann man dann generell in ASP.NET bspw. in der Global.asax.cs in der Methode Application_Error() loggen.
Ich persönlich gehe sogar so vor, das ich zuerst ohne Fehlerbehandlung entwickle und diese erst später hinzufüge.
So gehen während der Entwicklung keine Fehler vergessen und das Programm befindet sich nie in einem inkonsistenten Zustand.

Solchen Code wie oben gezeigt ist - wie auch Gregor im Kommentar bemerkt hat - vielerorts zu finden, was ich tragisch finde.
Die Konsequenzen daraus müssen in keinem Fall so harmlos sein, wie in diesem Beispiel gezeigt. Man stelle sich nur mal ein Atomkraftwerk vor, das durch eine inkonsistente Software gesteuert wird.

Bearbeitung / Korrekturen:
13.11.09 - Fehlendes Komma in den Codesnippets hinzugefügt
13.11.09 - Zusatz / Fazit hinzugefügt

Eingetragen von Peter Bucher | 7 Kommentare

Professionals im Profil - Interview von Golo Roden mit mir

Golo Roden hat mit http://www.professionals-im-profil.net/ ein Projekt gestartet, wo er berufstätige Entwickler interviewt, unter anderem mit der Frage, wie man den Einstieg ins Berufsleben geschafft hat und vorallem woher man die Motivation nimmt, immer neue Dinge zu lernen.

Softwareentwicklung ist ein faszinierendes Thema – keine Frage. Doch wie gelingt der Einstieg? Wie und womit sollte man beginnen? Woher die Motivation und die Energie nehmen, auf Dauer beständig Neues zu lernen? Welche Voraussetzungen sollte man als Anfänger überhaupt erfüllen, um auf Dauer erfolgreich sein zu können?

All diese Fragen beschäftigen jene, die heute versuchen, einen vernünftigen Einstieg in die Softwareentwicklung zu finden.

Doch diese Fragen haben auch all jene beschäftigt, denen der Einstieg bereits gelungen ist und die sich inzwischen professionell – entweder beruflich oder in der Community – mit Softwareentwicklung beschäftigen.

Warum also nicht einfach fragen, wie es ihnen bei ihrem Einstieg ergangen ist? Welche Hürden sie zu überwindern hatten, welche Erfolgserlebnisse sie hatten, und woher sie ihre Motivation genommen haben?

Dies ist die Idee von .NET Professionals im Profil: Die Webseite enthält Interviews zu diesem Thema mit Personen, die im Bereich .NET professionell tätig sind und sich beruflich oder in der Community einen Namen gemacht haben.

Für mich ist es eine Ehre, sich als ersten den Fragen von Golo stellen zu dürfen und ich freue mich schon auf die folgenden Interviews.
Das Interview mit mir ist unter http://www.professionals-im-profil.net/Peter-Bucher.aspx zu finden.

Viel Spass!

Eingetragen von Peter Bucher | 0 Kommentare

Wieviel Sinn machen Unittests?

Am 13. Oktober 2008 haben Golo Roden und ich unter dem Titel Noch Fragen, Roden? Ja, Bucher! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen.
Außerdem nimmt diesen Monat auch Christian Wenz wieder an unserem Streitgespräch teil.

Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. November 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

Wieviel Sinn machen Unittests?

So wohl Golo wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Golos Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema:

Schon in einem früheren Streitgespräch “Die Forderung nach Softwarequalität” habe ich Unittests erwähnt.

Ich würde als direkte Antwort natürlich gleich sagen: Sehr viel Sinn!
Jedoch muss die Frage irgendwie auseinandergenommen werden, denn generell lässt sie sich nicht beantworten.

Wo macht Unittesting Sinn?

Grundsätzlich macht es überall Sinn, wo das Verfahren leicht anzuwenden ist, ohne irgendwelche Handstände zu machen.

Schwierige Testumgebungen

Gerade in der Webentwicklung bzw. überall wo eine Oberfläche vorhanden ist, wird es schwieriger Abläufe zu testen.

Handelsübliche ASP.NET (WebForms) Anwendungen die schon entwickelt sind, jedoch nachträglich getestet werden müssen, eigenen sich überhaupt nicht dazu, nachträglich mit Unittesting zu versorgt zu werden.
Das liegt daran dass die Zuständigkeiten (Concerns) physikalisch und auch logisch nicht strikt getrennt sind, sondern schlussendlich bei den meisten Anwendungen irgendwo in den Page-Eventhandlern liegt.

Zum “nachträglich” kommen wir dann später noch mal zurück.

Wenn eine ASP.NET Anwendung von Grund auf neu entwickelt wird, kann das MVP (Model View Presenter)-Pattern eingesetzt werden, damit Unittests überhaupt eingesetzt werden können.
Wiederum gibt es ASP.NET MVC, das – wie der Name schon sagt – auf das MVC (Model View Controller)-Pattern setzt, was die Testbarkeit um einiges vereinfacht.
Natürlich gibt es auch dort noch Hürden und auch eine ASP.NET MVC Anwendung kann so geschrieben werden, das sie kaum noch testbar ist.

Für solche schwer testbare Anwendungen sind Oberflächentests der bessere bzw. möglichere Weg und stellen auch einen zusätzlichen Weg dar, für Anwendungen die schon mit Unittests abgedeckt sind.

Optimale Testumgebungen

Am besten eigenen sich kleine Greenfield (Start von der grünen Wiese aus)-Projekte, die – wenn möglich – Bibliotheken sind, die dann später in die Oberfläche integriert werden, bzw. ihre Aufgabe aufgrund einer Aktion der Oberfläche erfüllen.

Ein super Beispiel dafür ist die Entwicklung eines Dependency Injection Containers. Da kann man sogar hergehen und komplett testgetrieben arbeiten, also zuerst den Test und dann der Produktivcode, weil keine äusseren Abhängigkeit oder Oberflächen mit von der Partie sind.
Schlussendlich kann dann so sichergestellt werden, dass der Code das tut, was er sollte, zumindest in den getesteten Szenarien.

Lizenznummern generieren, parsen, zählen, prüfen, auch das ist ein super Beispiel wo Unittesting sehr gut angewendet werden kann, wenn es richtig aufgezogen wird.
Ich würde sogar behaupten es wäre fast unmöglich ohne irgendwelche Tests (Und hier eigenen sich Unittests am besten), so eine Bibliothek aufzubauen und sicherzustellen, damit sie korrekt funktioniert.

Denn erstens kann so sichergestellt werden, dass sich das implementierte Verhalten auch so verhält, wie es der Test vorschreibt und zweitens können Seiteneffekte entdeckt, behoben und schlussendlich ausgeschlossen werden. Denn nach jedem zusätzlich geschriebenen Test, sollten alle Tests noch einmal durchlaufen, so können dann Seiteneffekte erkannt und behoben werden.

Wieviel Testabdeckung ist sinnvoll?

Vielerorts wird geschrieben und gesagt das 100% Testabdeckung das Ziel sein sollte. Ich sage, das es gut ist, seine Ziele hochzustecken. Jedoch sind eben die letzten paar Prozent fast nicht testbar, oder es macht keinen Sinn sie zu testen, entweder weil es viel zu aufwändig ist, oder der Code schon durch Integrationstests abgedeckt ist.

Nachträgliches Unittesting?

Eine Anwendung nachträglich mit Unittests abzudecken macht m.E. nicht sehr viel Sinn.
Es gibt zuviel Aufwand und die Anwendung bzw. dessen Abläufe und verstrickter Code soll bestimmen, wie / wo und was getestet werden soll / muss.
Ich habe das Gefühl, dass sowas sehr schwierig ist, im nachhinein reinzupflanzen, nicht nur wegen dem Aufwand, sondern auch weil man nicht wirklich weiss, was getestet werden soll und wann alles abgedeckt ist.

Anders sieht es bei einem Redesign einer Anwendung aus, dort kann man eher Unittests einbauen, ganz sicher beim neuen Code und dann ggf. noch die Integration mit dem bestehenden Code testen, der dann meistens dabei noch angepasst wird.

Hardcore-TDD?

“Hardcore-TDD”, also zuerst die Tests und erst danach den Produktivcode, oder eher locker mal den Code schreiben und am Schluss die Tests hinzufügen?

Ja, ich gebe es zu, das ist eine Streitfrage. Ehrlich gesagt verstehe ich aber nicht wieso :-).
Irgendwie habe ich das Gefühl das es Extreme gibt, um den Menschen überhaupt klar zu machen, das es so / oder dies und das besser ist, als das bisherige.
Mit dieser Vorgehensweise kann man die Leute zum Aufwachen bringen, sich das überhaupt mal anzusehen – auch bei Clean Code Developer / Clean Code schön zu sehen.

Wenn man vor den Kopf gestossen wird, ist das schon mal der erste Schritt. Der zweite Schritt ist dann, sich mit dem Extremen zu befassen und irgendwo seinen Stil einzuordnen. Ich finde es macht – abgesehen um Leute vor den Kopf zu stossen – überhaupt keinen Sinn, etwas ins Extreme zu treiben.

Immer zuerst den Test schreiben und erst dann den Produktivcode mag bei kleineren Projekten, oder eben solchen die sehr modular und für Tests optimiert aufgebaut sind, funktionieren.

Ich habe das selber auch schon probiert und es ist schon eine coole Erfahrung:

  1. Test schreiben
  2. Benötigte Klassen erstellen
  3. Kompilieren => kompiliert
  4. Test laufen lassen => schlägt fehl => rot
  5. Klassen ausimplementieren, nur das nötigste
  6. Test laufen lassen => läuft => grün

Es gäbe theoretisch noch einen Zwischenschritt, bei dem kompiliert wird, obwohl die Klassen noch nicht vorhanden sind, aber damit kann ich mich irgendwie nicht anfreunden.
Auf jeden Fall macht man sich damit Gedanken, wie man sein API benutzen möchte und modeliert dann die Klassen auch so aus,
zusätzlich wird im besten Fall nur das implementiert was die Tests erwarten, also bis sie grün sind.

So kann mit Leichtigkeit die Einhaltung von YAGNI beim Entwickeln eingehalten werden.

Meiner Erfahrung ist aber leider die, dass vielerorts eben schon Projekte bestehen, die nicht darauf optimiert sind, mit Unittests abgedeckt zu werden.
Sei das jetzt nachträglich oder für neue Features die dazukommen. Dort ist es echt schwierig und da können meistens nur sehr loose angedockte Zusatzbibliotheken getestet werden, also ein Greenfield-Projekt das dann in die bestehende Umgebung eingebunden wird.

Überall wo es möglich ist, nach TDD zu entwickeln, mache ich das jetzt auch – mehr oder weniger, aber nicht komplett im Extremen.

Eingetragen von Peter Bucher | 3 Kommentare
Abgelegt unter: , ,

Richtig testen, oder: Was ist schneller… Foreach, LAMBDA Expressions, oder LINQ?

Einleitung

Der schweizer Kollege Daniel Schädler hat einen Blogpost mit dem Titel “Was ist schneller… Foreach, LAMBDA Expressions, oder LINQ?” veröffentlicht.

Nur schnell eine Korrektur zum Titel, die LINQ-Syntax wird – wie hier schon gezeigt – schlussendlich in die Erweiterungsmethoden-Syntax kompiliert.
Ich habe den Titel so übernommen, damit klar ist, dass das eine Antwort auf seinen Post darstellt.

Daniel hat sich die Frage gestellt, was wohl schneller ist: Listen per foreach, über LINQ oder die Erweiterungsmethoden Syntax für LINQ filtern.

Nun, ich wusste natürlich schon vorher, dass die Resultate nur ganz wenig auseinander liegen dürfen, weil:

  1. Wird die LINQ-Syntax in den Erweiterungsmethoden-Syntax übersetzt (Nahezu gleich).
  2. Arbeitet LINQ intern auch mit den Iteratoren, wie sie in foreach genutzt werden. Siehe Enumerable-Klasse im Reflector.

Abgesehen davon nutze ich diese Antwort in Form eines Blogposts einfach mal dazu, wie ich Geschwindigkeiten teste, auch wenn es in diesem Fall für mich theoretisch klar war, das alle in etwa gleich schnell sind.
Es braucht für einen Geschwindigkeitstest nicht unbedingt eine grafische Anwendung, auch wenn das natürlich nicht schlecht ist. Ich habe mir den Aufwand nicht gemacht und mich auf das Wesentliche konzentriert: Das Testen.

Verfälschte Tests und wie sie verhindert werden können

Der Test von Daniel liefert leider das falsche Resultat, sogar ein sehr verfälschtes.
Das liegt daran, das die Ergebnisse von LINQ bzw. den Erweiterungsmethoden als IEnumerable<T> zurückgegeben werden und diese zeitverzögert ausgeführt werden (deferred Execution).

Das heisst der ganze Code der die IEnumerable<T> Instanz liefert, wird erst ausgeführt, wenn das Ergebnis tatsächlich durchlaufen wird.
Dies kann bspw. mit <Menge>.Count(), <Menge>.ToList(), … angestossen werden.

Erst dann, und wirklich erst dann wird der Code überhaupt ausgeführt und braucht dann eben auch länger.

Auch wenn dies geschehen ist, bleibt das Ergebnis von Daniel noch verfälscht, denn eine Testiteration kann durch mehrere Faktoren verfälscht werden.
Sei das eine einmalige Kompilation einer Abfrage zur Laufzeit oder durch diversen Hintergrundprozessen die genau in dem Moment mehr Leistung benötigen als beim vorherigen Testkandidaten.

Es heisst also: Mehrere Iterationen einer Operation die getestet werden will, ausführen.

Darüber hinaus ist es noch so, dass das Gesamtergebnis auch noch bei mehreren Iterationen der zu testenden Operation verfälscht sein kann, weil eben die erste ausgeführte Operation verfälscht ist.

Um da einen Mittelwert zu bekommen, macht man über die ganzen Testläufe nochmals mehrere Testläufe.
Das hört sich jetzt womöglich ein bisschen verwirrend an, jedoch meine ich einfach gesagt nur folgendes:

  • Eine Operation: Einträge aus einer Menge filtern
  • Mehrere Iterationen einer Operation: Die Operationen mehrmals ausführen
  • Das ganze für alle Testkandidaten mehrmals ausführen

Somit kann man sehr sicher sein, dass die Ergebnisse der verschiedenen Kandidaten realistisch miteinander vergleichbar sind, nicht aber dass die Werte 1:1 dem entsprechen, wie sie dann auch in der Produktivumgebung auftreten, denn dort kommen wieder andere Faktoren dazu.

Nur das keine Missverständisse auftreten: Natürlich ist dann ein solcher Test auch für die Praxis aussagekräftig, nur wird er nicht 100% gleich ausfallen, wenn man die Zeit stoppt.

Als Testhilfe würde ich nicht DateTime.Now, etc.. benutzen, da dies zu ungenau ist. Das meines Wissens genauste Instrument das ohne P/Invoke-Aufrufe in unmanaged Code verfügbar ist, heisst Stopwatch und ist im System.Diagnostics-Namespace zu finden.

Mittels P/Invoke Aufrufen lässt sich eine noch genauere Messung vornehmen, jedoch ist das dann vorallem für Echtzeitanwendungen sinnvoll. Den Einsatz sieht man in einem myCSharp-Post für einen Framecounters unter XNA.

Mittels der Eigenschaft <Stopwatch>.ElapsedMilliseconds lassen sich die Millisekunden auslesen, die seit dem Start- und Stopaufruf vergangen sind, das reicht uns für den Test und ist auch aussagekräftig und vorstellbar, was bei den von Daniel genutzten Ticks m.E. nicht der Fall ist.

Für die Tests nutze ich eine Methode namens SpeedTest die einen Action-Delegate entgegennimmt den sie n-Mal ausführt.
So kann das Testen zentralisiert werden und ist mit sehr kleinem Aufwand möglich den Test selber zu erweitern, sowie neue Kandidaten hinzuzufügen.

Wenn der Test ausgeführt wird, habe ich Abweichungen von 1 bis 4 Millisekunden und das bei sehr vielen Durchläufen. Diese Abweichungen sind für mich also – wie am Anfang vermutet – irrelevant.

Folgend den Code der ich für meinen Test verwendet habe:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace SpeedTest
{
    public class Program
    {
        static void Main(string[] args)
        {
            int randomDataCount = 1000;
            var persons = GetPersons(randomDataCount);

            int iterations = 1000;
            int runs = 10;

            for (int runNumber = 1; runNumber <= runs; runNumber++)
            {
                Console.WriteLine("Run {0} ---------------", runNumber);

                SpeedTest("LINQ", iterations,
                          () =>
                          {
                              var result = (from person in persons
                                            where person.FirstName.Equals("Peter") && person.Age <= 25
                                            select person).ToList();
                          });

                SpeedTest("LINQ Extension Syntax", iterations,
                          () =>
                          {
                              var result = persons.Where(p => p.FirstName.Equals("Peter") && p.Age <= 25).ToList();
                          });

                SpeedTest("Manual ForEach", iterations,
                          () =>
                          {
                              List<Person> result = new List<Person>();

                              foreach (Person person in persons)
                              {
                                  if (person.FirstName.Equals("Peter") && person.Age <= 25)
                                  {
                                      result.Add(person);
                                  }
                              }
                          });

                Console.WriteLine("End run --------");
                Console.WriteLine(String.Empty);
            }

            Console.Read();
        }

        private static void SpeedTest(string description, int iterations, Action speedTestAction)
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();

            for (int i = 0; i < iterations; i++)
            {
                speedTestAction();
            }

            watch.Stop();

            Console.WriteLine("{0}: {1}ms",
                              description,
                              watch.ElapsedMilliseconds);

            Console.WriteLine(String.Empty);
        }

        private static IEnumerable<Person> GetPersons(int randomDataCount)
        {
            Random random = new Random();
            string[] surnames = new[] { "Peter", "Daniel", "Johannes", "Stefanie", "Hans", "Klaus", "Benjamin" };
            string[] lastnames = new[] { "Bucher", "Hurzeler", "Kübel", "Honegger", "Bock", "Wurst", "Grube" };

            int dataLength = surnames.Length;

            for (int i = 0; i < randomDataCount; i++)
            {
                yield return new Person
                                 {
                                     FirstName = surnames[random.Next(0, dataLength)],
                                     LastName = lastnames[random.Next(0, dataLength)],
                                     Age = random.Next(0, 100)
                                 };
            }
        }
    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }
}

Eingetragen von Peter Bucher | 5 Kommentare

Generierung der designer.cs / vb Datei forcieren oder “Der Name ControlXYZ ist im aktuellen Kontext nicht vorhanden

Wenn eine ASPX- / ASCX-Datei ausserhalb vom Visual Studio Editor geändert wird, bekommt das der Designer nicht mit.
Das Updaten der <Dateiname>.<Erweiterung>.designer.cs geschieht nicht sehr häufig und nur bei bestimmten Fällen.

So kann es gut sehr gut sein, dass folgende Fehlermeldung beim Kompilieren erscheint:

The name ‘ControlXYZ’ does not exists in the current context

bzw.

Der Name ControlXYZ ist im aktuellen Kontext nicht vorhanden

Um die Neugenerierung der Designer-Datei zu erzwingen, kann die ASPX- / ASCX- Datei im Designer geöffnet werden, oder eine Eigenschaft hinzugefügt / geändert werden.

Wenn das nichts nützt (Danke an Stefan):

Leider funktioniert das aber lange nicht immer. Ich hab das gerade bei größeren Projekten (meist dann, wenn man in VS ein Control kopiert und umbenennt (inkl. Klassenname natürlich) öfter mal. Schon ein paar mal half schlußendlich nur das Löschen der Datei in VS und das erneute Erstellen. Reines Drag&Drop in das VS Projekt hinein half da auch nciht.

Mehr Details zu diesem Verhalten gibt es in folgendem Posting:

Eingetragen von Peter Bucher | 2 Kommentare

LINQ: Any, anyone? Range oder Repeat?

Mit LINQ sind unzählige Erweiterungsmethoden für IEnumerable<T> hinzugekommen, die auch ausserhalb von LINQ Abfragen sehr nützlich sein können.

Damit ich mir das merke und ihr evt. noch was neues kennenlernt, möchte ich zwei kurz vorstellen:

Enumerable.Any()

Kommt euch Code wie der folgende bekannt vor?

if(addresses.Count > 0)
{
    // …
}

oder

if(addresses.Count == 0)
{
    // …
}

Das kann jetzt folgendermassen umgeschrieben werden:

if(addresses.Any())
{
    // …
}

und

if(!addresses.Any())
{
    // …
}

Die Implementation der Any()-Methode holt sich den Enumerator der Auflistung und versucht den ersten Eintrag zu holen, wenn das klappt gibt sie true zurück, ansonsten false.

Wenn Any() true zurückliefert, heisst das also, es ist mindestens ein Element vorhanden.

PS: Darüber hinaus gibt es auch noch eine zweite Überladung, der man Funktion einspeisen kann (Anonyme Methode, Lambda Ausdruck, …). Diese bestimmt dann, ob es mindestens ein Element hat, bei dem die Funktion true zurückliefert.
Die Funktion nimmt ein Element vom Typ TSource entgegen und gibt einen bool zurück.

Enumerable.Range() und Enumerable.Repeat()

Schon mal Testdaten benötigt, oder eine Liste von Zahlen die dann durcheinandergewürfelt werden?
Das schreibt man im einfachsten Fall dann in etwa so:

List<int> numbers = new List<int>();
for(int i=1; i <= 100; i++)
{
    numbers.Add(i);
}
// …

Mit Enumerable.Range() geht das viel einfacher:



var numbers = Enumerable.Range(1, 100);

// …

Mit LINQ lässt sich ganz einfach eine gemischte Liste von Zahlen erstellen, zwei Zeilen braucht es dazu:

Random random = new Random();
var numbers = Enumerable.Range(1, 100).OrderBy<int, int>(random.Next);

Hier noch ein kleiner Hinweis: Um eine gleichmässige Verteilung einer solchen Liste zu erhalten, sollte ein Algorithmus wie bspw. hier benutzt werden.

An Enumerable.Repeat() hingegen kann im ersten Parameter eine Instanz übergeben werden, oder auch ein einfacher Wertetyp wie bspw. eine Zahl und eine Anzahl, wie häufig dieser Wert wiederholt werden soll.
Schlussendlich bekommt man eine Auflistung zurück, das wars.

Eingetragen von Peter Bucher | 0 Kommentare
Abgelegt unter: , , , , , ,

Alles var – oder nicht?

Am 13. Oktober 2008 haben Golo Roden und ich unter dem Titel Noch Fragen, Roden? Ja, Bucher! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen. Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. September 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

Alles var – oder nicht?

So wohl Golo wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Golos Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema:

Nein, werter Leser, das ist kein Rechtschreibefehler, das ist eine wirklich vwa(h)re Geschichte.
Scherz beiseite, los gehts… ;-)

Einleitung

Mit C# 3.0 kam ein neues Schlüsselwort names var hinzu, nur was hat es damit auf sich?

Es handelt sich dabei weder um ein spät gebundenen noch um einen Variant Typ, wie man ihn bspw. von Scriptsprachen her kennt, sondern um ein Feature das erst die Nutzung von anonymen Typen möglich macht.

Einfach gesagt heisst das, dass der Compiler den Typ auf der linken Seite vom Ausdruck auf der rechten Seite ableitet.
Also sind die Variablen immer stark typisiert und zwar zur Kompilezeit, nicht erst zur Laufzeit.

Was ist der Sinn des ganzen, bzw. wieso wurde dieses Feature integriert?

Im Zuge der Entwicklung von LINQ wurden die anonymen Typen eingefügt um eine Projektion der Daten auf irgendeine Objektstruktur zu ermöglichen, ohne dazu immer wieder neue Datenhaltungsklassen erstellen zu müssen.

Damit ist dann bspw. sowas möglich:

List<string> data = new List<string>
{
  "Patrick:24",
  "Stefan:16",
  "Jörg:22"
};

var persons = from dataEntry in data
              let splitted = dataEntry.Split(new[] { ':' })
              select new
              {
                Name = splitted[0],
                Age = int.Parse(splitted[1])
              };

foreach (var person in persons)
{
  Console.WriteLine("Name: {0}, Age: {1}", person.Name, person.Age);
}

Dabei ist der Typ von persons IEnumerable<T> wobei T in Visual Studio als "a” für Anonymous gekennzeichnet wird.
Und dementsprechend ist jeder Eintrag in dieser durchlaufbaren Menge ein anonymer Typ, der im Hintergrund vom Kompiler generiert und bereitgestellt wird.

Die Eigenschaft “Name” ist – wer hätte es gedacht – vom Typ string und “Age” vom Datentyp int.

Wo kann var überall eingesetzt werden?

Das Schlüsselwort kann nur für lokale Variablen genutzt werden, so sind automatisch auch anonyme Typen nur in diesem Bereich nutzbar. D.h. es können auch keine anonymen Typen über Methodengrenzen hinaus übergeben werden.

Wo macht es Sinn var einzusetzen und wann ist ein var mehr zuviel?

Das ist eine spannende Frage und eigentlich der Kernpunkt dieses Streitgespräches.
Hier einfach mal ein paar Beispiele:

private void SetProperties()
{
  var collectionMapping = this.CollectionMapping;

  if(collectionMapping.Count() > 0)
  {
    collectionMapping.Clear();
  }
}

private void SetProperties()
{
  ICollectionMapping collectionMapping = this.CollectionMapping;

  if(collectionMapping.Count() > 0)
  {
    collectionMapping.Clear();
  }
}

public static void RegisterType()
{
    var objectToXElement = BuildObjectToXElementFunc<TEntity>();
    var xElementToObject = BuildXElementToObjectFunc<TEntity>();

    RegisterType(objectToXElement, xElementToObject);
}

public static void RegisterType()
{
    Func<TEntity, XElement> objectToXElement = BuildObjectToXElementFunc<TEntity>();
    Func<XElement, TEntity> xElementToObject = BuildXElementToObjectFunc<TEntity>();

    RegisterType(objectToXElement, xElementToObject);
}

oder sowas:

var wtf = GetPattern();

vs

Pattern pattern = GetPattern();

In der ersten Methode wird var benutzt und in der folgenden dann nicht mehr.
Ich habe die Beispiele extra so gewählt, denn wenn in diesen Methoden var benutzt wird, sieht man auf den ersten Blick (ohne die Maus zu benutzen, oder einen verrenkten Shortcut) nicht, um was für einen Typen es sich hier handelt.

Und das ist natürlich ein sehr wichtiger Aspekt.
Denn was nützt mir das weniger schreiben und weniger Code, wenn ich beim lesen – was übrigens vom Zeitaufwand deutlich mehr ist als das Schreiben – nicht mehr auf den ersten Blick erkennen kann, was für Typen das sind.

Man sollte das Schlüsselwort im Regelfall wirklich nur einsetzen um die anonymen Typen benutzen zu können.

Ausnahme wenn es sich um eine lange Typdefinition handelt _und_ initialisiert wird

Ich für meinen Teil halte es so, das ich es eben dann benutze und zusätzlich auch noch in Fällen bei denen die Initialisierung (nicht Zuweisung) rechts daneben steht.

Und das auch nur wenn es sich um eine lange und komplexere Typbezeichnung handelt, das sind dann meistens solche mit generischem Typparameter, Beispiel:

public void Foo()
{
    Dictionary<string, Person> persons = new Dictionary<string, Person> {…}
}

public void Foo()
{
    var persons = new Dictionary<string, Person> {…}
}

Durch den sprechenden Namen und dadurch das die Initialisierung der Variable und so auch die implizite Zuweisung des Types auf der rechten ist, kann das auch gut gelesen werden und ist praktikabel finde ich.

Diese Anwendung hilft auch Redundanzen zu vermeiden. Wenn man bspw. die Initialisierung änderet ist der Typ auch automatisch angepasst.
Das ist ein netter Nebeneffekt, kann aber auch böse enden, wenn man sich dessen nicht bewusst ist, das Interface gleich ist, aber sich die Methoden / Eigenschaften die später aufgerufen werden, anders verhalten.

Ausnahme wenn es um LINQ Abfragen handelt

Bei LINQ Abfragen benötigt es kein var, wenn keine anonymen Typen genutzt werden.
Allerdings halte ich es auch bei LINQ-Abfragen so, dass ich meistens var benutze.
Denn mit guten Namen und im kleinen Kontext gehalten ist klar und verständlich was rüber kommt. Grösster Vorteil hierbei ist auch die automatische Anpassung des Types.

Dies kommt in diesem Fall sehr zum Vorschein, denn durch Projektion kann sich der Rückgabetyp schnell ändern, obwohl die Eigenschaften bspw. gleich bleiben.

public void Foo()
{
    IEnumerable<Person> persons = from person in list.Persons where person.Age > 20 select person;
}

public void Foo()
{
    var persons = from person in list.Persons where person.Age > 20 select person;
}

Das wars auch schon mit den Ausnahmen. Alles andere ist in meinen Augen nicht mehr lesbar und auch nicht gerechtfertigt.
Ich finde es schon ein wenig beängstigend, wenn ich im Web (Auch von Microsoft) Beispiele sehen, die Zahlen und Zeichenfolgen in 20, 30 Zeilen nur mit var arbeiten.
Wenn die Variablennamen dann noch schlecht gewählt, gute Nacht.

Was denkt ihr über die Sache und vorallem über meine genannten Ausnahmen?

Eingetragen von Peter Bucher | 4 Kommentare
Abgelegt unter: , , , ,

ASP.NET Sicherheit - Directory Traversal verhindern

Im Wikipedia Artikel ist schon gut und ausführlich beschrieben, was unter “Directory Traversal” zu verstehen ist, Zitat:

Unter Directory Traversal versteht man eine Sicherheitslücke in Web-Programmen wie z. B. einem Webserver oder einer Webanwendung, bei der durch Manipulation von Pfadangaben auf beliebige Dateien und Verzeichnisse zugegriffen werden kann, die dafür eigentlich nicht vorgesehen waren. Diese kann so ausgenutzt werden, dass sensible Daten wie Passwörter preisgegeben werden.

Was kann der Entwickler dagegen tun?
Im besten Fall eine Guid / Id benutzen, um Dateien anzusprechen, jedoch ist das eine Mehrarbeit und manchmal nicht gewollt.

Hier noch kurz ein Fall, der auf Directory Traversal anfällig ist:

string xmlBasePath = Server.MapPath(“~/App_Data/XmlData/”);
string xmlFilePath = Path.Combine(xmlBasePath, Request.QueryString[“filename”]);
XmlDocument document = new XmlDocument();
document.Load(xmlFilePath);

In diesem Fall sieht der Pfad am Schluss so aus: “C:\Pfad\Zum\Web\App_Data\..\bild.xml”
Wie man sieht, ist das Zurückgehen per “../” noch nicht aufgelöst, dies macht entweder Server.MapPath() oder bspw. auch andere Parteien wie bspw. XmlDocument innerhalb der Load()-Methode.

Server.MapPath() wurde im oberen Beispiel aber nur für die Auflösung des Basispfades genutzt, darum hat sie keinen Einfluss.
Beim nächsten Beispiel ist wieder die selbe Situation, nur das hier Server.MapPath() den Pfad auflöst:

string xmlBasePath = “~/App_Data/XmlData/”;
string filePath = Server.MapPath(Path.Combine(xmlBasePath, Request.QueryString[“filename”]));
// weiterer Code…..

Der Wert vom Benutzer – also Request.QueryString[“filename”] – kann also eine “../” Zeichenfolge vor dem Dateinamen selber enthalten und evt. sogar andere Pfadangaben.

Wenn der Benutzer richtig böse ist, kann er so versuchen an einen anderen Ort innerhalb des Webs oder – bei schlechten Sicherheitseinstellungen – sogar des Webservers zu gelangen.

Die simpelste Abwehrmethode ist das Ersetzen von allen möglichen Vorkommnissen von “../”.
Jedoch ist das mühsam und immer noch nicht 100% sicher, denn über eine Eingabe von “/secureimages/image.jpg” kommt der Benutzer immer noch an eine Datei in einem geschützten Unterordner(App_Data ist grundsätzlich geschützt) ran.

Das denkbar schlimmste Horroszenario wäre die Übernahme einer Datenbank oder oder sogar des Servers, was so durchaus machbar wäre.

Die einfachste und zugleich auf effektivste Abwehrmassnahme ist die Benutzung von Path.GetFileName(<Wert vom Benutzer>);

Im oben stehenden Wikipedia Artikel ist noch beschrieben, dass auch Url kodierte Zeichen genutzt werden können und dann die erste hier vorgestellte Lösung unwirksam wird.
Dies muss bei ASP.NET nicht beachtet werden, da bei Request.QueryString[] immer “../” ankommt, die Methode dekodiert also die Werte in der Url schon.

Ein angriffssicheres Beispiel sieht dann so aus:

string xmlBasePath = Server.MapPath(“~/App_Data/XmlData/”);
string xmlFileName = Path.GetFileName(Request.QueryString[“filename”]);
string xmlFilePath = Path.Combine(xmlBasePath, xmlFileName);

XmlDocument document = new XmlDocument();
document.Load(xmlFilePath);

C# oder VB: Welche Sprache soll ich lernen?

Am 13. Oktober 2008 haben Golo Roden und ich unter dem Titel Noch Fragen, Roden? Ja, Bucher! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen. Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. Juli 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

C# oder VB: Welche Sprache soll ich lernen?

So wohl Golo wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Außerdem nimmt diesen Monat auch Christian Wenz an unserem Streitgespräch teil.

Golos und Christians Kommentare finden sich zeitgleich in den entsprechenden Blogs, folgend nun mein Kommentar zu diesem Thema:

Also gleich vorneweg, es geht hier nicht um eine Glaubensfrage und auch nicht um “C# vs VB.NET” das bei einer Google Suche knapp 7 Millionen Treffer ergibt und von denen die meisten in einem Glaubenskrieg ausarten.

Ich werde zwar auch C# vs VB.NET ansprechen, jedoch neutral und nüchtern verglichen sowie auf den Titel dieses Streitgespräches bezogen.

Zuerst meine Erfahrungen zu diesem Thema:

Ich habe den Einstieg in die Programmierung mit VBScript (Classic ASP) und ein wenig Javascript gefunden.
Es gab zu dieser Zeit auch die Möglichkeit JScript zu benutzen, um Classic ASP zu entwickeln, jedoch gab es viel weniger Beispielcode dazu im Netz und mir kam die Syntax für einen Anfänger nicht wirklich natürlich und intuitiv vor.

Später machte ich dann neben Visual Basic 6 auch Versuche in PHP (Ja, Jevoha Stefan ;-)).
Desto mehr ich Erfahrungen sammelte und auch mit Sprachen die C ähnliche Syntax aufwiesen, herumexperimentierte, desto mehr wandte sich meine Einstellung das diese Art von Syntax doch nicht so unnatürlich und unintuitiv wirkt.

Im gleichen Zug fand ich dann auch, das die kompaktere Art der Syntax den Code eleganter machte und auch auf das wesentliche reduzierte.

Das waren meine Gründe das ich bei meinem Start in die .NET Welt gleich mit C# losgelegt habe.
Am Anfang war das natürlich eine ziemliche Umstellung und vorallem der Switch, wieder mal VBScript zu schreiben und zurück auf C# komisch.

Bei meinem ersten Arbeitsgeber musste ich dann erzwungenermassen VB.NET entwickeln, weil die bestehende Software darauf basierte.
Am Anfang habe ich mir natürlich ein wenig schwer getan, jedoch sitzte die andere Syntax innerhalb von zwei Wochen schon sehr gut. Das ist natürlich auch meinen Erfahrungen mit VBScript zu verdanken, sodass die Elemente und Konventionen doch nicht so fremd waren.

Mit der Zeit fand ich richtig Gefallen an VB.NET. Wichtig und zugleich interessant war für mich zu dieser Zeit (Da ich immer noch C# präferierte), dass ich privat immer mit C# gearbeitet habe.

Schlussendlich bin ich froh das ich "erzwungenermassen” mit VB.NET arbeiten musste und dabei auch C# nicht aus den Augen verloren habe. Der Horizont wird erweitert und wenn irgendwo mal was in VB.NET steht, versteht man auch was damit gemeint ist.

Auch wegen meiner Erfahrungen denke ich, das es für komplette Anfänger leichter ist mit VB.NET einzusteigen, da die Sprache am Anfang natürlicher und intuitiver erscheint. Nicht ohne Grund, denn der Ursprung von VB.NET wurde genau für diesen Zweck entwickelt, eine einsteigerfreundliche Sprache zu sein.

Nun, das war jetzt meine Situation und meine Einschätzung. Was kann den generell dazu gesagt werden?

Wenn jemand schon Erfahrungen in einer anderen Sprache hat, die auf dem BASIC-Dialekt basiert, wird er es beim Umstieg mit VB.NET sicher bequemer haben.

Schlussendlich ist es (fast) eine reine Geschmacksfrage, was jemand bevorzugt oder auch was ihm besser liegt.

Da VB.NET und C# bis auf das Aussehen der Syntax im Hintergrund genau dasselbe Paket haben und im Moment bis auf ein paar Featureungleichheiten das gleiche leisten, kommt es in den allermeisten Fällen auch nicht darauf an welches Feature jetzt von der zu lernenden Sprache unterstützt wird.

Folgend finden sich noch zwei Verleichsauflistungen von C# und VB.NET:

Ich bin jetzt mal ganz böse und möchte behaupten das es gar nicht so schlecht ist, wenn zuerst – also in der Anfangszeit - mit einer untypisierten und nicht objektorientierten Sprache geübt wird.
So kann man sich ohne grosse Hindernisse und Dinge die Zeit und Wissen benötigen um sie zu verstehen, mit den grundlegenden Dingen der Programmierung beschäftigen, strukturiert. Wenn dies möglichst modular gelernt wird, ist dann auch der Umstieg auf eine objektorientierte Sprache – die ja auch die Konzepte der Strukturen beinhaltet – einfacher und nicht so überladen.

Bei vielen Integrationen wie die von Tools in Visual Studio (bspw. ReSharper) oder der Unterstützung von VB.NET auf Mono hinkt VB.NET hinterher. Dasselbe gilt auch für die Unterstützung der Sprache in anderen IDEs.
Auch ist es so, das die meisten grossen und bekannten Open Source Projekte meistens in C# geschrieben sind.
Und wissentlich ist die Einsicht in fremden Quellcode für das Lernen unabginglich und sehr zu empfehlen.

An verschiedenen Quellen habe ich gelesen, das C# Entwickler auf dem Arbeitsmarkt besser bezahlt werden und das mehr Stellen vorhanden sind, wo C# gefordert wird.
Wieviel da wirklich dran ist, kann ich nur gefühlsmässig einschätzen und würde da zustimmen. Es gibt sicherlich irgendwo noch Statistiken dazu.

C# hat auch den Vorteil, das der Umstieg zu anderen Sprachen die C ähnliche Syntax benutzt, wie bspw. Java, leichter fällt.

Wie sieht es nun mit der Weiterentwicklung und dem Support für VB.NET und C# in der Zukunft aus?

Microsoft will in nächster Zukunft eine Featuregleichheit von C# und VB.NET erreichen, sodass sich die Sprachen featuremässig ebenwürdig sind. Das finde ich eine gute Entwicklung und stärkt die Position von VB.NET als Nummer zwei der Sprachen für das .NET Framework.

Fazit:

Um direkt auf die Titelfrage zu antworten, würde ich sagen: Lernt beide Sprachen, nein, lernt so viele Sprachen wie möglich. Allerdings fokusiert euch auf eine, damit ihr dort sehr gut werdet / bleibt.

Wenn es darum geht mit welcher Frage man anfangen soll, bleibt es schlussendlich dem Geschmack überlassen.
Im jetzigen Stand haben beide Kontrahenten jeweils Features die der andere nicht hat, jedoch sind diese in den meisten Fällen zu vernachlässigen. Das heisst, alle wichtigen Merkmale und Funktionen ist bei beiden vorhanden.
Und das reicht für den Einstieg mehr als aus.

Wichtiger finde ich, das einem späteren Umstieg eigentlicht nichts im Wege steht und das sich die Geschmäcker mit der Zeit auch ändern können.

Eingetragen von Peter Bucher | 14 Kommentare
Abgelegt unter: , , ,

.NET Stammtisch Konstanz-Kreuzlingen – Die nächsten fünf Treffen im Überblick

6 Treffen liegen schon hinter uns und wegen dem .NET Open Space Süd 2009 (Berichte und Fotos dazu) Treffen wurde das letzte Treffen in einem kleinen Rahmen gehalten.

Die Entwicklung der grenzübergreifenden Usergroup geht schneller voran als Jürgen und ich gedacht hatten. Das ist natürlich erfreulich!

Dank INETA (International .NET Association) Deutschland haben wir die Möglichkeit bekommen, bekannte Sprecher zu sehr interessanten Themen zu gewinnen.

Die nächsten fünf Treffen stehen fest, unten findet ihr eine Zusammenfassung aller kommenden Treffen.

Wir halten es so, dass es bei jedem Treffen einen Vortrag gibt, anschliessend jedoch genügend Zeit bleibt um bei einem Bierchen darüber zu diskutieren, damit die Teilnehmer auch aktiv werden und die Sprechern Feedback empfangen und zusätzliche Fragen beantworten können.

Wenn ihr Vorschläge für Themen oder eine andere Art für ein Treffen habt, könnt ihr uns jederzeit mit den Kontaktangaben auf der Homepage erreichen.

Die nächsten Treffen finden alle bei der Fachhochschule in Konstanz statt und unter jedem Link für ein Treffen, findet ihr den Anfahrtsplan und ggf. eine andere Ortsangabe, wenn wir uns zur Abwechslung mal zu einem Bierchen treffen wollen.

Das sechste .NET-Stammtisch Treffen findet mit Thomas Schissler und folgendem Thema statt:

Überblick über VSTS 2010.
Mit Visual Studio Team System 2010 bring Microsoft eine neue Genereation siner Entwicklungsplattform auf den Markt.
Neben einer großen Anzahl von Verbesserungen bring VSTS 2010 und das Backendsystem TFS 2010 auch völlig neue Funktionen und Möglichkeiten mit. Der Vortrag beleuchtet die verschiedenen Bereiche und stellt jeweils die wichtigsten Neuerungen vor.

Diese werden mit verschiedenen Praxisbeispielen plastisch erläutert.
Vorgetragen wird das Thema von Thomas Schissler.
Thomas ist Leiter die Software-Entwicklung bei der Artiso AG in Ulm, Gründungsmitglied und Team-Leader der .NET Developer-Group Ulm und MVP für den Bereich Team System. Desweiteren ist Thomas viel als Sprecher auf großen Konferenzen und in User Group unterwegs. Das Weblog von Thomas, mit vielen Beiträgen zum Thema VSTS, ist unter folgender URL zu finden: http://www.artiso.com/problog/

 

Das siebte .NET-Stammtisch Treffen findet mit Golo Roden zu folgendem Thema statt:

Dependency Hell? Nein, danke!.
Code verfügt nicht erst seit Objekten und Komponenten, die aufeinander aufbauen, über innere Abhängigkeiten.
Doch welche Abhängigkeiten sind gut, welche schlecht? Golo Roden zeigt in dieser Session, welche gängigen Arten von Abhängigkeiten es in der Dependency Hell gibt und erläutert grundlegene theoretische Begriffe und Konzepte wie beispielsweise Kohäsion und Kopplung, implizite und explizite Abhängigkeit und Separation of Concerns.
Die Vorstellung passender Gegenmaßnahmen und ihrer Anwendung – vom einfachen Refactoring auf Quellcode- bis hin zum Einsatz eines Microkernels auf Architekturebene – runden die Session mit kleinen Praxisbeispielen schließlich ab.

Golo Roden lebt seit dem Jahr 2005 in Freiburg im Breisgau und ist Autor, Sprecher und Trainer für .NET und verwandte Technologien. Er beschäftigt sich mit Software Engineering, Applikationsarchitektur, Infrastruktur und Webtechnologien im Allgemeinen. Golo ist verheiratet und Vater einer Tochter, hat einen Collie wie auch eine Schwäche für Eisbären und beschäftigt sich in seiner Freizeit mit elektronischer Musik, digitaler Fotografie und Kochen.

 

Das achte .NET-Stammtisch Treffen findet mit Jürgen Gutsch und folgendem Thema statt:

ASP.NET Best Practices.
Jürgen Gutsch beschreibt in einem Vortrag, wie man optimal mit ASP.NET Anwendungen schreibt, ohne im Durcheinander von PostBacks und ViewStates nicht mehr weiter zu kommen.
Sowie PostBacks sparsam und gezielt einsetzt werden und wie man den ViewState klein hält und somit auch die Performance optimiert hält.

 

Das neunte .NET-Stammtisch Treffen findet mit Gregor Biswanger und folgendem Thema statt:

TDD / BDD
Ein neues Software Projekt beginnt. Das Design der Architektur steht auch schon. Nun können die hoch motivierten Entwickler starten, ihre Fachbereiche mit Code zu füllen. Doch kommt es schon nach kurzer Zeit zu großen Problemen! Die Anwendung macht an unterschiedlichen Stellen alles andere als das, was gefordert wurde. Keiner kann am Ende sagen woran das liegt, jeder versucht seine Position zu verteidigen. Ist das Projekt nun zum Scheitern verurteilt? Wird nun der Fertigstellungstermin noch weiter nach hinten geschoben, der sowieso schon an der Schmerzgrenze lag?! Nein, durch Test Driven Development kann dieses Problem verringert werden. Damit ist nicht die Fehleranfälligkeit gemeint, sondern das rechtzeitige Erkennen, an welcher Stelle es gerade nicht funktioniert wie es soll.

Einführung in Test Driven Development
Was ist überhaupt TDD? Wie kann ich TDD für neue oder bestehende Projekte richtig nutzen? Welche Arten von Testmöglichkeiten für heutige Softwareprojekte geboten wird, soll auch verdeutlicht werden. Dabei wird einmal die Theorie und anschließend die Praxis genauestens durchleuchtet. Dementsprechend werden dabei folgende Punkte besprochen: Unit-Tests, Integrations-Tests, Akzeptanz-Tests und Mocking.

Theorie & Praxis: Code-Coverage
Sehr oft wird beim Schreiben von Codes genau an denn Tests geschrieben, die niemals zu Problemen eintreffen werden. Somit passieren Fehler, die bis heute im Unbekannten weiter leben. Damit diese Horrorvisionen nicht Wirklichkeit wird, spielt die Testabdeckung eine wichtige Rolle!

Einführung in Behavior Driven Development
Durch eine Erweiterung von TDD durch Behavior-Driven Development (kurz BDD) werden Tests strukturierter nach den Anforderungen aufgebaut. Hier wird unverkennbar der Kern von TDD für qualitative Softwareprojekte genutzt, und durch die Erweiterung von BDD die funktionalen Anforderungen in den Mittelpunkt gestellt.

Über den Sprecher
Gregor Biswanger ist Consultant bei der Firma TRIA IT-solutions in München. Seine Schwerpunkte liegen im Bereich der .NET-Architektur und agilen Prozessen.
Biswanger ist auch freier Autor, Speaker und Microsoft CLIPler der INdotNET (Ingolstädter .NET Developers Group).

Verlosung: Fuzzing-Tests für .NET mit CrashTest.Net
CrashTest.Net ist ein Testwerkzeug, das explizit auf .NET-Projekte zugeschnitten ist und eine bisher für das .NET-Umfeld ungenutzte Testmethode verwendet. Bei der Testmethode handelt es sich um Fuzzing. Es hilft Entwicklern ihre Software zu optimieren und zeigt ihnen unbedachte Fälle, die später beim Endnutzer fatale Folgen haben können. Ohne notwendige Einstellungen führt es vollautomatisch eine sehr große Anzahl von Tests an ihrer .NET-Assembly durch. Es versucht alle Methoden mit sehr vielen Parametern auszuführen. Und all das, ohne vorher komplizierte Einstellungen zu vorzunehmen oder im Quellcode irgendwelchen Test-Code zu implementieren. Fuzzing birgt ein sehr großes Potential. Dieses Potential wird der .NET-Welt mit CrashTest.Net einen entscheidenden Schritt näher gebracht.

CrashTest.Net unterstützt uns freundlicherweise mit 1 Lizenz zur Verlosung 

 

Das zehnte .NET-Stammtisch Treffen findet mit Jürgen Gutsch und folgendem Thema statt:

Barrierefreie Anwendungen mit ASP.NET.
Jürgen Gutsch beschreibt in einem Vortrag, ob es möglich ist Barrierefreie Webentwicklung mit ASP.NET zu betreiben und zeigt anhand von Beispielen was nötig ist um Barrierearme Anwendungen zu Entwickeln

Anschließend wird wie immer beim gemütlichen Bierchen weiter diskutiert, bzw. im Advent ist natürlich Glühwein auf dem Konstanzer Waihnachtsmarkt angesagt :-)
Eingetragen von Peter Bucher | 1 Kommentare
Mehr Beiträge Nächste Seite »