Hur blir man bättre på errorhantering och felhantering?
Jag hade först och främst skrivit den yttersta if-satsen som:
if (modelName.isEmpty()) {
// namnet är tomt
} else if (modelName.contains(delimiter)) {
// namnet innehåller delimiter
} else if (modelName.contains("0")) {
// namnet innehåller 0
} else {
// namnet är ok!
}
Detta gör att du inte behöver kontrollera strängen två gånger när det är något fel på den som du gör nu, och du undviker felet du gjorde i din kod med att du kollar om den innehåller delimiter
första gången men ","
den andra.
Om du vill förenkla koden ytterligare så kan du dela upp metoden i en metod som läser in ett namn och kontrollerar att det har rätt format, samt en metod som försöker lägga till ett namn i databasen.
Det går väl också att använda ett reguljäruttryck för att kontrollera om strängen har rätt format, men då är det svårt att få reda på den exakta orsaken till varför strängen inte är giltig. Har du ett lite mer komplicerat format så är dock troligtvis reguljäruttryck vägen att gå.
Jag hade först och främst skrivit den yttersta if-satsen som:
if (modelName.isEmpty()) {
// namnet är tomt
} else if (modelName.contains(delimiter)) {
// namnet innehåller delimiter
} else if (modelName.contains("0")) {
// namnet innehåller 0
} else {
// namnet är ok!
}
Detta gör att du inte behöver kontrollera strängen två gånger när det är något fel på den som du gör nu, och du undviker felet du gjorde i din kod med att du kollar om den innehåller delimiter
första gången men ","
den andra.
Om du vill förenkla koden ytterligare så kan du dela upp metoden i en metod som läser in ett namn och kontrollerar att det har rätt format, samt en metod som försöker lägga till ett namn i databasen.
Det går väl också att använda ett reguljäruttryck för att kontrollera om strängen har rätt format, men då är det svårt att få reda på den exakta orsaken till varför strängen inte är giltig. Har du ett lite mer komplicerat format så är dock troligtvis reguljäruttryck vägen att gå.
Okej. Så det finns inget "python"-sätt i Java t.ex. "Do this" och sedan är det klart?
Det jag berömmer Python för är att man kan typ skriva en hel funktionalitet på en enda rad.
Okej. Så det finns inget "python"-sätt i Java t.ex. "Do this" och sedan är det klart?
Det jag berömmer Python för är att man kan typ skriva en hel funktionalitet på en enda rad.
Python är definitivt bra på det. Det finns dock saker du kan göra för att förenkla din kod som gör det snyggare och kanske inte mer lättläst men iaf mer snabbläst. Tex att if(condition) {} snarare än if(condition == true). Denna kan du t.ex ändra från if (createModel(modelName) == true) till if(createModel(modelName)){} och om exist är false kan du kolla med if(!exist).
Har förvisso inte med felhantering att göra men en sak jag såg direkt när jag kollade koden
Python är definitivt bra på det. Det finns dock saker du kan göra för att förenkla din kod som gör det snyggare och kanske inte mer lättläst men iaf mer snabbläst. Tex att if(condition) {} snarare än if(condition == true). Denna kan du t.ex ändra från if (createModel(modelName) == true) till if(createModel(modelName)){} och om exist är false kan du kolla med if(!exist).
Har förvisso inte med felhantering att göra men en sak jag såg direkt när jag kollade koden
Jag värderar lättläshet mer än snyggare här faktiskt
Okej. Men då förstår jag att det handlar bara om att träna och träna och det finns inga smarta knep, förutom lambdauttryck som jag ofta använder mig utav.
Kör fortfarande Java 8. Ska gå över till Java 11 när GluonHQ släpper stabila java versionen för Iphone och Android.
Jag förstår inte vad du menar med Python-sätt i det här läget.
Så här hade jag refaktorerat din kod i ett första steg:
/**
* Create a new table row inside the table view
*/
private void createNewTableRow() {
String modelName = dialogs.input("New", "Enter new name");
if (modelName.contains(",")) {
dialogs.alertDialog(AlertType.ERROR, "Cannot use ','", "Select another file name.");
return;
}
if (modelName.contains("0")) {
dialogs.alertDialog(AlertType.ERROR, "Cannot use '0'", "Select another file name.");
return;
}
if (modelName.equals("")) {
dialogs.alertDialog(AlertType.INFORMATION, "Missing name", "Select a file name");
return;
}
if (networkTableCSV.exist(modelName, "Name")) {
dialogs.alertDialog(AlertType.ERROR, "Exist", "File name already exist.");
return;
}
/*
* kanske refaktorera createModel så att den kastar en exception istället?
* den här sortens felkontroll känns väldigt "C"-ig
*/
if (!createModel(modelName)) {
dialogs.alertDialog(AlertType.ERROR, "Creation", "Could not create model!");
return;
}
reloadTable();
networkTable.getSelectionModel().selectLast();
selectedRowIndex = networkTable.getSelectionModel().getSelectedIndex();
}
Jag hade sedan övervägt att faktorera ut kontrollen som validerar om modellnamnet är giltigt som en egen hjälpfunktion. Eller kanske flytta denna kontroll till createModel? Och sedan kasta ett fel från createModel beroende på vad det är för slags fel... idag returnerar du bara sant/falskt från createModel, här kan du utnyttja exceptions och kasta olika sorters fel som du sedan presenterar grafiskt i själva felhanteringskoden.
(Du kanske till och med kan göra en metod i dina exceptions som visar en dialogruta för felet!)
Posta createModel också så får vi se vad vi kan köra, känns som att det är där all felkontrollen egentligen ska ligga, medan createNewTableRow borde foka på GUI-meck. För egentligen borde din kod kunna vara typ:
/**
* Create a new table row inside the table view
*/
private void createNewTableRow() {
String modelName = dialogs.input("New", "Enter new name");
try {
createModel(modelName);
reloadTable();
networkTable.getSelectionModel().selectLast();
selectedRowIndex = networkTable.getSelectionModel().getSelectedIndex();
} catch (MissingModelNameException e) {
dialogs.alertDialog(AlertType.INFORMATION, "Missing name", "Select a file name");
} catch (InvalidModelNameException e) {
dialogs.alertDialog(AlertType.ERROR, e.message, "Select another file name.");
} catch (FileAlreadyExistsException e) {
dialogs.alertDialog(AlertType.ERROR, "Exist", "File name already exist.");
} catch (ModelCreationException e) {
dialogs.alertDialog(AlertType.ERROR, "Creation", "Could not create model!");
}
}
Ett tredje steg i refaktorering är att fundera på om det ens är createNewTableRow som ska ha ansvaret att faktiskt visa felmeddelandedialogerna. Beror ju helt på var den anropas. Då skulle createNewTableRow kunna se ut så här:
/**
* Create a new table row inside the table view
*/
private void createNewTableRow() {
String modelName = dialogs.input("New", "Enter new name");
createModel(modelName);
reloadTable();
selectedRowIndex = networkTable.getSelectionModel().getSelectedIndex();
}
(Eventuellt med en throws-del i själva metodsignaturen.) Sedan skulle själva felvisningsdelen kunna ligga i den kod som anropar.
Jag förstår inte vad du menar med Python-sätt i det här läget.
Så här hade jag refaktorerat din kod i ett första steg:
/**
* Create a new table row inside the table view
*/
private void createNewTableRow() {
String modelName = dialogs.input("New", "Enter new name");
if (modelName.contains(",")) {
dialogs.alertDialog(AlertType.ERROR, "Cannot use ','", "Select another file name.");
return;
}
if (modelName.contains("0")) {
dialogs.alertDialog(AlertType.ERROR, "Cannot use '0'", "Select another file name.");
return;
}
if (modelName.equals("")) {
dialogs.alertDialog(AlertType.INFORMATION, "Missing name", "Select a file name");
return;
}
if (networkTableCSV.exist(modelName, "Name")) {
dialogs.alertDialog(AlertType.ERROR, "Exist", "File name already exist.");
return;
}
/*
* kanske refaktorera createModel så att den kastar en exception istället?
* den här sortens felkontroll känns väldigt "C"-ig
*/
if (!createModel(modelName)) {
dialogs.alertDialog(AlertType.ERROR, "Creation", "Could not create model!");
return;
}
reloadTable();
networkTable.getSelectionModel().selectLast();
selectedRowIndex = networkTable.getSelectionModel().getSelectedIndex();
}
Jag hade sedan övervägt att faktorera ut kontrollen som validerar om modellnamnet är giltigt som en egen hjälpfunktion. Eller kanske flytta denna kontroll till createModel? Och sedan kasta ett fel från createModel beroende på vad det är för slags fel... idag returnerar du bara sant/falskt från createModel, här kan du utnyttja exceptions och kasta olika sorters fel som du sedan presenterar grafiskt i själva felhanteringskoden.
(Du kanske till och med kan göra en metod i dina exceptions som visar en dialogruta för felet!)
Posta createModel också så får vi se vad vi kan köra, känns som att det är där all felkontrollen egentligen ska ligga, medan createNewTableRow borde foka på GUI-meck. För egentligen borde din kod kunna vara typ:
/**
* Create a new table row inside the table view
*/
private void createNewTableRow() {
String modelName = dialogs.input("New", "Enter new name");
try {
createModel(modelName);
reloadTable();
networkTable.getSelectionModel().selectLast();
selectedRowIndex = networkTable.getSelectionModel().getSelectedIndex();
} catch (MissingModelNameException e) {
dialogs.alertDialog(AlertType.INFORMATION, "Missing name", "Select a file name");
} catch (InvalidModelNameException e) {
dialogs.alertDialog(AlertType.ERROR, e.message, "Select another file name.");
} catch (FileAlreadyExistsException e) {
dialogs.alertDialog(AlertType.ERROR, "Exist", "File name already exist.");
} catch (ModelCreationException e) {
dialogs.alertDialog(AlertType.ERROR, "Creation", "Could not create model!");
}
}
Smart sätt! Jag brukar sällan använda return vid void metoder! Jag ska införa detta! Blir mycket smidigare då
Känns som om metoden har ett större ansvar än den utger sig för att ha. Den heter createNewTableRow men gör koller och hanterar utskrifter. Försök att plocka isär den tills den enbart gör det den utger sig för att göra, det kommer också göra det enklare att återanvända kod i framtiden.
Skickades från m.sweclockers.com
Känns som om metoden har ett större ansvar än den utger sig för att ha. Den heter createNewTableRow men gör koller och hanterar utskrifter. Försök att plocka isär den tills den enbart gör det den utger sig för att göra, det kommer också göra det enklare att återanvända kod i framtiden.
Skickades från m.sweclockers.com
Så här blev mitt resultat! Renare kod.
import java.io.File;
import com.gluonhq.charm.glisten.animation.BounceInRightTransition;
import com.gluonhq.charm.glisten.application.MobileApplication;
import com.gluonhq.charm.glisten.control.AppBar;
import com.gluonhq.charm.glisten.mvc.View;
import com.gluonhq.charm.glisten.visual.MaterialDesignIcon;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseEvent;
public class ModelsPresenter {
@FXML
private View models;
@FXML
private TableView<String> tableView;
@FXML
private TableColumn<String, String> columnName;
/*
* Fields
*/
private FileHandler fileHandler = new FileHandler();
private Dialogs dialogs = new Dialogs();
private final String modelPath = "/Deeplearning2CStorage/Models/";
private ObservableList<String> list;
public void initialize() {
/*
* Run this test so we make sure that we can create and delete files
*/
fileHandler.runCreateDeleteTest(modelPath + "test" + ".zip");
/*
* Slide smooth in and out
*/
models.setShowTransitionFactory(BounceInRightTransition::new);
/*
* Listener for leaving and enter the page
*/
models.showingProperty().addListener((obs, oldValue, newValue) -> {
if (newValue) {
/*
* Enter the page
*/
AppBar appBar = MobileApplication.getInstance().getAppBar();
appBar.setTitleText("Models");
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> MobileApplication.getInstance().getDrawer().open()));
appBar.getActionItems().add(MaterialDesignIcon.CREATE.button(e -> createModel()));
appBar.getActionItems().add(MaterialDesignIcon.SAVE.button(e -> saveModel()));
appBar.getActionItems().add(MaterialDesignIcon.DELETE.button(e -> deleteModel()));
}else {
/*
* Leaving the page
*/
}
});
/*
* ObservableList to table view
*/
columnName.setCellValueFactory(data -> new SimpleStringProperty(data.getValue()));
list = FXCollections.observableArrayList();
tableView.setItems(list);
/*
* Update the table view if we have files and select first row
*/
int totalFiles = fileHandler.countFiles(".zip", modelPath);
if(totalFiles > 0) {
updateTableView();
tableView.getSelectionModel().selectFirst();
}
}
/**
* Delete our model and update table
*/
private void deleteModel() {
if(dialogs.question("Delete", "Do you want to delete?") == true) {
String modelName = tableView.getSelectionModel().getSelectedItem();
int selectedRow = tableView.getSelectionModel().getSelectedIndex() + 1;
int totalFiles = fileHandler.countFiles(".zip", modelPath);
fileHandler.deleteFile(modelPath + modelName + ".zip");
updateTableView();
if(selectedRow == totalFiles) // selectedRow can never be larger than totalFiles
tableView.getSelectionModel().selectLast();
else
tableView.getSelectionModel().select(selectedRow-1);
}
}
/**
* Save the configurations
*/
private void saveModel() {
}
/**
* Create a new model
*/
private void createModel() {
/*
* Pop-up dialog that ask for a name
*/
String modelName = dialogs.input("New", "Enter new name");
/*
* Exceptions
*/
if(modelName.equals("test") == true) {
dialogs.alertDialog(AlertType.INFORMATION, "Cannot use 'test'", "Select another file name."); // Look at initialize()
return;
}
if(modelName.equals("") == true) {
return;
}
/*
* Create the file and update the table and then select last row
*/
fileHandler.createNewFile(modelPath + modelName + ".zip");
updateTableView();
tableView.getSelectionModel().selectLast();
/*
* Insert a real basic model into that .zip file we just created. Then save it.
*/
DL4JModel dL4JModel = new DL4JModel();
dL4JModel.createBasicModel(modelPath + modelName + ".zip");
}
/**
* This method will update the table view
*/
private void updateTableView() {
list.clear();
File[] files = fileHandler.scanFolder(".zip", modelPath);
if(files != null)
for(File file : files)
list.add(file.getName().replace(".zip", ""));
}
/**
* When we click on the table view, e.g on a row, then we going to load a model
* @param event Mouse event
*/
@FXML
void clickedOnTableView(MouseEvent event) {
}
}
Jag värderar lättläshet mer än snyggare här faktiskt
Det är inte lättläst att skriva x == true
. Eller vad sägs om följande?
if (createModel(modelName) == true == true == true) {
// …
}
modelName.contains(delimiter) == false
kan jag se anledning att skriva, då det är lätt hänt att läsa !modelName.contains(delimiter)
som modelName.contains(delimiter)
eller vice versa. Har själv i ett liknande sammanhang använt en funktion isFalse
(i TypeScript) just för att minimera risken att en läsare missar ett !
före ett lite större booleskt uttryck, men vet inte hur vanligt eller accepterat det är i verkligheten. Kände mig lite löjlig när jag gjorde det.
Skrivet med hjälp av Better SweClockers
- Igår Quiz: Har du koll på det senaste inom processorkylare? 66
- Igår Cooler Master Ncore 100 Max – lättbyggt minstingchassi 12
- 27 / 3 Nytt vetenskapligt genombrott kan lösa OLED-inbränning 46
- 27 / 3 Microsoft vill göra handhållen Xbox 41
- 26 / 3 Microsoft patenterar teknik för bättre ray tracing-prestanda 27
- Igår Ny RAM-sparande funktion upptäckt i Microsoft Edge 7
- Igår Så byter du till gamla Notepad i Windows 11 32
- Igår Microsoft Copilot kan snart köras direkt på datorn 14
- 27 / 3 Stort steg för Windows på ARM: Google släpper optimerat Chrome 26
- 27 / 3 Xbox-chef är öppen för fler spelbutiker på konsol 23
- Igår Svenska Embracer säljer Gearbox för 4,9 miljarder kronor 14
- Igår Var femte användare har lämnat X sedan Musk tog över 111
- 27 / 3 Veckans fråga: Hur gammalt är ditt Steam-konto? 162
- 27 / 3 Bluffkampanj sprider sig genom Googles AI-sökfunktion 11
- 26 / 3 82 studenter avstängda för AI-fusk – Uppsala strängast 55
- Quiz: Har du koll på det senaste inom processorkylare?67
- Microsoft Copilot kan snart köras direkt på datorn14
- Plats för lite gubbgnäll9648
- Hur gör ni med jobbmobilen?150
- Var femte användare har lämnat X sedan Musk tog över111
- ATX 3.0 - Vilken skillnad!1
- Windows session minimerar öppnade dokument vid första gången uppstart2
- Två stycken asus Prime b450m-a II vägrar boots0
- Hur mkt kan jag sälja min dator för1
- Kan jag få in ett grafikkort i den här workstation-burken13
- Säljes 2 Auktioner - Lenovo T14 G3 och Nvidia A4000
- Köpes Söker 24-25" 240hz+ 1080p. Ev byte mot 1440p 165hz
- Köpes Desktop/"server"/Workstation, 128gb RAM (t.ex. LGA 2011-system) eller delar till sådant system
- Säljes Playstation 5 - Digital Edition
- Säljes Acer Nitro N50-600 (9400F, 1660 Ti, 32 GB RAM & 500 GB SSD)
- Säljes Utförsäljning: 3 stycken helt nya roomba robotdammsugare säljes till bra pris.
- Säljes Kingston 32GB (2x16GB) DDR5 6000MHz CL36 FURY Beast
- Säljes Gigabyte B650I Aorus Ultra AM5 - garanti
- Säljes apple macbook pro 16 m1 max 32gb ram 1tb ssd
- Säljes Apple iPad Pro 11'' 5G (gen 4)
- Ny RAM-sparande funktion upptäckt i Microsoft Edge7
- Quiz: Har du koll på det senaste inom processorkylare?67
- Svenska Embracer säljer Gearbox för 4,9 miljarder kronor14
- Cooler Master Ncore 100 Max – lättbyggt minstingchassi12
- Var femte användare har lämnat X sedan Musk tog över111
- Så byter du till gamla Notepad i Windows 1132
- Microsoft Copilot kan snart köras direkt på datorn14
- Stort steg för Windows på ARM: Google släpper optimerat Chrome26
- Nytt vetenskapligt genombrott kan lösa OLED-inbränning46
- Xbox-chef är öppen för fler spelbutiker på konsol23