You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by iberck <ib...@gmail.com> on 2014/02/06 19:05:04 UTC

inheritance to composition design in components

hi all, how can I transform the next example from inheritance design to
composition design ?

ParentComponent.tml:
<container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
xmlns:p="tapestry:parameter"
t:content="text/html; charset=utf-8">
    this is parent component<br/>

    <extension-point id="body_child"/>
</container>


ParentComponent.java:
public abstract class ParentComponent {

    @Property
    @Parameter(required=true)
    private String param1;
    @Property
    @Parameter(required=true)
    private String param2;
    @Property
    @Parameter(required=true)
    private String param3;

}

C1.tml
<t:extend xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
xmlns:p="tapestry:parameter" t:content="text/html; charset=utf-8">
    <t:replace id="body_child">
        body of c1 ${param1}, ${param2}, ${param3}
    </t:replace>
</t:extend>

C1.java
public class C1 extends ParentComponent {
}

test.tml:
...
<t:c1 param1="1" param2="2" param3="3"/>
...

Thanks in advance.

Re: inheritance to composition design in components

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Fri, 07 Feb 2014 14:10:43 -0200, iberck <ib...@gmail.com> wrote:

> Hi Thiago, thank you very much by your answer.

Hi!

> The scenario is the next:
> I have to create a page to show a survey, so in my model I have some  
> clases:
>
> ---------------------------------------------------------------
> Survey
>     + List<Question> questions
>
> Question
>
> QuestionText extends Question
>
> QuestionRating extends Question
>
> QuestionOptions extends Question

So a question can be text, rating or (multiple) options?

> So, I need to display each Question to be answered by the user.
> With tapestry I think I have to create a component for each question type

No, the framework doesn't oblige you to do that. You can have a single  
component if you want. You can have one for each type. You choose.

In this case, as you have a small number of different question types, I'd  
write a single component and just use some If's which use the question  
type as the test (isText(), isRating(), isOptions()) for the parts which  
are specific to a given question type.

Your solution in the previous message would be good too, although I think  
it's more complex than you need for the scenario described above, but  
still perfectly valid.

-- 
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: inheritance to composition design in components

Posted by iberck <ib...@gmail.com>.
Hi Thiago, thank you very much by your answer.

The scenario is the next:
I have to create a page to show a survey, so in my model I have some clases:

---------------------------------------------------------------
Survey
    + List<Question> questions

Question

QuestionText extends Question

QuestionRating extends Question

QuestionOptions extends Question
...
---------------------------------------------------------------

So, I need to display each Question to be answered by the user.
With tapestry I think I have to create a component for each question type
and then create a component for decide what component display when I want
to show a survey.

For example, I have a survey with 3 question text, so I have to loop the
survey's questions for display each one like this:

-------------------------------------
question text 1
[text field]
-------------------------------------

-------------------------------------
question text 2
[text field]
-------------------------------------

-------------------------------------
question text 3
[text field]
-------------------------------------

How can I design that scenario with Tapestry?

I appreciate your help, thank you for your time reading the post.




On Thu, Feb 6, 2014 at 4:08 PM, Thiago H de Paula Figueiredo <
thiagohp@gmail.com> wrote:

> On Thu, 06 Feb 2014 18:57:24 -0200, iberck <ib...@gmail.com> wrote:
>
>  Thank you for your answer Thiago.
>>
>
> ;)
>
>
>  I have to create multiple c1,c2,c3,c4,c5,c6,c7,c8,c9 child components of
>> parentcomponent so I prefer to put the logic inside each component and
>> then decide which component use with a separate component:
>>
>
> I have no idea what scenario you're describing now I understand what you
> wrote, to be sincere. And I guess it's not much related to the scenario in
> the original post of this thread.
>
>
>  ComponentCase.tml:
>> <t:delegate to="block"/>
>>
>> <t:block id="c1">
>>     <t:c1 param1="${param1}" param2="${param2}" param3="${param3}"/>
>> </t:block>
>>
>
> For the love of everything which is sacred for you, never, never, ever use
> ${} expansions when passing parameters*. In 100% of the cases, it's useless
> (when the parameter type value is a string) or completely wrong and causes
> an error (when it isn't).
>
> [*]: According to http://apache-tapestry-mailing-list-archives.1045711.
> n5.nabble.com/template/NamlServlet.jtp?macro=search_
> page&node=2375124&query=never%2C+never+ever+expansion&n=2375124, I've
> said this 47 times already. It seems it wasn't enough, so the 48th is in
> this message! :D
>
>
>  What kind of design is better implemented in this case?
>>
>
> It depends on the case. This thread described just very vague scenarios. I
> don't even know why would you need so many component subclasses (the c1,
> c2, cn you described above). You either have a very weird requirement or a
> very bad way of doing code reuse.
>
>
> --
> Thiago H. de Paula Figueiredo
> Tapestry, Java and Hibernate consultant and developer
> http://machina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

Re: inheritance to composition design in components

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Thu, 06 Feb 2014 18:57:24 -0200, iberck <ib...@gmail.com> wrote:

> Thank you for your answer Thiago.

;)

> I have to create multiple c1,c2,c3,c4,c5,c6,c7,c8,c9 child components of
> parentcomponent so I prefer to put the logic inside each component and  
> then decide which component use with a separate component:

I have no idea what scenario you're describing now I understand what you  
wrote, to be sincere. And I guess it's not much related to the scenario in  
the original post of this thread.

> ComponentCase.tml:
> <t:delegate to="block"/>
>
> <t:block id="c1">
>     <t:c1 param1="${param1}" param2="${param2}" param3="${param3}"/>
> </t:block>

For the love of everything which is sacred for you, never, never, ever use  
${} expansions when passing parameters*. In 100% of the cases, it's  
useless (when the parameter type value is a string) or completely wrong  
and causes an error (when it isn't).

[*]: According to  
http://apache-tapestry-mailing-list-archives.1045711.n5.nabble.com/template/NamlServlet.jtp?macro=search_page&node=2375124&query=never%2C+never+ever+expansion&n=2375124,  
I've said this 47 times already. It seems it wasn't enough, so the 48th is  
in this message! :D

> What kind of design is better implemented in this case?

It depends on the case. This thread described just very vague scenarios. I  
don't even know why would you need so many component subclasses (the c1,  
c2, cn you described above). You either have a very weird requirement or a  
very bad way of doing code reuse.

-- 
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: inheritance to composition design in components

Posted by iberck <ib...@gmail.com>.
Thank you for your answer Thiago.

I have to create multiple c1,c2,c3,c4,c5,c6,c7,c8,c9 child components of
parentcomponent so I prefer to put the logic inside each component and then
decide which component use with a separate component:

ComponentCase.tml:
<t:delegate to="block"/>

<t:block id="c1">
    <t:c1 param1="${param1}" param2="${param2}" param3="${param3}"/>
</t:block>

...

<t:block id="c9">
    <t:c9 param1="${param1}" param2="${param2}" param3="${param3}"/>
</t:block>

ComponentCase.java:
public class ComponentCase {
    @Parameter(required=true)
    @Property
     private String param1;

     @Parameter(required=true)
     @Property
     private String param2;

     @Parameter(required=true)
     @Property
     private String param3;

    @Inject
    private Block c1;
    ...
    @Inject
    private Block c9;

    public Block getBlock() {
        switch (pseudo type) {
            case 1:
                return c1;
                ...
            case 2:
                return c2;
    }
}

Test.tml
<t:componentCase param1="1" param2="2" param3="3"/>


What kind of design is better implemented in this case?

Thanks in advance.


On Thu, Feb 6, 2014 at 1:13 PM, Thiago H de Paula Figueiredo <
thiagohp@gmail.com> wrote:

> On Thu, 06 Feb 2014 16:05:04 -0200, iberck <ib...@gmail.com> wrote:
>
>  hi all,
>>
>
> Hi!
>
>
>  how can I transform the next example from inheritance design to
>> composition design ?
>>
>
> You don't even need to have two different components to have a component
> which can have a part of its template replaced:
>
> ParentComponent.tml:
> <t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
>
>  xmlns:p="tapestry:parameter" t:content="text/html; charset=utf-8">
>         this is parent component<br/>
>         <t:delegate to="prop:blockToRender"/>
>         <t:block id="defaultBlock">default stuff.</t:block>
> </t:container>
>
> ParentComponent.java:
> @SupportsInformalParameters
> public class ParentComponent {
>
>      @Parameter(required=true)
>      private String param1;
>
>      @Parameter(required=true)
>      private String param2;
>
>      @Parameter(required=true)
>      private String param3;
>
>      @Parameter(required=true, value="block:defaultBlock")
>      private Block blockToRender;
>
>      @Inject
>      @Property
>      private Block defaultBlock;
>
>      // getters for parameters
>
>  }
>
> When using the component above:
>
> <t:block id="myBlock">
> <t:ParentComponent blockToRender="block:myBlock"/>
>
> --
> Thiago H. de Paula Figueiredo
> Tapestry, Java and Hibernate consultant and developer
> http://machina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

Re: inheritance to composition design in components

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Thu, 06 Feb 2014 16:05:04 -0200, iberck <ib...@gmail.com> wrote:

> hi all,

Hi!

> how can I transform the next example from inheritance design to
> composition design ?

You don't even need to have two different components to have a component  
which can have a part of its template replaced:

ParentComponent.tml:
<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
  xmlns:p="tapestry:parameter" t:content="text/html; charset=utf-8">
	this is parent component<br/>
	<t:delegate to="prop:blockToRender"/>
	<t:block id="defaultBlock">default stuff.</t:block>
</t:container>

ParentComponent.java:
@SupportsInformalParameters
public class ParentComponent {

      @Parameter(required=true)
      private String param1;

      @Parameter(required=true)
      private String param2;

      @Parameter(required=true)
      private String param3;

      @Parameter(required=true, value="block:defaultBlock")
      private Block blockToRender;

      @Inject
      @Property
      private Block defaultBlock;

      // getters for parameters

  }

When using the component above:

<t:block id="myBlock">
<t:ParentComponent blockToRender="block:myBlock"/>

-- 
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org