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 41.
What I Learned in Week 41
First, Hibernate validator has a @SafeHtml validator which can be used to ensure that the given text doesn't contain malicious code. This is a handy way to protected your application from XSS attacks if you don't want to silently strip the malicious code from the text.
Second, Domain model constraints must be equal to the constraints found from the database.
I think that this is important for two reasons:
- These constraints acts as a documentation. If the constraints are equal, the developers don’t have to check everything from the database. This is a huge time saver.
- Integration tests are often run against a database created by Hibernate. If the constraints are not equal, the database used by integration tests is not equal to production database. This might cause false positives which might become a problem when the application is deployed to production environment.
Also, I often add other non mandatory JPA annotations (mainly @Table and @Column) as well because this way I can decide the names of database tables and columns.
Third, All Jira issues must be enabling specifications.
I wrote last week that an issue tracker can be used as a specification tool. This week I realized that this isn’t good enough.
Let me explain.
A specification is often understood as something which is required when we want to add new features to our application or change the implementation of an existing feature. Although it is understandable why people feel this way, a software project has many tasks which don’t change the behavior of the application.
How should we describe these tasks?
We should treat these tasks in the same way than the tasks which alter the behavior of our application. We should add all required information information to the description of the ticket.
How do we know what information is required?
It is hard to give a general guideline about this because it all depends from the skills and experience of our team members. That is why I suggest that we should start by adding all information which seems relevant to the us, and improve our tickets by asking feedback from our team members.
This will take some time but eventually we will know what information is relevant and what is not.
Why should we care about this?
This week I started working on an application which was unfamiliar to me. All I had was a vague understanding about the general idea of the application.
This experience taught me the importance of enabling specifications. Because I had no idea about business rules of the application or its architecture, I had to spend hours finding the information which was not found from the ticket. This was quite frustrating experience.
I agree that writing enabling specifications will take time. Nevertheless, I think that it is better to spend fifteen minutes or half an hour for writing a good issue tracker ticket because it can save the developer from hours of frustration.
This sounds like a no brainer to me.
Also, if you are having productivity issues, writing enabling specifications is an easy way to boost the productivity of your team.
Fourth, Using JPA Inheritance with InheritanceType.TABLE_PER_CLASS can lead into a pretty fucked up database.
Let’s think of the following scenario:
- We are using JPA inheritance with the InheritanceType.TABLE_PER_CLASS. This means that we have to create a database table for each concrete entity class.
- The name of the superclass is AbstractFoo.
- The AbstractFoo class has two subclasses which are called FooOne and FooTwo. The information of these entities is stored to the database tables called foo_ones and foo_twos.
Our class hierarchy is done. The next step is to add a AbstractFoo field to an entity and specify the used join column:
@OneToOne @JoinColumn(name = "foo_id") private AbstractFoo foo;
To which table does the foo_id column reference?
Well, it references either to the table foo_ones or to the table foo_twos. That is pretty damn scary.
Can you answer to this question:
How do you create a foreign key constraint for the column foo_id?
Be afraid. Be very afraid.
Fifth, Failure is a good teacher.
Although some people think that learning from your mistakes is overrated, I still believe that failure is a good teacher. Of course, learning from your mistakes has its limitations but you can still learn more than you would think.
Don't waste your mistakes by thinking:
"I know now that it is not a good idea to use X. I will try Y next time."
Think about this quote by Jason Fried of 37Signals:
"What did you learn? You learned what didn’t work. Now you won’t make the same mistake twice, but you’re just as likely to make a different mistake next time. You might know what won’t work, but you still don’t know what will work. That’s not much of a lesson."
I agree. The correct way to learn from your mistakes is to find out how you could have avoided making the mistake in the first place. In other words:
You have to find out what works!
I agree that you should concentrate on learning from your successes because they teach you what works. However, if you happen to screw up (and believe me you will), you can still learn what works as long as you deal with your failures in the right way.
What Did You Learn This Week?
Share your learning experiences or other comments on the comment section.
P.S. I promised to review a book called Scaling Big Data with Hadoop and Solr. I haven’t started reading it yet but its description looks pretty interesting. I think that I will start reading it next week.