Tuesday, December 9, 2014

Importing and Packages - Customs won't like this.

Alright, I've been ignoring it, but the time has come to take on a fairly important issue when it comes to organizing your code.  The topic of the day is packaging.

Packages are really not much more than a set of directories (or folders if you prefer) into which your .class files are placed.  This becomes important once your projects get beyond two or three .java files, because you really want to avoid namespace clashes.  You don't even know what they are yet but I'll bet you're agreeing that they sound like something to avoid.  More importantly, proper packaging will help you to keep your workspace and brain organized.  Programming is hard enough, you don't need to make it worse on yourself.  I may keep a messy desk but I do try to have my source code laid out in a logical fashion.

Most of the time, we bundle up our .class files into something called a Jar.  This is just a file with a .jar extension, and it's actually in technical terms a .zip archive file.  This is convenient because a sizeable system can contain dozens or hundreds of .class files, and managing them individually will make you want to gnaw your foot off.

Now, we could go ahead and just put all of the .class files into one giant list.  But that's not a list you want to be looking at or searching through.  It is almost always possible to separate out the various parts of a project into logical subsections, and you should do this.

At the most basic level, you can control packaging by putting a line at the top of your source file like this one:

    package com.oopuniversity.packages;

It dictates that the compiled .class file should be placed in a subdirectory called 'com.oopuniversity.packages'.  When you want to refer to a class called 'PackageDemo' in your java code, you can do it either the hard way:

    com.oopuniversity.packages.PackageDemo = new com.oopuniversity.packages.PackageDemo();

Or you can do it the easy way.  Add an 'import' line up above your class declaration like this:

   import com.oopuniversity.packages.PackageDemo;

This applies to any class that is not in the same package as the class on which you're working.  For classes within the same package the import statement is unnecessary.'

IDEs make this whole process really easy.  You tell them to create a new package, and they do so, creating all of the necessary directories for both java and class files.  You try to create an object and they can automatically figure out that you need an import statement and add it for you.  When they build the code, it's placed in the correct location.

At first this may seem like a needless complication, but it pays off as soon as you're doing any work that is not extremely basic in nature.

The rules for package names are simple.  While it's not hard and fast, stick to lower case letters.  Separate individual words with periods.  You can call them anything you like, but it's generally a good idea to go from less specific to more specific.  Most of the standard packages that come in the Java libraries start with 'java.' and most third party packages start off with the domain name of the developer (this 'com.oopuniversity') and are then followed by as many identifiers as needed for your purposes.  It is a good idea to organize this way, because if you use the same package names as someone else does you could badly confuse your ClassLoader and this leads to really irritating situations when you try to get programs to actually run.  In short, 'util' is a pretty bad package name, but 'org.mycompany.util' is better.  'org.mycompany.secretproject.util' is even better yet.

In summary:

Organize your code into packages.
Specify the package name at the top of your source file.
Import the classes you need by specifying their packages in import statements.

There are specific packaging rules I like to follow when building systems, related to how the code itself is structured.  I'll talk about those rules when it's appropriate.  Those are going to be more on the order of recommendations, but it won't hurt you (much) to go along with them.

Friday, December 5, 2014

Encapsulation - Protecting You From Yourself

Encapsulation sounds like the central plot point of some weird science fiction movie, but actually it's a fundamental technique for improving the reliability and predictability of object oriented programs. Let's pull out our old friend PersonData and see what's ailing him today: 

public class PersonData { 
    public String givenName; 
    public String surName; 
   
    public PersonData() { } 

    public PersonData(String given, String sur) { 
        givenName = given; 
        surName = sur; 
    } 

    public String toString() { 
        return givenName + " " + surName; 
    } 


Let me start by saying that there is nothing fundamentally wrong with this class. It is properly formed, is created with a valid constructor, and has a fully functional toString override method that formats the name is a reasonable manner. Is it object oriented? Well, it's an object at any rate, but we can do better.

 Here's the key issue I'd like to address today. Suppose we had a method that we wanted to use to ensure that a person's name begins with a capital letter. The logic for this is simple enough, but I'm going to deliberately break it for this example, so don't use this method as-is:

public static String ensureFirstCharacterIsUpperCase(String input) { 
    String upperCaseString = null; 
    if (Character.isUpperCase(input.charAt(0))) { 
        return input; 
    } 
    upperCaseString = input.substring(0,1).toUpperCase() + input.substring(1); 
    return input; //Bad programmer! No Pizza! 


 Ignoring for the moment the fact that this method will not quite do what we actually want, how would one go about using it? Well, we could go ahead and write something like this:

PersonData joeBlow = new PersonData(); joeBlow.givenName=ensureFirstCharacterIsUpperCase("joe"); joeBlow.surName=ensureFirstCharacterIsUpperCase("blow"); 
System.out.println(joeBlow); 

That would work just fine, the first, second, and eight hundredth time you do it. But why would you want to? What if you decided that you wanted to capitalize all surnames? What if you wanted to plug in some library that understands how to capitalize special names like MacNeil or something? Do you really want to search out every instance of setting the last name and change it?

There is a better way, my friend, and it gets to one of the other key aspects of object oriented programming. Encapsulation is basically protecting your data from your own programs by making it inaccessible except through a very clearly defined path that you strictly control.

We start by making the fields surName and givenName private. This indicates that they cannot be changed by code in any class except PersonData.

private String givenName; 
private String surName; 

Of course, we aren't quite finished at this point, because we can't change or even see these values. That could make for a remarkably useless class if we did not find a way around it. The way around it is by creating 'accessor' and 'mutator' methods. Those are horrible names so we usually just call them 'getters' and 'setters'. These labels actually make a lot more sense, because the naming convention is to prefix the field name with 'get' and 'set'. 

The required methods for PersonData could look like this:

public void setGivenName(String newGivenName) { 
    givenName = newGivenName; 


public String getGivenName() { 
    return givenName; 


public void setSurName(String newSurName) { 
    surName = newSurName; 


public String getSurName() { 
    return surName; 


 With the fields marked private, and with our getters and setters in place, we would now write the code above more like this:

 PersonData joeBlow = new PersonData(); 
 joeBlow.setGivenName (ensureFirstCharacterIsUpperCase("joe")); 
 joeBlow.setSurName (ensureFirstCharacterIsUpperCase("blow")); 
 System.out.println(joeBlow); 

 But wait, there's more!

 Why should we take a chance that we (or some other developer) fails to use that method to make sure our first character is correct? We can do better than that, and make sure it always happens no matter what kind of night someone had. For now, we'll move 'ensureFirstCharacterIsUpperCase' into PersonData (we'll talk about a better way later) and we'll change our setters a bit:

public void setGivenName(String newGivenName) { 
    givenName = ensureFirstCharacterIsUpperCase(newGivenName); 


public void setSurName(String newSurName) { 
    surName = ensureFirstCharacterIsUpperCase(newSurName); 


 With this done, we can now do this instead:

 PersonData joeBlow = new PersonData(); 
 joeBlow.setGivenName ("joe"); 
 joeBlow.setSurName ("blow"); 
 System.out.println(joeBlow); 

 And still get everything looking the way we expect. We've minimized the amount of code we need to write, and we've encapsulated both field access and a bit of business logic in our PersonData class. Malicious or misinformed programmers will not be able to bypass our hard and fast rules. IDEs won't even let you see the fields in their helpful pop-up dialogs. Dogs will love us.

Of course, we can (and really should) do more than this. First off, we have a constructor that accepts the two names, and we need to make sure it's also performing this task. That's probably most easily done by also having it call the setters. Second, we can think about other business rules we can enforce, like "A user's first name cannot be null or zero length". The setter can check for this and refuse to accept a bad value. Of course, if it does so it also needs to complain to the caller that they've done it wrong. This would be done via an Exception, which we'll need to talk about soon.

Get used to writing your code this way. Protect your data from yourself. Use accessor and mutator methods regularly and uniformly. It's a small amount of extra work, but you will thank yourself later. It's actually a VERY small amount of extra work, given that any decent IDE will create the methods for you if you just ask, and it will certainly save you time and energy later on.

I'll update this post later with a link to a gist containing the fully updated PersonData Object.