Another rewrite
It seems to be that I only write blog posts when I update the software that runs my website. This post concerns my experience from the latest rewrite, and it will be rather light on technical details.
This time, I've rewritten my website back-end in Haskell, my new favourite programming language. The source code is on GitHub. I used the popular Yesod framework, which I will be commenting on in this post.
I also refreshed the front-end. It has responsive CSS now, so you can read it on mobile. Even I, Luddite as I am, have had a smartphone since 2015. For some reason it never occurred to me to check my own website on my smartphone until very recently. I just sort of assumed it would work. (Turns out it didn't).
A Haskell back-end with Yesod
Haskell is of course famous as a functional programming language, but it's the strong static type system that truly makes Haskell shine. Acquaintances who champion dynamically typed programming languages think I must be crazy to choose a statically typed language.
There is definitely a downside to static types. Static typing introduces a delay between writing code and running it, because the compiler has to come in and check the types (and often we have to fix a whole lot of type errors). Static typing also limits the number of programs one can write (i.e. there are programs that would produce correct results, but they don't type check). And, of course, the classic argument against static types is that they lead to verbose code.
However, static types can also be a big win, when done right. Classic languages like C and Java don't get the balance right, and I think that's a lot of what fuels the anti static typing arguments. Haskell's powerful type system allows us to encode invariants about our programs, which the compiler can check for us, eliminating entire classes of bugs. Type inference eliminates the verbose type declarations, and advanced type system features (Haskell's type system is Turing-complete) greatly expand the number of well-typed programs that can be compiled.
My go to example is null-pointer bugs. In Haskell, no value can ever be "null" unless we explicitly mark it as such, and then the compiler forces us to deal with the null case. A program with a null-pointer bug simply will not compile. Compare to Java where the null-pointer exception is the most common runtime error (according to Takipi Blog). (Although, I am glossing over the issue of partial functions).
In terms of rewriting my website back-end, I feel that Haskell with Yesod gives me the best of both worlds. Yesod leverages Haskell's type system to pull off cool tricks like compiler-checked URLs (so I can be sure that none of my internal hyperlinks are broken). At the same time, I can write terse, high level functional code without worrying too much about types until I'm ready to fire up the compiler.
When I started with Yesod, I found that there is a bit of a learning curve. Part of that was because it's been too long since I did any server-side web development. But, Yesod does throw up a few hurdles of its own. When one makes a mistake, or generally deviates from Yesod's idea of best practices, the result is usually a type error. These type errors are perplexing to the beginner. It's a common problem in the Haskell world. Probably more could be done in the compiler and in the libraries to improve the situation. But, for now, it's worth noting that understanding and fixing the type errors gets easier with practice.
Yesod makes extensive use of Template Haskell to provide DSLs for routing, persistence, and HTML/CSS/Javascript generation. This presents a tradeoff. One the one hand, the DSLs are simple, declarative, and type checked by the compiler. On the other hand, Template Haskell is slow (since it adds extra code-generation steps to the compilation process), and the error messages are difficult to understand. Personally I prefer a more lightweight approach to DSLs, but the web is a complex environment to program in, and it may be that Yesod's Template Haskell approach is necessary to the whole thing palatable.
After a few days with Yesod, and having explored the routing, persistence, and forms subsystems, I found that I became quite productive. I was able to add authentication and authorization in just a few hours and with minimal debugging effort.
Deployment on AWS has been very easy. Yesod has a companion project for deployment, Keter. Now that everything is set up I can deploy with a single command. It certainly beats the good old days of mucking around with FTP clients and Apache configurations.
Overall it's been a positive experience and I hope to build more websites in the future powered with Yesod and Haskell.
The front-end: HTML5/CSS
My previous back-end was still using XHTML, which was considered best practice at one time. I was slow to adopt HTML5 because it reverses a lot of the XHTML lessons that had been drilled into us about properly closing tags and properly quoting attributes. However, HTML5 does have a lot of advantages in terms of smaller and more semantic markup.
CSS, too has come a long way since I wrote articles like this. I think one of the biggest improvements is that now we have the MDN CSS reference, and thank goodness. That knowledge used to be distributed across a slew of confused forum posts, low-quality tutorials, misleading specs, and out-of-date books.
CSS has some nice new features. I like the new box-sizing style. I like the rounded corners (they used to be such a pain to do). I like the CSS animations. The nav buttons on my site are now nothing more than hyperlinks styled with CSS. On the early versions of this site (circa 2005), those buttons actually required JavaScript! I love that one can do it in CSS now, and it looks so much better too.
Reactive layouts are a big deal these days since so many people have ditched their laptops in favour of smartphones. I found making this site reactive to be quite easy. But then I'm certainly no expert on such matters and it's quite likely that I've made some fatal mistake. In any case, I don't doubt that reactive design is a seriously difficult problem for more complicated sites.
Summary
I updated my site for the first time in 4 years. I completely rewrote my old XHTML PHP backed in Haskell with Yesod. The front-end is now HTML5 and I'm using some of the more recent CSS features to subtly improve the look and provide reactive mobile support. This project took 10 days (from when I started reading the Yesod book to when I deployed on AWS), which is much longer than I wanted to spend, but probably reasonable considering it's the first web development project I've done since 2011.