Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I overlapped at LinkedIn at the same time as the author. While there, I wrote my first (and to date only) FactoryFactory.

LinkedIn replaced its uses of Spring with a thing called Offspring. Offspring explicitly disavowed being a dependency injection framework, but it did a similar job for us. I rather liked it. Notably, you just wrote Java with it. Invariably, in Offspring, you'd have to write a FooFactory to construct your Foo object to inject it into some (other class. By convention, all of the factories ended in Factory.

Well, I had a use case for a runtime class that needed to make a per-request factory to make little objects. So to make my Bars, I needed a BarFactory; and to construct the BarFactory, I needed an Offspring factory, thus BarFactoryFactory. There it was. I felt a little weird after that.

I suspect the EventFactoryFactoryFactory code here was such an Offspring factory being used for dependency injection, but I can't explain why it produced a FactoryFactory.



> LinkedIn replaced its uses of Spring with a thing called Offspring.

I think dependency injection itself is reasonable, but I increasingly wonder why you need a framework for it at all.

Yeah, for certain extremely complex scenarios, such as dynamically loaded plugins which are only known at runtime, you'd need some "host" code which manages the plugins - though even in that case, it will probably be helpful if that management code is part of your application's codebase, so you can easily debug it.

However, that's already the big exception. I'd claim that in the vast, vast majority of projects, DI is only used during development - and at runtime, there is exactly one way how the object graph is supposed to be assembled. So if that's the case, why not just make a big "application" class in your codebase and instantiate the objects/assemble the graph yourself? What exactly do you need a framework for?

Another exception are callback situations, most prominently web endpoints. A framework can be a big help here to get the headers right, manage auth, caching, CORS etc through filter chains, avoid a good part of typecasting, redundant declarations, etc.

But even there, Java now introduced lambdas and records which makes working with callbacks and "dumb structs" far easier. So the future of "web apps" here might as well be some library which lets you register web endpoints with lambdas - instead some overarching framework which expects that you structure your whole codebase around the fact that your app will serve HTTP on port 8080.


DI at LinkedIn was used for development, for unit test isolation, and to reduce tight coupling.

One big problem with a giant "Application" class is that it means all of the dependencies are laid out there, and their dependencies, and their dependencies, all named and instantiated. But some dependencies are in libraries, and basic detail encapsulation means ... a factory.

Offspring wasn't much of a framework, more of a set of conventions and utilities for building that stuff in plain Java code (with key annotations). In particular, I think the Offspring setup wasn't opinionated about the framework of the rest of the application, although other parts of LinkedIn were (and presumably still are).


> One big problem with a giant "Application" class is that it means all of the dependencies are laid out there, and their dependencies, and their dependencies, all named and instantiated. But some dependencies are in libraries, and basic detail encapsulation means ... a factory.

Indeed they are - and I strongly believe that is a good thing. Because at which other place are all your dependencies laid out and instantiated? In your deployed application code at runtime.

So to understand your application in its entirety (and not just individual components), knowing the whole object graph is essential. And the easiest way to know it is if it's already written down somewhere.

This doesn't have to keep you from enforcing loose coupling and encapsulation, at least for certain definitions of those:

If you want to keep the components encapsulated - i.e. ensure that FooService works with any implementation of BarService - you can still do that: Just ensure the individual components only refer to each other through interfaces and forbid direct dependencies between them. Then in the end, the application class should be the only location in the entire codebase where multiple concrete components interact in the same class (excluding tests). You can even enforce this by putting each components in a separate artefact and only allowing dependencies to an "API" artefact that is distinct from the implementation.

However, if you understand loose coupling such that no part of the application should know about the other, and the entire application assembles its component through some magical algorithm, I'd call into question why this is even a desirable property: You still have an object graph, you just go out of your way to hide it. And it's still very important that the object graph must be assembled in some very specific way, which is why the algorithm must be coaxed into doing the right thing with qualifyer annotations or magic priority numbers.


A FactoryFactory is just a poor man’s currying!


Currying is just poor man's obfuscation :-)

Seriously, I think anytime I have met currying (admittedly only in JS projects) the code could be rewritten to be better without it.


It's a lot more common in e.g. OCaml and Haskell where the syntax makes the partial application a lot easier.


I don't have any inside knowledge, but I'd guess an EventFactory is tied to a specific Event type, so the FactoryFactory is about producing Factories for any such type? I'd never have guessed the third though.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: