Zu viel Konstruktor-Injizierung!?

Ist zu viel Konstruktor-Injizierung ein Anti-Pattern? In einem Blog-Post konstruiert Jeff Palermo ein Beispiel, in dem eine injizierte Komponente eine wirklich langsame Initialisierung hat. Da die Komponente nur von einer Methode der Klasse benötigt wird, leitet er ab, dass statt der Konstruktor-Injizierung von Komponenten eine Lazy-Factory die bessere Alternative ist.

Die Kommentare lehnen diesen Schluss fast fast einhellig  ab, denn:

1) Eine Verzögerung der Initialiszierung ist auch über den Container und mit .NET 4 auch über System.Lazy<> zu erreichen.

2) Gegen eine Schnittstelle zu programmieren bedeutet gerade, dass man Implementierungsdetails nicht in der Hand hat.

3) Langwierige Initialisierung in der Komponente bedeutet, dass die Komponente minderer Qualität ist, hier muss dann nachgebessert werden. Es sollten keine aufwändigen Operationen in der Konstruktor-Implementierung durchgeführt werden.

4) Ein Abstrakte Fabrik erzeugt ein Abhängigkeit gegenüber dieser, was die Menge der Abhängigkeiten steigert und die Vorteile des IoC reduziert. Jedes „new“ ist bad „news“.

5) Um häufige Initialiserung zu umgehen, könnten Services als Singelton konfiguriert werden, wobei globale Konfiguration ein Problem sein kann, weil sie schwer zu Debuggen und auf Anwendungsebene auch schwer nachzuvollziehen sein kann.

Danke an Jeff Palermo für seinen sehr lesenwerten Post!

Links:


GEN0 und GEN2 Heap gegenläufig?

Gen2 und Gen0 sind deutlich gegenläufig, versteh ich nicht, hat jemand ein Erklärungsmuster? Fängt der Garbarge-Collector an in Gen2 aufzuräumen weil viel neuer Speicher allokiert werden muß?

Bild: Speicher für Camping.Info Server: (8 GIG RAM, 2x Quadcore, ca.: 1000 aktive Sessions, Requests per Second: Avg.: 50, Peak: 120)

Memory-Gen1-Gen2

Das 10x mehr Speicher in Gen2 liegt bedeutet natürlich, dass wir unser Memory-Leak immer noch nicht aufgespürt haben. Normal müsste Gen 2 kleiner sein als Gen 0? Viele Fragen :-)

(Robert)


ALT.NET.BERLIN Zweiter „Coding Dojo“ und erster „OPEN-TABLE“

ALT.NET.BERLINDie Berliner User Group „ALT.NET-BERLIN“ hat Ihren zweiten „Coding-Dojo „durchgeführt (und das 14. Treffen). Sehr lesenswert ist die Aufbereitung des Coding-Dojos durch Mike. Ich konnte wirklich viel aus dem Treffen und dem Bericht ziehen. Jedem der kann, sei ein Besuch des nächsten Dojos sehr ans Herz gelegt!

Morgen am Dienstag den 11.05.2010 findet unser erster Open-Table statt. Thema sind Design-Patterns. Die Agenda ist hier zu finden.

Wer über ALT.NET.BERLIN Termine auf dem Laufenden bleiben möchte, dem sei die XING-Gruppe .NET Berlin empfohlen, die Marco heute gegründet hat :-)


Memory-Leak vs. Memory Waste

kurzer Nachtrag zum vorherigen Post. Eigentlich kann management Code für sich keine Memory-Leak haben. Es ist lediglich möglich Speicher schlecht zu nutzen, in dem er zum Beispiel zu lange gehalten wird. Technisch ist das kein Memory-Leak. Nur unmanaged Code kann nicht mehr verwalteten Speicher zurück lassen. Deswegen suchen wir streng genommen vermutlich eher nach "Memory-Waste"!


ASP.NET Memory-Leak

Wir sind auf der Suche nach einem Memory-Leak für Camping.Info.

Es ist jetzt Donnerstag, 11:56Uhr. Der Web-Server läuft jetzt erst seit 16 Stunden.

Memory-Leak 

Die aktuelle Session-Zahl liegt bei 652. Den Session Timeout von 20min rausgerechnet, bei einer Verweildauer von 7 Minuten, entspricht das ungefähr 70 tatsächlich aktiven, parallelen Besuchern zu diesem Zeitpunkt. (Im laufen des Tages, werden das deutlich mehr.)

Session-Zahl

Der Speicherverbrauch ist für die aktuelle Session-Zahl zu hoch und steigt anscheinend stetig über mehrere Tage hinweg.

Es gibt 2 Möglichkeiten für Memory-Leaks in Managed-Code.

  • Referenzen auf Objekte werde nicht wieder frei gegeben, in dem Sie Beispielsweise im ASP.NET Cache gehalten werden.
  • NET Code verwendet unmanaged Resourcen wie FileSystem oder "Datenbank-Connections und diese Resourcen werden nicht wieder explizit frei gegeben. Auch “System.Drawing" stellt ein Problem dar, da es auf unmanagement Resourcen verweist.

Oliver hat einen Dump erstellt der wie folgt aussieht:

Speicher-Dump 

Wir sind auf der Suche, über die Lösung des Problems werden wir berichten.


Vorsicht bei String als Lock-Objekt

Wenn man denn unbedingt einen String als Lock-Objekt nutzen will und man sich davon überzeugt hat, nicht den Type eines gerade durch die Methode schwirrenden Objektes zu nutzen (das könnte ja jeder machen ;-)), dann sollte man auf jeden Fall an String.Intern(myLockString) denken!

Wo man kann, sollte man also weiterhin einen einfachen object-Lock nutzen:

   1: private static readonly object _lock = new object();

Aber man darf dann nicht vergessen, dass alle Threads, die auf den Code im Lock zugreifen von einem einzigen Lock bedient werden. Wenn man die Threads aber in Gruppen aufteilen kann, die unabhängig voneinander arbeiten können, ist diese Beschränkung zu scharf. Ich suchte also einen Weg, einen eindeutigen Lock für jede dieser Gruppen (hier: TranslationGroup) zu generieren, der von allen Instanzen geteilt wird. Der Gruppenidentifikator heißt hier _pageNameKey.

Beispiel:

   1: private const string _migrateLock = "9B90360AAF4342798A739DA2D85AF5AF"; // guid
   2:  
   3: private string _pageNameKey = ...; // can be the same in multiple parallel threads
   4:  
   5: public void Migrate(string oldGroupName, Dictionary<string, string> controlIdsOldToNew)
   6: {
   7:     lock (string.Intern(_migrateLock + _pageNameKey))
   8:     {
   9:         // do something not here that should not be done in parallel
  10:     }
  11: }

Ließe man in Zeile 7 das String.Intern(…) weg, würde bei jedem Aufruf der Methode ein neues String-Objekt generiert – was für dem Lock seine Existenzberechtigung raubt.

Gruß, Oliver

Technorati-Tags: ,,,

Arten von Branches, Branch per Refactoring

Wir hatten gerade eine Diskussion zum Nutzen von “Feature-Branches”, “Long-Running Branches” und “Topic Branches”. Das Gespräch bezog sich auf die Nutzung mit GIT. Zunächst eine kurze Klärung der Begriffe:

  • “Feature-Branches”, für ein Feature wird eine neuer Entwicklungszweig genutzt
  • “Branch-per-Configuration”, es wird kein physischer branch erzeugt, sondern die Entwicklung erfolgt im Hauptzweig. Ein entwickeltes Feature läst sich per Konfiguration ein und ausschalten.
  • “Long-Running Branches”, Ein Branch der länger als ein paar Tage genutzt wird
  • “Topic Branch”, Ein Branch der kurzlebig ist. Kurzlebig sind ein paar Minuten oder Stunden.

Aus meiner Perspektive sind Feature-Branches und Long-Running-Branches - wenn möglich - zu vermeiden. Ideal ist sind “Branches per Configuration”, die bei der Entwicklung ein modulares Arbeiten und damit eine gute Architektur erzwingen. Aufwände für das mergen werden vermieden. “Topic Branches“ sind durchweg positiv, wenn sie lokal bleiben und nicht zu entfernten Repositories gepushed werden.

Branch per Refactoring

Es kam auch kurz das Gespräch auf das Thema “Branch per Refactoring” bzw. eine Refaktorisierung wurde als “Feature Branch” bezeichnet. Aus meiner Sicht deutet das auf einen CodeProcess-Smell hin. Die Refaktorisierung ist zu groß.  Refaktorisierungsschritte sollten klein sein und ein Arbeitsschritt direkt wieder in den Hauptentwicklungszweig einfließen können.


Benamungs-Strategien

  • SettingsApp
  • SettingsUser
  • SettingsSubSystemX

vs.

  • AppSettings
  • UserSettings
  • SubSystemXSettings

beides hat seine für und wider. Variante 1 ist IntelliSense freundlicher und Variante 2 ist näher an der Grammatik.

Ich bin ich ganz klar - soweit die Wortgebilde nicht total obskur werden - meist für Variante 1.


32-bit DLL in 64-bit WebApp: An attempt was made to load a program with an incorrect format

Die folgende Fehlermeldung erhielt ich heute von unserem IIS7, als ich Camping.Info starten wollte:

Server Error in '/' Application.

Could not load file or assembly 'Microsoft.Cci' or one of its dependencies. An attempt was made to load a program with an incorrect format.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.BadImageFormatException: Could not load file or assembly 'Microsoft.Cci' or one of its dependencies. An attempt was made to load a program with an incorrect format.

Also das Orakel gefragt und u.a. das hier gefunden: http://forums.asp.net/t/1358032.aspx

Standardmäßig unterstützt ein 64-bittiger IIS 7 keine 32-bit-Module (u.a. DLLs). Man kann es ihm aber einfach beibringen :-)

Im IIS-Manager den gewünschten ApplicationPool auswählen und in den Advanced Settings die folgende Einstellung vornehmen:



Der Vollständigkeit halber hier noch ein Link zur Anleitung für den IIS6 auf Windows 2003 Server: http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/405f5bb5-87a3-43d2-8138-54b75db73aa1.mspx?mfr=true

Happy Coding!

Oliver


Configuration mit configSource auslagern - Copy always

Eine kleine Notiz für die Zukunft:

Wenn man eine Configuration-Section aus einer *.config-Datei in eine eigene Datei auslagert, so wie neulich geschehen für die NHibernate-Konfiguration, dann sollte man die "Copy to Output Directory"-Option auf "Copy Always" setzen:

<!-- Lokal eine passende NH.config anlegen -->
<hibernate-configuration configSource="NH.config" />



Ansonsten bekommt man nämlich eine der folgenden ähnliche Fehlermeldung:

System.Configuration.ConfigurationErrorsException: Die configSource-Datei "NH.config" kann nicht geöffnet werden.
(G:\Projects\Camping.Info\Tests\bin\Debug\Tests.dll.config line 12)

Oliver


Über speak-friend

Wir Stefan, Oliver, Anton und Robert, sind die Entwickler von speak-friend.

Hier schreiben wir über unsere Coding-Abenteuer.

Letzten Kommentare