On 11.1.2015 г. 11:34 ч., Vicente J. Botet Escriba wrote:
Le 11/01/15 08:50, Borislav Stanimirov a écrit :
On 10.1.2015 г. 21:46 ч., Vicente J. Botet Escriba wrote:
Hi,
First of all, I want to say that I like your library too much. It is quite close to a library I was working one EntityRoleSubject. You library could be extended to to take in account the subjective programming paradigm (see below).
I have some comments/remarks/questions:
* I have some doubts about the name mixin. What a mixin has more than a facet or an aspect? Mixins in C++ have a specific mean in the context of CRTP. Why have you chosen the mixin name?
The name is chosen to match the term mixin in Ruby. Ruby was the inspiration for the library. I though about naming it "component" or "dynamic polymorphism" or even something vague like "hameleon" or "zeus". Do you have any other suggestions for a name? I will reserve Mixin for a library that helps to define C++ CRTP mixins. You provide a E/C framework (I have removed the system part of ECL intentionally), why not ECF/ECL.
Maybe Boost.EntityComponent could be a better name... I'll make a separate thread about it.
* The construction of the mixins in the tutorial is done always with the default constructor. Can we do emplace construction? How can you ensure the invariants of some mixing classes?
For now a default constructor is a requirement for the mixins. I know how to proceed in order to have non-default constructors, and it is in the roadmap so this is an upcoming feature for sure.
Why not allow the construction of the mixing outside the entity? Why do you want it to be constructed by the entity? In the context en entity/roles a role can change of the entity that is playing it.
Firstly, that's because of the way the entity holds its components. It doesn't just contain a list of buffers for each component. The buffers are bigger than needed to hold a pointer to the enity (so bm_this could work). So each component is constructed by a placement constructor and the allocation needs to happen from the entity. Custom allocators are the library's alternative for this.
* The priority of the messages doens't compose well. The user needs to have a global view of the application so that it can assign the correct priority. I have not a better suggestion, but I think that this issue would need more insight.
I have thought about that, too. I will continue to think of a better way to assign priorities. For now in the software I've written with the library I use enums with elements like "mixin_x_message_y_priority" or "message_x_low_priority"
You priority approach has value. Having the possibility to associate a mixing to an existing mixing could help to express the override obtained with the priority. Having mixin composition, could help to define explicitly the order and the combinator of the messages inside this composed mixin.
If you're talking about compile time composition, this is not a planned feature of the library.
* Respect to subjective programming: it would be great to be able to create subject from an entity so that only the mixins of the subject would play when a reference to this subject is addressed.
subject
s (o); o.get
() works as expected. o.get<Other>() compile fails if not equal to any Mix_k
This subject class can be made, but it won't have a relation with the boost::mixin::object class. `object` is not a template class and I don't want to make it one. Such a functionality could be added to the object class if the error is run time and not compile time. I have some upcoming features which will introduce somewhat similar behavior - the multiple domains.
I don't know what multiple domain is.
It's a future feature of the library that allows you to register mixins and messages to different "domains", such that you cannot construct an object from mixins of different domains. This may be useful if two independent systems of the application use the library, and their mixins and messages shouldn't be mixed.
I'm not sure why this is a desired feature. How is this any different from simple inheritance or composition without any templates?
I can understand that in your domain you don't need it. Your library checks everything at run-time and I'm locking for something that can be checked at compile-time :( Clearly it is difficult to conciliate the two views.
Indeed. The library's focus are run time features.
* The macro bm_this :(
Is the name a problem or the fact that it's a macro? :)
Both.
Alas I can't think of another way to have this functionality.
* I would like to see what is behind the scenes the different macros in an implementation section.
That's a good idea to add in the documentation. I'll add it to the upcoming tasks for the library.
Great.
* The entity-mixin relation is not recursive, that is, a mixin can not have associated mixins, or can them?
I'm not sure what you're asking. A mixin can have associated mixins via mutation rules (see http://ibob.github.io/boost.mixin/boost_mixin/tutorials.html#boost_mixin.tut... )
But I wouldn't call this recursive. It's more like a sibling (or enemy) connection.
I'm not for the recursive name if you want. What it is important is to be able to state the relation at compile time.
* Can a mixin D inherit from another mixin B? Could the mixing D be retrieved when getting the mixing B?
mutate(o).add<D>;
o.get<B>()->f() // f been a virtual function on B?
A mixin can inherit from another as any class can but it can't be obtained via get<Parent> (or receive messages automatically). Inheriting a mixin from another is not registered or noticed by the library. To the library those are like any two unrelated classes.
You could easily implement that feature via a message. Let's say you have a class `behavior` and two children `enemy_behavior` and `friendly_behavior`. You chould add a method to the children
behavior* get_behavior() { return this; }
Then you could make it into a message and use code like:
::get_behavior(some_object)->f()
Is there already a complete example on the documentation? if not I will appreciate one.
No there is not. I'll make one.
* The example of the mixin headphones_player show that the play() implementation makes use of get_sound() provided by other mixins. This dependency is not explicit. I would expect to be able to say that headphones_player depends on another mixing providing the get_sound message.
You could add a dependency on a concrete mixin via the mutation rules as mentioned above, but that will prevent you from having polymorphism for get_sound, as illustrated in the example by the two sound providers: cd_player and mp3_player. A compilation error is impossible for such a case.
I missed this possibility. Could you elaborate?
Both cd_player and mp3_player in the example implement the message "get_sound". You're asking to make a dependency between mixins, so when I construct an object with headphones_player, the message get_sound will be available. Due to the nature of the library this will be a run time error. The library provides mutation rules, which can add a specific mixin when some mixins are added. This is not helpful, because we're not interested in a specific mixin, but in the message get_sound, regardless from where it comes. I could make a feature that would trigger a runtime error if an object is constructed, that lacks a specific message but I'm not sure whether it would be very helpful, since incomplete objects are a common occurrence when using the library. Still I'll add such a feature to the roadmap. It may not be used often enough, but it won't be harmful. Again, though, this will lead to an exception when an incomplete object is constructed. It cannot be a compilation error. -- Borislav