Kinnu

Software

About programming languages

Programming languages are the systems of code we use to tell computers what to do. As we know, computers actually only understand one language, which is 1s and 0s. In this context we refer to that as ‘machine language’. But as humans designing applications for our computers, it would be extremely difficult and time-consuming to write out all of our data and instructions in machine language. Programming languages act as a middle-man between human actions and computable data.

Some code written in the C language. This is a set of instructions that will get the computer to print the words 'Hello World' in the terminal.

These languages fall into two main groups: easy-to-understand (high-level) and more complex (low-level) options.

High-level languages are used for building applications.  Scripting languages, a subgroup of high-level languages, are for automating tasks.

Low-level languages, like assembly code, offer a different approach. Unlike user-friendly high-level languages, low-level languages are intricately linked to the computer's hardware. This tight connection allows for fine-grained control and highly efficient code.

A part of a program written in assembly code. By Swtpc6800 en:User:Swtpc6800 Michael Holley - Own work, Public Domain, https://commons.wikimedia.org/w/index.php?curid=15345825

In assembly, you write instructions that are pretty close to machine language. This gives you precise control over data manipulation and calculations. This power comes at a cost – assembly is complex and time-consuming to write, making it impractical for building large applications today. However, there are still a handful of specialised cases where developers work in it.

Unlike assembly code, high-level coding languages have many features that make them much easier to write, and more similar to natural language. Prominent examples of these include C++, Python, Java, Javascript and many others. Most modern software developers will spend the majority of their time working in these languages, because they allow programs and applications to be written much more quickly and easily.

One feature of high-level languages that sets them apart is their use of abstraction. Abstraction allows programmers to work with more complex concepts and structures without having to worry about the low-level details of how these are implemented in the computer's hardware.

For example, in lower-level languages like assembly or C, memory management is a large part of the programming process. In languages like Python or Java, this is largely handled automatically, and the programmer can focus more on the logic of the program.

All languages, whether high- or low-level, ultimately need to be translated into machine language.

This is done through one of two processes – compiling or interpreting. Compiled languages, such as C and C++, require the source code to be translated into machine code by a compiler before it can be executed. The result is then executed directly by the CPU.

Compiled languages typically offer better performance because the code is optimized during the compilation process. However, the need to compile the code before execution can make the development process slower and less flexible.

A diagram showing how compiled languages are transformed into machine language. Image: Seda Kh., CC BY-SA 4.0 <https://creativecommons.org/licenses/by-sa/4.0>, via Wikimedia Commons

Interpreted languages, such as Python, take a different approach. Instead of being translated into machine code all at once, the source code is executed line by line by an interpreter. This allows for greater flexibility and faster development cycles, as changes to the code can be tested immediately without the need for recompilation.

However, interpreted languages often suffer from slower execution speeds compared to compiled languages, as the interpreter must process each line of code in real-time.

Different programming languages are suited to different types of applications. For example, C and C++ are often used for system-level programming, such as operating systems and embedded systems. Python, with its simple syntax and many extensions, is popular for web development, data analysis, and machine learning. Java, balancing performance and flexibility, is widely used for enterprise applications and mobile development.

Beyond the usual suspects, there are even stranger languages like Brainfuck or Whitespace, designed to explore coding concepts in unconventional ways. These are called esoteric languages. The world of programming offers endless possibilities!

Introduction to operating systems and the boot process

Operating systems are the software that runs on the device, allowing us to run applications and manage files in a much more user-friendly way.

In the early days of computing, programmers wrote programs on punch cards, which were specially designed paper cards with holes punched into them to represent data and instructions. These punch cards were then fed into room-sized computers by operators.

As computers become exponentially faster, the manual process of inserting programs using punch cards became longer than the actual program execution, leading to the creation of operating systems to streamline the process and enable computers to manage and operate themselves without constant human intervention.

Diagram of the different layers of software types. Image: Golftheman, CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0>, via Wikimedia Commons

When you press the power button on your computer, a sequence of events begins known as the boot process. This process initializes the system and loads the operating system, which in turn manages all other software and hardware resources.

The boot process starts with the Basic Input/Output System (BIOS) or its modern counterpart, the Unified Extensible Firmware Interface (UEFI). These firmware interfaces initialize and test the system's hardware components, ensuring everything is in working order. They also locate the bootloader, a small program responsible for loading the operating system into memory, marking the transition from hardware initialization to software management.

An operating system (OS) orchestrates all activities within the system, with primary components including the kernel, file system, user interface, device drivers, and process management. The kernel serves as the core component, directly interacting with hardware to manage resources like CPU, memory, and I/O devices. It schedules tasks, ensuring multiple processes can run concurrently without interference, thus optimizing system performance and stability.

Virtual memory is a technique that uses a portion of the hard drive as temporary memory, allowing the OS to compensate for shortages in physical RAM. The user interface is the visual and interactive aspect of the OS, enabling users to interact with the system easily. Device drivers are software components that facilitate communication between the OS and hardware devices, translating generic instructions into device-specific commands.

Process management oversees the allocation of resources to running programs and ensures they run smoothly without interfering with each other. When a hardware device needs attention, it sends an interrupt signal to the CPU, prompting the kernel to pause the current process and handle the interrupt. This process allows the OS to respond promptly to external events, such as user input or data transfer requests.

Multitasking is a key capability of modern OSs, enabling multiple programs to run simultaneously. Even without multiple cores, smart OS developers figured out how to give the illusion of parallel execution. By letting processes take turns on the CPU and cycling through them rapidly, running a couple of instructions from each one, all processes can be responsive without any single process hogging the CPU. Don't confuse parallel execution, which you learned in the previous tile, with multitasking.

Memory management is another vital function of the operating system. It keeps track of each byte in the computer's memory and allocates space to processes as needed, including both RAM and virtual memory on the hard drive. The OS ensures each process has its own memory space, preventing one application from overwriting another's data.

File system management is another crucial aspect of operating systems. The file system organizes and stores data on storage devices in a structured and efficient manner, ensuring data integrity and security by implementing permissions and access controls. In addition to these core functions, modern operating systems offer a range of additional features, such as user interfaces, security mechanisms, and networking capabilities.

Application software and software development

Application software is the type of software that allows users to perform specific tasks on a computer. This can range from word processing and spreadsheet management to graphic design and video editing. Unlike system software, which includes the operating system and utility programs that manage computer resources, application software is designed to help users accomplish particular tasks. Examples of application software include Microsoft Office, Adobe Photoshop, and web browsers like Google Chrome.

The development of application software is a complex process that involves several stages, each critical to the creation of a functional and user-friendly product. Many models for the software development lifecycle exist. Probably the most famous ones are the V-Model, the Waterfall-Model and agile models like SCRUM or Kanban. Agile methods are different in that they represent the software development cycle as short term, iterative cycles, called sprints, instead of using a sequential, linear approach.

The V-Model. Image: Herman Bruyninckx, CC BY-SA 3.0 <http://creativecommons.org/licenses/by-sa/3.0/>, via Wikimedia Commons

Screenshot 2024-10-22 at 16.25.01.png

The first stage of SCRUM development is requirement analysis, where developers gather information about what the software needs to do. This involves talking to potential users, understanding their needs, and defining the software's functionality. This stage is crucial because it sets the foundation for the entire project. If the requirements are not well understood, the final product may not meet the users' needs.

Once the requirements are clear, the next stage is design. During this phase, developers create a blueprint for the software. This includes designing the user interface, which is how users will interact with the software, and the software architecture, which is how the software will be structured internally. The design phase is essential for ensuring that the software will be both functional and user-friendly.

After the design is complete, the next stage is implementation, where developers write the actual code. This is often the most time-consuming part of the process, as it involves translating the design into a working program. Developers use programming languages like Java, Python, or C++ to write the code. Each programming language has its strengths and weaknesses, and the choice of language often depends on the specific requirements of the project and regulatory compliance, such as in the medical sector.

Once the code is written, the next stage is testing. During this phase, developers test the software to ensure that it works as intended. This involves running the software under various conditions to see if it performs correctly and identifying any bugs or issues that need to be fixed. Testing is a critical part of the development process because it helps ensure that the software is reliable and free of errors.

Testing consists of verification and validation. Verification means “building the product right”. This is static and accomplished via code reviews to look if the specifications are met.

Validation on the other hand means “building the right product” and is a dynamic process. This can be done via black-box or white-box testing. Examples are unit-tests or tests by the final users in the final environment.

After testing is complete, the next stage is deployment, where the software is released to users. This can involve distributing the software through various channels, such as online downloads or physical media.

A user downloads an update. Image: Public domain

Once the software is in the hands of users, developers often continue to provide support and updates to fix any issues that arise and add new features. That would be the maintenance stage which is often overlooked.

Software development is not a one-time process but an ongoing cycle. Even after the software is released, developers continue to work on it, fixing bugs, adding new features, and improving performance. This is known as software maintenance, and it is an essential part of the software development lifecycle.