Type Script - Interfaces and Inversion of Control
Plan
The paln is to learn how Inversion of Control - IoC and Interfaces can be used to achieve loosely coupled design for programs in Type Script.
We learn by writing a program which automatically responds to Discord messages.
Program will listen for the messages, check for a specific word ex: ping
in the message and then send reply to the message if the word is found in the message.
What is Discord ?
Discord is a group-chatting platform originally built for gamers, but which has since become a general use platform for all sorts of communities.
Pre Requisites
Discord
- Create an account in Discord https://discord.com/
- Download and install Discord application on your computer or open in Browser
- Add a Server -> Create My Own Server
- Browse the following url and create an application - https://discord.com/developers/applications
- After creating the application, create a Bot inside the application
- Copy Client ID of the application
- Add the bot to your Discord Server by replacing the client id in the following url:
https://discord.com/api/oauth2/authorize?client_id=<REPLACE_YOUR_CLIENT_ID_HERE>&scope=bot&permissions=1
Node
Node js version 12 or higher should be installed on your computer
Install and Run
Clone my GitHub repository -
https://github.com/smarigowda/discord-bot
Install node modules -
npm install
Rename the file
.env.example
to.env
. Copy the bot token into .env fileCompile/ Transpile the Type Script program -
npm run compile
Run the program -
npm start
- Test the program (animated gif below). As you can see the bot program sends a reply if the message has a
ping
word in it.
Program Overview - Interfaces
Discord provides a node module to interact with its APIs https://www.npmjs.com/package/discord.js
. It exposes Client
class which can be used to login, listen to messages and send reply.
Our program has a Bot
class which encapsulates discord Client
. Bot
class implemts IBot
interface, having listen()
method. This way the end user (which is index.ts file) does not need to worry about the internal details, but just use the listen()
method.
In order to implement the search functionality we create two more interfaces IPingFinder
and IMessageResponder
PingFinder
and MessageResponder
classes are concrete implementations of interfaces IPingFinder
and IMessageResponder
Interface IPingFinder
has one method isPing()
which returns true if the message contains the word ping
Interface IMessageResponder
has one method handle()
which is used by the Bot
class to handle the message and see if the message contains the word ping
The program gets concrete implementations using inversion of control.
Inversion of Control/ Dependency Injection
Inversify http://inversify.io/
is used to automatically provide dependencies. Inversify is a lightweight container providing inversion of control for JavaScript and Node.js apps powered by TypeScript.
By using inversion of control and interfaces, the program achieves loose coupling. Concrete classes can be replaced without needing any change in the program code where they are used, because the code does not refer to concrete implementation at all, it only refers to the interfaces.
Also, since we are uisng inversion of control, concrete classes need to be updated only at one place, inversify config file.