2. Context and Background

In this chapter, we establish a practical context and provide some background information for the study of programming languages.

2.1. Software requirements

In most cases, we develop software to provide some form of value:

  • learn a language, library, framework, platform, technique, or tool (see also the ThoughtWorks Technology Radar)

  • solve a problem

  • produce an asset

There is usually some tension among these three activities.

The basic categories of requirements are

  • functional (FR)

    • output as function of input: y = f(x)

    • or some other description of observable behavior

      • batch

      • interactive/event-based

  • nonfunctional (NFR): additional properties of f, e.g.

    • testability

      • most important nonfunctional requirement

      • allows testing whether functional requirements are met

      • good architecture often happens as a side-effect (APPP pp. 36-38), such as separating I/O from core functionality

    • performance

    • scalability

      • e.g. performance for large data sets: asymptotic order of complexity

      • (big-Oh) in terms of input size n

    • reliability

    • maintainability

    • static versus dynamic NFRs

Several common questions and issues related to requirements arise:

  • how do requirements relate to the project development lifecycle?

  • BUFD versus MVP

  • how do testing and refactoring relate to requirements?

The following figure by Kazman relates unit operations (high-level generalizations of refactorings) and software quality factors (nonfunctional requirements).

_images/KazmanQualityFactors.png

2.2. Overview of a lightweight development process

A successful development process usually comprises these minimal elements:

  • automated regression testing

    • tests represent expectations of how the software should behave

    • when expressed as code, these are

      • fun to produce (like other coding)

      • convenient to run frequently

    • fix system-under-test (SUT) (not tests themselves) until tests pass

    • retest every time

      • a feature is added

      • the code is refactored

  • refactoring

    • improve the quality of the code without changing its behavior

      • macro level: nonfunctional requirements (quality factors)

      • micro level: code smells

    • catalog of refactorings

  • continuous integration

The process tree example illustrates continuous integration using various hosted services:

The click counter example includes additional hosted continuous integration and delivery targets suitable for mobile app development.

2.3. Software design principles and patterns

The software development community has identified various principles intended to guide the design and development process, for example:

  • DRY (don’t repeat yourself)

  • SoC (separation of concerns)

  • SOLID

The community has also developed a body of design patterns that represent reusable solutions to recurring problems. Some key design patterns we will rely on in this course include

  • Iterator

  • Strategy

  • Command

  • Composite

  • Decorator

  • Visitor

  • Abstract Factory

  • Observer

We will recap these throughout the course as needed.

Note

Language-specific design patterns are called idioms.

2.4. Programming language history and paradigms

The resources in this section cover fundamental models of computation, language paradigms, and language principles.

Todo

expand into a proper section

2.5. Popularity indices and performance comparisons

There are a number of programming language popularity indices and performance comparisons. Before drawing any conclusions from these indices, it is important to understand their methodology.