Java application
2026
My City
A Java app that lets Montréal residents look up the roadwork happening on their street, and lets contractors find and bid on the work people file.
The city publishes all of it as open data, and none of it is readable by a person. I took a working team project and made it something another developer could actually pick up.
- Moved the build to Maven so a fresh clone compiles. Before that it only built inside the IDE we wrote it in.
- Split two very large classes into smaller ones, taking Resident.java from 780 lines to 106 and Menu.java from 579 to 97.
- Found and fixed 6 bugs while removing duplicated code, and grew the test suite from 9 tests to 35.
- Java 17
- Maven
- JUnit 4
- Gson
- REST / JSON
- Montréal open data
What splitting a 780-line class turned up
- Resident.java
- 780 → 106 lines
- Menu.java
- 579 → 97 lines
- Test suite
- 9 → 35 tests
- Duplication defects found
- 6
The screens, an HTTP client, JSON parsing and the Scanner reads came out. What is left is a person's seven fields and the two operations that belong to them.
Both sign-in screens, both registration screens, both post-sign-in menus and five input validators came out. It now picks between signing in and registering.
Across 6 files, from 3. The old suite needed a live third-party API to pass; mvn test now needs neither a network nor a terminal.
Each one surfaced while collapsing copies of the same code. Listed in the commit that removed them.
Three of us built this for a course and it worked fine on our machines. That was the problem. JUnit and Hamcrest were committed as jar files, and Gson came in through an IntelliJ setting that pointed at a folder on somebody's laptop. Anyone else who cloned it got a wall of errors. Moving it to Maven was the first thing I did.
The part I found most interesting was splitting up Resident.java. It was 780 lines and doing about five jobs at once: holding a person's details, drawing the screens, calling the city's API, parsing the JSON and reading the keyboard. I pulled the network and parsing code into its own package and the screens into another. Doing that turned up a bug I liked. The list of ten work categories existed in three separate copies that had drifted apart, so option 8 read "Travaux résidentiel" on one screen and "Travaux résidentiels" on another. A resident could file a request and then never find it again. It is one enum now, with a test that fails if the labels stop matching.
Most of the bugs I found came from the same cause: the same logic written out more than once. The other thing I took away is that separating the code that fetches from the code that parses is what let the tests run without a network. The old suite had one test that called the live city API, so the build failed on any machine that could not reach it.
