Laden...
S
spike24 myCSharp.de - Member
Programmierer Steiermark Österreich Dabei seit 01.02.2008 443 Beiträge
Benutzerbeschreibung

Forenbeiträge von spike24 Ingesamt 443 Beiträge

06.02.2011 - 13:57 Uhr

Welchen parktischen Hintergrund hat das was Du da schreibst?
Mir fällt beim besten Willen kein Grund ein, warum ich einen Thread wegen eines anderen nach 2 Sekunden schlafen schicken soll.

05.02.2011 - 11:56 Uhr

Hallo Leute,

Ich glaube das nennt man SmartClientLayer wo die BusinessObjects vorhanden sind.

Grundsätzlich geht es darum dass ich ein Transactionframework basteln will.
Ziel ist es Massenimporte und -bearbeitungen zusammenzufassen, bzw. einzelne BusinessObjects (mehrere veränderten Properties) gesamt zu speichern.
Die Usecases habe ich schon ausgearbeitet und auch schon einzelne Testmethoden geschrieben (1000 Zeilen).

Durch ein Gespräch mit Arbeitskollegen bin ich aber unsicher geworden ob ich auf dem richtigen Weg in der Benutztung bin.

Wie soll der Benutzer (Programmierer) das framework benützen können?
Ich schreib mal ein paar Beispiele damit ihr wisst was ich meine.

// neu erstellen
Adresse adresse = new Adresse();
adresse.Name = "New NameValue";
adresse.Commit(); // implzite Transaction am/beim BusinessObject

soweit meine Variante: das gleiche in der Variante meiner Arbeitskollegen.

// neu erstellen
Adresse adresse = new Adresse();
adresse.Name = "New NameValue";
TransactionPool.Commit(adresse);

Ich würde eben mit ExtensionMethods die Transaction-Methoden auf das BusinessObject hängen. bzw. an ein ITransactionableObject.
Mein Ziel ist es, eine Transaction nur dann angreifen zu müssen wenn ich sie auch zwingend brauche, zum Beispiel eine Massenbearbeitung

// massenbearbeitung
// geben ist eine List<Adresse>
Transaction transaction = TransactionPoolCreateTransaction(/*zwei bool Parameter*/);

transaction.Observe(adresses);

// hier bearbeitet man die Liste, wichtig: jedes BusinessObject muss Commited werden
adresses[0].Name = "New NameValue";
adresses[0].Commit();

transaction.Commit();

Was sagt ihr dazu, wie bedient sich das Framework besser?

15.11.2010 - 15:08 Uhr

das meinte ich, schlecht geschrieben.

Könnte man aber über Reflection lösen.
Allerdings müssten dann die abgeleiteten Klassen in der selben Assembly liegen, sonst können sie keinen internal-ctor haben ... ausser man verwendet das Attribut InternalsVisibleToAttribute.

15.11.2010 - 13:19 Uhr

Konstruktoren sind eh statisch? ähm ... nein
Es gibt static und instance Konstruktoren
Die statischen haben static davor stehen die anderen einen Accessmodifier (public, protected, internal, private)

@MarsStein
Ja, schön ist das nicht sonderlich (in meiner benutzung dieses constructs lese ich eine Assembly aus und befülle somit das Dictionary mit den elementen ohne sie zu kennen)
Ja die construktoren können internal sein, ging mir nur ums Prinzip.

//Edit, mich hats nicht in Ruhe gelassen
jetzt gibt es nur noch die unsauberkeit des statischen ctors, was ich bei mir ja anders gelöst habe.

  internal interface ICreateable<T> where T : Base<T>
  {
    T CreateInstance();
  }

  public abstract class Base<T> where T : Base<T>
  {

    private static Dictionary<Type, object> mFactories;

    static Base()
    {
      mFactories = new Dictionary<Type, object>();
      mFactories.Add(typeof(A), new A());
      mFactories.Add(typeof(B), new B());
      mFactories.Add(typeof(C), new C());
    }

    public Base()
    {
    }

    public static T Create()
    {
      if (SomeCondition())
      {
        ICreateable<T> factory = (ICreateable<T>)mFactories[typeof(T)];
        return factory.CreateInstance();
      }

      return null;
    }

    private static bool SomeCondition()
    {
      return true;
    }

  }

  public class A : Base<A>, ICreateable<A> // <- <A> nur bei Klassendeklaration nötig
  {

    internal A()
    { }

    A ICreateable<A>.CreateInstance()
    {
      return new A();
    }

  }

  public class B : Base<B>, ICreateable<B> // <- <B> nur bei Klassendeklaration nötig
  {
    internal B()
    { }

    B ICreateable<B>.CreateInstance()
    {
      return new B();
    }

  }

  public class C : Base<C>, ICreateable<C>
  {
    internal C()
    { }

    C ICreateable<C>.CreateInstance()
    {
      return new C();
    }

  }
12.11.2010 - 18:47 Uhr

oh, static, übelesen

    public interface ICreateable<T> where T : Base<T>
    {
      T CreateInstance();
    }

    public abstract class Base<T> where T : Base<T>
    {

      private static Dictionary<Type, object> mFactories;

      static Base()
      {
        mFactories = new Dictionary<Type, object>();
        mFactories.Add(typeof(A), new A());
        mFactories.Add(typeof(B), new B());
        mFactories.Add(typeof(C), new C());
      }

      public Base()
      {
      }

      public static T Create()
      {
        if (SomeCondition())
        {
          ICreateable<T> factory = (ICreateable<T>)mFactories[typeof(T)];
          return factory.CreateInstance();
        }

        return null;
      }

    }

    public class A : Base<A>, ICreateable<A> // <- <A> nur bei Klassendeklaration nötig
    {
      public A CreateInstance()
      {
        return new A();
      }
    }

    public class B : Base<B>, ICreateable<B> // <- <B> nur bei Klassendeklaration nötig
    {
      public B CreateInstance()
      {
        return new B();
      }
    }

    public class C : Base<C>, ICreateable<C>
    {
      public C CreateInstance()
      {
        return new C();
      }
    }

aber von schön sind wir nun auch schon ein Stück weit entfernt.

//Edit: man sollte builden bevor man postet
// Edit 2: Ups, sorry!

12.11.2010 - 17:13 Uhr

Schuss in den Nebel:

public abstract class Base<T> where T : Base<T>
{
    public Base()
    {
    }

    public static T Create()
    {
        if (SomeCondition())
            return CreateInstance();

        return null;
    }

    protected abstract T CreateInstance();

}

public class A : Base<A> // <- <A> nur bei Klassendeklaration nötig
{
  protected override A CreateInstance()
  {
    return new A();
  }
}

public class B : Base<B> // <- <B> nur bei Klassendeklaration nötig
{
  protected override B CreateInstance()
  {
    return new B();
  }
}

public class C : Base<C>
{
  protected override B CreateInstance()
  {
    return new B();
  }
}

public class Program
{
    public static void Main()
    {
        A x = A.Create(); // <- kein <A> mehr nötig
        B x2 = B.Create(); // <- kein <B> mehr nötig
    }
} 

// EDIT Copyright MarsStein

12.11.2010 - 15:08 Uhr

Das werfen des Events passiert immer am GUI thread, wo sonst.
das abhandeln könnte man aber in einem Thread auslagern, damit der GUI thread wieder frei ist für das nächste Event. dann könnte auch mein Vorschlag greifen.

12.11.2010 - 14:43 Uhr

Gui Events: ja

12.11.2010 - 13:16 Uhr

bin mir jetzt nicht sicher ob ich es richtig verstanden habe aber:

private object SelectionHandlerLock;
private bool mTheNextIsHere;
private object mTheNextIsHereLock;

private void SelectionHandler(object src, AutomationEventArgs e) 
{
  lock (mTheNextIsHereLock)
    mTheNextIsHere = true;
  lock(SelectionHandlerLock)
  {
    lock (mTheNextIsHereLock)
    {
      if (mTheNextIsHere)
        return;
      mTheNextIsHere = false;
    }

    // Berechnungen
    if (mTheNextIsHere) // hier kein lock notwendig (zumindest kein muss)
      return;
    // diese Abfrage kann so oft vorkommen wie Du es brauchst.
    // Berechnungen
  }
}

so schmeist der nachfolgende Thread den vorigen raus

12.11.2010 - 12:58 Uhr

Wie brings du es zusammen dass die Events warten?
Bist Du singlethreaded unterwegs?

08.11.2010 - 12:37 Uhr

Ich würde da auch in die Kerbe von gfoidl schlagen.

Jede Datenbank die ich gesehen welche die Variante 1 implementiert hat, hat genau bei diesem Punkt Probleme gemacht. Es war dann alles irgendwie lösbar, aber halt irgendwie.

In Deinem Fall unwahrscheinlich aber was ist wenn man 15 verschiedene Typen an ein Paket hängen kann? Wieviele Spalten sind dann in der einen "magic" Tabelle und wieviele sind davon leer? Dann kommen irgendwelche Blitzkneisser daher und meinen man könnte ja gewisse Spalten reusen ... denen sollte man dann am besten die Tastatur wegnehmen.
(Welche Informationen werden zu einem Mail gespeichert? KlickKlick und man sieht eine Tabelle mit z.b. 80 Spalten und Spalte 3, 8, 19, 33, und 45 gehören zum Typ Mail)

Bei Variante 2 bekommt man zwar einige Tabellen zusammen, aber es entspricht der 3. Normalform und es ist um einiges überschaubarer.
(Welche Informationen werden zu einem Mail gespeichert? KlickKlick und man sieht eine Tabelle mit z.b. 5 Spalten)

(3. Normalform sollte in jeder Datenbank Standard sein.)

08.11.2010 - 09:51 Uhr

@marco.b
Die Alternative wäre nichts zu fragen ... jetzt auch nicht die beste Lösung.

eben meiner Erfahrung nach gehts ja auch nicht primär darum das man ein .Net guru ist sondern wie tut der Bewerber. wie redet er, wie sicher ist er und man erkennt auch bei Kindergarten fragen ob er was verstanden hat.
Und wie geht er mit den Dingen um wo er sich nicht auskennt.

05.11.2010 - 15:39 Uhr

Bei meinem letzten Vorstellungsgespräch bekam ich code auf einer A4 Seite vorgelegt, ein bisschen Zeit diesen durchzulesen und danach wurden mir dazu fragen gestellt.
Was ist ein ctor, wo ist er, wann wird er aufgerufen

welche methode ist als überschreibbar definiert, wo ist die Eventhandler Methode.
Woran erkenne ich das diese klasse von einer anderen ableitet.
Was bedeuted dieses schlüsselwort. und kompiliert der Code?

Also eher triviale Fragen hatte auch alle richtig bis auf "kompiliert der Code" da ich das schlüsselwort new nicht kannte (ich war vb programmierer)

Und dann wurde ich noch relative viel im Bereich datenbanken ausgequetscht. wie erstellt man eine Tabelle, ein Feld, wie löscht man eine Tabelle.
Wie ist die Syntax von einem Insert oder Update. Was ist ein JOIN und was ist der unterschied von LEFT JOIN zu INNER JOIN.

Da ich damals recht viele Interviews hatte, kann ich noch sagen, es ist nicht so wichtig dass man 100% der Fragen richtig hat, sondern eher wie geht man mit Fragen um die man nicht beantworten kann. Beschreibt indirekt Dein Verhalten in Stresssituationen.

Also 80% richtig beantworten, vielleicht mit privaten Arbeiten punkten, das mögen unternehmen sehr wenn man sich auch privat weiterbildet. und bei den 20% die man nicht weis einfach locker bleiben
Der der mit Dir das Vorstellungsgespräch führt kocht auch nur mit Wasser.

good luck.

//EDIT: und ganz wichtig, nicht zu weit aus dem Fenster lehnen. Manchmal wird einem da eine Falle gestellt und dann muss man felsenfest wissen von was man redet.

20.10.2010 - 16:10 Uhr

Kann sein dass ich Deine Frage nicht richtig verstanden habe, aber zur Imitation eines Servers verwende ich einen Mock (NMock2)

Bei dem gibt man an welches Interface er "mocken" soll und welche Methodenaufrufe man erwartet.
Zumindest habe ich eine komponentenbasierte Andwendung und mache es so.

16.10.2010 - 17:47 Uhr

Dann gäbs ne Möglichkeit, die nennt sich Verlinken

Es gibt ein Projekt in der Assembly A mit einer Klasse ClassA

public partial class ClassA
{
}

in der Assembly B wird das File als Link eingefügt und dann kann man im erstellten File ClassA.Customer {0} schreiben

public partial class ClassA
{
}

der Nachteil daran, Programmierer B kann Assembly A verändern
(kann man mit SVN commit Regeln verhindern)

16.10.2010 - 11:16 Uhr

Ich kenne mich bei Serverdatenbank Systemen nicht so gut aus, aber könnte man nicht einen Trigger beim "GetRow" "Event" ranhängen? (zumindest gibt es ein BeforeUpdate)

Beim View-Problem würde ich mir die ganzen SqlStatements in ein File lassen und mit RegEx einen Parser schreiben der mir durchsieht wieviele Views es gibt und danach mit Find sucht wo sie überall verwendet werden.

15.10.2010 - 10:46 Uhr

steht dem der Assembly B programmiert der SourceCode von Assembly A zur Verfügung?

14.10.2010 - 09:35 Uhr

Du wirst nicht daran vorbeikommen für die Anzeige eine eigene "Datenschicht" zu basteln.

Ich würde eine List<T> nehmen und eine Klasse schreibe die die Properties hat die Du gerne im DGV siehtst.
Beim Aufbau der GUI für jeden Tag eine Instanz erstellen und in die List<T> rein stecken. Danach die Daten laden und die Werte in das entsprechende Element reinstecken (eben beim richtigen Datum)
Wenn der Kunde dann bei einem Datum was einträgt könntest Du mit dem INotifyPropertyChanged interface die ganze Sachen nach aussen Triggern damit in der Datatable auch eine neue Row angelegt wird, bzw. bei einem bestehenden Datensatz die Werte entsprechend verändern.

Direkt "magic" neue Datensätze auf dem Weg vom DataTable zur Gui zu "erfinden" fällt mir keine Möglichkeit ein.

04.10.2010 - 16:40 Uhr

In welchem UseCase wird benötigt, dass ein Doppelklick-Event vom Code aus so geworfen wird dass es aussieht als hätte der Benutzer selbst doppelgeklickt?

17.09.2010 - 15:49 Uhr

gegen das wachsen hilft
dieser Link

mitliefern muss man nichts, glaube ich halt, man braucht nur MDAC und das ist schon standarmässig überall dabei.

ist .mdf nicht SQL-server?

17.09.2010 - 09:44 Uhr

Wenn man 0 installationsaufwand haben will, bietet sich Access an.
Ich weis nicht was die Leute gegen Access haben, ich arbeite seit gut 10 Jahren damit und bin äusserst zufrieden. Hat eine brauchbare Geschwindigkeit, Sicherungen erstellt man mit copy/paste und hat ne replikation die funktioniert.
Bei einem "unter 10-Mann" Unternehmen würde ich nie was anderes installieren.

16.09.2010 - 10:50 Uhr

Ich glaube nicht, dass es eine Frage des "Sterbens" einer Sparte ist.
Besitze beides, PC und Konsole (PS2)
und wie hier schon erwähnt wurde kommt es auf die Art des Spieles an
Spring könnte ich nie auf einer Konsole spielen, die Steuerung reicht dafür einfach nicht aus.
Allerdings GT4 könnte ich mir nie auf einem PC vorstellen, dafür brauche ich einfach auch das Feeling.

Denke einfach dass es sich Hype-technisch einmal in diese Richtung und dann wieder in die andere Richtung dreht, wobei man am Rande anmerken muss, irgendwie gehen den Spiele entwicklern am PC die Ideen aus. 😦

09.09.2010 - 09:20 Uhr

Ich glaube da gibt es 2 passende Möglichkeiten,
einerseits im Rahmen eines Unittest übergibt man im ctor das eine benötigte Interface als Mock, dann wäre es ein "sauberer" Unittest.

Andererseits machst Du ja Integrationtests, also Tests mit lebenden Daten für das würdest Du aber auch einen "lebenden" IIndexServer benötigen welchen Du dir über IoC holst.

Bei genauerem Überlegen würde ich mit dem Argument, wenn schon IntegrationTest dann richtig, die zweite Variante empfehlen.

Gehen tut aber beides.

08.09.2010 - 12:52 Uhr

richtig, sorry, aber beide Arten von cast brauchst Du nicht, es genügt das 'as'

und wenn das so gewollt ist, ich kenne natürlich nicht die genauen Anforderungen dann wird der code auch so passen.

Aber generell, wenn ich so einen Code schreibe, denke ich nochmal darüber nach ob ich nicht die Anforderungen an die Suche umgestalten kann.

07.09.2010 - 13:49 Uhr

Keine Antwort* nehme ich als ja
Aber so kann ich das nicht aktzeptieren, habe mir da bei meinem privaten Projekt was ausgedacht und wenn ich es mal niedergeschrieben habe werde ich es hier kundtun.

* mir ist schon bewusst dass man nicht immer sofort Zeit hat zu antworten, aber ein "nein, man macht das so" wäre recht schnell geschrieben und die Diskussion hat nicht so ausgesehen als gäbe es da ein standardverhalten.

07.09.2010 - 09:39 Uhr

also einerseits finde ich

        public static Repository<T> Create()
        {
            if (typeof(T) == typeof(News))
                return (Repository<News>)new NewsRepository() as Repository<T>;
            return new Repository<T>();
        }

relative umständlich
ein

return new NewsRepository(); 

reicht da vollkommen.

und bei einem where T: class bin ich auch leicht irretiert, das ist gerade soviel Einschränkung dass keine Valuetypes genommen werden können, aber dennoch sehr nahe bei object.
Ist das ein gewünschtes Verhalten?

06.09.2010 - 13:20 Uhr

d.h. mir bleibt nichts anderes über als mit der Hand alle Spuren von IConnector nachzuprüfen und in den Tests (vom ObjectStoreService) die Mocks nachzubessern?

06.09.2010 - 12:53 Uhr

?
Ich glaube Du hast mich missverstanden und/oder ich schlecht erklärt.

Das Verhalten der Klasse Connector hat sich geändert.
bei einem string alá "SELECT LfdNr_Adr, Adr_Name FROM Adressen WHERE LfdNr_Adr = 1" kam früher ein DataTable mit einer Zeile und 2 Spalten.
Jetzt kommen 2 Zeilen und 4 Spalten.

die Tests der ParentKlasse (ObjectStoreService) mocken das Interface IConnector und haben von dieser Änderung grundsätzlich keine Ahnung, da sich das Interface ja nicht verändert hat und sie haben eigentlich auch keine Ahnung von der Klasse Connector. Und da diese Tests für den Mock die Ergebnisse selbst zusammenbauen werden sie von der Änderung in der Klasse Connector nie erfahren.

die Tests für die Klasse Connector wurden natürlich angepasst da sie fehlerhaft waren.

Aber wie kann ich sicherstellen dass die Test des ObjectStoreService vom veränderten Verhalten der Klasse Connector erfahren?

06.09.2010 - 11:16 Uhr

Ok, so sehe ich das auch.

Aber wie würden die Tests richtig geschrieben sein?

01.09.2010 - 15:42 Uhr

Frage:
Wie löst ihr folgendes Problem, bzw. löst ihr es überhaupt?

Folgendes Szenario:
es gibt ein public Interface gegen das UnitTests geschrieben sind

public interface IConnector
{
  DataTable SomeMethod(string bla);
}

Implementiert wird dieses interface von der Klasse, nenne es mal Connector.
Und es gibt mehrere Klassen die dieses Interface benützen (damit ist nicht implementieren gemeint, sondern wirklich benützen, z.b. über IoC resolved)
Nennen wir eine dieser Klassen ParentClass

zu denen (dieser) gibt es ebenfalls Unittests, welche dieses Interface richtigerweise NICHT instanzieren* sondern mocken (ich verwende NMock2)

In den Tests für die ParentClass wird der returnValue immer wieder neu zusammengebaut. Eben welcher Wert in 'bla' drin steht so sieht dann auch der returnValue vom Type DataTable aus (nicht so wichtig was da drinn steht)

Soweit die Vorgeschichte.

Nun kommt die Aufgabe: "Baue die Klasse Connector um" und daraus ergibt sich einen Änderung im Aussehen der retunierten DataTable (Rows oder Columns oder was auch immer)

Die Unittests des Interfaces IConnector, bzw. der Klasse Connector wurden entsprechend angepasst weil sie ja fehlschlugen.
Allerdings die Tests der Klasse Parent funktionieren mit der alten Struktur (sie werden ja in jedem Testcase neu erstellt) weiterhin und damit treten die Fehler erst in der Laufzeit des Programmes auf und die Anwendung kackt fürchterlich ab, obwohl alle Tests funktionieren.

Wie geht ihr mit diesem Problem um?

* die Klasse die das Interface implementiert.

25.08.2010 - 10:01 Uhr

Ich glaube Befürworter und Gegner reden hier generell nicht von der gleichen Sache.

Es sei dahingestellt welcher Gruppe ich angehöre.

Die Befürworter sagen, ja wo ist das Problem, man sieht die Häuser nur von vorne und es sind keinen Personenbezogenen daten und blablabla.
Die Gegner werden wahrscheinlich selbst feststellen, dass es eigentlich nicht so eine grosse Sache ist was GSV da so macht, aber denoch dagegen sein.

Sie sind, so meine Vermutung, ja auch gegen GSV sondern gegen die Art und Weise wie auch die Menge.
Und unter Menge verstehe ich, wir die Bevölkerung haben keinen Einfluss mehr wer unsere Daten bekommt. Und da geht die "Gefahr" ja nicht nur von Goggle aus sondern alle Daten sammelnden Unternehmen (fällt mir gerade nichts ein ausser der Staat).
Klar bei den SN (Facebook) geben wir unsere Daten freiwillig her, aber es gibt in Summe schon soviele Stelle die über Teile unserer Daten verfügen dass irgendwann mal einen Grenze erreicht ist. Und für diesen Fall gibt es keine Argumente die ein Befürworter nicht in 2 Minuten erledigen kann. (Wenn GSV gegangen ist wird wohl bla auch noch gehen)

Wir, jetzt kommt das Outing, haben nicht vor GSV Angst, sondern wir haben das Gefühl dass eine gewisse Grenze/Hemmschwelle überschritten ist und keiner hört zu.

Soweit die Lesung aus meinem Kopf

24.08.2010 - 14:04 Uhr

Ja, er ist der Pappenberg

ich habe seine Frage so verstanden dass er alles in einer Klasse haben will und da würde es sich ja so anbieten.
Das mit der Schleife (while()) war eigentlich so gemeint (schlecht beschrieben) dass er, wenn er die Verzeichnisse rekursiv durchgeht, er ja irgendwo eine Schleife haben muss, diese war gemeint

BGW kenne ich blöderweise nicht so, ich arbeite meist mit echten Threads, bzw haben wir einen eigenen Threadpool geschrieben (lange Geschichte warum) und somit bin ich da in der eigentlichen Verwendung nicht mehr so fit.
Aber den BGW werd ich mir wohl mal reinziehen müssen ...

23.08.2010 - 18:01 Uhr

Ich glaube er meint das ein so.

    public class FilebasedSearcher
    {

      private BackgroundWorker mWorker;
      private bool mKeepRunning;

      public FilebasedSearcher()
      {
        mWorker = new BackgroundWorker();
        mWorker.DoWork += new DoWorkEventHandler(mWorker_DoWork);
        mKeepRunning = false;
      }

      public void Start(string folder)
      {
        mKeepRunning = true; // MUSS vor dem starten des BGW stehen!
        mWorker.RunWorkerAsync(folder);
      }

      public void Stop()
      {
        mKeepRunning = false;
      }

      private void mWorker_DoWork(object sender, DoWorkEventArgs e)
      {
        while (mKeepRunning)
        {
          // hier Deine Suche 
        };
        // hier das Event werfen dass er fertig ist, oder eben das Event vom mWorker nutzen
      }

    }

Somit hast Du eine Asyncrone Klasse vom dem der Aufrufer nichts weis und du es ohne Probleme wieder verwenden kannst.
Hint:
Mit einem Dictionary<string, BackgroundWorker> können man mehrere Suchen parallel implementieren.

//EDIT:
wer nicht klar im Kopf ist muss 2x editieren

17.08.2010 - 09:26 Uhr

Du kannst aber auch, ich weis nicht ob das praktikabel für Dich ist, aus einem string eine Dll erstellen

@"namespace bla
{
  public class Test
  {
    public Test()
    {
    }
  }
}"

und diesen string kann man auch dem CodeDom geben und der macht daraus eine dll.

17.08.2010 - 09:23 Uhr

🤔
Du hast ein Interface, suchst jedesmal eine Methode die offensichtlich vorhanden sein muss und die Methode ist nicht im Interface deklariert?

Ich würde da eher her gehen und im Interface diese Methode deklarieren (als Parameter ParameterBase) und der aufgerufene soll sich die instanz auf den entsprechenden Typen casten.

09.08.2010 - 09:13 Uhr

Also meiner Erfahrung nach hat die anzahl der Spalten in einer Query relativ wenig Auswirkung auf die Geschwindigkeit (in Relation zu allen anderen Aufgaben die für das Holen der Daten notwendig sind)
Ausser die Query ist extrem komplex.

09.08.2010 - 08:43 Uhr
where T : class

sollte da nicht

where T : IPlugin

hin?

06.08.2010 - 09:18 Uhr

Mir ist es ziemlich egal wer wohin rennt, solange ich nicht nachrennen muss.
(Für die Frauen unter uns: euch schon garnicht)

automatisch zu einer nicht änderbaren und damit öffentlichen Funktion

öffentlich im Sinnen von public class oder im Sinne von hervorgehoben und gut dokumentiert aber internal class?

05.08.2010 - 09:27 Uhr

aus einer anderen Welt ist gut

Wie herbivore sagt, bin ich auch der Meinung dass man nur öffentliches testen muss (soll?)
Wenn ich in einer Assembly nur eine Klasse habe die public ist, ist sicherzustellen dass diese ihr Verhalten nicht ändert.

Bei meinem Projekt (ORMapper) teste ich "momentan" nur klassen die ein öffentliches Interface impelementieren ... eigentlich könnte ich alle anderen klassen dann internal machen aber das ist ein anderes Thema.
ein Interface ist IConnector
und beim testen ist es mir eigentlich komplett egal woher er die daten bekommt, aus der lokalen Access datenbank oder über csv aus China und welche klassen er dafür braucht. Bei der Verwendung muss ein richtiges DataTable rauskommen.
Also privates zu testen ist vielleicht nicht sinnlos aber zuviel und unötig

In meinem Beispiel ist es eigentlich nur deswegen sinnvoll da ich sonst die doppelte Anzahl von tests gehabt hätte und ich im endeffekt zu faul war diese zu schreiben, bzw. wenn sich das XML ändert diese zu warten.
sonst halte ich auch nicht sonderlich viel davon. Ich würde mich bei einer zentralen internal Klasse vielleicht noch breitschlagen lassen wenn diese von vielen Stellen benützt wird. Aber da auch nur die Fehlerfälle damit ich diese Tests nicht bei allen x public klassen schreiben muss (d.h. Testanzahl verringern)

//Edit
@Stefan O.
Wenn private und/oder internal klassen nicht durch das testen der öffentlichen Klasse verwendet werden ... wann werden die denn sonst verwendet?

04.08.2010 - 13:56 Uhr

@FZelle
Es ist eh nicht eine einzelne Methode, weis es zwar nicht mehr genau, aber soweit ich mich errinnern kann gibt es für jeden NodeType in dem XML eine eigene Methode. oder so ähnlich. Eine Methode alleine hätte den Review eh nicht geschafft.

Kann es sein, dass es Dich gibt seit dem ich programmiere?

04.08.2010 - 13:00 Uhr

In meiner "langen" Zeit als Programmierer wo ich auch Test schreiben "muss" hat es bis jetzt nur einen Fall gegeben in der es angebracht war eine private Methode zu testen.
diese eine Methode wurde von 2 public aufgerufen und hat selbst ein mehr oder weniger kompliziertes XML überprüft und an gut 15 Stellen Exceptions geworfen
Ergo wenn ich nur die public Methoden getestet hätte, hätte ich original die Testmethoden kopiert und alles wäre 2 mal dagestanden.

Bei meinem privaten Projekt gehe ich "momentan" einen anderen Weg:
Ich teste nur Klassen die ein public Interface implementieren.
und das nicht als Unittest, sondern als Integrationstest mit Abhängigkeiten

Beispiel:
eine Klasse implementiert IConnector und hat 2 Methoden
hier teste ich mit allen möglichen richtigen Aufrufen und speichere das Ergebniss in einem XML File. (die Aufrufe die Exception produzieren müssen noch nachgeliefert werden, habe im Schnitt alle 30 Zeilen ein TODO stehen 😃 )
eine Klasse implementiert IObjectStoreService welche im ctor einen IConnector bekommt.
Diesen IConnector Mocke ich (NMock2) und bei den Expections lade ich als Rückgabewert die XML-Files der IConnector-Tests.
Somit teste ich die IObjectStoreService-Klasse mit realen Werten ohne eine "direkte" Abhängigkeit zu haben.

Ich habe eingangs geschrieben "momentan", mir ist bewusst dass sich meine Teststrategie ändern wird (z.b. mehr Richtung Unittesting) aber mit diesem System habe ich alle bekannten Probleme beim Testschreiben erschlagen.

Zurück zum Thema:
private Methoden zu testen macht insofern wenig Sinn wenn diese private Methode bei der KaffeeQualität was auszusetzen hat wirft sie eine Exception. Gut, und was macht die Methode die die private Methode aufruft mit dieser Exception?
d.h. Du musst für die public den gleichen TestCase nochmal schreiben nur um sicherzustellen das die Methode die Exception nicht fängt sondern weiterrasseln lässt.
Noch umständlicher wird es bei 2 public Methoden
z.b. value GetValue(key) und bool TryGetValue(key, out value)
da brauchst Du für KeyNotFoundException 3 tests.

wie gesagt in den letzten 3 Jahren habe ich eine private Methode getestet und da haben wir gute 30 Minuten darüber diskutiert ob das wirklich sein muss.

02.08.2010 - 15:33 Uhr

Also das mit den Raubkopierern könnte man auch anders lösen.
Mein letztes Spiel das ich mir gekauft habe war C&C schiess mich tot und hat 60€ gekostet.
Und ehrlich gesagt, wenn ich mit meiner Freundin Multiplayer spielen will sind mir 120€ zuviel auch wenn das Spiel absolut super ist (meiner Ansicht nach)

Wäre interessant heraus zu finden, wenn man bei der Spiele entwicklung komplett auf den Kopierschutz pfeift den Preis noch ein bisschen drückt und dann in der Nähe von 25€ landet, ob dann mehr Leute das Spiel kaufen so dass sich im Endeffekt wieder alles hereinspielt. Um 50€ oder 60€ (In Summe) kaufe ich mir schon ein Spiel zweimal, und die CD kosten eines Spieles werden den Preis ja nicht ausmachen.

Auch wenn der Preis von 39€ voll ok ist für das Spiel (habs bei einem Freund gespielt) finde ich Online-Aktivierung die falsche Richtung.

26.07.2010 - 13:00 Uhr

Kann sein dass ich zu spät dran bin, aber:
soweit ich das verstanden habe sind in deinem "StartObjekt" Koordinaten eines Punktes drin.
Weiters ist auch die Qualität drin (was auch immer Qualität bedeutet)
Dein Problem ist dass Du einen Punkt (StartObjekt) mit verschiedenen Qualitäten brauchst.
was hältst Du davon wenn Qualität ein eigenes Object wird, initialisiert mit:

Qualität qualität = new Qualität(3);

und dass als Schlüssel in einem Dictionary benützt

dictionary.Add(qualität, startObjekt);

somit hättest Du jedem Punkt eine Qualität verpasst ohne dass Du Dein StartObjekt verändern muss (somit musst du es nicht mehr kopieren)

26.07.2010 - 11:02 Uhr

Abgesehen davon, dass man sich darüber gedanken machen sollte ob man das wirklich braucht, könnte man die Methode zu einer void machen und den ehemaligen Rückgabewert in einem out Parameter verstecken.

int RechneWas(double zahl1, double zahl2)
double RechneWas(double zahl1, double zahl2)

wird zu

void RechneWas(double zahl1, double zahl2, out int result)
void RechneWas(double zahl1, double zahl2, out double result)

dann ist die Signature auch eine andere

15.07.2010 - 12:01 Uhr

Aja, aber an das habe ich beim Besten willen nicht mehr gedacht.

[Dass ich mich im ctor zu statischen Events hänge]

15.07.2010 - 09:27 Uhr

Haha

Ihr werdet nie draufkommen was es war!
Ich habe mein Projekt einem Arbeitskollegen von mir gegeben der bei uns seit neuem die Tests über hat und der hats gefunden.
Im ctor der Klasse ObjectStoreClient melde ich mich bei den Events einer statischen Klasse an. Da aber der ObjectStoreClient kein Dispose hat meldet sie nie jemand ab und somit hat er beim zweiten Test 2 Events die im Endeffekt beim Mock vorbeilaufen.

Der Klasse ObjectStoreService ein Dispose verpasst wo ich mich bei den Events wieder abmelde und es funkt.

Danke für die Unterstützung.

12.07.2010 - 09:34 Uhr

So, jetzt schnalle ich es überhaupt nicht mehr!
Jetzt funktionieren 2 Tests. Aber keine Ahnung warum.
Seiteneffekte sind es nicht, da die Reihenfolge der Tests egal ist (OrderedTests)

Hmm, ich kann euch jetzt keine Hinweise mehr liefern die euch helfen könnten mir zu helfen.

Ich rücke mal mit einem Stückchen Code raus, vielleicht bin ich auch nur zu blöd.

    [TestMethod]
    [DeploymentItem("oRRoSoft.Customizable.DtoDescriptions.dll")]
    public void GetBusinessObjectList_SimpleToN()
    {
      mMock = new Mockery();

      mObjectStoreServerMock = mMock.NewMock<IObjectStoreServer>();

      mObjectStoreClient = new ObjectStoreClient(mObjectStoreServerMock);

      List<Dto> simpleToNDtos = TestResults.LoadDtos(GetObjectStoreResultFileName("GetDtos_SimpleToN_Lazy.xml"));
      Expect.Once
        .On(mObjectStoreServerMock)
        .Method("GetDtos")
        .With(new QueryMatcher(new Query(typeof(SimpleToNDto))))
        .Will(Return.Value(simpleToNDtos));

      List<Dto> toNChildDtos = TestResults.LoadDtos(GetObjectStoreResultFileName("GetDtos_ToNChild_Parent_1.xml"));
      Query query = new Query(typeof(ToNChildDto));
      query.Parameters.Add("Ansp_LfdNr_Adr", 1);
      Expect.Once
        .On(mObjectStoreServerMock)
        .Method("GetDtos")
        .With(new QueryMatcher(query))
        .Will(Return.Value(toNChildDtos));

      BusinessObjectList<SimpleToN> simpleToNs = mObjectStoreClient.GetBusinessObjectList<SimpleToN>();

      SimpleToN simpleToN = simpleToNs[0];

      ChildRelation<ToNChild> to1Childs = simpleToN.Childs;

      Assert.AreEqual(2, to1Childs.Count);

      mMock.VerifyAllExpectationsHaveBeenMet();
    }

Die Klasse TestResults lädt Testergebnisse vone anderen Test (in diesem Fall von der TestKlasse ObjectStoreService) um den Mock mit "echten" Rückgabewerten zu versehen.

08.07.2010 - 16:48 Uhr

Und, so weit meine Erkenntnis, nur weil einer kompletten Bullshit programmiert heist das noch lange nicht, dass er keine guten Ideen hat.

bin immer wieder selbst über meine Ideen erstaunt 😃

08.07.2010 - 15:32 Uhr

Ja, sieht schwer danach aus, hab aber keinen

es gibt zwei globale Vars
den Mockery und einen Mock vom Typ des Interfaces mit der die zu testende Klasse redet.

der Fehler ist eine 'unexpected innvocation of ': Exception mit der Methode die eben auf dem Mock ausgeführt werden soll.

Ich werd mal probieren für jeden test einen eigenen Mockery und eigenen Mock zu erzeugen. Es wird dann wahrscheinlich gehen und ich wundere mich warum die anderen 75 Test funktionieren (die einen Mockery benutzen und alle nach dem gleichen Schema aufgebaut sind)

08.07.2010 - 12:46 Uhr

Ja, so sieht es aus, aber da passt alles soweit ich es kontrolliert habe.
Was auch dagegenspricht ist dass ich in jeder TestMethode ein VerifyAllExpectations habe, was ja sicherstelt dass nicht von einer TestMethode in die nächste wandert.