|
| 1 | +--- |
| 2 | +title: "Concerto 2: The Good, The Bad, and The Over-Engineered" |
| 3 | +date: 2026-02-17T22:48:00-05:00 |
| 4 | +author: bamnet |
| 5 | +layout: post |
| 6 | +permalink: /blog/2026/02/17/concerto-2-retrospective |
| 7 | +description: "A retrospective on 10+ years of Concerto 2 development — frontend framework choices, plugin architecture pitfalls, and lessons learned." |
| 8 | +image: /assets/images/blog_20260217.jpg |
| 9 | +categories: |
| 10 | + - Development |
| 11 | + - Retrospectives |
| 12 | +tags: |
| 13 | + - Software Design |
| 14 | + - Lessons Learned |
| 15 | +--- |
| 16 | + |
| 17 | +Concerto 2 was an ambitious plan to rebuild our application from the ground up, |
| 18 | +fixing all the little corners we backed ourselves into with the first version of |
| 19 | +Concerto. Most importantly, Concerto 2 needed to be something that anyone could |
| 20 | +set up and start using, instead of an application hardcoded to the |
| 21 | +idiosyncrasies of our [university](https://www.rpi.edu) in upstate New York. |
| 22 | + |
| 23 | +I think we achieved those goals, but looking back on the past 10+ years of |
| 24 | +development _(wow, has it been that long!)_ there are a few decisions I made |
| 25 | +that hampered our ability to perform ongoing maintenance and development of the |
| 26 | +Concerto 2 codebase. |
| 27 | + |
| 28 | +As I atone for my mistakes with a "LTS" focused version of Concerto, I wanted to |
| 29 | +debrief on what went wrong. Maybe you can avoid the same mistakes I made. |
| 30 | + |
| 31 | +## Frontend Frameworks |
| 32 | + |
| 33 | +I consistently picked the losing horses of 2010's frontend frameworks. |
| 34 | + |
| 35 | +We started with **Google's Closure Compiler** which provided a very "correct" |
| 36 | +implementation, with all the benefits of type checking, tests, and robust set of |
| 37 | +common libraries that modern day developers have come to enjoy. |
| 38 | + |
| 39 | +Unfortunately it was quite complicated to get setup and working right. The |
| 40 | +JavaScript that got written was verbose and hard to understand if you weren't |
| 41 | +living and breathing in the framework. I'm looking at you `goog.provide` and |
| 42 | +`goog.require`. |
| 43 | + |
| 44 | +We transitioned to web components powered by the **Polymer Project**. The idea of |
| 45 | +web components was great; different content types, like Graphics and Videos, |
| 46 | +could have their own self-contained web component. This helped establish clear |
| 47 | +interfaces between different layers of the frontend player which was sorely |
| 48 | +lacking in Concerto 1's jQuery-based frontend. |
| 49 | + |
| 50 | +As far as I can tell Polymer never really took off, leaving us with a limited |
| 51 | +ecosystem of documentation and examples to draw from. It felt like we were often |
| 52 | +pushing the bounds of what was possible in Polymer, and that was more |
| 53 | +representative of how limited the ecosystem was than how advanced our use |
| 54 | +cases were. |
| 55 | + |
| 56 | +Eventually, Marvin kept up with the times enough to realize that Vue made a |
| 57 | +great choice for a frontend and started building a much more reasonable |
| 58 | +implementation. I've drawn heavy inspiration from his early work building out |
| 59 | +the new Vue 3 frontend. |
| 60 | + |
| 61 | +## Plugin Maintenance |
| 62 | + |
| 63 | +Concerto 2 has a robust plugin system. Worried about polluting the core of the |
| 64 | +application with extra or optional functionality, we pushed lots of features to |
| 65 | +be developed as standalone plugins - largely powered by Rails Engines to be |
| 66 | +packaged and installed as gems. |
| 67 | + |
| 68 | +This achieved our goal of keeping the core as lightweight as possible, but made |
| 69 | +maintenance and ongoing nightmare thanks to the dependency tree. When there's a |
| 70 | +security update in a common library - like rack - we need to update versions |
| 71 | +across each plugin and re-release them. For example, the latest `rack` |
| 72 | +vulnerability requires updates and releases across 9 different repos. |
| 73 | + |
| 74 | +Dependabot makes this a tractable problem, but keeping up with all the different |
| 75 | +repositories became a lot of overhead for a volunteer project. |
| 76 | + |
| 77 | +This was further compounded by Rails version updates. When a new major version |
| 78 | +of Rails was released we needed to update each of the plugins and often fix |
| 79 | +subtle behaviors to keep them working. We didn't have great integration tests to |
| 80 | +catch these cases so someone needed to have all the plugins installed, |
| 81 | +configured correctly, and able to tell what it meant for them to be working vs |
| 82 | +not. |
| 83 | + |
| 84 | +In hindsight, we should have had more conversations about the functionality we |
| 85 | +wanted to support in Concerto and brought the vast majority of these plugins |
| 86 | +into the core application. |
| 87 | + |
| 88 | +## Dynamic Installation |
| 89 | + |
| 90 | +Installing someone else's Ruby on Rails application has historically been more |
| 91 | +of an art than a science. In the days before Docker and Kamal, we wanted to |
| 92 | +avoid System Administrators having to muck around in Gemfiles, `.rb` environment |
| 93 | +files, or yaml configs. After installing Concerto, perhaps via our `.deb` or |
| 94 | +Virtual Machine, the admin would only need to click though our friendly web UI |
| 95 | +to configure everything. |
| 96 | + |
| 97 | +To make this happen, we wrote hooks deep into the initialization process for |
| 98 | +Rails. These hooks injected critical information from the database, like a list |
| 99 | +of Gems to be loaded (those plugins!) and how auth should be configured. |
| 100 | + |
| 101 | +It was brilliant engineering work by some of the best developers I know. |
| 102 | + |
| 103 | +Somewhere along the way, Rails (or maybe Ruby?) overhauled the initialization |
| 104 | +process. It's better, faster, more effecient... I dunno, I didn't keep up with |
| 105 | +the change. The side effect was that many of our clever hooks were broken in |
| 106 | +very subtle ways, and it was far enough in the rear-view mirror that nobody |
| 107 | +remembered exactly what we did, how it worked. and how to get it working again. |
| 108 | + |
| 109 | +> _We were clever. Being clever is not always a great idea._ |
| 110 | +
|
| 111 | +Explicit goals of my current work including being as boring as possible and |
| 112 | +doing things the "rails way". Optomistically, that will minimize our surprises |
| 113 | +when Rails ships updates. Or maybe I'll be writing another one of these posts in |
| 114 | +10 years. Only time will tell. |
0 commit comments