Refactored GUI tools made with Java8 + JavaFX in 2016
Contents
- 4 years ago from May 4, 2020, write a story about refactoring GUI tools that I made as a hobby when I was a student at that time.
- Click here for the refactored repository
- https://github.com/jiro4989/TKoolFacetileMaker2
background
- A tool called TKoolFacetileMaker2 was released on the unofficial forum of RPG Maker in July 2016
- https://github.com/jiro4989/TKoolFacetileMaker2
- I remember when Java 8 was still new when I created it.
- Four years later, Java is now 14.
- I stopped writing Java at work and became more interested in Nim and Go
- Result maintenance was virtually neglected
- I know from email notifications that some people are still using it after 4 years.
- There is no obligation to perform maintenance, but as a technician, I have become more and more unwilling to leave old things as they are.
- It's no longer a good idea to have users install Java 8
- I would rarely use this tool, but I decided to lift my back and maintain it.
The problem I was having
- I was still a student when I made this tool, so I had a lot of problems making it.
- For example
- I'm building with an old build tool called ant
- Package and class naming conventions are not defined and are not common in Java projects
- In Java, the reverse order of domains is common for package names.
- It's strange that it doesn't happen
- Not in MVC style, logic is scattered everywhere
- Logic may or may not be stuck in the controller class
- Shit, to say the least
- The project structure is not the general structure of a Java project and cannot be imported into IntelliJ
- There is no such thing as
src / main / java
resources
exists with the source code
- No test code
- ** Some code of dependent libraries is not left and cannot be built in the first place **
- It depends on my own library, but the source code of the library does not remain.
- I don't know how to build because there are no build procedures left
- I don't know how to build because the dependent library is missing and I don't know how to get it.
- I was frustrated trying to refactor once in 2018
- I tried to port to kotlin while moving to gradle and it was difficult
- If you upgrade from Oracle Java 8 to Open JDK 11, the build method will change because JavaFX has been separated from the JDK.
- Frustrated due to various reasons
- Two years later, as a result of various studies, it was decided to refactor and continue maintenance with Java.
Problem decomposition
- We decided to break down the above problems and crush them one by one.
- Clarified problems and things to do in GitHub Issues
- If you try to do it all at once, you will die
- I will do it later, so I will not do it now
- issues
- Allow to build with gradle
- Manual build is fine at first
- Allow to build with CI
- Be ready to build / release
- Code format
- Follow Google coding style
- Upgrade Java
- From Java 8 to Java 14
- Refactor
- Assuming writing test code
- Make it MVC
- Automatically test with CI
- Maintain test code
- Document maintenance
- Write a developer documentation (for yourself)
What was important
- Anyway, "maintaining a buildable state" is the highest priority
- Start after preparing for automatic build with CI
- Die if you can't find it broken early
- Do not perform release build on local PC
- Development environment can change
- If you can build and release in CI environment, you can release at any time
- Anything can be handed over to another person
- Implemented on the assumption that it will be automatically tested by CI
- Separate UI and logic
- Allow only the logic part to be tested
- Logic modeling
What I did / what I was able to do
Finally achieved my wish on 5/11/2020
Now works with custom JRE
- Since it is distributed together with the custom JRE, it is no longer necessary to install the JRE on the user PC in advance.
- Double-click the enclosed startup script to start the GUI
- I was impressed when I started it in an environment where Java was not installed ...
- File size is now about 50MB
- It's quite big, but it's unavoidable
Automatic build and automatic release with CI
- Binaries will be released when the release draft is published on GitHub Actions
- https://github.com/jiro4989/TKoolFacetileMaker2/releases
Automatic format
Changed to format before build with google-java-format-gradle-plugin
Visualization of test coverage
- Enabled to get test coverage with Gradle plugin called Jacoco
- Visualized test coverage with CodeCov
- Increased the test coverage rate of logic parts such as Model to 90% or more.
- https://codecov.io/gh/jiro4989/TKoolFacetileMaker2
- I gave up because it seemed difficult to test the UI part
Code diet
- The number of lines of code has been greatly reduced because the functions that were deemed unnecessary have been completely deleted.
- Take full advantage of JavaFX's original property binding feature
- Now you don't have to set the value
Before refactoring
$ find src/ -name '*.java' | xargs wc -l
31 src/application/fileList/FileListHBox.java
189 src/application/fileList/FileListHBoxController.java
31 src/application/imageViewer/ImageViewerBorderPane.java
288 src/application/imageViewer/ImageViewerBorderPaneController.java
92 src/application/Main.java
471 src/application/MainController.java
44 src/application/options/Numberings.java
104 src/application/options/Options.java
40 src/application/options/OptionsStage.java
165 src/application/options/OptionsStageController.java
69 src/application/options/Separators.java
36 src/application/outputViewer/MyButton.java
122 src/application/outputViewer/MyImageView.java
33 src/application/outputViewer/OutputViewerAnchorPane.java
130 src/application/outputViewer/OutputViewerAnchorPaneController.java
25 src/application/TKoolVersion.java
29 src/application/version/VersionStage.java
42 src/application/version/VersionStageController.java
1941 total
After completion
- The number of test cases is now 90
# main
$ find src/main/java/ -name '*.java' | xargs wc -l
8 src/main/java/com/jiro4989/tkfm/data/CropSize.java
42 src/main/java/com/jiro4989/tkfm/data/Position.java
38 src/main/java/com/jiro4989/tkfm/data/Rectangle.java
67 src/main/java/com/jiro4989/tkfm/Main.java
422 src/main/java/com/jiro4989/tkfm/MainController.java
235 src/main/java/com/jiro4989/tkfm/model/CroppingImageModel.java
21 src/main/java/com/jiro4989/tkfm/model/ImageFileModel.java
52 src/main/java/com/jiro4989/tkfm/model/ImageFilesModel.java
211 src/main/java/com/jiro4989/tkfm/model/PropertiesModel.java
133 src/main/java/com/jiro4989/tkfm/model/TileImageModel.java
15 src/main/java/com/jiro4989/tkfm/util/ImageUtil.java
6 src/main/java/com/jiro4989/tkfm/Version.java
1250 total
# test
$ find src/test -name '*.java' | xargs wc -l
13 src/test/java/com/jiro4989/tkfm/data/CropSizeTest.java
29 src/test/java/com/jiro4989/tkfm/data/PositionTest.java
26 src/test/java/com/jiro4989/tkfm/data/RectangleTest.java
212 src/test/java/com/jiro4989/tkfm/model/CroppingImageModelTest.java
28 src/test/java/com/jiro4989/tkfm/model/ImageFileModelTest.java
64 src/test/java/com/jiro4989/tkfm/model/ImageFilesModelTest.java
143 src/test/java/com/jiro4989/tkfm/model/PropertiesModelTest.java
120 src/test/java/com/jiro4989/tkfm/model/TileImageModelTest.java
43 src/test/java/com/jiro4989/tkfm/util/ImageUtilTest.java
13 src/test/java/com/jiro4989/tkfm/VersionTest.java
691 total
Test code maintenance
- As mentioned above, the test coverage of the logic part has been increased to 90% or more.
- Introduced the TestFX plugin to test JavaFX
- In CI environment, there is no DISPLAY, so the test is moss
- Avoid with the command
xvfb-run
- Using JUnit 5
- Go writes a table driven test, so I wrote a similar test
- Convenient Parameterized Test for Junit 5
Time taken
- It took 66 hours including design time
- I didn't expect a 2000 line program to take 66 hours at most ...
- All GW disappeared + I did it even after GW was over
Having a hard time
I'm not stupid about suffering from the tools I made (ridiculous)
gradle
- I had never written gradle in the first place
- I needed to understand how to write and the concept
- I've written maven, so maven was fine, but I like the scripting language, so I chose gradle.
JavaFX Separation Problem (jmods)
- JavaFX was included in the JDK when Oracle Java 8 was used.
- OpenJDK must be used to develop for free in Java with Java 9 or later
- OpenJDK also does not include JavaFX in the JDK
- Need to use modularity with JavaFX SDK and JavaFX JMODS
- Difficult to understand module functions that did not exist at the time of writing in Java 8
Custom JRE
I don't have the source code for my library
- I pulled out the class file from the executable JAR I was distributing and decompiled it with jad and restored it from the generated code.
- When will the day come to decompile my distribution ...
Impressions
I'm glad I did it
- Functionally decreased rather than increased
- But maintainability has improved
- Automatic testing is now possible
- Now available for release at any time
- Freed from the curse of having to keep using Java 8
- I'm glad I made Java14
Reflection 4 years ago
- Do not implement unused functions
- No good, only increased maintenance costs
- Avoid tight coupling of UI and logic
- It's not good that you can't test without manually manipulating the screen
- Inhibits test automation
- Write test code
- Correct behavior remains in the code
- Notice behavior that was not considered
- Implementation of the premise of writing a test
- Improves quality
- Get test coverage
- I was able to find an untested branch by visualizing with CodeCov
- Create an automated test environment
- This time, I built an automatic build / test environment with [GitHub Actions], but it was correct.
- Immediately notice that the behavior has changed
- The sooner you build an automated test environment, the more effective it will be
- Create an automatic release environment
- Forget how to build / release
- The environment that can be released changes
- Host PC changes at OS level
- If you build only on the host PC, you may have "unaware dependency"
- This time, the "Oreore library with no source code left" is exactly that.
- I was able to build at that time, but now I can't
- If you can release it in CI environment, the dependency will always be coded somewhere
- Should be built on the CI environment so that anyone can build / release at any time
- My implementation four years ago was shit
- Garbage
- moron
- Poop
from now on
- There are some tools made with JavaFX other than this tool, so I would like to do the same refactoring.
- (Since there are few users, it's just self-satisfaction)
Summary
- Let's design properly from the beginning
- Let's write the test properly
- Let's automate
- Follow the de facto standard
If I had done these from the beginning, I wouldn't have had such a painful feeling ...
that's all