In the past and even to this day, when you create a game or application you set up the classes and such and some of them know about each other so that they can interact, but it is mostly abstracted.
Then you want to add new content to the game. Generally you have to change the existing classes to do this, or sacrifice truly new content. This is considered a design flaw, but it has been used successfully for years.
I aim to change that.
Games with high replay value are those with modding/plugin support, which are easily extensible to add new content. The issue is the interaction between plugins and other plugins and even the core vanilla behavior.
Plugins are forced to be independent and isolated from each other. Sometimes if they can see that they exist they can interact more deeply, but other than that there is no way to predict everything.
Say someone creates a plugin which adds various animals to the game. In the context of that plugin it doesn't make sense to do more than necessary to achieve the goal (YAGNI). This works great, until another plugin come along.
This plugin adds content that deals to some extent with the animal plugin, and in this context it needs to refactor the class hierarchy by making some animals Breedable. It would be totally derpy to account for the various animals in a non-OO way and say "if instanceof ThatPlugin.Pig then enable breeding mechanics" alongside the plugin's own animals which simply extend a Breedable class/interface.
It can work, but it's ugly, as it means either the original developer forgot to predict the future, or the future developer forgot to change the past.
I'm changing this. Through some way, be it a class design library, a well-managed design pattern, or inventing a new language, I will change this.
The latter plugin should simply indicate that, for all intents and purposes, the prior plugin's various animals now extend Breedable, Tameable, etc. and have whatever data members and methods are thus inherited. This isn't about secure code, it's about self-refactoring, encapsulated, extendable code.
No need to predict the future.
No need to change the past.
Just a way to refactor at runtime based on what plugins are loaded, because you shouldn't have to buy a time machine to make a game or plugin.
In short, I'm solving a problem I keep running into possibly by creating a new language, because so far no language I look at doesn't have this problem. Wolf should be able to be passed as Breedable (which has data members and concrete methods) even if Wolf has no idea that Breedable exists. It just simplifies things in an environment where various classes are developed by different authors for different self-contained plugins.
Close to Duck-typing, but the person doesn't have to know how to act like a duck when a duck can implant that knowledge if a duck actually walks by.
So, as far as I know, I am a pioneer. Since nobody else seems to be trying to deal with this problem, and nobody I talk to really thinks past a few updates to a game, I must be one of the early people to try and solve this.
Is there a design pattern I could use? Probably, but that requires that you enforce it upon all plugin developers, which is not feasible.
Is there a language I could use that does this already? I've not seen one yet, and if so, it probably isn't popular enough to have good support for making games.
Am I venting? Yes.
Do I want help in finding an alternative? No. I've spent the last year or so going back and forth with various people who eventually came to the conclusion that they couldn't solve my problem.
Is my goal due to a design flaw? Well, yeah, I'm trying to solve the design flaw...
Thanks for reading this. I'll probably never have time to accomplish my goals, and it's comforting to know that now my goals can't be forgotten.
It seems to me that this type of behavior can exist on a meta or "meta-meta" level with existing languages...In all cases it would be ugly and you would probably find yourself soon crucified by other users of the language though. The most obvious route of crucification would to be with either java or scala and writing a custom class loading suite (which would be both fragile and frowned upon by the all-mighty oracle servants). It seems like a fair enough endeavor. Although I don't have the time or skill to help, I'm curious to see what comes of this.
L-B Quack! -- the first next-gen duck language. Nice ring to it.
It sounds like a solution to a problem no one has. A plugin is by default meant to extend a program, not as a building block for other plugins. If someone comes along and decides to write a plugin that depends on a non-basic plugin, it's obviously a design error in the newcomer.
You seem to be suggesting some kind of system that alters behavior of an existing class without notifying that class' maintainer. This has a number of possible problems, such as what happens if the class is updated in a way that breaks the assumptions of the overriding behavior. Does the new behavior break and needs to be updated as well? If so, how is this better than simply maintaining an independent class hierarchy?
I think you're over-thinking. A client is to provide events to the plugin which then acts upon each event. I don't see any real reason why OOP has to be taken in anywhere. While OOP can be used internally, why force it on the interface? I believe this is overcomplicated. Even for a game, this event model works perfectly. It's been used in Unreal for years.
I'm not an expert at structure and design, so what I say may not make sense, but here are some thoughts.
You could have a class implement a dynamic list of interfaces which get loaded at runtime along with the implementations of all of the methods the interfaces require.
If your data structures are handled by an interpreted language, then they can be re-define simply by using a script which just searches through your source code and inserts additional code. You could even build in some intelligence to ensure that your extensions make sense and your plugin code is valid.
Again I'm don't know exactly what I'm talking about, and am not really sure I completely understand the problem your trying to solve.
As far a breeding goes, I'm not sure how to solve the problem without more specifics. You could have a creator class, that creates new objects periodically by checking metadata which defines the frequency, position, and other specifics about when and how objects of different types should be created. You could have meta data for defaults, and meta-data for dynamic runtime behavior which is modified in game based game state and circumstances, etc. Plugins could over-ride default creation behavior, or rules for how data evolves in game.
Well, .Net assemblies (.exe and .dll files) contain metadata like the name, description and version of the module, and the classes in the System.Reflection namespace are used for accessing that (which is useful because you can check if a file was created with incompatible versions of your program). RTTI, which C++ supports, is another form of reflection.
p.s. Reflection has nothing to do with static methods AFAIK.