It was so tempting to start this blog in the classic style: ‘Nested Classes Considered Harmful’, but people turn you off when they see that sort of thing and rightly so. There are few hard and fast rules in software development, and when you take a strident position you end up in a flame war. You can’t have a conversation. So, forget I wrote the “considered harmful" part.
Let’s start this again.
I have strong feelings about nested classes. I tend to avoid them and I don’t think I'm being irrational. Here’s why.
- Nested classes can make code less readable. If they are short, it’s no problem, but it’s not uncommon to see one that spans half a page. When that happens, the class it's embedded in is unavoidably less readable: it’s interrupted by the nested class. Want to scan up and look at the imports or see what it inherits from? Well you have to scroll over the nested class, and it’s worse when there are declarations above the nested class. You lose the big picture.
- Nested classes (in most languages) have special access to their enclosing scope. “So what?”, I hear you say. Well, whenever you have nested scopes you have the possibility of name conflicts. In many languages, a new scope can silently hide variables and methods. I’ve seen people spend 10 to 20 minutes debugging problems related to nested scopes. Don’t get me wrong, I think it’s great to have a global scope and it’s great to have method scopes. Namespaces are great too, but every level increases the chances of misunderstanding.
- Nested classes are often hard to find. “Pfaaaa!” I hear you say, “I use modern tools, I can find anything in a few keystrokes.” Well, yes, but it’s amazing the number of times that you have to ask yourself where something is in a project, times when you are outside of a tool and file names are your only guidance. Even when you are in your editor or IDE and able to just leap to a definition, you confront the semantic problem: when you arrive at a nested class you have to ask yourself “Gee, what does it pull from the outer scope? Why is it here? Is it hiding anything?”
So, at this point, I guess you can see why I’m not pressing this, why I’m not saying “nested classes considered harmful.” It’s a style thing. I just find that I don’t need them. If I need a non-anonymous class, I have no problem promoting it to normal class scope. I know that many people don’t like that. They look at the cases where their little class is used only inside of another one and say “This is perfect, when I make this class an inner class I'm documenting the fact that it's used locally. I avoid polluting the outer name space.” That’s fine, but, really, if you’re that concerned with polluting the outer name space maybe it's too large already. It’s something to think about.
To me, code is much clearer when nested classes are used sparingly.
But, that’s just me.