At #wrocloverb in the begining of March I started to bootstrap Maroon and have now released a fully bootstrapped version. It took longer than I had anticipated based on the time it took me to write maroon in the first place. The main reason for this was that part of the process lead me to find bugs needing fixing or features required to implement maroon that maroon didn’t support(1). Both tasks some what mind boggling. How do you fix a bug in the tool you use to fix said bug? a lot of the time I ended up having two mental models of the same concept and to be honest that’s one more than my mind can handle.
One model was of what the current version was capable of and another was what it was supposed to do. All this was part of the motivation for bootstrapping in the first place and often the reason why a lot of compilers are bootstrapped too. The current state of the code is a mess. I knew it would be. I’m often asked questions like “Is the code then in fact a lot cleaner when using DCI?” and my answer is that it for me depends on how I design the system. If I design as I presented at wroc_love.rb 2013 (top-down) then yes the code is a lot cleaner, however if I design as I often do when not using DCI (bottom-up) then I often find that the code becomes more messy when I try to rewrite it using DCI and maroon was designed bottom-up.
I’ve done some cleaning up but postponed a large part of the cleaning up till the bootstrapping was actually complete so that I had a foundation to test my refactorings against. So the now live version of maroon is a fully bootstrapped version making maroon the most complete example of how to use maroon. The goal of the version thereafter is to clean the code up and make maroon a good DCI example as well. An example I hope to have both James and Trygve review if their time schedules permit. What bugs did I find?
- Indexers on self didn’t work in role methods, so if an array played a role you couldn’t do self to get the second element
- You couldn’t name a class method the same as an instance method. This wasn’t really a big deal because you couldn’t define class methods in the first place but since that’s one of the features added it did become an issue
What features were added?
- You can define initialize for context classes
- You can define role methods and interactions with the same name as methods defined for objects of the Context class. E.g. you can define a role method called ‘define’
- You can define class methods (The syntax for that is still messy but you can do it)
- You can use splat arguments in role methods or interactions. In general arguments for role methods are discouraged which I heavily violate in the current version of maroon
- You can use block arguments (&b). The syntax for this is even worse than the syntax for class methods
- You can choose whether to build the classes in memory or to output a classname.rb file for each generated class. That’s the way the bootstrapping works. I use the current stable version to generate the files of the next version. I then use those generated files to generate an additional set of generated files and the last set of files, which are generated using the upcoming version are then packaged as a gem and pushed.
What features would I still like to add?
- Default values for arguments to role and interaction methods
- Make it possible to use all valid method names for role and interaction methods E.g. field_name=, which are currently not possible
- Cleaner syntax for both block arguments and for defining class methods. I have an idea for this but it won’t be until after I’m done with the cleaning up. It’s going to be an interesting task since it’s probably not going to be backwards compatible. The changes will be small and make the syntax intuitive to ruby programmers (which the current is not for the features in question) but since I’m bootstrapping I’m breaking my own build before I’m done.
- a strict flag that would enforce a strict adherence to DCI guidelines and a warn flag that would warn if any of those guidelines were violated
- Add a third option, that instead of creating classes in memory or class files will visualize the network of interconnected roles for each interaction.
(1) Yes it’s a bit strange to talk about bootstrapping. You think/say stuff like “ features required to implement maroon that maroon didn’t support” that sounds kind of nonsensical a lot. The most mind boggling part of that is when debugging…