Editions: 2021, 2022, 2023, 2024, 2025, 2026

Software Atelier 4: Software Engineering Project
- Bachelor in Informatics (Core course)
Description. Programming skills are essential but not enough to develop large and complex software systems that require the coordination of a team of specialists. Software engineering is about the development of such moderns software systems. Students will learn to go beyond programming, to coordinate a team, to apply modern methodologies and techniques.
Course Topics
Building large software systems is hard. Most projects run into the same recurring problems: poor quality and the presence of bugs, inconsistencies between requirements, design, and implementation, ambiguous or imprecise communication, insufficient testing paired with a subjective sense of where the project actually stands, and a failure to confront risk until it is discovered too late to address cheaply.
The good news is that a set of established best practices helps teams keep these problems under control. The course is organized around them.
Specify software behavior
Specifications describe what a piece of software is supposed to do. They underpin much of software engineering: they let work be delegated cleanly across a team, they act as a contract between the provider of a functionality and the people who use it, and they make functionality easier to test. Use cases and scenarios capture behavior in an unambiguous way, models record design decisions, and abstraction lets details be hidden until they are needed.
////// Finds an Integer value in a list./// @param list a list of integers./// @param value an integer value./// @returns A non-empty optional with the index of value in the list,/// or an empty optional if not present./// @throws IllegalArgumentException if list or value are null.///public static Optional<Integer> find(List<Integer> list, Integer value)Develop software iteratively
The classic waterfall lifecycle, moving once through requirements, analysis, design, testing, and deployment, pushes risk forward in time, where undoing early mistakes becomes expensive. An initial design is almost always flawed with respect to its key requirements, and discovering those flaws late leads to cost overruns or outright cancellation. As Tom Gilb put it, “if you do not actively attack the risks in your project, they will actively attack you.” Working iteratively surfaces misunderstandings early, invites the user feedback needed to elicit real requirements, keeps the team focused on the critical issues, and uses continuous testing to give an objective read on project status. Inconsistencies are caught sooner, workload is spread more evenly, lessons learned feed back into the next iteration, and stakeholders get concrete evidence of progress. This is the mindset behind agile software development.
Manage requirements
A requirement is a condition or capability that a system must have. Requirements are dynamic and keep changing: it is impossible to state all of them completely before a project begins, and their understanding evolves as they change. Managing them actively means eliciting, organizing, and documenting the required functionality and constraints, evaluating proposed changes and their impact, and recording the trade-offs and decisions made along the way. Done well, communication rests on defined requirements, requirements can be prioritized, filtered, and traced, functionality and performance become measurable, and, with tool support, everything lives in a repository with links back to the relevant documents.
Design and model software
A model is a simplification of reality that describes a system from a particular perspective. Modeling helps a team visualize, specify, construct, and document both the structure and the behavior of a system. A standard modeling language such as UML gives the team a shared vocabulary, with different diagram types (class, state, component, deployment, use-case, and scenario) offering complementary views. Visual modeling ultimately helps manage software complexity and improves communication.
Continuously validate software
Problems are far more expensive to find and fix after deployment, so validation should be continuous rather than a final phase. Testing throughout development makes project status assessment objective, because it evaluates results rather than documents, exposes inconsistencies between requirements, design, and implementation, and catches defects early when they are cheap to repair. Automated testing tools improve functionality, reliability, and performance at every level of abstraction, from individual methods to components to the fully integrated system, and safety-critical systems can add formal verification for mathematical guarantees of correctness. Still, as Dijkstra warned, “program testing can be a very effective way to show the presence of bugs, but is hopelessly inadequate for showing their absence.”
Manage software quality
Quality can be measured. Using metrics, quality management helps identify code fragments that are likely to be problematic or a source of future bugs, quantify the amount of technical debt a system carries, and surface design disharmonies before they spread.
Use adequate architectures
A software system has to be viewed from many perspectives at once, including those of end users, designers, developers, testers, and managers. Its architecture is perhaps the most important deliverable for reconciling those viewpoints and controlling how the system evolves. Architecture covers the structural organization of a system, the elements and interfaces that make it up, and their behavior. A central theme is reuse: rather than reinventing the wheel, teams lean on well-known architectures, and there are many ways to break a system into components that make it more resilient and reusable. Real-world designs, such as the microservice architecture behind systems like Netflix, illustrate the idea.
Student Evaluations
The reported student evaluations for each course are always instructor-specific, so these are always related to me, even if there are other instructors.