One of the “early mistakes” that any programmer makes is creating an infinite loop. Maybe a condition was not correctly set in a while loop. Or maybe some unexpected overflow condition occurred in a for loop.

Infinite loops have always had a bad cognitation for me. However, infinite loops are effectively the backbone of any long-running program. Whether it be apps with a user interface or a server side program, they all effectively use infinite loops to process incoming data.

Consumer apps use loops which listen for any UI interfaction among other data sources. Server side programs can use loops to listen for incoming events such as a new connection and then process data based on those events. Once the event has been processed, the loop starts again and waits for the next event.

Of course, in the technical definition, the run/event loops are not infinite because there are some loop termination conditions (whether it be a process signal or other flag). However, in practice, the expectation is that the programs run in a loop until a user wants to terminate the entire program.

When a programmer encounters an infinite loop the first time, s/he may think of it as something to avoid, but in practice, infinite loops are one of the core building blocks.

One (perhaps obvious) thing I’ve practiced over the years is to write code where every variable and method has the most private access control possible. As I iterate over the code and refactor pieces, I keep trying to limit access to data. In effect, limiting access helps with encapsulation.

Once I’ve iterated over the code several times, I find that the public methods usually leads to a good API. With some refinement, the public methods become public interfaces/protocols which eventually other modules consume.

When I was introduced to object-oriented programming, inheritance was one of the main principles taught. Inheritance is a good concept to learn. There are type relationships where something “is-a” child type of an existing parent type.

However, composition is a much more useful concept. When something “has-a” typed member, it is a more useful relationship.

For instance, instead of caring that types inherits from an Animal base implementation, the concern should be that individual types implement a set of methods (hence implementing an interface). For types which are composed with other member types, you can implement the interface by adapting to the interface and delegating to a composed member instance.

Adapting to an interface (whether strongly defined or just by “duck typing”) using delegation gains the benefits of re-using a method implementation without the downsides of inheritance.

The downsides of inheritance include (in most languages) only allowing single parent type inheritance, base parent types which cannot be easily changed without affecting child types, and potential complexities in multiple layers in inheritance type hierarchies.

Inheritance comes with many limitations and a few benefits, but composition is ultimately what should be preferred.