Gary,

we seem to have a difference in underlying principles.  I don't want
to imply (that I think) that your principles/opinions are wrong, I'm
just presenting mine as an alternative, and partial justification for
my opinions.

Well, then...

On 6/29/05, Gary Feldman <[EMAIL PROTECTED]> wrote:
> Troy Laurin wrote:
> 
> >I have no issues with making the shell configurable, that's definitely
> >a Good Idea, although the actual nature of how to configure it would
> >probably need discussion.  Would it be a normal (magical) property, or
> >a special parameter like the logger?  Presumably it could be
> >overridden locally by the exec task itself?
> >
> What's wrong with
> 
>    <exec shell="cmd" ...>
> 
> where the shell attribute is optional?

Absolutely nothing, but should there be a mechanism to set/override
the default shell on a per-buildfile or per-invocation level?  This
would only affect exec calls that don't specify their own shell, so
I'm not sure how useful it would really be...

Actually, I've just back-flipped.  Changing shells is likely to be
disruptive enough that it shouldn't be as dynamic as a property or
option.  With the differences in how different shells handle quoting,
and escaping, and redirecting, it probably makes most sense for a
shell-sensitive command to explicitly:
<exec command="shell-of-choice" commandline="properly quoted &amp;
escaped command" />
Perhaps it would be better for NAnt to recommend this approach than
perform any magic "shelling" of commands under the covers.

> That's the case I'm talking about.  It's the difference between
> 
>     <exec commandline="getfiles | filter .cs | filter modified_today |
> sort -size" />
> and
>    <exec commandline="getTodaysCSfilesInSizeOrder.sh" />
> where I'm taking liberties with the syntax, since exec today can only
> take one program.

Liberties accepted.  I don't think your second invocation is better
than your first, but more on that below.

> >If there are several programs to be run in some order,
> >then that's flow control, which I think is more part of NAnt's
> >territory, so makes more sense to use multiple <exec> calls.  The only
> >
> Flow control is in the territory of every procedural language.  I don't
> see why to favor NAnt for it.

We're not comparing NAnt with procedural languages.  We're comparing
NAnt with shell scripts.  And unless you're willing to install a unix
shell in a Windows environment (with all the associated
forward/backslash issues), NAnt is more portable.

> >If NAnt were to introduce pipe support, then this could be split into
> >multiple execs and dependence on the shell would be diminished...
> >
> But if you do it this way, there's virtually no difference between using
> a pipe and using a temporary file, at least as far as the way it's
> written.

More on pipes below.

> But my point is that it's still clearer to write
> 
>   <exec program="FtpFilesToRemoteNode" />
> 
> and let the FtpFilesToRemoteNode contain
>    ls | perl makeftpscript.pl | ftp

I personally think that this is an anti-pattern.  It is a workaround
to the fact that NAnt currently doesn't have support for pipes (so is
using temporary files, incidentally).  It obscures the flow of the
script by segueing into a different file and exacerbates this by
changing language as well.  To be fair, it also mitigates both of
these by using a meaningful name for the script, but that's
documentation, not functionality - you can achieve the same effect by
moving the exec into a similarly-named target.

None of these things are issues for the person who wrote the scripts,
and maintains them as part of his/her job.  But that's not the point
of maintainability.  Each little obfuscation makes the system a little
harder to learn, and to understand, for a new person asked to do some
work on or pick up the build system.

> >In this example, using NAnt pipes rather than a single exec probably
> >decreases maintainability of the script by itself, by increasing cut
> >and paste (in the pipe names)... but the idea is to add extra
> >opportunities to improve the script - perhaps the perl script could be
> >replaced with a NAnt script element in C# (or whatever is the
> >incumbent language in the organisation), reducing the number of
> >scripts to track and maintain, and the number of languages in the mix
> >- slowly improving the maintainability.
> >
> I don't agree with either of those as valid measures.  Try to keep the
> number of scripts to a minimum is what leads to monolithic scripts on
> the UNIX side, which are not particularly maintainable.  A better
> measure is how much text, not how many files the text is spread across.
> This is similar to the design philosophy of having each object
> responsible for just one thing, with a multitude of very simple objects.

I like to think that NAnt compares favourably to unix-style scripting,
because of an expressive syntax and support for modularising a (build)
task through targets, and to a lesser extent child build files.  I
know unix-style scripts can do both of these, but the focus IMHO is
inverted - more to subscripts, and less to functions.

Regarding having less text in the entire build system, executing
external scripts which perform magic rather than inlining that magic
into the NAnt script doesn't reduce the amount of text, it just makes
it more difficult to find.  Again, not for the person who wrote and
maintains the script, but for the people who want to learn and
understand the script.

I've worked in several places where some part of the build process is
done by a perl script, or in some other language that only one (or a
small number of) person(s) know.  Whenever any issue came up
surrouding this script, that person had to be taken off whatever they
were doing to help with the other person's build issue.  And that's if
they were even still around, in one case the original author had left!

Migrating these scripts to the predominant language might slow the
scripts down slightly, it might be less efficient in other ways (more
source code in the build script, for example)... but it starts to
matter less who is on holiday.

Perhaps my comments have been a little confused because I have two
different purposes here... I advocate porting shell scripts to NAnt
for portability as much as maintainability, but I advocate porting
perl/python/whatever scripts to C#/VB/Java/whatever 100% for
maintainability.  Granted, there will be cases where there is no
suitable language to replace the existing script, and then you simply
have a dilemma... which bad option to choose.


> As for languages, I've always felt that software engineers should be
> fluent in several.  While I don't think there should be a multitude of
> redundant languages - i.e., pick just one of Perl, Python, or Ruby - I
> also don't believe there's enough overlap between NAnt and most other
> languages or that NAnt is functional enough to justify using a NAnt as a
> replacement for anything more than cmd.exe.

NAnt isn't a replacement for cmd.exe, or even *sh.  NAnt is an
alternative to Ant, which is a replacement for Make.  Shells execute
given commands in certain orders.  Build scripts encapsulate a body of
knowledge of an application required to build the system.

There's little reason why a perl script couldn't be replaced by a C#
script block - C# provides file parsing, regular expressions and maps
just as well as perl does. (No flame/religious wars intended)  Unless
of course the project doesn't use C#, then there's every read _not_ to
make such a replacement :-)

> ><output-pipe name="|file" />
> ><exec program="cmd1" output="|file" />
> ><exce program="cmd2" output="|file" />
> ><write-pipe name="|file" file="${filename}" />
> 
> As indicated above,
>    <exec program="cmd1" output="${filename}" />
>    <exec program="cmd2" output="${fielname}" append="True" />
> already works, and is shorter.

Not the same thing though, unfortunately.  There is opportunity
between the two <exec> commands for the file to be locked, modified or
deleted by another process if using a file.  The pipe operation
provides isolation guarantees that mean your file will either contain
completely what you expect, or completely what someone else expects,
there's no chance of some combination that neither of you expected.

IMHO, temporary files are a workaround when no better solution exists,
and having to use a temporary file is an indication that some part of
the system is lacking or incorrect.  They introduce potential for
error (files are more likely to fail in the face of low disk space
than pipes are), requirements for cleanup and probably aren't as
efficient as in-memory pipes.




-- 
Troy


-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_idt77&alloc_id492&op=click
_______________________________________________
nant-developers mailing list
nant-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nant-developers

Reply via email to