Simplification is a good thing
Posted Dec 18, 2016
Although PHP is (with good reason) regarded as a bad language, it holds a special place in my heart. It was the first useful programming language I learned when I started getting into coding in my teens, and since then I have used it for everything from simple dynamic pages to large ORM-powered APIs. The former is definitely the problem that PHP solves best, as there is practically no setup or boilerplate required to get a page up and running (if you discount the HTTP server). It’s a technology that is in my experience still unmatched on ease of use for that purpose. Sadly, the web of 2016 has little use for such simple things, and over the years PHP has borrowed so many concepts from other languages that modern PHP has mostly ended up a slightly worse version of them. It has classes, but little type safety. It has collection libraries, but no generics. It has lambdas, but no terse syntax for them. And yet, because of its ubiquity, it’s still widely used for relatively complex systems around the web.
My personal web projects were historically PHP-based because I grew up on free web hosts that allowed PHP, MySQL, and nothing else. But for the last 18 months this site has been running on a $10 Digital Ocean droplet that hosts everything I need, from Ghost to nda to a custom personal finance tool and more. Over time, I retired or replaced most of the stuff that used PHP; not because I specifically wanted to get rid of it, but as a natural consequence of changing interests. But until today, there was one application of mine still relying on a LAMP stack to function, and that’s my game collection app that I sort of mentioned almost two years ago.
This irked me a bit. The only reason I kept Apache on my server was to support this single thing. nginx is on proxy duty anyway, so static files could be served just as well by that. And making a significant change to the underlying technology is one of the freedoms you are afforded when no one but you depends on the project. So for the last month, I’ve been porting the entire backend to something else: ASP.NET Core with Entity Framework Core. C# is a good language and I’m very happy to see that Microsoft is committed to making .NET (and important frameworks) cross-platform. I also haven’t used .NET extensively in a web context before, so it’s been a great learning experience.
The rewrite also made me realize that some architectural decisions didn’t make sense anymore. The old list evolved from a simple mysql_query()
call on a shared web host where MySQL was the only option, but of course, that’s no longer a requirement (and realistically hasn’t been since it started using tools like Composer and npm). Relying on MySQL also comes with its own issues, namely having to install and run mysqld
if you aren’t already. So while we’re at it, we might as well replace MySQL with something more suited for the task. I can think of no better option than SQLite: it’s zero-configuration, it’s easy to manage, and it has first-class support in EF Core. Using SQLite not only simplifies the system requirements for the application, it also simplifies configuration: Previously, you would have to enter a database address, name, credentials, and a table prefix in addition to app-specific options. With SQLite, everything but the last one can be skipped because it’s self-contained and uses no access control mechanism beside the filesystem itself.
Another (unrelated) simplification I implemented in this version was replacing Gulp with npm as the frontend build tool. Gulp seems like a good tool if you’re doing large, multi-target build tasks, but in the case of g_, the only task I need is concatenating and minifying Javascript files. I recently read an interesting article on how to use npm itself as a build tool, and since npm is a dependency anyway, we might as well make use of it. Previously, the build task was carried out by a 30-line gulpfile.js
and required Gulp, two plugins, and the tools that actually provided the functionality. With npm, this was reduced to a dependency on UglifyJS and a one-line command in package.json
. If we wanted to add a file watcher that would be one more dependency and one more command. Easy.
The new, rewritten version is actually live right now. Nothing at all should change from the looks of it, but everything behind the scenes has been ripped out and replaced with new, shiny, (relatively) typesafe code. This is a testament to how well a single-page app with a REST API separates frontend and backend concerns: not one line of client-side Javascript has been changed as a result of this rewrite.
So with this, it looks like I can finally retire Apache (and maybe even MySQL), and I have learned a bunch about the .NET Core stack at the same time. I’m gonna go ahead and say that’s a win-win.