Q & A – MSDN on Tour - Another USING issue (StyleCop vs. Template)

 

Die Frage:

“Warum schlägt mir StyleCop vor die „using“ Direktiven im Namespace zu verwenden, währen das Visual Studio Template die „using“ Direktiven außerhalb des „Namespaces“ setzt? “

Es geht also um diese Geschichte hier:

  using  System;
  
  namespace  ConsoleApplication1
  {
      class  Program 
      {
          static  void  Main(string[] args)
          {
              Console.WriteLine("Hello" );
          }
      }
  }
  
  vs.
  
  namespace  ConsoleApplication1
  {
      using  System;
  
      class  Program 
      {
          static  void  Main(string[] args)
          {
              Console.WriteLine("Hello" );
          }
      }
  }
  

Und eine Sekunde lang wollte ich schon sagen: “Das kann man ja einstellen!” Aber ich wusste da war irgendwas. Irgendwo hatte ich mal ein Problem, oder etwas gelesen, was der Grund dafür ist. Aber mir ist es beim besten Willen nicht eingefallen warum. Jetzt vor meinem Rechner und mit Don Box an meiner Seite fällt es mir wie Schuppen von den Augen.

Es gibt einen kleinen aber feinen Unterschied. Aber um das Problem zu verstehen, sollten wir einen Blick auf „Namespaces“ werfen.

„Namespaces“ sind das Äquivalent zu „Packages“ in Java oder „Header Files“ in C++!?

Sehr oft hört man diese Erklärung. Wie bewerten Sie diese Aussage?

“Zu falsch um richtig zu sein, und zu richtig um falsch zu sein!”

 

Der Java Developer

Ein Entwickler der aus Java kommt wird Namespaces so verwenden wie Packages. Will heißen, pro Assembly wird genau ein „Namespace“ verwendet. Wenn man sich an diese Konvention hält, läuft man nur selten in Probleme. Man stört sich allerdings an den Namespaces und den Referenzen die man setzen muss.

 

Der C++ Entwickler / Framework Entwickler

Ein C++ Entwickler ist es gewohnt Header Files anzulegen die je nach Architektur und Model relevant sind. Kommt man aus der C++ Welt macht es durchaus Sinn unterschiedliche „Namespaces“ in einer „Assembly“ zu haben. Oft wird auch während der Designtime (Entwicklung) ein Projekt angelegt. Der Namespace gilt für dieses Projekt. Aber das Projekt wird zusammen mit anderen Projekten in eine „Assembly“ gepackt und als eine DLL deployed. Selbst innerhalb einer „Executable“ macht das Erstellen von „Namespaces“ in denen gewisse Controls oder Interfaces liegen Sinn. Oder eine Applikation ist so klein, dass es Sinn macht Ihr unterschiedliche „Namespaces“ zu geben (siehe CardGame) um eine Trennung in Framework etc. zu bekommen.

 

Next Generation Developers

Der High-Potential Entwickler von Morgen überlässt das Management von „Namespaces“ Tools wie Resharper, CodeRush oder JustCode. Warum sollte man auch eine künstliche Trennung durch „Namespaces“ erzwingen?

 

Fazit Namespaces

„Namespaces“ sind flexibel einsetzbar. Verwendet man Namespaces arbiträr kümmert man sich selbst darum, muss aber auch selbst Herr der etwaigen Konflikte werden. Javalike Packages Developer oder Refactoring Tools lösen Namespace Konflikte dadurch, dass Sie sagen: „… System.IO.File file…“ Sie machen eine Explizite Aussage darüber woher eine Methode stammt. Oder verwenden clevere Tricks um zu schauen ob die “Namespaces” und “Usings” harmonieren.

Resharper und StyleCop mit „Default Einstellungen“ zusammen gebracht sind ein Spaß, den man sich nicht entgehen lassen sollte. !

Nun aber zum eigentlichen Kern der Frage.

  using  System;
  
  namespace  Outer.Inner
  {
      class  Circle 
      {
          public  double  CalculateArea(double  radius)
          {
              return  2 * radius * Math.PI;
          }
  
          //... 
      }
  }
  

Hier sehen wir eine Klasse Circle die im Namespace Outer.Inner lebt. Außerhalb des Namespaces existiert eine Referenz auf System. Die statische Klasse Math lebt im System Namespace, und hat eine Konstante Pi die zur Berechnung der Kreisfläche dient.

Stellen wir uns nun vor, dass jemand anders im Projektteam in unserem Projekt eine weitere Datei hinzufügt.

  using  System;
  
  namespace  Outer
  {
      class  Math 
      {
  
      }
  }
  

Was passiert nun? Der Kompiler schaut zunächst im Namespace Outer.Inner nach, findet aber keine Definition für die Klasse Math. Nun schaut er im Namespace Outer nach und findet eine Klasse Math. Diese ist aber weder statisch noch enthält Sie eine Definition für PI. Was zwangsläufig zu einem Compiler Fehler führt. Ändert man die Klasse Circle wie folgt ab:

Ändert man die Klasse Circle wie folgt ab:

  namespace  Outer.Inner
  {
      using  System;
  
      class  Circle 
      {
          public  double  CalculateArea(double  radius)
          {
              return  2 * radius * Math .PI;
          }
      }
  }
  

Steht das entsprechende Using im Namespace Outer.Inner und der Compiler erkennt sofort, dass System.Math für diesen Kontext gültig ist. Und siehe da, die Applikation läuft wieder.

Ja, dass Argument mit System.Math wirkt etwas künstlich. Aber kommt es nie vor, dass jemand eine Klasse so nennt, wie eine Framework Klasse heißt? (Es gibt immerhin 6025 Klassen im .net Framework 3.5) Kommt es nie vor, dass es zu Konflikten im “Namespace” kommt? StyleCop will die Sinne für diese Problematik schärfen. Allerdings muss ich sagen, dass diese Poblematik dank ReSharper und Co. auch für mich bis zu dieser Frage kein Problem war. Auch nicht in großen Projekten ohne Resharper. ( Ich hasse mich für den nächsten Satz - Dank diverser Guidelines und Konventionen. )

Übrigens, kommt jetzt jemand auf die Idee, man könnte die Klasse Circle in den Namespace Outer verschieben, dem sei gesagt: “Schlechter Plan!”

Der Kompiler schaut immer zuerst auf den Namespace bzw. Hirachie von Namespaces, bevor er sich um “usings” kümmert. Will heißen: Die Klasse Circle kompiliert nicht mehr.

Mein Wort zum Sonntag am Montag …



StyleCop und CleanCode

SyleCop und CleanCode Development sind eine Geschichte die Ihren Ursprung in C++ Projektteams haben mit 50+ Developer. Über Fluktuation in solchen Teams brauche ich nicht zu sprechen. Viele Ansätze von StyleCop sollen helfen sich an Firmenweite Konventionen zu halten. Man sollte also StyleCop auch die Konventionen der Firma beibringen. Der Code soll dadurch lesbarer und Teamfreundlicher werden. Deshalb will StyleCop die “Namespaces” auf diese Gesichtspunkte hin optimieren. Während also das Visual Studio Template erstmal keine Vorgaben macht, was Teamgröße und Architektur angeht.

Ich hoffe ich konnte die Frage damit beantworten.