Getting Started with Clean Code in Python
Learn who this course is for and what it will cover.
We'll cover the following
In this course, it is assumed that the reader is already familiar with the principles of object-oriented software design and has experience writing code.
The course is organized in such a way that the content is in an increasing order of complexity. The first sections cover the basics of Python, which is a good way to learn the main idioms, functions, and utilities available in the language. The idea is not just to solve some problems with Python, but to do so in an idiomatic way.
The course takes a pragmatic approach. Examples are limited to what the case study requires, but are also intended to resemble the context of a real software project. It is not an academic course, and as such the definitions made, the remarks made, and the recommendations should be taken with caution. The reader is expected to examine these recommendations critically and pragmatically rather than dogmatically. After all, practicality beats purity.
Intended audience
This course is suitable for all software engineering practitioners who are interested in software design or learning more about Python.
It will also appeal to team leads, software architects, and senior software engineers who want to learn good Python coding techniques to create projects from scratch or work on their legacy systems to save costs and improve efficiency.
Experienced programmers will also benefit from the topics in this course, as some sections cover advanced topics in Python, such as decorators, descriptors, and an introduction to asynchronous programming. It will help the reader discover more about Python because some of the cases are analyzed from the internals of the language itself.
Scientists using Python for data processing can also benefit from the content in this course, and to that end, several parts of the course are dedicated to setting up projects from the ground up in terms of the tools, configuration of environments, and good practices needed to release software.
Course contents and objectives
Chapter 2, Introduction to Clean Code, Code Formatting, and Tools, is an introduction to the main tools the reader needs to set up a development environment in Python. We cover the recommended basics a Python developer should know to start working with the language effectively. It also includes some guidelines for maintaining readable code in the project, such as tools for static analysis, documentation, type checking, and code formatting. Having a common understanding of coding standards is a good thing, but relying only on good intentions doesn't scale. That's why the chapter concludes by discussing tools to work more effectively.
Chapter 3, Pythonic Code, looks at the first idioms in Python, which we'll continue to use in the following chapters. We cover the particular features of Python, how they are meant to be used, and start building knowledge around the idea that Pythonic code is in general of much better quality.
Chapter 4, General Traits of Good Code, reviews the general principles of software engineering with a focus on writing more maintainable code. With the knowledge gained from the previous chapter, we take a look at general clean design ideas and how they can be implemented in Python.
Chapter 5, The SOLID Principles, covers a set of design principles for object-oriented software design. This acronym is part of the language or jargon of software engineering, and we'll see how each of them can be applied to Python. In particular, the reader will learn how dependency injection makes the code more maintainable, a concept that will be very useful in the next chapters.
Chapter 6, Using Decorators to Improve Our Code, looks at one of the greatest features of Python. After learning how to create decorators (for functions and classes), we put them in action for reusing code, separating responsibilities, and creating more granular functions. Another interesting learning point in this chapter is how to use decorators to our advantage to simplify complex and repetitive function signatures.
Chapter 7, Getting More Out of Our Objects with Descriptors, explores descriptors in Python, which take object-oriented design to a new level. While this is a feature more related to frameworks and tools, we can see how to improve the readability of our code with descriptors and also reuse code. The content revisited in this chapter will help the reader achieve a higher level of understanding of Python.
Chapter 8, Generators, Iterators, and Asynchronous Programming, starts by showing how generators are a fantastic feature of Python. The fact that iteration is a core component of Python might make us think that it leads to a new programming model. By using generators and iterators in general, we can think differently about the way we write our programs. With the lessons learned from generators, we'll go further and learn about coroutines in Python and the basics of asynchronous programming. This chapter wraps up by explaining the new syntax (and new magic methods!) for asynchronous programming and asynchronous iteration.
Chapter 9, Unit Testing and Refactoring, discusses the importance of unit tests in any codebase that claims to be maintainable. We discuss refactoring as a prerequisite to evolve and maintain a code base, and how unit tests are critical for this. We learn all of this with the support of the proper tools (mainly the unittest
and pytest
modules). Finally, we learn how the secret for good testing lies not so much in the tests themselves, but in having testable code.
Chapter 10, Common Design Patterns, reviews how to implement the most common design patterns in Python, not from the point of view of solving a problem, but by examining how they solve problems by leveraging a better and more maintainable solution. The chapter mentions the peculiarities of Python that have made some of the design patterns invisible and takes a pragmatic approach to implement some of them. We discuss other (not so "conventional") patterns that are Python-specific.
Chapter 11, Clean Architecture, focuses on the idea that clean code is the base of good architecture. All those details we mentioned in the first chapter, and everything else revisited along the way, will play a critical role in the entire design when the system is deployed.