Wikibook: CI for Software Medical Devices

I’ve started a Wikibook, and I welcome any contributors: CI for Software Medical Devices.

[Wikibooks]

Why I Dislike the @author Annotation

Here’s why I LOVE the @author annotation (in Javadoc comments): It makes me look really good having my name on tons of code. It shows that I am a high-output engineer.

Here’s why I HATE the @author annotation: It implies some sort of ownership of a method, class or package to the rest of the team.

When it comes to writing software, my experience has always been that smaller teams with good developers can get significantly more done than large teams with mediocre developers. (On this note, it may be a good idea to hire a single great developer at $150k rather than 3 junior programmers at $60k, but that’s a separate post).

The @author annotation can be very good to place in your javadoc comments so that others know who to turn to for questions about the code that was written. I’m not opposed to its use (in fact, I use it all the time). Its use, however, should not imply that others on the team are prohibited from modifying the code written by another programmer. On the contrary: Code is the responsibility of the entire team. All code!

There have been many occasions throughout my career wherein another developer said to me, “Hey Matt, can you write such-and-such a method so that I can get such-and-such?” An obvious example is in DAO classes. Another developer may be writing some controller code that requires some DAO method downstream. That developer should not find it necessary to ask the guy or gal who wrote the DAO class to implement a method. Write it yourself! Okay, there are certainly times when it may be appropriate to do so, but the main point is that we should make it clear that all code is the responsibility of everyone on the team.

Another example is when a defect is found. We’ve all made them… Writing code, to some extent, means writing defects. When a defect is found it is never appropriate to allow the rest of the team to be hung up because of it. The person discovering the defect, whether he or she wrote the defect or not, is free to correct it.

I’ll use myself as an example. One time I wrote a POJO class with a method like this:

getSTatus()

Oops! This is a pretty straightforward problem: That T should be lowercase. Because this was code that I checked in and my name appear as the @author, another team member pointed the typo out to me and asked me to correct the problem. This is certainly fair to do, but in the amount of time it took to call me over, show me the typo and send me to fix it, the other team member could have simply checked in a fix. That @author tag does not indicate that the @author is the only one allowed to modify any code.

Tabs vs. Spaces

[Coding Horror: Death to the Space Infidels]
[Joel on Software Forum: Tabs or Spaces?]
[Why I Love Tabs]
[Why I Prefer NO Tabs]
[The Tabs vs. Spaces Holy War]
[Revisiting Tabs and Spaces]
[Rizzoweb: Tabs vs. Spaces]
[Tabs vs. Spaces: The End of the Debate!]

The list goes on and on…

A Bidirectional Add-To-List Mistake

Here’s a somewhat real-world example of a bad coding practice. When setting up bidirectional relationships, its important to remember that the add methods for adding to a list that results in a one-to-many and many-to-one relationship set the parent/child relationship in both directions. To make life simple, I like to provide a couple of different ways of adding to a one-to-many list. For example, say a database contains a “PEOPLE” table made of of Person objects, and each person has many Phones:

@Entity
public class Person {
    @Id
    @GeneratedValue
    private int id;

    private String name;
    private int age;

    @OneToMany(mappedBy = "person")
    @JoinColumn(name = "PERSON_ID")
    private List phones;
    ...
}
@Entity
public class Phone {
    @Id
    @GeneratedValue
    private int id;

    private String number;
    private String type;
    private boolean preferred;

    @ManyToOne(mappedBy = "person")
    @JoinColumn(name="PERSON_ID", nullable=false) 
    private Person person;  
    ...

    public Person getPerson() {
        return person;  
    }
}

Naturally, we need to enforce the bidirectional relation ship like so that adding a phone requires us to add a person (the PERSON_ID foreign key cannot be null!) and adding a phone via a person (person.addPhone(…)) requires that the a phone is added to the phones property and the phone object added to that list is assigned a parent person.

So in our Person class we need a method like this:

addPhone(Phone phone) {
    if (!phones.contains(phone) {
        phones.add(phone);  
        phone.setPerson(this);
    }
}

And in the Phone class we need:

setPerson(Person person) {
    if (this.person != person)
        this.person = person;
}

This is all fine and nice, but sometimes it is much easier to have a method that allows us to set all the child relationships at once. I like to offer both methods (i.e., my Person class would have both an addPhone and addPhoneList method). This isn’t at all uncommon. The problem is that where the phone owner is set may be confusing. Is it inside or outside the POJO?

It is tempting to leave the calling logic to do the work. For example:

List phones = new Phones();
for (some loop) {
    Phone = new phone;
    phones.add(phone);
    phone.setOwner(person);
}

person.addPhoneList(phones);

In our Person class we would then need a method like this:

addPhoneList(List phones) {
    this.phones = phones;
}

This assumes that whoever is writing the calling code understands the need to set the phone owner prior to persisting the person object. It also goes against our previous logic for adding a single phone to the list of phones for a person object. (I realize that I am ignoring the fact that my example method may leave some existing phone numbers orphaned or uni-directional, a separate issue).

A better approach to the addPhoneList method is this:

addPhoneList(List phones) {
    for (Phone phone : phones {
        phone.setPerson(this);
    }
}

By doing things this way we keep the work properly encapsulated to the Person class, and we don’t have to assume that the calling logic (and whoever writes it) set the owner for each phone in the list. Its just cleaner… As with nearly everything, there is a tradeoff between efficiency and bulletproof code. We are forced to loop through the list of phones twice in this scenario: Once when the phones are created and again when inserting a phone list to a Assuming we don’t have a massive list and are not making this call with extreme frequency, the overheard is really negligible.

This seems like a basic problem with an obvious solution, but I have seen code this written this say a number of times (where the add single phone method covers the bidirectional relationship but the add multiple method does not). Hibernate/JPA cannot magically figure out the parent/child relationship, so it is very important to enforce it and properly encapsulate responsibility within the persisted POJOs.

[Level Up: One-To-Many Associations]
[Level Up: Many-To-One Associations]

Is there ever a reason NOT to use an Artificial Primary Key?

I found this post on the subject of choosing a primary key. While Java Persistence Annotations allow us to use any field we want as a primary key (as long as it is naturally unique), is there a good reason to use anything that is not a surrogate/artificial primary key?

There are plenty of fine examples for natural primary keys: SKUs, usernames, email addresses, and so on. While these may work fine as a primary key insofar as they satisfy uniqueness requirements, there are some drawbacks, the biggest being the fact that uniqueness may not be guaranteed.

This post lists the reasons against using natural primary keys with 10 very good points:

  • Con 1: Primary key size – Surrogate keys generally don’t have problems with index size since they’re usually a single column of type int. That’s about as small as it gets.
  • Con 2: Foreign key size – They don’t have foreign key or foreign index size problems either for the same reason as Con 1.
  • Con 3: Asthetics – Well, it’s an eye of the beholder type thing, but they certainly don’t involve writing as much code as with compound natural keys.
  • Con 4 & 5: Optionality & Applicability – Surrogate keys have no problems with people or things not wanting to or not being able to provide the data.
  • Con 6: Uniqueness – They are 100% guaranteed to be unique. That’s a relief.
  • Con 7: Privacy – They have no privacy concerns should an unscrupulous person obtain them.
  • Con 8: Accidental Denormalization – You can’t accidentally denormalize non-business data.
  • Con 9: Cascading Updates – Surrogate keys don’t change, so no worries about how to cascade them on update.
  • Con 10: Varchar join speed – They’re generally integers, so they’re generally as fast to join over as you can get.

So while on the surface it may seem simple to use a seemingly unique field for a primary key (a username on a domain, for example), it can be disastrous later on. Con 6 above is the big one, but Con 7 is something people don’t seem to think about as much. We can enforce uniqueness on any field we want, be it a key field or not… That said, I really cannot think of a good reason to use a natural key (other than developer laziness, which is in fact the key reason why bad code tends to be written in the first place).

[Stack Overflow: Deciding between an artificial primary key and a natural key for a Products table]
[Rapid Application Development: Surrogate vs Natural Primary Keys – Data Modeling Mistake 2 of 10]
[Wikipedia: Surrogate Key]
[Wikipedia: Natural Key]

Valuable Unit Tests in a Software Medical Device, Part 9

I thought I was done, but here is yet another good reason to incorporate complex function automated testing: Validation of multiple Java runtime environments. Fabrizio Giudici proposes this as a solution for testing with Java 7, but we can always take it a step further, verifying multiple OS environments as well. Of course, this requires that we have those build environments available (easy enough, using virtual machines).

Where Do Hibernate Transactions Fit In?

I recently got into a discussion on where Hibernate transactions should be placed in the scope of DAO logic. Some people have a desire to begin and end a transaction inside a DAO method. This is really a question of unit of work, and not scope of the DAO.

Let’s say we have a single unit of work that involves updates to several tables. Within the scope of this unit of work we have to update table 1, table 2 and table 3. During the sequence of events table 1 updates just fine and then table 2 fails to update. Now, are we to move on and update table 3? What are we to rollback? Do we want to rollback both changes (the partial change to table 2 and the complete change to table 1 that is within the same unit of work)? (We probably do.)

But with our transactions being committed within every single DAO method we cannot; The previous transaction was already committed before we discovered an error.  So the ultimate answer is this: Placing transaction begin and end statements within each DAO method makes things messy. While it is important to keep the length of a transaction as short as possible, it CANNOT be done at the expense of the integrity of a the unit of work!

In the example that I scribbled below (and its not a great example), a single unit of work (adding a person with an address and an employer) allows for partial completion. This isn’t what was desired in the first place.

[Stack OverFlow: DAO PAttern-Where to Transactions Fit In?]
[Java Bouique: Managing DAO Transactions in Java]