Defining a feasible software design is important to prevent bugs, rework, and maintenance problems. While important, it is also highly challenging to define a proper software design. Many design processes, paradigms, and patterns exist, each having different pros and cons. In this course, we will provide an overview of software-development processes, version-control, requirements engineering, design principles, graphical user interfaces, and design patterns focusing on object-oriented software development with Java. Involving lectures, exercises, and graded individual as well as group work assignments, the course aims at providing the theoretical foundations needed to properly design software, and at enabling students to explore these on smaller example projects.