On Thu, Sep 27, 2012 at 10:45 PM, Sven Meier <s...@meiers.net> wrote: >> this will make more advanced developer more unconfortable > > > I hear that ;). > > Jeremy gave a good suggestion: "set up some kind of code-check"
Well this is an option but again it makes more advanced developers not feeling comfortable. For example: recently I had to suppress such CheckStyle check for the usage of PageParameters#add() in our app because a colleague of mine earlier had a bug with getPageParameters().add() and use this parameters for the generation of a new Url. The side effect was that after that call the current page instance had few more parameters and this leaded to the bug. In my case I really wanted to use #add() because I wanted to add several values. A perfectly valid case. So now we have: https://issues.apache.org/jira/browse/WICKET-4774 Here is another suggestion for the archives :-) trait Advanced { self: Component => def setDefaultModel(model: IModel) { ... } .... } val myComponent = new Label(id, text) with Advanced myComponent.setDefaultModel(Model.of(advancedText)) without "with Advanced" you wont be able to see #setDefaultModel (assuming that it is removed from Component API) > > Sven > > > > On 09/27/2012 09:38 PM, Martin Grigorov wrote: >> >> On Thu, Sep 27, 2012 at 10:29 PM, Sven Meier <s...@meiers.net> wrote: >>>> >>>> lets take a concrete example of FormComponent ... your thinking we would >>>> have to make >>>> >>>> both setDefaultModel and setModel methods protected >>> >>> >>> Nope, I just ruminated about making setDefaultModel protected. >>> >>> >>>> a common subclass of FormComponent is FormComponentPanel which pretty >>>> much always distributes its model. >>> >>> >>> In my experience FormComponentPanels are often highly specialized >>> components >>> developed by senior developers. Perhaps there are a handful of these in a >>> project, most other cases are just nested panels. >>> >>> >>>> in the end, the developer has to know what the method >>>> does if they chose to call it. >>> >>> >>> Agreed. >>> >>> Just one little nitpick: In my scenario it's two developers, one who has >>> to >>> safeguard against another developer calling a method he isn't suppose to >>> call. >> >> I think Michael Mossman is in the same situation. >> And I understand what you see as an improvement that will protect the >> average developer. >> But I don't like that: >> - this change will lead to an inconsistent API - setDefaultModel() and >> seModel() are basically the same method. Just #setModel() has some >> help from the compiler >> - this will make more advanced developer more unconfortable - he has >> to extend the component just to make the method public to be able to >> use it for his needs. And sooner or later every average developer >> becomes advanced... >> >>> Sven >>> >>> >>> >>> On 09/27/2012 08:59 PM, Igor Vaynberg wrote: >>>> >>>> On Thu, Sep 27, 2012 at 10:49 AM, Sven Meier <s...@meiers.net> wrote: >>>>> >>>>> We're discussing the case where a component distributes its model to >>>>> its >>>>> children or behaviors. >>>>> For the component developer it's easier to assume that the model can't >>>>> be >>>>> changed without its consensus (i.e. by offering a generic #setModel()). >>>>> >>>>> Of course this can be handled perfectly by a coding guideline. I always >>>>> tell >>>>> people to *never* change a component's model. >>>>> I cannot count times where I'm called to a developer's IDE with him >>>>> having >>>>> absolutely no clue why something entered here doesn't display over >>>>> there: >>>>> In >>>>> many cases this is caused by setting models. >>>>> >>>>> But a protected #setDefaultModelObject() would make this explicit in >>>>> the >>>>> API. >>>> >>>> ok. lets start with a bit of history to have more context. >>>> setDefaultModel() only exists because of type-erasure. before wicket >>>> supported generics all components had a public setModel() method. so, >>>> one might say that having a public setModel() is "the wicket way" >>>> because it was there since 1.0. just to establish the baseline. >>>> >>>> lets take a concrete example of FormComponent. right now it has a >>>> public setModel() method, but by your thinking we would have to make >>>> both setDefaultModel and setModel methods protected, because we do not >>>> know that all FormComponents support changing the model. after all, a >>>> common subclass of FormComponent is FormComponentPanel which pretty >>>> much always distributes its model. so, we leave it to subclasses of >>>> FormComponent and FormComponentPanel to decide whether or not to >>>> override setModel() to make it public. >>>> >>>> a TextField would make its setModel() public - because it properly >>>> handles the usecase, correct? so it is still possible for your >>>> developers to call setModel() on a textfield and rewire it so it no >>>> longer links with a model of another component correctly. >>>> >>>> so we are now back to square one with the addition that a lot of >>>> components have to override setModel() just to change its visibility >>>> from protected to public - introducing a lot of noise. >>>> >>>> im all for making the code better, but i do not think that this change >>>> does. in the end, the developer has to know what the method does if >>>> they chose to call it. >>>> >>>> -igor >>>> >>>> >>>> >>>> >>>>> Sven >>>>> >>>>> >>>>> >>>>> On 09/27/2012 07:09 PM, Igor Vaynberg wrote: >>>>>> >>>>>> i thought the issue we were discussing here is the way the models are >>>>>> linked...which is not solved by making setdefaultmodelobject >>>>>> non-public. >>>>>> >>>>>> -igor >>>>>> >>>>>> On Thu, Sep 27, 2012 at 10:04 AM, Sven Meier <s...@meiers.net> wrote: >>>>>>> >>>>>>> If you extend GenericPanel you inherit setModel() and getModel(), >>>>>>> that's >>>>>>> the >>>>>>> whole purpose of this base class. >>>>>>> You want these two methods, otherwise you wouldn't extend it - >>>>>>> there's >>>>>>> nothing to fix. >>>>>>> >>>>>>> Component#setDefaultModel() is dangerous because it allows others to >>>>>>> tinker >>>>>>> with your component innards. >>>>>>> >>>>>>> I still think limiting access to #setDefaultModel() is a good idea, >>>>>>> but >>>>>>> this >>>>>>> is no crucial issue anyway. >>>>>>> >>>>>>> Sven >>>>>>> >>>>>>> >>>>>>> >>>>>>> On 09/27/2012 06:16 PM, Michael Mosmann wrote: >>>>>>>> >>>>>>>> Am 27.09.2012 17:51, schrieb Igor Vaynberg: >>>>>>>> >>>>>>>> good point.. >>>>>>>> -1 from me.. thought it was a good idea, but wasn’t >>>>>>>> >>>>>>>> Michael >>>>>>>> >>>>>>>>> so what happens if panel A extends GenericPanel which has setModel? >>>>>>>>> you havent fixed anything. >>>>>>>>> >>>>>>>>> -igor >>>>>>>>> >>>>>>>>> On Thu, Sep 27, 2012 at 8:50 AM, Michael Mosmann >>>>>>>>> <mich...@mosmann.de> >>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>> Am 27.09.2012 17:32, schrieb Igor Vaynberg: >>>>>>>>>> >>>>>>>>>> Hi, >>>>>>>>>> >>>>>>>>>> .. i would leave setModel as it is, only make this change for >>>>>>>>>> Component.setDefaultModel(). >>>>>>>>>> >>>>>>>>>> Michael >>>>>>>>>> >>>>>>>>>>> -1 on changing setDefaultModel(). >>>>>>>>>>> >>>>>>>>>>> 1) if B panel's model is truly dependent on A's then that >>>>>>>>>>> dependency >>>>>>>>>>> should be expressed: >>>>>>>>>>> >>>>>>>>>>> add(new BPanel("b", new PropertyModel(this, "defaultModel")); >>>>>>>>>>> >>>>>>>>>>> or do not use the default model slot of B to store the model. >>>>>>>>>>> that >>>>>>>>>>> way >>>>>>>>>>> setDefaultModel() calls on B will be a noop and you can choose >>>>>>>>>>> not >>>>>>>>>>> to >>>>>>>>>>> provide a setter. >>>>>>>>>>> >>>>>>>>>>> 2) you are only "solving" this for a subset of usecases where the >>>>>>>>>>> container (A) is not generic. are we also going to make >>>>>>>>>>> setModel(T) >>>>>>>>>>> protected? that would require the model assignment be done >>>>>>>>>>> through >>>>>>>>>>> the >>>>>>>>>>> constructor only and would eliminate any possibility of writing >>>>>>>>>>> builder-style code. consider a simple example: >>>>>>>>>>> >>>>>>>>>>> new DropDownChoice("foo").setModel(bar).setChoices(baz)... >>>>>>>>>>> >>>>>>>>>>> this kind of code should be possible whether written directly by >>>>>>>>>>> the >>>>>>>>>>> developer in the page or produced by some builder. >>>>>>>>>>> >>>>>>>>>>> -igor >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On Thu, Sep 27, 2012 at 5:19 AM, Sven Meier <s...@meiers.net> >>>>>>>>>>> wrote: >>>>>>>>>>>> >>>>>>>>>>>> Even a simpler example might fail (no PropertyModel involved): >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> class APanel extends Panel { >>>>>>>>>>>> APanel(String id, IModel<Some> model) { >>>>>>>>>>>> super(id,model); >>>>>>>>>>>> >>>>>>>>>>>> add(new BPanel("b", model); >>>>>>>>>>>> } >>>>>>>>>>>> } >>>>>>>>>>>> >>>>>>>>>>>> A client using APanel might later change the model, leaving >>>>>>>>>>>> BPanel >>>>>>>>>>>> working >>>>>>>>>>>> on the old model: >>>>>>>>>>>> aPanel.setDefaultModel(otherModel); >>>>>>>>>>>> >>>>>>>>>>>> You could argue that APanel should be made failsafe when passing >>>>>>>>>>>> the >>>>>>>>>>>> model: >>>>>>>>>>>> >>>>>>>>>>>> add(new BPanel("b", new PropertyModel(this, >>>>>>>>>>>> "defaultModel"))); >>>>>>>>>>>> >>>>>>>>>>>> But it would be much easier if APanel could assume that its >>>>>>>>>>>> model >>>>>>>>>>>> isn't >>>>>>>>>>>> changed unattendedly. >>>>>>>>>>>> >>>>>>>>>>>> IMHO changing a component's model isn't the "wicket way" so I'd >>>>>>>>>>>> suggest >>>>>>>>>>>> changing the visibility of Component#setDefaultModel() to >>>>>>>>>>>> protected. >>>>>>>>>>>> >>>>>>>>>>>> Sven >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 09/27/2012 10:47 AM, Martin Grigorov wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> I see. This is an advanced way to create a static model :-) >>>>>>>>>>>>> But again I find PropertyModel as the real problem here. >>>>>>>>>>>>> >>>>>>>>>>>>> I'll let others give their opinions too. >>>>>>>>>>>>> >>>>>>>>>>>>> On Thu, Sep 27, 2012 at 11:39 AM, Michael Mosmann >>>>>>>>>>>>> <mich...@mosmann.de> >>>>>>>>>>>>> wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>> Am 27.09.2012 09:51, schrieb Martin Grigorov: >>>>>>>>>>>>>> >>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>> >>>>>>>>>>>>>> a dont care about the type issue here.. Maybe i can explain it >>>>>>>>>>>>>> again >>>>>>>>>>>>>> in >>>>>>>>>>>>>> an >>>>>>>>>>>>>> other way: >>>>>>>>>>>>>> >>>>>>>>>>>>>> APanel uses model instance A and the label uses a property >>>>>>>>>>>>>> model >>>>>>>>>>>>>> instance >>>>>>>>>>>>>> P >>>>>>>>>>>>>> which uses a reference to model instance A. >>>>>>>>>>>>>> >>>>>>>>>>>>>> After calling APanel.setDefaultModel(B) APanel uses model >>>>>>>>>>>>>> instance >>>>>>>>>>>>>> B,but >>>>>>>>>>>>>> label uses model instance P which uses model instance A as >>>>>>>>>>>>>> before. >>>>>>>>>>>>>> So >>>>>>>>>>>>>> the >>>>>>>>>>>>>> label does not see any changes, because no one tells the model >>>>>>>>>>>>>> instance >>>>>>>>>>>>>> P, >>>>>>>>>>>>>> that it should use B instead of A. I think, there are rare >>>>>>>>>>>>>> cases >>>>>>>>>>>>>> for >>>>>>>>>>>>>> such >>>>>>>>>>>>>> a >>>>>>>>>>>>>> usage. >>>>>>>>>>>>>> >>>>>>>>>>>>>> thanks >>>>>>>>>>>>>> Michael >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> In this particular code I think the "problem" is >>>>>>>>>>>>>>> PropertyModel, >>>>>>>>>>>>>>> since >>>>>>>>>>>>>>> it brings the type unsafety. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Another solution is to make Component<T>, this way we can >>>>>>>>>>>>>>> remove >>>>>>>>>>>>>>> #setDefaultModel() and have #setModel(IModel<T>) only and >>>>>>>>>>>>>>> such >>>>>>>>>>>>>>> problems will go away. >>>>>>>>>>>>>>> But as discussed in early Wicket 1.4 days this will lead to >>>>>>>>>>>>>>> more >>>>>>>>>>>>>>> typing. With Java 7 diamonds it is half the typing though. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> For now you can use GenericPanel, GenericPage and all >>>>>>>>>>>>>>> FormComponent. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On Thu, Sep 27, 2012 at 10:41 AM, Michael Mosmann >>>>>>>>>>>>>>> <mich...@mosmann.de> >>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Am 27.09.2012 09:01, schrieb Martin Grigorov: >>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I think, there is a little difference in using >>>>>>>>>>>>>>>> setDefaultModel >>>>>>>>>>>>>>>> and >>>>>>>>>>>>>>>> setDefaultModelObject .. the first one sets a new model >>>>>>>>>>>>>>>> instance, >>>>>>>>>>>>>>>> the >>>>>>>>>>>>>>>> second >>>>>>>>>>>>>>>> only change the value in the existing model. Some >>>>>>>>>>>>>>>> pseudo-code: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> class APanel extends Panel { >>>>>>>>>>>>>>>> APanel(String id,IModel<Some> model) { >>>>>>>>>>>>>>>> super(id,model); >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> add(new Label("name",new >>>>>>>>>>>>>>>> PropertyModel(getDefaultModel(),"name")); >>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> If you replace the value in model, everything is fine and >>>>>>>>>>>>>>>> works >>>>>>>>>>>>>>>> as >>>>>>>>>>>>>>>> expected. >>>>>>>>>>>>>>>> If you call setDefaultModel you might think, that everything >>>>>>>>>>>>>>>> is >>>>>>>>>>>>>>>> fine, >>>>>>>>>>>>>>>> but >>>>>>>>>>>>>>>> its not. A child component does not use >>>>>>>>>>>>>>>> getParent().getDefaultModel() >>>>>>>>>>>>>>>> to >>>>>>>>>>>>>>>> get >>>>>>>>>>>>>>>> these changes. I saw a lot of code like this, which leads to >>>>>>>>>>>>>>>> trouble, >>>>>>>>>>>>>>>> if >>>>>>>>>>>>>>>> you >>>>>>>>>>>>>>>> change the model and not the value. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> If there is no benefit in using setDefaultModel over >>>>>>>>>>>>>>>> setDefaultModelObject i >>>>>>>>>>>>>>>> would like to remove this method. This could prevent many >>>>>>>>>>>>>>>> "you >>>>>>>>>>>>>>>> might >>>>>>>>>>>>>>>> not >>>>>>>>>>>>>>>> got >>>>>>>>>>>>>>>> the full picture how to use wicket the right way" errors. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Michael >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Most of the time it is recommended to use a dynamic model, >>>>>>>>>>>>>>>>> so >>>>>>>>>>>>>>>>> there >>>>>>>>>>>>>>>>> is >>>>>>>>>>>>>>>>> no reason to replace the component's model. >>>>>>>>>>>>>>>>> Component#setDefaultModel() gives you semi-dynamic nature - >>>>>>>>>>>>>>>>> you >>>>>>>>>>>>>>>>> can >>>>>>>>>>>>>>>>> replace the model completely with a new one. Same with >>>>>>>>>>>>>>>>> #setDefaultModelObject(). >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> What is the problem you face with it ? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On Thu, Sep 27, 2012 at 9:57 AM, Michael Mosmann >>>>>>>>>>>>>>>>> <mich...@mosmann.de> >>>>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> is there any usefull application of >>>>>>>>>>>>>>>>>> Component.setDefaultModel(...)? >>>>>>>>>>>>>>>>>> IMHO >>>>>>>>>>>>>>>>>> this Method is the cause for much trouble without any >>>>>>>>>>>>>>>>>> benefit. >>>>>>>>>>>>>>>>>> But >>>>>>>>>>>>>>>>>> maybe >>>>>>>>>>>>>>>>>> i >>>>>>>>>>>>>>>>>> did not understand when someone should replace a component >>>>>>>>>>>>>>>>>> model... >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> thanks >>>>>>>>>>>>>>>>>> Michael >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >> >> > -- Martin Grigorov jWeekend Training, Consulting, Development http://jWeekend.com