DEV Community

Discussion on: Need help to better understand Typescript, IoC, Hexagonal architecture

Collapse
 
johncip profile image
jmc • Edited

However, what do you mean by “[…] as an implementation detail, you’re probably going to be able to wrap multiple logger instances and dispatch to all of them at once”?

Only that, so long as you're writing a logger class, it might be interesting to add the ability to write to multiple destinations at once, using a single instance.

Should I do the same thing (IConfig interface + ConfigImplConvict implementation) for the configuration of the project? And use dependency injection instead of decorator?

Hard to answer without knowing what the project is and what your goals are. If it's a learning exercise, then I might try multiple solutions and see how each differs. But without a concrete need motivating them, I don't think you can say that one would be better.

Otherwise, it sounds like the scope might be small enough that no matter what you do you're not going to run into maintenance problems. Design patterns exist to solve specific problems (and specifically in languages not dynamic enough to allow them to be solved more simply). So more isn't necessarily better.

If the goals for this project are centered around an app with specific behavior, my advice would be to focus on the behavior and not over-think the supporting stuff. For instance, if you have a real need for logging, let that guide your decisions about how to implement it. You can always add more logging code, but if you add and later remove it, you can't get that time back.

A simple config solution might just be a class that acts as a namespace for some constants. You may find later that you want instances, so that it's easy to pick a stage at runtime ("dev", "prod", "test", etc.). Or you might prefer to have a data file that's separate from the source code, so that you can add secrets without having to put them in version control. (Or so you don't have to make the type checker happy whenever your config changes.)

For context, most of my professional experience has been with dynamic languages, and I prefer metaprogramming to patterns (where possible). But my overall experience has been that it's not hard to write a decorator, but it is hard to finish an app, so I would try not to get bogged down in places where a naive design choice will be cheap to adjust. Especially since static typing makes refactoring that much less error-prone.

Regarding dependency inversion: spotting violations is easy enough -- wherever a class depends on another class, make it depend instead on a passed-in instance instead. But I would first ask what it buys you -- it's good to depend on abstractions, but until you actually reuse a piece of code, it can be hard to know what the right abstraction will be, at least in my experience.

Thread Thread
 
alashahonore profile image
Grégory "Alasha" HOARAU

Thank you for the valuable advice. I will put them into practice :)