Discussion:
code organization and name conflicts
Ryan Davis
2011-04-13 18:35:03 UTC
Permalink
When working on a larger lisp code base, one with 10+ files in one
package, I begin to get nervous about accidental name conflicts, and was
wondering how other people deal with this.

Here's the scenario I'm worried about:

* dsl.lisp, written by a coworker two years ago, has a number of
small functions that are helpers for the main #'WRITE-DSL-REPORT
function; one of these helpers is #'GET-WAN-IPS
* nagios-config.lisp, written by me today, has a number of small
functions that are helpers for the main #'WRITE-NAGIOS-CONFIG
function; one of these helpers is #'GET-WAN-IPS
* I miss the compiler warning about redefining #'GET-WAN-IPS
* I test my code, it works in my REPL so I commit and call it a day
* Code eventually gets pushed to production and #'WRITE-DSL-REPORT
is broken

It doesn't happen very often (and testing procedures usually catch stuff
before it goes to production), but it seems like there should be a nicer
way to deal with helper functions that you want to develop/test from the
REPL, but don't need to be used outside the current file.

I had a few ideas to solve it, none of which I really like. I could add
a top-level FLET for the file, but the extra indentation will be
annoying and it'll be harder to test/maintain those helper functions. I
could define a helper package, per-file, and put my helper functions in
that package (e.g. (defun nagios-config-helpers::get-wan-ips ...)), but
that feels funny and awkward, which usually means it's a bad idea. I
could break up my code into many smaller packages, each exporting and
importing the functions needed elsewhere in the system, but that seems
like recipe for dependency headaches and a lot of unneeded paperwork.

Do other people have this anxiety? Are there elegant ways to deal with
it? (besides medication and more unit testing)

Thanks,
--
Ryan Davis
Acceleration.net
Director of Programming Services
2831 NW 41st street, suite B
Gainesville, FL 32606

Office: 352-335-6500 x 124
Fax: 352-335-6506
Thomas M. Hermann
2011-04-13 18:57:57 UTC
Permalink
For your specific example, I would do some combination of

- Figure out why there are 2 GET-WAN-IPS helpers, how they differ, and
factor to a single function.
- Change GET-WAN-IP to a generic function and factor.
- Create another package and factor.

The entire point of packages is to avoid name conflicts. So, if you are
experiencing a name conflict in a single package, it's time to factor the
code.

Search the archives for a recent discussion on conflicts between packages,
maybe that has some insight that is applicable to your issue.

Good luck,

Tom
----------------------------------------------------------------
Thomas M. Hermann
Odonata Research LLC
http://www.odonata-research.com/
http://www.linkedin.com/in/thomasmhermann
Post by Ryan Davis
When working on a larger lisp code base, one with 10+ files in one
package, I begin to get nervous about accidental name conflicts, and was
wondering how other people deal with this.
- dsl.lisp, written by a coworker two years ago, has a number of small
functions that are helpers for the main #'WRITE-DSL-REPORT function; one of
these helpers is #'GET-WAN-IPS
- nagios-config.lisp, written by me today, has a number of small
functions that are helpers for the main #'WRITE-NAGIOS-CONFIG function; one
of these helpers is #'GET-WAN-IPS
- I miss the compiler warning about redefining #'GET-WAN-IPS
- I test my code, it works in my REPL so I commit and call it a day
- Code eventually gets pushed to production and #'WRITE-DSL-REPORT is
broken
It doesn't happen very often (and testing procedures usually catch stuff
before it goes to production), but it seems like there should be a nicer way
to deal with helper functions that you want to develop/test from the REPL,
but don't need to be used outside the current file.
I had a few ideas to solve it, none of which I really like. I could add a
top-level FLET for the file, but the extra indentation will be annoying and
it'll be harder to test/maintain those helper functions. I could define a
helper package, per-file, and put my helper functions in that package (e.g.
(defun nagios-config-helpers::get-wan-ips ...)), but that feels funny and
awkward, which usually means it's a bad idea. I could break up my code into
many smaller packages, each exporting and importing the functions needed
elsewhere in the system, but that seems like recipe for dependency headaches
and a lot of unneeded paperwork.
Do other people have this anxiety? Are there elegant ways to deal with it?
(besides medication and more unit testing)
Thanks,
--
Ryan Davis
Acceleration.net
Director of Programming Services
2831 NW 41st street, suite B
Gainesville, FL 32606
Office: 352-335-6500 x 124
Fax: 352-335-6506
_______________________________________________
pro mailing list
http://common-lisp.net/cgi-bin/mailman/listinfo/pro
Scott L. Burson
2011-04-13 19:10:26 UTC
Permalink
When working on a larger lisp code base, one with 10+ files in one package,
I begin to get nervous about accidental name conflicts, and was wondering
how other people deal with this.
I used to work on some large Lisp systems in a place where standard
practice was often to let packages grow very large -- much larger than
10 source files -- and as I recall, name collisions occurred
remarkably rarely. And often when they did happen, the two functions
actually had the same or very similar contracts.

I think part of the reason for this was good naming practices. As a
general matter, the more specific the purpose of a routine, the longer
its name should be. If it's used only in one file, there should be at
least one word in its name that identifies it as related to the other
code in the file, such that that word is unlikely to appear in
unrelated code.

If that doesn't satisfy you, you're welcome to try my lexical contexts package:

http://common-lisp.net/cgi-bin/viewcvs.cgi/devel/src/contexts.text?rev=1.1&root=misc-extensions&view=markup
http://common-lisp.net/cgi-bin/viewcvs.cgi/devel/src/contexts.lisp?rev=1.1&root=misc-extensions&view=markup

I've found it handy on occasion, though I don't use it for everything
by any means.

-- Scott
Ken Tilton
2011-04-13 21:13:23 UTC
Permalink
Post by Ryan Davis
When working on a larger lisp code base, one with 10+ files in one
package, I begin to get nervous about accidental name conflicts, and
was wondering how other people deal with this.
* dsl.lisp, written by a coworker two years ago, has a number of
small functions that are helpers for the main #'WRITE-DSL-REPORT
function; one of these helpers is #'GET-WAN-IPS
* nagios-config.lisp, written by me today, has a number of small
functions that are helpers for the main #'WRITE-NAGIOS-CONFIG
function; one of these helpers is #'GET-WAN-IPS
* I miss the compiler warning about redefining #'GET-WAN-IPS
* I test my code, it works in my REPL so I commit and call it a day
* Code eventually gets pushed to production and #'WRITE-DSL-REPORT
is broken
It doesn't happen very often (and testing procedures usually catch
stuff before it goes to production), but it seems like there should be
a nicer way to deal with helper functions that you want to
develop/test from the REPL, but don't need to be used outside the
current file.
The compiler warning should not have been missed. We have a "no
warnings" policy so warnings stand out, and I use the option in the
AllegroCL IDE that has it pop up a dialog on warnings (so I /really/
cannot miss them).

I suspect also that there may be a problem with the conclusion that the
code has been tested and works because it works in a REPL.

Absent those two issues, there is no longer a problem. :)

kt

Continue reading on narkive:
Loading...