Laden...

Profil von Traumzauberbaum

myCSharp.de - Member Mitglied seit
T
Traumzauberbaum
myCSharp.de - Member
10
Themen
512
Beiträge
Dabei seit
25.04.2006
Letzte Aktivität
vor 18 Jahren
Erstellt vor 18 Jahren

An sich ist das keine Redundanz, sondern nur unterschiedliche Zugriffspfade. Einmal hat man den Zugriffspfad über die Spielfelder, oder man hat den Zugriffspfad über den Spieler, aber es ist ja immer die selbe Spielfigur.

Also eine Art Index. Natürlich kann das Sinn machen, es hängt davon ab wie gut die einzelnen Zugriffspfade auf deine Anwendung passen. Es ist zum Beispiel eigentlich immer Sinnvoll einen Zugriffspfad über das Spielfeld zu haben. Man will ja ziemlich oft auf Kollisionen testen. Manchmal will man aber auch für alle Figuren eines Spielers eine bestimmte Aktion ausführen (sie sollen blinken z.B.), dann ist der Zugriffspfad über den Spieler natürlich der bessere.

Redundant wird es eigentlich erst dann, wenn man z.B. im Spielfeld speichert, wo die Spielfigur ist, und in der Spielfigur speichert, auf welchem Feld sie sich befindet. Oder zu welchem Spieler gehört die Figur, und welche Figuren gehören dem Spieler. Dann hat man die Informationen doppelt vorliegen, und muss dann dafür sorgen, dass die Daten konsistent bleiben. Das ist an sich aber auch unkritisch. Problematisch kann es dann werden, wenn mehrere Threads gleichzeitig auf den Daten arbeiten.

Erstellt vor 18 Jahren

Du könntest auch einfach die Dienste auf manuell stellen und eben nur starten, wenn du sie brauchst. Z.B. als "External Tools" das Starten aller benötigten Dienste ablegen.
Mein Notebook ist um Welten schlechter als deines, reicht aber locker als Entwicklungsumgebung mit VS 2005 Professional und SQL Express 2005 und teilweise auch noch Oracle Express, was alleine schon meinen ganzen RAM frisst. Klar braucht er manchmal etwas, aber das liegt im Sekundenbereich und ist wirklich zu verkraften. Also daran liegts schonmal nicht, oder deine Ansprüche sind zu hoch 😉

Erstellt vor 18 Jahren

Ein Weblog hat mich auf den Gedanken gebracht. Was haltet ihr für die größten Sünden die so in der Programmierwelt verbreitet sind?

Ich leg mal zum besseren Verständniss ein paar Beispiele vor:

Premature Optimization

Heute hab ich doch tatsächlich in einem msdn Forum die Frage gelesen:
Was ist effizienter StringBuilder.AppendLine() oder StringBuilder.Append( Environment.NewLine ) ?
Aber das ist ja eigentlich noch ein harmloses Beispiel. Schlimm wird es dann, wenn man ganze Verwaltungsstrukturen aufbaut und vermeindlich optimiert, und dann am Ende der Flaschenhals ganz woanders sitzt.
Viele schlaue Leute haben es schon gesagt: Bring das Programm erstmal zum Laufen und lokalisiere dann die Problemstellen. Oder auch "Premature optimization is the root of all evil"
Natürlich sollte man schon ein Auge drauf haben, welcher Lösungsweg für die Situation der Beste ist. Nachträgliche Änderungen können auch viel Zeit kosten. Aber man darf sich nicht in Mikrooptimierung verlieren ("Diese Multiplikation kann ich auch mit Shift&Add umsetzen") und im Zweifel zwischen Optimierung und Aufwand (und man sollte oft zweifeln) den einfacheren Weg wählen.

Feature Overkill

Man hat gerade eine Klasse implementiert und denkt sich, dass die Klasse eigentlich auch noch ein paar andere Dinge machen könnte. Wenn man dann zurück blickt, stellt man fest, dass man nur seine Zeit damit verschwendet hat. Hier erweist sich das YAGNI Prinzip als hilfreich: You Aren't Gonna Need It. Ist eigentlich ein Prinzip aus eXtreme Programming, aber imo ein recht allgemein anwendbares. Erstmal alle Anforderungen erfüllen, sich nicht selbst neue Anforderungen (und damit Arbeit) schaffen. Das hält auch den Code kürzer, und weniger Code ist leichter wartbar.

Reinventing the Wheel

Damit fängt glaub ich jeder an. Aber das Problem ist ja nicht ein Anfänger, der mal selbst eine Linked List programmiert oder eine Vektorklasse implementiert. Eigentlich ist das auch ein Punkt, der mich weniger bei anderen stört, als bei mir selbst. Ich finde es einfach dann schade um die Zeit, wenn man etwas baut, und dann feststellt, dass es im Framework schon enthalten ist, wenn auch etwas abgewandelt. Oder dass es schon eine (oft freie) Bibliothek dafür gibt.
Umso schlimmer wenn man das mit Absicht macht, weil man anderen zu wenig zutraut, oder keine Lust (manche nennen das auch Inkompetenz) hat rauszufinden, wie man diese fremde Bibliothek benutzen soll.

Was haltet ihr für die häufigsten (tödlichen) Fehler in der Programmierung? Was nervt euch an Code und Programmen von anderen oder von euch selbst am meisten? Wobei der Schwerpunkt auf Fehlern trotz Wissen liegen sollte 😉 also nicht aus Unerfahrenheit oder Anfängerfehler 🙂 Vieleicht kann man ja noch etwas lernen.

Erstellt vor 18 Jahren

Ich hab nichts gegen Singletons. Ich hab nur was dagegen, dass auf sie zurückgegriffen wird, obwohl man sie nicht braucht. Ich kann nichtmal was von einer Argumentation von dir erkennen. Du sagst nur, dass static das gleiche wäre, was nunmal nicht stimmt.
Wohlgemerkt hab ich nie davon gesprochen den Login zu einer statischen Klasse zu machen, aber irgendwie hab ich den Eindruck, dass du es genau so verstehen willst.

Der Unterschied:

  • Singletons gehören niemanden. Jeder hat darauf gleiche Zugriffsrechte.
    Eine statische Variable gehört zu einer Klasse. Diese Klasse hat volle Zugriffsrechte und räumt anderen die Rechte dafür ein.

  • Singletons erzwingen, dass nur eine Instanz erstellt werden kann. In nahezu allen Fällen braucht man das nicht. Das ist aber der Entscheidende Punkt eines Singletons. Warum ein Singleton benutzen und sich damit Einschränkungen auferlegen, die nicht nötig sind.
    Eine normale Klasse erzwingt erstmal garnichts. Dass man diese Klasse auch für statische Variablen benutzt, kann der Klasse ja ziemlich egal sein, außer es würde eben zu Fehlern führen.

  • Wie siehts denn bei Singletons mit Vererbung aus? Da wirds schon etwas komplizierter, so dass man im Normallfall erstmal auch das ausschließt (private Konstruktor, nicht protected). Das meinte ich damit, dass du auch keine Klasse sealed machst, nur weil du Vererbung nicht brauchst.

Wenn du das nicht hier in dem Thread klären willst, kannst du mir auch gerne eine PM schreiben. Aber bis jetzt erkenne ich von dir leider garkeinen Punkt der mich irgendwie weiter bringen würde. Du sagst nur, dass es eigentlich das gleiche ist. Ich erkenne nichtmal im Ansatz, wo sich das auch nur ähnlich sein sollte, eine statische Variable anzulegen, oder ein Singleton Pattern zu benutzen.
Mit dem einen benutzt man eine Klasse, mit dem anderen definiert man eine Klasse.

Es gibt noch viele weitere Patterns die für diese Aufgabe genauso falsch wären wie Singleton: Singlestate oder Dependency Injection. Die erledigen die einzige gestellte Anforderung von globaler Zugreifbarkeit genauso und haben wie das Singleton Nebenwirkungen, die einen nicht weiter stören würden. Ich sehe nichts was bei einer ganz simplen Anforderung von globaler Sichtbarkeit für eines davon sprechen würde.
Warum nicht einfach eine statische Variable hinterlegen, die von einem definierten Punkt aus setzen und von überall Verwendung erlauben? Warum eines dieser Patterns verwenden, und sich damit Einschränkungen ins Haus holen, die man nicht braucht?

Wenn kein Grund für Singleton spricht, würde ich es wie gesagt einfach nach dem KISS Prinzip als statische Variable anlegen, oder überlegen es nicht doch als Parameter weiterzureichen.

Erstellt vor 18 Jahren

Original von herbivore
Hallo Traumzauberbaum,

es kann immer nur ein Benutzer zur Zeit angemeldet sein. Deshalb Singleton. Ganz im Sinne des Pattern. 🙂 Demzufolge laufen deine Einwände alle ins Leere.

Man abgesehen davon, dass ich static hier nicht nur für ungünstig halte, sondern die Konsequenz von static ebenfalls wäre, dass es die Daten nur einmal gäbe. Denn static hat genau so viel oder wenig mit global zu tun wie Singleton. static bedeutet genauso wie Singleton, dass es die Daten nur einmal gibt. Wenn also deine Argumentation greifen würde (was sie m.E. nicht tut, s.o.), dass es hier um Globalität und nicht um Einzigartigkeit ging, wäre static genauso unpassend wie Singleton. Wenn deine Argumentation also greifen würde, liefe dein Vorschlag also darauf hinaus, den Teufel mit dem Beelzebub auszutreiben. 🙂

herbivore

Nein eben nicht. Es gibt dann so viele Instanzen von der Klasse, wie man Variablen anlegt. Ob diese static sind, ist doch egal. Man baut es nicht in die Definition der Klasse ein, wie sie benutzt wird. Beim Singleton darf es genau nur eines geben und du legst fest, wie sie benutzt werden soll, und das ohne einen Grund dafür zu haben. Und du weißt genau wer dann diese static Variablen setzt, beim Singleton weiß man das nicht.

Und genau dein erster Abschnitt ist, was mich so gewaltig an dem Singleton stört: Es kann nur ein Benutzer angemeldet sein, es muss aber nicht. Es führt nicht zu Fehlern wenn mehrere Instanzen dieser Klasse existieren würden, also warum nur eine einzige erzwingen?
Machst du Klassen sealed, weil du sie in diesem Programm nicht ableiten willst?

Man legt nicht etwas fest, was man nicht wirklich auch braucht. Die Einzigartigkeit braucht man in den seltensten Fällen, warum also das Singleton benutzen? Das ist nur für Einzigartigkeit da, wird aber in 99% der Fälle benutzt, weil man nicht weiß, wo man die static Variable sonst hinlegen soll.

Erstellt vor 18 Jahren

Und Singleton halte ich in den meisten Fällen für absolut falsch und unnötig. Es ist eben ein einfaches Pattern, und dadurch auch das Bekannteste.

Z.B. zwingt dich Singleton dazu, dass es nur eine Instanz gibt. In den meisten Fällen wo Singleton eingesetzt und auch von herbivore vorgeschlagen wird, ist einem das egal, weil man eh nur eine Instanz braucht, und man nimmt es eben als Nebeneffekt in kauf. Nahezu nie wird es eingesetzt, weil um Fehler bei mehrfacher Instanzierung zu Vermeiden (z.B. wenn man 2 mal auf die Grafik zugreift führt das garantiert zu Fehlern).

Aber das ist der Punkt: Man will eigentlich globalen Zugriff, nimmt aber ein Pattern, dass als Hauptmerkmal eigentlich nur das Erzwingen von nur einer Instanz hat. Das ist einfach ein Misbrauch dieses Patterns in Anwendungsfällen, die dieses Pattern nicht brauchen. Und ich verstehe nicht warum herbivore es in jedem Thread zum Thema globale Variablen vorschlägt.

Bevor man ein Pattern verwendet, sollte man sich Fragen, ob man denn das wünscht, was das Pattern realisiert. Das Singleton-Pattern realisiert das verhindern von mehreren Instanzen. Braucht man das in diesem Fall? Ich denke eher nicht.
Wenn es nur um Sichtbarkeit geht, sollte man eine stinknormale statische Variable benutzen. Dort hat man dann nämlich den Vorteil, dass man die Sichtbarkeit und Setzbarkeit eindeutig regeln kann. Bei einem Singleton erstellt der die Instanz, der zuerst kommt. Welche Klasse führt den Login durch? Die, die zuerst kommt. Finde ich äußerst fragwürdig.

Erstellt vor 18 Jahren

Ich würde eher sagen, es funktioniert nicht in Konstruktoren. Erst nach dem Konstruktor kann für das Control der DesignMode eingeschaltet werden, weil Site zu dem Zeitpunkt noch nicht gesetzt ist.

Ich hab zu dem Thema zwei Lösungsideen gefunden:

  1. Den Code aus dem Konstruktor nach Init verschieben
  2. LicenseManager.UsageMode == LicenseUsageMode.Designtime abfragen

Wobei die Erste eigentlich die Schönere ist.

Ansonsten mal nach DesignMode und Constructor googeln.

Erstellt vor 18 Jahren

Gut, ich wollte mir auch nicht zu viel Gedanken machen.
Hab eben grob die zwei Prinzipien eingebaut: Selektion und Kombination

Da mir für die Selektion auf die schnelle nichts cleveres eingefallen ist, hab ich einfach über das quadrat der Zufallszahl eine simple Verteilung genommen, die eher die "guten" Werte nimmt, aber auch mal bei den schlechten zuschlagen kann.
In die Reproduktion hab ich dann noch Mutation eingebaut (das bei default), um Pech bei der Initialisierung etwas zu kompensieren.

In den meisten Fällen klappts, manchmal kommt aber auch nichts gutes raus. War ja zu erwarten. Aber ich bin froh, dass es so weit wenigstens etwas funktioniert 😉

Erstellt vor 18 Jahren

Was ist denn an dem Pattern schlecht?
Dann kann ich aus dem Index der Gruppe auf den gematchten Inhalt schließen 😉

Hab mich eben an nem genetischen Algorithmus versucht:


private static Random rand = new Random();

private static double Fitness( int guess, string text )
{
	string guessText = guess.ToString( "d10" );

	if( guessText.Length > text.Length )
		text = new string( '0', guessText.Length - text.Length ) + text;
	
	int matches = 0;
	for( int i = 0; i < text.Length; ++i )
	{
		if( guessText[i] == text[i] )
		{
			++matches;
		}
	}

	double fitness = (double)matches / (double)text.Length;

	return fitness;
}

private static int Reproduce( int a, int b )
{
	int bigger = Math.Max( a, b );
	int smaller = Math.Min( a, b );

	int result = 0;

	while( bigger != 0 )
	{
		result *= 10;

		switch( rand.Next( 0, 5 ) )
		{
			case 0:
			case 1:
				result += bigger%10;
				break;

			case 2:
			case 3:
				result += smaller%10;
				break;

			default:
				result += rand.Next( 0, 10 );
				break;
		}

		bigger /= 10;
		smaller /= 10;
	}
	return result;
}

public static int Str2Int( string text )
{
	int[] generation = new int[4096];
	double[] fitness = new double[generation.Length];

	for( int i = 0; i < generation.Length; ++i )
	{
		generation[i] = rand.Next( -1, int.MaxValue ) + 1;
		fitness[i] = Fitness( generation[i], text );
	}

	List<int> newGeneration = new List<int>( generation.Length );
	double h;
	int a, b;

	for( int i = 0; i < 1000; ++i )
	{
		Array.Sort( fitness, generation );
		if( fitness[generation.Length - 1] == 1.0 )
			return generation[generation.Length - 1];

		for( int k = 1; k < generation.Length / 4; ++k )
			newGeneration.Add( generation[generation.Length-k] );
		
		while( newGeneration.Count < generation.Length )
		{
			h = rand.NextDouble();
			h *= h;
			h = Math.Round( h * (generation.Length - 1) ) + 1.0;
			a = generation[generation.Length - (int)h];

			h = rand.NextDouble();
			h *= h;
			h = Math.Round( h * (generation.Length - 1) ) + 1.0;
			b = generation[generation.Length - (int)h];

			newGeneration.Add( Reproduce( a, b ) );
		}

		generation = newGeneration.ToArray();
		newGeneration.Clear();
		for( int k = 0; k < generation.Length; ++k )
			fitness[k] = Fitness( generation[k], text );
	}

	return generation[generation.Length - 1];
}

Ich hab nicht wirklich Ahnung davon. Wäre also nett wenn jemand kommentieren könnte, ob das überhaupt etwas GA ähnliches ist 😉

Erstaunlicherweise funktioniert das sogar recht gut. Für positive Zahlen wohlgemerkt.

EDIT: Noch einen Fehler behoben, jetzt überleben die Besten 😉

Erstellt vor 18 Jahren

Original von Moooitic
Arg, lol,

Ich rede die ganze zeit über ref -_- (daher auch immer der pointer vergleich - out ist ja etwas anders)

Damit hab ich schon fast gerechnet, aber dazu möchte ich auch noch was sagen:

Eine dumme Verwendung von Schlüsselworten ist kein Argument gegen die Schlüsselworte, sondern gegen diese Art von Verwendung.

Pointer selbst sind sehr gut mit OOP vereinbar. Man kann einen Pointer genauso als Klasse verstehen, wie ein Array. C++ unterscheidet ja nichtmal zwischen den beiden, und in C# könnte man jedes ref auch durch ein Array ersetzen. Aber ist das dann OOP, nur weil ich das gleiche ohne ref mache?

Sobald du ein normalen Referenztypen übergibst, musst du doch auch damit rechnen, dass die Funktion dieses Objekt verändern kann. Wo ist der Unterschied zu einem Pointer?