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<http://www.manning.com/bauer3/> >> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >> Spring Batch in Action <http://www.manning.com/templier/> >> 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<http://www.manning.com/bauer3/> > JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> > Spring Batch in Action <http://www.manning.com/templier/> > 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<http://www.manning.com/bauer3/> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> Spring Batch in Action <http://www.manning.com/templier/> Blog: http://garygregory.wordpress.com Home: http://garygregory.com/ Tweet! http://twitter.com/GaryGregory
