On Tue, Mar 8, 2011 at 11:22 PM, Maarten Billemont <lhun...@gmail.com> wrote:
>>>>
>>>> Just like EJBs, you should be careful about how much interaction you do 
>>>> beyond your object's scope within the constructor.  Your component doesn't 
>>>> have a hierarchy, getPage() cannot be accessed, none of your subclass 
>>>> constructors have been invoked and therefore your instance is not properly 
>>>> initialized and ready for use.
>>> not really sure what you mean by subclass constructors or how they
>>> come into play when constructing an instance...
>> If I understand correctly, here is an example of what he means :
>
>
> Exactly.  If B extends A and I do something in A's constructor that goes 
> beyond the scope of setting up A's instance variables, then I risk a 
> side-effect that relies on the instance to be constructed at B's level as 
> well.  There's nothing in the JVM that prevents this and these bugs are very 
> hard to see and debug.  They should be avoided by good coding practices.

yep, calling overridable methods from constructors is bad - you just
made the case for making page.oninitialize() final...

>
> On 08 Mar 2011, at 22:07, Igor Vaynberg wrote:
>>
>> i think code like this should be possible:
>>
>> NameEditor e=new NameEditor("name", firstNameModel, lastNameModel);
>> e.getFirstNameEditor().setRequired(true);
>> e.getLastNameEditor().setEnabled(false);
>
>> taking the previous example of a name editor, with constructor we have:
>>
>> class nameeditor extends panel {
>>  public nameeditor(...) {
>>     add(new textfield("first",..);
>>     add(new textifled("last", ...);
>>  }
>>  public textfield getfirst() { return get("first"); }
>>  public textfield getlast() { return get("last"); }
>> }
>
> Firstly, it's my opinion that you really shouldn't be doing anything to 
> components directly, especially not from outside your class.  As for why, see 
> Encapsulation and Law of Demeter.

neither of the two apply because nameeditor explicitly exposes the two
components as part of its contract via public getters.

> But if you really wanted to use this pattern, it really wouldn't have to be 
> as cumbersome as you make it out to be.  Also, I really don't like condoning 
> get(String), it's nasty and very type-unfriendly.  It also breaks as soon as 
> you do any refactoring in your component hierarchy.

yes, i traded off some refactorability for better memory footprint.
imho a perfectly valid trade off when memory and space are costly.

> class NameEditor extends Panel {
>    TextField<String> firstField;
>    TextField<String> lastField;
>    @Override protected void onInitialize() { super.onInitialize(); 
> add(getFirst(), getLast()); }
>    public textfield getFirst() { if (firstField == null) firstField = new 
> TextField<String>(); return firstField; }
>    public textfield getLast() { if (lastField == null) lastField = new 
> TextField<String>(); return lastField; }
> }

there are still problems with this:
*you still have the two extra memory slots that are a complete waste
here - component references
*the lazy init code is cumbersome to write
*you are missing the two slots needed to pass models from constructor
to the two textfields - so thats four extra slots total that you have
now forced on users
* the components i get from the getters are not added to their parent
- for more complex components that need access to their markup this is
a problem, eg if
("text".equals(getFirst().getMarkupTag().get("type")).......not
necessarily a good example taking this particular custom component as
context, but a valid usecase in plenty of other situations.

-igor


> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org
> For additional commands, e-mail: users-h...@wicket.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org
For additional commands, e-mail: users-h...@wicket.apache.org

Reply via email to