Java, the Programming, and Everything

Thursday, April 24, 2014

Do not underestimate the power of the fun

Do you like your tools?

Are you working with the technology, programming language and tools that you like? Are you having fun working with it?

When a new project is being started, the company has to decide what technologies, frameworks and tools will be used to develop it. Most common sense factor to take into consideration is the tool's ability to get the job done. However, especially in Java world, usually there is more than one tool  able to pass this test. Well, usually there are tens, if not hundreds of them. So another factors have to be used.

The next important and also quite obvious one is how easy the tool is to use, and how fast can we get the job done with it. "Easy" is subjective, and "fast" depends strongly on the tool itself and the environment it is used in. Like the tool's learning curve or the developers knowledge of it.

While the developers knowledge of the tool usually is taken into account, their desire to work with it (or not), usually is not. Here I would like to convince you that it is really important too.

Known != best

There are cases where it's better to choose cool tools instead of known ones. Yes, the developers need to learn it, and it obviously costs some time, but I believe it is an investment that pays off later. Especially if alternatives are the ones that the devs are experienced with, but don't want to use any more. Probably there are some people who like to code in the same language and use the same frameworks for 10 years, but I don't know many of them. Most of the coders I know like to learn new languages, use new frameworks, tools and libs. Sadly, some of them can't do it because of corporate policies, customer's requirements or other restrictions.

Why I believe such an investment pays off? If you think developer writes 800 LOC/day, so 100 LOC/hour, so 10 LOC/minute... well, you're wrong. Developers are not machines working with constant speed 9 to 5. Sometimes we are "in the zone", coding like crazy (let's leave the code quality aside), sometimes we are creative, working with pen and paper, inventing clever solutions, algorithms etc. and sometimes we are just bored, forcing ourselves to put 15th form on the page or write boilerplate code.

The power of fun

Now ask yourself, in which situation you (or your developers) are most often? And if you are often bored, working 5th year with the same technology and tools, think about the times when you were learning it. Remember when you were using it for the first time? Were you bored then? Or rather excited? Were you less productive? That's truism, but we are not productive when we need to force ourselves to work. Maybe it's a good idea to change your work to be more fun? Use some tools you don't know (yet), but really want to try? It might seem you are going to be less productive, at least at the beginning, but is it really true? Moreover, if it allows you to write less boilerplate code or closures or anything else that can make you faster and more efficient in the long run, it seems a really good investment.

There is one more advantage of cool and fun tools. If you are a company owner, do you want your business partners to consider your company expensive but very good, delivering high quality services and worth the price, or not-so-good but cheap? I don't know any software company that wants the latter. We all want to be good - and earn more, but well deserved, money. Now think about good and best developers - where do they go? Do they choose companies where they have to work with old, boring tools and frameworks? Even when you pay them much, the best devs are not motivated by money. Probably you know it already. Good devs are the ones that like to learn and discover new stuff. There is no better way to learn new stuff than working with it. And there are not many things that are as fun for a geek as working with languages, technologies and tools they like.

So, when choosing tools for your next project, take fun factor into account. Or even better - let the developers make the choice.

This presentation might be interesting: It's Graham Tackley story about how they introduced Scala in Guardian, and what happened then.

Cool image courtesy of Łukasz Żuchowski

Tuesday, January 22, 2013

Spock testing framework

Some time ago I gave presentation about Spock on Szczecin JUG. Later I gave this presentation also on my company SoftwareMill meeting. 

I think it's high time to share it on my blog too: (navigate with arrow keys).

Friday, November 2, 2012

FEST Assertions for Joda Time

Do you write unit tests? Of course you do. Do you use Joda Time? I think so. Do you use FEST Assertions? You should try it if you haven't yet. With FEST Assertions we can write fluent code like this:
Now let's assume we have some functions that return joda DateTime, and we want to test it. Can we do this in FEST Assertions?
No, we can't :( FEST Assertions don't handle Joda Time classes. However, do not worry :) At SoftwareMill we have written our own TimeAssertions for that :) So you can write your code like this:
TimeAssertions works for org.joda.time.DateTime, java.util.Date and org.joda.time.LocalDateTime. You can freely exchange DateTime and Date, i.e. you can compare DateTime to Date, DateTime to DateTime etc. LocalDateTime can be compared only to instances of the same class, as it doesn't make sense to compare it to DateTime or Date without specifying the time zone. TimeAssertions is available on github. If you want to use it from Maven project, add repository:
    <name>SoftwareMill Releases</name>
And dependency:
Happy testing!

Wednesday, September 26, 2012

Get script's own directory in bash script

It was always a problem for me to get the directory the called script is stored in, in the script itself. Thanks to this SO question ( it's not a problem anymore. As it says:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
Or, to get the dereferenced path (all directory symlinks resolved), do this:
DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Saturday, September 15, 2012

Get specific PC IP from "arp -a"

I want to extract IP of machine leonidas. arp -a returns such line (among others): 
leonidas.home ( at 0:1c:c0:de:8f:28 on en1 ifscope [ethernet] 

To have only IP:
arp -a | grep leonidas | cut -f 2 -d ' ' | sed 's/[()]//g'

Monday, January 9, 2012

My encounter with a small bug in Hibernate

The problem

At work, I needed to use entities with @DiscriminatorColumn inheritance. It means all types are kept in the same table, with value in this column showing what type given row is of. It's not recommended way to handle inheritance, but for some reasons we needed to use it. In developement, locally, I was using PostgreSQL database. When I tried to store this entities, I was receiving strange errors. Saying I cannot store an entity because entity with such id is already in database. It was quite strange, I was trying to store vanilla new entity. Test case to show this error is very short, so I'll include it here:
//Parent entity
@Inheritance(strategy = SINGLE_TABLE)
@DiscriminatorColumn(name = "CLASS_ID", discriminatorType = INTEGER)
public abstract class ParentEntity {
  @GeneratedValue(strategy = IDENTITY)
  private Long id;

//Child entity with discriminator  
public class InheritingEntity extends ParentEntity {

public class PersistChildEntitiesWithDiscriminatorTest extends BaseCoreFunctionalTestCase {
  public void shouldPersistTwoEntities() {
    Session session = openSession();
    InheritingEntity child1 = new InheritingEntity();
    InheritingEntity child2 = new InheritingEntity();;;

The cause

This test throws exception on second save, but only on PostgreSQL. Why is that? Well, when you save new entity to persistence context, Hibernate issues SQL call to database instantly. Other queries, like updates, are cached, and sent to database on em.flush or em.commit. But inserting of new entities is not cached and there is a reason for that. When we save new entity, Hibernate needs to assign ID to it, and this is taken from database. Most databases return ResultSet with one row and one column after insert, and it contains newly assigned ID. However, PostgreSQL behaves a bit differently. It returns whole inserted row (of course, with ID filled in). In most cases it works, because ID is the first column in this row, so when Hibernate takes value from the first row and the first column, it is the correct one. However, in case of classes with discriminator, ID is not the first column. Discriminator is the first column. So first insert is correct, ID 1 is assigned to child1, but then when we try to store child2, Hibernate also tries to assign 1 to it's ID, and complaints that there already is another entity with it.

The solution

So there was a bug in Hibernate. Can I solve it? I asked this question to myself, but to answer I couldn't do anything else than try ;) So I forked hibernate repository (yes, it's on github!) and... I was quite overwhelmed by the mass of code there. First challenge was to try to open it in my IDE, with all the subprojects and their interdependencies configured correctly. Thankfully there is gradle task for creating project files for IntelliJ IDEA, the IDE I'm happy user of. Next task was configuring Hibernate tests to use my PostgreSQL database. It turned out quite easy after one or two emails on hibernate-dev list. Now I had to change the code assigning IDs to entities to take it not always from first column first row, but sometimes from column of given name. So I had to get the name of column keeping IDs, which I did with a little help from other developers on the dev list.

The contribution

Now I commited fix to my forked repository on github, issued a pull request, got some comments, fixed files formatting... We'll see if it's accepted. UPDATE: It is accepted :)

Wednesday, December 28, 2011

Easy way to convert file encoding

Easy way to convert text files to UTF-8 on Ubuntu. Install package enca and you are able to:
enconv -L pl -x UTF-8 myfile.txt
Where after -L is language specified (necessary for enca to recognize file encoding before conversion) and after -x destination encoding.
Warning: enconv overwrites existing file, so better create backup copy before.

UPDATE: Another way, useful if you know source file encoding:
iconv -f ISO-8859-2 -t UTF-8 source.txt > utf8.txt