Software Process Engineering is not a course about a programming language, nor about a single design notation. It is a course about the process by which a piece of software comes into existence: how a problem stated in the language of its users becomes a model, how that model becomes an architecture, and how the architecture becomes an artefact that a machine can build, test, package and ship without a human dragging files around. The five goals declared at the opening lecture read as a compact manifesto:
| Goal | What it means in practice |
|---|---|
| Learn how to design software systems, following a domain-, model-, and/or test-driven approach | The three drivers of the course: DDD (Chapters 2-4), MDD (Chapter 5), and testing as the gate of every automated step |
| Zero-overhead from domain definition to executable code | The distance between "what the domain expert said" and "what the machine runs" should be paid for once, not at every release |
| Agile development practices, DevOps philosophy | Short feedback loops; development and operations as one continuum rather than two departments |
| High automation + technical excellence | Automation is not a bonus: it is the mechanism by which quality becomes repeatable |
| Understand analogies and differences among programming platforms | Why the exam project must target two or more platforms (see §4) |
The course is taught by two lecturers, Danilo Pianini and Giovanni Ciatto, at the Cesena campus of the University of Bologna. Lectures are held in a lab with immediate hands-on: the material is designed to be typed, not only read. The slides are published with a rolling release model, they are meant to contain everything needed, and the code examples produced during a lecture are made available right afterwards, with most of the code already on GitHub. There are no mandatory books, but both recommended readings and additional useful books are listed on the course webpage.
The unifying thread of the whole course is the reduction of overhead between a domain and its executable form. Domain-Driven Design removes the semantic overhead (the model speaks the language of the domain); Model-Driven Development removes the transcription overhead (code is generated from models); MLOps and LLMOps remove the operational overhead (experiments, models and prompts are tracked and reproduced by pipelines rather than by memory).
The DDD lecture opens with a question that is really the question of the whole course. You already know how to program, in several languages. You know object-oriented programming and design patterns. You know software architectures and design principles. You know software engineering best practices. So:
What is the criterion to choose if and when to adopt languages, patterns, architectures, principles, practices?
The recommended workflow is a chain of three named transformations:
Problem --analysis--> Model --design--> Architecture --implementation--> Solution
The two red arrows in the original slide are analysis and design: they are the steps where the criterion is needed, and they are the steps that a generic engineering culture leaves underspecified. Implementation, by contrast, is the step the whole course tries to automate away. The lecture then asks the follow-up that motivates Domain-Driven Design: yet, how to derive the model?
Nothing in the material claims that the pipeline is traversed once. On the contrary, both the DDD lecture (models must keep adhering to the domain "at any moment") and the MLOps lecture (workflows are cyclical, not linear) insist on the return arrow. Read the chain as a cycle whose iterations get cheaper as automation increases.
The declared prerequisites are modest in quantity and precise in kind:
The third item is spelled out in a sentence that deserves to be quoted verbatim, because it is the closest thing the course has to a motto:
Never stop when it works, stop when you know why it does. — and the slide immediately adds: this is especially true in the LLM era.
The remark is not decorative. A generative model will happily hand you a build script, a Gradle configuration or a validation rule that runs; the entire discipline of this course consists in being able to say why it runs, which invariant it preserves, and what will break when the domain changes. Chapters 5 and 6 return to the point from two different angles: a DSL is exactly a device for making the "why" explicit and machine-checkable, and LLMOps is exactly the practice of not trusting a prompt that happened to work once.
The exam is a discussion of a group project. There is no written test to prepare and no list of exercises to drill: the object of the assessment is a piece of software your group built, and the conversation about how it was built. The project must feature, non-negotiably:
| Requirement | Detail | Where it is taught |
|---|---|---|
| Domain-driven design | The model must be derived from a domain and named after its ubiquitous language | Chapters 2-4 |
| Clear development process and DevOps practices | The process must be visible in the repository, not only in the report | Chapter 1, Chapter 6 |
| Full-scale automation | Including continuous integration and delivery | Chapter 6 (the same discipline, applied to models and prompts) |
| Deploy automation | Via containerization and/or orchestration | Chapter 6 (mlflow models build-docker is a worked example of the idea) |
| Two or more target platforms | e.g. JVM, NodeJS, Python, C, C++, Rust, Go | See the rule below |
The slide gives a rule with a hard part and a soft part:
Be able to state the five mandatory features of the project and, for the multi-platform requirement, the precise criterion: different runtime ⇒ different target; different build system ⇒ likely different, with Scala/sbt + Java/Gradle as the named counterexample. This is the one place in the course where a rule is given with an explicit exception, which makes it excellent oral-exam material.
The exam project can be developed as a project work: a project whose requirements are provided by a real-world company acting as a commissioner. The arrangement has three declared properties:
The slides describe it as an opportunity to learn by doing in a context closer to the industry. Available project works are posted on the course site on virtuale.unibo.it.
Chapter 7 of this site works through a brief of exactly this shape: ChatFlow, a middleware commissioned in the style of a real customer, complete with security constraints and expected deliverables. Reading it after Chapters 2-5 is the intended order: the brief is written in the language of the client, and turning it into contexts, blocks and a build pipeline is the exercise.
The environment is part of the syllabus, not an accident of it: a course about automation cannot tolerate a "works on my machine" setup. The lecture splits the software into what is required and what is recommended, and then offers a way to skip the whole discussion.
Note what the required list implies: the toolchain assumes you can pin a JDK version and run a container. Both are prerequisites for reproducible builds and for the deploy-automation requirement of the exam.
zsh shell is recommendedFeeling lazy? A container with all the course software is provided:
docker pull danysk/linux-didattica
It is published at hub.docker.com/repository/docker/danysk/linux-didattica, with instructions at github.com/DanySK/docker-linux-didattica.
Feeling Windows-y? The container can be converted into a WSL2 Linux distribution; instructions live in the same repository.
The lab PCs are equipped with the WSL2 image:
zsh shell.Lectures are held in lab with immediate hands-on, on a two-slot weekly timetable:
| Day | Time | Room |
|---|---|---|
| Thursday | 11:00–14:00 (3h) | Room 2.5 |
| Friday | 11:00–14:00 (3h) | Lab 4.2 |
Changes are published on the forum. The two course pages are the Virtual Learning Environment ("Virtuale" — enrol if you have not already) and the slides themselves.
virtuale.unibo.it/mod/forum/view.php?id=1342533) for all technical questions and any other non-personal question.(1) Learn how to design software systems following a domain-, model-, and/or test-driven approach; (2) achieve zero-overhead from domain definition to executable code; (3) practise agile development practices and the DevOps philosophy; (4) combine high automation with technical excellence; (5) understand analogies and differences among programming platforms.
Problem → Model → Architecture → Solution, where the transformations are analysis (problem to model), design (model to architecture) and implementation (architecture to solution). The open question the lecture raises immediately afterwards is how to derive the model — which is what Domain-Driven Design answers.
Two targets are different if they run on a different runtime (for example native + JVM). They are likely different if they use different build systems, but this is weaker and admits exceptions: Scala/sbt + Java/Gradle are not considered different targets, since both run on the JVM.
Domain-driven design; a clear development process and DevOps practices; full-scale automation including continuous integration and delivery; deploy automation via containerization and/or orchestration; and two or more target platforms.
Yes. It can be a joint effort with other courses (SPE cares about the domain modelling and the application of DevOps techniques, so a project from another course with those aspects added is fine), it can be created for SPE alone, or it can cover SPE plus the thesis.
A project whose requirements are provided by a real-world company acting as commissioner. Students interact with the company to apply DDD on a real piece of software, and the project is open source. Crucially, all the features required for a normal exam project still hold.
An internet connection, a working JDK (Jabba is suggested for managing versions) and Docker. They are the minimum needed to make a build reproducible on a machine that is not yours: a pinned runtime plus a way to ship an environment. Kotlin, Gradle, IntelliJ, VS Code, a good Unix terminal and ki-shell are recommended rather than required.
Use the prepared container danysk/linux-didattica (instructions at github.com/DanySK/docker-linux-didattica). On Windows the same container can be converted into a WSL2 distribution — which is exactly the image installed on the lab PCs.
The slide reads: never stop when it works, stop when you know why it does — this is especially true in the LLM era. Generated code and generated configuration can pass a run without anybody understanding the invariant they rely on. The course answers with artefacts that make the "why" explicit and checkable: a ubiquitous language, a validated DSL grammar, tracked experiments and automated evaluations.
Prioritise the forum for all technical and non-personal questions. When email is unavoidable, include both teachers, always. Office hours are published on each teacher's webpage.