# Richtiger Programmierstil ?



## ehlr (23. Dez 2011)

Hallöchen.
Ich bin Anfänger, habe aber schon einige Programme geschrieben.
Nun stellt sich für mich die Frage, ob ich auch wirklich "richtig" programmiere, also mit einem nahe zu normalen Programmierstil.

Hier ist ein Programm von mir (Schere-Stein-Papier) :

tester.java

```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

public class tester extends JFrame {

	int playerchoose = 0;
	int pcchoose = 0;
	static int wins = 0;
	static int loses = 0;
	static int score = 0;
	
	private static final long serialVersionUID = 689925824694774327L;

	public static void main(String[] args) {
		tester gui = new tester(); //objekt von gui wird erzeugt
		gui.setVisible(true); //Frame wird visible
		gui.setBounds(750,100,360,375); //Größe setzen
		gui.setTitle("Stein-Schere-Papier"); //Titel geben
		gui.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); //Prozess beenden, wenn X
		gui.setResizable( false ); //Nicht vergrößerbar
   	}//ende main method

	JLabel lblchoosen, lbltext1, lblpcchoosen;
	JLabel lbltext2;
	JLabel lblregel;
	JLabel lbltext3, lblwins, lblloses, lblscore;
	static JLabel lblgewinner;
	JButton button_stein, button_schere, button_papier;
	
	
	public tester() {
	  this.getContentPane().setLayout(null); 
	  this.initWindow();
	}//ende public gui
	
	protected void initWindow() {

	  button_stein = new JButton("Stein");
	  button_schere = new JButton("Schere");
	  button_papier = new JButton("Papier");
	  lblchoosen = new JLabel("Bereit");
	  lbltext1 = new JLabel("Ausgewählt :");
	  lblpcchoosen = new JLabel("Bereit");
	  lbltext2 = new JLabel("PC wählt :");
	  lblregel = new JLabel("<HTML><BODY>Schere schlägt Papier, Papier schlägt Stein,<BR>Stein schlägt Schere<BR><BR>Gewonnen : 10 Punkte<BR>Verloren : -8 Punkte<BR>Unentschieden : 2 Punkte</BODY></HTML>");
	  lbltext3 = new JLabel("Gewinner :");
	  lblgewinner = new JLabel("Noch nichts gewählt!");
	  lblwins = new JLabel("Gewonnen : 0");
	  lblloses = new JLabel("Verloren : 0");
	  lblscore = new JLabel("Punktestand : 0");
	  
	  
	  button_stein.setBounds(10,150,100,25);
	  button_schere.setBounds(120,150,100,25);
	  button_papier.setBounds(230,150,100,25);
	  lblchoosen.setBounds(100,195,150,25);
	  lbltext1.setBounds(10,195,100,25);
	  lblpcchoosen.setBounds(100,210,150,25);
	  lbltext2.setBounds(10,210,100,25);
	  lblregel.setBounds(10,10,300,100);
	  lbltext3.setBounds(10,250,90,25);
	  lblgewinner.setBounds(100,250,150,25);
	  lblwins.setBounds(10,295,100,25);
	  lblloses.setBounds(130,295,100,25);
	  lblscore.setBounds(10,315,150,25);
	  
	  	 
	  this.getContentPane().add(button_stein);
	  this.getContentPane().add(button_schere);
	  this.getContentPane().add(button_papier);
	  this.getContentPane().add(lblchoosen);
	  this.getContentPane().add(lbltext1);
	  this.getContentPane().add(lblpcchoosen);
	  this.getContentPane().add(lbltext2);
	  this.getContentPane().add(lblregel);
	  this.getContentPane().add(lbltext3);
	  this.getContentPane().add(lblgewinner);
	  this.getContentPane().add(lblwins);
	  this.getContentPane().add(lblloses);
	  this.getContentPane().add(lblscore);
		 
	  this.pack();
	  
	  button_stein.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent arg0) {	
				
				game game = new game();
				
				// Player nimmt Stein (1)
				int playerchoose = 1;
				
				// Zug des PCs ermitteln
				int pcchoose = (int)((Math.random()) * 3 + 1); 
				
				// Zahl in Stein,Schere oder Papier wandeln
				String ausgabe_player = game.wahl(playerchoose) ;
				String ausgabe_pc = game.wahl(pcchoose);
				
				// ausgewählte anzeigen
				lblchoosen.setText(ausgabe_player);
				lblpcchoosen.setText(ausgabe_pc);
				
				// Gewinner ermitteln
				String gewinner = game.prüfe(playerchoose, pcchoose); 
				lblgewinner.setText(gewinner);
				
				// Score 
				lblwins.setText("Gewonnen : " + wins);
				lblloses.setText("Verloren : " + loses);
				lblscore.setText("Punktestand : " + score);
				
			}

			
			
	  });//ende actionlistener		
	  
	  button_schere.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent arg0) {	
				
                game game = new game();
				
				// Player nimmt Papier (2)
				int playerchoose = 2;
				
				// Zug des PCs ermitteln
				int pcchoose = (int)((Math.random()) * 3 + 1); 
				
				// Zahl in Stein,Schere oder Papier wandeln
				String ausgabe_player = game.wahl(playerchoose) ;
				String ausgabe_pc = game.wahl(pcchoose);
				
				// ausgewählte anzeigen
				lblchoosen.setText(ausgabe_player);
				lblpcchoosen.setText(ausgabe_pc);
				
				// Gewinner ermitteln
				String gewinner = game.prüfe(playerchoose, pcchoose); 
				lblgewinner.setText(gewinner);
				
				// Score 
				lblwins.setText("Gewonnen : " + wins);
				lblloses.setText("Verloren : " + loses);
				lblscore.setText("Punktestand : " + score);
				
			}
			
	  });//ende actionlistener		
	  
	  button_papier.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent arg0) {	
				
                game game = new game();
				
				// Player nimmt Schere (3)
				int playerchoose = 3;
				
				// Zug des PCs ermitteln
				int pcchoose = (int)((Math.random()) * 3 + 1); 
				
				// Zahl in Stein,Schere oder Papier wandeln
				String ausgabe_player = game.wahl(playerchoose) ;
				String ausgabe_pc = game.wahl(pcchoose);
				
				// ausgewählte anzeigen
				lblchoosen.setText(ausgabe_player);
				lblpcchoosen.setText(ausgabe_pc);
				
				// Gewinner ermitteln
				String gewinner = game.prüfe(playerchoose, pcchoose); 
				lblgewinner.setText(gewinner);
				
				// Score 
				lblwins.setText("Gewonnen : " + wins);
				lblloses.setText("Verloren : " + loses);
				lblscore.setText("Punktestand : " + score);
				
			}
			
	  });//ende actionlistener		
		
	}//ende initwindow
	
	
}//ende class gui
```


game.java

```
import java.awt.Color;


public class game {
 
    
    public String wahl(int a) {
         
        String ausgabe = null;
        
        // 1 -> Stein
        if (a == 1) {
             ausgabe  = "Stein";
        }
        
        // 2 -> Schere
        if (a == 2) {
            ausgabe = "Schere";
        }
        
        // 3 -> Papier
        if (a == 3) {
            ausgabe = "Papier";
        }
            
 
        return ausgabe;
    }// ende methode
    
    
    
    public String prüfe(int a, int b) {
    	
    	String ausgabe = null;
   
    	if(a == 1 & b == 1) {
    		ausgabe = "Unentschieden!";
    		tester.lblgewinner.setForeground(new Color(0,0,0));
    		tester.score = tester.score + 2;
    	}
    	
    	if(a == 1 & b == 2) {
    		ausgabe = "Du gewinnst!";
    		tester.lblgewinner.setForeground(new Color(0,255,0));
    		tester.wins++;
    		tester.score = tester.score + 10;
    	}
    	
    	if(a == 1 & b == 3) {
    		ausgabe = "Du verlierst!";
    		tester.lblgewinner.setForeground(new Color(255,0,0));
    		tester.loses++;
    		tester.score = tester.score  -8;
    	}
    	
    	if(a == 2 & b == 1) {
    		ausgabe = "Du verlierst!";
    		tester.lblgewinner.setForeground(new Color(255,0,0));
    		tester.loses++;
    		tester.score = tester.score  -8;
    	}
    	
    	if(a == 2 & b == 3) {
    		ausgabe = "Du gewinnst!";
    		tester.lblgewinner.setForeground(new Color(0,255,0));
    		tester.wins++;
    		tester.score = tester.score + 10;
    	}
    	
    	if(a == 2 & b == 2) {
    		ausgabe = "Unentschieden!";
    		tester.lblgewinner.setForeground(new Color(0,0,0));
    		tester.score = tester.score + 2;
    	}
    	
    	if(a == 3 & b == 1) {
    		ausgabe = "Du gewinnst!";
    		tester.lblgewinner.setForeground(new Color(0,255,0));
    		tester.wins++;
    		tester.score = tester.score + 10;
    	}
    	
    	if(a == 3 & b == 2) {
    		ausgabe = "Du verlierst!";
    		tester.lblgewinner.setForeground(new Color(255,0,0));
    		tester.loses++;
    		tester.score = tester.score - 8;
    	}
    	
    	if(a == 3 & b == 3) {
    		ausgabe = "Unentschieden!";
    		tester.lblgewinner.setForeground(new Color(0,0,0));
    		tester.score = tester.score + 2;
    	}
    	
    	
    	
    	return ausgabe;
    }// ende methode
    
}// ende class
```


Was sollte ich am besten anders machen?


Besten Dank!

lg ehlr


----------



## TKausL (23. Dez 2011)

Was ich auf anhieb sehe:


```
tester gui = new tester(); //objekt von gui wird erzeugt
        gui.setVisible(true); //Frame wird visible
        gui.setBounds(750,100,360,375); //Größe setzen
```

Kommentare sind gut, aber nicht zuviele.
Was dort passiert brauchst du nicht zu Kommentieren, dass sieht jeder Programmierer.
Kommentiere nicht WAS du tust, sondern WARUM du es tust.


----------



## Marcinek (23. Dez 2011)

Furchtbar.

Diese Inline Actionlistner unterscheiden sich doch nur in einem Wert?


----------



## Fab1 (23. Dez 2011)

Hi,

sieht doch ganz ordentlich aus. Klassen sollte man allerdings immer groß schreiben. Und Namen sollten im CamelCase schreiben. Und deine Methoden könnte man noch etwas besser benennen.


----------



## VfL_Freak (23. Dez 2011)

Moin,

mir ist noch ein logischer Fehler aufgefallen:

Diese Prüfungen

```
if(a == 1 & b == 1)
```

sollten ja wohl vermutlich SO lauten :

```
if( (a == 1) && (b == 1) )  // 2x '&'
```
oder? 
Das andere wäre ein Bitvergleich !

Gruß
Klaus


----------



## ehlr (23. Dez 2011)

Was sind CamelCases ?

Bisher habe ich immer wie folg angefangen ein Programm zu schreiben :

1. GUI schreiben
2. Methoden et cetera schreiben

Ist das richtig so?

Wie würdet ihr den Programmcode der GUI beurteilen?



@ VfL_Freak : Es sollen doch zwei Zahlen verglichen werden, ob beide den gleichen Wert haben.


----------



## Pippl (23. Dez 2011)

Also mir ist auf gefallen das du die Klassennamen klein schreibst.
Die ActionListener unterscheiden sich in nur einer Zahl, gibt besser Möglichkeiten

"Code Optimierung"
Im game.prüfe (Umlaute in Methodennamen sollte man auch vermeiden) hast du 3 Vergleiche für Unentschieden, eine einfach Überprüfung ob a==b reicht um zu wissen das es ein unentschieden ist.


----------



## ARadauer (23. Dez 2011)

Ein paar Tips von mir, wobei bei einem Schere Papier Stein Spiel, kann man nicht viel über Stil und Architektur schreiben.

Klassen schreibt man groß.
Generel trennt man Logik, Darstellung und Daten.

Nicht so viel kommentieren.
gui.setVisible(true); //Frame wird visible.... tatsächlich....

lbltext2 was ist das? sprechende Variablen!

Variablen camelCase ausgabe_player -> ausgabePlayer


----------



## TKausL (23. Dez 2011)

VfL_Freak hat gesagt.:


> Moin,
> 
> mir ist noch ein logischer Fehler aufgefallen:
> 
> ...



Würde keinen großen Unterschied machen. Bei #1 würde b==1 auch noch überprüft werden fals das erste schon false ist, bei #2 nicht. Ergebnis ist das gleiche


----------



## Fab1 (23. Dez 2011)

```
setVisible(true); //Frame wird visible
```

sollte immer am Schluss aufgerufen werden, sonst bekommst werden am Schluss manchmal nicht alle Komponenten angezeigt. Glaub mir wenn so ein Fehler auftritt und man das nicht weiß ist das ein sehr mysteriöses Rätsel, spreche leider aus Erfahrung. 

zu CamelCase:

DasIstCamelCaseManKannEsLesenObwohlKeineLeerzeichenDazwischenSind


----------



## ehlr (23. Dez 2011)

ARadauer hat gesagt.:


> Ein paar Tips von mir, wobei bei einem Schere Papier Stein Spiel, kann man nicht viel über Stil und Architektur schreiben.
> 
> Klassen schreibt man groß.
> Generel trennt man Logik, Darstellung und Daten.
> ...




Wie sieht diese Trennung denn aus?


----------



## Tomate_Salat (23. Dez 2011)

ehlr hat gesagt.:


> 1. GUI schreiben



Würde ich so nicht machen. Warum? Ganz einfach: du fängst an das Programm an das GUI anzupassen und nicht das GUI ans Programm. Wie mein Vorredner schon angedeutet/gesagt hat: Schau dir MVC an. Da werden die Schichten getrennt behandelt. 

Ich würde auch nicht soviele Einstellungssachen in die main packen. Definiere diese Werte lieber gleich in der eigentl. Klasse vor. Bei Bedarf kann man die nachher ja immernoch ändern. 

Was mir noch aufgefallen ist sind diese Punkte:
1.public class tester
2.JButton button_stein
3.public String prüfe(int a, int b) {

zu 1.+2.:
Konventionen (siehe mein Link). In Java schreibt man Klassen UpperCamelCase und Felder/Variablen lowerCamelCase. Solche "unterstriche" setzt man wenn dann bei "Konstanten" ein, dann gilt aber auch ALLUPPERCASE. 

zu 3.
Verwende sinnvolle Parameternamen. int a sagt absolut nichts aus. Dann vermeide Umlaute, dass ist eher unschön und zu guter letzt: mach Parameter final. Mit Eclipse z.B. kannst du einstellen, dass er automatisch beim speichern alle Parameter final setzt.


----------



## ehlr (23. Dez 2011)

Tomate_Salat hat gesagt.:


> Würde ich so nicht machen. Warum? Ganz einfach: du fängst an das Programm an das GUI anzupassen und nicht das GUI ans Programm. Wie mein Vorredner schon angedeutet/gesagt hat: Schau dir MVC an. Da werden die Schichten getrennt behandelt.
> 
> Ich würde auch nicht soviele Einstellungssachen in die main packen. Definiere diese Werte lieber gleich in der eigentl. Klasse vor. Bei Bedarf kann man die nachher ja immernoch ändern.
> 
> ...



Ds hilft mir weiter!

Welche Parameter meinst du ?


----------



## ehlr (23. Dez 2011)

Ich arbeitet z.Z. an einem kleinen Rechen-Trainer.

Wie findet ihr diesen Code (nicht fertig) :


```
import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;



@SuppressWarnings("serial")
public class RechenTrainer extends JFrame {

	
	public static void main(String[] args) {
		RechenTrainer rechenTrainer = new RechenTrainer(); 
	}
	
	JLabel lblExercise, lblInstruction, lblUserSolution, lblTrueSolution;
	
	public RechenTrainer() {
		this.getContentPane().setLayout(null); 
		this.initWindow();
		this.setBounds(750,100,300,200); 
		this.setTitle("Rechen-Trainer"); 
		this.setResizable( false ); 
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 
		this.setVisible(true); 
	}
	
	protected void initWindow() {
		lblExercise = new JLabel("x + x");
		lblInstruction = new JLabel("Bitte löse die Aufgabe!");
		lblUserSolution = new JLabel("Deine Lösung = ");
		lblTrueSolution = new JLabel("Lösung : 2x");
		
		lblInstruction.setBounds(10,10,150,25);
		lblExercise.setBounds(10,40,150,25);
		lblUserSolution.setBounds(10,70,100,25);
		lblTrueSolution.setBounds(10,100,100,25);
		
		lblExercise.setForeground(Color.red);
		
		this.getContentPane().add(lblExercise);
		this.getContentPane().add(lblInstruction);
		this.getContentPane().add(lblUserSolution);
		this.getContentPane().add(lblTrueSolution);
		
		this.pack();
	}//ende initwindow


}//ende class
```


Als nächstes würde ich jetzt in die main Methode ein neues Objekt einer weiteren Klasse erzeugen.
In dieser Klasse soll dann die ganze Logik rein.
Wie sollte ich diese Klasse nennen? Sie soll neue Aufgaben stellen und Lösungen mit Benutzereingaben überprüfen.


----------



## KSG9|sebastian (23. Dez 2011)

Hi,

folgende Anmerkungen:

1. Instanzvariablen (deine Labels) sollten immer private sein
2. Verwende ein vernünftiges Layout für deine UI - kein setBounds
3. Warum ist initWindow protected? Generell immer die restriktivste Sichtbarkeit wählen die möglich ist
4. Du gehst es immer noch falschrum an

Zuerst solltest du die Klasse für die Logik schreiben, später dann die passende Oberfläche.


----------



## ehlr (23. Dez 2011)

Da ich die Oberfläche schon fertig habe, mach ich es zum letzten mal andersrum 
Wie macht man den ein UI ohne setBounds?!

Ich habe nun alle JLabels als private.
Möchte mit der Logik Klasse drauf zugreifen und einem Label einen anderen Text geben.
Wie geht das ?

(lblExercise ist unterkringelt und will eine nicht private ,static)


```
public class RechenTrainer {
	
	public void run() {
		RechenTrainerGUI.lblExercise.settext(neueAufgabe());
	}
	
	static String neueAufgabe() {
		String aufgabe = "";
		return aufgabe;
	}
	
}//ende class
```


----------



## VfL_Freak (23. Dez 2011)

Moin,



ehlr hat gesagt.:


> (lblExercise ist unterkringelt und will eine nicht private ,static)


in einem solchen Fehlerfall steht ganz links in der Zeile ein kleines rotes Kästchen, dass den Fehler anzeigt. Klick' mal mit der rechten Maustaste drauf und wähle dann "Schnellbehebung" (oder so ähnlich).

Darüber bekommst Du dann immer Vorschläge zur Fehlerbehebung!
Ist (meist) sehr hilfreich 

Gruß
Klaus


----------



## ehlr (23. Dez 2011)

VfL_Freak hat gesagt.:


> Moin,
> 
> 
> in einem solchen Fehlerfall steht ganz links in der Zeile ein kleines rotes Kästchen, dass den Fehler anzeigt. Klick' mal mit der rechten Maustaste drauf und wähle dann "Schnellbehebung" (oder so ähnlich).
> ...



Ja, aber ich soll ja die JLabels als private machen, eclipse will diese ohen private und als static.


----------



## ehlr (23. Dez 2011)

Ist das korrekt ?


```
public class RechenTrainer {
	
	private static int solution;
	
	//Um neue Augabe zu stellen
	public void next() {
		System.out.println(neueAufgabe());
	}
	
	//Um Aufgabe zu stellen und zu überprüfen
	public void run() {
		System.out.println(solution);
		System.out.println(checkUserSolution(20));
	}
	
	static String neueAufgabe() {
		String aufgabe = "";
		int figur1 = (int)((Math.random()) * 200 + 1);
		int figur2 = (int)((Math.random()) * 200 + 1);
		solution = figur1+figur2;
		aufgabe = figur1 + " + " + figur2;
		return aufgabe;
	}
	
	static String checkUserSolution(int userSolution){
		String yesOrNo = "Lösung ( " + userSolution + " ) ist falsch.";
		if (userSolution == solution) {
			yesOrNo = "Lösung ist richtig.";
		}
		return yesOrNo;
	}
	
	
	
}//ende class
```


----------



## bygones (23. Dez 2011)

du mixt ein bisschen static und non-static durcheinander... entweder das eine oder das andere.

Die UI sieht nach UI Builder aus - aufgrund der schrecklichen Namen und der setBounds.


----------



## Tomate_Salat (23. Dez 2011)

ehlr hat gesagt.:


> Welche Parameter meinst du ?



Parameter in der Methode: Siehe Beispiel ;-). 

```
public void doSomething(final Object meIsAParameter) {}
```


----------



## ehlr (23. Dez 2011)

Soo.
Habe das Programm fertig, es funktioniert sogar 1A.
Wer es mal testen möchte, bitte pn schreiben.

Hier der Code, vllt findet ihr ja Fehler :

*RechenTrainerGUI.java*

```
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;



@SuppressWarnings("serial")
public class RechenTrainerGUI extends JFrame {

	static RechenTrainer rt = new RechenTrainer();
	
	public static void main(String[] args) {
		@SuppressWarnings("unused")
		RechenTrainerGUI rtg = new RechenTrainerGUI();
		rt.next();
	}
	
	static JLabel lblExercise;
    private JLabel lblInstruction;
	private JLabel lblUserSolution;
	static JLabel lblTrueSolution;
	private JButton btnCheckSolution;
	private JButton btnNextExercise;
	private JTextField txtUserSolution;
	static JLabel lblYesOrNo;
	
	public RechenTrainerGUI() {
		this.getContentPane().setLayout(null); 
		this.initWindow();
		this.setBounds(750,100,350,200); 
		this.setTitle("Rechen-Trainer"); 
		this.setResizable(false); 
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 
		this.setVisible(true); 
	}
	
	private void initWindow() {
		lblExercise = new JLabel("x + x");
		lblInstruction = new JLabel("Bitte löse die Aufgabe!");
		lblUserSolution = new JLabel("Deine Lösung : ");
		lblTrueSolution = new JLabel();
		btnCheckSolution = new JButton("Lösung überprüfen");
	   	btnNextExercise = new JButton("Nächste Aufgabe");
	   	txtUserSolution = new JTextField();
	   	lblYesOrNo = new JLabel();
		
		
		lblInstruction.setBounds(10,10,150,25);
		lblExercise.setBounds(10,40,150,25);
		lblUserSolution.setBounds(10,70,100,25);
		lblTrueSolution.setBounds(10,100,100,25);
		btnCheckSolution.setBounds(10,130,150,25);
		btnNextExercise.setBounds(170,130,150,25);
		txtUserSolution.setBounds(110,70,150,25);
		lblYesOrNo.setBounds(120,100,150,25);
		
		lblExercise.setForeground(Color.red);
		
		this.getContentPane().add(lblExercise);
		this.getContentPane().add(lblInstruction);
		this.getContentPane().add(lblUserSolution);
		this.getContentPane().add(lblTrueSolution);
		this.getContentPane().add(btnCheckSolution);
		this.getContentPane().add(btnNextExercise);
		this.getContentPane().add(txtUserSolution);
		this.getContentPane().add(lblYesOrNo);
		
		this.pack();
		
		 
		  btnCheckSolution.addActionListener(new ActionListener() {
				
				public void actionPerformed(ActionEvent arg0) {	
					
					int userSolution = 0;
					
					try
					{ 
						userSolution = Integer.parseInt(txtUserSolution.getText().trim());
					}
					catch (NumberFormatException e)
					{ 
                        txtUserSolution.setText("Fehler bei der Eingabe!");
					}
					
					rt.setSolution();
					lblYesOrNo.setText(RechenTrainer.checkUserSolution(userSolution));
					
				}

				
				
		  });//ende actionlistener		
		  
		  btnNextExercise.addActionListener(new ActionListener() {
				
				public void actionPerformed(ActionEvent arg0) {	
					
					rt.next();
					lblTrueSolution.setText("");
					lblYesOrNo.setText("");
					txtUserSolution.setText("");
					
				}

				
				
		  });//ende actionlistener		
		  
	}//ende initwindow


}//ende class
```

*RechenTrainer.java*

```
import java.text.DecimalFormat;


public class RechenTrainer {
	
	private static String solutionStr;
	private static int solution;
	
	//Um neue Augabe zu stellen
	public void next() {
		RechenTrainerGUI.lblExercise.setText(neueAufgabe());
	}
	
	public void setSolution() {
		RechenTrainerGUI.lblTrueSolution.setText("Lösung : " + solutionStr);
	}
	
	static String neueAufgabe() {
		String aufgabe = "";
		int figur1 = (int)((Math.random()) * 200 + 1);
		int figur2 = (int)((Math.random()) * 200 + 1);
		DecimalFormat df = new DecimalFormat("#");
		solutionStr = df.format(figur1+figur2);
		solution = figur1+figur2;
		aufgabe = figur1 + " + " + figur2;
		return aufgabe;
	}
	
	static String checkUserSolution(final int userSolution){
		String yesOrNo = "Lösung ( " + userSolution + " ) ist falsch.";
		if (userSolution == solution) {
			yesOrNo = "Lösung ist richtig.";
		}
		return yesOrNo;
	}
	
	
	
}//ende class
```


----------



## Marcinek (23. Dez 2011)

Da fand ich aber die letzte Lösung cooler. 

Und kann das sein, dass das nun verschiedene Programme sind?

rt ist doch immer null?


----------



## ehlr (23. Dez 2011)

Mmh ja, ich habe ja auch geschrieben, dass ich versuche ein regelkonformes Programm in eine andere Sinnrichtung zu schreiben.
rt wird z.B. als Referenz bei rt.next(); verwendet.


----------



## Marcinek (23. Dez 2011)

Also das Programm ist höchstens syntaktisch korrekt aber dann wird es schwierig.

wenn du rt.next() aufrufst bekommst du eine NPE


----------



## ehlr (23. Dez 2011)

Ich habe doch eine Referenz zugewiesen :


```
static RechenTrainer rt = new RechenTrainer();
	
	public static void main(String[] args) {
		
		@SuppressWarnings("unused")
		RechenTrainerGUI rtg = new RechenTrainerGUI();
		rt.next();
        }
```


Ich bin mir nicht sicher, wo ich das Objekt erzeugen sollte, deshalb habe ich es über die main Methode gepackt.


Habe es gerade mal ohne static in die main methode reingepackt, dann bekomme ich aber bei den nächsten Referenz Aufrufen einen Fehler :


```
btnCheckSolution.addActionListener(new ActionListener() {	
		  public void actionPerformed(ActionEvent arg0) {	
					
			int userSolution = 0;
			try	{ 
	     		userSolution = Integer.parseInt(txtUserSolution.getText().trim());
			}catch (NumberFormatException e){ 
                txtUserSolution.setText("Fehler bei der Eingabe!");
			}
			rt.setSolution();
			lblYesOrNo.setText(RechenTrainer.checkUserSolution(userSolution));	
			
		  }//ende actionperformed		
		});//ende actionlistener
```


Dort wird rt nochmal verwendet.
Und dieser Fehler kommt nur nicht, wenn ich es über der main method als static mache.



Und so funktioniert alles :


```
static RechenTrainerGUI rtg = new RechenTrainerGUI();
	static RechenTrainer rt = new RechenTrainer();
	
	public static void main(String[] args) {
		rt.next();
	}
```


----------



## Marcinek (23. Dez 2011)

Hi,

Sorry ich bin doof... Ich habe das new Rechner im quelltext gesucht dabei war es ja schon als klassen variable


----------



## xehpuk (23. Dez 2011)

Da das noch nicht so deutlich hervorgehoben wurde …


VfL_Freak hat gesagt.:


> Das andere wäre ein Bitvergleich !


Das stimmt nicht. Zum einen müsste es einen Compilerfehler geben, zum anderen sind [c]&[/c] und [c]|[/c] keine Bitvergleiche, sondern Bitoperationen (die einen nummerischen Wert liefern).
Jedoch nicht nur. Sie sind ebenfalls boolesche Operatoren. Der Unterschied zu [c]&&[/c] und [c]||[/c] ist, dass die ersteren "eager operators" und die letzteren "short-circuit operators" sind. Das bedeutet, dass bei ersteren immer beide Ausdrücke ausgewertet werden, während bei letzteren der zweite nicht mehr ausgewertet wird, wenn das Ergebnis schon nach Auswertung des ersten feststeht ("false AND x" ergibt immer false, "true OR x" ergibt immer true, wobei x ein boolescher Ausdruck ist).


```
int a = 1;
int b = 0;
if (b != 0 && a / b > 42);
if (b != 0 & a / b > 42);
```
Der erste Vergleich läuft durch, beim zweiten fliegt eine ArithmeticException.


```
Object o = null;
if (o != null && o.hashCode() == 0);
if (o != null & o.hashCode() == 0);
```
Der erste Vergleich läuft durch, beim zweiten fliegt eine NullPointerException.

Short-circuit evaluation - Wikipedia, the free encyclopedia


----------



## turtle (24. Dez 2011)

Ich mache immer *TDD*, also _beginne _ich mit einem *Test *. *Danach *schreibe ich das Programm, um den* Test  erfolgreich* zu machen und *danach *führe ich ein *Refactoring *durch.

Dann weiss ich, dass das Programm noch funktioniert und habe gleichzeitig eine gute Testabdeckung. 

Dadurch liegt mein Hauptaugenmerk auf das "Fleisch" des Programms. Erst, wenn ich weiss, dass alles ordentlich funktioniert, beginne ich, eine GUI zu schreiben.


----------



## emailundlos (24. Dez 2011)

```
int eigenes = 2;
int anderes = 1;

// Stein: 1, Schere: 2; Papier: 3

if (eigenes == 1) {
  // oder switch
  if (anderes == 2) {
    winner();
  } else {
    loser();
  }
} else if (eigenes == 2) {
// usw.
}
```

hätte ist jetzt die abfrage programmiert.


----------



## turtle (24. Dez 2011)

Ich hätte definiert:

```
enum Stein {
	Papier, Stein, Schere
}
```


----------



## emailundlos (24. Dez 2011)

Richtig und dann muss noch undefined oder so etwas hinzu.


----------



## Landei (24. Dez 2011)

Wenn ich noch einen Rat geben dürfte: Schaffe dir Clean Code von Onkel Bob an. Ich wünschte, ich hätte es schon früher gelesen (auch wenn ich nicht mit allem 100% übereinstimme): Viele der dortigen Weisheiten habe ich mir selber mühsam erarbeiten müssen.


----------



## JavaProfi (25. Dez 2011)

Hallo ehrl,

dein Code ist noch ziehmlich dirty. Aber das sollte dich nicht entmutigen. Das wird schon.

Nun zum Problem. 
Die Verwendung des Modifiers "static" sollte nur in den dafür vorgesehenen Fällen verwandt werden. Mit static werden Klassenvariablen oder Klassenmethoden deklariert. Ein Anwendungsfall wäre z.B. die Definition von Klassenkonstanten in Verbindung mit dem Schlüsselwort "final".

Java ist eine objektorientierte Sprache und daher solltest du so weit wie möglich nur Objektvariablen und Objketmethoden verwenden. Deine Anwendung benötigt in keinem Fall "static"-definierte Variablen.

Wie ich das momentan sehe, entwickelst du interaktive Programme. Daher solltest du dich mit einem etablierten Architekturmuster für dieses Genre der Softewareentwicklung vertraut machen. 

Für die überwiegende Anzahl der interaktiven Software ist das MVC (Model-View-Controller) Architecture-Pattern geeignet.

MVC trennt komplexe Software in drei logisch voneinander getrennte modulare Komponenten.

(1) model : beinhaltet die Daten des Programms und stellt Methoden zur Datenmanipulation bereit (Datenmodell)

(2) view : visualisiert die Daten z.B. mittels einer GUI (Darstellung)

(3) controller : beinhaltet die Geschäftslogik (Funktionalität)
Die Komposition erfolgt durch das aufrufende Objekt oder eine aufrufende Klasse.

Damit legts du die Grundsteine für einen professionellen Code.
Versuche es mal. Ich habe mir die Mühe gemacht, deinen Code dem MVC entsprechend anzupassen. Vielleicht hast du Lust dir den Code mal anzusehen. ich habe dabei so viel wie möglich alten Code von dir behalten, damit du dich schnell zurechtfindest.

Kommentierung:
Zu jedem guten Quellcode gehört eine umfassende Kommentierung. Wenn hier die Rede davon ist "nicht zu viel zu kommentieren", dann zeugt das nur von wenig Ahnung. Wer guten professionellen code schreibt, der kommentiert diesen auch umfangreich. Jedoch solltest du dafür JavaDoc und nicht Zeilenkommentare verwenden. Dabei ist als Mindeststandard jede Klasse, jede Objektvariable und jede Methode zu kommentieren. Ich habe dir mal in der  Klasse "RechenTrainerController" ein paar JavaDoc-Kommentare als Beispiel eingefügt.

Und zu guter letzt: Jeder Programmierer findet seine eigenen Stil!

Gruß
Der JavaProfi (professional coder since 1983)

Aufrufende Klasse

```
public class Main {
    
    public static void main(String[] args) {
    	RechenTrainerModel model = new RechenTrainerModel();				
    	RechenTrainerGUI view = new RechenTrainerGUI(model);	
		new RechenTrainerController(model, view);	
    }
}
```

Model

```
public class RechenTrainerModel {
    private String solutionStr;
    private int solutionInt;
    
    
    public String getSolutionString(){
		return solutionStr;
    	
    }

    public void setSolutionString(String solution){
		this.solutionStr = solution;
    }

    public int getSolution(){
		return solutionInt;
    	
    }

    public void setSolution(int solution){
		this.solutionInt = solution;
    }
}
```

View

```
import java.awt.Color;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;


public class RechenTrainerGUI extends JFrame {
 	private static final long serialVersionUID = 1L;
    
    protected JLabel lblExercise;
    private JLabel lblInstruction;
    protected JLabel lblUserSolution;
    protected JLabel lblTrueSolution;
    protected JButton btnCheckSolution;
    protected JButton btnNextExercise;
    protected JTextField txtUserSolution;
    protected JLabel lblYesOrNo;
    
    public RechenTrainerGUI(RechenTrainerModel model) {
    	super("Rechen-Trainer");
        this.getContentPane().setLayout(null); 
        this.initWindow();
        this.setBounds(750,100,350,200); 
        this.setResizable(false); 
        this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);		
        this.setVisible(true); 
    }
    
    
    private void initWindow() {
        lblExercise = new JLabel("x + x");
        lblInstruction = new JLabel("Bitte löse die Aufgabe!");
        lblUserSolution = new JLabel("Deine Lösung : ");
        lblTrueSolution = new JLabel();
        btnCheckSolution = new JButton("Lösung überprüfen");
        btnNextExercise = new JButton("Nächste Aufgabe");
        txtUserSolution = new JTextField();
        lblYesOrNo = new JLabel();
        
        
        lblInstruction.setBounds(10,10,150,25);
        lblExercise.setBounds(10,40,150,25);
        lblUserSolution.setBounds(10,70,100,25);
        lblTrueSolution.setBounds(10,100,100,25);
        btnCheckSolution.setBounds(10,130,150,25);
        btnNextExercise.setBounds(170,130,150,25);
        txtUserSolution.setBounds(110,70,150,25);
        lblYesOrNo.setBounds(120,100,150,25);
        
        lblExercise.setForeground(Color.red);
        
        this.getContentPane().add(lblExercise);
        this.getContentPane().add(lblInstruction);
        this.getContentPane().add(lblUserSolution);
        this.getContentPane().add(lblTrueSolution);
        this.getContentPane().add(btnCheckSolution);
        this.getContentPane().add(btnNextExercise);
        this.getContentPane().add(txtUserSolution);
        this.getContentPane().add(lblYesOrNo);
        
        this.pack();
    }
}
```

Controller

```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;

/**
 * An instance of the class RechenTrainerController is the appropriate control unit to 
 * a view, instanced by the class RechenTrainerGUI according to the model-view-controller design pattern.
 * It contains all listener subclasses to handle the user events, fired by the view components.
 * Therefore the listeners register themselves with the according view's components.
 * @version 1.0
 * @author ehrl
 *
 */
public class RechenTrainerController {

	/** contains a reference to the datamodel */
	private RechenTrainerModel model;
	
	/** contains a reference to the view */
	private RechenTrainerGUI view;
	
	/**
	 * Constructs a new RechenTrainerController
	 * @param model - Reference to the view
	 * @param view - Reference to the data model
	 */
	public RechenTrainerController(RechenTrainerModel model, RechenTrainerGUI view){
		this.model = model;
		this.view = view;
		initListener();
		next();
	}
	
	/**
	 * The method register the listeners to the according components of the view. 
	 */
	private void initListener(){
		view.btnCheckSolution.addActionListener(new ButtonCheckListener());
		view.btnNextExercise.addActionListener(new ButtonNextListener());
	}

    private void next() {
    	view.lblExercise.setText(neueAufgabe());
    }
    
    private void showSolution() {
        view.lblTrueSolution.setText("Lösung : " + model.getSolutionString());
    }
    
    private String neueAufgabe() {
        String aufgabe = "";
        int figur1 = (int)((Math.random()) * 200 + 1);
        int figur2 = (int)((Math.random()) * 200 + 1);
        DecimalFormat df = new DecimalFormat("#");
        
        model.setSolutionString(df.format(figur1 + figur2));
        model.setSolution(figur1 + figur2);
        
        aufgabe = figur1 + " + " + figur2;
        return aufgabe;
    }
    
    private String checkUserSolution(int userSolution){
        String yesOrNo = "Lösung ( " + userSolution + " ) ist falsch.";
        if (userSolution == model.getSolution()) {
            yesOrNo = "Lösung ist richtig.";
        }
        return yesOrNo;
    }
    
    private class ButtonCheckListener implements ActionListener {
    	@Override
		public void actionPerformed(ActionEvent event) {
    		int userSolution = 0;
            
            try
            { 
                userSolution = Integer.parseInt(view.txtUserSolution.getText().trim());
            }
            catch (NumberFormatException e)
            { 
                view.txtUserSolution.setText("Fehler bei der Eingabe!");
            }
            
            showSolution();
            view.lblYesOrNo.setText(checkUserSolution(userSolution));	
		}
    }
    
    private class ButtonNextListener implements ActionListener {
    	@Override
		public void actionPerformed(ActionEvent e) {
    		   next();
               view.lblTrueSolution.setText("");
               view.lblYesOrNo.setText("");
               view.txtUserSolution.setText("");
		}
    }
    
}
```


----------



## ehlr (26. Dez 2011)

*Das ist wirklich sehr interessant und hilfreich.

Vielen Dank!!*


----------



## maki (26. Dez 2011)

> Zu jedem guten Quellcode gehört eine umfassende Kommentierung. Wenn hier die Rede davon ist "nicht zu viel zu kommentieren", dann zeugt das nur von wenig Ahnung. Wer guten professionellen code schreibt, der kommentiert diesen auch umfangreich. Jedoch solltest du dafür JavaDoc und nicht Zeilenkommentare verwenden. Dabei ist als Mindeststandard jede Klasse, jede Objektvariable und jede Methode zu kommentieren. Ich habe dir mal in der Klasse "RechenTrainerController" ein paar JavaDoc-Kommentare als Beispiel eingefügt.
> 
> Und zu guter letzt: Jeder Programmierer findet seine eigenen Stil!


Mal eine Frage an den selbsternannten "JavaProfi":
Wieso zeugt die Aussage "nicht zuviel kommentieren" von wenig Ahnung?

Was mir zB,. gar nicht klar ist, warum private Attribute mit JavaDoc kommentieren, wenn das JavaDoc tool in der Defaultkonfig keine Doku für private Attribute/Methoden erzeugt? 
"private" ist ja eindeutig ein Zeichen für ein Implementierungsdetail, dass dafür keine öffentliche Doku generiert wird ist Absicht.

Mal abgesehen von der Tatsache dass diese Kommentare nicht wirklich mehr INformationen als der Code selber hinzufügen:

```
/** contains a reference to the datamodel */
    private RechenTrainerModel model;
    
    /** contains a reference to the view */
    private RechenTrainerGUI view;
```
Bei guter Benamsung (wie hier gegeben) ist diese Art von JavaDoc überflüssig, also zuviel, in doppelter Hinsicht (1. keine erzeugte JavaDoc und falls doch gibt es plötzlich öffentliche Dokus für private Details, 2. keine zusätzlichen Informationen enthalten).

Nur mal ein paar Gedanken von jemadem der der Meinung ist dass man zuviel Dokumentieren kann und sich einbildet trotzdem ein bisschen Ahnung zu haben


----------



## Tomate_Salat (26. Dez 2011)

Noch eine Anmerkung zum MVC: Ich würde gegen Interfaces Programmieren. Ein konkreten View z.B. zu überschreiben wäre hier eher lästig (mal ein kleines Bsp):

```
class View 
{
	public View(String s) 
	{
		System.out.println("Ich bin ein View mit dem Titel " + s + " und bin eigentl. nur ein nerviges Fenster!!!");
		final JFrame frame=new JFrame("nerf");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		SwingUtilities.invokeLater(new Runnable() {
			
			@Override
			public void run() {
				frame.setVisible(true);
			}
		});		
	}
}

class MyBetterView extends View
{
	public MyBetterView(String s) 
	{
		super(s);
		System.out.println("Ich bin toller, starte aber leider trotzdem meinen vererbten View =(");
	}
}
```


----------



## fastjack (27. Dez 2011)

1. camelCase hinoderher, lies die Java Code Conventions von Oracle
2. Schmeiss die Zeilen-Kommentare raus, besonders diese ende-Teile
3. benutze auch mal else if(...)
4. Deine Klassen und Methoden sind zu groß, machen zu viele Sachen
5. Definiere mehr Klassen und Methoden, die immer nur eine Sache machen
6. Pack die inline-Klassen in vernünftige Klassen
7. if(a == 3 & b == 1) { sagt mir gar nix... besser wäre etwas wie if(isPlayerWinning())  { oder so
8. Nimm Patterns, z.B. MVC

Ich denke in diesem Fall würde ich auch erst mal ganz locker mit der GUI anfangen. Sobald ich aber eine Logik entdecke, mache ich eine entsprechende Klasse und Methoden daraus. In diesem Fall wird Deine Logik immer schön schlank bleiben und nur Sachen enthalten, die auch wirklich gebraucht werden. Du mußt aber aufpassen, das die GUI nicht zu viele Extrazeugs mit den gelieferten Daten macht, was womöglich schon wieder eher Logik wäre. 
Andersherum kannst DU Dir aber auch die GUI auf dem Papier oder sonst wo überlegen und daran Deine Logik implementieren.

Wenn Du es schaffst, mache TDD.

P.S.: Ich würde mich auch von den ganzen String-Repräsentationen in der Logik verabschieden, nimm Enums oder andere Rückgabewerte, die Du dann in der GUI entsprechend interpretierst.


----------



## JavaProfi (27. Dez 2011)

Sorry maki, 
ich wollte hier sicherlich niemanden angreifen! Aber ich erlaube mir bei mehr als 30 Jahren Programmiererfahrung und Inhaber der SCJD Lizenz deutlich Position zu beziehen.



maki hat gesagt.:


> Was mir zB,. gar nicht klar ist, warum private Attribute mit JavaDoc kommentieren, wenn das JavaDoc tool in der Defaultkonfig keine Doku für private Attribute/Methoden erzeugt?
> "private" ist ja eindeutig ein Zeichen für ein Implementierungsdetail, dass dafür keine öffentliche Doku generiert wird ist Absicht.



Nun ja, ich arbeite als Chief Software Development Officer in einem großen Softwarehaus. Du kannst dir sicherlich vorstellen, dass da große Projekte arbeitsteilig programmiert werden. Mein Team besteht aus bis zu 15 Programmierern. Da müssen Implementierungsdetails den anderen Programmierern durch die Kommentierung auch von privaten Attributen bekannt gemacht werden. Von uns erstellte JavaDoc werden wir als proprietäres Unternehmen niemandem außer unseren Entwicklern zur Verfügung stellen. Die Fluktuation bei den Programmierern ist ein weiterer Grund, wenn es darum geht Software zu erweitern oder Updates zu entwickeln. 

Der Aufwand wäre sonst viel zu groß sich in fremden Code einzuarbeiten.



maki hat gesagt.:


> Bei guter Benamsung (wie hier gegeben) ist diese Art von JavaDoc überflüssig, also zuviel, in doppelter Hinsicht (1. keine erzeugte JavaDoc und falls doch gibt es plötzlich öffentliche Dokus für private Details, 2. keine zusätzlichen Informationen enthalten).



Da widerspreche ich dir mal ausdrücklich und reflektiere auf meine langjährige Erfahrung bei der Programmierung größerer Projekte. Der Bezeichner kann noch so gut gewählt sein. Bei Projekten mit 1000 Klassen und 10 Programmierern verliert man schnell den Überblick, was denn Programmierer A mit der Bezeichnung "irgendwas" gemeint hat.

Für kleine Anwendungen, die du nur selber schreibst, weist du ja was du mit dem Bezeichner ausdrücken willst, da du die Semantik deines Begriffes ja selber gewählt hast. Bei 10 Programmierern hast du aber schnell 10 unterschiedliche Meinungen über ein und den selben Begriff.



maki hat gesagt.:


> Nur mal ein paar Gedanken von jemadem der der Meinung ist dass man zuviel Dokumentieren kann und sich einbildet trotzdem ein bisschen Ahnung zu haben



Wie o. a. kein böser Wille!


----------



## bERt0r (27. Dez 2011)

Ich weis ja nicht, ein Model für einen Rechentrainer sollte meiner Meinung nach folgendes machen:

Die Anzahl richtig und falsch gelöster Aufgaben speichern
Eine Methode bereitstellen, die eine neue Rechenaufgabe zurückgibt bzw. die nächste aus einer bestehenden Datenstruktur.
Ausserdem würde ich wirklich vom Null-Layout abraten. Das ist mMn ein unter den Anfängern hier im Forum viel zu weit verbreitetes Antipattern.


----------



## GUI-Programmer (27. Dez 2011)

@JavaProfi:


> Für die überwiegende Anzahl der interaktiven Software ist das MVC (Model-View-Controller) Architecture-Pattern geeignet.
> 
> MVC trennt komplexe Software in drei logisch voneinander getrennte modulare Komponenten.
> 
> ...



Ganz meiner Meinung. Endlich mal jemand, der weiß, wie man MVC sinnvoll implementieren kann. Denn die Theorie von MVC ist ja nicht wirklich schwer zu verstehen!

Bei deiner Controller Klasse hätte ich allerdings die Listener implementiert und den Buttons in der View die Controller Klasse als Listener hinzugefügt.

Aber wie gesagt: Jeder entwickelt halt seinen eigenen Programmierstil.


----------



## Landei (27. Dez 2011)

JavaProfi hat gesagt.:


> Da widerspreche ich dir mal ausdrücklich und reflektiere auf meine langjährige Erfahrung bei der Programmierung größerer Projekte. Der Bezeichner kann noch so gut gewählt sein. Bei Projekten mit 1000 Klassen und 10 Programmierern verliert man schnell den Überblick, was denn Programmierer A mit der Bezeichnung "irgendwas" gemeint hat.



Mit anderen Worten: Ein Programmierer, der nicht in der Lage ist, seine Variable so zu benamsen, dass seine Kollegen verstehen, was diese darstellen soll, soll also mit einem Kommentar den Kollegen erklären, was die Variable (genau die, die er nicht richtig benamsen konnte) eigentlich bedeutet. Aha.


```
...
   /**
     * The array buffer into which the components of the vector are
     * stored. The capacity of the vector is the length of this array buffer,
     * and is at least large enough to contain all the vector's elements.
     *
     * <p>Any array elements following the last element in the Vector are null.
     *
     * @serial
     */
    protected Object[] elementData;

    /**
     * The number of valid components in this {@code Vector} object.
     * Components {@code elementData[0]} through
     * {@code elementData[elementCount-1]} are the actual items.
     *
     * @serial
     */
    protected int elementCount;

    /**
     * The amount by which the capacity of the vector is automatically
     * incremented when its size becomes greater than its capacity.  If
     * the capacity increment is less than or equal to zero, the capacity
     * of the vector is doubled each time it needs to grow.
     *
     * @serial
     */
    protected int capacityIncrement;

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -2767605614048989439L;
    ...
```

Inwiefern ist das aussagefähiger als das folgende?


```
...
    protected Object[] elementData;
    protected int elementCount;
    protected int capacityIncrement;
    private static final long serialVersionUID = -2767605614048989439L;
   ...
```


----------



## JavaProfi (27. Dez 2011)

GUI-Programmer hat gesagt.:


> Bei deiner Controller Klasse hätte ich allerdings die Listener implementiert und den Buttons in der View die Controller Klasse als Listener hinzugefügt.
> Aber wie gesagt: Jeder entwickelt halt seinen eigenen Programmierstil.



Ja kann man in diesem Fall machen.
Ich gebe aber Folgendes zu bedenken:

(1) "Listener" sind interfaces und können daher sowohl als Schnittstelle implemtiert werden oder die Klasse erweitern. Das bedeutet aber, du musst immer alle Methoden im Controller implementieren!
Bei einer GUI mit einem umfangreichen Menü und Mouseevents kann das schnell sehr unübersichtlich werden. Alternativ (und davon mache ich in der Regel Gebrauch) kann man Adapter verwenden.

(2) "Adapter" sind hingegen abstrakte Klassen. Der Vorteil ist, dass man nur die Methoden implementieren muss, die man benötigt. Adapter kann man aber eben nicht als interfaces implementieren, da es abstrakte Klassen sind. Java kennt (und das ist gut so) keine Mehrfach-Vererbung.



GUI-Programmer hat gesagt.:


> Aber wie gesagt: Jeder entwickelt halt seinen eigenen Programmierstil.



GENAU !

Gruß
Der JavaProfi


----------



## JavaProfi (27. Dez 2011)

@ Landei
Danke für dieses wunderschöne Beispiel:
Es zeigt wunderschön das Problem. 

"elementCount" wäre ohne deine Erklärung im JavaDoc doch sehr abstrakt. Für dich und deine Semantik sicherlich eindeutig. Andere Programmierer hätten vielleicht folgende Bezeichner gewählt:

elementNumber
dataCount
currentMaxDataIndex
...

Folgende Interpretationsmöglichkeiten fallen mir spontan für "elementCount" ein:

(1) es beinhaltet die Anzahl aller der in elementData enthaltenen Objekte 

oder

(2) es beinhaltet die Anzahl aller der in elementData enthaltenen VALIDEN Objekte 

oder

(3) es legt die maximale Anzahl von Elementen in elementData fest

oder

(4) es ist eine Zähler, der Elemente aus elementData mit bestimmten Eigenschaften zählt 

usw.

Das Problem ist , dass man den Bezeichner so lang wählen müsste, damit er eindeutig ist und nicht mehrere Interpretationen zu lässt. Berücksichtige immer dabei, dass andere Personen, die deinen Code lesen mit ihrer Semantik deine Begriffe interpretieren. Ihre Semantik muss nicht (und das ist die Regel) mit deiner übereinstimmen.


----------



## Landei (27. Dez 2011)

- Bei (2)  wäre der Name schlecht gewählt, sollte dann [c]validElementCount[/c] oder so lauten
- Nummer (3) ist nicht sinnvoll, da ein Array maximal genau [c]array.length[/c] Elemente enthalten kann. Es wäre schon ziemlich überraschen, wenn man ein Array verwendet, dessen maximale Kapazität nie ausgeschöpft würde. 
- Bei (4) wäre der Name schlecht gewählt, sondern müsste dann z.B. [c]countXY[/c] oder so heißen.


Ich empfehle dir wirklich, einmal das enstprechende Kapitel in "Clean Code" zu lesen. Man muss nicht mit allem in dem Buch übereinstimmen, aber was dort über Kommentare gesagt wird, ist ziemlich überzeugend und stimmt zumindest mit meinen Beobachtungen überein.

Übrigens sollte bereits gute Namen für die Klasse und deren API-Methoden verhindern, dass man sich unnötigerweise deren Code anschaut, was die Anzahl der Leute, die sich wirklich die Innerein anschauen sollten, minimiert. Und die sollten dann auch wissen, was in dieser Klasse ungefähr zu erwarten ist.


----------



## kama (27. Dez 2011)

Hallo,



JavaProfi hat gesagt.:


> ...Aber ich erlaube mir bei mehr als 30 Jahren Programmiererfahrung und Inhaber der SCJD Lizenz deutlich Position zu beziehen.


Darf ich mal eine persönliche Frage stellen: Wie alt bist Du ? Ich selbst bin 47 und kriege gerade mal 30 Jahre zusammen...(mit 16 Angefangen)...



JavaProfi hat gesagt.:


> Nun ja, ich arbeite als Chief Software Development Officer in einem großen Softwarehaus. Du kannst dir sicherlich vorstellen, dass da große Projekte arbeitsteilig programmiert werden. Mein Team besteht aus bis zu 15 Programmierern. Da müssen Implementierungsdetails den anderen Programmierern durch die Kommentierung auch von privaten Attributen bekannt gemacht werden. Von uns erstellte JavaDoc werden wir als proprietäres Unternehmen niemandem außer unseren Entwicklern zur Verfügung stellen. Die Fluktuation bei den Programmierern ist ein weiterer Grund, wenn es darum geht Software zu erweitern oder Updates zu entwickeln.


Also ich habe noch nie erlebt, dass ein Projekt mit nur einem Entwickler durchgeführt wird somit wird immer im Team gearbeitet....und 15 Leute ist doch klein schaue Dir mal Projekte mit 200 Entwickerln an...



JavaProfi hat gesagt.:


> Der Aufwand wäre sonst viel zu groß sich in fremden Code einzuarbeiten.


Genau dafür sind gute Namen, kleine Methoden usw. Code Style Guides gut und vor allem Unit- und Integrationstests...90/10 Regel (siehe auch Clean-Code etc.)



JavaProfi hat gesagt.:


> Da widerspreche ich dir mal ausdrücklich und reflektiere auf meine langjährige Erfahrung bei der Programmierung größerer Projekte. Der Bezeichner kann noch so gut gewählt sein. Bei Projekten mit 1000 Klassen und 10 Programmierern verliert man schnell den Überblick, was denn Programmierer A mit der Bezeichnung "irgendwas" gemeint hat.


Damit zeigst Du genau auf den Punkt den @Maki meinte...mit "irgendwas" ist keinem geholfen...es sind sinnvolle Namen hilfreich...

Ein Kommentar sollte dann geschrieben werden wenn eine Entscheidung getroffen wurden (also warum)...das Wie beschreibt der Source-Code...oder wenn Performance Optimierungen (so sie denn Notwendig sind) den Code schlecht lesbar machen...

Ich betrachte das auch noch von einer anderen Seite: Ein Kommentar nur dann wenn der wirklich Notwendig ist...in den Beispielen die Du gezeigt hast sind alle Kommentar redundant...da keinerlei Mehrwert enthalten ist...ich muss und will keinem Entwickler etwas über MVC erzählen müssen...wenn der/die das nicht weiß hat er/sie im Projekt nichts verloren...Punkt...

Wenn ich mir weiterhin überlege, dass Du Kommentare wie in Deinem Beispiel schreibst (sprich überflüssig), dass stellt sich mir die Frage: Das Kostet Zeit und zwar in mehr als einer Hinsicht...
Zum einen wird der Kommentar geschrieben...Kostet Zeit und somit Geld...
Was aber noch schlimmer ist: Kommentare werden gelesen...das Kostet dann nochmal Zeit und Geld...(was schon im Code Steht also doppelt)...

Somit wird hier an mehreren Stellen Geld verschwendet...Betriebswirtschaftlich ist das schlicht Käse....Wenn ich das mal auf 1000 Klassen etc. hochrechne kommt schon eine Menge zusammen...geschweige wenn ich das auf 200 Entwickler und entsprechend mehr Klassen hochrechen....

Abgesehen davon kommt dazu dass es nie geschaft wird den Kommentar auch aktuell zu halten...der Code wird überarbeitet und geändert ...dann bleibt noch alter Kommentar stehen...
Jetzt kommt dann noch schlimmere Effekt: Kommentar wird gelesen (Zeit!)...Code wird gelesen...und jetzt ist die Frage: Wer hat recht? Kommentar / Code => Verwirrung...noch schlimmer...
Falsche Kommentare sind noch schlimmer als kein Kommentar...

Mal meine Meinung dazu....
Gruß
Karl Heinz Marbaise


----------



## JavaProfi (27. Dez 2011)

Ich habe wirklich nicht vor hier eine Grundsatzdiskussion zu führen, 
aber dennoch ein paar Anmerkungen.

(1) 
Mir geht das hier zu sehr durcheinander. Hier wird Kommentieren mit Dokumentieren synonym verwandt.
Wir unterscheiden in unserer Firma deutlich zwischen Quellcode-Kommentaren (implemetations comments)  und Quellcode-Dokumentation (documentation comments), so wie in den Sun-Code-Conventions auch vorgesehen.

(2) 
Die Clean-Code-Richtlinien sprechen von Kommentaren (implemetations comments) und da teile ich die Auffassung ganz und gar. Zudem hat jede größere Softwarehaus seine eigenen Richtlinien, so auch wir.

(3)@ Karl-Heinz
Wie du bereits angeführt hast: es ist ein (zugegebener Maßen unglückliches) BEISPIEL, mehr nicht. Es bringst nichts darauf herumzureiten ob der Inhalt des Kommentars inhaltschwer ist oder nicht. Meine Dokumentation hätte ich (hätte ich vorher um die Diskussion darum gewusst) anders gewählt. Es ging hier nur darum "sceptical" zu zeigen, wie (handling) man javaDoc schreibt und nicht darum den Inhalt auch noch auszudiskutieren. Inhaltlich gibt es wenig her. Das stimmt. Wir halten dennoch aus den dargelegten Gründen daran fest umfangreich mit JavaDoc zu dokumentieren. Ich denke da geht jede Firma mit eigenen Richtlinien ihren eignen Weg. Und wir haben damit sehr gute Erfahrungen gemacht.

Und: Ja tatsächlich, ich bin älter als du (aber unwesentlich älter). Bin froh dass ich nicht der einzige OLDIE hier bin. :toll: 

(4)
Ein Kommentar kann überflüssig sein, eine Dokumentation nur mehr oder weniger detailliert.
Kommentare MUSS man lesen, weil sie ja im Code implementiert sind. Das ist zeitraubend! JavaDocs MUSS MAN NICHT lesen, aber man KANN und DARF sie lesen. JavaDocs lassen sich genau aus diesem Grunde in Eclipse z. B. ausblenden oder nachträglich aus dem Code extrahieren.

(5)
Sun sah seinerzeit (und das ist nun auch schon aus 1997) in den Codeconventions vor, dass alle "classes, interfaces, constructors, methods, and ﬁelds" zu dokumentieren sind. Ich halte das immer noch für sinnvoll. Zu klassenweiten Variablen (und  nur um die geht es) wir keine Aussage getroffen. Schon gar nicht wird zwischen "public" oder "private" deklarierte Variablen unterschieden.

(6)
Ich glaube, dass es beim Kommentieren und Dokumentieren keinen Königsweg gibt. Insofern ist auch die Diskussion müßig, ob es SO oder SO richtig ist. Ich denke jede Sichtweise hat sicherlich ihren Platz. Bei uns hat es jedenfalls dazu geführt, dass im Code selbst keine Kommentare mehr vorkommen.

Gruß @ all und einen guten Rutsch ins neue Jahr
Wünsche allen die mit der Programmierung ihr Geld verdienen ein erfolgreiches 2012.


----------



## bERt0r (27. Dez 2011)

Irgendwie gehts hier komplett durcheinander. ehlr (der TO) hat einen einigermaßen sauberen Code für einen Anfänger gepostet. Bis auf die static methoden und das Null layout, hatte er schon ein ganz sauber nach MVC aufgebautes Programm, mit der Klasse RechenTrainer als Model, RechenTrainerGUI als View und dem ActionListener als Controller. (hiervon red ich)
JavaProfi, erlaube mir eine Frage: Du hast ja schon etliche Jahre mehr Programmier Erfahrung auf dem Bucke als ich, aber wie lang treibst du dich schon in Internetforen usw. herum? Deine ersten paar posts hier im Forum haben bei mir einfach keinen sehr netten Eindruck hinterlassen.


----------



## JavaProfi (27. Dez 2011)

bERt0r hat gesagt.:


> Irgendwie gehts hier komplett durcheinander. ehlr (der TO) hat einen einigermaßen sauberen Code für einen Anfänger gepostet. Bis auf die static methoden und das Null layout, hatte er schon ein ganz sauber nach MVC aufgebautes Programm, mit der Klasse RechenTrainer als Model, RechenTrainerGUI als View und dem ActionListener als Controller. (hiervon red ich)
> JavaProfi, erlaube mir eine Frage: Du hast ja schon etliche Jahre mehr Programmier Erfahrung auf dem Bucke als ich, aber wie lang treibst du dich schon in Internetforen usw. herum? Deine ersten paar posts hier im Forum haben bei mir einfach keinen sehr netten Eindruck hinterlassen.



Ja wenn dem so ist, dann wird es Zeit mich aus diesem Forum einfach leise zu verabschieden.
CU


----------



## maki (27. Dez 2011)

Hier braucht sich keiner zu verabschieden, ausser er/sie möchte unbedingt.

Meinungen gibt es immer viele, vor allem im Internet, solange man drüber diskutieren kann ist doch alles ok, man muss ja nicht derselben Meinung sein um sein Gegenüber trotzdem schätzen zu können.

In diesem Sinne...


----------



## ehlr (23. Dez 2011)

Hallöchen.
Ich bin Anfänger, habe aber schon einige Programme geschrieben.
Nun stellt sich für mich die Frage, ob ich auch wirklich "richtig" programmiere, also mit einem nahe zu normalen Programmierstil.

Hier ist ein Programm von mir (Schere-Stein-Papier) :

tester.java

```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

public class tester extends JFrame {

	int playerchoose = 0;
	int pcchoose = 0;
	static int wins = 0;
	static int loses = 0;
	static int score = 0;
	
	private static final long serialVersionUID = 689925824694774327L;

	public static void main(String[] args) {
		tester gui = new tester(); //objekt von gui wird erzeugt
		gui.setVisible(true); //Frame wird visible
		gui.setBounds(750,100,360,375); //Größe setzen
		gui.setTitle("Stein-Schere-Papier"); //Titel geben
		gui.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); //Prozess beenden, wenn X
		gui.setResizable( false ); //Nicht vergrößerbar
   	}//ende main method

	JLabel lblchoosen, lbltext1, lblpcchoosen;
	JLabel lbltext2;
	JLabel lblregel;
	JLabel lbltext3, lblwins, lblloses, lblscore;
	static JLabel lblgewinner;
	JButton button_stein, button_schere, button_papier;
	
	
	public tester() {
	  this.getContentPane().setLayout(null); 
	  this.initWindow();
	}//ende public gui
	
	protected void initWindow() {

	  button_stein = new JButton("Stein");
	  button_schere = new JButton("Schere");
	  button_papier = new JButton("Papier");
	  lblchoosen = new JLabel("Bereit");
	  lbltext1 = new JLabel("Ausgewählt :");
	  lblpcchoosen = new JLabel("Bereit");
	  lbltext2 = new JLabel("PC wählt :");
	  lblregel = new JLabel("<HTML><BODY>Schere schlägt Papier, Papier schlägt Stein,<BR>Stein schlägt Schere<BR><BR>Gewonnen : 10 Punkte<BR>Verloren : -8 Punkte<BR>Unentschieden : 2 Punkte</BODY></HTML>");
	  lbltext3 = new JLabel("Gewinner :");
	  lblgewinner = new JLabel("Noch nichts gewählt!");
	  lblwins = new JLabel("Gewonnen : 0");
	  lblloses = new JLabel("Verloren : 0");
	  lblscore = new JLabel("Punktestand : 0");
	  
	  
	  button_stein.setBounds(10,150,100,25);
	  button_schere.setBounds(120,150,100,25);
	  button_papier.setBounds(230,150,100,25);
	  lblchoosen.setBounds(100,195,150,25);
	  lbltext1.setBounds(10,195,100,25);
	  lblpcchoosen.setBounds(100,210,150,25);
	  lbltext2.setBounds(10,210,100,25);
	  lblregel.setBounds(10,10,300,100);
	  lbltext3.setBounds(10,250,90,25);
	  lblgewinner.setBounds(100,250,150,25);
	  lblwins.setBounds(10,295,100,25);
	  lblloses.setBounds(130,295,100,25);
	  lblscore.setBounds(10,315,150,25);
	  
	  	 
	  this.getContentPane().add(button_stein);
	  this.getContentPane().add(button_schere);
	  this.getContentPane().add(button_papier);
	  this.getContentPane().add(lblchoosen);
	  this.getContentPane().add(lbltext1);
	  this.getContentPane().add(lblpcchoosen);
	  this.getContentPane().add(lbltext2);
	  this.getContentPane().add(lblregel);
	  this.getContentPane().add(lbltext3);
	  this.getContentPane().add(lblgewinner);
	  this.getContentPane().add(lblwins);
	  this.getContentPane().add(lblloses);
	  this.getContentPane().add(lblscore);
		 
	  this.pack();
	  
	  button_stein.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent arg0) {	
				
				game game = new game();
				
				// Player nimmt Stein (1)
				int playerchoose = 1;
				
				// Zug des PCs ermitteln
				int pcchoose = (int)((Math.random()) * 3 + 1); 
				
				// Zahl in Stein,Schere oder Papier wandeln
				String ausgabe_player = game.wahl(playerchoose) ;
				String ausgabe_pc = game.wahl(pcchoose);
				
				// ausgewählte anzeigen
				lblchoosen.setText(ausgabe_player);
				lblpcchoosen.setText(ausgabe_pc);
				
				// Gewinner ermitteln
				String gewinner = game.prüfe(playerchoose, pcchoose); 
				lblgewinner.setText(gewinner);
				
				// Score 
				lblwins.setText("Gewonnen : " + wins);
				lblloses.setText("Verloren : " + loses);
				lblscore.setText("Punktestand : " + score);
				
			}

			
			
	  });//ende actionlistener		
	  
	  button_schere.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent arg0) {	
				
                game game = new game();
				
				// Player nimmt Papier (2)
				int playerchoose = 2;
				
				// Zug des PCs ermitteln
				int pcchoose = (int)((Math.random()) * 3 + 1); 
				
				// Zahl in Stein,Schere oder Papier wandeln
				String ausgabe_player = game.wahl(playerchoose) ;
				String ausgabe_pc = game.wahl(pcchoose);
				
				// ausgewählte anzeigen
				lblchoosen.setText(ausgabe_player);
				lblpcchoosen.setText(ausgabe_pc);
				
				// Gewinner ermitteln
				String gewinner = game.prüfe(playerchoose, pcchoose); 
				lblgewinner.setText(gewinner);
				
				// Score 
				lblwins.setText("Gewonnen : " + wins);
				lblloses.setText("Verloren : " + loses);
				lblscore.setText("Punktestand : " + score);
				
			}
			
	  });//ende actionlistener		
	  
	  button_papier.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent arg0) {	
				
                game game = new game();
				
				// Player nimmt Schere (3)
				int playerchoose = 3;
				
				// Zug des PCs ermitteln
				int pcchoose = (int)((Math.random()) * 3 + 1); 
				
				// Zahl in Stein,Schere oder Papier wandeln
				String ausgabe_player = game.wahl(playerchoose) ;
				String ausgabe_pc = game.wahl(pcchoose);
				
				// ausgewählte anzeigen
				lblchoosen.setText(ausgabe_player);
				lblpcchoosen.setText(ausgabe_pc);
				
				// Gewinner ermitteln
				String gewinner = game.prüfe(playerchoose, pcchoose); 
				lblgewinner.setText(gewinner);
				
				// Score 
				lblwins.setText("Gewonnen : " + wins);
				lblloses.setText("Verloren : " + loses);
				lblscore.setText("Punktestand : " + score);
				
			}
			
	  });//ende actionlistener		
		
	}//ende initwindow
	
	
}//ende class gui
```


game.java

```
import java.awt.Color;


public class game {
 
    
    public String wahl(int a) {
         
        String ausgabe = null;
        
        // 1 -> Stein
        if (a == 1) {
             ausgabe  = "Stein";
        }
        
        // 2 -> Schere
        if (a == 2) {
            ausgabe = "Schere";
        }
        
        // 3 -> Papier
        if (a == 3) {
            ausgabe = "Papier";
        }
            
 
        return ausgabe;
    }// ende methode
    
    
    
    public String prüfe(int a, int b) {
    	
    	String ausgabe = null;
   
    	if(a == 1 & b == 1) {
    		ausgabe = "Unentschieden!";
    		tester.lblgewinner.setForeground(new Color(0,0,0));
    		tester.score = tester.score + 2;
    	}
    	
    	if(a == 1 & b == 2) {
    		ausgabe = "Du gewinnst!";
    		tester.lblgewinner.setForeground(new Color(0,255,0));
    		tester.wins++;
    		tester.score = tester.score + 10;
    	}
    	
    	if(a == 1 & b == 3) {
    		ausgabe = "Du verlierst!";
    		tester.lblgewinner.setForeground(new Color(255,0,0));
    		tester.loses++;
    		tester.score = tester.score  -8;
    	}
    	
    	if(a == 2 & b == 1) {
    		ausgabe = "Du verlierst!";
    		tester.lblgewinner.setForeground(new Color(255,0,0));
    		tester.loses++;
    		tester.score = tester.score  -8;
    	}
    	
    	if(a == 2 & b == 3) {
    		ausgabe = "Du gewinnst!";
    		tester.lblgewinner.setForeground(new Color(0,255,0));
    		tester.wins++;
    		tester.score = tester.score + 10;
    	}
    	
    	if(a == 2 & b == 2) {
    		ausgabe = "Unentschieden!";
    		tester.lblgewinner.setForeground(new Color(0,0,0));
    		tester.score = tester.score + 2;
    	}
    	
    	if(a == 3 & b == 1) {
    		ausgabe = "Du gewinnst!";
    		tester.lblgewinner.setForeground(new Color(0,255,0));
    		tester.wins++;
    		tester.score = tester.score + 10;
    	}
    	
    	if(a == 3 & b == 2) {
    		ausgabe = "Du verlierst!";
    		tester.lblgewinner.setForeground(new Color(255,0,0));
    		tester.loses++;
    		tester.score = tester.score - 8;
    	}
    	
    	if(a == 3 & b == 3) {
    		ausgabe = "Unentschieden!";
    		tester.lblgewinner.setForeground(new Color(0,0,0));
    		tester.score = tester.score + 2;
    	}
    	
    	
    	
    	return ausgabe;
    }// ende methode
    
}// ende class
```


Was sollte ich am besten anders machen?


Besten Dank!

lg ehlr


----------



## java_rockt (27. Dez 2011)

Ja finde ich auch schade! R.I.P.


----------



## ehlr (27. Dez 2011)

Wie kinder


----------

