Each week I write a blog post which describes what I learned that week. I write these blog posts for two reasons.
First, I want to keep track of my personal development and writing regular blog posts is a great way to do it.
Second, I want to share my findings with you. I hope that you can use some of them in your daily work.
Let’s get started and find out what I learned in week 47.
What I Learned in Week 47
First, Take your time to design and configure your build process when you start a new project.
How many of you start a new project by copying the build script from an existing project? I have noticed that this is a quite common practice, and I have done this multiple times. After all, using an existing build script makes sense because it saves a lot of time and ensures that we know the build process very well.
This approach has one big problem:
Different projects require different build processes.
If you start a project by copying a build script from an existing project and using it as is, you take a risk that the build process isn’t optimal for your current project. In the worst case scenario, you will transfer the problems of the build process into your new project.
You don't want to do this. Instead, you should spend some time and figure out what kind of a build process you really need. You should find answers to the following questions:
- What build tool should I use?
- How do I integrate my build with the continuous integration server?
- Should I create a multi-module project?
- How should I deploy my application?
After you have figured out the answers to these questions, you can see if the existing build script solves your problems. Remember that you have to live with your choices. Thus, it is wise to ensure that you make the correct choices.
Second, Don't be too creative!
Frameworks are made to be extended, and extending a framework is a good way modify the behavior of the framework. However, this is safe only if you use the provided extension points. If you get too creative, you can run into problems when you update the framework to a newer version.
I stepped on this mine.
I had written both unit and integration tests to my controllers by using the spring-test-mvc project. To make matters worse, I had created a JUnit rule which configured my tests. When I updated the project to use Spring framework 3.2, I had to migrate my tests to use the Spring MVC Test framework.
Unfortunately, my custom JUnit rule was broken by this update, and I had to fix my tests. Luckily, this did't take too much time but I learned an invaluable lesson:
Don't be too creative!
Third, I don’t know enough about garbage collection.
I am a bit ashamed to admit this but my knowledge about the garbage collection mechanism of JVM is pretty limited. This became apparent when we noticed that our production server was spending a lot of time in garbage collection. The situation was so bad that it stopped responding to requests when the garbage collection was running.
I had no idea how I could solve this problem.
Then we ran into this Gist (Thanks Joe) which solved our problem (or at least it looks this way at the moment).
However, my job is not done yet. My next goal is to figure out how garbage collection really works.
If you know any good tutorials about this, let me know!
Fourth, Don't overengineer your code.
Implementing the first version of a function is often pretty straightforward, and it is not too hard to write clean code. However, the odds are that when you deploy that function into the production environment, your customer notices that the function is not working properly. He realizes that there are several exceptional situations which must be supported as well.
This is where you have to make a decision:
- You can add a quick fix to your code
- You can redesign your code
Although adding a quick fix sounds a bit bad, it is often the best thing to do. If you have to handle only a few exceptions, it makes no sense to overengineer your code because it makes simple things harder than they should be.
Nevertheless, when the number of exceptions grow, you will eventually reach a point where your code is so messy that it is no longer sensible to add yet another quick fix to it.
This is the point where you have to redesign your code.
Fifth, Use Spring Batch.
Spring framework has an easy way to create scheduled jobs by using the @Scheduled annotation. This is a handy way to implement small scheduled jobs which don’t import information from another system or export it to another system.
On the other hand, if you have to implement "more" complex scheduled jobs, you should seriously consider using Spring Batch. It is not a scheduling framework, and you still need to figure out a way to schedule your jobs.
However, Spring Batch frees you from writing the plumbing code that glues your components together. This is extremely valuable because writing plumbing code is surprisingly hard if you implement a decent error handling mechanism. And if you don't do that, your jobs are pretty crippled.
Do yourself a favor and take a look at Spring Batch. Maybe you can use it in your next project.
What Did You Learn This Week?
Share your learning experiences or other comments on the comment section.