Jonasz's dev blog

Java and more

Getting practical

OOP - fewer definitions, more practice

26/12/2019

Easier thought than done

Having a good idea for a project is not an easy thing. What’s even more difficult is actually starting the project and finishing it. Many distractions show up during the process of development, especially when programming after school/work, during your free time. You may be tired, may have other things to do or maybe even a great idea for another application has suddenly come to your mind. Sounds familiar?

When learning a framework, a tool or a new programming language, I would suggest starting with something relatively small. I’d say that it would be best if such a project could be finished in its basic form in a week. After that time you could start something new or continue with adding new features to this one, but I want to emphasize having something actually done. While agile development might not be all sunshine and rainbows, when carried out right, it really helps both the developers and the client. Why not be agile at home?

Create the project

I assume that you have an IDE of your choice installed (it’s IntelliJ IDEA for me), since this series’ target audience are developers with some experience. As said in the previous post - start with the build tool. I’m using Maven in this project, but Gradle is analogous.

When creating a new Maven project, we need to set up the pom.xml configuration file (when using an IDE, this is usually handled by a project wizard). Let’s start with a minimal POM.

Group ID is an identifier that all our projects should have in common - it’s a way of defining the author(s) of the project and grouping all the projects by the same authors together. For example: org.apache groups the projects of the Apache foundation and org.springframework - the Spring Framework projects. By convention, it’s usually the main page of your organization/personal page’s URL reversed, so in my case it’s io.github.jonarzz - if you don’t have your own domain, you could start with a similar one, with the username replaced.

Artifact ID - the actual name of the project.

Version - current version of the project - already explained in the previous post.

<groupId>io.github.jonarzz</groupId>
<artifactId>i18n-example</artifactId>
<version>1.0.0</version>

First build

JDK and Maven are installed (according to the tutorial on the aforementioned page or embedded in the IDE), and the system path is set, the project is configured - let’s build it.

mvn clean package

run from the command line in the project base directory (where pom.xml is placed) should result in a successful build and a .jar file in the target directory.

As said before, we’ll use the current LTS Java version - 11, so if that’s different in your case, update it. To avoid problems with running embedded Maven in IntelliJ IDEA, we’ll also add a build section to our pom.xml:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>${java.version}</source>
                <target>${java.version}</target>
            </configuration>
        </plugin>
    </plugins>
</build>

In the build section we can define, what plugins should run during the Maven build execution. In this case we override the JDK version default value (6 for plugin version greater than or equal to 3.8.0, 5 otherwise) in the plugin configuration.

java.version variable has to be defined in properties section like so (just for convenience, the value could be inlined as well):

<properties>
    <java.version>11</java.version>
</properties>

One last thing worth noting is the warning displayed during the build:

[WARNING] Using platform encoding (Cp1250 actually) to copy filtered resources, i.e. build is platform dependent!

Adding such a property to the properties section mentioned above (where we defined java.version) is a solution:

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

Define responsibilities

Let’s think of the steps our application should perform to do what it’s supposed to do and meet the requirements. We’ll prepare a user story and divide it into more technical tasks.

Main goal

As a static website owner I want to be able to create multiple files in different languages based on a template, so that it’s easy to create multilingual versions of my page and reach people from around the world.

Requirements

What is in it for a developer

Thanks to dividing a seemingly simple goal into smaller tasks, we are able to divide the actual code into parts that are separated from each other and only communicating through the packages’ API. It gives us a possibility to define the API from the start and then, for example, split the tasks among team members or perform internal package refactoring without affecting the whole project workflow (as long as the tests of the package API are successful). So right now a natural step would be designing the said API for each of the requirements and preparing the packages. They may change in the future, of course it’s hard to think about every possibility at the very beginning of the project, but the designing will help us create more elastic, easily maintainable and expandable code base.

Red - green - refactor

In the next parts we will focus on the said API and to do that, we will write some test cases that will be failing, until we develop the actual code - then they should pass. After that we will be ready for refactoring.

Go to main page Next post