It's easy to avoid "AbstractFactoryProviderBuilder" if everything is hardcoded. Try to make it reusable and extensible, and I bet you write one yourself.
The first domino is opting for OOP. AbstractFactoryProviderBuilders are just the inevitable downstream consequence of that initial choice. No need for factories if you don't traffic in objects in the first place.
Objects. Just say no.
What's a good codebase that is very large but without either OO or pseudo-OO?
I work on large (but private, so I cannot share, sadly) FP-style codebases. The code style is stateless functions grouped in modules that operate on data-only structs in a factory line manner. Typed boundaries for correctness, short and maintainable functions for clarity. No member functions, so no vtables.
I've never seen such code need or use OOP design patterns. I'm just very gently pushing back against the idea all code devolves into OOP spaghetti in due course. It doesn't! There are better ways. :)
I did not use any inheritance. In general I would say OOP craziness faded long ago (in Java too), together with XML. Interfaces -- yes, are very much alive though.
A friendly joke in response to the claim that sufficiently complex code always ends up sprouting OOP abstract nonsense.
And all the stuff like factories and everything exist in FP as well, it's pretty short sighted to say otherwise. These are patterns that may or may not be useful in a given case. Sometimes a language feature can replace them (e.g. pattern matching ~ visitor pattern, but not even this is a full match see closed vs open hierarchy), but in most cases you just call them something else/don't have that problem because you are not writing that big of a software.
> And all the stuff like factories and everything exist in FP as well, it's pretty short sighted to say otherwise. These are patterns that may or may not be useful in a given case. Sometimes a language feature can replace them (e.g. pattern matching ~ visitor pattern, but not even this is a full match see closed vs open hierarchy), but in most cases you just call them something else/don't have that problem because you are not writing that big of a software.
This is precisely the viewpoint that made me want to reply to the original comment. If you live and breathe OOP, you see OOP design patterns as solutions, because you've run into OOP problems that they solve. FP code does not tend to run into OOP problems, and ergo does not tend to utilise OOP solutions to those problems. I appreciate this can be hard to imagine, but I respectfully suggest you have some OOP blinders on if you're so confident everyone is using factories that you attempt to size-shame FP codebases you've not even seen so you can remain in the right. :)
The purpose of factories is to decouple object creation and use. But FP already does this by never coupling behaviour and data in the first place. Think about it. If data is in a simple struct, with no member functions, ideally immutable, what kind of factory could you possibly need? How would it even work? What kind of problem could it possibly solve?
To say nothing of e.g. the Visitor pattern, which is an approximation of functional styles using OOP. There is no need to define some small subset of behaviour outside a class, and then hook up boilerplate machinery inside that class to run that behaviour (ie the Visitor pattern) if all behaviour is always defined outside the class. The Visitor pattern solves a problem that arises only in OOP, due to its penchant for stateful data-code coupling, and it does so with a sprinkling of FP. It's incoherent to speak of a Visitor pattern in FP code. It's an OOP solution to an OOP problem.
Visitor pattern is meant to address the other half of the expression problem - you have n types of data all with m behaviors. OOP makes it easy to add a new row (new class) while FP makes it easy to add a new column (new function). But both are asymmetrical, traits a la rust are probably the closest to solving it properly. So no, it is incorrect assumption on your part to hand wave it away, this is not solved (especially not in "FP java", which otherwise I also like and use).
Though JS will still have the least boilerplate because of the way it handles types.
var wg = sync.WaitGroup
defer wg.wait()
wg.Add(1)
go func() {
defer wg.Done()
}
)And create a separate channel to return errors from a goroutine. Definitely more work.
No, you don’t. Any stack-allocated resources are freed when the function returns. WaitGroup is just there for synchronization.
Also I don't understand "it's not trivial to grow them". It is trivial to grow them, and that's why Go went this way. Maybe only 0.1% or fewer of use-cases will ever find any issues with the resizing stack (in fact probably the majority of uses are fine within the default starting stack size).
Well, guess how coroutines are implemented in Rust/C++/everywhere else!
Nonetheless, I do think that java virtual threads are superior for the vast majority of use cases and they are a good default to reach for for "async" like code.
Don't get me wrong, I like Java and don't very much like the Go language. But Java has a lot to improve upon still.
I don't really think it's fair to compare some old jboss monstrosity doing the job of a whole kubernetes cluster to a dumb hello world server written in go.
Sure, java startup time is and will probably always be worse than putting everything into a single binary - but it is way overblown in many discussions. I have a bunch of Quarkus services on my home server and they start up immediately.