In a way, I’m a very isolated developer. Not in that I work from home, which I do, but I work on Komodo, which comes with its own "stack" (Mozilla) and doesn’t have access to a huge package repository like you would with Node.js. This means much of the work I do is isolated within this stack, and I only interact with what’s happening in the "outside world" through integrations and side projects. You might get the sense that this is a negative, and certainly in some ways it is, but I consider this a positive overall because, frankly, modern full-stack development sucks.
In the Beginning... There Was Lamp
I’m still relatively young... at 31 years of age, I have roughly a decade and a half worth of programming experience. But things move fast in the software world, and I remember a much simpler time... the time of LAMP. This was a time in which that simple abbreviation encapsulated the entirety of what it meant to be a "full stack developer." Linux - Apache - MySQL - PHP. Of course, depending on your roots, your stack might have looked somewhat different but you’d likely have been able to summarize them in a similar short abbreviation. Of course, frameworks existed, but they tended to be far more barebones and since you didn’t have package management everything tended to be a lot more self-sufficient.
When I would start a new project, which was often, I was young and full of energy. All I would do is bootstrap my project with my framework of choice and start programming—all within the span of 10 minutes. By the time my project was finished, 90% of the code would contain the application itself. Now, I’m not necessarily saying this was "better" than what we have now, I’m simply trying to illustrate how "simple" things were then. Simple in the sense that it was easy to wrap your head around the "full stack."
Down the Rabbit Hole of Dependencies
I still like experimenting these days, and I often start small projects on the weekends to experiment with new technologies. Most of these projects never see the light of day, they’re experiments for me to learn from. But it really has made me realize how "full stack development" is basically dead these days. Today, when I start a new project, I easily spend half a day setting up dependencies, constructing my build system, setting up the foundation for unit tests, and installing some basic libraries my application needs. Usually, by the time I’m done, I’ll have exhausted my motivation to work on the actual application I intended to work on. I can’t even imagine how jarring this all must be for new developers.
Here’s the kicker though, when I start a new "full stack" project these days and I install everything I need for my project, I don’t end up with the sum of its parts. I might have a direct dependency on a total of 10 modules, but those 10 modules each might have a dependency on 10 more modules, and those might then each have a dependency too. It makes for a very deep rabbit hole and for you to truly be a full stack developer you need to know how deep that rabbit hole goes. My simple 500 line application might turn into thousands of lines of code worth in dependencies.
Komodo is very different in this regard, and it’s one of the reasons I very much enjoy developing Komodo. Komodo does not have dependency management. Old school! Now, it does have the ability to include dependencies, mind you, but there is no encapsulating dependency management system. This means any dependency we add to Komodo practically has to be self-contained because anything else would be both a nightmare to import and a nightmare to maintain. While it certainly shows its age in places (Komodo is over 15 years old), what you end up with is a codebase that is extremely navigable. We have full insight into any code that is introduced to the project and it doesn’t require us to review dozens of additional dependencies.
Web Development Evolution
As developers, we go through an interesting "growth" cycle. Starting out programming, the possibilities of what you can do are overwhelming. I remember when I was learning how to save, update, and delete database information based on user input; my mind was going haywire with the endless possibilities it presented me.
Soon after, we learn to contain ourselves and our focus shifts from the applications to the logic of our code. This is where things go really crazy, we come up with the most over-engineered and abstract code structures known to man… just look at any modern PHP framework (zing!). "Why make a basic to-do app with basic logic when that logic could also encapsulate any other app that saves, updates, and deletes." Abstract everything, test all the things, oh and maybe actually write the actual application.
Once we reach the final stage of our "growth" cycle, we’ve realized how pointless this over-abstraction is. Our code is in service of our application, not the other way around. If we’re writing a to-do app we create the basic logic required to add, update, and delete a todo item and call it a day. No time wasted developing the core logic, and more importantly, the resulting codebase is (ironically) all the more maintainable.
It often feels to me that the stage we’re in, as web developers, is the middle stage I just described. Everything is being abstracted away and to the point where it’s hard to tell what you were even doing in the first place. Personally, I’m done trying. I’ll continue to experiment with new technologies, but I think my future experiments will be relatively old school. And I look forward to package managers "growing up" to the point where they can provide their core functionality without being "exploited" for it.