TODO

Summary

Maintainability
Test Coverage
* TODO:

* Create a module to allow methods to be added to existing Attribute objects
  in such a way that the same methods can be easily mixed into other
  things, like functions or relations.
  * Replace the explicit mix-into-relation with something that adds the
    methods to Axiom::Attribute::Relation, and then have Axiom::Relation
    "inherit" those by declaring it's own relation methods as being of that
    type.

* Move all Axiom::Algebra classes under Axiom::Relation::Operation

* Change Algebra::Extension#extensions to be a non-primtive
  * May also change EvaluationContext#functions to return a set of functions.

* Add key minimization to Header
  * When unioning two keys together it is really simple to end up
    with indexes that overlap and cause an exception.

* Make Equalizer handle subclasses without having to specify the attribtues
  again in each descendant.

* Allow Evaluator::Context to be used like:

    relation.extend { new_extensions }

  This will require the return value from the block to become useful.

* Add domain object for Extensions and Summarizers
  * Add Evaluator::Context subclasses for Extensions and Summarizers, and return
    those as instances rather than Hashes of attributes and functions.

* Convert Tuple to a Struct
  * Make Header a "Struct Class", and copy all the Header instance methods to
    the class level. Move all the Tuple instance methods into the Header
    instance.
    * Rename Header as Tuple
    * Make sure the Tuple has a class level method called #header that returns
      the set of attributes.
    * Use a class variable to store each "Tuple class" so that anything with a
      similar header will be reused.

* Remove Sorted, Reverse, Limit and Offset from the Relation inheritance chain
  * Instead make it so they are proxy classes that wrap Relations, but
    proxy method calls to the Relation methods, and then wrap the return
    value (assuming it's a Relation) in a copy of itself.
  * Also this will allow knowledge of #directions to be removed from
    all the Relation classes. Only the Ranking classes will need to know
    about directions.
  * The Reverse class will probably not be needed either. All we need is
    for the #reverse method to create a new Sorted with the directions
    reversed.
  * Remove the knowledge of directions from materialized relations
    and instead wrap materialized relations in the Sorted object
    if any.

* Update Attributes so that constraints are modelled using predicates,
  so that when "join-ability" is tested, the predicates can just be
  compared for equality.
  * Create an object that can wrap a predicate, and if it fails it will
    set the object's error state, and then propagate the status to the
    caller. This will allow a "complex" predicate to set the errors
    on tuples, while still allowing all the same objects to be used.

* Within the restriction context, make sure the attributes have aliases for:
  * Alias #== to #eq (may break alot)
  * Alias #!= to #ne (in 1.9 only)
  * Alias #>= to #gte
  * Alias #> to #gt
  * Alias #<= to #lte
  * Alias #< to #lt
  * Alias #=~ to #match

* Within the sort_by context, make sure the attributes have aliases for:
  * Alias #@+ to #asc
  * Alias #@- to #desc

* Handle case where one attribute is required, and the other is not, when joined
  (or other ops), the resulting attribute should always be required.
  * In other operations, the resulting attribute may be something else, but will
    need to research to know how to handle this.
  * Current behaviour is to require both attributes are equivalent all the way
    around to allow them to be joined. This constraint will need to be relaxed
    to implement this new behaviour.

* Add operations for efficiently determining the following Enumerable properties
  of a relation, when no block is provided:
  * all?
  * any?
  * empty?
  * one?
  * none?
  * many?
  * include? / member?
  * min / max / minmax (when the tuples are sorted)

* Add Axiom::Relation aggregate methods:
  * count
  * count(attribute)
  * sum(attribute)
  * minimum(attribute)
  * maximum(attribute)
  * mean(attribute)
  * standard_deviation(attribute)
  * variance(attribute)