When we get to the UI we find that we have a button that puts a group into edit mode. It doesn't make sense that this button is enabled for system groups, as they cannot be edited. So, when the button is rendered, it makes sense to decide whether or not it should be enabled.
Some folks might be tempted to set the enabled state of their button based on the type of the group, e.g.:
if(model.getSelectedGroup().getClass().equals(SystemGroup.class)) {
manageGroupLink.setEnabled(false);
} else {
manageGroupLink.setEnabled(true);
}
I'm not really a fan of this approach. To me this says system groups can't be managed. And it says it in the UI code. To reiterate, this approach puts a business rule (system groups can't be managed) into the UI code. It also puts knowledge of the subtype hierachy into the UI which means that any careful work we might have done to ensure that the UI works with interfaces is now lost. But it is quick and easy. And if business rules change and more subtypes are created, maybe another developer will be the lucky one who has to fix things.
Actually, its perhaps hard to see in an isolated example why this is a problem. But as systems grow and this logic is required in more places it becomes a maintenance nightmare to have business rules repeated all over the UI that need updating if they change or if new subtypes are introduced.
Separating concerns into discrete layers is a fairly well accepted but often misused concept. The UI should arguably not be concerned with business rules and concrete implementations. It should be concerned with displaying data and reacting to user input.
If we stick to this rule, even though not doing so doesn't present a problem at this stage, we have protected ourselves against future changes by design. If we get into the habit of keeping UI components free of business rules and knowledge of subtypes then we might not even realise that doing so in a particular situation saved us a world of pain.
Duck typing is one possible solution to the problem. Its based on the theory that 'if it quacks like a duck it must be a duck'. The premise is that if an object responds in a certain way then we can treat it accordingly. So how would things look different if we applied this approach?
manageGroupLink.setEnabled(model.getSelectedGroup().isManageable());
This implies that the selected group implements isManageable. Any implementation of group can implement this property. This nicely puts the business logic into the domain object. We could look at a system group and see that it returns false when isManageable is called. In my opinion, there's no better place to put this information. UI components don't need to know about the subtype hierachy and the job is done in one line of code (imagine if there were ten subtypes, some of which were manageable and so of which weren't, we'd have a big if-else block).