Richtiger Programmierstil ?

ehlr

Aktives Mitglied
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
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
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

Top Contributor
Was ich auf anhieb sehe:

Java:
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.
 

Fab1

Top Contributor
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

Top Contributor
Moin,

mir ist noch ein logischer Fehler aufgefallen:

Diese Prüfungen
Java:
if(a == 1 & b == 1)

sollten ja wohl vermutlich SO lauten :
Java:
if( (a == 1) && (b == 1) )  // 2x '&'
oder?
Das andere wäre ein Bitvergleich !

Gruß
Klaus
 

ehlr

Aktives Mitglied
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.
 
Zuletzt bearbeitet:
P

Pippl

Gast
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

Top Contributor
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

Top Contributor
Moin,

mir ist noch ein logischer Fehler aufgefallen:

Diese Prüfungen
Java:
if(a == 1 & b == 1)

sollten ja wohl vermutlich SO lauten :
Java:
if( (a == 1) && (b == 1) )  // 2x '&'
oder?

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

Top Contributor
Java:
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. :oops:

zu CamelCase:

DasIstCamelCaseManKannEsLesenObwohlKeineLeerzeichenDazwischenSind
 

ehlr

Aktives Mitglied
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


Wie sieht diese Trennung denn aus?
 
T

Tomate_Salat

Gast

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

Aktives Mitglied
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.

Ds hilft mir weiter!

Welche Parameter meinst du ?
 

ehlr

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

Wie findet ihr diesen Code (nicht fertig) :

Java:
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.
 
Zuletzt bearbeitet:

KSG9|sebastian

Top Contributor
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

Aktives Mitglied
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)

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

VfL_Freak

Top Contributor
Moin,

(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

Aktives Mitglied
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).

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

Gruß
Klaus

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

ehlr

Aktives Mitglied
Ist das korrekt ?

Java:
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
 
B

bygones

Gast
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.
 

ehlr

Aktives Mitglied
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
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
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
 
M

Marcinek

Gast
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

Aktives Mitglied
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.
 
M

Marcinek

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

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

ehlr

Aktives Mitglied
Ich habe doch eine Referenz zugewiesen :

Java:
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 :

Java:
		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 :

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

xehpuk

Top Contributor
Da das noch nicht so deutlich hervorgehoben wurde …
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).

Java:
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.

Java:
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
 
Zuletzt bearbeitet:

turtle

Top Contributor
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.
 
Zuletzt bearbeitet:
E

emailundlos

Gast
Java:
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.
 

Landei

Top Contributor
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

Aktives Mitglied
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
Java:
public class Main {
    
    public static void main(String[] args) {
    	RechenTrainerModel model = new RechenTrainerModel();				
    	RechenTrainerGUI view = new RechenTrainerGUI(model);	
		new RechenTrainerController(model, view);	
    }
}

Model
Java:
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
Java:
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
Java:
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("");
		}
    }
    
}
 
M

maki

Gast
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:
Java:
    /** 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 ;)
 
T

Tomate_Salat

Gast
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):
Java:
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

Top Contributor
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

Aktives Mitglied
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.

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.

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.

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

Top Contributor
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

Top Contributor
@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.

(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.

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

Top Contributor
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.

Java:
    ...
   /**
     * 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?

Java:
    ...
    protected Object[] elementData;
    protected int elementCount;
    protected int capacityIncrement;
    private static final long serialVersionUID = -2767605614048989439L;
   ...
 
Zuletzt bearbeitet:

JavaProfi

Aktives Mitglied
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.

Aber wie gesagt: Jeder entwickelt halt seinen eigenen Programmierstil.

GENAU !

Gruß
Der JavaProfi
 

JavaProfi

Aktives Mitglied
@ 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.
 
Zuletzt bearbeitet:

Landei

Top Contributor
- 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.
 
Zuletzt bearbeitet:

kama

Top Contributor
Hallo,

...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)...

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...

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.)

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

Aktives Mitglied
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 fields" 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

Top Contributor
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

Aktives Mitglied
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
 
M

maki

Gast
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...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
tun3d Packet trotz richtiger Addressierung nicht auffindbar? Java Basics - Anfänger-Themen 10
C initialisieren eines arrays richtiger Größe und mit geeignetem Datentyp Java Basics - Anfänger-Themen 26
V_Fynn03 Erste Schritte JButton funktioniert nicht trotz richtiger Methode. Java Basics - Anfänger-Themen 17
P Problem mit richtiger Formatierung :( Java Basics - Anfänger-Themen 1
F Richtiger Start in Java? Java Basics - Anfänger-Themen 2
G [Hibernate] Richtiger ColumnType Java Basics - Anfänger-Themen 2
E Drei zahlen sortieren und in richtiger Reihenfolde ausgeben. Java Basics - Anfänger-Themen 15
frau-u Probleme mit richtiger Verwendung von FileInputStream Java Basics - Anfänger-Themen 2
Avalon Programmierstil beim Mocken Java Basics - Anfänger-Themen 45
S Zugriff auf protected Fields = guter Programmierstil? Java Basics - Anfänger-Themen 11
K Sauberer Programmierstil? Java Basics - Anfänger-Themen 3
M Best Practice Programmierstil Graphen-A*-Suche Java Basics - Anfänger-Themen 5
F Erste Schritte Frage zum Programmierstil Java Basics - Anfänger-Themen 11
A OOP Fragen zu Programmierstil Java Basics - Anfänger-Themen 18
I Programmierstil Java Basics - Anfänger-Themen 64
M Sind ternäre Operatoren für einen guten Programmierstil wichtig ? Java Basics - Anfänger-Themen 10
M Programmierstil Java Basics - Anfänger-Themen 14
B Frage zu Programmierstil: sollte Hauptklasse nur main enthalten? Java Basics - Anfänger-Themen 6
G Guter Programmierstil? Java Basics - Anfänger-Themen 8
G Guter Programmierstil? Java Basics - Anfänger-Themen 4
D Programmierstil - Bei Vererbung welchen Typ benutzen? Java Basics - Anfänger-Themen 8
Bernasconi Programmierstil / Wann eine neue Datei? Java Basics - Anfänger-Themen 5
K guter Programmierstil Java Basics - Anfänger-Themen 3
C Programmierstil und OOP Java Basics - Anfänger-Themen 7
M Programmierstil Java Basics - Anfänger-Themen 17
D Programmierstil Java Basics - Anfänger-Themen 6

Ähnliche Java Themen

Neue Themen


Oben