Ahh. Good point. Will do. N
On Aug 2, 2013, at 3:45 PM, Gary Gregory wrote: > Nick, > > Please attach your patch to the JIRA for safekeeping. > > Gary > > > On Thu, Aug 1, 2013 at 9:39 PM, Nick Williams <[email protected]> > wrote: > 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 > > > > > -- > 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
