Re: extending IUIBase with interfaces (was: Re: Version property (was: Let's bump Royale version to 1.0))
Hi Carlos, I've said this before: I feel bad sometimes that Flex taught folks some questionable programming practices. The short answer: -Don't reference concrete classes -Choose composition patterns over inheritance The long answer: Yishay and Andrew are headed in the right direction. A good goal for Royale is to try to avoid references to concrete classes (other than what your class subclasses). Referencing concrete classes essentially breaks PAYG by creating an unreplaceable chain of dependencies. Flex referenced too many concrete classes and we all paid for it. But addition to using interfaces, we should try to remember that Royale is more about composition than inheritance. Beads are composed into instances to implement functionality. Hopefully, many beads can be re-used on other instances with different base class ancestry if the API surfaces are designed correctly. And, not only are beads best referenced via their interfaces, you can also ask "has" instead of "is". IOW, you can ask if an instance "has" a bead instead of just testing if the instance "is" (implements) an interface. The first word in PAYG is Pay. PAYG is not Free-AYG. Somebody has to pay. The more features you use, the more you pay in download size and performance, especially at startup. The point of PAYG and beads is to enable optimization. If you want to make cookies and you buy each ingredient separately it will take up more space and weight because of the packaging as opposed to buying one bag of ready-to-bake cookie mix. But the point of having separate ingredients is so you can replace white flour with whole wheat or rye or gluten-free easily. If it turns out there is significant overhead in some set of beads, you can choose to inline them, just like any other inlining optimization. That is a manual process today. Inlining is effectively copying code, so it sounds like that is what you are doing today. But the copying of code should only be a last resort after proving that the composition patterns have too much overhead. The inlining will have its own overhead, usually in download size, as you mentioned. I explained the "exploded component" concept a while back. It attempts to illustrate composition by showing how, in MXML, a component can really be declared as its beads. For example: Could be written more verbosely as: Then a ToggleButton could be implemented by simply replacing the controller (and probably the view). So it is only for convenience, so you don't have to type all of these tags, that we create a top-level component (TLC) called Button that pre-packages some set of beads and write glue code that proxies some of the bead APIs to the TLC's API such as: public class Button extends UIBase { public function set label(value:String):void { model.label = value; } } The point, relative to this topic, is there is a cost to this convenience, which is the line or two of glue code. So, with beads, it is only for convenience that the TLC implements these PAYG interfaces. If you package up the implementation of IClassSelectorListSupport into a bead, that bead should be able to be composed into different classes with different base classes. We actually have a choice of whether to add the glue code that proxies that implementation to the API surface. If you do that proxying, then other code can look like: if (myInstance is IClassSelectorListSupport) (myInstance as IClassSelectorListSupport).someAPi = "foo"; But the other option is the "has" pattern, which looks like: Var foo:IClassSelectorListSupport = myInstance.getBeadByType(IClassSelectorListSupport); If (foo) foo.someAPI = "foo"; I've not done any measuring of which is better, but the latter does not require glue code, which allows someone to just drop in any IClassSelectorListSupport bead on some other random instance they've created and not make any assumptions about base classes or proxy code to interfaces. For example: This instance, declared in MXML without the overhead of creating a TLC and proxying code to the API surface, would work with the "has" code, but not the "is" code. Is it all worth it? I don't know. I'm waiting to see folks try it, especially in more complex apps. But for sure, composition "has" patterns are more flexible than traditional "is" patterns. This "has" pattern allows us to sort of have multiple inheritance or "mixin" type patterns, but it is done by accessing the beads directly not by proxying code to the TLC so "inheritance" isn't an accurate word. TLCs are more for convenience, to avoid repeating a lot of tags in MXML or calling addBead a lot, but we should try to make our code even more flexible by not requiring folks to work with TLCs. So, in theory, you should try to package the implementation of IClassSelectorListSupport into a bead and see if you run into
Re: extending IUIBase with interfaces (was: Re: Version property (was: Let's bump Royale version to 1.0))
Hi Yishay, El mar., 30 abr. 2019 a las 13:27, Yishay Weiss () escribió: > It seems to me this is more an AS3 issue than a Royale issue. It would be > cool to enhance AS to include features such as Mixins, but as long as we > have a simple single inheritance model the solution you implemented is > probably optimal. > > If you and others think is the best we can get, maybe we can left as is. Maybe we can just optimize as Andrew said making that a class to be implemented by the rest of classes, in that way all share that and changing just one class will change the 3 implementors at once... > Also, in my opinion you should always check to see if a said object > implements an interface, rather than extends a class. If you stick to that > your solution works fine. > > the problem with this is what I stated before. I expect users to use UIBase/StyledUIBase classes instead or interface in this class of context. And the problem in this case is that we can't generalize a code since not all components will be "StyledUIBase". For me this is the most serious problem -- Carlos Rovira http://about.me/carlosrovira
RE: extending IUIBase with interfaces (was: Re: Version property (was: Let's bump Royale version to 1.0))
It seems to me this is more an AS3 issue than a Royale issue. It would be cool to enhance AS to include features such as Mixins, but as long as we have a simple single inheritance model the solution you implemented is probably optimal. I personally wouldn’t worry too much about code duplication of one liners in framework code. The average user isn’t going to care. Also, in my opinion you should always check to see if a said object implements an interface, rather than extends a class. If you stick to that your solution works fine. From: Carlos Rovira Sent: Tuesday, April 30, 2019 12:29:10 PM To: dev@royale.apache.org Subject: Re: extending IUIBase with interfaces (was: Re: Version property (was: Let's bump Royale version to 1.0)) Hi Andrew, thanks for your thoughts. One of the main problems here that I didn't put on my email is that you loose the opportunity to ask if the components is a "StyledUIBase", since we are "bifurcating" the code when implement in Group and DataContainerBase and others the interface IClassSelectorLitsSupport. You can ask for "IClassSelectorLitsSupport", but you probably would want just ask for StyledUIBase. El mar., 30 abr. 2019 a las 8:14, Frost, Andrew () escribió: > Hi Carlos > > Isn't this similar to the challenge that Adobe had with EventDispatcher? > which I think is why there are two possibilities: > a) derive from EventDispatcher > b) implement IEventDispatcher > > In the second case, you have to create an instance of EventDispatcher > within your class, and then you have to implement the IEventDispatcher > functions with calls to the EventDispatcher object. So it's not > zero-effort, but it's not too bad (and probably the best option you can get > without multiple inheritance..). Yes there's repeated code, but it's > limited to one line per function so is relatively easy to copy/paste. > This solution could save code duplication if method bodies are long. In this case method bodies are similar, so I'm afraid will not apply here to make a significant difference > > Not 100% sure if the same approach can be applied in the scenario you're > talking about, but that might help perhaps..? So the functionality you want > to repeat would go into a class ("ClassSelectorListSupportImpl"?) and you > create one of these in each of the classes that derive from > UIBase/Group/etc and implement IClassSelectorLitsSupport. > Yes, this could be similar to before and more elegant, but the problem is the same I put before. > > Some alternatives perhaps: > - I'm also wondering whether you could create a helper function that > actually adjusted the class prototype and programmatically added the > necessary functions to your classes... ? > - the repeated functionality could be put into other .as files and just > 'included' in the classes? I know, this is a major hack, but I've seen it > done :-( > > hehe, prefer not to go that way ;-) What I want to expose here is that beads are a good composition way and love it. But we still has a problem in cases like this. Thinking on this and seeing how the overall picture is now, I think the actual solution is not helping PAYG at all. Maybe we should see if we can add IClassSelectorLitsSupport to UIBase and remove IClassSelectorLitsSupport implementations (StyledUIBase and the rest). We'll be saving code, and Basic components will have access to that API that is tiny and seems finaly make sense to be in UIBase. At least I see other frameworks out there have it's own "addClass", "removeClass", etc... as part of it's core, since nowadays the use of CSS selectors is crucial and people will needed always (and that's the key for PAYG). Thoughts? > > Hope it helps.. > > thanks > >Andrew > > > > -Original Message- > From: Carlos Rovira [mailto:carlosrov...@apache.org] > Sent: 29 April 2019 18:04 > To: dev@royale.apache.org > Subject: [EXTERNAL] extending IUIBase with interfaces (was: Re: Version > property (was: Let's bump Royale version to 1.0)) > > Hi Alex, > > initial problem is: I want to add to all jewel components (that use to > have UIBase as common class) a new interface and implement the methods. In > concrete interface is: IClassSelectorListSupport > > So the expected result should be to make all Jewel components implement > IClassSelectorListSupport, but to avoid repeat code in all classes we need > a root for all the components. > > Perfect point would be UIBase, but we can't add at that point for PAYG > reasons. > > Current solution in Jewel is to create StyledUIBase that is > > public class StyledUIBase extends UIBase implements > IClassSelectorListSupport > > but this makes other classes like jewel Group that extend html Group have > UIBase in the hierarchical chain instead StyledUIBase, so we need to make > Group as this: > > public class Group extends org.apache.royale.html.Group implements > IClassSelectorListSupport > > same for > > public class DataContainerBase
Re: extending IUIBase with interfaces (was: Re: Version property (was: Let's bump Royale version to 1.0))
Hi Andrew, thanks for your thoughts. One of the main problems here that I didn't put on my email is that you loose the opportunity to ask if the components is a "StyledUIBase", since we are "bifurcating" the code when implement in Group and DataContainerBase and others the interface IClassSelectorLitsSupport. You can ask for "IClassSelectorLitsSupport", but you probably would want just ask for StyledUIBase. El mar., 30 abr. 2019 a las 8:14, Frost, Andrew () escribió: > Hi Carlos > > Isn't this similar to the challenge that Adobe had with EventDispatcher? > which I think is why there are two possibilities: > a) derive from EventDispatcher > b) implement IEventDispatcher > > In the second case, you have to create an instance of EventDispatcher > within your class, and then you have to implement the IEventDispatcher > functions with calls to the EventDispatcher object. So it's not > zero-effort, but it's not too bad (and probably the best option you can get > without multiple inheritance..). Yes there's repeated code, but it's > limited to one line per function so is relatively easy to copy/paste. > This solution could save code duplication if method bodies are long. In this case method bodies are similar, so I'm afraid will not apply here to make a significant difference > > Not 100% sure if the same approach can be applied in the scenario you're > talking about, but that might help perhaps..? So the functionality you want > to repeat would go into a class ("ClassSelectorListSupportImpl"?) and you > create one of these in each of the classes that derive from > UIBase/Group/etc and implement IClassSelectorLitsSupport. > Yes, this could be similar to before and more elegant, but the problem is the same I put before. > > Some alternatives perhaps: > - I'm also wondering whether you could create a helper function that > actually adjusted the class prototype and programmatically added the > necessary functions to your classes... ? > - the repeated functionality could be put into other .as files and just > 'included' in the classes? I know, this is a major hack, but I've seen it > done :-( > > hehe, prefer not to go that way ;-) What I want to expose here is that beads are a good composition way and love it. But we still has a problem in cases like this. Thinking on this and seeing how the overall picture is now, I think the actual solution is not helping PAYG at all. Maybe we should see if we can add IClassSelectorLitsSupport to UIBase and remove IClassSelectorLitsSupport implementations (StyledUIBase and the rest). We'll be saving code, and Basic components will have access to that API that is tiny and seems finaly make sense to be in UIBase. At least I see other frameworks out there have it's own "addClass", "removeClass", etc... as part of it's core, since nowadays the use of CSS selectors is crucial and people will needed always (and that's the key for PAYG). Thoughts? > > Hope it helps.. > > thanks > >Andrew > > > > -Original Message- > From: Carlos Rovira [mailto:carlosrov...@apache.org] > Sent: 29 April 2019 18:04 > To: dev@royale.apache.org > Subject: [EXTERNAL] extending IUIBase with interfaces (was: Re: Version > property (was: Let's bump Royale version to 1.0)) > > Hi Alex, > > initial problem is: I want to add to all jewel components (that use to > have UIBase as common class) a new interface and implement the methods. In > concrete interface is: IClassSelectorListSupport > > So the expected result should be to make all Jewel components implement > IClassSelectorListSupport, but to avoid repeat code in all classes we need > a root for all the components. > > Perfect point would be UIBase, but we can't add at that point for PAYG > reasons. > > Current solution in Jewel is to create StyledUIBase that is > > public class StyledUIBase extends UIBase implements > IClassSelectorListSupport > > but this makes other classes like jewel Group that extend html Group have > UIBase in the hierarchical chain instead StyledUIBase, so we need to make > Group as this: > > public class Group extends org.apache.royale.html.Group implements > IClassSelectorListSupport > > same for > > public class DataContainerBase extends > org.apache.royale.core.DataContainerBase implements > IClassSelectorListSupport > > This make we have 3 classes that are duplicating the same exact code > implementing in the same maner addClass, removeClass, etc.. > > what can we do for this cases? > > Hope is more clear now, > > thanks > > > > El lun., 29 abr. 2019 a las 17:41, Alex Harui () > escribió: > > > > > @Carlos, I couldn't understand your scenario. Feel free to start a > > separate thread on it. The key aspect, as a guess, is trying to avoid > > code that assumes that an instance is a subclass of a particular base > > class instead of an implementation of an interface. > > > > HTH, > > -Alex > > > > On 4/29/19, 7:29 AM, "Carlos Rovira" wrote: > > > > @Mark, if you use Maven, then artifacts in the poms
RE: extending IUIBase with interfaces (was: Re: Version property (was: Let's bump Royale version to 1.0))
Hi Carlos Isn't this similar to the challenge that Adobe had with EventDispatcher? which I think is why there are two possibilities: a) derive from EventDispatcher b) implement IEventDispatcher In the second case, you have to create an instance of EventDispatcher within your class, and then you have to implement the IEventDispatcher functions with calls to the EventDispatcher object. So it's not zero-effort, but it's not too bad (and probably the best option you can get without multiple inheritance..). Yes there's repeated code, but it's limited to one line per function so is relatively easy to copy/paste. Not 100% sure if the same approach can be applied in the scenario you're talking about, but that might help perhaps..? So the functionality you want to repeat would go into a class ("ClassSelectorListSupportImpl"?) and you create one of these in each of the classes that derive from UIBase/Group/etc and implement IClassSelectorLitsSupport. Some alternatives perhaps: - I'm also wondering whether you could create a helper function that actually adjusted the class prototype and programmatically added the necessary functions to your classes... ? - the repeated functionality could be put into other .as files and just 'included' in the classes? I know, this is a major hack, but I've seen it done :-( Hope it helps.. thanks Andrew -Original Message- From: Carlos Rovira [mailto:carlosrov...@apache.org] Sent: 29 April 2019 18:04 To: dev@royale.apache.org Subject: [EXTERNAL] extending IUIBase with interfaces (was: Re: Version property (was: Let's bump Royale version to 1.0)) Hi Alex, initial problem is: I want to add to all jewel components (that use to have UIBase as common class) a new interface and implement the methods. In concrete interface is: IClassSelectorListSupport So the expected result should be to make all Jewel components implement IClassSelectorListSupport, but to avoid repeat code in all classes we need a root for all the components. Perfect point would be UIBase, but we can't add at that point for PAYG reasons. Current solution in Jewel is to create StyledUIBase that is public class StyledUIBase extends UIBase implements IClassSelectorListSupport but this makes other classes like jewel Group that extend html Group have UIBase in the hierarchical chain instead StyledUIBase, so we need to make Group as this: public class Group extends org.apache.royale.html.Group implements IClassSelectorListSupport same for public class DataContainerBase extends org.apache.royale.core.DataContainerBase implements IClassSelectorListSupport This make we have 3 classes that are duplicating the same exact code implementing in the same maner addClass, removeClass, etc.. what can we do for this cases? Hope is more clear now, thanks El lun., 29 abr. 2019 a las 17:41, Alex Harui () escribió: > > @Carlos, I couldn't understand your scenario. Feel free to start a > separate thread on it. The key aspect, as a guess, is trying to avoid > code that assumes that an instance is a subclass of a particular base > class instead of an implementation of an interface. > > HTH, > -Alex > > On 4/29/19, 7:29 AM, "Carlos Rovira" wrote: > > @Mark, if you use Maven, then artifacts in the poms are all what > you need, > so maven takes care of pulling all right dependencies you need. > > @Alex, about extending IUIBase, my own experience is that beads > are a very > good way to extend/compose more code you need, but extending core > interfaces like the one you said is not the case. Let me put you an > example: For Jewel I use "StyledUIBase" that extends "UIBase" to add > IClassSelectorListSupport, the css CRUD API (addClass, > removeClass, > etc..): > > public class StyledUIBase extends UIBase implements > IClassSelectorListSupport > > This makes that some components are easy to extend but others need > to be > recreate. There are lots of cases in Jewel where I need to > > If you search in Jewel for implements IClassSelectorListSupport > you'll find Jewel Group, Jewel DataContainerBase and Jewel Table, are > implementing that class while, so they are not StyledUIBase in > it's core > are standard UIBase and at its level we implement the interface and add > again all methods repeating the code. So we are duplicating that > code all > that times. > > I think this is one of the few things I don't like in Jewel, If > you know > some way to do this in a better way, I can change it > > thanks > > -- Carlos Rovira https://clicktime.symantec.com/37RX7Zfo3fgsrnBKZDX18bM7Vc?u=http%3A%2F%2Fabout.me%2Fcarlosrovira