One of the most surprising things about learning to play chess is that the middle game is a lot harder than the opening or end game. In the opening after all, there aren’t many moves that are even possible, 20 to be exact. On your first move, it’s only possible to move a pawn or a knight- that’s it. Same for your opponent. That’s not much to keep track of.
Once you’ve dutifully looked up chess openings in Wikipedia, you can winnow even that small set of moves down to a few acknowledged best openings: e4, d4, Nf3, and c4. And of those, really, most just stick to e4 or d4, that is, moving the pawn in front of your king or queen out two spaces. There are so few good possibilities in the first 3 or 4 turns, that each popular combination has its own name and body of research attached to it- the Scotch Game, the Ruy Lopez, the Danish Gambit, Sicilian Defence, etc.
Before long, though, as the board opens up, the number of possible moves and their potential consequences gets increasingly difficult to sort through. When you make that first move of your pawn, you can be sure that you’re not risking anything. In the middle game, where pieces have moved out from their initial positions, all kinds of attack vectors open up.
You need to worry not just about the piece you’re moving, but also about how it changes the state of all the other pieces. For example, maybe your pawn is between your queen and your opponent’s bishop. You move your pawn to a perfectly safe position, but you’ve just exposed your queen to attack.
Wikipedia’s article on the middle game comments, “There are usually too many pieces on the board for theoretical positions to be completely analyzed…” In other words, you’re on your own! No more looking up the best move instead of working it out for yourself. But as you move towards the end game, assuming you haven’t found a way to lose abruptly, it gets easier. With fewer pieces to study, you can once again find theory on various scenarios: bishop vs knight endings, queen vs two rooks, etc.
The lesson here is clearly that the more pieces you have that are in positions to effect other pieces, the more your head hurts trying to keep track of all the possibilities. Software has a lot of pieces, too, that all move and interact in different ways. In a language like java, you can manage the access to many of those pieces by declaring them private, which helps reduce the number of ways your code can be used. But it doesn’t help inside of a class and some developers seem determined to write enormous sausage classes that do everything themselves anyway.
Besides reducing the access to attributes, you can also make them simpler to handle by making them final- once you’ve given them a value, they’re guaranteed not to change. Immutable objects present many fewer scenarios to work through. That may sound small, but a lot of code out there just ignores the possibility of state changes and breaks badly when it happens.
Making attributes private and/or immutable makes an object less complicated to deal with, but why not just take some pieces off the board? If you can get away with storing fewer attributes, you remove a whole set of scenarios to worry about. Say that you have a function that merely accepts input arguments and return a value without causing side-effects like changing global variables. That’s a function that can only mess up your program in clearly defined, limited ways. That’s easy to think about.
This is the world of functional languages- they operate by evaluating functions rather than manipulating global state. But for all their recent hype, they are not used commercially very much. Even in a non-functional language like java, though, you can still make your life simpler by minimizing the amount of state you’re keeping track of and trying to write your functions to have no side effects. You can choose to make your code more like the opening or end game instead of the middle if you want.
Some chess players, of course, are great at seeing all the different possibilities on the board, even in the middle game. Some developers are great at keeping in mind all the different ways a program’s state could mutate. Sometimes you don’t have a choice in the matter and the complexity of your situation can’t be reduced. But if you do have a choice, fewer pieces is always easier to handle than more.