In the latest Pharo release (Pharo 5.0) there’s an optional library/plugin called StateSpec. This is the author’s description:
StateSpec is an object state specification framework. It describes particular object states by first class specifications. For example, there are SpecOfCollectionItem, SpecOfObjectClass and SpecOfObjectSuperclass. They can match and validate given objects. In case when an object doesn’t satisfy a defined specification you will get a failure with detailed information about the state problem.
spec matches: anObject.
spec validate: anObject. “it returns validation result which can be success or particular failure”
To easily create specifications and validate objects by them StateSpec provides two kinds of DSL: ‘should’ expressions and ‘word’ classes.
The first allows you to write “assertions”:
1 should be: 2
1 should equal: 10
The second allows you to instantiate specs by natural readable words:
Kind of: Number
Instance of: String
Equal to: ‘test’
Oddly, the way that the words DSL works is very reminiscent of how FORTH works, ‘WORDS’ are the main structure in FORTH, they act as both objects and messages (although, since ‘message’ is an object, in a certain sense a message is simply an arbitrary object without content – in FORTH, ‘WORDS’ may or may not have content).
In any case, I was looking at the source, to see how difficult it would be to implement in Eclipse with EMF (EMF to write the DSL’s, since it includes the two DSL’s). A method called specComposer in an abstract class specObjectState applies the spec to the particular type of object the subclass deals with, which can be in Smalltalk, either of the DSL’s, or a mixture of any of the three. As a result, the specComposer has to be pretty generic (the subclasses include specCollection, specCollectionItem, etc.). The following is the code to handle NOT in any expression:
^ self copy
The code for the invert and denial messages implementations look like this:
denial := denial not.
denial == aBoolean
ifTrue: [ ^ self ].
invertChildren is an abstract method that needs to be implemented, since it will be different depending on the object type. This is the implementation in the subclass SpecOfBlockState:
That for me is what elegance in programming looks like. Everything is as simple as possible (but not simpler), it’s properly composed (and decomposed). NOT a 1200-line script dumped into whatever language structure is available.