Classic Season 1
Lesson 1
We'll use the shell and the git command line tools to iterate over revisions, computing a statistic for each revision. Initially, it'll be a one-liner at the prompt. Then we'll promote it to a full script, refactor it, and add some more features.
More
Lesson 2
We'll look at nil from many angles. Why do nils show up in your programs? What kinds of problems can they cause when they get out of control? How can we design our systems to fail loudly when unexpected nils exist and, more importantly, to avoid the introduction of nils entirely? This screencast uses Ruby, but the techniques apply in any language.
Lesson 3
RSpec has lured many programmers into the Ruby world with its beautiful syntax. For some, its working remain a mystery. Let's dispel that. We'll build some of RSpec's basic syntax from scratch, test driving it using Test::Unit. This is done in Ruby, of course. Basic Ruby knowledge will definitely help.
Lesson 4
Source code history is a touchy topic. Should we ever edit history? Is it safe? We'll look at what can go wrong when editing history, and how to avoid the potential problems. We'll also briefly talk about the Mercurial and Git communities. Warning: there's some editorializing!
Lesson 5
In modern web frameworks, it's easy to extend model and controller objects over and over again, leaving you with huge, unwieldy objects. To avoid this, you can extract small pieces into their own classes. This has many benefits, such as: much faster test execution, naming concepts in the system that were previously implicit, and adding explicit abstraction layers. We'll look at an example from Destroy All Software itself, a Rails app, and pull a piece of model logic embedded in a controller out into its own class with isolated tests.
Lesson 6
There are a whole lot of object oriented design principles. It's tempting to view them as absolute rules, but we also need to understand the trade-offs between them. We'll look at a case where The Single Responsibility Principle and Tell Don't Ask conflict, then touch on the grander implications.
Lesson 7
When building a system, it's easy to continually append tests to your suite without considering the relationship between them. By building your test suite more deliberately, you can write clearer, terser tests, and also put better design pressure on your system. We'll build a small piece of code both ways: first by simply appending tests, then by extending existing tests and thinking about the implications.
Lesson 8
Processes and jobs—processes running in your shell—are the core of a Unix development workflow. For the first half of this screencast, we'll look at the shell's job control mechanisms, how GNU Screen works, and how I use them together for my development workflow. Then we'll look at an advanced use of process management that enables powerful composition of Unix tools beyond simple piping.
Lesson 9
The mantra "don't use exceptions for control flow" is repeated often, but its real implications tend to be glossed over. Using an example, I'll show you exactly what I think about it, and why I'm OK with using exceptions in certain cases that some people would dismiss as control flow.
Lesson 10
Rails' startup can make running tests, and especially doing TDD, painful. You can escape this for most tests by moving code into the lib directory and testing it outside of Rails. We'll look at the performance of tests with and without Rails, as well as how I configure my environment to automatically skip loading it when possible. The script mentioned at the end of this screencast is available for download.
Lesson 11
Many people have asked about my git workflow, so here it is. Almost every command I run is an alias of some kind, but I explain them all. We'll go through a cycle of hacking, retroactively splitting commits, running tests over them, fetching from origin, rebasing over it, running tests over the new commits, and finally pushing. You can download my .gitconfig and the run-command-on-git-revisions script to use them yourself. Also see the "Source Code History Integrity" screencast for more on that topic.
Lesson 12
There's been an explosion in packaging tools in the last few years. Creation and installation aren't the hard parts any more: now we're managing multiple runtime versions, isolating package sets for different applications, and specifying dependencies in a repeatable way. This screencast looks at the landscapes in Ruby and Python, comparing their solutions to these problems. A companion table of packaging-related commands in Ruby and Python is available to review the tools used in this screencast.
Lesson 13
Vim's file navigation features are weak, so customization can speed you up a lot. We'll cover finding and opening files, including Rails-specific hacks that help you avoid the problem of finding one file among many with similar names. Then we'll look at the customizations I use to make splitting and window management work well with an outside-in TDD workflow. To try these customizations yourself, see the reference that accompanies this screencast.
Lesson 14
This is a sequel to the original Extracting Domain Objects screencast. Once again, we'll look at Destroy All Software's catalog logic, pulling it out of the Django View (equivalent to a Rails controller), and moving it into its own domain-relevant class. Then we'll isolate and simplify the tests for both the view and the new Catalog class. Finally, we'll use the newly isolated tests to extend the behavior of the Catalog without changing or breaking the view and its tests.
Lesson 15
Writing traditional arrange-act-assert tests for performance is difficult: what do you assert on? In this screencast, we'll look at a simple method for doing ongoing performance analysis: running small benchmarks across the commits in version control. With a few lines of shell scripts and RSpec, we can get a visual sense of our system's performance over time, allowing us to catch performance problems before they make it to production. The run-command-on-git-revisions script used here is available on GitHub.
Lesson 16
While thinking about this week's screencast, I happened to do a pretty big refactoring on one of Destroy All Software's controllers. I translated a confusing mess of exception rescuing into a more sensible action, pushing validation and special cases down into lower-level classes. We'll look at the before picture, the changes I made, and then the after picture. There are naming changes, structural changes, and some important Rails behavior that was a little surprising. This is a departure from the normal Destroy All Software style, so please let us know what you think!
Lesson 17
Third party APIs can be a source of bad design in your applications. When you mix your application's logic with calls into an API, you're obscuring both responsibilities. In this screencast, we'll look at a class where I've done just that. Then we'll extract the API access out into a wrapper, simplifying the original class and adding clarity to both the production code and the tests.
Lesson 18
Several Destroy All Software screencasts have touched on isolated testing, but never addressed it directly for its own sake. That's the topic of this screencast: why do we care about isolating the class under test from other classes? We'll look at an actual example I ran into: I started TDDing a class, letting it integrate with some other simple classes. After realizing that the test was becoming a mess, I deleted it, rewrote it in an isolated way, and it was far more readable. We'll retrace those steps to see the dramatic difference isolated testing made.
Watch Online Classic Season 1
# | Title | Duration |
---|---|---|
1 | Статистика по репозиториям Git | 14:27 |
2 | Как и зачем избегать нуля | 13:59 |
3 | Строим RSpec с Нуля | 14:48 |
4 | Source Code History Integrity | 14:39 |
5 | Extracting Domain Objects | 18:31 |
6 | Conflicting Principles | 12:18 |
7 | Growing a Test Suite | 13:38 |
8 | Processes and Jobs | 15:12 |
9 | Exceptions and Control Flow | 11:00 |
10 | Fast Tests With and Without Rails | 15:50 |
11 | Git Workflow | 11:50 |
12 | Packaging in Ruby and Python | 15:44 |
13 | File Navigation in Vim | 10:23 |
14 | Extracting Objects in Django | 15:08 |
15 | Quick and Easy Perf Tests | 13:15 |
16 | A Refactoring Story | 12:36 |
17 | Wrapping Third Party APIs | 17:21 |
18 | Clarity via Isolated Tests | 10:09 |