Reviewing good coding habits in Java


In this video we are going to assume that
you are already familiar with the basics of writing object-oriented code, and review some
of the fundamental stylistic aspects of writing good quality code. Our focus will primarily
be on good practice. In other words, we will look at things that are not actually required
by the Java compiler, but are coding habits or practices that we choose to adopt because
they are beneficial. You might wonder why we bother if the compiler
does not require them. The main reason is that we want our code to be easily understood
by anyone who chooses to read it. If you are a student, then you will obviously want your
examiners to be able to understand what you have written – so that you get a good mark
– but readability is also important in a wider context where other people might have to read
your code or, most especially, where you have to read someone else’s code. There are few
things more frustrated in programming than being given someone else’s code to read and
not being able to make sense of it. If you can get into the habit of coding well, then
everyone benefits in the long run. Let’s start with a basic class that is designed
to model the module that a student might take as part of their course. The class will be
relatively simple, because we are primarily interested here in the stylistic aspects. When we open a class source file, the first
thing we probably want to know is what this class is for or what does it do. The place
to look for that is the javadoc comment right at the start of the file. When you create a new class, try to get into
the habit of always writing something descriptive in the class comment as the very first thing.
If you don’t do it straight away, it is likely to get forgotten. You don’t have to write
much; just the basics of what the class is for and the sort of data that instances will
be storing. In general, there is no need to go into details of data types here. You can
see here what we have written, and we have also included details of the author and date.
If you are not sure how to use javadoc tags – things like @author, @param and @return
– look up how to do that because good quality code will always include them in the comments. The class has a standard class header. Remember
to always use an initial upper-case letter for the names of classes and – in general
– the only time you should use an initial upper-case letter is for class names. We will
actually see an exception to this general rule later, but the reasons for the exception
will be clear. Definitely avoid using an initial upper-case letter for method names and standard
variable names. Otherwise, your code will look very odd and confusing to its readers. Immediately inside the opening curly bracket
of the class body we have to define the fields or instance variables: in this case name and
mark. Notice that both have been designated as `private’. This is a very important part
of good code quality but, for some reason, it is one of the most neglected aspects. Defining
instance fields as private supports the important object-oriented principle of `encapsulation’.
If you like, think of it as a way to secure an object’s data inside a capsule, safe from
interference from other objects in the program. Hopefully you can see even from this small
example how important that could be. If we don’t define the variables as private then,
potentially, another part of the program could change a student’s mark and the Module code
would have absolutely no way to prevent that from happening – or even of being aware that
it has happened. But by making the variables private, all changes to them must be channelled
through methods defined in the Module class, and we have control over what gets written
there. Note that the variable names follow our rule
of using an initial lower-case letter. One final point to note about the fields is
that there is a brief comment before each, describing what they are for and any particular
constraints on their values. Try to get into a similar habit in your code. Next we have a constructor. Once again, we
have written a brief descriptive comment using javadoc notation. The comment describes the
purpose of the parameter and notes other features that are relevant to the initialisation process. The constructor uses the standard convention
of using the same name for the parameter as the name of the field it will be used to initialise.
Hence the use of the keyword `this’ to distinguish between the two different variables called
`name’. Notice that we have explicitly initialised
the variable `mark’ even though it would naturally be given the value of zero by default. We
prefer to be in the habit of explicitly initialising all the instance variables in this way to
ensure that none of them gets forgotten. While you could easily argue that there is no point
with such a small example class, getting into this habit with small classes means we are
much more likely to do it when it really does matter in classes with far more fields. Immediately after the constructor, we have
two standard `getter’ or `accessor’ methods: getName and getMark. Notice that, once again,
we have included javadoc comments for them, even though they are such simple methods.
We have included both a description of their purpose and the @return documentation. It
is not uncommon to see code with either or both of these parts missing for getter methods.
We prefer to fully document because sometimes only the generated javadoc documentation,
and not the source code, will be available to someone working with your classes and clear
documentation leaves no room for doubt about the purpose or function of each method. Something else to notice is the way in which
the curly brackets of the constructor and the getters have been placed in similar positions:
consistency of layout is important. You can observe the same idea in the position of the
statements inside the bodies of the constructor and the getters: each has been indented to
the same position: 4 spaces in this particular case. In general, exactly where you place the curly
brackets or how much you indent by is not the most important thing. It is consistency,
because that will make your code easier to read by everyone. Next, we don’t have a `setter’ or `mutator’
method for the course name, because that is set on construction and won’t be changed during
the lifetime of the associated instance. But we do have a setter for the mark value, because
that is not set to anything other than zero on construction. Once again, we have fully documented the purpose
of the method and – particularly – we have been clear that the expected value of the
parameter must lie between 0 and 100. This information is very important to any user
of our class, or reader of the documentation. The valid mark range could be anything: 0
to 20, 0 to 50, even maybe -20 to +20. We haven’t written the class to be completely
flexible over mark ranges (which we could have done); we have written it to work with
marks from 0 to 100. Notice, too, that we have been explicit about whether the limits
of the range – 0 and 100 – are included as valid values or excluded. Again, this is essential
information for the reader. The job of a setter is obviously to allow
the value of one of the fields to be set, and in so doing it completes the core aspect
of encapsulation made possible by declaring the instance variables as `private’. It protects
the variable from being set to any value other than one that is within the allowed range
– and it is the Module class that defines that allowed range. Hence, the first thing
the setter does before setting the variable from the parameter is to check the parameter’s
value. Only if the parameter’s value is in the correct range is the instance variable’s
value updated. The importance of this role of a setter cannot be overemphasized: it is
a guardian of an object’s internal state and keeps the object from ever getting into an
incorrect state. Note how the error message is informative
so that any error in calling the method with a wrong value can be easily diagnosed and
corrected. In essence, the message contains three important details that should be considered
including in most error messages: It alerts that a calling error has occurred. It shows the value that is in error. It provides information that explains exactly
what was wrong with the value. Something worth observing about the body of
the setMark method is that there is often not a particularly neat way of formatting
strings that involve lots of concatenation. Here we have broken a single statement over
three lines, with indentation on the second and third to try to indicate that they are
really still part of the preceding line. Finally, there is a toString method that returns
a formatted version of the module name and mark. Notice that the style is exactly the
same in terms of documentation and layout as all the other methods in the class. In this video we have revised the basics of
good style in writing object-oriented Java classes. Although the class we have looked
at is one of the most basic, all of the aspects we have covered can be applied over and over
again in every class you write. Forming good habits will make your coding easier – because
you won’t have to keep thinking about what to do – and will create a good impression
of your coding skills in anyone who reads your code.

Leave a Reply

Your email address will not be published. Required fields are marked *