dkubb / adamantium

Create immutable objects
MIT License
373 stars 13 forks source link

Add devtools support (boilerplate reduction) #6

Closed mbj closed 11 years ago

mbj commented 11 years ago

I finished the initial version of devtools. This pull request is against the least complex gem we have in the dm-2 stack. If you accept here I'll prepare pull requests like this for all dm-2 repos.

Had to split the Gemfile in to a project specific and a shared part. The shared one is Gemfile.devtools that lives in the project root. A specific rake task `devtools:sync allows to copy the Gemfile.devtools on updates.

Pro

All the boilerplate under tasks/**/*.rb is now sharable between projects. No development flow changes are required. git clone && bundle install still works. No submodules are required. Heckle is now configured with config/heckle.yml will add support for adding aliases here before doing a pull request on veritas.

All tools or infrastructures like gemnasium, travis, etc do not see any difference. Only the Gemfile is a littlebit fancier than before.

All changes to the Gemfile.devtools can be done and tested locally without the need to modify my devtools repo. Plan to give @dkubb, @solnic, @snusnu access to the devtools repo to share fixes.

Contra

We have split gemfiles and no explicit development dependencies in .gemspec anymore. The latter is IMHO not a problem.

mbj commented 11 years ago

It was a depdendency but I removed the dep at some point. As equalizer is now a gem we can bring it back!

mbj commented 11 years ago

I came to a point where I cannot kill mutants as the mutants infer with mutant. Basically mutant mutates adamantium while mutant is using adamantium. I see the following strategies:

Sure I run the mutations in a fork, so the main process is not affected. But an injected mutation can prevent the killer to start correctly.

@dkubb Your idea is missing here!

Edit: Markdown.

solnic commented 11 years ago

How about not using adamantium in mutant :P

mbj commented 11 years ago

@solnic This is heretic!

solnic commented 11 years ago

From what you wrote it seems like mutant should not have any deps

mbj commented 11 years ago

@solnic Where I wrote this? Adamantium is a big help in keeping mutants code structured.

dkubb commented 11 years ago

@mbj I've run into the problem of using devtools with ice_nine too. If there was a way to turn off metrics:mutant via the configuration file, I think we would probably use it for ice_nine and adamantium and other deps. (for the immediate future)

I think vendoring could work, but I'd rather use that as a last resort. I would prefer to create Mutant::Adamantium, Mutant::IceNine, Mutant::Equalizer, etc and dynamically rewrite the dep source to use those namespaces. Then we can safely mutate the actual original namespaces without fear of conflict.

Actually, what if by default when Mutant starts up it creates a Zombie namespace, and rewrites (in memory of course) all it's own source to be mounted under that namespace? It then does the same thing for all of it's dependencies, transitive and direct. Basically you'd end up with a sandboxed environment, and then you could do whatever you need to the original source. Since it is the "standard way" things are run, you'd work out all the kinks more quickly, rather than having a special "self mutate" mode.

Actually, this sandboxed namespace could probably even use an anonymous module, because ruby's constant lookup rules would (I think) be relative to that namespace. I would think once you get this working it might even be usable outside the context of mutant.

mbj commented 11 years ago

@dubb I finally setteled with the following:

All libraries which are dependencies of mutant will not be mutated with mutant. For these library we'll use the zombie that is normally used to mutate mutant.

As Zombie is dynamically created we can create ::Zombie::Adamantium, ::Zombie::IceNine etc. Also Adamantium will be rewritten to use Zombie::IceNine on the fly.

Basically I have 95% of the infrastructure done in mutant/spec/support/zombie.rb.

Zombie is normally activated with using the zombie rather the mutant executable. Mutant detects it is run as zombie and dynamically creates the copy of itself and calls the newly generated code.

We'll extend devtools to support a zombie flag in config/mutant.yml:

---
namespace: Adamantium
zombie: true

Until we have this done, we could add a enabled: false flag to the configuration. I'd really like to have time to hack on this full time, we need funding at some point ;)