Blog-Archiv

Sonntag, 16. Oktober 2016

About Getters and Setters

There has been a lot of discussion about getters and setters, spanning different programming languages.

For example in Java, there are programmers that write classes where all fields always have both public getters and setters. When you ask them for the reason, they say "It can be easily done with my IDE", or "I thought this is required".

In JavaScript, getters and setters are not a programming tradition, because JS is not an object-oriented language. Nevertheless people try to use it as such, and you find getters and setters also in JS code.

I believe the get / set tradition started with C++, which was the first real object-oriented language. There the getter is called "accessor", and the setter "mutator".

What is Getter / Setter?

A getter is a method that returns the value of a "member"-field, and a setter lets change its value. It is a stereotype used in object-oriented languages. Here is an example for a Java Bean.

public class Person
{
    private String name;
        
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

Following the Java Beans Specification we call "name" a property, and an instance of Person a bean. Thus a bean is a container for 1..n properties. A bean is meant to be the smallest building-block for composing reusable software.

The "name" property is a read/write property, because it has both getter and setter. Would it have only getter, it was read-only. Would it have neither getter nor setter, it was just a field, not a property.

Why do we need Getter / Setter?

In the bean-example above, getters and setters can be used for implementing read-only access. In other words, when you make a field private in Java, you can neither read nor write it from outside the class. When you make the field protected or public, it would always have both read- and write-access in the same way. You can not implement read-only properties other than by

  • setting the field private,
  • provide a getter,
  • and leave out the setter.

There is no readonly access-modifier in Java which would make it writeable to just the owning class.

Here is the Person bean with a read-only property "name". Mind that "name" is still writeable within the owning class!

public class Person
{
    private String name;
        
    public Person(String name) {
        this.name = name;
    }
        
    public String getName() {
        return name;
    }
}

So whether you need getters and setters seems to depend on the programming-language. Assuming there is a programming language that provides a readonly access modifier, would we still need getters?

Let's say "No". But, we would still like to use setters!

public class Person
{
    private String name;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        fireChanged();
        this.name = name;
    }

    private void fireChanged() {
        .... // TODO
    }
}

This bean has a little "logic" in it. It notifies listeners as soon as one of its properties was changed. How could we implement value-change logic safely when not using a setter?

There is also another common reason for using getters and setters, that is software maintenance. Imagine we made the "name" field public and provided neither getter nor setter. All surrounding code that uses objects of that class now reads and writes to the field directly. (We reduced the lines of code for this class greatly :-)

public class Person
{
    public String name;
}

So this is how a Person looks like now.

Unfortunately a month later it turns out that the name of the person must be provided by another database class PersonData, and Person must delegate to that new class now.

public class PersonData
{
    public String name;
}

public class Person
{
    public PersonData data;

    public String getName() {
        return data.name;
    }
}

Now all the classes that use person.name must be rewritten. When you consider that domain-objects like Person are the most widely used in an application, and that the field-access needs to be refactored to be a method-call, you might agree that using getters and setters makes sense, at least with a programming language like Java (which is still one of the most modern ones).

Of course the same applies to PersonData, so here it is how they should look like:

public class PersonData
{
    private String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

public class Person
{
    private final PersonData data;

    public Person(PersonData data) {
        assert data != null;
        this.data = data;
    }

    public String getName() {
        return data.getName();
    }
    public void setName(String name) {
        data.setName(name);
    }
}

There is one last reason why I would like to have a getter. This reason may have expired in environments where debuggers let set watch-points to detect field modifications. But in environments where debuggers do not allow such, I would like to set a breakpoint into the getter to find out what the heck modifies that field so that this bug occurs - !

When Getter exists, use only Getter

In the following example, the getFullName() method accesses firstName and lastName directly, ignoring their getters. The question rises whether you are allowed to directly access a field, within its class, in case a getter exists (same for setter).

public class Person
{
    private String firstName;
    private String lastName;
    
    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getFullName() {
        return firstName+" "+lastName;
    }
}

The answer is "No". As soon as there is a getter, only the getter should be used. Think of the maintenance example above. This also applies to the owning class itself. And, as soon as a setter exist, value-change logic could have been implemented, which may be ignored when accessing the field directly.

So, as soon as you introduce a getter or setter, refactor the class to not access the field directly any more. Exception is access in constructor, because you should not call overrideable methods from constructor.

public class Person
{
    ....

    public String getFullName() {
        return getFirstName()+" "+getLastName();
    }
}

Advices

If this sounds now like me trying to convince you that setters and getters always make sense: No, I did not say that! Getters and setters sometimes make sense. I just showed some of the situations where you need to encapsulate fields.

  • Getters should be created just when needed
  • When getter exists, use only getter
  • Getters should have as much encapsulation as possible, best private, else package-visible or protected final, worst is public
  • Setters should be created just when needed
  • Setters should have as much encapsulation as possible, ...
  • Getter and setter can have different access modifiers, try to reduce especially the setter's visibility!




Freitag, 7. Oktober 2016

How to Avoid Switch Statements in Java

A refactoring that has been made popular by Martin Fowler is "Replace Switch-Statements by Polymorphism". We learn that wherever a switch statement is, OO thinking has been absent.

This impressive refactoring has been described on the Internet many times. It demonstrates the power of OO thinking in an unique way. Here comes my contribution.

Smelling Switch Code

Two types of employees exist, ENGINEER gets the base salary, MANAGER gets more, because (s)he is more equal. The distinction is done by a switch-case statement that uses the constructor parameter.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Employee
{
    public static final int ENGINEER = 1;
    public static final int MANAGER = 2;

    private final int monthly = 100;
    private final int bonus = monthly / 10;

    private final int type;

    public Employee(int type) {
        if (type < ENGINEER || type > MANAGER)
          throw new IllegalArgumentException("Unknown employee type: "+type);

        this.type = type;
    }

    public int salary() {
        switch(type) {
            case ENGINEER: return monthly;
            case MANAGER: return monthly + bonus;
        }
    }
}

We could test this with following code:

final Employee engineer = new Employee(Employee.ENGINEER);
assert engineer.salary() == 100;

final Employee manager = new Employee(Employee.MANAGER);
assert manager.salary() == 110;

Aside from the social smell the question rises whether it is acceptable to implement two types of employees in the same class (type). OO-thinking people have provided an impressive alternative.

Refactored using Sub-Classes

The rewrite is scattered across several classes, but it is not longer than the code above.

1
2
3
4
5
6
abstract class AbstractEmployee
{
    protected final int monthly = 100;

    public abstract int salary();
}

1
2
3
4
5
6
7
8
public class Engineer extends AbstractEmployee
{
    @Override
    public int salary() {
        final int bonus = monthly / 10;
        return monthly + bonus;
    }
}

1
2
3
4
5
6
7
public class Manager extends AbstractEmployee
{
    @Override
    public int salary() {
        return monthly;
    }
}

To be tested by:

final Employee engineer = new Engineer();
assert engineer.salary() == 110;

final Employee manager = new Manager();
assert manager.salary() == 100;

As you can see, this is intuitively readable and much cleaner.
Even the social smell has been refactored :-)




Donnerstag, 6. Oktober 2016

Java Access Modifiers

It is stunning to see how many programmers simply ignore valuable language features like access modifiers. That's a pity. It takes some time to get familiar with them, but it pays, for sure.

The Java access modifiers are, in order of their encapsulation strength, descending, following reserved words:

  • private
  • using no modifier is called "default access", or "package-visible"
  • protected
  • public

They can be mixed with two more keywords that define the nature of a field, method or class more exactly:

  • final
  • static

Ignoring access modifiers means writing code that lacks robustness. You must make clear what of the class is public, what is to be inherited only, and what must not be seen from outside at all. Thus access modifiers should be means of expression of your daily programming work. Encapsulation is the target. And the target of encapsulation is to reduce complexity by exposing just what's needed to the outer world. Complexity is what makes our life hard.

You might use an IDE that provides the auto-complete action Ctrl-Space. This enables fast and safe programming, without reading thick books before using an API. When the authors of that API used access modifiers in a correct way, you will, in your auto-complete, see just methods that really can be called or overridden, not all the confusing internals. Thus access modifiers are a prerequisite for a good auto-complete functionality.

Any modern programming language must provide some means for encapsulation, else you wouldn't be able to implement big applications with it.

Private

If I would have designed the Java language, I would have made private the default access modifier. Stating nothing about access (default access) means "stay in context", and the context is mostly the class, not the package.

Make as much as possible private in your application, that way you hide complexity from the outer world. Private methods and fields can not be accessed by other classes, not even by sub-classes. When having a hierarchy of classes, e.g. Animal, Mammal extends Animal, Cat extends Mammal, each of these could have a private move() method implementation of its own, not overriding the super-class implementation. A private thing is usable only within its own class.

The private modifier can be used on methods, fields and inner classes, but not on top-level classes.

Final

As this modifier plays together with all of the following, I describe it here and now. A final field can not be modified any more after it got its value once. It is a constant, or an immutable field. Such fields must get their value directly at definition, in a static- or instance-initializer, or in a constructor. Try to use final on fields as much as possible, it will make your implementation more robust and easier to understand.

Methods that are final can not be overridden. Private methods need not to be set final, because they can not be overridden by nature. Referring to the anti-pattern DoNotCallOverridableMethodsInConstructor I would recommend to make final all methods that are called from a constructor.

Classes that are final can not be derived (extended to sub-classes). This is very useful for utility classes that contain just stateless static methods. Additionally declare a private constructor on them and nobody will be able to wrongly instantiate such a class.

(No Modifier)

The so-called default-access expresses "package-visibility". A method or field with no access modifier can be read and written by classes in same package only. It is not visible outside the package, even sub-classes can not see it when they are in a different package.

This access modifier is rarely used, but it makes sense when you want to encapsulate several top-level classes into a package, instead of using inner classes (because the outer class would get too big then). Typically you would have some package-visible classes, and one public facade-class that uses all of them.

Default-access can be used on methods, fields, inner classes and top-level classes.

Protected

This is for inheriting to sub-classes. In other words, you do not want that to be accessible by any class except a sub-classes. Unfortunately the Java protected modifier also allows read / write access by all classes in same package, but this mostly is not a problem.

While the final keyword does not make sense with the private modifier (is final automatically), it makes a lot of sense with protected methods. You should distinguish between protected methods that are made to be overridden, and such ones that are made to be called by sub-classes (utility methods). The last should be final. This makes life easier for developers that derive the class and wonder what they need to override now.

The protected modifier can be used on methods, fields and inner classes, but not on top-level classes. I would not recommend to make fields protected, you lose their encapsulation to sub-classes.

Public

Visible for the whole world. Fields that are public can be modified by everyone (avoid them). Methods that are public can be called by everyone, which may be what you want. Make them final when their overriding could break the "state" of the class. Classes that are public can be used by everyone, although you can restrict their instantiation by the access modifiers of their constructors.

Try to avoid public as much as possible. If all methods of a class are public, you missed encapsulation. Exceptions prove the rule, so anemic classes may have public on all methods.

The public modifier can be used on methods, fields, inner classes and top-level classes. Mind that you should never have public fields that are not final. Mutable non-final fields make up the "state" of an object, and thus are primary subjects for encapsulation. But public final fields are OK. You don't need to write getter-methods then. Just keep in mind that some reflection utilities might not be happy with that.

Static

This modifier binds to the class, not to the object-instance (created from that class). Fields that are static are the same for all instances of a class. Always make them final. A static final field is what is called constant in other programming languages.

Code in static methods is not reusable and overridable. Try to avoid that. Static methods always should be stateless, meaning the only fields they are allowed to use are their parameters.

Instances of static inner classes are not bound to an instance of the outer class. In other words, they do not have an implicit pointer to the enclosing object, like instances of non-static inner classes have. This may be a disadvantage in some cases, but in general it makes garbage collection easier, and that pointer to the outer instance may not be needed at all in many cases. So static inner classes are the preferable ones.

The static modifier makes no sense on top-level classes.


Shadowing

What happens when you have a class Animal, and a class Mammal extends Animal, and both define a protected field with name "mouth"? This is an ambiguity that you should avoid. Always make fields private. If sub-classes need to see them, create protected getter-methods for them, and try to avoid the parallel setter. Fields that are protected and not final can quickly get out of control.


My Recommendations

  • Try to minimize visibility by selectively using access modifiers; hiding complexity means preventing its abuse.
  • Fields always should be private; in any other case (default access, protected, public) they should be final.
  • Make all non-private methods called from a constructor final, to avoid initialization bugs from overrides.
  • Use default-access as much as possible for hiding things within the package that the outer world doesn't need to see.
  • Distinguish between protected methods that are to be overridden, and such that should be just callable by sub-classes (make the latter final).
  • Avoid static methods, their code is not reusable in an object-oriented way; consider using singletons instead.
  • Prefer static inner classes, they don't have possibly unneeded dependencies to the enclosing object.
  • Make classes that contain just static stateless utility methods final, and define a private do-nothing constructor on them; this makes a wrong instantiation impossible.