Eine Familie von Microsoft-Suiten integrierter Entwicklungstools zum Erstellen von Anwendungen für Windows, das Web, mobile Geräte und viele andere Plattformen. Verschiedene Themen, die nicht in bestimmte Kategorien passen.
JavaFX SchulController refactoring, validation best practices, and code structure
I am currently working on a JavaFX application for school management (Schulverwaltung). I have written a Controller class (SchulController) that handles UI interactions, validates text input fields for first names, last names, postal codes, and roles (such as teacher or student), and updates both a ListView and a statistics label.
While the code is currently functional, I have several concerns regarding code quality, maintainability, and best practices in Java / JavaFX. I would appreciate some advice from the community on how to improve this. And please excuse the weird names of the methods, they are german.
My specific questions: Input Validation and Regex: In the onHinzufuegen() method, I am iterating over the characters of the first and last name to check if they only contain letters, spaces, or hyphens. Is there a cleaner, more idiomatic way to achieve this using Regular Expressions (Pattern / Matcher) or JavaFX TextFormatter?
Method Complexity and Refactoring: The onHinzufuegen() method has grown quite large and contains deep nested if-else statements. What is the best way to extract this validation and object creation logic into smaller, helper methods without breaking the JavaFX binding or event-handling structure?
Separation of Concerns: Should the validation logic (like checking the length of postal codes or role restrictions) reside directly inside the JavaFX Controller, or should it be delegated to a model/service layer? If so, how should errors be communicated back to the UI to display alerts properly?
Thank you very much in advance for your help! Here is my complete, unedited code:
public class SchulController {
@FXML
private RadioButton schuelerRadioButton;
@FXML
private RadioButton lehrerRadioButton;
@FXML
private TextField vornameField;
@FXML
private TextField nachnameField;
@FXML
private TextField rolleField;
@FXML
private TextField strasseField;
@FXML
private TextField plzField;
@FXML
private TextField ortField;
@FXML
private Label rolleLabel;
@FXML
private ListView<String> personenListView;
@FXML
private Label statistikLabel;
Schule schule = new Schule();
Adresse adresse = new Adresse("abc", 1234 , "abc");
Schueler schueler1 = new Schueler("willy", "wonka1",adresse , "123" );
Schueler schueler2 = new Schueler("willy", "wonka2",adresse , "123" );
Lehrer lehrer = new Lehrer("Willfried", "Unterrainer", adresse, "WSRU");
@FXML
public void initialize() {
IO.println("SchulverwaltungController initialized");
schule.personhinzufuegen(schueler1);
schule.personhinzufuegen(schueler2);
schule.personhinzufuegen(lehrer);
IO.println(lehrer.toString());
personenListView.getItems().add(lehrer.toString());
personenListView.getItems().add(schueler1.toString());
personenListView.getItems().add(schueler2.toString());
statistikAktualisieren();
}
@FXML
protected void onRolleGeaendert() {
if(lehrerRadioButton.isSelected())
{
rolleLabel.setText("Kürzel:");
rolleField.setPromptText("z.B JJWU");
}
else
{
rolleLabel.setText("Klasse:");
rolleField.setPromptText("z.B 3AHINF");
}
}
@FXML
protected void onHinzufuegen() {
Alert alert = new Alert(Alert.AlertType.ERROR);
if(vornameField.getText().isEmpty() || nachnameField.getText().isEmpty())
{
showAlert("Vornamefeld oder Nachnamefeld ist leer");
return;
}
String vorname = vornameField.getText();
for (int i = 0; i < vorname.length(); i++) {
char zeichen = vorname.charAt(i);
if (!Character.isLetter(zeichen)
&& zeichen != ' '
&& zeichen != '-') {
showAlert("Vorname ist inkompatibel");
return;
}
}
String nachname = nachnameField.getText();
for (int i = 0; i < nachname.length(); i++) {
char zeichen = nachname.charAt(i);
if (!Character.isLetter(zeichen)
&& zeichen != ' '
&& zeichen != '-') {
showAlert("Nachname ist inkompatibel");
return;
}
}
if(strasseField.getText().isEmpty() || ortField.getText().isEmpty())
{
showAlert("Straße ist falsch");
return;
}
if(plzField.getText().length() != 4)
{
showAlert("Postleitzahl ist falsch");
return;
}
if(Objects.equals(rolleLabel.getText(), "Klasse:"))
{
if(rolleField.getText().length() < 2 || rolleField.getText().length() > 6)
{
showAlert("Rolle ist falsch");
return;
}
char[] zeichen = rolleField.getText().toCharArray();
if(Character.isDigit(zeichen[0]))
{
int erste_zahl = Integer.parseInt(String.valueOf(zeichen[0]));
if(erste_zahl > 5 || erste_zahl < 1)
{
showAlert("Kein zeichen");
return;
}
}
Adresse adresse = new Adresse(strasseField.getText(),Integer.parseInt(plzField.getText()), ortField.getText());
Schueler schueler = new Schueler(vornameField.getText(), nachnameField.getText(), adresse, rolleLabel.getText());
schule.personhinzufuegen(schueler);
statistikAktualisieren();
personenListView.getItems().add(schueler.toString());
} else if (rolleField.getText().length() < 2 && rolleField.getText().length() > 4) {
showAlert("Es dürfen zwischen 2-4 Zeichen verwendet werden!");
return;
}
else
{
Adresse adresse = new Adresse(strasseField.getText(),Integer.parseInt(plzField.getText()), ortField.getText());
Lehrer lehrer = new Lehrer(vornameField.getText(), nachnameField.getText(), adresse, rolleLabel.getText());
schule.personhinzufuegen(lehrer);
statistikAktualisieren();
personenListView.getItems().add(lehrer.toString());
}
}
private void showAlert(String text) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Achtung!");
alert.setHeaderText((String)null);
alert.setContentText(text);
alert.showAndWait();
}
@FXML
protected void onFelderLeeren() {
personenListView.getItems().clear();
schule.personenLeeren();
statistikAktualisieren();
}
private void statistikAktualisieren() {
statistikLabel.setText(
"Schüler/innen: " + schule.getAnzahlSchueler()
+ " | Lehrer/innen: " + schule.getAnzahlLehrer()
);
}
}