Closed gabriel-dehan closed 11 years ago
I agree the generator needed to be refactored (as it was built in a couple hours basically), I like the approach.
One thing I'd like to avoid is require 'yaml' being something that is loaded on anything that uses the obvious gem. The reason this is problematic is when I was trying to build an android/ruboto app, the yaml dependency caused some issues. Apparently there are 2 separate parsers and one is C based, which JRuby doesn't like.
Since the only thing that requires YAML is the generator, it might be good to only require YAML if we are running the generator.
On the majority of web projects, this isn't an issue, but it's probably worth the effort to avoid the dependency unless we are actually using YAML in a project.
What about ditching YAML entirely, as suggested here? http://blog.mojotech.com/post/40108629420/turtles-all-the-way-down
I'm not opposed to ditching YAML entirely. The use of YAML in the first place was a stopgap for avoiding having to create my own file format. YAML gave something that is mostly human readable and easily translates into something a generator could use.
So your'e suggesting something like this:
Action: CreateStatus
Description: should create a status update
Code:
- c: validate input
- c: set default id and values for new Status entity
- c: create/populate Status object
requires: Status.populate
- c: save status to jack
requires: StatusJack.save, Status.to_hash
- c: return the result
would become:
{
action: CreateStatus,
description: should create a status update
code: [
'validate input',
'set default id and status values for new Status entity',
[ 'create/populate Status object',
requires: 'Status.populate' ],
[ 'save status to jack,
requires: [ 'StatusJack.save', 'Status.to_hash'] ],
'return the result'
]
}
As a programmer, this approach has some benefits, but I don't know if I like this from a language standpoint.
What I was hoping to achieve with the descriptors (which themselves might need a better name), is a kind of sketch pad for the system. You sketch out what you think you might need for a set of actions, and the generator fills out those ideas in the Obvious architecture structure with empty tests, pseudocode, and all that jazz.
YAML got me close to the minimal thing I would need to achieve this goal with a fairly readable syntax. I wish I didn't have to add a c: in front of each comment.
I'm shooting for something with a high glance factor - something that is obvious to read and understand what's going on. If someone has a better format or structure for this, I'm all ears.
Well, I think this discussion don't have much to do with the Generator refactoring itself, it can be refactored and we can modify the YAML dependency afterwards :)
But I do understand the issue, and I have several ideas :
describe CreateStatus do
description 'Should create a status update'
it {
should 'validate input'
should 'set default id and values for new status'
should 'populate Status object'
requires Status.populate
should 'save status to jack'
requires: StatusJack.save, Status.to_hash
should 'return the result'
}
end
It would actually be really readable for rspec users as the syntax is mainly the same.
The main pro here, apart from the familiar syntax, is the fact that it does not need parsing, we could just execute it with our own DescriptorLibrary that would define describe/it/should/requires which should be trivial to implement.
We'd just need to use method_missing and the NullObject pattern to prevent things like Status.Populate
to be evaluated.
An other and slight different version could be :
describe CreateStatus do
description 'Should create a status update'
it {
should 'validate input'
should 'set default id and values for new status'
should 'populate Status object' {
requires Status.populate
}
should 'save status to jack' {
requires: StatusJack.save, Status.to_hash
}
should 'return the result'
}
end
An other way to create descriptors could be plain text or comments, just like tomdoc almost :
# Action: Create Status
# Description: Should create a status update
#
# Code:
#
# Validate the input
#
# Set default id and values for new Status entity
#
# Create and populate Status object
# requires: Status.populate
#
# Save status to jack
# requires: StatusJack.save, Status.to_hash
#
# Returns the result
A simple parser could take care of this the same way we could use YAML, it's just a slightly different syntax, more readable maybe.
Ok, we can move this discussion of different descriptor setups to a different issue. The code here is fine for now. I don't like adding the fileutils gem just to copy a file, but we can fix that later. My issue with Fileutils is that it has a runtime dependency on rmagick.
In general, with Obvious, I'd like to avoid dependencies on other gems unless they are essential and useful. This is important to keeping Obvious clean. This might seem obsessive for now, but it will be important later.
Yep, let's move this to a different issue. Thanks for the insight on Fileutils, I had no idea, I'll fix it up.
I agree with the idea of having as few dependency as possible.
I have refactored the Generator into lib/generators.
It should be more maintainable and readable, I hope (especially the Descriptor class, that can be used for a further generator (to generate new descriptions scaffolds).
Cheers :)