Diving into Java (with strong JavaScript and Python background) Part 5(Sample Console App)

Jon Cundiff
6 min readMar 2, 2022

--

Welcome back to my journey to learn and become proficient in Java. To recap, my plan of action is as follows:

  1. Load most common environment
  2. Research naming conventions
  3. √ Hello World app to confirm environment set up properly
  4. √ Review and practice basic data types and available methods in Java
  5. √ Review and practice equivalents to arrays/lists and objects/dictionaries in Java
  6. √ Algorithm practice
  7. Sample projects with the above knowledge
  8. Learn Spring framework
  9. Sample projects with Spring with REST API and WebSockets or Socket.IO

In my previous article, I explored the different basic algorithms and implemented them in Java. I’m equipped to start building to start building some console applications (meaning no graphic user interface).

Project Introduction

For this project, I’ve decided to reimplement an early class project that was written in Python — a pool table management app that could be utilized in a pool hall. The functionality is quite simple:

  1. It should track the time a table is occupied.
  2. It should track the time a table has been vacated.
  3. Based on the above, it should track the time and total cost to rent the table.
  4. It should prevent a table from being double booked.
  5. It should prevent cost calculation on an unoccupied table.
  6. It should show all the rental entries of a pool table.

For this project, I researched, learned, and implemented 3 new technologies: Maven, JUnit, and Java Scanner Class,.

Maven

Maven is a package manager and a build automation tool for Java projects. There are several packages (classes and features others have crafted to help other developers on their projects) on the Maven Central Repository. It’s main alternative at the time of this article is Gradle. According to the most recent Jet Brains The State of Developer Ecosystem survey is currently the more popular of the two managers. Gradle is the goto tool for Android developers writing in Java or the closely-related language Kotlin. Since Maven is the standard today, it made most sense to start with this tool for this first project. I also needed Maven to install and work with the next package: JUnit.

JUnit

While writing code, it is best practice to write unit tests to ensure each piece of your code operates as expected in isolated chunks. In Java, the most popular unit testing framework is JUnit (according to the previously linked survey), so it makes sense to learn this framework first. At first glance and throughout this project, it seems to follow similar patterns to what I’ve seen with Python’s built-in unittest and with Jest in JavaScript. Not a huge shift in how to approach testing from what I’m used to.

The strategy I utilized when building this application is called test driven development. The idea is to clearly define how you want each piece of your software to operate before you actually write the code. When you write each new test, you make sure it fails (because you haven’t implemented it yet). Then you write code that makes it pass.

Failed Test

We start with a failed test with the conditions specified so that we are confident that if there was a change that results in the code giving the wrong result, that the test will actually catch it. The other great thing about this is we’re ensuring the code we write lines up with the goals of the code. Whenever tests are written after the code, there’s a temptation to write a test to work with the code rather than tests to meet the goal. Okay, so I’ve got my failing test, let’s look at code that makes this pass (and fulfills the design goal for the code):

Before the failing test, lines 2–4 was not a part of this function, and therefore did not properly handle the case of trying to close the play time for a table that nobody is using. So after adding these lines, I rerun my tests and get this:

All tests pass!

I am now confident I implemented code that meets the needs for the scenario. Every time I add more tests, or implement more things, the tests are reran to ensure I didn’t break anything with the new code. And because I wrote the test with failing code initially, I can be confident that each time I run this test with each new code addition, that each pass are genuine passes rather than luck of the circumstance and that the test describes my desired end result rather than my code.

One thing to note about unit testing frameworks is you can only really test if a function is giving you the results you want. This is an automated process, so anything that relies on user input cannot be tested, and neither can the text the program displays. So this means I can’t test my main loop because that is heavily dependent on user input or the display functions. This is okay though, the bulk of the functionality lives in the PoolTable class and everything that isn’t related to getting data ready for display has been tested.

Java Scanner Class

The last major thing I needed to learn for this project was learning how to actually accept user input within Java. There are quite a few options within Java to do this task. Browsing through several different Java guides, this is one of the last things addressed. The newest feature within Java is the Scanner class. By default, Java doesn’t provide you any clean methods for accepting and processing user input within System.in. Instead you pass that as a parameter when initializing a Scanner. The nice thing about Scanner, is I don’t always have to read input as a string. I need to be able to select pool table numbers in the follow up command, so not needing to do a separate command to parse a string to get an integer is highly convenient:

The UserDisplay class handles everything with how information is displayed and retrieved. I used static fields and methods within this class since I don’t need to create instances of this class — the primary purpose of it is to house all the utility functions and values to be used elsewhere in the app. Doing it this way allows me to keep the Main class and function clean and concise:

The entry point of every Java application is the main function. It is designated within your build configuration before you can compile it, or configured in your IDE so you can run your app while building it (you still need to do some manual testing by actually using the software even though automated tests have been written). I placed the main loop that controls the app in a separate function so that the entry point is only responsible for setting up initial values and then call the loop.

Screenshot of one cycle of a loop before the screen gets cleared for the next cycle

In just over a week, I went from minimal knowledge of Java to enough knowledge about data structures and composition to implement algorithms. In another couple days, I was able to take this foundation to build a simple, but complete, application adding a few more tools in the process. There are still lots of other advanced data structures and classes I still haven’t learned, but I definitely have a strong enough foundation to learn those as needed, and most importantly, learn the most popular application frameworks in Java: Spring. Each framework (regardless of programming language) will introduce its own opinion on how an application should be built, so at times, learning a new framework can take as much time as learning a new programming language. My next article will feature my exploration with Spring to build web applications.

Complete Source To This App

--

--

Jon Cundiff
Jon Cundiff

Written by Jon Cundiff

Full-Stack JavaScript developer and Dart/Flutter enthusiast

No responses yet