Remix.run Logo
liampulles 2 days ago

I'm starting to build a bit of antagonism to all-encompassing frameworks (e.g. Spring, Larvel, Phoenix, etc.), because while they are productive to build new things with, I seem to always have the same issue on legacy projects built with them.

It always seems to be a challenge to upgrade dependencies for these projects. Its usually because (in building the thing) one can't fully follow the "prescribed" way of doing things with the god framework, because each project has to deal with a niche infrastructure environment and/or business context that requires some hack or additional dependency. Then when you need to, say, upgrade a language version, you can't follow the god framework's guide for doing this (if there even is a decent one) because it will break your workaround. So you end up with this hodgepodge which never gets updated until it reaches a critical point where it cannot continue to run on your infrastructure, and it forces a big migration project.

Using a selection of libraries to build up the elements of a web service, and creating your own high-level abstractions for utilizing them, does require an additional time investment, but it leaves you in more control to do upgrades piece by piece, and to pivot the way things work when it is needed.

I feel like the Go ecosystem follows the latter approach more than most, and it was bit of a mindset shift for me at first, but I've grown to appreciate it.

tombert 2 days ago | parent | next [-]

Web frameworks for me are one of those things that's "great until it isn't".

If you're making a simple app then web frameworks can feel downright magical (like the original "Build a blog in 15 minutes with Rails" demo [1]), but for anything that gets even remotely complicated, I find that they generally just get in the way.

I personally have grown to prefer the "mid-level" HTTP setups, like Express with Node.js or Vert.x with Java.

[1]

networked 2 days ago | parent [-]

[1] https://www.youtube.com/watch?v=Gzj723LkRJY

tombert a day ago | parent [-]

oops, sorry. Forgot to attach it...thanks!

3eb7988a1663 2 days ago | parent | prev | next [-]

In the Python world, I see this as the microframework (Flask-esque) vs macroframework (Django). I will take Django every single time.

Flask prescribes so little that every project is a snow flake. Which of the N available options will you pick to handle auth/templating/cookies/email/whatever. Real decision fatigue when trying to enable core functionality. Extra special is that many of these libraries are single author creations, so maintenance and security are a mixed bag.

Django - every project roughly looks the same. You get so much out of the box that you must have special requirements if you must supplement with libraries. Since so many bits are first party, you have greater confidence that code is being maintained/checked for security problems.

evantbyrne 2 days ago | parent | prev | next [-]

The reason Go does not have a grand framework is that the language has a severely underdeveloped type system, which makes building complex libraries that meaningfully complement each other overly difficult. I waited nine years before starting on my first Go database toolkit so I could use generics. I succeeded, but can't shake the feeling that I know I had a better experience doing it with Java in undergrad. Being able to map/filter/reduce from a result type into another generic type would be a complete game changer. Being able specify union types would eliminate my need for the "any" type. Being able to overload would clean up a lot of code. It needs more time in the oven.

overfeed 2 days ago | parent | next [-]

> The reason Go does not have a grand framework is that the language has a severely underdeveloped type system

Counterpoint: PHP.

PHP 5.3 had an even less capable type system, but developed several usable frameworks.

evantbyrne 2 days ago | parent | next [-]

That's a complimentary point, not a counterpoint. I'm talking about Go's type system being restrictive. PHP and many other languages avoided that particular trap by allowing variables to be reassigned to any type. Java and many other languages went in a different direction and instead chose to build more complete type systems.

pkphilip 2 days ago | parent | prev | next [-]

PHP's type system is so "dynamic" that it is very easy to build frameworks for it.

For instance, PHP allows for even function calls like this:

$language = "German";

$functionName = $language."_send_email";

$functionName("Mike", "mike_1@gmail.", "Text ...");

This sort of flexibility has its own problems and it is only possible because of the very lax type system of PHP but it is also extremely powerful when it comes to developing reusable frameworks.

const_cast 2 days ago | parent | prev [-]

PHP has fully looped back around and have a more capable type system than Go or even JS or Python. It took a long time, but it got there and it did it pretty competently.

In the past it got away with it because of PHP magic. PHP let's you do pretty much whatever, at least in the past.

liampulles 2 days ago | parent | prev [-]

I think the Java stream API is amazing, and I do like that.

Not having the equivalent of hibernate level ORMs is not a disadvantage for me personally, just because I don't like ORMs - Asking chatgpt to spit out some SQL and mapping code for me and being able to tweak the actual SQL over time is preferable (but again that is just my preference).

I don't really agree with the idea that Go has an underdeveloped type system, I think its contraints lend itself to productivity in other ways. Of the various languages I've worked with, Go programs I expand have the highest chance of working the first time I run them, because the compiler and language server A) give meaningful indications of mismatched usages and B) older Go projects have a very good chance of just working, without me having to worry about getting them going with my IDE again. B is a product of the fact that they have been very conservative with the language.

evantbyrne 19 hours ago | parent [-]

Is it possible that some of the mismatch in how people view Go's type system is due to experiences differing from writing applications vs writing libraries? I personally find some of the repetition in Go code to be tolerable when writing web applications and CLI tools, but a real issue for the composability of libraries with different purposes. Going back to the database toolkit example, the query builder can easily return a result type, but what if I also want to handle validation of input before the query and then later return a HTTP response? Well to chain a result type end-to-end in Go requires it to have knowledge of all the different types/interfaces that it could map to, which I believe is way too broad of a responsibility for one type, even though all of those features feel as though they could very naturally chain together and reduce down to a single error. These kinds of type limitations effectively force Go libraries to live on their own islands where they don't compose with one another.

fozdenn 2 days ago | parent | prev | next [-]

Yep, In my domain only Go/Rust are useful. The opinionated framework culture never fits the bill. I think Rails/Laravel/Django are great when you have a beaten path for relational DB crud.

some_furry 2 days ago | parent | prev | next [-]

> It always seems to be a challenge to upgrade dependencies for these projects. Its usually because (in building the thing) one can't fully follow the "prescribed" way of doing things with the god framework, because each project has to deal with a niche infrastructure environment and/or business context that requires some hack or additional dependency. Then when you need to, say, upgrade a language version, you can't follow the god framework's guide for doing this (if there even is a decent one) because it will break your workaround. So you end up with this hodgepodge which never gets updated until it reaches a critical point where it cannot continue to run on your infrastructure, and it forces a big migration project.

Can you give any specific examples?

I'd like to see which of these are open source. And whether or not they're funded for maintenance.

zakirullin 2 days ago | parent | prev | next [-]

PSR to the rescue! For the past ~5 years I've been only using PSR-compatible components, with no framework whatsoever. For both enterprise-grade projects and small services. The reason was the same - those all-encompassing frameworks in long run just don't work. Too many constraints, too much hustle maintaining/updating.

billy99k 2 days ago | parent | prev | next [-]

I've been out of web dev for a few years now, but my issue with frameworks was always the ORMs. Simple CRUD apps always worked fine, but when I had to optimize SQL queries or create something more complex, I would end up having to add hacky additions to the app that always broke upgrades.

b_e_n_t_o_n 2 days ago | parent | prev | next [-]

I've found this for web frameworks as well. The time you spend learning the framework's abstractions could just be spent picking a queue library or whatever you need and adding it to your Go server.

KronisLV 2 days ago | parent | prev | next [-]

> So you end up with this hodgepodge which never gets updated until it reaches a critical point where it cannot continue to run on your infrastructure, and it forces a big migration project.

This matches my experience, literally took months to migrate an older Spring project to something with fewer CVEs and bugs. Created some new bugs and issues along the way, including one where compiling it on Windows would produce a .jar that runs fine, whereas compiling it on Linux changed something in how the Spring beans are initialized, leading to it failing to even start (the settings for allowing lazy initialization changed nothing).

> Using a selection of libraries to build up the elements of a web service, and creating your own high-level abstractions for utilizing them, does require an additional time investment, but it leaves you in more control to do upgrades piece by piece, and to pivot the way things work when it is needed.

Yes and no. If you only wire things up, then sure. But depending on how much code your devs have to write (and depending on the devs), you might actually end up with a bespoke mess if you have to dig into writing various base mechanisms (think transaction handling, scheduled tasks, task pools for parallel execution, key/value stores and caching, validations, auditing and metrics, file uploads and downloads etc.) - one that will have less documentation than something like Spring Boot, you won't be able to ask anyone how to solve issues in it, alongside sometimes just having architectures that neither scale nor work properly, because it isn't something battle tested over literal decades.

> I feel like the Go ecosystem follows the latter approach more than most, and it was bit of a mindset shift for me at first, but I've grown to appreciate it.

I still agree with this, to me it feels like the correct approach is indeed to give you most of the tools you might need for the technical bits and make you (or other devs) only write a bit of glue to wire everything up, to order how data moves through your system (resources, services, validators, repositories etc.) according to whatever business rules you might have. Things really go south when you miss out on that detail.

In the Java land, I think Dropwizard is a good example of that: it uses a bunch of mostly idiomatic libraries that are well tested, without being quite as rigid as Spring (and Spring Boot), letting you set things up as you please and also not getting in the way too much: https://www.dropwizard.io/en/stable/getting-started.html

In Go, I really like that a lot of the stuff is already present in the standard library.

N2yhWNXQN3k9 2 days ago | parent | prev [-]

In Laravel, the issue is that the framework is sold as "productive" as default. There is no real "beef" to the framework though, IMO. It is better today, but historically it is just a wrapper around symfony with some dependency injection through reflection, questionable serde, tons of magic, and with some unique takes on templates and routing, which are arguably not very good takes? Maybe components are better, but blade in general seems backwards as a template language.

Ever want to type `$model->foo instead of $model->getFoo()` but then have `$model->foo` magically call `$model->getFooAttribute()`, but fall back to `$model->getAttribute('foo')` if that method doesn't exist? Then that magically calls some casting methods, and possibly even fetches infinite records from a remote store? It is so artisan, bro. I can tell you more if you got five minutes.

therealpygon 2 days ago | parent [-]

Never really understood using a template language when PHP is first and foremost its own template language. I also don’t understand developers making decisions now about things that might one day have to be replaced. It’s like building a bridge, but letting the plan to maybe have to tear down the bridge 50 years later dictate all the design decisions.

The fact this happens to lead to more organized and testable code masks the wastefulness in the original goal of such an effort. It simply trades back-side efforts that may or may not ever be required for additional front-side effort with the result of making things easier later if it happens to be needed. I’m not saying it is completely a bad thing, more that it isn’t de-facto a good thing either.

I guess, like with all things, the important part is finding the right balance for the situation.

yurishimo 2 days ago | parent [-]

Templating languages in PHP are largely about better ergonomics. Sure, you can have your own helper functions that do the html escaping or an abstraction layer to pass variables into includes without polluting global variable scope, but that’s all boilerplate.

Twig and Blade are both fine templating engines with their own quirks and features but they’re also battle tested and have proven their use over the past decade+. If someone wants to use a dedicated templating language for abstracting away chunks of HTML, it’s low on my list of complaints.