<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://quest.windwards.net"  xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>Quest for improvement - software-development</title>
 <link>http://quest.windwards.net/tags/software-development</link>
 <description></description>
 <language>en</language>
<item>
 <title>Evolution of the lib-framework dichotomy</title>
 <link>http://quest.windwards.net/content/evolution-lib-framework-dichotomy</link>
 <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; property=&quot;content:encoded&quot;&gt;&lt;p&gt;The debate about the relative merits of frameworks versus libraries will likely remain a fixture in software development theory for a long time to come. Nevertheless, there are trends afoot, that suggest that this dichotomy is not so rigid as the &lt;a data-mce-=&quot;&quot; href=&quot;http://www.cs.umaine.edu/%7Elarry/latour/WISR/wisr6/proceedings/ps/lubars.ps&quot; shape=&quot;rect&quot; target=&quot;_blank&quot;&gt;OO theorists of the 90s would have us think&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The increasingly asynchronous nature of programming is one such trend. Many modern libraries, from &lt;a data-mce-=&quot;&quot; href=&quot;http://akka.io&quot; shape=&quot;rect&quot; target=&quot;_blank&quot;&gt;Akka&lt;/a&gt; to &lt;a data-mce-=&quot;&quot; href=&quot;http://backbonejs.org&quot; shape=&quot;rect&quot; target=&quot;_blank&quot;&gt;backbone.js&lt;/a&gt; prescribe event-driven (callback-/message-driven) models that means a certain inversion of control is present. They thus acquires framework-like properties. The starkest example is probably the rapid adoption of MapReduce as the prevalent query paradigm in newer NoSQL databases.&lt;/p&gt;
&lt;p&gt;We have also seen the rise of several platforms lately. &lt;a data-mce-=&quot;&quot; href=&quot;http://www.docker.com&quot; shape=&quot;rect&quot; target=&quot;_blank&quot;&gt;Docker&lt;/a&gt; is perhaps the most interesting example, though &lt;a data-mce-=&quot;&quot; href=&quot;http://www.npmjs.org&quot; shape=&quot;rect&quot; target=&quot;_blank&quot;&gt;npm&lt;/a&gt; also deserves to be named. These are clearly frameworks, but with very narrow contracts: if you follow a narrow set of rules, tons of magic will ensue.&lt;/p&gt;
&lt;p&gt;Thirdly, most serious frameworks are acts of curation. As can be seen from e.g. &lt;a data-mce-=&quot;&quot; href=&quot;http://search.maven.org&quot; shape=&quot;rect&quot; target=&quot;_blank&quot;&gt;Maven&lt;/a&gt;, the nature of this curation is changing, as are developers&#039; expectations. &lt;a data-mce-=&quot;&quot; href=&quot;http://jbossas.jboss.org/&quot; shape=&quot;rect&quot; target=&quot;_blank&quot;&gt;JBoss AS&lt;/a&gt; now exposes all its internal dependencies as &quot;modules&quot; allowing easy (or at least clear) replacement. A stark contrast to older versions&#039; repackaged jars.&lt;/p&gt;
&lt;p&gt;The dichotomy is also affected by the steadily improving quality, particularly of open source projects. This is partly because a lot of open source is in fact produced commercially, but improving methodology and fierce competition also helps. This reduces the need for discovery and quality aspects of curation.&lt;/p&gt;
&lt;p&gt;I think all these trends points roughly in the same direction: it pushes both libs and frameworks towards the middle ground, with narrow concepts (e.g. Akka&#039;s &quot;there is only message-passing&quot;), usually following established, well understood models (e.g. MapReduce). These will be successful because they can easily be combined into new constructs, lib style (e.g. a Maven-Docker plugin). I think we would do well to remember this when choosing software components for our projects.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-tags field-type-taxonomy-term-reference field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Tags:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/quest-blog&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;quest-blog&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item odd&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/software-development&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;software-development&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
 <pubDate>Tue, 09 Apr 2013 23:15:16 +0000</pubDate>
 <dc:creator>quest</dc:creator>
 <guid isPermaLink="false">35 at http://quest.windwards.net</guid>
 <comments>http://quest.windwards.net/content/evolution-lib-framework-dichotomy#comments</comments>
</item>
<item>
 <title>What does it mean to develop software?</title>
 <link>http://quest.windwards.net/content/what-does-it-mean-develop-software</link>
 <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; property=&quot;content:encoded&quot;&gt;&lt;p&gt;Consider the following:&lt;/p&gt;
&lt;p&gt;In principle, in the general purpose computing world, once you check in to your version control system a solution to a certain problem, you will solve that problem for everyone everywhere for all eternity.&lt;/p&gt;
&lt;p&gt;You may counter that if that were true, there would be only one Get Things Done app for Android, rather than 100. However, this springs more from disagreement on what the problem is.&lt;/p&gt;
&lt;p&gt;If we take that basic premise to be true, we need to gradually increase our capacity to solve problems. If we do not, logically we must sooner or later run out of problems that we can actually solve.&lt;/p&gt;
&lt;p&gt;Or, bluntly put, writing software is the craft of producing unemployment.&lt;/p&gt;
&lt;p&gt;Now, Joseph Stigliz may say that this has a lot to do with cheap capital favouring capital investment (such as massive compute farms and powerful software systems) over investment in manpower. This may be so, but this has been the norm for the last decade and a bit, and is likely to remain true for a decade to come while banks and states deleverage. Thus the principle will stand for the forseeable future (several aeons by ICT yardsticks).&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-tags field-type-taxonomy-term-reference field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Tags:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/quest-blog&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;quest-blog&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item odd&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/software-development&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;software-development&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
 <pubDate>Thu, 04 Oct 2012 12:14:48 +0000</pubDate>
 <dc:creator>quest</dc:creator>
 <guid isPermaLink="false">25 at http://quest.windwards.net</guid>
 <comments>http://quest.windwards.net/content/what-does-it-mean-develop-software#comments</comments>
</item>
<item>
 <title>The twelve-factor app</title>
 <link>http://quest.windwards.net/content/twelve-factor-app</link>
 <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; property=&quot;content:encoded&quot;&gt;&lt;p&gt;I do not normally do &quot;look-it-I-found&quot; posts, but sometimes you encounter some article, or even a whole community, that makes you go &quot;This is exactly what I feel!&quot;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.12factor.net/&quot;&gt;The Twelve-Factor App&lt;/a&gt; is such an article. It collects in one compact article several relevant points about writing software-as-a-service, that I have been trying to make. In particular, the article articulates the relationship between such things as dependencies, releases and deploys, which I have long felt to be marginalized in the greater software development discussion.&lt;/p&gt;
&lt;p&gt;Before you think &quot;But I don&#039;t do SaaS stuff,&quot; be advised that all of these recommendations are good practices even for more traditional software development. In fact, I think it excessive modesty on the part of the author to limit himself to this scope.&lt;/p&gt;
&lt;p&gt;I agree with and would emphasize each and every rule in &lt;em&gt;The Twelve-Factor app&lt;/em&gt;, bar one. I have one real piece of beef with the article, namely its view of configuration.&lt;/p&gt;
&lt;h1&gt;
	The world is not so simple&lt;/h1&gt;
&lt;p&gt;Says &lt;a href=&quot;http://www.12factor.net/config&quot;&gt;section III&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;The twelve-factor app stores config in &lt;em&gt;environment variables&lt;/em&gt;&lt;/strong&gt; (often shortened to &lt;em&gt;env vars&lt;/em&gt; or &lt;em&gt;env&lt;/em&gt;). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java System Properties, they are a language- and OS-agnostic standard.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There are several problems with using environment variables as the main configuration vehicle:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
		environment variables can not easily be changed after startup,&lt;/li&gt;
&lt;li&gt;
		many applications have far too much configuration for environment variables to be useful, and&lt;/li&gt;
&lt;li&gt;
		environment variables are too visible.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Changes after startup:&lt;/strong&gt; The article envisions that running a process should perform a task once and then return/exit. Thus, configuration changes can occur between restart. However, there are numerous legitimate use cases where you want to change configuration of a running process &lt;em&gt;inside&lt;/em&gt; the scope of its task. For example, you may have a web trawling process and you want to change its logging verbosity or what back-off delay it uses.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configuration volume&lt;/strong&gt;: Certain applications have a large volume of configuration. In particular, commercial software typically pass several slightly different use cases over its lifetime as it passes from one financing customer to the next. This means it will accumulate configuration options to select between those use cases or simply need to be configurable by customer or similar. This will quickly grow unmanageable if set through environment variables. One may argue that these are not optimal circumstances for software development, but the alternative is typically bankruptcy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Environment variables are too visible&lt;/strong&gt;: It is difficult to manage security of environment variables. Some ways they may leak:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
		ps e&lt;/li&gt;
&lt;li&gt;
		Set in shell before startup&lt;/li&gt;
&lt;li&gt;
		.bash_history or .zhistory&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;By contrast, a configuration file can be referred to by name without revealing its content, which makes it much preferable; most configuration files will end up containing credentials sooner or later.&lt;/p&gt;
&lt;h1&gt;
	Making room for configuration management&lt;/h1&gt;
&lt;p&gt;The brilliance of &lt;em&gt;The Twelve-Factor App&lt;/em&gt; is that it carves out a distinct niche for &lt;a href=&quot;http://en.wikipedia.org/wiki/Configuration_management&quot;&gt;Configuration Management&lt;/a&gt;, essentially by excluding it from the software development process altogether. Also, it pushes much of process management to systems administrators, by empowering them.&lt;/p&gt;
&lt;p&gt;However, those systems administrators may have to manage numerous different installations with different configuration sets. For example, an organization may run one instance per customer. At this point, the configuration will have to be versioned and managed in its own right, whereby the environment variables will have to be written to and loaded from file anyway.&lt;/p&gt;
&lt;h1&gt;
	Alternative recommendation&lt;/h1&gt;
&lt;p&gt;While environment variables may be useful to name the configuration file or configuration backing service, using them as the main configuration strategy will lead to grief in most non-trivial cases. It may work in the early stages of the life cycle, but sooner or later, chances are you will out-grow that strategy.&lt;/p&gt;
&lt;p&gt;Rather, my recommendation would be to use either of two strategies, depending on the use case:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
		&lt;em&gt;plain configuration file&lt;/em&gt;, using whatever standard tools are available in your environment, or&lt;/li&gt;
&lt;li&gt;
		&lt;em&gt;configuration backing service&lt;/em&gt;, when configuration becomes complex; in particular, when different processes need to behave differently depending on e.g. connecting user.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This critique notwithstanding, my hat is off to &lt;a href=&quot;http://adamwiggins.com&quot;&gt;Adam Wiggins&lt;/a&gt; of &lt;a href=&quot;http://www.heroku.com/&quot;&gt;Heroku&lt;/a&gt; fame.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-tags field-type-taxonomy-term-reference field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Tags:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/software-development&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;software-development&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item odd&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/quest-blog&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;quest-blog&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
 <pubDate>Sat, 12 May 2012 08:03:13 +0000</pubDate>
 <dc:creator>quest</dc:creator>
 <guid isPermaLink="false">18 at http://quest.windwards.net</guid>
 <comments>http://quest.windwards.net/content/twelve-factor-app#comments</comments>
</item>
<item>
 <title>Shell scripting patterns: configuration and option parsing</title>
 <link>http://quest.windwards.net/content/shell-scripting-patterns-configuration-and-option-parsing</link>
 <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; property=&quot;content:encoded&quot;&gt;&lt;p&gt;
	Adhering to software patterns lowers the threshold for doing the right thing, even when the quick hack beckons. This is particularly true in shell script handling of options and configuration. Essentially, the top of all scripts should look like this:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
OPTION1=&quot;default_value&quot;

. /etc/my.conf

function usage() {
    echo &quot;./dascript [-o &amp;lt;value&amp;gt;] -p &amp;lt;value&amp;gt;&quot;
    echo &quot; -o: set the value of option1&quot;
    echo &quot; -p: set the value of option2&quot;
}

while getopts &quot;ho:p:&quot; opt ; do
    case &quot;$opt&quot; in
    o) OPTION1=$OPTARG
    p) OPTION2=$OPTARG
    h) usage ; exit 0 ;;
    *) usage &amp;gt;&amp;amp;2 ; exit 1 ;;
    esac
}

[ -n &quot;$OPTION2&quot; ] || {
    echo &quot;Please supply -p &amp;lt;value&amp;gt;&quot;
    usage
    exit 1
} &amp;gt;&amp;amp;2
&lt;/pre&gt;&lt;p&gt;
	Copy the above example each time you get to the point where you need any configuration whatever for a script. It&#039;s much easier than trying to cheat.&lt;/p&gt;
&lt;p&gt;
	So what is going on?&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;
		List all parameter with their default values.&lt;/li&gt;
&lt;li&gt;
		Source a configuration file, which will overwrite the default value.&lt;/li&gt;
&lt;li&gt;
		Define a function usage that prints all available options (so that we can use it when parsing options).&lt;/li&gt;
&lt;li&gt;
		Parse options supplied on the commandline to allow overriding the configuration file.&lt;/li&gt;
&lt;li&gt;
		Verify that options have good values, including mandatory options.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;
	The only time this pattern fails is when you need to allow supplying the name of the configuration file.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-tags field-type-taxonomy-term-reference field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Tags:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/quest-blog&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;quest-blog&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item odd&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/shell-scripting&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;shell-scripting&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/software-development&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;software-development&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
 <pubDate>Wed, 06 Jul 2011 20:49:51 +0000</pubDate>
 <dc:creator>quest</dc:creator>
 <guid isPermaLink="false">7 at http://quest.windwards.net</guid>
 <comments>http://quest.windwards.net/content/shell-scripting-patterns-configuration-and-option-parsing#comments</comments>
</item>
<item>
 <title>Shell scripting patterns: paths, file globs and and current dir</title>
 <link>http://quest.windwards.net/content/shell-scripting-patterns-paths-file-globs-and-and-current-dir</link>
 <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; property=&quot;content:encoded&quot;&gt;&lt;p&gt;The basis of this pattern is simple: never ever change current working directory in your scripts. In fact, never ever assume that you have a working directory unless your command explicitly works from local directory (e.g. find). Consequently, you should never use relative paths in your script unless you got it from the caller; since your script doesn&#039;t change working directory, it&#039;s fine to just use whatever path the caller handed you.&lt;/p&gt;
&lt;p&gt;There are numerous reasons for this. The most straightforward reason for this is that &lt;strong&gt;cd&lt;/strong&gt; executed without an argument will change directory to the executing user&#039;s home directory, which is arguably where the script can do the most damage.&lt;/p&gt;
&lt;p&gt;There is one case where your script needs to refer to a relative path, namely if your script is distributed together with other files (e.g. in a zip file) and should be runnable after being unzipped. The script must be able to find files/directories relative to wherever &lt;strong&gt;the script&lt;/strong&gt; resides, so relative to the current working directory does not cut it if the user tries ./zipdir/script.sh. Fortunately, all shells have a $0 that is the path of the script itself. Thus, you do this:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
DATADIR=$(dirname $0)/data&lt;/pre&gt;&lt;p&gt;While you are avoiding things, also avoid shell expanded glob expressions. They are simply too imprecise and it is too easy to get bitten by paths with space in them. In 99 of 100 cases, &lt;strong&gt;find&lt;/strong&gt; is better than shell glob. &lt;strong&gt;find&lt;/strong&gt; is your friend.&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
find /dir/with/cruft -mindepth 1 -maxdepth 1 \
     -type f -regex &#039;.*\.sh&#039; | frobnicate_script&lt;/pre&gt;&lt;p&gt;There are numerous things going on here. mindepth/maxdepth describes how deep to look; a depth of 0 means the path supplied to find, so 1/1 means &quot;look in the directory /dir/with/cruft&quot;. type f means &quot;look only for files&quot;. regex uses regular expressions to match files, which is a lot more expressive than globs (normally supplied to find via -name). It is tempting at this point to reach for -exec, but please refrain. The exec option creates code that is very difficult to read.&lt;/p&gt;
&lt;p&gt;Instead xargs is the friend of your find. If all you want to do is a simple operation on each found file, you can do something like this:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
find $rootdir -mindepth 1 -type d -cmin -10 -print0 | xargs -0 chmod o-rwx&lt;/pre&gt;&lt;p&gt;Or, in English: remove world permissions on all directories under $rootdir that I created the last 10 minutes. Find option -print0 will terminate each line with a null character instead of a newline and -0 will tell xargs to ignore whitespace and instead react to null characters. Presto, no problem with space (or even newlines) in paths.&lt;/p&gt;
&lt;p&gt;Discouraging users from using delimiter characters (such as space, tab, newline, comma, pipe, et.c.) in file and directory names is part of the holy cause. Nevertheless, some file will have them, sometimes even for good reasons. So your script needs to be prepared for them. Quote all data that comes from outside.&lt;/p&gt;
&lt;p&gt;As an aside, it is an annoying aspect of shell scripting that most syntax highlighters will treat e.g. &quot;$1&quot; as a string and give it string colour, but $1 as a variable and give it variable colour. Most unhelpful.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-tags field-type-taxonomy-term-reference field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Tags:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/quest-blog&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;quest-blog&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item odd&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/shell-scripting&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;shell-scripting&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/software-development&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;software-development&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
 <pubDate>Mon, 04 Jul 2011 22:01:21 +0000</pubDate>
 <dc:creator>quest</dc:creator>
 <guid isPermaLink="false">5 at http://quest.windwards.net</guid>
 <comments>http://quest.windwards.net/content/shell-scripting-patterns-paths-file-globs-and-and-current-dir#comments</comments>
</item>
<item>
 <title>Shell scripting patterns: errors and failure</title>
 <link>http://quest.windwards.net/content/shell-scripting-patterns-errors-and-failure</link>
 <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; property=&quot;content:encoded&quot;&gt;&lt;p&gt;In my opinion, error handling is the area where shell script clearest shows its age. The idea that the shell will &lt;strong&gt;by default&lt;/strong&gt; ignore that commands signal an error state (i.e. a non-zero exit code) seems very strange when viewed through the lens of modern programming theory. Thus, all scripts should start with this instruction, that tells the shell to care about exit codes:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
set -e&lt;/pre&gt;&lt;p&gt;Now, the following code will no longer result in tears when /destination does not exist:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
process &amp;lt; /source/file &amp;gt; /destination/file
rm /source/file
&lt;/pre&gt;&lt;p&gt;To explicitly ignore the exit code of a command, use:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
process &amp;lt; /source/file &amp;gt; /no/such/file || true&lt;/pre&gt;&lt;p&gt;... or if you care, but don&#039;t want to just bail, you can:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
may_explode || result=$?&lt;/pre&gt;&lt;p&gt;Just remember that $result will be empty rather than 0 if all goes well, so you cannot do [ $result -gt 0 ].&lt;/p&gt;
&lt;p&gt;In rare cases, it may genuinely be that you have a section of instructions that you&lt;strong&gt; want&lt;/strong&gt; to execute even if the previous fail. If so, use a subshell:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
(
    set +e
    ...
)&lt;/pre&gt;&lt;p&gt;The set operation will only be active in the subshell.&lt;/p&gt;
&lt;p&gt;It is quite possible to achieve something akin to modern exception handling in bash shells. Consider the following:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
(
    do_this || exit 1
    do_that || exit 2
) || {
    fail=$?
    case $fail in
    1) handle_case_1 ;;
    2) handle_case_2 ;;
    *) exit $fail ;;
    esac
}&lt;/pre&gt;&lt;p&gt;Of course, do_this, do_that may already return decent exit codes such that you don&#039;t need the &#039;|| exit&#039; bit. More generally, now that &lt;strong&gt;set -e&lt;/strong&gt; is turned on, you need a mental model of execution flow, much like any other programming language. Just remember the law: &lt;em&gt;any context (be it subshell, function or block) has an exit code/return value of the first statement executed that returns a non-zero exit code/return value.&lt;/em&gt; Somewhat simplified, as soon as a statement returns non-zero, execution will abandon successive scopes until someone &quot;handles&quot; the non-zero state. The three main ways to &quot;handle&quot; the non-zero state are pipe &quot;|&quot;,  command substitution &quot;$()&quot;, or &quot;||&quot;. The background control operator &quot;&amp;amp;&quot; also does not propagate the exit code (it can later be retreived with &lt;strong&gt;wait&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;It may be tempting to use &lt;strong&gt;exit&lt;/strong&gt; to make life simpler inside functions, but you should resist. exit will abort execution of the current shell, but parentheses and pipes create subshells, so a function cannot know whether it will abort the master shell process or just a subshell. Use only return statements in functions and save exit for top-level code. exit should only be needed in top-level code to tell the caller that parameters or input were invalid.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-tags field-type-taxonomy-term-reference field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Tags:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/quest-blog&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;quest-blog&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item odd&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/shell-scripting&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;shell-scripting&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/software-development&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;software-development&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
 <pubDate>Mon, 04 Jul 2011 05:22:28 +0000</pubDate>
 <dc:creator>quest</dc:creator>
 <guid isPermaLink="false">3 at http://quest.windwards.net</guid>
 <comments>http://quest.windwards.net/content/shell-scripting-patterns-errors-and-failure#comments</comments>
</item>
<item>
 <title>Shell scripting patterns: returning from functions</title>
 <link>http://quest.windwards.net/content/shell-scripting-patterns-returning-functions</link>
 <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; property=&quot;content:encoded&quot;&gt;&lt;p&gt;
	One shortcoming of shell scripting is the inability to return anything of significance from a shell script function. Consider: get a function that returns the youngest file in a directory. The basic moving part in this is &lt;strong&gt;ls -tr /da/dir | tail -1&lt;/strong&gt;. Abstracting this to a function seem problematic, given that we cannot return a value. However, functions is very similar to external commands in bash, so you can do this:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
functions latest_file() {
  ls -tr &quot;$1&quot; | tail -1
}&lt;/pre&gt;&lt;p&gt;
	... and then simply invoke it thus:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
latest=$(latest_file /da/dir)&lt;/pre&gt;&lt;p&gt;
	From this point, we can write what effectively is a generator:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
function find_magic_scripts() {
    find $1 -type f -name &#039;*.sh&#039; | while read fname ; do
        grep -l &#039;magic word&#039; $fname || true
    done
}&lt;/pre&gt;&lt;p&gt;
	We can now use it as a source for a consumer:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
find_magic_scripts /da/dir | link_and_version&lt;/pre&gt;&lt;p&gt;
	These two processes will be run in parallel, which is good since they both take a little time. Of course, find_magic_scripts will still block as soon as it has output a file, but will restart as soon as link_and_version has read that line.&lt;/p&gt;
&lt;p&gt;
	However.&lt;/p&gt;
&lt;p&gt;
	There is an issue with this pattern: a sequence of pipes will have the error code for the last command, ignoring any previous failures. So, if /da/dir does not exist, link_and_version will simply get EOF and be happy. Unfortunately, there is no neat workaround that solves all problems. The best strategy is usually to introduce an explicit failure marker in the protocol over the pipe, something like:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
function foo() {
    {
        ...
    } || echo &quot;FAIL $?&quot;
}
foo | bar&lt;/pre&gt;&lt;p&gt;
	Or, where left side is an external command, simply:&lt;/p&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;
{ find /may/not/exist -name &#039;*.sh&#039; || echo &quot;FAIL $?&quot; ; } | bar&lt;/pre&gt;&lt;p&gt;
	Now bar() can know that something went wrong and abort.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-tags field-type-taxonomy-term-reference field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Tags:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/quest-blog&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;quest-blog&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item odd&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/shell-scripting&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;shell-scripting&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/software-development&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;software-development&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
 <pubDate>Tue, 28 Jun 2011 22:12:51 +0000</pubDate>
 <dc:creator>quest</dc:creator>
 <guid isPermaLink="false">1 at http://quest.windwards.net</guid>
 <comments>http://quest.windwards.net/content/shell-scripting-patterns-returning-functions#comments</comments>
</item>
<item>
 <title>Shell scripting patterns - a personal perspective</title>
 <link>http://quest.windwards.net/content/shell-scripting-patterns-personal-perspective</link>
 <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; property=&quot;content:encoded&quot;&gt;&lt;p&gt;It is often said that no serious development project should ever use shell script.&lt;/p&gt;
&lt;p&gt;While it is certainly true that there are some serious shortcomings is the bash strain of shells, this is not to say that these shortcomings cannot be overcome. Like so much else in programming, it is mostly a matter of finding good patterns that contain those shortcomings.&lt;/p&gt;
&lt;p&gt;I want to write something on this matter, so I&#039;m planning a series of blog posts on important patterns that help in keeping bash shell scripts readable and maintainable while keeping a reasonable performance. With luck, they will have something for you as well.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-tags field-type-taxonomy-term-reference field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Tags:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/quest-blog&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;quest-blog&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item odd&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/shell-scripting&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;shell-scripting&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;field-item even&quot; rel=&quot;dc:subject&quot;&gt;&lt;a href=&quot;/tags/software-development&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;software-development&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
 <pubDate>Sat, 25 Jun 2011 11:15:00 +0000</pubDate>
 <dc:creator>quest</dc:creator>
 <guid isPermaLink="false">8 at http://quest.windwards.net</guid>
 <comments>http://quest.windwards.net/content/shell-scripting-patterns-personal-perspective#comments</comments>
</item>
</channel>
</rss>
