Introduction

The one tricky thing about tech and software development is sometimes how to understand certain things.  You know how it goes, you read articles, watch endless YouTube videos and whatever you try, nothing sticks, leaving you with a mixed bag of emotions.

However, sometimes there comes along an example that brings everything into clarity, and it all becomes clear.  Life is all of a sudden good once more.

My brain and I presume many other minds out there like real-world examples to explain some concept.  I thought I would share a couple of examples that help me understand and explain some concepts but importantly makes it easier to explain to newcomers to the industry.  Two of the best real-world explanations I have come across explain:

  • Programming Interfaces
  • Node.js Event Loop

One of the tests of the success of explanation is we should not only be able to explain the concept to junior programmers but also adults with no technical understanding or even children.

For clarity, this is not a guide on how to implement these topics. Instead, it is just a fundamental understanding of the concept.

Interfaces

The definition of an interface lifted straight from MSDN is as follows:

An interface contains definitions for a group of related functionalities that a non-abstract class or a struct must implement. An interface may define static methods, which must have an implementation. Beginning with C# 8.0, an interface may define a default implementation for members. An interface may not declare instance data such as fields, auto-implemented properties, or property-like events.

By using interfaces, you can, for example, include behavior from multiple sources in a class. That capability is important in C# because the language doesn't support multiple inheritance of classes. In addition, you must use an interface if you want to simulate inheritance for structs, because they can't actually inherit from another struct or class.

This is an excellent definition but probably means is a little on the verbose side, making it difficult to read and understand.  One of the best examples of explaining interfaces is in the book - Dependency Injection in .Net

The author, Mark Seemann, uses electrical sockets to explain Interfaces, I recommend reading the full example by buying the book, or if you want the first chapter is free online, which contains this example.

A summary of the explanation is:

An electrical socket on a wall enables the support for multiple devices.  You can plug a computer, lamp, phone charger or anything else into it to receive power as long as it the plug matches the shape defined by the socket.

In the above analogy, the socket is our interface and the devices we plug in our concrete implementations.  The socket does not care what the device does, or even know about future devices.  In software, as long as our classes match the interface, the implementation can be anything.

Node.js Event Loop

Understanding the Node.js queue is essential to know why Node.js is a fantastic choice for fast, efficient and high scaling web applications.  Node.js is a single-threaded server that is asynchronous by default which differs from traditional servers such as Apache which is multi-threaded but synchronous by default.  We will see why this is important in a moment, but before we do let us have a look at our real-world example and compare two Mexican restaurants.

Restaurant 1

  • The customer enters the restaurant and sits down.
  • The waiter takes the customer order and delivers it to the kitchen.
  • A second customer enters the restaurant and sits down.
  • The waiter sits in the kitchen and waits for the chef to prepare the meal.

As the waiter is sitting in the kitchen for the first customers' meal, he is unable to serve the second customer.  Eventually, the chef completes the order for the first customer and takes it to the table and is now free to serve the second customer.

Restaurant 2

  • The customer enters the restaurant and sits down.
  • The waiter takes the customer order and delivers it to the kitchen.
  • A second customer enters the restaurant and sits down.
  • The waiter does not wait on the chef, instead serves the second customer and delivers their meal to the kitchen.
  • The chef completes the second customer order and gives it to them.

The waiter doesn't stop working and repeatedly:

  • Takes an order from the customer.
  • Places the order in the kitchen.
  • once completed, they take the meal to the customer.

The waiter does not stop unless becoming blocked by a long-running request, in our scenario spending too long talking to a customer.

Node.js event loop

These two examples show the difference between blocking and non-blocking, which is the fundamental problem Node.js solves.

Kitchen one is our Apache server. Threads (The waiter) synchronously do their work.  For example, a thread making a database request will wait until the response and does nothing until the request is complete.

Kitchen two is our Node.js server. The thread asynchronously does their work. For example, the thread makes the database request but does not wait for it to finish; instead, it registers a callback to run once the response is received.  The thread is free to perform other operations.

Apache can overcome this by spinning up multiple threads but eventually will run out of threads to complete the task.  Node.js, on the other hand, can keep executing requests and running callbacks in the order they are received.

This asynchronous non-blocking approach works excellent for I/O operations because Node.js does not directly do the disk or network operations.  In CPU intensive work such as long-running calculations, this would block the thread and effectively stop Node.js performing.

This is a simple and short explanation of the event loop, and if you would like to read more I would recommend visiting the tutorials and documentation on https://nodejs.dev/

Wrapping Up

So there we have it, I think these are two straightforward real-world examples to explain some software development patterns.  We all work differently, but for me, being able to associate how things work in software development with real-world examples helps to cement my understanding.

I hope you have enjoyed this short read, but would love to hear any examples you have.