In the next posts I will try to examine some simple ways to make your application extensible. Most of the applications we use in our daily life have some form of extensibility. For example the Visual Studio has add ins, extensions, packages and other forms of extensibility which allow you integrate your own functionality to an existing application. For the purpose of our discussion I will define extensibility of an application simply as adding new application functionality without having to recompile any part of the application.
I will demonstrate briefly several simple ways to make your application extensible. To this end I have prepared a demo project (in fact, this post will discuss only this demo project).
The Balls Simulation
The demo project might be familiar to some of my readers since I take it from the new employee training program of my previous job. The application contains a rectangular area called "field". The user adds entities to that field called "balls" and they move inside the field. The balls may collide with each other during the movement within the field and they have to react accordingly. The balls may also collide with the walls and react accordingly.
A screenshot from my demo application |
- Movement - Determins how the ball is going to move around the field.
- Drawing - Determins how the ball is going to be drawn on the filed.
- Collision - Determines how the ball will react to a collision with another ball.
Now that I decided that these three items are my extensibility points I need to decide on the design of the application. I chose to implement it using the strategy design pattern. Each of the three elements mentioned above will have a strategy object which will be assigned to a ball. (The ball will be composed of the three element.) Now that this is decided I can define a dll that will be given to the extension writers, clients, which will contain the required interfaces. You don't want to give your clients a bulky dll that will contain all the classes and the logic but a thin layer which will not confuse them but will allow to write a complete extension set.
The interfaces I defined are:
public interface IMover
{
void Tick(IBall ball);
void Initialize(IBall ball);
void AtWalls(IBall ball, HashSet<WallType> wallTypes);
}
public interface IDrawer
{
void Tick(IBall ball);
void Initialize(IBall ball);
}
public interface IColider
{
void AfterCollision(IBall ball, IBall other);
void BeforeCollision(IBall ball, IBall other);
void Collision(IBall ball, IBall other);
}
At this point I want to dedicate a short passage on coding games. The basic design of a game contains a game timer that paces the game. The game timer activates as fast as possible but sometimes it is limited to a specific frame rate - FPS (Frames Per Second). Each time the timer activates is called a game "tick". In each tick the game manager iterates on all the entities within the game (called "sprites") and calls a method that updates their inner parameters. Then the game manager iterates on all the sprites again and draws them on the screen.