Pages this page links to:
Pages linking to this page:
Application Architecture
There are two primary delivery mechanisms for software today:
- local installation (pkg managers, app stores, etc)
- web delivery (saas)
Local installation loads all of the software onto a particular device, which can then run the software without needing additional information from the internet. Local installation requires that software be developed to be compatible with the device it will be run on. In the 80s, a lot of software was custom built for specific combinations of hardware, targetting devices with specific resolutions or even cpu clock timing. These days, software layers (osx, windows, ios, android, etc) provide a rich platform to program against, so authors usually only need to specifically target the platform and the architecture (x86, arm, etc).
Web delivery involves loading an application from a remote source and running it. There are two main approaches, "thin client" and "thick client."
In the 80s and early 90s, client machines were expensive, large, and noisy, so the dream was to be able to run inexpensive "thin clients" on peoples desks and let your more powerful centralized computing resources (like a mainframe) run programs centrally. X11 is designed to be exported over the network to facilitate this type of delivery, though it's starting to be replaced by Wayland. This is why there is an xclient
and xserver
; when you click on interface elements, a message is sent to the server, and a response tells the client what to render. The VT100 terminal is another example of a thin client, and terminal based applications are still popular (though remote usage is almost exclusively over SSH).
By the late 90s, the PC revolution made thick clients much more viable. Today, the most popular form of web delivery by far is over HTTP, with applications run in a web browser. The modern browser provides a strong set of rendering primitives and a language (JavaScript) to extend behavioral capabilities by running code on the client machine. When people say "web apps", they mean HTTP delivered applications.
Separation of Concerns
Nearly all applications have three primary concerns: the data layer, the application logic, and the presentation logic.
If you consider eg. a video encoder, which is usually a local application, the data layer is relatively simple: the local filesystem provides an API to read and write files. It contains the video files the application modifies, as well as some user settings that persist across sessions. The application logic includes code that can parse the metadata from a video file or transcode from an existing file to some new encoding settings. The presentation logic makes some of that data available to the user, and provides an interface for the user to select the transcoded target's settings.
It's common for newer programmers to mix these concerns. You'll write eg. a calculator, with a config file that allows the user to specify int or float mode:
def calculator():
int_mode = True if open("calculator.cfg").read().strip() == 'int' else False
print("Welcome to my Calculator")
equation = input("calc > ")
parts = equation.split()
a, op, b = float(parts[0]), parts[1], float(parts[2])
if int_mode:
a, b = int(a), int(b)
if op == "+":
print(equation, "=", a+b)
elif op == "-":
print(equation, "=", a-b)
elif op == "*":
print(equation, "=", a*b)
elif op == "/":
if int_mode:
print(equation, "=", a//b)
else:
print(equation, "=", a/b)
You can see here that the data, application, and program logic is all mixed. For very simple programs, this is fine, and in fact the most common mistake that intermediate programmers make is applying too many abstractions to simple programs like this.
What happens when you modify this program to add new features? Consider the following modifications:
- adopt
json
for the config file - add a config option to specify output in English or French
- add a support for modulo (%) and binary shift (<< / >>)
- add a routine for our calculator to output the result as an image
- add support for parentheses
- only read the config file when it changes
- support multiple concurrent users
It's clear that we will have to create some abstractions to support these features, and what programmers found is that abstracting each logical layer separately led to easier modification over time.
MVC
MVC stands for Model-View-Controller, and it's a popular paradigm for developing software with user interfaces.
MVC originates from GUI software development. Consider a GUI with a lot of various check boxes and option boxes. When it comes time to execute some operation, the parameters for that operation probably depend on the state of those boxes. The simplest way to ensure that the operation executes correctly is to scour your GUI for the state of those options. Simple is good, but this has two major problems: traversing the GUI may be prohibitively expensive, and now your application logic depends on the GUI and can break if it's changed!
MVC provides a way to separate this into layers. The "model"