C# - Programm

Alexander12

Erfahrenes Mitglied
Hi.

Hoffe Ihr kennt mich noch. ;)
Ich dachte Ich schreib Mal wieder was, nachdem Ich ja mir einfach ne längere Auszeit genommen habe.

Ich habe die Zeit genutzt um mich fortzubilden (in C#) und habe mit neuem Wissen auch gleich n Programm, meinen Vokbeltrainer neu programmiert und hoffe auf euer Voting, habe auch diesmal gleich alle Sourcen mitangehängt.. ;)

Also er hat folgende Features:
- Abfrage Normal / Auf Zeit
- Vokabeltest auf Zeit
- Wortlisten erstellen/verwalten etc.
- Habe versucht es möglichst OOP-gerecht zu machen..
- Das Programm können mehrere User benutzen, sodass jeder seine eigenen Wortlisten und Notendurchschnitte hat -> fehlt nur noch das Login-Formular ..
- Das Programm ist weitestgehend dazu ausgelegt, dass Man Sprachpakete einbinden kann
- Habe versucht das Ding von Anfang bis ende sauber durchzuprogrammieren, auch die bennennung von Steuerelementen etc. :suspekt:

Was findet Ihr gut/schlecht an Design/Code/Funktionaltität etc.?

Ich freue mich auf eure Votings! ;-)


MfG Alexander12

//Edit: Ach, das Programm benötigt .NET 2.0
 

Anhänge

  • 24821attachment.zip
    57,3 KB · Aufrufe: 88
Zuletzt bearbeitet:
Usability:
Ich finde ein Tree Menu hier fehl am platz. Besonders irritiert mich das häckchen wenn ich einen Menupunkt auswähle.

Ein "Häckchen im Kästchen" bedeutet für mich noch immer: "gemacht-erledigt". Aber Programminfo aufrufen hat ja nichts mit Erledigt zu tun.

Auch klickt mann auf Abfrage und nichts passiert. Du solltest hier den Klassischen Weg gehen: Menu oben da wo mann es erwartet ;)

Eigenschaften - Von - Nach. Diese Felder sind anwählbar aber nicht beschreibbar. Wenn du Felder hast die mann nicht beschreiben kann dann disable sie. Sprich ein Courser in den Feldern aber keine Möglichkeit diese Felder auszufüllen verwirrt.

Unter Wortlisten gibts ein Progress Balken der aber auf 100% steht. Wenn progess balken dann bitte wieder verschwinden lassen wenn kein Progress mehr stattfindet.

Zum Code:
public class all_wordlists <-- Ist quatsch. Eine Klasse Representiert ein Object und keine Menge. Mal davon abgesehen gibts auch bei C# Styleguides wie Klassen benannt werden sollten.

Zudem leider ein paar Schnitzer entdeckt:

private void SetLanguage(string LanguagePack)
{
words = LanguagePack.Split(new char[] {'|'});
// Set the language
this.lblHeadline.Text = words[0];
this.c1.Text = words[1];
this.c2.Text = words[2];
this.c3.Text = words[3];
this.c4.Text = words[4];
this.btnDelete.Text = words[5];
this.btnRefresh.Text = words[6];
}

Was passiert wenn dein Programm mal abstürzt und eine Zeile nicht komplett geschrieben wurde. Oder anderweitig die Datei aus der du ausliest beschädigt ist?
Wenn in dem betreffenden Teil sich kein array mit 6 Items herauslesen lässt. Dann
schmiert dein Programm ab.
Hier fehlt etwas in dieser Art:

Code:
if(LanguagePack==null )
    throw new IrgendwasException("dumm gelaufen");
words = LanguagePack.Split(new char[] {'|'});
if(words.size()<6)
   throw new IrgendwasException("file corrupt");
this.lblHeadline.Text = words[0];

Du solltest immer davon ausgehen das irgendwelche Daten kaputt sein können
:)

Ich habe aus test mal eben die Datei Unit 2.LST so verändert das ich einfach cat| rausgeschnitten habe:

nformationen über das Aufrufen von JIT-Debuggen
anstelle dieses Dialogfelds finden Sie am Ende dieser Meldung.

************** Ausnahmetext **************
System.IO.EndOfStreamException: Über das Ende des Streams hinaus kann nicht gelesen werden.
bei System.IO.__Error.EndOfFile()
bei System.IO.BinaryReader.ReadString()
bei voxtar1_0.all_wordlists.GetWordlists(String diretory)
bei voxtar1_0.all_wordlists.All_wordlistsLoad(Object sender, EventArgs e)
bei System.Windows.Forms.UserControl.OnLoad(EventArgs e)
bei System.Windows.Forms.UserControl.OnCreateControl()
bei System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
bei System.Windows.Forms.Control.CreateControl()
bei System.Windows.Forms.Control.ControlCollection.Add(Control value)
bei voxtar1_0.MainForm.TreeMenuAfterSelect(Object sender, TreeViewEventArgs e)
bei System.Windows.Forms.TreeView.OnAfterSelect(TreeViewEventArgs e)
bei System.Windows.Forms.TreeView.TvnSelected(NMTREEVIEW* nmtv)
bei System.Windows.Forms.TreeView.WmNotify(Message& m)
bei System.Windows.Forms.TreeView.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** Geladene Assemblys **************
mscorlib
Assembly-Version: 2.0.0.0.
Win32-Version: 2.0.50727.42 (RTM.050727-4200).
CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll.
----------------------------------------
voxtar1_0
Assembly-Version: 1.0.2357.25970.
Win32-Version: 1.0.2357.25970.
CodeBase: file:///C:/chris/temp/voc/Voxtar%201.0/voxtar1_0.exe.
----------------------------------------
System.Windows.Forms
Assembly-Version: 2.0.0.0.
Win32-Version: 2.0.50727.42 (RTM.050727-4200).
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll.
----------------------------------------
System
Assembly-Version: 2.0.0.0.
Win32-Version: 2.0.50727.42 (RTM.050727-4200).
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll.
----------------------------------------
System.Drawing
Assembly-Version: 2.0.0.0.
Win32-Version: 2.0.50727.42 (RTM.050727-4200).
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll.
----------------------------------------
System.Configuration
Assembly-Version: 2.0.0.0.
Win32-Version: 2.0.50727.42 (RTM.050727-4200).
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll.
----------------------------------------
System.Xml
Assembly-Version: 2.0.0.0.
Win32-Version: 2.0.50727.42 (RTM.050727-4200).
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll.
----------------------------------------
mscorlib.resources
Assembly-Version: 2.0.0.0.
Win32-Version: 2.0.50727.42 (RTM.050727-4200).
CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll.
----------------------------------------
System.Windows.Forms.resources
Assembly-Version: 2.0.0.0.
Win32-Version: 2.0.50727.42 (RTM.050727-4200).
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms.resources/2.0.0.0_de_b77a5c561934e089/System.Windows.Forms.resources.dll.
----------------------------------------

************** JIT-Debuggen **************
Um das JIT-Debuggen (Just-In-Time) zu aktivieren, muss in der
Konfigurationsdatei der Anwendung oder des Computers
(machine.config) der jitDebugging-Wert im Abschnitt system.windows.forms festgelegt werden.
Die Anwendung muss mit aktiviertem Debuggen kompiliert werden.

Zum Beispiel:

<configuration>
<system.windows.forms jitDebugging="true" />
</configuration>

Wenn das JIT-Debuggen aktiviert ist, werden alle nicht behandelten
Ausnahmen an den JIT-Debugger gesendet, der auf dem
Computer registriert ist, und nicht in diesem Dialogfeld behandelt.

^-- Fehlermeldung. Hier wäre es schöner das der Benutzer eine Fehlermeldung bekommt mit der er was anfangen kann, wie eben: "Unit 2.LST ist korrupt. Kann diese Datei nicht parsen" oder sowas :)
 
Hi Christian.

Ok, vielen Dank für den Tipp, habe da vergessen an den paar verwundbaren stellen ExceptionHandling einzubauen. Ansonsten wirds aber ins Log-File gschrieben.. ;)

Das Menu oben kommt auch noch hin.

Ach ja, zur Info:
Das Programm befindet sich im Endstadium/Testphase, muss es dann noch mit Beta kennzeichnen.. Wir könne also jederzeit ändern.

Habe auf jeden fall noch nich so viel gegen meine OOP-Kenntnisse gehört, das ist vielversprechend ;-)


MfG Alexander12
 
Zuletzt bearbeitet:
Code:
			if(user_mistakes == 0)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 1"); grade = 1; }
			else if(user_mistakes == 1)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 1-2"); grade = 1.5; }
			else if(user_mistakes == 2)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 2"); grade = 2; }
			else if(user_mistakes == 3)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 2-3"); grade = 2.5; }
			else if(user_mistakes == 4)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 3"); grade = 3; }
			else if(user_mistakes == 5)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 3-4"); grade = 3.5; }
			else if(user_mistakes == 6)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 4"); grade = 4; }
			else if(user_mistakes == 7)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 4-5"); grade = 4.5; }
			else if(user_mistakes == 8)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 5"); grade = 5; }
			else if(user_mistakes == 9)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 5-6"); grade = 5.5; }
			else if(user_mistakes == 10)
			{	MessageBox.Show("Sie haben " + user_mistakes.ToString() + " Fehler. -> Note: 6"); grade = 6; }

ist auch etwas unelegant.

Möglichkeit:
int[][] errorGrade = { new double[0][1], new double[1][1.2],new double[3][2] } ;
MessageBox.Show("Sie haben+"user_mistakes+" Fehler -> Note:"+ errorGrade[user_mistakes]);grade=errorGrade[user_mistakes]);

Zusätzlich ist es nie gut irgendwelche String Meldungen die dem Benutzer angezeigt werden in den Quellcode einzubauen. Wenn du das ganze auf Englisch anbieten willst musst du in jeden Quellcode rein. Hau das ganze in Propertie Files raus.

Dann machst du 2 mal das selbe:
Code:
vok_time.cs

private void InputWord(string NewWord)
		{
			string[] splitted = NewWord.Split(new char[] {'|'});
			this.txtFrom.Text = splitted[0];
			this.txtTo.Text = splitted[1];
			this.txtSort.Text = splitted[2];
			this.txtWord.Text = splitted[3];
			CurrentRightWord = splitted[4];
			this.txtCorrection.Text = "";
			CurrentTip = splitted[5];
			if(splitted[5] == "-")
				this.btnTip.Enabled = false;
			else
				this.btnTip.Enabled = true;
			//GotWord = true;
		}

und 
all_wordlist.cs
private void SetLanguage(string LanguagePack)
{
words = LanguagePack.Split(new char[] {'|'});
// Set the language
this.lblHeadline.Text = words[0];
this.c1.Text = words[1];
this.c2.Text = words[2];
this.c3.Text = words[3];
this.c4.Text = words[4];
this.btnDelete.Text = words[5];
this.btnRefresh.Text = words[6];
}

Sprich du hast 2 Stellen (vielleicht auch mehr, hab nur eben die 2 gefunden :) ) in denen du dein Protokoll (die Art wie du deine Wortliste liest und schreibst) handelst. Wenn du nun dein Protokoll änderst und die Wordlisten bsp in eine Datenbank ausrangieren willst musst du dein Code komplett ändern.
Auch überall wieder jene Fehlerüberprüfung usw machen.
C# bietet dir doch Interfaces. Nutze sie:

(sorry schreibs in Java, C# ist zu lang her :D, aber sollte für C# Programmierer problemlos lesbar sein was ich will)
Code:
public interface IWordListController {

   public WordList readWordListe();

   public void writeWordList() throws BöseException;

   public void updateWordList() throws BöseException;
}

public class FileWordListController  {
   public WordList readWordList() { 
     File file = new File(Configuration.getWorldListPath());
     /// ganz toll lesen usw wordList erstellen;;
     return wordList;
   }
  
   // andere Methoden implementieren usw
}


public class DatabaseWordListController {
  public WordList readWordList() { 
    Connection conn = ... // ganz toll aus DB lesen
     //    wordList erstelle;
    return wordList;
  }
}

Sinn der ganzen Sache. Trennung der Applikationsteile. Sprich das lesen von Dateien hat nichts in der selben Klasse zu tun die irgendwelche Controlls auf der Benutzeroberfläche ändert.


... geht gleich weiter :)
 
Hier MVC anwenden. Das kannst du dadurch das du dir 3 Projekte machst anstatt eines. :)

Ein Trick wie mann sich das beibringen kann:

Ein Projekt das nur die Daten händelt.
Ein Projekt das nur Berechnungen durchführt die nicht direkt mit der Benutzeroberfläche zu tun hat
Ein Projekt das eigentlich nur die Benutzeroberfläche anzeigt bzw dynamische Dinge berechnet.

Dann nimmst du nur jeweils ein - zwei Interfaces von je einem Projekt und kopierst die in das andere Projekt hinein. Dein Code in dem jeweiligen Projekt arbeitet nur mit den Interfaces des jeweils anderen Projektes.
Zum Testen kannst du die Interfaces mit einer Dummy Klasse implementieren dann hast du immer gleichbleibende Werte die auch beim Entwickeln helfen.
Sobald deine Projekte so weit sind das du die wirklichen Daten brauchst dann führst du sie zusammen. Der grosse Vorteil ist du hast dich damit dann selber gezwungen die Abhängigkeiten klein zu halten, und dein Projekt hat automatisch ein bessere OOP Design.

Sei mir nicht bös, ich wollt dir das jetzt nicht schlecht reden. Versteh das bitte als konstruktive Kritik.

grüsse
 
Hi Christian.

Nein, nein, Ich bin für jede konstruktive Kritik offen, find Ich gut das du dir da sogar die Mühe machst und das alles auflistest.

Zum Punkt OOP:
Ich könnte die Interfaces etc. z.B. in ne eigene Library auslagern -> Login System kommt auch noch rein, das habe Ich aber schon vor längerem in eine DLL geschrieben.

Das wäre dann z.B. ein seperates Projekt. Übrigens, Ich find solche Diskussionen wie diese recht gut, da kann Man mehr lernen als Man denkt..

Da kann man das Projekt auch besser warten...;)


MfG Alexander12

// Edit: Was meinst, soll Ich die UserControls auch auslagern? Die lassen sich dann leicht austauschen...
 

Neue Beiträge

Zurück