Learning Languages Test-first and Project-first

Sometimes I wonder why don’t books and tutorials teach programming languages closer to the way web apps are taught and made: By making projects up front, and by incorporating tests right away.

I am going through some Pluralsight tutorials for Go and Elixir, and while there is a lot of information in them, in most of them the code is not well organized. Only one of the dozen or so Go tutorials that I have been through makes a project. Why not do that every time? That is how we make web apps, especially since after Rails most frameworks are created with generators. You can make projects with most languages, but for some reason it is not emphasized. Granted, Go is a language where you can run code outside of a project: You can just put code into “some_file.go”, and then type “go run some_file.go”, but in my opinion it is a bad practice.

Several years ago, I went through a Rails bootcamp. After I was done, another alumni and I started a small study group to go through the RSpec book by David Chelimsky et al. We only had a few meetings, and I do not remember how far in the book we got. We thought that testing was not covered enough in the bootcamp, and we thought it was odd that some languages (like Ruby) have a strong “test-first” culture but when it comes to learning the language tests are treated like an afterthought. If we tell people to write their apps tests-first (or at least simultaneously with their code), why not teach languages test-first? A lot of books wait until halfway through before talking about tests and/or projects, or leave it until the end.

Even Dave Thomas holds off on projects and testing. I thought one of the guys famous for being part of the agile/extreme/TDD movement would start out with tests right away. The pickaxe book and his Elixir book do not get to them until halfway through; it is chapter 13 out of 25 in the Elixir book. Chapter 13 starts with: “Let’s stop hacking and get serious.” Why not start out serious?

It also might help in learning a language. If you are going through a tutorial, I think it is better to have the different sections as files in a project as opposed to just one-off files or snippets floating in space.

It might seem like it is too much for beginners. But what is another chapter in a 200+ page book? And people should know it anyway. If we want people to be competent professionals, they should learn the proper way to do things from the beginning. I think we need to get rid of this idea that a smart developer can learn a language in a weekend. Yes, syntax can be picked up quickly. But to really be good at a language, you need to know the libraries, frameworks and tools. And how to structure your code so that other people can understand and use it.

To introduce people to projects and tests, a tutorial could make a package (or namespace or whatever your language calls them) that just has a few functions/methods that take a couple of numbers, sums them, and adds one to the sum. And another method that subtracts one from the sum. And you could have another package that does the same for multiplication.

I might re-do some of the Pluralsight tutorials by making them into projects. I noticed there is now one for the Gin web framework. Perhaps someone at Pluralsight read my post a few months back on things I do not like about Javascript. They have a tutorial on Go web services that includes a massive Angular app; it takes up more than 500 MB on my hard drive. I wrote it would have been easier (and better for learning Go) to just make a web app in Go.

I was looking for a way to make a project with Go, when I found a video that creates a project while using VS Code. This tutorial follows a page on the Go site. One thing I do not like about Go is that “go test” does not run tests in all the sub-directories by default. Maybe it does and I am just not as familiar with it. But “mvn test” or “gradle test” or “lein test” will run all the tests.

Keep in mind, I am not a TDD purist. I do not always write failing tests first. I have no issue with writing tests after code; Ken Kousen calls it GDD: Guilt Driven Development. I also have no problem with tests hitting the database. A presenter at Austin Ruby years ago pointed out that you can get mocks and stubs to do what you want. If your code has a lot of mocks and stubs, are your tests telling you that your code does what you think it should do, or are they telling you that you are good at mocking and stubbing? Some TDD people say it is fine to use an in-memory database. Why not use an actual database? You are still going outside your code either way.

If you are a TDD purist, do not bother arguing with me. You will not change my mind, and NOTHING ever changes the mind of a purist. Not even the fact that purists are more likely to turn people off to something than turn them on to it. I announced my Groovy Email Server on a list somewhere, and someone got pissy with me because the first thing they did was run tests, and they failed because there was no database connection. Even though the README clearly states that you need to set up a database first. Like Will Rogers said, some people read the sign, and some people just gots to touch the electric fence.

You’re welcome.

Image from León Antiphonary, a 10th-century manuscript hosted at Virtual Library of Bibliographic Heritage, image allowed under Creative Commons CC BY 4.0.