I am making a text adventure. The following code is a toy model showing my problem.
public class Player:
private Location location;
private Inventory inventory;
public take(Item item) throws ActionException {
location.remove(item); // throws ActionException if item isn't in location
inventory.add(item); // throws ActionException if item can't be picked up
}
}
My issue is this: what if the item can be removed from the location, but can't be added to the player's inventory? Currently, the code will remove the item from the location but then fail to add it to the player's inventory.
Essentially, I want both to happen, or neither.
Any idea how I can do this? Any help appreciated.
Ideally, you would have like an inventory.canAddItem(item) function, whatever it may be called, that returns a boolean that you can call before removing from the location. As the commenter pointed out, using Exceptions for control flow is not a great idea.
If it's not an issue to add back to the location, then something like:
public take(Item item) throws ActionException {
location.remove(item);
try{
inventory.add(item);
}
catch(ActionException e){
location.add(item);
}
}
could work for you.
What you're generally looking for is the concept of transactions.
This is non-trivial. The usual strategy is to use DBs, which support it natively.
If you don't want to go there, you can take inspiration from DBs.
They work with versioning schemes. Think blockchain or version control systems like git: You never actually add or remove anything anywhere, instead, you make clones. That way, a reference to some game state can never change, and that's good, because think it through:
Even if the remove works and the add also works, if other threads are involved or there is any code in between these two actions, they can 'witness' the situation where the item is just gone. It has been removed from location but hasn't been added to inventory yet.
Imagine a file system. Let's say you have a directory with 2 files. You want to remove the first line from the first file and add that line to the second file. If you actually just do that (edit both files), there will always be a moment-in-time when any other program observing the directory can observe invalid state (where it either doesn't see that line in either file, or sees it in both).
So, instead, you'd do this: You make a new dir, copy both files over, tweak both files, and then rename, in one atomic action, the newly created dir onto its old name. Any program, assuming they 'grab a handle to the directory' (which is how it works on e.g. linux), cannot possibly observe invalid state. They either get the old state (line is in file 1 and not in file 2), or the new state (line is in file 2 and not in file 1).
You can use the same approach to your code, where all state is immutable, all modifications are done via builders (mutable variants) or one step at a time, with immutable trees in between, and once you're done all you do is take a single field of type GameState and update it to reference the new state - java guarantees that if you write: someObj = someExpr, that other threads will either see the old state or the new state, they can't see half the pointer or other such nonsense. (You'd still need volatile or synchronized or something else to ensure that all threads get the update in a timely fashion).
If threading just doesn't matter, there is one more alternative:
GameState actions.
Instead of just invoking location.remove, what you can do instead is work with a gamestate action. Such an action knows both how to do the job (remove the item from the location), but it also knows precisely how to undo the job.
You can then write a little framework, where you make a list of gamestate actions (here: the action that can do or undo 'remove from location', and one that can do or undo 'add this to inventory'). You then hand the framework the list of actions. This framework will then go through each action, one at a time, catching exceptions. If it catches one, it will go in reverse order and call undo on every gamestate action.
This way, you have a manageable strategy, where you can just run a bunch of operations in sequence, knowing that if one of them fails, everything done so far will be undone properly.
This strategy is utterly impossible to make work correctly in a multi-threaded environment without global state-locking, so make sure you aren't going to need that in the future.
This is all quite complex. As a consequence... most people would just use a DB engine to do this stuff; they have transactional support. As a bonus, saving your game is now trivial (the DB is saving it for you, all the time).
Note that h2 is a free, open source, all-java (no servers needed, just one jar that needs to be there when your program is run), file-based (As in, all DBs are a single file) DB engine that supports transactions and a decent chunk of SQL syntax. That'd be one way to go. For convenient access, combine it with a nice abstraction over java's core DB access layer, such as JDBI and you've got a system that:
Can save files trivially.
Lets you run complex queries in a fast fashion, such as 'find all game rooms with a bleeding monster on it'.
Fully supports transactions.
You would just run these commands:
START TRANSACTION;
DELETE FROM itemsAtLocation WHERE loc = 18 AND item = 356;
INSERT INTO inventory (itemId) VALUES (356);
COMMIT;
and either both happen or neither happens. As long as you can express rules in terms of DB constraints, the DB will check for you and refuse to commit if you violate a rule. For example, you can trivially state that any given itemId can be in inventory no more than once.
The final and perhaps simplest but least flexible option is to just code it up: All your 'game-state-modifying-code' should FIRST check that it is 100% certain it can perform every task in the sequence in a non-destructive fashion. Only when it knows it is possible, then all jobs are done. If one of them fails halfway through, just hard-crash, your game is now in an unknown, unstable state. The point of throwing exceptions is now relegated to bug-detection: An exception now simply means that you messed up and your check code didn't cover all the bases. Assuming your game has no bugs, the exceptions would never happen. Naturally, this one too just cannot be made to work in a multithreaded fashion. Really, only DBs are a solid answer if that's what you want, or handrolling most of what DBs do.
Related
In a game I'm writing there is a player that moves on a board. On this board there are other objects too. So I have a bunch of objects each one holding its state. The player can be asked to move onto a specific adjacent cell. Its moving is made of three discrete parts: exiting its current cell; traversing from the current cell to the destination cell; entering the new cell. Each of these phases may trigger some change of the objects on the board. The player either perform a full movement or doesn't move at all. There may be obstacles that prevent the player from reaching the goal cell on each of the three phases. The problem is to tell if the player can perform the move, and move it if and only if it can.
I first thought that I can inspect if there is no obstacle that prevents the player from exiting its current cell, if there is no obstacle preventing it to traverse towards the goal cell, and if there is no obstacle that prevents it to enter the goal cell. If all these conditions are matched, then I move the player; if not, then I don't move the player and the state of the board hasn't changed.
But it's not that simple. In fact, even if the three tests succeed, the player may be unable to move. For instance, when it exits its cell a change of the board may be triggered that makes impossible for it to later transition to the goal cell. In this situation everything must stay the same: the player shouldn't move (because it can't perform a full move) and the board should stay the same, meaning that no event should be triggered.
Since I can't know if the player can move or not beforehand, but only attempting to move it, I thought about another approach. I can try to move the player without checking anything beforehand, and rollback to the previous state in case of failure on any of the three moving steps. The rolling back is necessary because, while trying to move, an event may have been triggered so the board may have changed accordingly.
The question is the following. How can I try to execute some code that may change the state of some objects and then rollback to the previous state in case something happens? More concretely, suppose I have a method move that returns a boolean, and that changes the state of some objects. I'd like to keep the changes if the method returns true, otherwise rollback all the changes. How can such a behaviour be implemented?
Or do you have a better idea to solve the described problem?
It's a fine approach. Databases do this all the time.
There are, unfortunately, many, many answers to this question, and the most appropriate choice amongst these many answers depends on your specific scenario an data storage mechanism.
Use a database
The simplest one available is databases.
This involves the following setup:
Ensure you always use transactions, for everything. Preferably even read-only operations.
Ensure you have a non-idiotic database. For example, MySQL MyISAM counts as an idiotic database; don't use that. Most SQL-based DBs are sane in this regard. Avoid mongodb and other such document-based db engines for this specific use-case. You're looking for a database that supports SERIALIZABLE level transactions and actually adheres to the rules of it (vs. many db engines that act like they support it, but don't actually give you the guarantees that SERIALIZABLE describes).
Set up your connection to use TransactionLevel.SERIALIZABLE.
This inherently means so-called 'retry'. To manage this, you need to wrap any and all code that interacts with databases in a lambda so that the underlying framework can re-run your code if neccessary. In general, do not use JDBC directly, instead use a much nicer abstraction built on top of it. You have two mainstream options: JOOQ and JDBI. The tutorials of both of these excellent libraries include details on how to do it right.
Once you have all that, 'fail the operation and change nothing at all' is as easy as exiting your 'do these data operations' (which is a block of code, filled with DB query statements (sql INSERT/UPDATE/DELETE/SELECT), handed to jdbi/jooq) by way of an exception. The transaction will be rolled back and nothing you changed in the DB actually 'sticks'. Also useful: All other code sees the way things were before you started the 'move the player' song and dance routine in one instant, and then in the next, as if everything applied. In other words, the player move ends up acting as if it is atomic, which is presumably a requirement for this model to work right. No other code, if ever you make this a multi-threaded setup, should ever act on half-a-move!
If you're not currently using databases, then it gets much, much more complicated. You're more or less signing up to write your own MVCC-style database engine which is not an easy job.
There are a few easier answers. As usual for easy answers, they may be utterly infeasible for your particular use case.
Immutables / Cloning
If the data structure that describes your game state is 100% immutable (zero setters), or even if not: As long as your 'move the player' code never actually modifies anything at all and is instead operating on / produces new slightly modified clones every step of the process, then 'aborting' is trivial: Just.. return.
The one and only way the game state ever actually updates is if you update the one field that points at an object representing the entire game state, which you do at the very end. Changing a reference in java (any non-primitive variable is a reference) is atomic.
If your game state is quite large this is probably a bad idea as it neccessarily involves a complete copy.
Rollback logs
Another option is that every operation you can do to the game state is paired with a mirror implementation that undoes it. Every 'change' you make to the state is described in the form of an Operation object, and each Operation has code inside that both knows how to apply the change to the underlying game state, AND it knows how to un-apply it. Applying may be implemented by way of adding new Operations to the queue.
For example:
public class HitCreature extends Operation {
private Player actor;
private Creature target;
private Weapon weapon;
public void apply() {
target.health -= actor.getStrength();
if (weapon.hasKnockBack()) {
//calculate direction...
queue.addOperation(new KnockbackCreature(target, direction));
}
if (target.isDead()) {
queue.addOperation(new RemoveCreature(target));
queue.addOperation(new AddSkeleton(target));
}
}
public void unapply() {
target.health += actor.getStrength();
}
}
Any given move is simply a single operation that explodes into multiple operations and you maintain a List, with each operation on it, in order. Either you get to the end of this list without any errors in which case, great, it all succeeded. Or, one of the operations fails, in which case, walk back to the 0-index in it, invoking unapply, which should exactly undo everything it did (and the unapply code CANNOT add new operations, it just undoes what it directly changed without causing any further side-effects).
This is no bueno if you are using multi-threaded code, though.
Other options
There's more strategies, but these hopefully give you some ideas on where to go from here.
Should the question be asked on programmers.stackexchange please just move it or notify me.
Imagine a program with the sole purpose to measure temperature with a sensor. There are two inputs, the sensor and the user (user can press an abort button).
When the program starts, certain conditions have to be met. Lets say the sensor must not have a temperature higher than x. If the condition is met, the program moves on to the next step, if not, the user is being told to make sure the condition is met.
Once it is met, the user is presented with the next thing to do, like "now stick the sensor into the object you want to measure".
The program now measures. Assume this process requires more than a snapshot of the sensor but some rather complex filtering etc. Once certain criteria have been met, the user is being told what to do next.
At some point the user is being presented with the result.
The user can decide at any point to abort the whole thing (go back to start or close).
Why im struggling with this is, what if at some point another step is introduced, or some step is removed but they will always follow the same workflow. Im in the beginning of a new program and i want to create a maintainable system.
Im not sure if a state machine is a good solution for this or if i completely misunderstood what a state machine is for or if there is a simpler solution.
Under a loose definition, any program you write would classify as a state machine. Your program changes state as it moves from one line of code to another, and as the variables change values.
When we talk about using a state machine as a design pattern, it usually involves separating out the main state transitions into separate modules (classes), where each object's fields store the state information that it's interested in, and its main execution method deals with the primary task of that current state, and then returns information about the next state that you should move into. A main control loop invokes each state's main execution method until a defined end-state is returned.
This pattern has the advantage of closely mirroring the structure of a visual workflow that you might create in Visio or some such. When each main state of the program has vastly different responsibilities, then this helps you to naturally group your code following the Single Responsibility Principle. And when each state can only move into one or two other states, you end up with relatively loosely-coupled code, which also helps to make things more maintainable.
The program you describe seems to be a good candidate for this pattern.
It sounds like it will be complex enough that you don't want to define the whole workflow in a single class or method.
It sounds like each state will allow you to move to a limited number of other states.
It sounds like the expected operations in each state are different enough to merit their own classes. If changes are made to the workflow, they will probably affect one or two states, and not the entire workflow, so it makes sense to split your classes up this way.
Yeah, any sequential process can be modeled as a state machine. The reason that EVERY sequential process is not implemented as a state machine is that usually (almost always) you can build a "smaller" machine (fewer conceptual flip-flops/variables and NAND gates/if statements, eg) using other techniques -- and "smaller" usually means "easier to understand".
However, because a state machine is so general, with a small number of well-defined rules, it is sometimes the best ("smallest" and easiest to understand) actual realization for a system with an irregular structure, especially if the structure is poorly understood and/or apt to need frequent modification.
Additionally, there are cases, in hardware at least, where devices such as a "programmable logic array" (PLA) implement a state machine rather cleanly -- more cleanly (and more cheaply) than a custom-designed integrated circuit.
This is one of the questions that involves crossing what I call the "Hello World Gulf" I'm on the "Hello world" I can use SQLite and Content Providers (and resolvers) but I now need to cross to the other side, I cannot make the assumption that onUpgrade will be quick.
Now my go-to book (Wrox, Professional Android 4 development - I didn't chose it because of professional, I chose it because Wrox are like the O'Reilly of guides - O'Reilly suck at guides, they are reference book) only touches briefly on using Loaders, so I've done some searching, some more reading and so forth.
I've basically concluded a Loader is little more than a wrapper, it just does things on a different thread, and gives you a callback (on that worker thread) to process things in, it gives you 3 steps, initiating the query, using the results of the query, and resetting the query.
This seems like quite a thin wrapper, so question 1:
Why would I want to use Loaders?
I sense I may be missing something you see, most "utilities" like this with Android are really useful if you go with the grain so to speak, and as I said Loaders seem like a pretty thin wrapper, and they force me to have callback names which could become tedious of there are multiple queries going on
http://developer.android.com/reference/android/content/Loader.html
Reading that points out that "they ought to monitor the data and act upon changes" - this sounds great but it isn't obvious how that is actually done (I am thinking about database tables though)
Presentation
How should this alter the look of my application? Should I put a loading spinning thing (I'm not sure on the name, never needed them before) after a certain amount of time post activity creation? So the fragment is blank, but if X time elapses without the loader reporting back, I show a spiny thing?
Other operations
Loaders are clearly useless for updates and such, their name alone tells one this much, so any nasty updates and such would have to be wrapped by my own system for shunting work to a worker thread. This further leads me to wonder why would I want loaders?
What I think my answer is
Some sort of wrapper (at some level, content provider or otherwise) to do stuff on a worker thread will mean that the upgrade takes place on that thread, this solves the problem because ... well that's not on the main thread.
If I do write my own I can then (if I want to) ensure queries happen in a certain order, use my own data-structures (rather than Bundles) it seems that I have better control.
What I am really looking for
Discussion, I find when one knows why things are the way they are that one makes less mistakes and just generally has more confidence, I am sure there's a reason Loaders exist, and there will be some pattern that all of Android lends itself towards, I want to know why this is.
Example:
Adapters (for ListViews) it's not immediately obvious how one keeps track of rows (insert) why one must specify a default style (and why ArrayAdapter uses toString) when most of the time (in my experience, dare I say) it is subclasses, reading the source code gives one an understanding of what the Adapter must actually do, then I challenge myself "Can I think of a (better) system that meets these requirements", usually (and hopefully) my answer to that converges on how it's actually done.
Thus the "Hello World Gulf" is crossed.
I look forward to reading answers and any linked text-walls on the matter.
you shouldnt use Loaders directly, but rather LoaderManager
I have a lot of existing data in my database already, and want to develop a points mechanism that computes a score for each user based on what actions they do.
I am implementing this functionality in a pluggable way, so that it is independent of the main logic, and relies on Spring events being sent around, once an entity gets modified.
The problem is what to do with the existing data. I do not want to start collecting points from now, but rather include all the data until now.
What is the most practical way to do this? Should I design my plugins in such a way as to provide for an index() method, which will force my system to fetch every single entity from the database, send an EntityDirtyEvent, to fire the points plugins, for each one, and then update it, to let points get saved next to each entity. That could result in a lot of overhead, right?
The simplest thing would be to create a complex stored procedure, and then make the index() call that stored procedure. That however, seems to me like a bad thing either. Since I will have to write the logic for computing the points in java anyway, why have it once again in SQL? Also, in general I am not a fan of splitting business logic into the different layers.
Has anyone done this before? Please help.
First let's distinguish between the implementation strategy and business rules.
Since you already have the data, consider obtaining results directly from the data. This forms the data domain model. Design the data model to store all your data. Then, create a set of queries, views and stored procedures to access and update the data.
Once you have those views, use a data access library such as Spring JDBC Template to fetch this data and represent them into java objects (lists, maps, persons, point-tables etc).
What you have completed thus far does not change much, irrespective of what happens in the upper layers of the system. This is called Model.
Then, develop a rule base or logic implementation which determines, under what inputs, user actions, data conditions or for all other conditions, what data is needed. In mathetical sense, this is like a matrix. In programming sense, this would be a set of logic statements. If this and this and this is true, then get this data, else get that data, etc. This encompasses the logic in your system. Hence it is called "Controller".
Do not move this logic into the queries/stored procedure/views.
Then finally develop a front-end or "console" for this. In the simplest case, develop a console input system, which takes a .. and displays a set of results. This is your "view" of the system.
You can eventually develop the view into a web application. The above command-line view can still be viable in the form of a Restful API server.
I think there is one problem here to be considered: as I understand there's huge data in the Database so the idea to create only one mechanism to calculate the point system could not be the best approach.
In fact if you don't want to start collecting points but include all the data, you must process and calculate the information you have now. Yes, the first time you will run this can result an overhead, but as you said, you need this data calculated.
By other hand you may include another mechanism that attends changes in an entity and launches a different process capable of calculate the new pointing diffence that applies to this particular modification.
So, you can use one Service responsible of calculate the pointing system, one for a single entity and another, may be longer to finish, capable of calculate the global points. Even, if you don't need to be calculated in real-time you can create a scheduled job responsible of launch it.
Finally, I know it's not a good approach to split the business logic in two layers (Db + Java) but sometimes is a requirement do it, for example, if you need to reply quickly to a request that finally works with a lot of registries. I've found some cases that there's no other option than add business logic to the database (as a stored procedures, etc) to manage a lot of data and return the final result to the browser client (ex: calculation process in one specific time).
You seem to be heading in the right direction. You know you want your "points" thing decoupled from the main application. Since it is implied you are already using hibernate (by the tag!), you can tap into the hibernate event system (see here section 14.2). Depending upon the size/complexity of your system, you can plugin your points calculations here (if it is not a large/complex system), or you can publish your own event to be picked up by whatever software is listening.
The point in either design approach is that neither knows or cares about your point calculations. If you are, as I am guessing, trying to create a fairly general purpose plugin mechanism, then you publish your own events to that system from this tie-in point. Then if you have no plug-ins on a given install/setup, then no one gets/processes the events. If you have multiple plug-ins on another install/setup, then they each can decide what processing they need to do based upon the event received. In the case of the "points plugin" it would calculate it's point value and store it. No stored proc required....
You're trying to accomplish "bootstrapping." The approach you choose should depend on how complicated the point calculations are. If stored procedures or plain update statements are the simplest solution, do that.
If the calculations are complicated, write a batch job that loads your existing data, probably orders it oldest first, and fires the events corresponding to that data as if they've just happened. The code which deals with an event should be exactly the same code that will deal with a future event, so you won't have to write any additional code other than the batch jobs themselves.
Since you're only going to run this thing once, go with the simplest solution, even if it is quick and dirty.
There are two different ways.
One is you already know that - poll the database for for changed data. In that case you are hitting the database when there may not be change and it may slow down your process.
Second approach - Whenever change happens in database, the database will fire the event. That you can to using CDC (Change Data Capture). It will minimize the overhead.
You can look for more options in Spring Integration
I've always wanted to write a simple world in Java, but which I could then run the 'world' and then add new objects (that didn't exist at the time the world started running) at a later date (to simulate/observe different behaviours between future objects).
The problem is that I don't want to ever stop or restart the world once it's started, I want it to run for a week without having to recompile it, but have the ability to drop in objects and redo/rewrite/delete/create/mutate them over time.
The world could be as simple as a 10 x 10 array of x/y 'locations' (think chessboard), but I guess would need some kind of ticktimer process to monitor objects and give each one (if any) a chance to 'act' (if they want to).
Example: I code up World.java on Monday and leave it running. Then on Tuesday I write a new class called Rock.java (that doesn't move). I then drop it (somehow) into this already running world (which just drops it someplace random in the 10x10 array and never moves).
Then on Wednesday I create a new class called Cat.java and drop that into the world, again placed randomly, but this new object can move around the world (over some unit of time), then on Thursday i write a class called Dog.java which also moves around but can 'act' on another object if it's in the neighbour location and vice versa.
Here's the thing. I don't know what kinda of structure/design I would need to code the actual world class to know how to detect/load/track future objects.
So, any ideas on how you would do something like this?
I don't know if there is a pattern/strategy for a problem like this, but this is how I would approach it:
I would have all of these different classes that you are planning to make would have to be objectsof some common class(maybe a WorldObject class) and then put their differentiating features in a separate configuration files.
Creation
When your program is running, it would routinely check that configuration folder for new items. If it sees that a new config file exists (say Cat.config), then it would create a new WorldObject object and give it features that it reads from the Cat.config file and drops that new object into the world.
Mutation
If your program detects that one of these item's configuration file has changed, then it find that object in the World, edit its features and then redisplay it.
Deletion
When the program looks in the folder and sees that the config file does not exist anymore, then it deletes the object from the World and checks how that affects all the other objects.
I wouldn't bet too much on the JVM itself running forever. There are too many ways this could fail (computer trouble, unexepected out-of-memory, permgen problems due to repeated classloading).
Instead I'd design a system that can reliably persist the state of each object involved (simplest approach: make each object serializable, but that would not really solve versioning problems).
So as the first step, I'd simply implement some nice classloader-magic to allow jars to be "dropped" into the world simulation which will be loaded dynamically. But once you reach a point where that no longer works (because you need to modify the World itself, or need to do incompatible changes to some object), then you could persist the state, switch out the libraries for new versions and reload the state.
Being able to persist the state also allows you to easily produce test scenarios or replay scenarios with different parameters.
Have a look at OSGi - this framework allows installing and removing packages at runtime.
The framework is a container for so called bundles, java libraries with some extra configuration data in the jars manifest file.
You could install a "world" bundle and keep it running. Then, after a while, install a bundle that contributes rocks or sand to the world. If you don't like it anymore, disable it. If you need other rocks, install an updated version of the very same bundle and activate it.
And with OSGi, you can keep the world spinning and moving around the sun.
The reference implementation is equinox
BTW: "I don't know what kinda of structure/design" - at least you need to define an interface for a "geolocatable object", otherwise you won't be able to place and display it. But for the "world", it really maybe enough to know, that "there is something at coordinates x/y/z" and for the world viewer, that this "something" has a method to "display itself".
If you only care about adding classes (and not modifying) here is what I'd do:
there is an interface Entity with all business methods you need (insertIntoWorld(), isMovable(), getName(), getIcon() etc)
there is a specific package where entities reside
there is a scheduled job in your application which every 30 seconds lists the class files of the package
keep track of the classes and for any new class attempt to load class and cast to Entity
for any newlly loaded Entity create a new instance and call it's insertIntoWorld().
You could also skip the scheduler and automatic discovery thing and have a UI control in the World where from you could specify the classname to be loaded.
Some problems:
you cannot easily update an Entity. You'll most probably need to do some classloader magic
you cannot extend the Entity interface to add new business bethod, so you are bound to the contract you initially started your application with
Too long explanation for too simple problem.
By other words you just want to perform dynamic class loading.
First if you somehow know the class name you can load it using Class.forName(). This is the way to get class itself. Then you can instantiate it using Class.newInstance(). If you class has public default constructor it is enough. For more details read about reflection API.
But how to pass the name of new class to program that is already running?
I'd suggest 2 ways.
Program may perform polling of predefined file. When you wish to deploy new class you have to register it, i.e. write its name into this file. Additionally this class has to be available in classpath of your application.
application may perform polling of (for example) special directory that contains jar files. Once it detects new jar file it may read its content (see JarInputStream), then call instantiate new class using ClaasLoader.defineClass(), then call newInstane() etc.
What you're basically creating here is called an application container. Fortunately there's no need to reinvent the wheel, there are already great pieces of software out there that are designed to stay running for long periods of time executing code that can change over time. My advice would be to pick your IDE first, and that will lead you someways to what app container you should use (some are better integrated than others).
You will need a persistence layer, the JVM is reliable but eventually someone will trip over the power cord and wipe your world out. Again with JPA et al. there's no need to reinvent the wheel here either. Hibernate is probably the 'standard', but with your requirements I'd try for something a little more fancy with one of the graph based NoSQL solutions.
what you probably want to have a look at, is the "dynamic object model" pattern/approach. I implemented it some time ago. With it you can create/modify objecttypes at runtime that are kind of templates for objects. Here is a paper that describes the idea:
http://hillside.net/plop/plop2k/proceedings/Riehle/Riehle.pdf
There are more papers but I was not able to post them, because this is my first answer and I dont have enough reputation. But Google is your friend :-)