Object Oriented in Practice with BufferUnderflow
Introduction#
While learning theory is important, it's equally important to apply that theory in practice. In this section, we build a real-world application, focusing on the following concepts from the previous section: encapsulation, abstraction, composition, and polymorphism.
The program we are building, BufferUnderflow, is a forum for developers to ask and answer questions. A question can have many answers, but only one chosen answer. An answer can only belong to one question. Both questions and answers can have multiple attachments.
The diagram below shows the dependencies between the various classes and interfaces in our program:

We created an "All Classes" circle that implements the Unique
and Summary
interfaces to avoid having to draw a lot of messy lines.
Our dependency diagram dictates the implementation order of our classes and interfaces. For starters, we will implement the three interfaces Summary
, Unique
, and Attachment
. Then we'll implement our classes: Image
, Answer
, Question
, and User
.
Code Examples#
The code in this section will live under a BufferUnderflow
folder. The top-level folder structure of our code will be as follows:
BufferUnderflow/
├── entities/
├── utils/
├── app.ts
├── package.json
├── tsconfig.json
The entities
folder will contain all classes and interfaces. The utils
folder will contain global utilities that can be imported from anywhere in the app. The app.ts
file represents the entry point of our application--it will contain the code that makes use of the entities we create in the entities
folder. The package.json
will contain the dependencies of our project (i.e. ts-node
and typescript
). And the tsconfig.json
will contain compilation configuration that will be used by ts-node
and our IDE.
We run the following commands to initialize package.json
and install our two dependencies, typescript
and ts-node
:
> npm init --yes
> npm install --save-dev typescript ts-node
We run the following command to create .tsconfig
file with strict mode enabled.
> npx tsc --init --strict
For a detailed breakdown of strict mode, refer to the Compiler Options chapter. For now, trust that it will surface more useful errors than non-strict mode.
To test that everything is working correctly, let's write the following code in the BufferUnderflow/app.ts
file:
console.log('Type Safety Rocks!');
And run it with the following command:
> npx ts-node app.ts
If you see Type Safety Rocks!
in your terminal, everything is working as expected. We'll use ts-node
to run the code snippets in the following sections.
Unique Entity#
There are two important requirements that all instantiated classes in BufferUnderflow must satisfy: they must be uniquely identifiable and they must be able to generate summaries of themselves. A summary is defined as a string consisting of the most important information about an object.
To enforce these requirements, we'll use interfaces. The first of our interfaces is the Unique
interface shown below:
type UniqueId = string;
This page is a preview of Beginners Guide to TypeScript