technomancy / slamhound

Slamhound rips your namespace form apart and reconstructs it.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

seems to be a problem with Compojure and or Midje

hutch opened this issue · comments

Code that uses ring/compojure and midge. Midje is used in-line (the facts are in the source file not in the test directory).

  • from inside vim, again since Slamhound never terminates, I’ve got to Control-C out of it, and consequently the buffer is never updated.
  • when I run Slamhound from the command line:
    • it never terminates

    • despite not terminating, it does update all but one of the files properly

    • it does not handle the file(s) that start ring servers and complains:

      Failed to reconstruct: #<File src/jel/server.clj>
      Address already in use
      

      This is even if the address really isn’t in use, I think it’s trying to ‘run’ server.clj a second time. And it doesn’t terminate either.

I tried updating both fireplace and clojure-static but that made no difference.

from inside vim, again since Slamhound never terminates, I’ve got to Control-C out of it, and consequently the buffer is never updated.

Unfortunately, when you forcibly kill a fireplace eval, you also destroy the nREPL connection. After this, you must re-connect to the nREPL server with the :Connect command, or exit and re-launch vim.

it never terminates

As with #58, I will look into this.

it does not handle the file(s) that start ring servers and complains
Failed to reconstruct: #<File src/jel/server.clj>
Address already in use

This appears to be because the file src/jel/server.clj starts a Ring server on load? Unfortunately, like with #58, slamhound will fail on a file like this, as well as many other tools that work with namespaces.

One of the challenges of doing Clojure development for me has been how to manage state needed for REPL driven development, yet avoid global state and side-effects on namespace evaluation.

Stuart Sierra has done a lot of thinking and work on this topic, and I have integrated his development workflow into my own projects with great results:

It feels a bit complicated at first, but the end result is a perfectly modular system that does not rely on side-effects on ns load or global variables (aside from one global var for development).

I whole-heartedly recommend looking into his work; it has been well worth the investment in time.

Thank you again for bringing the issues here from the ML.

@hutch imho, in general, you save yourself a lot of trouble in Clojure by never executing code at load time. One instance of this concept is to not have defs that get set at load time. Instead you have some init function to set the var or atom when it is called. This way you get to control the timing at a fine grain.

In production, at Staples Innovation Lab (formerly Runa) you will often see the situation where the global state needs to be setup differently dependent on some environment configuration, but the only time you know the configuration is after namespace load time. So we use only initialization-type functions to set the state up after the config file has been loaded.

Yeah, the assumption that namespaces are well-formed and don't have side-effects (other than var definition) during compilation is baked pretty deeply into Slamhound; there's no way to support stuff like this without completely rewriting it.

Okay, your point of view is, of couse, perfectly valid... but I'd add: for production.

I've got a long history of developing code (since about 1987 with Smalltalk) that makes full use of executing code in the file at load during development. Too late to change that :-) Though that code has to be removed before production where, as you note, you need better control of what happens when.

I think you'll find a lot of people work this way in Clojure and other lisps. Consider one of the common workflows for midje.

Slamhound will still be useful as I prep the code for production. I'll wait until then.

I didn't notice this while reading the docs. Is it documented? Saying this more prominently might help a bit.

This is a very cool project, thanks! I'll have another go as I take my stuff into production.

@hutch:

I respect the convenience of executing code on file load; sometimes a task is not big enough to merit a full scaffolding. One of the trade-offs of this convenience, of course, is the inability to use meta-tools such as this one.

Thank you for your input. I hope Slamhound can be useful to you in the future!

@technomancy:

Yeah, the assumption that namespaces are well-formed and don't have side-effects (other than var definition) during compilation is baked pretty deeply into Slamhound; there's no way to support stuff like this without completely rewriting it.

Happily, the only part that would need to be significantly rewritten/augmented is the slam.hound.regrow/check-for-failure path. A theoretical static analyzer could do most of the same work without executing any top-level code¹.

I am hoping to explore this in the future and submit a patch, so long as it's possible to totally avoid false positives.

¹ Unless there are side-effects during macro-expansion. yuck