Laden...

Forenbeiträge von SeboStone Ingesamt 489 Beiträge

01.10.2010 - 14:23 Uhr

Man wächst mit seinen Aufgaben! Also warum nicht?! Aber bedenke, dass Du entweder sehr viel Zeit investieren musst oder an der Funktionalität sparen musst.

Wenn Du bereits mit SPS entwickelt hast, dann bringst Du sicherlich schon mal ein paar Erfahrungen mit. Entwickeln heißt eben nicht nur, einfach nur Syntax und Tools zu kennen, man muss auch - ich sage mal - "die richtige denkweise" entwickelt haben.

Wahrscheinlich wird auch nicht gerade das beste Stück Software herausfallen, aber das ist denke ich hier auch nicht Dein Ziel.

Eine Gui zu bauen ist tatsächlich nicht das einfachste, auch wenn es auf den ersten Blick so aussieht. Der Kern Deiner Anwendung wäre auch sicher nicht die Gui, sondern die Ansteuerung der externen Geräte und das sichern der Daten, etc. Die Gui kannst Du später (!!!!) noch dazu basteln.

16.09.2010 - 13:34 Uhr

Bin selber gerade darauf gestoßen. Das Problem ist, dass Log4Net nun nicht mehr direkt aufgerufen wird, sondern dass Common.Logging alle Aufrufe des Log4Net wrappt. Ergo, ist die Ausgabe richtig, denn die Methode welche die Log4Net-Log-Methode aufruft ist nun die Log-Methode von Common.Logging - saublöd.

13.09.2010 - 11:25 Uhr

Nur so einfach wie das bei WinForms ging, geht das anscheinend nicht in WPF. Hab auch schon gelesen das es die Visuelle Vererbung, wie bei den WinForms bekannt, es jetzt in WPF nicht mehr gibt.

Doch, das geht. Du brauchst im XAML einfach nur nicht von Window oder UserControl erben sondern von Deiner Basisklasse. Aber in der Tat, visuelle Vererbung geht nicht. Das heißt Deine Basisklasse muss eine Klassen sein und zwar ohne XAML Code. Da Du aber nur von Methoden und Properties sprichst ist das ja kein Problem.

09.08.2010 - 18:05 Uhr

Hi zero_x,

Nein, das geht leider nicht, da kommen mir zwei dummerweise noch nicht genannte Randbedingungen in die Quere:

Jedes ViewModel kann hier über seine View editiert werden so lange der Benutzer das will. Das DTO wird dabei nicht verändert. Erst wenn der Benutzer sein Commit macht werden alle Änderungen in das DTO übertragen. Alle Bindings sind aber auf UpdateSourceTrigger=PropertyChanged gesetzt und sollen es auch bleiben. Das heißt, wenn ich die Valdierungen mit Hilfe des DTOs mache, ist es bereits zu spät oder ich verliere die Möglichkeit dass der Benutzer seine Änderungen verwerfen kann.

Wenn ich im Model - also eine Schicht tiefer als die ViewModels - validieren möchte gilt folgendes: Die ViewModels kennen das Model nicht. Das heißt ich müsste ein Event werfen dass die Validierung anstößt und das Model injected dann per Method-Call das ValidationResult in das ViewModel. Ich denke der Aufwand wäre hier nicht gerechtfertigt.

Mmh, ich bleibe glaube ich immer noch bei meinem auslagern und DI-injecten der Validierung. 🙂 Dennoch danke für Deine Hilfe!

09.08.2010 - 17:23 Uhr

Hi zero_x,

nein, es ist keine Datenbank, es ist ein Klassenmodell (DTO) dass ich über eine WCF Schnittstelle hole. Das DTO habe ich ständig lokal zur Verfügung. Bisher habe ich alle Validierungen im ViewModel mit dem Microsoft.Practices.EnterpriseLibrary.Validation Framework realisiert, aber nun habe ich den Fall, dass ich eben über mehrere ViewModels hinweg, bzw. deren Daten validieren muss.

Ich möchte nicht wirklich bis ins Modell runter gehen müssen, denn es handelt sich tatsächlich nur um eine Eingabevaldierung.

Bisher habe ich keine bessere Idee als eine Klasse zu bauen welche alle notwendigen Validierungsroutinen beinhaltet und eine per Constructor reingereichte Instanz des DTOs hält. Das DTO ist ein ständiges valides Abbild der ViewModels. Die ViewModels bekommen diese Validierungsklasse dann ebenfalls injected. Aber so richtig toll finde ich das nicht.

09.08.2010 - 16:01 Uhr

Hi!

Ich habe mehrere unabhängige ViewModels (und entsprechende Views) welche aber aus ein und derselben Datenbasis "generiert" werden. Nun soll eine Eingabevalidierung erweitert werden. Das Problem ist hierbei, dass auf Daten zugegriffen werden muss welche sich in anderen ViewModels befindet. Auf die Datenbasis möchte ich nicht zurückgreifen.

Ich habe mir dazu zwei mögliche Lösungen ausgedacht, bin aber mit beiden nicht so glücklich und ich hoffe auf noch bessere Ideen.

Einmal kann ich beim Befüllen des entsprechenden ViewModels auch gleich die Daten mit ins ViewModel holen (kopieren) welche ich für die Validierung benötige. Da sich über die Lebenszeit des ViewModels die Validierungsdaten nicht ändern wäre das so möglich.

Meine zweite Überlegung ist für diese Problematik eine Validierungsklasse zu basteln welche ich dann per Constructor DI in das ViewModel pumpe. Das ist momentan meine präferierte Lösung.

Hat jemand noch eine bessere Idee?

09.08.2010 - 13:08 Uhr

soll ich für jeden modelview eine andere classe definieren(was ich nicht möchte)

Jede View hat Ihr eigenes ViewModel.

06.08.2010 - 16:52 Uhr

Im Prinzip wird hier ein Aspekt, nämlich das an verschiedenen Stellen immer gleich Exeption-Handling, ausgelagert. Das reduziert die Redundanz der Modellklasse. Den ExceptionCatcher wäre also auch dann sinnvoll, wenn man überhaupt keine Unit-Tests schreiben würden.

Einen besseren "Beweis" als diesen kann es doch kaum geben, dass es eben nicht private zu sein hat - eben WEIL es an noch mehr Stellen Sinn machen würde.

Was für ein Beweis? Schau Dir den ExceptionCatcher doch mal an, der wirft eine spezielle Exception, eine Komponenten-Exception. (Ok, das "Irgendwas" sieht wohl nicht danach aus, war aber so gemeint) Keine andere Komponente hat diesen ExceptionCatcher zu verwenden, denn normalerweise treten in jeder Komponente auch andere Exceptions auf. Und komponentenintern wird er auch nur an den Schnittstellen verwendet -> im Normalfall repräsentiert die Schnittstelle genau eine Klasse, im schlimmsten Fall gibts da noch eine Base-Klasse. Ergo, den ExceptionCatcher global zu machen oder sogar in den Kontrakt aufzunehmen ist ein architektonischer Gau.

06.08.2010 - 12:48 Uhr

Wenn man z.b. mal individual SW für eine Anwaltskanzlei macht, und auch sein Geld haben will, muss man seeeehr präzise sein.){gray}

Dem stimme ich zu und ich bin der Meinung, dass ich mich fast immer entsprechend ausdrücke. Deswegen benenne ich auch immer wieder den Unterschied zwischen Unit- und Integrationstest - was Du z.B. nicht tust.
Vielleicht ist es mir bei dem betreffenden Post nicht ganz so gut gelungen wie gewollt, aber dann kann man doch davon ausgehen, dass ein intelligenter Leser das naheliegensde erkennt. Deine Analogie passt hierbei auch ins Bild. Wie wahrscheinlich ist es dass die Ehefrau gemeint hat dass er 6 Brote mitbringen soll?

06.08.2010 - 11:01 Uhr

Ahh, dann bist Du also ein Till Eulenspiegel. 😁 Also wolltest Du mich nicht richtig verstehen, ist auch ok.

06.08.2010 - 10:32 Uhr

dass eine private Methode oder Klasse häufig benutzt wird und wichtig ist, sogar so wichtig, dass sie als nicht änderbar angesehen wird, heißt doch noch lange nicht, dass sie öffentlich gemacht werden muss oder auch nur darf. Das ist doch abstrus.

Dem stimme ich absolut zu. Wie kommt man auf die Idee Methoden-Zugriffsmodifizierer nach Wichtigkeit zu vergeben? Warum nicht gleich Zugriffsmodifizierer mit der Schrotflinte reinrotzen? 😁

Aber damit erklärt sich auch die Haltung nur Public Methods zu testen. Offensichtlich werden einfach alle Funktionen die es Wert sind getestet zu werden Public gemacht. Das ist ganz sicher der falsche Ansatz.

ich denke, das kann nur SeboStone beantworten.
Richtig, und das hat er im Prinzip auch getan, indem er seine große Verwunderung und sein Unverständnis über die Behauptung, dass die Klasse in den Test-Code gehört, zum Ausdruck gebracht hat.

Tatsächlich habe ich das getan. Herbivore hat mich richtig verstanden, Golo und FZelle leider nicht. Die Klasse / Komponente braucht ein entsprechendes Exceptionhandling und nicht der Test!
Ich gebe aber FZelle recht, wenn er sagt, dass man das auch in Tests verwenden kann. Ich bezweifle dann aber stark, dass die Tests leicht nachvollziehbar und selbsterklärend sind. So ist es auch kein Wunder warum er propagiert nur Integrationstests auf den Interfaces zu bauen.

Hoffentlich habe ich mich jetzt nicht schon wieder uneindeutig ausgedrückt. 😉

05.08.2010 - 13:30 Uhr

Dann ist aber ExceptionCatcher aber nicht Bestandteil der Implementierung sondern eine Hilfsklasse für die Tests und gehört in die Unittest Klasse.

?( ?( ?( ?( Wie kommst Du denn darauf??

05.08.2010 - 12:57 Uhr

Stellt Euch vor, ihr habt eine WCF Schnittstelle die ein dutzend Methoden zur Verfügung stellt. Bei jedem Aufruf einer Methode auf der Schnittstelle können dutzende verschiedener Exceptions auftreten. Jede der Exception soll anders behandelt werden (benutzerfreundlicher und passender Text und verpacken in eigene Exception und throw). Wie testet Ihr so was? Wenn Ihr das nur auf dem Interface der Komponente testet welche die WCF-Kommunikation kapselt, dann habt ihr allein für das Fehlerhandling deutlich über 100 Tests. Und es sind immer genau dieselben Tests! Wäre es denn nicht einfacher einen ExceptionCatcher wie folgt zu bauen:


private T ExceptionCatcher<T>(Func<T> function)
{
	try
	{
		return function();
	}
	catch (ArgumentNullException ex)
	{
		throw new IrgendwasException("parameter war null", ex);
	}
	catch (Exception ex)
	{
		throw new IrgendwasException("unbekannter fehler", ex);
	}
}

Diesen dann vollständig zu testen (der gehört ganz sicher nicht zu einem Kontrakt) und dann immer nur noch (z.B. mit Rhino.Mocks) zu prüfen, ob die Methode bei jeder Operation auf der WCF-Schnittstelle auch wirklich aufgerufen wird.


public bool IsEqual(string irgendwas)
{
	return ExceptionCatcher(() => TryIsEqual(irgendwas));
}

Das reduziert die Tests um einen erheblichen Faktor und die Wahrscheinlichkeit dass Testfälle fehlen oder falsch getestet wird nimmt entsprechend ab.

03.08.2010 - 15:09 Uhr

Die Frage ist doch, ob das Überprüfen der Qualität überhaupt in die Klasse gehört, die den Kaffee kocht - oder ob das nicht als public-Methode in eine eigene Kaffee-Qualitäts-Tester-Klasse gehört.

Sicherlich würde es eine Klasse "KaffeeKochen" und eine Klasse "Kaffee" geben welche dann auch Aussagen über die Qualität treffen kann. Aber ich denke das ist an dieser Stelle erstmal gar nicht relevant.

Aus meiner Erfahrung deutet der Bedarf, privates zu testen, meistens darauf hin, dass Komponenten noch nicht fein granular genug sind.

Mmh, an der Stelle meinst Du sicherlich "Klassen" und nicht "Komponenten". denn wenn dem so wäre, dann müssten Deine Solutions hunderte Projekte beinhalten. 😉

Ich bin der Meinung, dass es tatsächlich Sinn macht "privates" ebenfalls zu testen. So sehr lassen sich Klassen nicht granulieren ohne insgesamt eine Absurdität zu werden. Man ist gar nicht in der Lage alle möglichen Fehlerquellen schon gar nicht Fehlermöglichkeiten alleine durch Tests auf den Interface Methoden und Properties abzudecken. Aber tatsächlich würde ich nicht auf privaten Methoden rum rutschen, ich weißt mit dem MS TestFramework geht das aber mit internals und InternalsVisibleTo hat man doch recht gute Möglichkeiten. Sobald man mit Rhino.Mocks anfängt wird man je nach Ausprägung und Teststrategie sowieso an den Zugriffmodifizierern noch einige Kompromisse eingehen müssen.

Aber wie gesagt, es gibt unterschiedlichen Teststrategien, jede hat seine Vor- und Nachtteile und keine ist meiner Erfahrung nach für sich alleine gesehen ausreichend. Meiner Erfahrung nach ist eine Mischung aus Unit-Tests (wie es CSL propagiert) und (Komponenten-) Integrationstests (wie es Golo Roden propagiert) die beste Möglichkeit der Qualität einer Software auf die Sprünge zu helfen. 🙂

03.08.2010 - 14:50 Uhr

Mmh, Du hast in Deinen Klassen sicherlich Methode welche andere Methoden derselben Klasse aufrufen. Und dann hast Du sicherlich Methoden welche Methoden von Dependencies aufrufen. Wie testest Du so was? So was testen kannst Du ohne Mocks gar nicht, Du könntest so was nur testen, wenn dadurch states manipuliert würden und Du diese prüfst. Du kannst natürlich Mocks auch selber schreiben anstatt sie z.B. mit Rhino.Mocks zu generieren, aber das ist erstens erheblich aufwendiger und zweitens extrem fehlerträchtig.

Mit Mocks habe ich derzeit (leider) noch nichts gemacht

Ok, das erklärt das eine oder andere Statement. 😁 Wenn Du Dich damit mal befasst hast, dann wird sich Deine Meinung bezüglich TDD sicherlich etwas ändern. Du wirst es dann auch mit dem Testen leichter haben. Ich kann mir gut vorstellen, dass Du bereits auf Code gestoßen bist wo Du nicht weißt wie Du das testen sollst. 😉

Zu TDD selber sagte ich ja schon mehrfach das ich mir demnächst endlich mal ein Buch besorgen muss, damit ich da auch sicherer bin, habe bestimmt nur hier und da kleine Denkfehler.

Naja, ein Buch schafft man sich an wenn man eine neue Technologie nutzen möchte. TDD ist nur eine Herangehensweise, ein Prozess, der ist schnell erklärt, da brauchts kein Buch, aber sehr viel Zeit und Ausdauer das ganze zu probieren und dabei zu bleiben. Am Anfang ist das nicht einfach und die Entwicklung verläuft sehr schleppend, aber es lohnt sich. 🙂

PS: Die CCD Grade sind nicht dafür gedacht dass Du sie stur Top Down in Dich reinklopfst. Es ist völlig legitim, dass Du auch mal in die anderen Grade hineinschnupperst und Dir das raus ziehst was Du sofort brauchen kannst. Continous Integration ist so ein Thema, dass Du - wenn Du es noch nicht hast - als nächstes einsetzen solltest.

03.08.2010 - 12:33 Uhr

Ein "Fehler" ist in meinen Augen auch, privates zu testen - es ist für den Unittest total egal, wie Du das intern aufziehst: Alles in einer Methode direkt, oder mit fünf privaten Methoden. Getestet wird nur die öffentliche Schnittstelle.

Ah, das ist kein echter Unit Test mehr, das ist bereits eine Art Integrationstest. 🙂 Ich denke beim Testen scheiden sich allgemein ein wenig die Geister. Jeder hat eine andere Teststrategie. Ich habe schon verschiedene Strategien ausprobiert, aber das Optimum habe ich für mich auch noch nicht herausgefunden. Zur Zeit teste ich hybrid. Das heißt ich habe Unit Tests die mir die die Methodenfunktionalität abdecken und Integrationstests welche mir die Funktionalität abdeckt.

Auch hier entweder wieder zu wenig geplant, oder - wenn Du nach TDD vorgehst - merkst Du ja schon beim Test schreiben, dass es sich irgendwie seltsam anfühlt, und kannst direkt gegensteuern.

Absolut! 👍

//edit: kleiner Fehler in der Wortwahl gefixt

03.08.2010 - 12:29 Uhr

Oder ich merke beim entwickeln das die Methode "HoleKaffeeFilter" überflüssig ist, da es eine Filterlose Maschine ist, dann Lösch ich die einfach.

Alles Aktionen die Anpassungen in den Units erfordern, da ist es doch praktischer wenn der Code dahin gehend bereits "fertig" ist. Vor allem bei kleineren Umstellungen während der Entwicklung.

Man könnte sagen, das klingt logisch, aber was machst Du wenn Du nach zwei Wochen weitere Features hinzufügen musst oder sie etwas ändern musst? Wann ist denn dann der Beste Zeitpunkt fürs Testen?

Nach Deiner Logik nach wäre es das Beste so lange mit den Tests zu warten bis die Klasse keinerlei Änderung mehr erfahren soll. Also eigentlich nie. 🙂

03.08.2010 - 12:24 Uhr

Oder, ich plane eine Klasse und habe dort eine Methode KocheKaffee vorgesehen, dann kann ich nun die Units schreiben, aber ich weiß doch noch gar nicht welche Methoden KocheKaffee alles benötigt

Ich denke, dann hast Du Deine Klasse nicht wirklich ausreichend geplant, oder die Anforderungen für Deine Funktionen wurden zu schwammig definiert.

nur dann weiß ich auch noch nicht ob ich dort intern eine "ÜberprüfeQualität" benötige.

Wo ist das Problem? Wenn Du merkst Dir fehlt noch etwas, dann schreibst Du einfach die Tests für die neue Methode und dort wo sie aufgerufen werde soll expectest Du dann den Methoden-Call z.B. mit Rhino.Mocks - das sind höchstens 2 Zeilen mehr in einem bestehenden Test, vorausgesetzt Du entwickelst tatsächlich nach CCD, Deine Signatur lässt das vermuten. 👍

Und Klassen-/ Komponentenintegrationstests lassen sich alle Mal TDD entwickeln.

03.08.2010 - 12:07 Uhr

Eingentlich möchte ich eine meiner Meinung nach sehr triviale Aufgabe lösen

Ist es auch.

mein ViewModel habe ich von INotifyPropertyChanged abgeleitet.

Interfaces kann man nicht ableiten, nur implementieren.

Das Problem ist jedoch dass ich nicht direkt auf das ViewModel binden kann.

Ich denke Du machst etwas grundlegend falsch. Servus hat Dir bereits einen Link geschickt, wenn Du Dir den vielleicht doch mal durchlesen würdest, würdest Du auch Dein Problem lösen könne.

Ich denke hier passt auch [Hinweis] Wie poste ich richtig? 1.1.1

22.07.2010 - 16:32 Uhr

Den einzigen Unterschied den ich zu meinen Implementierungen sehe ist, dass Du die Validierung für die CanExecute Methode eben nicht wie bereits propagiert implementiert hast, aber das kann es nicht wirklich sein. Was ich noch anders habe ist in XAML ein umschließendes <AdornerDecorator> Tag. Aber das fixt bei mir ein anderes Problem.

22.07.2010 - 16:18 Uhr

Ich kann hier nicht auf user stellen, es sei denn, ich stelle den Typ auf String.

Wenn Du die Werte ändern möchtest dann musst Du das.

Aber dann kann ich den Quellcode gar nicht mehr nutzen.

Jupp, wie schon geschrieben macht man das auch nicht so, wenn man mit dem Designer arbeitet.

ich halte das ganze Prozedere ehrlich gesagt auch für ziemlich umständlich.
10 Zeilen Quellcode, um eine fundamentale Änderung durchzuführen.

Jupp, so wie Du das gemacht hast ist es das auch.

Was ist denn mit der selbstgestrickten .ini oder .config Datei
Hat das derat Nachteile ? Oder anders: welchen fundamentalen Vorteil bringt mir die app.config ?

Jepp, wenn Du die app.config benutzt, dann hast Du Werte direkt unter "Settings.Default", sonst nicht.

22.07.2010 - 15:37 Uhr

Nur die GUI zeigt keinen roten Rahmen an (was in diesem Fall ja von mir auch so gewünscht ist).

Ok, das ist aber ein anderes Problem! Wird denn bei der anderen Textbox immer ein roter Rahmen angezeigt? Wie sieht Dein XAML dafür aus?

22.07.2010 - 14:53 Uhr

Hast Du die Settings mit dem Designer erstellt oder per Hand? Ich würde den Designer nehmen, dann brauchst Du nämlich auch nicht über den ConfigurationManager zu gehen sondern kannst über "Settings.Default" Deine Werte lesen und auch schreiben, wenn Du im Designer den Scpoe auf "User" gestellt hast.

22.07.2010 - 14:44 Uhr

Ich halte es für Problematisch, wenn Du Deine Validierung an zwei verschiedenen Stellen (CanExecute und this[]) implementierst. Du hast dann schon mal das Problem dass diese beiden Validieren nicht unbedingt gleich sein brauchen und es verstößt gegen DRY. Besser ist es, wenn Du für die Validierung für Deine CanExecute Methode die IDataErrorInfo Funktionalität nutzen würdest. Implementiere folgendes:

        public string Error
        {
            get
            {
                var error = new StringBuilder();

                foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(this))
                {
                    var propertyError = this[propertyDescriptor.Name];
                    if (propertyError != string.Empty)
                    {
                        error.Append((error.Length != 0 ? Environment.NewLine : string.Empty) + propertyError);
                    }
                }

                return error.ToString();
            }
        }

Und prüfe dann Error auf String.Empty. Hast Du einen Error kannste den Output dann auch gleich als Fehlertext verwenden.

An .NET 3.5 kann es nicht liegen, denn ich verwende auch 3.5 und habe keine Problem. Was ich eher glaube ist, dass Du ein Problem mit der Validierungsmethode hast. Könnte es sein, dass Prop2 mit null initialisiert ist und Deine Validierungsmethode darauf "nicht richtig" prüft? Da ist der Fehler. 😉

22.07.2010 - 14:23 Uhr

Jedes normale Programm hat doch im Startmenü seinen Eintrag zur Deinstallation.

Sicher nicht. der Normalfall ist genau die Vorgehenweise über die Systemsteuerung.

19.07.2010 - 16:27 Uhr

Gar nicht.

Es wäre sicherlich ratsam die Files in Controls aufzusplitten.

19.07.2010 - 10:35 Uhr

Also ich entwickel ohne DI und bekomme auch ein 100% Code Coverage problemlos hin.

100% Code Coverage bekommt man immer hin auch ohne DI. Was sagt denn die Code Coverage aus?? Doch nur, dass der Code mindestens einmal durchlaufen wurde. Das bedeutet dann noch lange nicht dass auch richtig getestet wurde.

16.07.2010 - 16:32 Uhr

Hast Du Controls auf der Form? Dann hast Du das Problem, dass das Control welches den Focus hat das Tastenereignis abfängt - es kommt nie bei der Form an. schau Dir mal dazu die die AccepButton Eigenschaft an.

08.07.2010 - 16:20 Uhr

Der BackgroundWorker von .NET arbeitet mit SynchronizationContext.

08.07.2010 - 12:12 Uhr

Ok, jetzt habe ich verstanden was Ihr meint. 🙂 Klar, das kann nur gehen wenn er wieder castet und davon will er ja weg.

08.07.2010 - 12:05 Uhr

Schau Dir mal die Klasse SynchronizationContext an. Die hat eine Send-Methode mit der kannst Du zurück.

08.07.2010 - 11:59 Uhr

Das klingt so als ob immer beim vorherigen Test irgendwas noch nicht vorhanden ist. wenn Du auf Rhino.Mocks umsteigst kann ich Dir eher helfen, von NMock2 habe ich keine Ahnung.

08.07.2010 - 11:56 Uhr

extensions gehen nur für einen konkreten typen. hier hat er aber immer nur den basistypen und da würde dein konzept nciht greifen, es sei denn du machst das, was die foreach momentan tut in der extensionmethode, die auf die basisklasse angewendetet werden kann aber das wäre dann nur eine umlagerung des problems.

Natürlich geht das:


using System;

namespace ConsoleApplication
{
    public static class Extension
    {
        public static void Blubber(this IFutzelBase futzel)
        {
            Console.WriteLine("Blubber");
        }
    }
    
    public interface IFutzelBase
    {
        void Blah();
    }

    public interface IFutzel : IFutzelBase
    {
        void Blub();
    }

    public class Futzel : IFutzel
    {
        public void Blah()
        {
            Console.WriteLine("Blah");
        }

        public void Blub()
        {
            Console.WriteLine("Blub");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var futzel = new Futzel();

            futzel.Blah();
            futzel.Blub();
            futzel.Blubber();

            Console.ReadLine();
        }
    }
}

08.07.2010 - 10:50 Uhr

Ich denke ich würde eine Art Initialize Methode an alle Controls packen, wahrscheinlich als Extension und dort die spezifischen Aufgaben erledigen. So musst Du in Deiner Schleife immer nur die Initialize Methode (über's Interface) aufrufen. Brachst Du unterschiedliche externe Daten würde das aber nicht funktionieren.

07.07.2010 - 16:10 Uhr

Das wäre dann kein Unit Test sondern ein Integrationstest auf der entsprechenden Ebene.

Wie Du testest kommt ganz auf Deine Teststrategie an.

07.07.2010 - 15:36 Uhr

Dein Chef will vielleicht, dass Du das machst, aber Du brauchst die Bereitschaft Deiner Kollegen. Aus deren Sicht ist Ihr Chef unzufrieden mit Ihnen und deswegen kommt da so ein Weltverbesserer der angeblich alles besser weiß und Ihnen nun zeigen soll wie man in .NET Software entwickelt. Implizit haben sie die letzten Jahre und Jahrzehnte Ihres Lebens also nur sch.... produziert - Du bist ganz sicher herzlich willkommen und sehr beliebt.

Wenn Du auch noch (deutlich) jünger bist als Deine Kollegen und sie wirklich so stur sind wie Du sagst, dann brauchst Du Machtwörter (Mehrzahl!!) Deines Chefs. Da kannst Du Dich dann schon mal drauf einstellen, dass Du Dich von "unbeliebte Person" nach "unbeliebteste Person" steigern wirst.

Erteilt Dir Dein Chef Weisungsbefugnis (muahaha) damit sich überhaupt irgendwas bewegt, dann ist Dein bester Freund die Putzfrau - nichts gegen diesen Beruf ohne diese Leute bleibts dreckig.

Fazit:

Egal wie Du es drehst, Du wirst Dich hoffnungslos zum Affen machen und dafür straft man Dich mit Missgunst und Ablehnung. Oder Du bist "clever" und schwimmst einfach mit im Sumpf. So oder so, glücklich wird man so sicher nicht.

07.07.2010 - 14:43 Uhr

@FZelle: Doch das tut er. Haste da tips oder erklärungen^^?

Wenn Du jemals glücklich werden willst, wechsle die Firma, bei mir hats geholfen.

07.07.2010 - 13:40 Uhr

meisnt du vielleicht den aufruf zu .SuppressFinilize? oder meinst du wirklich .Collect ?

Ähm ja, ersteres. Ok, da habe ich was verwechselt.

Ist vielleicht nicht der Hauptzweck von Dispose: Aber wenn ein Objekt, welches auf Events von injizierten anderen Objekten hört, zertört werden soll, muss es ja eine Möglichkeit geben, die Events wieder auszutragen. Da kann man nun eine Methode "UnsubscribeEvents" machen, aber eigentlich ist doch Dispose auch ganz passend für diese Fälle.

Richtig, habe ich vergessen zu erwähnen - das mache ich immer in Dispose, ein anderer Weg ist mir noch nie unter gekommen.

IDisposable-Schnittstelle
Definiert eine Methode zur Freigabe von reservierten, nicht verwalteten Ressourcen.

Ich weiß ja nicht aus welcher MSDN Du das hast, aber wenn Du das aus der hier hast, dann zitiere bitte auch richtig:

...werden hauptsächlich nicht verwaltete Ressourcen freigegeben...

07.07.2010 - 12:34 Uhr

Oben schreibst du aber noch was von

Ich cleare Listen

Ich habe geschrieben, dass ich in der Dispose Methode Listen cleare - warum auch nicht - aber ich habe nicht geschrieben, dass ich IDisposable implementiere um Listen zu clearen - das mache ich ganz sichern nicht. Wenn ich aber sowieso schon eine Dispose Methode habe, warum sollte ich dann nicht alles "aufräumen"?

07.07.2010 - 12:30 Uhr

nicht notwendig. der garbagecollector geht immer alle referenzen durch und wenn die aktuelle klasse keinen weg zum root hat, dann wird der gesamte ast freigeräumt.

Es ist notwendig, wenn die Elemente darin ebenfalls Disposable sind.

das wiederrum ist garnicht sinnvoll. der gc weiß besser wann er zu laufen hat und wann nciht. so bringst du nur sein generationssystem durcheinander, was dich unmengen an performance kostet.

Das kann gut sein, aber ich arbeite mit FxCop und der verlangt dort ein expliziten Aufruf. Über den Sinn FxCop hier Rechnung zu tragen kann man wirklich streiten, aber oft wird FxCop verwendet um die Qualität von Code zu beurteilen und dann bin ich mit meinem Argument wieder im Geschäft. 😉

07.07.2010 - 12:19 Uhr

Hier ist ja auch noch was.
Vor allem der Beitrag von norman_timo:

>

Damit dürfte die Antwort "perfekt" sein. 😉

Absolut! In dem Post finde ich alle meine Argumente in ausführlicher Form wieder und sie werden auch bestätigt. 😉

07.07.2010 - 12:09 Uhr

puh... ok das ist wieder das andere extrem....
was amchst du in einer komplett verwalteten klasse im dispose?

Ich cleare Listen (gegebenenfalls Dispose ich deren Elemente), lösche Event Handler, rufe Dispose Methoden anderer Klassen auf und rufe explizit den GC auf.

Der FxCop schreit nach einer Dispose Implementierung wenn man in einer Klasse eine Resource hat die Disposable ist.

Warum sollte es noch andere Referenzen geben? Und wenn es sie tatsächlich gibt, dann doch wahrscheinlich, weil sie benötigt werden.

Ja das frage ich mich in manchen Projekten bei manchen Kunden auch immer. 😁 Nein, leider nicht. Defacto wird nicht überall sauber entwickelt. 🙁

PS: Also wenn in so kurzer Zeit soviele Leute unabhängig voneinander ins gleiche Horn stoßen, sollte dich das schon zum Umdenken bewegen.

Nein, nicht alle meine Klassen bekommen ein Dispose, das wäre tatsächlich Blödsinn. Aber vielleicht werde ich mir in Zukunft etwas mehr Gedanken darüber machen ob es wirklich sinnvoll IDisposable zu implementieren. Ich neige oft dazu manche Dinge aus Gewohnheit zu machen. Sicherlich kennt Ihr das auch, man entwickelt mit der Zeit Vorgehensweisen, man kann vielleicht sogar von "persönlichen Pattern" sprechen. 😉

erstellst du eigendlich auch einen destruktor @SeboStone ?

Nein.

07.07.2010 - 11:30 Uhr

damit hat er vollkommen Recht! Dispose braucht man im Prinzip nur für nicht-verwaltete Ressourcen; in anderen Fällen stört Dispose. Wenn ein Objekt solche nicht benutzt und auch keine Objekte verwendet, die IDisposable implementieren, sollte man selbst auch kein IDisposable implementieren, sondern die Arbeiten dem CG überlassen. Dispose ist eine (wacklige) Hilfskonstruktion, um in einer verwalteten Umgebung mit unverwalteten Ressourcen umgehen zu können.

Technisch gesehen ist das richtig. Ich implementiere es dennoch gerne, denn ich mag das using Kontrukt und ich möchte, dass das Objekt auch dann zerstört wird, wenn irgendwo doch noch eine Referenz des Objektes gehalten wird - solche lassen sich damit leichter finden.

06.07.2010 - 10:06 Uhr

Wenn Du eine neue Zeile hinzufügst macht das DataTable natürlich auch genau das und nichts anderes. Willst Du die entsprechenden Zellen füllen musst Du Dir die entsprechende Zeile suchen und dann über den Zellenindex die Zelle füllen. Alles ganz einfach.

05.07.2010 - 18:13 Uhr

Klar kannst Du das so machen, dann lieferst Du eben an Deine Kunden den ganzen Quatsch mit aus. Kannst die Lizensierungsprobleme ja dadurch umgehen indem Du NUnit verwendest.

Deine Argumentation ist nicht nachvollziehbar. Wer um Himmels willen hat solch aufwendige Prozesse? Da stellt man sich ein Versionskontrollsystem hin auf das jeder Zugriff hat und so hat jeder genau die Solution welche der andere auch hat. Und die Tests werden von einem BuildServer nach dem Einchecken (oder währenddessen, je nach System) durchlaufen. Lokal führt man Tests nur während der Entwicklung der Tests und zu Kontrollzwecken aus, aber nicht zur Validierung des gesamten Entwicklungsprozesses.

01.07.2010 - 14:03 Uhr

Den Owner brauche ich zb, um mir die position von geschlossenen childs zu merken.

Wenn Du das MVVM Pattern implementiert hat, dann wird alles was Du Dir "merken" willst über Bindings aus oder in das ViewModel übertragen, da braucht's dann keinen Owner mehr. Die Kommunikation zwischen zwei ViewModels sollte dann dort passieren wo die VieModel Instanzen gehalten werden, üblicherweise in einem Controller oder ähnlichem.

01.07.2010 - 13:33 Uhr

Sitzt Du in einer Domäne? Ist Dein User Profil auf einem Netzwerkserver? Dann sage dem Admin, er soll Dein Userprofil in ein lokales Userprofil ändern.

01.07.2010 - 13:30 Uhr

??? Dann wirst Du Dir wohl oder übel nochmal Gedanken über Deine Architektur machen müssen. Mit dem MVVM Pattern hättest Du z.B. keine Abhängigkeitsprobleme dieser Art.

01.07.2010 - 13:25 Uhr

Hast Du den Owner entfernt?

01.07.2010 - 13:16 Uhr

Dann erzeuge das zweite Fenster dort wo Du auch das erste Fenster erzeugst und zeige es auch von dort aus an. Damit sind beide Fenster "gleichwertig".