I fully understand the need to help people understand the usage of APIs by how you expose them.
No doubt.. One can't work that long in the industry and not grok that...

I just feel that most of the time it is a major pain in the arse deciding, when you aren't making a library for the use of others but instead writing end-code, or if you're the recipient of such a library, you simply can't use the code you have executing in your own damned program the way you want to have it executing if you don't have the source to hand.
I think there must be a better way.
Then don't criticize those looking towards entity systems and by general extension component architectures as wasting time or that they suck as the
handful of us that are doing this are searching and some of us have found what we consider a better way. Searching and experimenting takes time and most definitely it takes an immense amount of time to convert a significant existing OO framework to a very granular component oriented one. I only did so after I saw the writing on the wall and pushed the older way to the limits. The inflexibility that you speak of above was obvious in my efforts with traditional Java / OOP mechanisms and I tried everything before going whole hog toward component architectures. Almost everything in my efforts now can be replaced or substituted fairly easily from external configuration files. A great deal of time was spent minimizing dependencies between components and related groupings so this is possible.
Beside the scenario above as you describe is just a poor API / framework that didn't do what it is intended to accomplish and I believe someone above commented on this sentiment in a reply above. I'm aware there may be times when a dev desires to mod a perfectly working API to do something slightly different as well, but usually that is an exceptional case as OOP in itself doesn't disable extension.
And that's how all new languages are born........
It can be, but I'm not ready to give up on Java yet. Though I certainly keep in mind how the CA can be leveraged from Scala and other JVM languages. In fact I certainly posit that it's a much better way to integrate Java w/ Scala or other JVM languages as opposed to extension of Java classes. I still need to experimentally validate this, but I put a lot of thought into it. A simple shift in perspective and coding practice is what I'm really trying to get at and while it works for me it may not work for everyone. The only downside so far is increased verbosity at the Java layer. There should be some ways with Scala for instance to reduce the verbosity in practice.
Now, I'm certainly not saying anyone has to follow me down the path I'm heading, but I do believe it will benefit any project small to large. It's not "f**king insane" as a poster above claimed. I have a large body of code that has only seen a benefit and things still chug along nicely in a reasonably complex 3D demo case. There will be early adopters and the typical bell curve of adoption. I most definitely have an up hill battle to fight, but it's an pedagogical one that can be overcome with good documentation, lots of clear tutorials, and perhaps a hit app or game + outside success stories. All that takes time...
To continue I would posit further that yet again this is a dirty mark on OOP and the is-a and explicit has-a relationship. It doesn't lend to flexible APIs / frameworks that can be easily extended or reconfigured and only truly works well for small to mid (at the most) sized projects in terms of maintenance unless there is someone full time working as a "cleaner / hands on architect" that can see the forest from the trees and has authority to refactor and uphold whatever standards that are set up. Code reviews are not enough in this regard as it's really an active full time position for a larger project with one or more folks involved day to day. Most small to mid sized projects with various devs involved benefit from a dedicated hands on architect.
Again a clarification, in my experience standard OOP as implemented in status quo Java projects doesn't work well as the central organizing mechanism, but is less of a deadly force in the leaves of any API / framework. Thus while my new efforts are component oriented they are partially still OO in the leaves which means some of the components / systems themselves. As a framework dev it's impossible to limit OOP in the leaves since OO is baked into Java. This is not necessarily the case for the entity system where it is recommended to minimize OO in the leaves, but for the runtime layer of my efforts it makes sense where there are component peers w/ a base cross-platform implementation + J2SE and Android peer extensions. Mind you the interface based programming aspect comes in because one stores the given platform implementation by the common interface / contract in the CA thus on any platform the dev just retrieves the particular platform implementation component by its common interface and bam easy cross-platform support w/ ease of adding more platform support on an as needed basis.
A simple shift of perspective to promoting the implicit has-a relationship as foundational and minimizing the explicit form and is-a relationship is not crazy. It's just a different approach. This is also fairly "CS 103"

material and shouldn't be strange language per se. It is a shift of perspective nonetheless though. It's true power is not realized until a significant amount of code is converted to this mechanism.
I know the "AbstractComponentManagerControl" thing may be hard to follow from a previous post as that is an implementation detail specific to my efforts, but I'll show it in psuedocode below (just a snippet mind you and not using best practices / IE never use foreach loop in near realtime bound code). It basically is an internally used component that can extend and change the behavior of the manager itself. It is what allows vetoing and encapsulation back that otherwise would be lost by the implicit has-a relationship. If you wanted to make a particular compound component final you'd first composite all the desired included components then add an ACMC that vetoes further set / unset actions.
This code is not the exciting part per se, but defines the bread and butter implicit has-a relationship. The exciting part is building a larger framework around a few essential new patterns that come from all of this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| public class ComponentManager { HashMap<Class<IComponent>, IComponent> components HashMap<Class<IComponent>, Collection<IComponent>> componentCollections
public <C extends IComponent> C getAs(Class<C> componentType) { return components != null ? components.get(componentType) : null; }
public <C extends IComponent> Collection<C> getCollection(Class<C> componentType) { return componentCollections != null ? componentCollections.get(componentType) : null; }
public <C extends IComponent> boolean set(Class<C> componentType, C component) { Collection<AbstractComponentManagerControl> controlCollection = componentCollections.get( AbstractComponentManagerControl.class); if (controlCollection != null) { for (AbstractComponentManagerControl control : controlCollection) { if (control.set(this, componentType, component) { return false; } } }
return components.put(componentType, component); }
public <C extends IComponent> IComponent unset(Class<C> componentType) { Collection<AbstractComponentManagerControl> controlCollection = componentCollections.get( AbstractComponentManagerControl.class); if (controlCollection != null) { for (AbstractComponentManagerControl control : controlCollection) { if (control.unset(this, componentType) { return null; } } }
return components.remove(componentType); } } |