Refactor storage

Refactored storage to be more generic, because we want to store more than just subject assignments.

- Add a basic key value interface (get, set, remove) that storage engines need to implement, instead of a myriad of different methods.
- Have a base storage class that implements all the storage operations as calls to get, set, and/or remove.
- Rename `subject_storage` -> `storage` everywhere.

I also removed `Experiment#wrapup` and related code. The code was useless, because you can only wrap up an experiment after it has been removed from the code, in which case the Experiment instance that you need to call `wrapup` up on will no longer exist.

The old Redis storage engine remains available as `LegacyRedisStorage`. When rolling this out, we need to make sure the current experiments use that storage engine, because the Redis operations of the new RedisStorage engine are not compatible. Once all these experiments are wrapped up, we can remove the legacy engine.

@peterjm @pseudomuto for review.