Return-Path: X-Original-To: apmail-commons-dev-archive@www.apache.org Delivered-To: apmail-commons-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 992AE102BC for ; Thu, 29 Aug 2013 19:14:25 +0000 (UTC) Received: (qmail 42383 invoked by uid 500); 29 Aug 2013 19:14:24 -0000 Delivered-To: apmail-commons-dev-archive@commons.apache.org Received: (qmail 42308 invoked by uid 500); 29 Aug 2013 19:14:24 -0000 Mailing-List: contact dev-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Commons Developers List" Delivered-To: mailing list dev@commons.apache.org Received: (qmail 42300 invoked by uid 99); 29 Aug 2013 19:14:23 -0000 Received: from minotaur.apache.org (HELO minotaur.apache.org) (140.211.11.9) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 29 Aug 2013 19:14:23 +0000 Received: from localhost (HELO mail-wg0-f46.google.com) (127.0.0.1) (smtp-auth username britter, mechanism plain) by minotaur.apache.org (qpsmtpd/0.29) with ESMTP; Thu, 29 Aug 2013 19:14:23 +0000 Received: by mail-wg0-f46.google.com with SMTP id k13so963278wgh.25 for ; Thu, 29 Aug 2013 12:14:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; bh=+BrdbfFFs9g81TAwQOtIYUlBd/EjL/RODmhl4jIxvqc=; b=lAna4M8bdsQSj+NDCxf3RdI6e2TUC3OnxHP8bxnvD57DLt6aZqUrdx/0Fx05KlU5R5 LjWB+zm9HpwdOyzC+Rf7pn4pj2RGDEhq291gFTzkjcK1rYbvyF6m7G/lzZEiDYlretbd Zq6KN8VF2Z0xBzl7ySygsDnYYYQ4LznxahIy2yYtLehS3P1/BFlemyUEoySrLpLqYJbc RAllxm80vG8fNGhYpp95rSDIqxR3iI+5WR3ObEpvu2zJLlO4rYfJZ7LR1Y8+aAup2Efp TmA8mXAyT6Ra5vQf3YxjqM3ZWJWCshwy8dXMs05yHeZzGj1Dhr+0twYukWQlCKTaPxoV 8NVA== MIME-Version: 1.0 X-Received: by 10.180.206.9 with SMTP id lk9mr9277548wic.26.1377803661592; Thu, 29 Aug 2013 12:14:21 -0700 (PDT) Received: by 10.194.32.196 with HTTP; Thu, 29 Aug 2013 12:14:21 -0700 (PDT) In-Reply-To: References: <5218FC62.1090905@oliver-heger.de> <521989BA.2060301@gmail.com> <521A348C.4050704@sandglass-software.com> <521B6153.1050102@oliver-heger.de> <521B9E53.8070007@oliver-heger.de> <521C33E9.90201@gmail.com> <521C5A02.7060905@oliver-heger.de> <521F9882.5090300@oliver-heger.de> Date: Thu, 29 Aug 2013 21:14:21 +0200 Message-ID: Subject: Re: [ALL] Design question: static utility classes From: Benedikt Ritter To: Commons Developers List Content-Type: multipart/alternative; boundary=001a11c369c2d1cf6804e51ae9d9 --001a11c369c2d1cf6804e51ae9d9 Content-Type: text/plain; charset=ISO-8859-1 Yep, makes sense... Thanks Matt. 2013/8/29 Matt Benson > I prefer a slight variant: don't give the user static methods on a > different class, just give them one static method yielding an instance > configured for default behavior. I think that's the basic approach being > taken with CSV formats, no? > > Matt > > > On Thu, Aug 29, 2013 at 1:52 PM, Oliver Heger > wrote: > > > Am 29.08.2013 10:26, schrieb Benedikt Ritter: > > > 2013/8/27 Oliver Heger > > > > > >> Am 27.08.2013 07:06, schrieb Phil Steitz: > > >>> On 8/26/13 11:28 AM, Oliver Heger wrote: > > >>>> Am 26.08.2013 16:18, schrieb Phil Steitz: > > >>>>> > > >>>>> On Aug 26, 2013, at 7:38 PM, Oliver Heger < > > >> oliver.heger@oliver-heger.de> wrote: > > >>>>> > > >>>>>> Am 25.08.2013 18:45, schrieb Adrian Crum: > > >>>>>>> +1 > > >>>>>>> > > >>>>>>> -Adrian > > >>>>>>> > > >>>>>>> On 8/25/2013 9:26 AM, James Carman wrote: > > >>>>>>>> AtomicReference? > > >>>>>> There are multiple aspects here. One is the safe publishing of a > > value > > >>>>>> written into the member field. This can be achieved by atomic > > >>>>>> references, synchronization, or a volatile field. > > >>>>>> > > >>>>>> The other aspect is that such a field of a static utility class is > > >>>>>> pretty global. You cannot have different values for different > > threads. > > >>>>>> > > >>>>>> So the question is, is it good design to have static utility > classes > > >>>>>> with state? > > >>>>> Excellent point. The key question to ask is are there use cases > > where > > >> different threads in the same JVM are really going to want different > > >> default factories. I wonder if any actual user of the current code > has > > >> ever wanted this. > > >>>>> > > >>>> In this special case, I *assume* that there are hardly any concrete > > use > > >>>> cases, but of course, we cannot be sure. > > >>>> > > >>>> However, there may be other examples in [configuration]. Would it > make > > >>>> sense to be homogeneous here, i.e. use the same design principles > for > > >>>> all classes? > > >>> > > >>> Yes and the non-static approach is certainly more flexible, so on > > >>> balance I think you and James are right. > > >> > > >> Many thanks for the feedback! So I think I will go for the "bean-based > > >> approach" then. > > >> > > > > > > One possibility to have the best of both worlds is to create a class > with > > > all static methods that delegates to an instance that is hold in a > static > > > field. This would be for all those that want the default behavior. > Those > > > who need customized behavior could instanciate the delegate directly an > > > configure it the way they like: > > > > > > public final class BeanHelperUtils { > > > > > > private static final BeanHelper DELEGATE = new BeanHelper(new > > > DefaultBeanFactory()); > > > > > > public static Bean someMethod() { > > > return DELEGATE.someMethod(); > > > } > > > > > > } > > > > > > public class BeanHelper { > > > > > > private final BeanFactory factory; > > > > > > public BeanHelper(BeanFactory factory) { > > > this.factory = factory; > > > } > > > > > > public Bean someMethod() { > > > factory.createBean(); > > > } > > > } > > > > > > client code can either call BeanHelperUtils.someMethod() > > > or create a BeanHelper with the appropriate BeanFactory instance... > > > > I was thinking about such a hybrid approach, too. But then, giving users > > too many options and alternatives could be again confusing. > > > > Oliver > > > > > > > > just my 2 cents > > > Benedikt > > > > > > > > >> > > >> Oliver > > >> > > >>> > > >>> Phil > > >>>> > > >>>> Oliver > > >>>> > > >>>>> Phil > > >>>>>> For users, it may be more convenient to simply access > functionality > > >>>>>> through static methods, especially if the default values for > static > > >>>>>> member fields are reasonable for most use cases. However, such a > > >> design > > >>>>>> makes it impossible to use the represented functionality with > > >> different > > >>>>>> settings in parallel. > > >>>>>> > > >>>>>> Also, I am not sure whether complex class loader scenarios (e.g. > an > > >>>>>> application server or an OSGi container) may cause problems with > the > > >>>>>> static approach. > > >>>>>> > > >>>>>> Oliver > > >>>>>> > > >>>>>>>> On Sunday, August 25, 2013, Phil Steitz wrote: > > >>>>>>>> > > >>>>>>>>> On 8/24/13 11:33 AM, Oliver Heger wrote: > > >>>>>>>>>> Hi all, > > >>>>>>>>>> > > >>>>>>>>>> regarding a principle design question I would like to get your > > >> opinion: > > >>>>>>>>>> > > >>>>>>>>>> In [configuration] there are a few static utility classes. One > > of > > >> them > > >>>>>>>>>> is BeanHelper which supports the creation of beans from > > >> configuration > > >>>>>>>>>> data. The actual bean creation is done by a BeanFactory which > > can > > >> be > > >>>>>>>>>> configured using the static (currently unsynchronized) > > >>>>>>>>>> setDefaultBeanFactory() method. > > >>>>>>>>>> > > >>>>>>>>>> Sebb stated correctly that this approach is thread-hostile > [1]. > > An > > >>>>>>>>>> alternative could be to make BeanHelper a non-static class > which > > >> can be > > >>>>>>>>>> instantiated and configured per instance. This would be more > > >> flexible > > >>>>>>>>>> and would also simplify testing of client code (just pass in a > > >> mock > > >>>>>>>>>> object). The drawback is that clients now always would have to > > >>>>>>>>>> create an > > >>>>>>>>>> instance, so the API becomes slightly more verbose - in fact, > > most > > >>>>>>>>>> clients will probably never have the requirement to change the > > >> default > > >>>>>>>>>> bean factory. > > >>>>>>>>>> > > >>>>>>>>>> So, the question is, what do you prefer? The static approach > > like > > >>>>>>>>>> Object myBean = BeanHelper.createBean(...); > > >>>>>>>>>> > > >>>>>>>>>> or using an instance as in > > >>>>>>>>>> BeanHelper helper = new BeanHelper(myFactory); > > >>>>>>>>>> // or use no-args ctor for default factory > > >>>>>>>>>> Object myBean = helper.createBean(...); > > >>>>>>>>> Personally, I would like the static method better as a user. > > >>>>>>>>> Synchronizing access to the static factory field would seem to > > fix > > >>>>>>>>> the problem unless I am missing something. Also, I would not > > >> expect > > >>>>>>>>> lots of concurrent access to the getter/setter for this field > in > > >>>>>>>>> normal use cases , so the performance overhead of the sync > would > > be > > >>>>>>>>> immaterial. Having the setter there may also be a little > easier > > >> for > > >>>>>>>>> dependency injection. > > >>>>>>>>> > > >>>>>>>>> Phil > > >>>>>>>>>> TIA > > >>>>>>>>>> Oliver > > >>>>>>>>>> > > >>>>>>>>>> [1] https://issues.apache.org/jira/browse/CONFIGURATION-486 > > >>>>>>>>>> > > >>>>>>>>>> > > >> --------------------------------------------------------------------- > > >>>>>>>>>> To unsubscribe, e-mail: > > >>>>>>>>>> dev-unsubscribe@commons.apache.org > > >>>>>>>>>> For additional commands, e-mail: > > >>>>>>>>>> dev-help@commons.apache.org > > >>>>>>>>> > > >> --------------------------------------------------------------------- > > >>>>>>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org > > >>>>>>>>> > > >>>>>>>>> For additional commands, e-mail: > > >>>>>>>>> dev-help@commons.apache.org > > >>>>>>> > > >>>>>>> > > --------------------------------------------------------------------- > > >>>>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org > > >>>>>>> For additional commands, e-mail: dev-help@commons.apache.org > > >>>>>> > > >>>>>> > > --------------------------------------------------------------------- > > >>>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org > > >>>>>> For additional commands, e-mail: dev-help@commons.apache.org > > >>>>>> > > >>>>> > --------------------------------------------------------------------- > > >>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org > > >>>>> For additional commands, e-mail: dev-help@commons.apache.org > > >>>>> > > >>>> > > >>>> > --------------------------------------------------------------------- > > >>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org > > >>>> For additional commands, e-mail: dev-help@commons.apache.org > > >>>> > > >>>> > > >>> > > >>> > > >>> --------------------------------------------------------------------- > > >>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org > > >>> For additional commands, e-mail: dev-help@commons.apache.org > > >>> > > >> > > >> > > >> --------------------------------------------------------------------- > > >> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org > > >> For additional commands, e-mail: dev-help@commons.apache.org > > >> > > >> > > > > > > > > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org > > For additional commands, e-mail: dev-help@commons.apache.org > > > > > -- http://people.apache.org/~britter/ http://www.systemoutprintln.de/ http://twitter.com/BenediktRitter http://github.com/britter --001a11c369c2d1cf6804e51ae9d9--