Ok, I'm hearing a lot of conflicting ideas here. So I'm going to shelve my changes for now (I'm just glad that I had only finished the code, and not the tests), stop progress on the issue, and mark it for a later version, unless someone things we should move forward with this.
I'm a smidge disappointed, mostly because I was really proud of how I designed it :-), but I won't be using it personally so I'm not that invested. Nick On Jul 29, 2013, at 8:14 PM, Gary Gregory wrote: > I thought about this a little more in the context of avoiding Logger becoming > a kitchen sink. > > This is today already a mini-leak in toward kitchen sink-ness due to the > (good IMO) addition of the printf APIs. > > The way I see it, if I am a 'classic' programmer, I will not use the fluent > API, and vice-versa, if I am a fluent programmer, I'll use the fluent API and > not the standard API. > > So why should both crowd the same interface. In fact why should all THREE > (fluent, standard, and printf) be in the same interface. > > I like the LogManager.get<Style>Logger approach proposed earlier. > > If I am a fluent programmer, then I call getFluentLogger() and I get a clean > fluent API sans extra stuff. > > If I am a classic programmer, then I call getLogger() and I get a clean > standard API sans extra fluent stuff. > > Whether or not we want a getPrintfLogger() I know not yet, but I think it > worth mentioning. > > Logger can even implement toFluentLogger(), toLogger() and toPrintfLogger(). > > Having separate interfaces lets you have your fluent API without crowding the > standard API. > > Thoughts, > Gary > > > > On Mon, Jul 29, 2013 at 7:57 PM, Remko Popma <[email protected]> wrote: > It is unfortunate that you've already put a lot of work into this. > For me, I am firmly in the "don't do this" camp. (Sorry Nick) > > I think a fluent interface would add unnecessary complexity that does not add > any value. > We currently have a single method call that does a bunch of work. > IMO, splitting up that work to make it "look fluent" is not what fluent is > about. Fluent is more than just a coding style, it should simplify and remove > clutter. > > The canonical example uses fluent correctly, *to reduce complexity*: > {code} > private void makeNormal(Customer customer) { > Order o1 = new Order(); > customer.addOrder(o1); > OrderLine line1 = new OrderLine(6, Product.find("TAL")); > o1.addLine(line1); > OrderLine line2 = new OrderLine(5, Product.find("HPK")); > o1.addLine(line2); > OrderLine line3 = new OrderLine(3, Product.find("LGV")); > o1.addLine(line3); > line2.setSkippable(true); > o1.setRush(true); > } > {code} > > After: > {code} > private void makeFluent(Customer customer) { > customer.newOrder() > .with(6, "TAL") > .with(5, "HPK").skippable() > .with(3, "LGV") > .priorityRush(); > } > > {code} > > In the above example a fluent interface adds value because it allows many > objects to cooperate and it removes clutter. > But I would argue that we don't have any clutter that needs removing. > > Remko > > From: Nick Williams <[email protected]> > > To: Log4J Developers List <[email protected]> > Sent: Tuesday, July 30, 2013 8:08 AM > > Subject: Re: LOG4J2-242 (Fluent Logging) > > Well that's unfortunate. I just finished it. :-( Haven't committed it yet... > > I'm not sure what the advantage is to delaying it to 2.1. Is it just to study > it further? I understand "do it" and "don't do it," but I don't understand > "do it later." > > I've heard a few "I don't like it fluent" and "I didn't understand how it's > better" assertions, and I think that's missing the point. I don't have a > particular fondness for fluent APIs, but some people use a different > programming style and prefer them. Just because person A doesn't like or > understand how fluent is better, doesn't mean that person B doesn't like or > understand how fluent is better. Person B might like fluent so much they > write their own logging API wrapper around ours. Person B might not be able > to wrap their head around non-fluent APIs for one reason or another. > > Is there a major difference between these two lines of code? > > logger.error("This is a message with {} arguments {}.", arg1, arg2, > throwable); > logger.error().message("This is a message with {} > arguments{}.").arguments(arg1, arg2).exception(throwable); > > No, no real difference. However, I /can/ see how it's more obvious that > throwable is an /exception/ and not an /argument to the message/. And while I > would probably, personally, use the first line, I can certainly understand > how someone might prefer the second line. > > We're not talking about changing the existing API methods. We're talking > about adding API methods to support this different style of programming that > some people prefer. If, after all, our goal is to further adoption of Log4j, > wouldn't it make sense to offer something like this that many people use, > even if we ourselves aren't familiar with it or don't prefer it? > > My $0.02. > > N > > On Jul 29, 2013, at 5:52 PM, Paul Benedict wrote: > >> Whoever said this is a 2.1 feature, I concur. >> >> >> On Mon, Jul 29, 2013 at 5:45 PM, Ralph Goers <[email protected]> >> wrote: >> I actually started to work on this myself several weeks ago and came to the >> conclusion that I just couldn't grasp how it is better - with one exception. >> You can reuse the MessageBuilder and replace the message or arguments, etc. >> But that seems dangerous as it wouldn't be thread safe. >> >> Ralph >> >> On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote: >> >>> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams >>> <[email protected]> wrote: >>> I'm working on LOG4J2-242 to add the ability to log fluently. It's going to >>> work something like this: >>> >>> interface Logger: >>> + MessageBuilder trace(); >>> + MessageBuilder debug(); >>> + MessageBuilder info(); >>> + MessageBuilder warn(); >>> + MessageBuilder error(); >>> + MessageBuilder fatal(); >>> + MessageBuilder log(Level); >>> >>> + interface MessageBuilder: >>> message(String); >>> message(Object); >>> message(String, Object...); >>> marker(Marker); >>> exception(Throwable); >>> argument(Object); >>> arguments(Object...); >>> log(); >>> >>> Bruce (the requester) had suggested adding the methods that return >>> MessageBuilder to a different interface (as opposed to Logger) to keep from >>> cluttering the Logger API. The way I see it our options are: >>> >>> - Create a FluentLogger interface to house these methods. I don't like this >>> option because A) it complicates things significantly, B) it makes users >>> have to call a different method on LogManager (getFluentLogger) to get a >>> FluentLogger, and C) it means users have to have a Logger and a >>> FluentLogger if they want to use both APIs. >>> >>> - Create a FluentLogger interface that extends Logger. This option is much >>> better. It avoids cluttering the Logger API if that's all someone wants to >>> use, it doesn't require someone to have a Logger and FluentLogger if they >>> want to use both APIs, and it doesn't complicate the implementation >>> significantly (all implementations can just implement FluentLogger). It >>> does still mean LogManager (and related classes/interfaces) need getLogger >>> and getFluentLogger methods, which I don't necessarily like. >>> >>> - Just add these methods to Logger, which is what I intended to do from the >>> get-go and is what I still think is the best option. >>> >>> - and there's option 4: Don't do it. >>> >>> At first glance, adding these methods to Logger looks confusing and >>> cluttered. The less messy solution seems to me FLogger extends Logger. >>> >>> Gary >>> >>> >>> I'm going to proceed with #3 for now, but if someone has a strong opinion >>> otherwise please voice it so that we can discuss before I complete this. >>> >>> Nick >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: [email protected] >>> For additional commands, e-mail: [email protected] >>> >>> >>> >>> >>> -- >>> E-Mail: [email protected] | [email protected] >>> Java Persistence with Hibernate, Second Edition >>> JUnit in Action, Second Edition >>> Spring Batch in Action >>> Blog: http://garygregory.wordpress.com >>> Home: http://garygregory.com/ >>> Tweet! http://twitter.com/GaryGregory >> >> >> >> >> -- >> Cheers, >> Paul > > > > > > > -- > E-Mail: [email protected] | [email protected] > Java Persistence with Hibernate, Second Edition > JUnit in Action, Second Edition > Spring Batch in Action > Blog: http://garygregory.wordpress.com > Home: http://garygregory.com/ > Tweet! http://twitter.com/GaryGregory
