Hacker News new | ask | show | jobs
by xg15 3700 days ago
I always found SLF4J's reasoning quite simple and logical and not at all an example of "those situations which show that software is difficult, and that often there are only compromises".

I think the core problem in this case is that the author is not clear if they are writing a library or a (command line) application.

The following workflow has always worked well for me:

1) Do you expect users of your project to use it by putting it in their classpath and calling its methods from their code? Then it's a library. You have no idea what else will be on the classpath and which context your library will be loaded in. (In fact, the user might not even be aware they are using your library thanks to transitive dependencies)

Libraries should never (if they can avoid it in any way) modify application-wide settings. So: Don't include any logger implementation at all, especially not the nop logger. (Please. Seriously. I've had to deal with misbehaving libraries in that regard and finding out why your logger settings are suddenly overwritten is a serious PITA.)

2) Do you expect your project to be used as a command line/standalone utility via java -jar ... or java -cp ...? Then you're writing an application. Do include a logger implementation and all necessary configuration. You can do it safely here as no one else should be using your project as a dependency.

3) Your project is a mix of 1) and 2) : Find out which parts of your project are library and which are application and split into sub-projects accordingly.

There are a few special cases I see, but not many:

4) You're writing unit tests for a library project: Do include a logger implementation, but make sure it's only visible to the test system. E.g., in Maven, you would add the logger implementation as a test-scoped dependency and put all configuration in src/test/resources.

5) You're writing a plugin/servlet/etc: Read up on your host system and find out if they provide logging or if it's your responsibillity. Proceed accordingly.

6) You're not using SLF4J but one of your dependencies does and so you get that message: Think about using SLF4J in your own project. Really. It's becoming almost a standard and usually you can keep using your old logging framework below it - but it will make things much easier later on. But if you don't want to, for some reason... 6a) If you're writing a library: Don't do anything at all. Do not include any logger implementation. See 1). The user of your library will be in a much better position to deal with the problem than you are. 6b) If you're writing an application: Include the slf4j-xxx implementation that corresponds to your logging framework: The log events from your dependency will be routed to the logging framework you're using and you can continue like you did before. If you're very certain you don't want any logging from any library using SLF4J, use the nop logger - however that is a very unusual case and a very inflexible solution.

1 comments

It's a set of clojure code that I expect people to use in an interactive shell by, yes, calling methods. Whether people do that within an IDE, directly at a REPL or by running a script is up to them.

I'm still not understanding why I should perform major surgery on my tool for the sake of a logging library which is a transitive dependency.

Nor am I understanding why I should pass the error message that confused me on to downstream users. I'm happy to make the decision rather than sit on the fence.

My point is that "not passing on the error message" could make life harder for downstream users too, depending on who those users are. (Sorry if my reply was arrogant or harsh - I got burned by this in the past, that's why I'm telling it)

If you're developing a project and use SLF4J by yourself, and use a third-party-dependency that already includes a logger implementation, this dependency can override your logging and cause all sorts of havoc. This can be a frustrating and hard to find bug.

(I'd say the fact that this can happen at all is a design flaw in it's own, partly caused by Maven's way of dependency resolution, partly by SLF4J. But I don't see that changing in the near future...)

I think it's important to consider how your project will be used. if it's really just for exploratory use in a REPL/a few scripts, then including a logger is fine. If you think this project could be used in larger projects, you should consider leaving it as it is or restructuring.

If you do include a logger, leave a note about it in the documentation. This way, users can at least exclude it again if they have to.