Re: Proposal to move @FunctionalInteface from IModel
I also am not convinced of splitting out a read only thing. Standards change and you can now create a modifiable div in markup with content editable. If Java were a good composable language enabling composite oriented programming (see e.g. https://polygene.apache.org) then I would be tempted to rewrite our most core interfaces. But Java isn't and isn't going to be in the near future. I don't think semantic correctness is achievable nor important after 8 major versions of Wicket. Wicket components can't make promises about their models usage due to our compound models. A model set on a page or webmarkupcontainer can be cascaded to a textfield or any other modifying component. There are many things we could improve to make Wicket more semantically correct, but that doesn't mean we should. If anything history has taught me (e.g. Wicket 2) is dat we need gradual improvements not revolutions. We have to live with design decisions made 13 years ago because we (i.e. the whole Wicket community) have hundreds of millions of lines of code depending on those decisions (my own department of our company has roughly 4 million lines already). There are many things that can be improved upon but the Model - Component - Behavior design was pretty well thought out and designed to be flexible, efficient and not be a straight jacket. Martijn On Tue, Apr 11, 2017 at 4:48 AM, Pedro Santoswrote: > Hi Andrea, > > thx for the reference. Michael's proposal is awesome and I'm I think we > should go for a better model interface hierarchy. But this proposal, of an > IReadyOnlyModel as an IModel extension, wasn't discussed. My point is that > we can provide an interface "designed" to provide a function as a model and > have a little impact on existent Wicket projects at the same time. Just to > be clear, I'm 1+ for Michael's proposal, but if don't pass, I would be 1+ > for this proposal. > > Hi Emond, > >> Your proposal will not work because Java does not resolve functional >> interfaces to subtypes of the target type. For example, take the Label >> constructor: > > I know, and that is just a good thing. Take TextField for example, we don't > want it constructed with a function as a model: > > new TextField("id", Bean::getMethod()) > > this proposal is correctly preventing the user from assigning a read-only > model to a component designed to write on it. > >> In Wicket 8 this works, because IModel is a functional interface, so Java >> knows how to convert a method taking no arguments and returning a double > into >> a IModel by mapping that method to getObject(). > > Sure, and it's our job to provide good a API allowing the user to benefit > from Java 8 features *where it does make sense*. A good set of constructors > for a Label would include: > > public Label(String id, IReadyOnlyModel model){ ... } > > Cheers > > Pedro Santos > > On Mon, Apr 10, 2017 at 3:27 AM, Emond Papegaaij > wrote: > >> Hi Pedro, >> >> Your proposal will not work because Java does not resolve functional >> interfaces to subtypes of the target type. For example, take the Label >> constructor: >> >> public Label(String id, IModel model) >> >> I would like to use this constructor as follows: >> >> new Label("id", Math::random) >> >> In Wicket 8 this works, because IModel is a functional interface, so Java >> knows how to convert a method taking no arguments and returning a double >> into >> a IModel by mapping that method to getObject(). >> >> With your proposal, this code needs to be changed to: >> >> new Label("id", (IReadOnlyModel) Math::random) >> >> So time ago, we tried to make IModel extend a ReadOnlyModel. In that case, >> it >> would work, but the change did not work out very well. >> >> Best regards, >> Emond >> >> On vrijdag 7 april 2017 12:45:53 CEST Pedro Santos wrote: >> > Hi devs, >> > >> > IModel isn't an interface designed to provide a function, it's rather an >> > interface designed to provide and manipulate (setObject and detach >> methods) >> > internal state. >> > >> > IMO a better alternative to benefit from Java 8 features would be to move >> > the FunctionalInterface annotation to an interface that actually is >> > designed to provide one function. >> > >> > I propose that we add a new interface extending IModel to provide this >> > functional interface, instead of to misplace it in an interface made for >> > objects with internal state. >> > >> > e.g. >> > >> > @FunctionalInterface >> > interface IReadyOnlyModel / IModelFunction / IFunction extends from >> IModel{ >> > >> > default void setObject(final T object) >> > { >> > throw new UnsupportedOperationException("unsuported"); >> > } >> > >> > default void detach() >> > { >> > throw new UnsupportedOperationException("unsuported"); >> > } >> > >> > } >> > >> > Cheers >> > >> > Pedro Santos >> >> >> -- Become a Wicket expert, learn from the best: http://wicketinaction.com
Re: Proposal to move @FunctionalInteface from IModel
On maandag 10 april 2017 23:48:27 CEST Pedro Santos wrote: > Hi Emond, > > > Your proposal will not work because Java does not resolve functional > > interfaces to subtypes of the target type. For example, take the Label > > constructor: > I know, and that is just a good thing. Take TextField for example, we don't > want it constructed with a function as a model: > > new TextField("id", Bean::getMethod()) > > this proposal is correctly preventing the user from assigning a read-only > model to a component designed to write on it. Your solution does not prevent this. Your IReadOnlyModel is a subinterface of IModel. Therefore it is perfectly fine to pass a IReadOnlyModel to the constructor of TextField. In your example, you will need to add a cast or assign it to a variable first: IReadOnlyModel model = Bean::getMethod; new TextField<>("id", model); Also, I think this should be allowed. A disabled TextField provides a read- only view of its model. There are a few read-only usecases in Wicket though: for example ListView and the choices in a dropdown select. > > In Wicket 8 this works, because IModel is a functional interface, so Java > > knows how to convert a method taking no arguments and returning a double > > into a IModel by mapping that method to getObject(). > > Sure, and it's our job to provide good a API allowing the user to benefit > from Java 8 features *where it does make sense*. A good set of constructors > for a Label would include: > > public Label(String id, IReadyOnlyModel model){ ... } This would require adding additional constructors to all classes that must support read-only models. You cannot replace the constructors, because it is perfectly fine to construct a label with a read-write model. The problem is that the is-a relation for IReadOnlyModel is defined wrongly: a read-write model is a read-only model (a read-write model provides all the capabilities of a read-only model and more). To get this right, IModel needs to be split into 2 super-interfaces: IReadOnlyModel and IWriteOnlyModel, both extending IDetachable. IModel then is simply a combination of IReadOnlyModel and IWriteOnlyModel. Both super-models can be functional interfaces and perhaps we can even support split models on components: new TextField<>("id", Bean::getMethod, Bean::setMethod); The problem however is "default model". For this to work, we need to drop the components default model, because you cannot know if it is IReadOnlyModel, IWriteOnlyModel or IModel. This includes CompoundPropertyModel. But this breaks the API of Wicket bigtime and the gain turned out the be very small. Best regards, Emond
Re: Proposal to move @FunctionalInteface from IModel
Hi Andrea, thx for the reference. Michael's proposal is awesome and I'm I think we should go for a better model interface hierarchy. But this proposal, of an IReadyOnlyModel as an IModel extension, wasn't discussed. My point is that we can provide an interface "designed" to provide a function as a model and have a little impact on existent Wicket projects at the same time. Just to be clear, I'm 1+ for Michael's proposal, but if don't pass, I would be 1+ for this proposal. Hi Emond, > Your proposal will not work because Java does not resolve functional > interfaces to subtypes of the target type. For example, take the Label > constructor: I know, and that is just a good thing. Take TextField for example, we don't want it constructed with a function as a model: new TextField("id", Bean::getMethod()) this proposal is correctly preventing the user from assigning a read-only model to a component designed to write on it. > In Wicket 8 this works, because IModel is a functional interface, so Java > knows how to convert a method taking no arguments and returning a double into > a IModel by mapping that method to getObject(). Sure, and it's our job to provide good a API allowing the user to benefit from Java 8 features *where it does make sense*. A good set of constructors for a Label would include: public Label(String id, IReadyOnlyModel model){ ... } Cheers Pedro Santos On Mon, Apr 10, 2017 at 3:27 AM, Emond Papegaaijwrote: > Hi Pedro, > > Your proposal will not work because Java does not resolve functional > interfaces to subtypes of the target type. For example, take the Label > constructor: > > public Label(String id, IModel model) > > I would like to use this constructor as follows: > > new Label("id", Math::random) > > In Wicket 8 this works, because IModel is a functional interface, so Java > knows how to convert a method taking no arguments and returning a double > into > a IModel by mapping that method to getObject(). > > With your proposal, this code needs to be changed to: > > new Label("id", (IReadOnlyModel) Math::random) > > So time ago, we tried to make IModel extend a ReadOnlyModel. In that case, > it > would work, but the change did not work out very well. > > Best regards, > Emond > > On vrijdag 7 april 2017 12:45:53 CEST Pedro Santos wrote: > > Hi devs, > > > > IModel isn't an interface designed to provide a function, it's rather an > > interface designed to provide and manipulate (setObject and detach > methods) > > internal state. > > > > IMO a better alternative to benefit from Java 8 features would be to move > > the FunctionalInterface annotation to an interface that actually is > > designed to provide one function. > > > > I propose that we add a new interface extending IModel to provide this > > functional interface, instead of to misplace it in an interface made for > > objects with internal state. > > > > e.g. > > > > @FunctionalInterface > > interface IReadyOnlyModel / IModelFunction / IFunction extends from > IModel{ > > > > default void setObject(final T object) > > { > > throw new UnsupportedOperationException("unsuported"); > > } > > > > default void detach() > > { > > throw new UnsupportedOperationException("unsuported"); > > } > > > > } > > > > Cheers > > > > Pedro Santos > > >
Re: Proposal to move @FunctionalInteface from IModel
Hi Pedro, Your proposal will not work because Java does not resolve functional interfaces to subtypes of the target type. For example, take the Label constructor: public Label(String id, IModel model) I would like to use this constructor as follows: new Label("id", Math::random) In Wicket 8 this works, because IModel is a functional interface, so Java knows how to convert a method taking no arguments and returning a double into a IModel by mapping that method to getObject(). With your proposal, this code needs to be changed to: new Label("id", (IReadOnlyModel) Math::random) So time ago, we tried to make IModel extend a ReadOnlyModel. In that case, it would work, but the change did not work out very well. Best regards, Emond On vrijdag 7 april 2017 12:45:53 CEST Pedro Santos wrote: > Hi devs, > > IModel isn't an interface designed to provide a function, it's rather an > interface designed to provide and manipulate (setObject and detach methods) > internal state. > > IMO a better alternative to benefit from Java 8 features would be to move > the FunctionalInterface annotation to an interface that actually is > designed to provide one function. > > I propose that we add a new interface extending IModel to provide this > functional interface, instead of to misplace it in an interface made for > objects with internal state. > > e.g. > > @FunctionalInterface > interface IReadyOnlyModel / IModelFunction / IFunction extends from IModel{ > > default void setObject(final T object) > { > throw new UnsupportedOperationException("unsuported"); > } > > default void detach() > { > throw new UnsupportedOperationException("unsuported"); > } > > } > > Cheers > > Pedro Santos
Re: Proposal to move @FunctionalInteface from IModel
Hi Pedro, I think we had a similar discussion some time ago: http://wicket-dev.markmail.org/message/vzdggjv5csmpzfrl?q=change+IModel+to+readonly+by+default We simply agreed to use IModel as a default read-only model. IMHO this is a good solution. Cheers. Andrea. On 07/04/2017 17:45, Pedro Santos wrote: Hi devs, IModel isn't an interface designed to provide a function, it's rather an interface designed to provide and manipulate (setObject and detach methods) internal state. IMO a better alternative to benefit from Java 8 features would be to move the FunctionalInterface annotation to an interface that actually is designed to provide one function. I propose that we add a new interface extending IModel to provide this functional interface, instead of to misplace it in an interface made for objects with internal state. e.g. @FunctionalInterface interface IReadyOnlyModel / IModelFunction / IFunction extends from IModel{ default void setObject(final T object) { throw new UnsupportedOperationException("unsuported"); } default void detach() { throw new UnsupportedOperationException("unsuported"); } } Cheers Pedro Santos
Proposal to move @FunctionalInteface from IModel
Hi devs, IModel isn't an interface designed to provide a function, it's rather an interface designed to provide and manipulate (setObject and detach methods) internal state. IMO a better alternative to benefit from Java 8 features would be to move the FunctionalInterface annotation to an interface that actually is designed to provide one function. I propose that we add a new interface extending IModel to provide this functional interface, instead of to misplace it in an interface made for objects with internal state. e.g. @FunctionalInterface interface IReadyOnlyModel / IModelFunction / IFunction extends from IModel{ default void setObject(final T object) { throw new UnsupportedOperationException("unsuported"); } default void detach() { throw new UnsupportedOperationException("unsuported"); } } Cheers Pedro Santos