logoalt Hacker News

Kinranytoday at 9:42 AM1 replyview on HN

Ignoring the singleton for now, because I don't quite see the need.

What's the alternative? Which part of this is actually caused by OOP? If you want to isolate IO, which you should, then you need to inject things that do IO and you need to specify a contract for them. And then it's nice to instantiate things or call functions without explicitly instantiating the whole tree of their dependencies.


Replies

sirwhinesalottoday at 1:08 PM

There are various ways to solve the problem (if you consider it a problem, I personally don't, there's no need for things to be this extremely decoupled, but for the sake of argument):

1) Allow objects to send messages to an implicit "parent" object, which supports "doesNotUnderstand" ala Smalltalk and that by default also forwards to the implicit parent. That means you can implement "log(...)" at the right point in the abstraction without manually passing a logger around.

2) Use algebraic effects, no need to handle this with OOP. A function requests the "log" effect and a handler defined in a higher level scope takes care of implementing log.

3) Have a language with an implicit context parameter that allows putting arbitrary things in it (closest would be Odin but Odin has a fixed set of operations in the context). Because it is implicit in the calling convention methods can be oblivious to it.

4) You separate the concerns: logging is the act of recording some information. Where that information is ultimately sent or stored is a separate concern. This is the more functional view of the problem. If you follow a "model-view-update" approach like the so called "Elm Architecture", logging is just another task produced by the view function, it doesn't need any special handling.

It's not that this is a "problem" of OOP, it is that OOP doesn't give you any tools for tackling this problem. That is why dependency injection frameworks exist. Some other paradigms and non-OOP architectures don't have any trouble with it. You can also replicate those architectures in an OOP language, but that's still "contorting the paradigm" rather than it helping or guiding you towards a clean solution.

Personally I think a global singleton logger is perfectly reasonable, it is other people (the ones using DI frameworks) that think otherwise ;)