This is Part 3 of our five part “Learn to Program” series. In Part 2, we created “DelphiSuperCalculator” project and learned how to build, run and debug it.
Layers
Before rushing into writing code it is a good thing to step back first and think about the overall architecture of your app. This typically involves breaking your app into smaller parts and in code a typical metaphor is a "layer" or "tier" of code. Even in the simplest possible app there could be at least two layers: one for the GUI (Graphical User Interface) and one for the application logic. Keeping the GUI part as thin as possible is always a good idea, especially when you build different screens for the same logic. Below the application logic there is typically some kind of data or service access layer, which encapsulates all aspects of interactions between an app and services or databases it depends on. Going further there are multi-tier, scalable, cloud architectures where database access can be further divided into additional layers which is important to implement scalable, fault-tolerant, multi-user systems.
You may think that a simple calculator apps does not need to have a “proper architecture”, but this leads to messy applications very quickly. Sooner than you expect even the simplest app starts to be complicated. Keeping the architecture of your app clean is one of the most important things in programming to improve performance, readability, and ongoing maintenance (and you never know when you might reuse a piece of code you wrote in a hurry today in a bigger application down the road).
In the case of our simple calculator app we can define just two layers. One layer with GUI – that is our main form unit, and one with the "calculation engine" that should live in a separate unit.
Adding a Second Unit
Let’s add a new unit (that is, a new Object pascal source code file) to our app with the File > New > Unit – Delphi command and save it as “uCalculator”. Here we are going to define a “TCalculator” class that is going to be responsible for performing basic calculations like adding, subtracting, multiplying and dividing numbers.
Enter the following code in the new unit:
unit uCalculator; interface type TCalculator = class public class function Add(a, b: Double): Double; class function Subtract(a, b: Double): Double; class function Multiply(a, b: Double): Double; class function Divide(a, b: Double): Double; endimplementation { TCalculator } class function TCalculator.Add(a, b: Double): Double; begin Result := a + b; endclass function TCalculator.Divide(a, b: Double): Double; begin Result := a / b; endclass function TCalculator.Multiply(a, b: Double): Double; begin Result := a * b; endclass function TCalculator.Subtract(a, b: Double): Double; begin Result := a - b; endend.
The Object Pascal language used in Delphi has been designed to teach good programming practices. It is very readable and helps develop programs in the top-down fashion. It is possible to write your code in a purely procedural fashion, ignoring completely object-oriented programming. However thinking about the problem domain in terms of objects and classes of objects proved to be a very good approach.
We want to implement calculator app, so we would probably want to have a "TCalculator" class that could be used for encapsulating calculator functionality. When you define a class it serves as a blueprint for creating objects of this class. In the case of our calculator we do not really need to have an instance of a calculator. Here the class serves more as a grouping of related arithmetic operations. That is why declarations of TCalculator methods have been preceded with a "class" modifier (which corresponds to "static" in C++). Class members of a class belong to the type itself, and you do not need to instantiate an object in order to call them. That's what we want. In our application code we would be able to type just "z := TCalculator.Add(x,y);" without creating a TCalculator object.
In Part 4 we will start building the user interface for our calculator and write code that will use our TCalculator class.
Next in this Series
Part 1: Introduction and Installation
Part 2: Building and Debugging in Delphi
Part 3: Architecture and Layers (This blog post)