Object Oriented in Practice with BufferUnderflow
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
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
Attachment. Then we'll implement our classes:
The code in this section will live under a
BufferUnderflow folder. The top-level folder structure of our code will be as follows:
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.
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,
> 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
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.
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;