# Introduction

This is a course about application software: software designed to help users perform a task or solve a problem. Most of the software that you interact with on a daily basis are applications: the weather app on your phone, the spreadsheet that you use for work, the online game that you play with your friends. Applications can include console applications (e.g., vim), desktop software (e.g., MS Word for Windows), mobile software (e.g., Weather on iOS), or even web applications (e.g., Gmail).

My applications folder, at the time of writing
My applications folder, at the time of writing

Applications are often constrasted with system software, or software that is meant to provide services other other software e.g., operating systems. The diagram below illustrates this division: the operating system is responsible for managing hardware and other resources, and provides a well-defined API through which applications can make requests. The operating system provides core functionality that the application requires to be functional and useful.

Communication between applications and operating systems is done through system libraries and well-defined APIs.
Communication between applications and operating systems is done through system libraries and well-defined APIs.

Although we'll certainly leverage the underlying OS, in this course we're most interested in building applications that sit above the OS kernel. Let's dive a little deeper into what that means.

# History

Early applications were often small console applications that were written by users for their own use, or to share with friends. Over time, as the computing industry matured, commercial software became more viable, and resulted in the rise of more sophisticated and complex applications.

The design of any piece of software always reflects the capabilities and restrictions of the technologies that existed when they were initially designed. For example, early personal computers lacked graphics capabilities, so any applications written during this era were restricted to text interfaces (e.g., Lotus 1-2-3). Graphical applications only arose once hardware was sufficiently advanced to support interactive graphics, and the industry was mature enough to support a shift towards graphical systems.

Lotus 1-2-3, one of the first spreadsheets, running on DOS
Lotus 1-2-3, one of the first spreadsheets, running on DOS

Let's consider some of the trends that led to the modern software application.

# 1970s: Batch Processing

Up to the late 1970s, computers were typically large, expensive systems that were shared by multiple users who took turns executing their software. In this era, batch processing dominated, where users would submit their jobs (programs), and wait for the results.

Encoding instructions on a punch card, to be read by a mainframe
Encoding instructions on a punch card, to be read by a mainframe

The later part of this era saw the introduction of time-sharing systems, where multiple users could interact with the computer at the same time through text-based terminals. This was the first time that users could interact with the computer in real-time, and it laid the groundwork for the interactive systems that we use today.

Applications from this era were typically text-based, and optimized for transmission between terminals and the central computer that was actually running the software. Text-interfaces were dominant until the 1980s when graphical user interfaces became much more common.

A text-based terminal, connected to a mainframe
A text-based terminal, connected to a mainframe

This mode of interaction still exists, as console applications e.g., bash, vim, and is still used for many system administration tasks. It's also the primary mode of interaction for many developers, who use text editors and command-line tools to write and test their software.

# 1980s: Interactivity & GUIs

The introduction of personal computers in the early 1980s changed the status quo.

Personal computers were relatively inexpensive, and designed to be used by a single user. Instead of submitting jobs to a central computer, users could now run their software directly on their own machine. This allowed for the develop of interactive computing, where users could interact with the computer in real-time.

Early personal computers were text-based, but as hardware improved, graphical systems quickly dominated. Introduced in 1984, the Apple Macintosh was the first successful commercial graphical operating system; other vendors (e.g. Microsoft, Commodore, Sun) quickly followed suit with their own designs.

Early Mac desktop demonstrating windows, and standard widgets
Early Mac desktop demonstrating windows, and standard widgets

Today, Graphical User Interfaces are the norm. Users assume that they can interact with their computer using a keyboard and mouse, and that they can see the results of their actions on the screen.

Key features of a graphical user interface include:

  • Use of a keyboard and pointing device (mouse) for interaction. Point-and-Click to interact with graphical elements.
  • Windows used as logical container for an application's input/output.
  • Cut-Copy-Paste as a paradigm for manipulating textual data.
  • Undo-Redo as a paradigm for reverting changes.

Modern desktop operating systems, including Linux, macOS and Windows, are remarkable similar to these early designs. Very little has actually changed in terms of how we interact with desktop systems.

Windows 11 is more polished and capable than early graphical operating systems, but retains the same core design
Windows 11 is more polished and capable than early graphical operating systems, but retains the same core design

How have graphical applications and operating systems stayed so fixed in design over almost 50 years? There are measurable benefits to this design.

  • Graphical interfaces are highly customizable: we can build anything we want within the confines of a window.
  • We can interact with a wide range of data, including text, graphics and multimedia.
  • A graphical interface can provide affordances: visual suggestions on how you might interact with the system. This can include hints like tooltips, or a graphical design that makes use of controls obvious (e.g. handles to show where to "grab" a window corner). This helps when users need to explore and discover how features work.

The additional of standard features helps with usability:

  • Undo-redo, and the ability to rollback to previous state makes exploration low-risk.
  • Desktop menus (File > New, Edit > Cut/Copy/Paste and so on) help with feature discoverability.
  • Standard and consistent widgets and other interactive elements (i.e. a button works the same across all applications).

Standardization led to a common look-and-feel, and placement of common controls - which made software easier to learn, especially for novices. Many of the standard features that we take for granted are a direct result of this design standardization in the 80s.

# 1990s: Internet & Web Applications

Prior to about 1995, most applications were standalone, and did not have network connectivity. Networks certainly existed, but were typically geographically contained, and not widely available to the general public. e.g., you could connect to a mainframe at work, but not to a mainframe across the country. You might have a modem at home, but it was used to connect to a local bulletin board system, not to the Internet.

The rise of the Internet in the 1990s changed this. Suddenly, it was possible to connect to any computer in the world, and to share information with anyone, anywhere. This led to the rise of web applications, which are applications that run in a web browser, and are accessed over the Internet.

By the mid 2000s, Internet connectivity was common enough that designers started to assume that applications would have access to the Internet.This has led to a wide range of new capabilities in software. e.g., adding the ability to lookup data on the Internet.

In a modern application, it's fairly common to assume that the application will have access to the Internet. This brings with it a number of user expectations:

  • An application should update itself when a newer version is available.
  • Online documentation or help should be available through your application.
  • Online data is accessible! You can lookup data from online resources. e.g., email, weather, news.
  • Online collaboration is possible (and expected).

# 2000s: Cloud Computing

Cloud computing is the on-demand availability of hosted services, such as data storage, servers, databases, networking, and software over the internet. It was the next logical step after the rise of the Internet, and has become a major trend in the software industry.

Simply put, cloud computing is the delivery of computing services over the Internet. Instead of owning and maintaining physical servers, you can rent computing power from a cloud provider, and pay only for what you use.

For a developer, this means that you no longer need to build and host your own servers (systems that provide capabilities to users). Instead, you can "rent" from a large cloud provider. This greatly reduces your costs.

For a user, this means that you can expect most applications to leverage cloud services in some way. This can include:

  • Data storage: your data is stored in the cloud, and is accessible from any device.
  • Multi-device support: your data is synchronized across all of your devices.
  • Data sharing: you can directly share your data with other users of a service.

# 2010s: Mobile-First

Although we had mobile devices in the early 2000s, it was the launch of the iPhone in 2007 that revolutionzed the industry. Smartphones represent the largest shift we had ever seen in consumer usage of technology; today, there are more smartphone users than desktop users, and the majority of Internet traffic comes from mobile devices.

This has led to a shift towards mobile-first design, where applications are designed for mobile devices first, and then adapted for desktop. This is a significant change from the past, where applications were typically designed for desktop first, and then adapted for mobile.

# Modern Applications

This leaves us with the current situation, where we feel pressure to support BOTH mobile and desktop targets. Deciding on which platform to support is a major decision for a developer, since it will determine the user experience, the capabilities of the application, and the number of users that you can potentially reach.

# Platform Choice

Here's the platforms to consider:

  1. Desktop software: Software that runs on a desktop operating system, like Windows, macOS or Linux. This software is often graphical, and provides a richer user experience. e.g., MS Word, Photoshop, League of Legends.
  2. Phone software: Software that runs on a mobile operating system, like Android or iOS; it is often designed specifically for a small screen, and is usually touch-enabled. This is the largest category of user-facing software e.g., Weather, Instagram, WhatsApp.
  3. Tablet software: Software that runs on a tablet operating system (or a mobile operating system). This overlaps with phone software, but is often designed for a larger screen. e.g., Kindle, Netflix, Spotify.
  4. Web applications: Software specifically designed to run in a web browser. This includes traditional web applications, as well as progressive web applications (PWAs) and single-page applications (SPAs). e.g., Gmail, Facebook, Twitter.

Each platform brings its own strengths and weaknesses, and is suited to different types of applications.

Style Platform Strengths Weaknesses
Console Windows, macOS, Linux Lightweight, information-dense display Limited user experience (graphics)
Desktop Windows, macOS, Linux Rich user experience, access to full hardware capabilities Not as widely used
Phone iPhone, Android Touch-enabled, always-on, location-aware Limited screen size, limited hardware capabilities
Tablet iPad, Kindle Touch-enabled, always-on, larger screen size Limited hardware capabilities
Web Any browser Cross-platform, easy to distribute, easy to update Limited user experience, Restricted capabilities

Many modern applications target multiple platforms, to reach the largest number of users.

# Language Trends

What programming language features are desireable? It depends greatly on the style of software you're producing.

Systems programming is often concerned with performance and resource usage. We want to write code that runs as fast as possible, and uses as little memory as possible. Examples of systems languages include C, C++, and Rust. Systems programming is often used for operating systems, device drivers, and game engines.

On the other hand, applications programming is often focused on delivering features to users. Performance is often traded off for reliability, expressiveness and ease of use of the language. Examples of application languages include Swift, Kotlin, and Dart. Applications programming is often used for web applications, mobile applications, and desktop applications.

These languages are optimized for different things, and have different features:

Language Features Systems Application
Memory management manual garbage collection
Type system static static or dynamic
Abstractions low high
Reliability high medium/high
Runtime performance high medium/low
Executables small, fast large, slow
Portability low high

Modern application languages have similar features:

Memory management. Manual memory management is more common in systems programming, where you need to control memory usage and performance. Garbage collection is more common in applications programming, where you want to reduce development time and bugs. Modern application languages tend to be garbage collected, since the (very) small performance tradeoff is worth it for most applications. The majority of the time, the performance difference is negligible1.

Type systems. Modern application languages are statically typed. The type system can catch bugs at compile time, and make the code easier to understand. Swift, Kotlin and Dart *also *have null safety built in, which can prevent null pointer exceptions. Dynamic typing is more common in scripting languages like Python and JavaScript, which can make development faster, but can also lead to more bugs; dynamic typing is a poor tradeoff for large applications.

Abstractions. Modern application languages have a lot of abstractions, which can make development faster and easier. e.g. classes, collections, higher-order functions. Often you have access to an entire ecosystem of community-built libraries, which can save you a lot of time.

Cloud/Network support. Given that modern applications are expected to be networked, your programming language needs access to libraries that can handle network requests, and that can parse and generate JSON. Modern application languages have excellent support for this.

Concurrrency. Working with resources, especially slow networked resources (like databases or cloud services) can be slow. Modern application languages have excellent support for concurrency, which can make your application be more responsive. Easy-to-use concurrency support is a core language requirement.

VS Code may not be the fastest editor, but it has a lot of features
VS Code may not be the fastest editor, but it has a lot of features

# Language Choice

In an ideal world, we would be able to build our application once, in our favorite programming language, and have it run on every platform i.e. mobile + desktop + web. Unfortunately, this is not really feasible as a developer. Why not?

There are no technical hurdles to this, but there are market barriers. The major platforms are controlled by different vendors, and they are not interested in making it easy for you to target their competitors' platforms. For example, Microsoft wants consumers to run Windows, so they produce development tools that make it easy for you to build Windows applications. They have no interest in helping you build applications for macOS or Linux. Apple wants consumers to run macOS and iOS, so they produce development tools that make it easy for you to build applications for those platforms. They have no interest in helping you build applications for Windows or Android.

The inevitable result of this is that each platform has it's own specific application programming languages, libraries, and tools1. For example, here's a typical technology stack for each platform. Notice that there is very little overlap.

Platform OS Main Languages/Libraries
Desktop Windows C#, .NET, UWP
macOS Swift, Objective-C, Cocoa
Linux C, C++, GTK
Phone Android Java, Kotlin, Android SDK
iOS Swift, Objective-C, Cocoa
Tablet Kindle Java, Kotlin, Android SDK
iPad Swift, Objective-C, Cocoa
Web n/a HTML, CSS, JavaScript, TS
Frontend: React, Angular, Vue
Backend: Node.js, Django, Flask

# Strategies

How do you target all of these platforms? There are three main approaches:

  1. Build a native application for each platform. i.e. use Microsoft's toolchain to build a Windows application, then use Apple's toolchain to build the macOS version (2x the work) and then repeat again for building an Android application (3x the work), and so on. This is what many companies do, since native toolkits tend to provide the most features and highest performance for that platform. However, it is also the most work, since you need to build and maintain separate codebases for each platform.

    There's potentially a lot of operating systems to support.

  1. Use a cross-platform framework. Find a way to leverage code and libraries across more than one platform. This can be done in a number of ways, including using a cross-platform framework like React Native, Xamarin, Flutter, or Compose Multiplatform. This approach can save time and effort, but it can result in a less polished user experience, since you are not using the vendor-preferred tools for each platform.

  2. Give up and just develop for the web. Part of the reason for the success of the web is that you can, theoretically, build an application that runs in a web browser on each platform. This is the easiest approach, since you only need to build and maintain one codebase, but it can also result in a less polished user experience. You also tend to have restricted access to the capabilities of the device e.g. the camera or the GPS.

# Our Approach

What does all of this mean for you as a developer? It means that you have a lot of challenges ahead of you! Twenty years ago, you could build a standalone Windows application and be confident that most users would be able to run it. Today, you need to build an application that is mobile-first, available on every platform, networked and cloud-enabled (and reliable, and secure).

In this course, we're going to build native Android and desktop applications that are network-connected and leverage cloud services. Specifically, we're going to learn Kotlin, and a number of supporting technologies.

Why Kotlin?

  • It's a modern language, with a lot of features that make development easier and more reliable.
  • It lets you build desktop and mobile applications (Android currently, iOS in the future).
  • It's much better at building services and backend systems than Dart.
  • The development tools can be used on Windows, macOS or Linux. iOS development, by comparison, requires a Mac; you can't build iOS applications on Windows or Linux. This is a major barrier to entry in a course like this.

# What's Next?

For your project, you're going to design either a mobile application or a desktop application in Kotlin2. We'll use an online database and explore using other cloud services as well.

We'll also use modern programming approaches to build a layered architecture that is flexible, scalable and relatively easy to maintain. We'll continue by discussing software process (how to manage a project, how to build software), and eventually software architecture and design (how it should be structured).


  1. Kotlin GC runs in less than 1/60th of a second, and only when necessary. Dart GC runs in less than 1/100th of a second. Users certainly don't notice this.

  2. Your choice, based on which you think is most suitable for your application. If you're not sure, I'd recommend starting with a mobile application, since it's the most widely used platform.