It’s a trap!
Many scholars want to have a webpage, website, or even a custom web application to showcase their work, provide open access to resources, or to collect data. In the digital world we live in, this is an excellent way to extend your reach and expand your impact. Although it is tempting to make your website as feature-rich and impressive as possible, I will argue that because scholars rarely have the resources to continually maintain a website, web development should usually be focused on minimizing and simplifying future maintenance work.
The work of developing these websites is often done by student research assistants or scholars themselves, neither of whom have much experience in web development. When I was hired just over seven years ago, I had enough coding experience to make a website, but nowhere near the experience needed to understand the broader implications of the decisions I was making about languages, frameworks, and paradigms. In an excellent blog post, my colleague Dr. Jeremy Browne told about the trap of using proprietary dependencies, such as Flash. I want to continue that conversation by identifying a couple more traps that have come back to bite me.
1. “This cool dependency will make it easy to add X functionality to the web app!”
When it comes to future maintenance of a website, all dependencies are evil. A few years ago, I worked with our Japanese Department to rewrite some courseware that had been written with a core dependency that became insecure, and lost functionality in modern web browsers. This broken dependency rendered the entire website useless. We re-wrote the website to use pure HTML, CSS, and vanilla javascript so that nothing could break (unless future browsers unthinkably break backward compatibility with older versions of javascript) and although it does not quite have the same custom look, it is nearly future-proof. My view of dependencies is simply a more general take on Dr. Browne’s idea that proprietary, non-standard dependencies are bad. I am convinced that all dependencies are evil. Some dependencies are a necessary evil, but the decision to add a dependency should never be taken lightly.
2. “This language/framework looks really neat. Let’s use that!”
Stack diversity is evil. Every language or framework that has to be supported is a massive time commitment for every future developer. Each has its own idiosyncracies and gotchas that require experience and time-on-task to master. After being hired, I was quickly assigned a number of web projects to maintain and/or “resurrect”. Things had broken, and nobody knew how to fix them because they used frameworks that no one in the office was familiar with. At the time, I assumed that most of my struggles were simply because of my own “skill issues”, but I am becoming more and more convinced that the real shortcoming in these cases was the original decision to use frameworks outside of our usual stack.
In our office, we have a handful of technologies that are more-or-less obligatory. We host a number of websites using WordPress, which uses PHP. Natural Language Processing (NLP) is a core component of many Digital Humanities projects, and Python is the de facto language for NLP and machine learning. Python is by many metrics the most popular programming language in the world, and one can generally expect that any student developer we hire will have experience using it. Both PHP and Python are extremely popular languages for website backends (code that runs on the server), so in our office, choosing a different language for backend development, no matter its virtues, is an unnecessary burden on future maintainers.
A couple years into my work in ODH, I took on a large web development project, Y-video, which we built from the ground up. After consulting with my team, I decided to use a Clojure backend, and React frontend (code that runs in the browser). I regret both of these decisions.
Clojure is a relatively obscure language, but it is based on the very popular Java runtime, and it is used by many large corporations. It also has an elegant–albeit unintuitive–syntax that enables a slick developing experience. However, as a “Lisp” language, it uses a syntax that is unfamiliar to student developers and coding patterns that are confusing to the uninitiated. Although we have a Clojure expert in our office, Y-video has never been his primary responsibility, and we have a number of mission-critical bugs that have been sitting for more than 18 months without resolution. If the backend had used PHP or Python, there are at least five full-time employees in our office who could have easily taken a stab at those issues. But with Clojure, we don’t have many options.
Although React is itself the de facto standard for modern frontend web development, the decision to use React for Y-video’s frontend is regrettable for similar reasons. First and foremost, React is a very complex framework with many dependencies. Merely by initializing a create-react-app
project, you immediately have hundreds of dependencies before writing a single line of code. The likelihood that one of those dependencies will negatively affect future maintenance is very high. The framework is based on multiple levels of abstractions that require custom tooling (e.g. redux
) to make sense of. Furthermore, React apps are notoriously verbose, with orders of magnitude more lines of code than equivalent apps written in other paradigms. More lines of code means more complexity and more time spent tracking down bugs. As the app has grown, the complexity has reached a level that my student developers struggle to even make sense of the existing code before trying to fix a bug or add a feature. One student developer has spent more than a semester on one new feature, and it’s still not done. Although React is a very powerful framework that can achieve very impressive user interfaces, the dependencies and complexity should be a major deterrent to anyone interested in manageable, future-proof maintenance. It is worth considering whether that sexy user interface feature is worth having a codebase that is that much more difficult to maintain.
Conclusions and (possible) solutions
Having a web presence is important for many scholars, and I have tried to illustrate two major pitfalls that can complicate the creation and/or maintenance of a website. It is important to keep your website as simple as possible by…
- …using as few dependencies as possible (preferably zero). If your app can easily function with pure HTML/CSS/JS, don’t use anything else.
- …limiting the number of technologies in your stack. If you or your team are already familiar with a technology that can do the job, don’t chase after new shiny languages and frameworks.
- …giving preference to frameworks that emphasize readability and simplicity. Avoid “clever” solutions that are difficult to understand and edit.
- …saying “no” to unnecessary website features that significantly increase the complexity of the app.
If you need features that require a database or user management, then for the sake of simplicity, I am a strong proponent of server-side rendering (giving the lion’s share of the work to the server) because it stays close to the foundational internet technologies of HTML/CSS/JS, and is therefore more transparent and simple to reason about (especially using the HATEOAS paradigm). In particular, I’m excited about tools that help simplify–rather than complicate–your codebase, like htmx. Although htmx does represent a dependency (only a single javascript file!), it facilitates modern, responsive user interfaces without the need to write any custom javascript. Having experienced the complexity of React, that is something I can get behind!