Reducing metaprogramming

The metaprogramming isn't gone altogether, but I hope it's a lot simpler and cleaner. The fact that I have methods that extract the articulation and symbol from the generated class as opposed to just storing instance variables definitely makes me think having no metaprogramming could be better.

The options, based on what you've suggested, seem to be (1) keeping it as is, (2) using a more general instance of Phone, or (3) using generator functions.

1. The arguments for keeping it as is are that it models the domain well and uses the class lookup table. My view of the domain is that you have the abstract idea of a phone, specific phones like AH, B, and Z, and instances of those within words. These are modeled by the Phone module, the generated classes, and instances of those generated classes. By using the class lookup table we don't need application logic around checking whether a symbol like AQ2 is valid you simply try to create an instance of the class and it throws an exception if it's invalid.

2. Using general instances of Phone seems problematic to me. A class becomes the top of the three levels of the domain, instances of that class the second level, and then I'm not sure what's left for the bottom level.

3. Using generator functions could be the solution to that problem. The middle level then becomes a function and the bottom level the instances of Phone. Symbol and articulation would be normal instance methods of Phone as opposed to arcane methods like they are now. The simplification of overall logic would probably balance out the increase in logic required by the hash to store the generator functions and the checking symbol validity.

I am thinking of creating an Articulation class to properly encapsulate sonority as opposed to the hash constant currently used. If I did that it would require a lookup hash similar to the one required for the generator functions so I might look at doing them at the same time.