<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dariusz on Software Quality</title>
	<atom:link href="http://blog.aplikacja.info/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.aplikacja.info</link>
	<description>Software Engineering Process and Tools</description>
	<lastBuildDate>Sat, 28 Apr 2012 04:58:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Classic Testing vs Design By Contract</title>
		<link>http://blog.aplikacja.info/2012/04/classic-testing-vs-design-by-contract/</link>
		<comments>http://blog.aplikacja.info/2012/04/classic-testing-vs-design-by-contract/#comments</comments>
		<pubDate>Sun, 22 Apr 2012 12:03:47 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[dbc]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1787</guid>
		<description><![CDATA[Automated unit tests are hard to write. Software architecture must be designed carefully to allow unit testing. You have to spend time to write tests as well and it&#8217;s not easy to write good tests. It&#8217;s easy to make big mess that is not easy to maintain after few weeks.
On the other hand automated integration [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Automated unit tests are hard to write</strong>. Software architecture must be designed carefully to allow unit testing. You have to spend time to write tests as well and it&#8217;s not easy to write good tests. It&#8217;s easy to make big mess that is not easy to maintain after few weeks.</p>
<p>On the other hand <strong>automated integration tests are </strong><strong>hard to maintain</strong> and are fragile. You can &#8220;write&#8221; them pretty easy in a record-and-replay tool, but later they show <a href="/2012/03/whats-wrong-with-automated-integration-tests/">their real cost</a> during maintenance.</p>
<p><a href="http://blog.aplikacja.info/wp-content/uploads/2012/04/dilbert-contract1.gif"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1796" title="dilbert-contract" src="http://blog.aplikacja.info/wp-content/uploads/2012/04/dilbert-contract1.gif" alt="" width="640" height="199" /></a></p>
<p>But there&#8217;s an answer for problems mentioned above. Do you know <a href="http://www.eiffel.com/">Eiffel</a> language? The language has special built-in constructs that support executable contract specification. It&#8217;s called <strong>Design By Contract (DBC)</strong>. DBC is easier to write and to maintain because no special test cases need to be specified, just conditions for method parameters, expected results and state invariant that must be preserved. How DBC can substitute old-fashioned tests? Read on!</p>
<p><span id="more-1787"></span></p>
<p>General concepts for DBC are:</p>
<ul>
<li><strong>pre-condition</strong>: you can specify rules for every input parameter to check contract fulfillment from caller side. If a pre-condition is not met that means there&#8217;s something wrong with caller</li>
<li><strong>post-condition</strong>: rules for post-method execution state can be specified as well. You can refer to input parameters, current object state and original object state (before method call)</li>
<li><strong>class invariants</strong>: refers to object members and must be valid after every public class call</li>
</ul>
<p>As an example I&#8217;ll use DBC implementation called &#8220;<a href="http://www.wayforward.net/pycontract/">pycontract</a>&#8221; (Python language). It&#8217;s pretty easy to introduce in a project and uses standard doc-strings (like <a href="http://docs.python.org/library/doctest.html">doctest</a> module). No preprocessing is needed.</p>
<p><strong>Pre-condition</strong> is specified by pre keyword:</p>
<pre style="padding-left: 30px;">pre:
    someObject != None and someObject.property &gt; 0</pre>
<p><strong>Post-condition</strong> syntax uses some special syntax to allow to refer to old values, you have to mention mutable variables object that should be available for state change comparisions:</p>
<pre style="padding-left: 30px;">post[self]:
    self.property = __old__.self.property + 1</pre>
<p>Above statement shows that property should be incremented by one after method return.</p>
<p><strong>Invariant</strong> syntax is as follows:</p>
<pre style="padding-left: 30px;">inv:
    self.state in [OPEN, CLOSED, SENT]</pre>
<p>All above statements must be embedded in method/class comments, here&#8217;s full example:</p>
<pre style="padding-left: 30px;">class SampleClass:
    """
    inv:
        self.state in [OPEN, CLOSED, SENT]
    """
    def open(self, x):
        """
        pre: x &gt; 0
        post: self.state != CLOSED
        """</pre>
<p>DBC assertions (like doc-strings) are <strong>disabled by default</strong> (they are just comments). You can decide to enable them for example in development builds (there&#8217;s an overhead related to DBC). An example how to enable pycontract:</p>
<pre style="padding-left: 30px;">import contract
contract.checkmod(modulename1)
contract.checkmod(modulename2)</pre>
<p><strong>Example failure</strong> (postcondition not met) caught by DBC:</p>
<pre style="padding-left: 30px;">DokumentFiskalny.testDokumentu() Traceback (most recent call last):
  File "test.py", line 164, in
    run_tests()
  File "test.py", line 144, in run_tests
    run_test_module(db, dao, moduleName)
  File "test.py", line 54, in run_test_module
    exec("%s.%s(env)" % (sName, sItem))
  File "", line 1, in
  File "", line 3, in __assert_testDokumentu_chk
  File "lib/contract.py", line 1064, in call_public_function_all
    return _call_all([func], func, va, ka)
  File "lib/contract.py", line 1233, in _call_all
    result = func.__assert_orig(*va, **ka)
  File "/home/darek/public_html/kffirma/DokumentFiskalny.py", line 433, in testDokumentu
    df.zapisz(args)
  File "/home/darek/public_html/kffirma/DokumentFiskalny.py", line 254, in zapisz
    args["idPodmiotuGospodarczego"],
  File "", line 3, in __assert_DokumentFiskalny__create_chk
  File "lib/contract.py", line 1165, in call_private_method_all
    return _method_call_all(getmro(cls), method, va, ka)
  File "lib/contract.py", line 1205, in _method_call_all
    return _call_all(a, func, va, ka)
  File "lib/contract.py", line 1241, in _call_all
    p(old, result, *va, **ka)
  File "", line 3, in __assert_DokumentFiskalny__create_post
  File "/home/darek/public_html/kffirma/DokumentFiskalny.py", line 155, in _create_post
    assert len(result) &gt;= 2</pre>
<p>The last part of this puzzle is <strong>coverage generation</strong>. DBC assertions are evaluated at runtime, so you have to ensure enough percentage code is execute during test runs. Im my experience you can rely on:</p>
<ul>
<li>integration-like scenarios (without explicit result verification)</li>
<li>random input generation</li>
</ul>
<p>For both cases you can integrate at high, UI level (keyboard, remote controller, HTTP, &#8230;).</p>
<p><strong>Focus on quality techniques is crucial for any software project</strong>. If you (1) pay some effort in making your codebase resistant to regressions and (2) maintain that state during project lifetime you can gain more stable software. The real craft lies in selecting proper tools and having enough energy to implement them.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/04/classic-testing-vs-design-by-contract/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Auto Profiling For Continuous Integration</title>
		<link>http://blog.aplikacja.info/2012/04/auto-profiling-for-continuous-integration/</link>
		<comments>http://blog.aplikacja.info/2012/04/auto-profiling-for-continuous-integration/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 21:49:33 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[profiling]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1782</guid>
		<description><![CDATA[When you have auto-build and auto-test process already in place you can use the same infrastructure to catch early performance problems as well. It&#8217;s not as complicated as you may think.
First of all you can monitor your CPU/IO usage during tests and take snapshots on &#8220;errant&#8221; situation. If there&#8217;s no high local processing probably 100% [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2012/04/clock.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-thumbnail wp-image-1783" title="clock" src="http://blog.aplikacja.info/wp-content/uploads/2012/04/clock-150x150.jpg" alt="" width="150" height="150" /></a>When you have auto-build and auto-test process already in place you can use the same infrastructure to catch early <strong>performance problems</strong> as well. It&#8217;s not as complicated as you may think.</p>
<p>First of all you can <strong>monitor your CPU/IO usage</strong> during tests and take snapshots on &#8220;errant&#8221; situation. If there&#8217;s no high local processing probably 100% CPU usage means that there are some performance problems in your software. Sample:</p>
<pre style="padding-left: 30px;">top -b -n 1 | awk '
  / 0% idle/ { enable=1 }
  $7 &gt; 20 &amp;&amp; $0 &amp;&amp; enable { print "kill -SIGUSR2 " $1; }
' | sh</pre>
<p>Above script <strong>checks for 0% idle time</strong> and sends every process that uses above 20% of CPU SIGUSR2 signal. Installed signal handler will make snapshot of current running thread and will give enough information to fix the performance issue.</p>
<p><span id="more-1782"></span></p>
<p>If your environment doesn&#8217;t allow to inspect current thread state at any time you can try to guess performance problems source and can introduce <strong>special profiling code</strong> to catch problems early. For example: typical performance problem is resource over-usage. Resource (remote server, database, &#8230;) may be called very often to retrieve the same data &#8211; it&#8217;s a candidate for local caching.</p>
<pre style="padding-left: 30px;">void ResourceProfiler::count() {
    if (!triggerCount) {
        return;
    }
    counter++;
    if (counter &gt;= triggerCount) {
        time_t deltaS = time(NULL) - timeOfFirstOccurenceS;
        if (deltaS &lt;= intervalS) {
            const int BUFFER_SIZE = 256;
            char buffer[BUFFER_SIZE];
            snprintf(buffer, BUFFER_SIZE, "Abused resource: %s=%d, %s=%ds", ENV_TRIGGER_COUNT, counter, ENV_INTERVAL_S, intervalS);
            warning(buffer);
        }
        timeOfFirstOccurenceS = 0;
        counter = 0;
    } else if (!timeOfFirstOccurenceS) {
        timeOfFirstOccurenceS = time(NULL);
    }
}</pre>
<p>Above example shows core method of <strong>resource usage profiling</strong> code that issues a warning when there are more than triggerCount events in intervalS time frame. You can install this handler by calling count() when given resource is used (served is called, database record is loaded, &#8230;). Over-usage will be located dynamically during auto-tests.</p>
<p>Above method can be generalized to <strong>count usage per SQL query</strong> to locate very frequent SQL queries (typical N+1 SELECT problem). Instead of use one counter use Map&lt;String, int&gt; for counters and Map&lt;String, time_t&gt; for timestamps. It&#8217;s left as an exercise for a reader.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/04/auto-profiling-for-continuous-integration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#8217;s Wrong With Automated Integration Tests?</title>
		<link>http://blog.aplikacja.info/2012/03/whats-wrong-with-automated-integration-tests/</link>
		<comments>http://blog.aplikacja.info/2012/03/whats-wrong-with-automated-integration-tests/#comments</comments>
		<pubDate>Thu, 15 Mar 2012 23:08:25 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[reliability]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1774</guid>
		<description><![CDATA[A quite typical picture: software development company X, first delivery of project Y to testing team after few months of coding just failed because software is so buggy and crashes so often. Project Manager decides to invest some money in automated testing tool that will solve all stability problems with click-and-replay interface. Demos are very [...]]]></description>
			<content:encoded><![CDATA[<p>A quite typical picture: software development company X, first delivery of project Y to testing team after few months of coding just failed because software is so buggy and crashes so often. Project Manager decides to invest some money in <strong>automated testing tool</strong> that will solve all stability problems with click-and-replay interface. Demos are very impressive. The tool was integrated and a bunch of tests were &#8220;clicked&#8221;.</p>
<p>After a month we have <strong>10% of tests that are failing</strong>. 10% is not a big deal, we can live with them. After additional month 30% of tests fails because important screen design was changed and some tests cannot authorize them for some reason. Pressure for next delivery increases, chances to delegate some testers to fix failing test cases are smaller every week.</p>
<p>What are the final results of above tool?</p>
<ul>
<li>unmaintained set of tests (and the tool itself) is abandoned</li>
<li>man-days lost for setting up test cases</li>
<li>$$ lost for the tool and training</li>
</ul>
<p>Has the tool been introduced too late? Maybe wrong tool was selected?</p>
<p>In my opinion automation and integration tests don&#8217;t play well together. Let&#8217;s review then main <strong>enemies of automation in integration tests</strong>:</p>
<h2><span id="more-1774"></span>Initial state setup of environment and system itself</h2>
<p>For unit-level tests you can easily control local environment by setting up mocks to isolate other parts of system. If you want test integration issues you have to face with <strong>integration-level complexity</strong>.</p>
<p>No more simple setups! If you want to setup state properly to get expected result you MUST explicitly set state whole environment. Sometimes it&#8217;s just impossible or extremely complicated to set it using UI. If you set states improperly (or just accept existing state as a starting point) you will end with random result changes that will make tests useless.</p>
<h2>Result retrieval after operation</h2>
<p>OK, we scheduled action A and want to check if record was updated in DB or not. In order to do that some list view is opened and record is located using search. Then record is opened and we can add expectations to that screen.</p>
<p>OK, but if we want to check if &#8220;e-mail was sent&#8221;? We cannot see that in application UI. Catching on SMTP level will be too unreliable and slow (timings).</p>
<p>It will just not work smoothly.</p>
<h2>What&#8217;s next then?</h2>
<p>It&#8217;s easy to criticize everything without proposing (and implementing) efficient alternatives.</p>
<p>My vision of integration testing<strong>:</strong></p>
<ul>
<li><strong>I&#8217;m not checking results</strong> for automated integration testing, it <span style="text-decoration: line-through;">will just doesn&#8217;t work</span> cannot be maintained efficiently</li>
<li>I&#8217;m usually generating <strong>random input</strong> to cover as much functionality as possible using high level interfaces (UI)</li>
<li>I depend on <strong>internal assertions/design by contract</strong> to catch problems during such random-based testing, they serve as an oracle (the more the results are better)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/03/whats-wrong-with-automated-integration-tests/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Linux: How To Locate Duplicated Files Quickly</title>
		<link>http://blog.aplikacja.info/2012/02/linux-how-to-locate-duplicated-files-quickly/</link>
		<comments>http://blog.aplikacja.info/2012/02/linux-how-to-locate-duplicated-files-quickly/#comments</comments>
		<pubDate>Sat, 25 Feb 2012 13:34:11 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sh]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1766</guid>
		<description><![CDATA[Locate duplicates quickly: I mean only size+filename check, not expensive MD5 sum computation:
find . -printf "%f:%s:%p\n" -type f &#124; \
    awk -F: '
        {
            key=$1 " " $2;
       [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/12/linux.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-thumbnail wp-image-1681" title="linux" src="http://blog.aplikacja.info/wp-content/uploads/2011/12/linux-150x150.jpg" alt="" width="150" height="150" /></a>Locate duplicates <strong>quickly</strong>: I mean only size+filename check, not expensive MD5 sum computation:</p>
<pre style="padding-left: 30px;">find . -printf "%f:%s:%p\n" -type f | \
    awk -F: '
        {
            key=$1 " " $2;
            occur[key]++;
            loc[key]=loc[key] $3 " "
        }
        END {
            for(key in occur) {
                if(occur[key]&gt;1) {
                    print key ": " loc[key]
                }
            }
        }
    ' | sort</pre>
<p>A bit of explanation of above magic:</p>
<ul>
<li><em>printf</em>: tells find command to output file metadata instead of only file path (the default), this metadata (size, filename) will be used later</li>
<li><em>-F:</em> :We want to handle properly paths with spaces, that&#8217;s why special separator is used</li>
<li><em>key=$1 &#8221; &#8221; $2</em>: we use file name (without dir) and file size to create ID for this file</li>
<li><em>occur</em>: table (key -&gt; number of file occurences)</li>
<li><em>loc</em>: maps file ID to list of locations found</li>
<li><em>occur[key]&gt;1</em>: we want to show only files that have duplicates</li>
<li><em>sort</em>: results are sorted alphabetically for easier navigation</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/02/linux-how-to-locate-duplicated-files-quickly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web2py Lighttpd Deployment</title>
		<link>http://blog.aplikacja.info/2012/02/leb2py-lighttpd-deploytment/</link>
		<comments>http://blog.aplikacja.info/2012/02/leb2py-lighttpd-deploytment/#comments</comments>
		<pubDate>Sun, 19 Feb 2012 07:29:07 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[web2py]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1759</guid>
		<description><![CDATA[Web2py is &#8220;full stack&#8221; Python Web Framework, Lighttpd is fast, multi-threaded HTTP server. I&#8217;ll present a method to connect web2py-based application under lighttpd.
I assume the following setup is already done:

A domain named &#8220;myapp.com&#8221; is configured to point to your server
Python / lighttpd is already installed on server
Your web2py app is placed under /var/www/web2py
Your web2py app [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://web2py.com/"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1723" title="web2py" src="http://blog.aplikacja.info/wp-content/uploads/2012/01/web2py.jpeg" alt="" width="314" height="58" />Web2py</a> is &#8220;full stack&#8221; Python Web Framework, <a href="http://www.lighttpd.net/">Lighttpd</a> is fast, multi-threaded HTTP server. I&#8217;ll present a method to connect web2py-based application under lighttpd.</p>
<p>I assume the following setup is already done:</p>
<ul>
<li>A domain named &#8220;<em>myapp.com</em>&#8221; is configured to point to your server</li>
<li>Python / lighttpd is already installed on server</li>
<li>Your web2py app is placed under /var/www/web2py</li>
<li>Your web2py app has application &#8220;myapproot&#8221; configured</li>
</ul>
<p>First of all, you have to configure lighttpd to locate web2py application,  create file /etc/lighttpd/conf-enabled/myapp.conf:</p>
<p><span id="more-1759"></span></p>
<pre style="padding-left: 30px;">$HTTP["host"] =~ "(www\.)?myapp\.com" {
	server.indexfiles = ( "/myapproot" )
	server.document-root = "/var/www/myapp"
	server.dir-listing = "disable"
	fastcgi.server = (
		".fcgi" =&gt; ("localhost" =&gt; (
			"check-local" =&gt; "disable",
			"min-procs" =&gt; "1",
			"max-procs" =&gt; "2",
			"socket" =&gt; "/tmp/myapp.sock")
		)
	)

	url.rewrite-once = (
		"^/$" =&gt; "/ad",
		"^(/.+?/static/.+)$" =&gt; "/applications$1",
		"(^|/.*)$" =&gt; "/fcgihandler.fcgi$1",
	)
	$HTTP["url"] !~ "^(/ad|/fcgihandler.fcgi|/applications/myapproot/static/)" {
		url.access-deny = ("")
	}
}</pre>
<p>Explanation:</p>
<ul>
<li> <em>(www\.)?myapp\.com</em>: regular expression to match domain with or without &#8220;www.&#8221; prefix</li>
<li><em>server.indexfiles</em>: specifies relative URL that should be called when only domain is given</li>
<li> <em>server.document-root</em>: specifies location of web2py app in filesystem</li>
<li> <em>server.dir-listing</em>: we do not want user to list our files using HTTP<em> </em></li>
<li><em> fastcgi.server</em>: specifies where socket file is located</li>
<li> <em>url.rewrite-once</em>: allow to use elegant (short) URLs</li>
<li> <em>url.access-deny</em>: files other than static directory should be forbidden (security)</li>
</ul>
<p>Then you have to configure fcgihandler.fcgi script properly:</p>
<pre style="padding-left: 30px;">(...)
fcgi.WSGIServer(application, bindAddress='/tmp/myapp.sock').run()</pre>
<p>Note that /tmp/myapp.sock must be the same as specified in lighttpd configuration.</p>
<p>Then you have to start the fcgihandler.fcgi proces and ensure it will start on every boot. That&#8217;s all.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/02/leb2py-lighttpd-deploytment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Large C++ Project Build Time Optimisation</title>
		<link>http://blog.aplikacja.info/2012/02/large-c-project-build-time-optimisation/</link>
		<comments>http://blog.aplikacja.info/2012/02/large-c-project-build-time-optimisation/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 01:07:39 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[c++]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1752</guid>
		<description><![CDATA[When you hit some level of code size in a project you starting to observe the following sequence:

Developer creates and tests a feature
Before submitting commit to repository update/fetch/sync is done
Developer builds project again to check if build/basic functionality is not broken
Smoke tests
Submit

During step 3 you hear &#8220;damn slow rebuild!&#8221;. One discovers that synchronization with repository [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2012/02/cpp.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1753" title="cpp" src="http://blog.aplikacja.info/wp-content/uploads/2012/02/cpp.jpg" alt="" width="264" height="191" /></a>When you hit some level of <strong>code size in a project</strong> you starting to observe the following sequence:</p>
<ol>
<li>Developer creates and tests a feature</li>
<li>Before submitting commit to repository update/fetch/sync is done</li>
<li><strong>Developer builds project again to check if build/basic functionality is not broken</strong></li>
<li>Smoke tests</li>
<li>Submit</li>
</ol>
<p>During step 3 you hear &#8220;damn slow rebuild!&#8221;. One discovers that synchronization with repository forces him to <strong>rebuild 20% of files</strong> in a project (and it takes time when project is really huge). Why?</p>
<p>The answer here is: <strong>header dependencies</strong>. Some header files are included (directly and indirectly) in many source code files, that&#8217;s rebuild of so many files is needed. You have the following options:</p>
<ul>
<li>Skip build dependencies and pray resulting build is stable / working at all</li>
<li>Reduce header dependencies</li>
</ul>
<p>I&#8217;ll explain second option.</p>
<p><span id="more-1752"></span></p>
<p>The first thing to do is to locate problematic headers. Here&#8217;s a script that will find most problematic headers:</p>
<pre style="padding-left: 30px;">#!/bin/sh

awk -v F=$1 '
/^# *include/ {
    a=$0; sub(/[^&lt;"]*[&lt;"]/, "", a); sub(/[&gt;"].*/, "", a); uses[a]++;
    f=FILENAME; sub(/.*\//, "", f); incl[a]=incl[a] f " ";
}

function compute_includes(f, located,
arr, n, i, sum) {
    # print "compute_includes(" f ")"
    if (f ~ /\.c/) {
        if (f in located) {
            return 0
        }
        else {
            located[f] = 1
            return 1
        }
    }
    if (!(f in incl)) {
        return 0
    }
    # print f "-&gt;" incl[f]
    n = split(incl[f], arr)
    sum = 0
    for (i=1; i&lt;=n; i++) {
        if (f != arr[i]) {
            sum += compute_includes(arr[i], located)
        }
    }
    return sum
}

END {
    for (a in incl) {
        n = compute_includes(a, located)
        if (F) {
            if (F in located &amp;&amp; a !~ /^Q/) {
                print n, a
            }
        }
        else {
            if (n &amp;&amp; a !~ /^Q/) {
                print n, a
            }
        }
        for (b in located) {
            delete located[b]
        }
    };
}

' `find . -name \*.cpp -o -name \*.h -o -name \*.c` \
| sort -n</pre>
<p>﻿Sample output:</p>
<pre style="padding-left: 30px;">266 HiddenChannelsDefinitions.h
266 nmc-hal/hallogger.h
268 favoriteitemdefinitions.h
270 nmc-hal/playback.h
279 pvrsettingsitemdefinitions.h
279 subscriberinfoquerier.h
280 isubscriberinfoquerier.h
286 notset.h
292 asserts.h</pre>
<p>As you can see there are header files that require ~300 source files to be rebuilt after change. You can start optimisations with those files.</p>
<p>If you locate headers to start with you can use the following techniques:</p>
<ul>
<li>Use forwad declaration (class XYZ) instead of header inclusion (#include &#8220;XYZ.h&#8221;) when possible</li>
<li>Split large header files into smaller ones, rearrange includes</li>
<li>Use <a href="http://c2.com/cgi/wiki?PimplIdiom">PIMPL</a> to split interfaces from implementations</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/02/large-c-project-build-time-optimisation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Monitor Multicast UDP Traffic</title>
		<link>http://blog.aplikacja.info/2012/02/monitor-multicast-udp-traffic/</link>
		<comments>http://blog.aplikacja.info/2012/02/monitor-multicast-udp-traffic/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 00:42:11 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[network]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1743</guid>
		<description><![CDATA[Recently I was diagnosing problems with missing multicast data for some system. Multicast send UDP packets from single source to many registered subscribers. IPTV is using this feature to stream video for example. For unicast (1-1) transmissions you can use netcat or telnet but what tool can test multicast data?
The answer was located pretty quickly: [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2012/02/cable-ethernet.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1744" title="cable-ethernet" src="http://blog.aplikacja.info/wp-content/uploads/2012/02/cable-ethernet.jpg" alt="" width="309" height="261" /></a>Recently I was diagnosing problems with <strong>missing multicast data</strong> for some system. Multicast send UDP packets from single source to many registered subscribers. <a href="http://en.wikipedia.org/wiki/IPTV">IPTV</a> is using this feature to stream video for example. For unicast (1-1) transmissions you can use netcat or telnet but what tool can test multicast data?</p>
<p>The answer was located pretty quickly: <a href="http://www.dest-unreach.org/socat/">socat</a> tool can register to multicast sources and pipe output to many destinations (stdout for example). Let&#8217;s give a sample first:</p>
<pre style="padding-left: 30px;">socat UDP4-RECVFROM:<strong>9875</strong>,ip-add-membership=<strong>225.2.215.254</strong>:0.0.0.0,fork -\
 | grep -a <strong>'^s='</strong></pre>
<p>Values to change:</p>
<ul>
<li>225.2.215.254: sample multicast IP address</li>
<li>9875: sample multicast port</li>
<li> ^s=: string to be located in multicast data (in my case data protocol is textual)</li>
</ul>
<p>Explanation:</p>
<ul>
<li>UDP4-RECVFROM: receive IPv4 UDP packets</li>
<li>ip-add-membership: multicast requires registering of packets receiver</li>
<li>0.0.0.0: accept multicast on any client interface (you can specify here your client network address here as well)</li>
<li>grep -a: sometimes you need just subset of incoming data, in my case textual data was mixed with binary (-a parameter for grep)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/02/monitor-multicast-udp-traffic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>8 types of waste in Lean Software Development</title>
		<link>http://blog.aplikacja.info/2012/02/8-types-of-waste-in-lean-software-development/</link>
		<comments>http://blog.aplikacja.info/2012/02/8-types-of-waste-in-lean-software-development/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 23:31:24 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[lean]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1729</guid>
		<description><![CDATA[Lean methodology is a &#8220;production practice that considers the expenditure of resources  for any goal other than the creation of value for the end customer to be  wasteful, and thus a target for elimination&#8221;. Lean ideas were moved into Software Development Fields by Marry and Tom Poppendieck. It&#8217;s interesting how general idea behind [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2012/02/factory.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1738" title="factory" src="http://blog.aplikacja.info/wp-content/uploads/2012/02/factory.jpg" alt="" width="200" height="168" /></a><a href="http://en.wikipedia.org/wiki/Lean_manufacturing"></a>Lean methodology is a &#8220;production practice that considers the expenditure of resources  for any goal other than the creation of value for the end customer to be  wasteful, and thus a target for elimination&#8221;. Lean ideas were moved into Software Development Fields by <a href="http://www.poppendieck.com/">Marry and Tom Poppendieck</a>. It&#8217;s interesting how general idea behind &#8220;Lean&#8221; (originally applied to manufacturing) can be applied for other fields (software development in this case).</p>
<h2>Waste of Over-production</h2>
<p>Have you ever developed a module that was never used in final product? Or end users weren&#8217;t using some functionality because it was too complicated? You will probably say &#8220;yes&#8221; here (like me). How can we eliminate unneeded functionality from specs? How can we validate user interface to ensure a part of a system will be useful before actual build?</p>
<p>We have two opposite options here: <strong>prototyping</strong> with detailed design (yeah, Waterfall!), and <strong>iterative</strong> functionality delivery (bye, bye fixed-price contracts, welcome estimated iteration deliverables). The former is better for customer (&#8220;my budget is fixed&#8221;), the latter for development shop (lower risk of invalid estimates).</p>
<p><span id="more-1729"></span></p>
<h2>Waste of Defects</h2>
<p>The Holly Grall of software development methodologies: to limit number of defects. There are many approaches here:</p>
<ul>
<li>Test-in quality at the end of a whole process (worst case IMHO)</li>
<li>Parallel tests with development (waste of repeated tests)</li>
<li>Automated system-level tests (may be hard to maintain!)</li>
<li>Automated unit-level tests (my choose)</li>
<li>Random DBC-based system level tests (promising &#8230;)</li>
</ul>
<p>Defect means: slower delivery and it&#8217;s waste of resources (time, QA time, &#8230;).</p>
<h2>Waste of Inventory</h2>
<p>Means &#8220;Holding inventory (material and information) more than required&#8221;. Looks like it&#8217;s missing continuous integration practices. If you working on a topic too long time integration effort might me much bigger than syncing in smaller steps (minimum once a day?). The only problem with frequent syncing might me hitting regression (thus slowing work). But we can handle that by automated testing (see &#8220;Defect&#8221; above).</p>
<h2>Waste of Over-Processing</h2>
<p>&#8220;Processing more than required wherein a simple approach would have done&#8221; tells us we should prefer KISS (Keep It Simple Stupid) over heavy frameworks and complicated (fat) interfaces. In my opinion not the completeness of an interface designates it&#8217;s quality. Better interfaces are ones that are harder to be used in incorrect way (for example: eliminate default constructor if it does not have sense).</p>
<h2>Waste of Transportation</h2>
<p>&#8220;Movement of items more than required resulting in wasted efforts and energy and adding to cost&#8221;, in my field possible wastes are:</p>
<ul>
<li>duplicating bugtrackers within one project &#8211; needs syncing in both directions</li>
<li>duplicating version control storage (local SVNs + central Perforce as a real example) &#8211; requires syncing methods</li>
<li>submitting code always to more than one branch &#8211; is it better to cherry-pick set of commits from branch A to B then retest before submit?</li>
</ul>
<h2>Waste of Waiting</h2>
<p>If team A is waiting for team B to produce module that will be used by team A it&#8217;s a waste of waiting. The solution:</p>
<ul>
<li>Create draft interfaces</li>
<li>Stub implementations from lower layer</li>
</ul>
<p>Then upper level modules can be started in parallel with lover level and stubs can be eliminated during integration. Interface will emerge as a result of two processes (A requirements + B possibilities).</p>
<h2>Waste of Motion</h2>
<p>How many &#8220;proxies&#8221; do we have for any information flow? Is there a person that just pushes some messages between customer and programmers without added value? Maybe we can make flows shorter (they will be faster and more effective).</p>
<h2>Waste of Un-utilized People</h2>
<p>Looks very similar to &#8220;Waste of waiting&#8221;. Our work strictly depends on people. We can improve our tools but people will be always be most important in software development activities. Avoid &#8220;push&#8221;-style, prefer &#8220;pull&#8221;-style work item assignment.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/02/8-types-of-waste-in-lean-software-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HOWTO: cleanup old files under Linux</title>
		<link>http://blog.aplikacja.info/2012/01/howto-cleanup-old-files-under-linux/</link>
		<comments>http://blog.aplikacja.info/2012/01/howto-cleanup-old-files-under-linux/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 13:29:56 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sh]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1726</guid>
		<description><![CDATA[Sometimes you want to separate old files (for example older than 30 days) into separate subdirectory to make navigation easier. Using Linux tools it&#8217;s pretty easy task:
mkdir -p OLD; find . -maxdepth 1 -mtime +30 -exec mv \{\} OLD \;
Explanation:

mkdir -p OLD: create OLD subdirectory if not exists
-maxdepth 1: search only one level under current [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/12/linux.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1681" title="linux" src="http://blog.aplikacja.info/wp-content/uploads/2011/12/linux.jpg" alt="" width="200" height="238" /></a>Sometimes you want to <strong>separate old files</strong> (for example older than 30 days) into separate subdirectory to make navigation easier. Using Linux tools it&#8217;s pretty easy task:</p>
<pre style="padding-left: 30px;">mkdir -p OLD; find . -maxdepth 1 -mtime +30 -exec mv \{\} OLD \;</pre>
<p>Explanation:</p>
<ul>
<li><strong>mkdir -p OLD</strong>: create OLD subdirectory if not exists</li>
<li><strong>-maxdepth 1</strong>: search only one level under current working directory</li>
<li><strong>-mtime +30</strong>: find only files that are older than 30 days</li>
<li><strong>-exec &#8230;. \;</strong>: for every file/directory found execute the following command</li>
<li><strong>\{\}</strong>: will be replaced by filename</li>
</ul>
<p>Above command will move all old files/subdirectories into OLD subdirectory.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/01/howto-cleanup-old-files-under-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Static verificaiton tool for web2py templates</title>
		<link>http://blog.aplikacja.info/2012/01/static-verificaiton-tool-for-web2py-templates/</link>
		<comments>http://blog.aplikacja.info/2012/01/static-verificaiton-tool-for-web2py-templates/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 23:09:24 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[quality]]></category>
		<category><![CDATA[static]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[web2py]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1722</guid>
		<description><![CDATA[Web2Py is a full-stack Python web framework that can be compared to Django, but is easier to learn due to convention-over-explicit-statement preference. In this article I&#8217;ll check how static verification techniques developed by me for many different environments (JSP, Django templates, TAL, &#8230;) can be applied for web2py environment.
Static verification means locating simple bugs without [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://web2py.com/"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-medium wp-image-1723" title="web2py" src="http://blog.aplikacja.info/wp-content/uploads/2012/01/web2py-300x54.jpg" alt="" width="300" height="54" />Web2Py</a> is a full-stack Python web framework that can be compared to <a href="https://www.djangoproject.com/">Django</a>, but is easier to learn due to convention-over-explicit-statement preference. In this article I&#8217;ll check how <strong>static verification techniques</strong> developed by me for many different environments (JSP, Django templates, TAL, &#8230;) can be applied for web2py environment.</p>
<p><strong>Static verification</strong> means locating simple bugs without running application thus very high (&gt;95%) testing coverage (and high related cost) is not required. Instead with trying to cover by tests every possible screen/workflow/code line/&#8230; we can scan all codebase and search for some constraints. Most of them (based on my experience) are static &#8211; do not depend on runtime data thus can be effectively checked without running an application.</p>
<p><span id="more-1722"></span></p>
<p>Here&#8217;s short example of web2py template language:</p>
<pre style="padding-left: 30px;">&lt;a href="{{=URL('books','show')}}"&gt;...&lt;/a&gt;</pre>
<p>As you can see web2py will substitute {{=&lt;python-expression&gt;}}s by evaluated result. In this example URL points to existing module controllers/books.py and function inside this module named &#8217;show&#8217;. I assume you see the problem here: one can select unknown module / function and it will result in runtime error.</p>
<p>First example is <strong>purely static</strong>: refence (URL(&#8216;books&#8217;,&#8217;show&#8217;)) will not change during runtime, neither the source code. Then our static checker might be applied succesfully: check if all URL&#8217;s in all *.html files have proper functions defined in source code.</p>
<p>Technical solution can be composed to the following steps:</p>
<ul>
<li>locating all resources to check: scanning given directory in filesystem tree</li>
<li>locating all interesting fragments in HTML file: I used regexp with arguments to easily extract interesting data</li>
<li>locating functions in *.py code: because controllers are not plain python modules (expects some data in global namespace) I decided just to scan them textually</li>
</ul>
<p>Another check that can be done is references inside HTML files (to CSS resources, JS files, &#8230;). This also can be automated:</p>
<pre style="padding-left: 30px;">&lt;script type="text/javascript" src="svgcanvas.min.js"&gt;&lt;/script&gt;
</pre>
<p>Source code refactorings might break your links/references and static scan might ensure you are not breaking application by refactoring.</p>
<p>Complete source code for URL() / SRC= / HREF=  checker:</p>
<pre style="padding-left: 30px;">import sys

sys.path.append("web2py/applications")
sys.path.append("web2py")

import os
import copy
import re
import string
from gluon.globals import *
from gluon.http import *
from gluon.html import *

RE_SRC = re.compile(r'src *= *"([^"]*)"')
RE_HREF = re.compile(r'href *= *"([^"]*)"')
RE_URL = re.compile(r'{{=URL\(\'([^\']*)\'')
RE_URL2 = re.compile(r'{{=URL\(\'([^\']*)\' *, *\'([^\']*)\'')

FILENAME= None
FNR = 0

request = Request()

def report_error(s):

    print "%s:%d: %s" % (FILENAME, FNR, s)

def check_src_exists(arg):

    if arg[0] == "{":
        # variable value
        return

    elif arg[0].find("{{"):
        # skip this URL
        pass

    elif arg[0] == "/":
        # absolute file
        fullPath = "web2py/applications" + "/" + arg
        if not os.path.exists(fullPath):
            report_error("file %s doesn't exists" % fullPath)

    else:
        # relative file
        fullPath = os.path.dirname(FILENAME) + "/" + arg
        if not os.path.exists(fullPath):
            report_error("file %s doesn't exists" % fullPath)

def check_href_exists(arg):

    #print arg
    if arg.startswith("{{="):
        pass
    elif arg.find("{{") &gt; 0:
        pass
    elif arg.startswith("/"):
        if not os.path.exists("web2py/applications" + arg):
            report_error("absolute file %s doesn't exists" % arg)
    elif arg.startswith("http://"):
        # external link, do not check
        pass
    elif arg.startswith("https://"):
        # external link, do not check
        pass
    elif arg.startswith("mailto:"):
        # external link, do not check
        pass
    elif arg.startswith("javascript:"):
        # external link, do not check
        pass
    elif arg.find("#") == 0:
        # anchor, skip
        pass
    else:
        fullPath = os.path.dirname(FILENAME) + "/" + arg
        if not os.path.exists(fullPath):
            report_error("relative file %s doesn't exists" % fullPath)

def templatePathToPythonPath(templatePath):

    return string.join(templatePath.replace("/views/", "/controllers/").split("/")[:-1], "/") + ".py"

def eq(got, expected):
    if got != expected:
        print "got:'%s' != expected:'%s'" % (got, expected)
        return False
    return True

assert eq(templatePathToPythonPath(
    "web2py/applications/ad/views/default/details.html"),
    "web2py/applications/ad/controllers/default.py")
assert eq(templatePathToPythonPath(
    "web2py/applications/ad/views/default/index.html"),
    "web2py/applications/ad/controllers/default.py")
assert eq(templatePathToPythonPath(
    "web2py/applications/examples/views/ajax_examples/index.html"),
    "web2py/applications/examples/controllers/ajax_examples.py")

name_to_contents = {}
def get_file_contents(fileName):

    global name_to_contents
    if not name_to_contents.has_key(fileName):
        if os.path.exists(fileName):
            f = file(fileName)
            name_to_contents[fileName] = f.read()
            f.close()
        else:
            report_error("Cannot load %s" % fileName)
            name_to_contents[fileName] = ""
    return name_to_contents[fileName]

def check_url_exists(url):

    if FILENAME.find("appadmin.html") &gt; 0:
        return

    if url.find(".") &gt; 0:
        functionName = url.split(".")[-1]
    else:
        functionName = url

    # print "check_url_exists(%s) moduleName=%s" % (url, moduleName)
    pythonFilePath = templatePathToPythonPath(FILENAME)

    if get_file_contents(pythonFilePath).find("def " + functionName + "()") &lt; 0:
        report_error("cannot find %s in %s" % (functionName, pythonFilePath))

def check_url2_exists(moduleName, functionName):

    if moduleName == "static":
        return

    # print "check_url_exists(%s) moduleName=%s" % (url, moduleName)
    pythonFilePath = string.join(FILENAME.replace("/views/", "/controllers/").split("/")[:-1], "/") + "/" + moduleName + ".py"

    if get_file_contents(pythonFilePath).find("def " + functionName + "()") &lt; 0:
        report_error("cannot find %s in %s" % (functionName, pythonFilePath))

def scan_file(path):

    global FILENAME
    global FNR

    FILENAME = path
    FNR = 0

    f = file(path)

    while 1:
        FNR += 1
        line = f.readline()
        if not line:
            break

        m = RE_SRC.search(line)
        if m:
            check_src_exists(m.group(1))

        m = RE_HREF.search(line)
        if m:
            check_href_exists(m.group(1))

        m = RE_URL2.search(line)
        if m:
            check_url2_exists(m.group(1), m.group(2))
        else:
            m = RE_URL.search(line)
            if m:
                check_url_exists(m.group(1))

    f.close()

def test_html(directory):

    for a in os.listdir(directory):
        if a == "epydoc":
            continue
        p = directory + "/" + a
        if os.path.isdir(p):
            test_html(p)
        if a.endswith(".html"):
            scan_file(p)

test_html("web2py/applications")
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/01/static-verificaiton-tool-for-web2py-templates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Configure locales under Ubuntu</title>
		<link>http://blog.aplikacja.info/2012/01/generate-locales-under-ubuntu/</link>
		<comments>http://blog.aplikacja.info/2012/01/generate-locales-under-ubuntu/#comments</comments>
		<pubDate>Thu, 12 Jan 2012 21:54:10 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1719</guid>
		<description><![CDATA[If you used to Debian you probably know that &#8220;dpkg-reconfigure locales&#8221; brings you locale selection tool. It&#8217;s not the case for Ubuntu. How to replace Debian&#8217;s behavior? Read below:
# grep pl_PL.UTF-8 /usr/share/i18n/SUPPORTED &#62; /var/lib/locales/supported.d/local
# dpkg-reconfigure locales
   Generating locales...
     pl_PL.UTF-8... done
   Generation complete.
Above example show how to add [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2009/12/debian.png"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-571" title="debian" src="http://blog.aplikacja.info/wp-content/uploads/2009/12/debian.png" alt="" width="179" height="61" /></a>If you used to Debian you probably know that &#8220;dpkg-reconfigure locales&#8221; brings you locale selection tool. It&#8217;s not the case for Ubuntu. How to replace Debian&#8217;s behavior? Read below:</p>
<pre style="padding-left: 30px;"># grep pl_PL.UTF-8 /usr/share/i18n/SUPPORTED &gt; /var/lib/locales/supported.d/local
# dpkg-reconfigure locales
   Generating locales...
     pl_PL.UTF-8... done
   Generation complete.</pre>
<p>Above example show how to add pl_PL.UTF-8 locale.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/01/generate-locales-under-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GIT hooks: commit-msg to enforce commit rules</title>
		<link>http://blog.aplikacja.info/2012/01/git-hooks-commit-msg-to-enforce-commit-rules/</link>
		<comments>http://blog.aplikacja.info/2012/01/git-hooks-commit-msg-to-enforce-commit-rules/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 23:21:36 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[sh]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1709</guid>
		<description><![CDATA[Recently I forgot to add #reviewthis directive for modifications of codebase that belongs to team A. And a subtle bug was introduced that way. Ops! I agreed earlier that all changes done to moduleB should be passed to a reviewer that will do peer review for that particular change. What a shame   (We [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/07/git.gif"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1571" title="git" src="http://blog.aplikacja.info/wp-content/uploads/2011/07/git.gif" alt="" width="500" height="67" /></a>Recently I forgot to add <a href="https://github.com/supermatter/reviewthis">#reviewthis</a> directive for modifications of codebase that belongs to team A. And a <strong>subtle bug was introduced</strong> that way. Ops! I agreed earlier that all changes done to moduleB should be passed to a reviewer that will do peer review for that particular change. What a shame <img src='http://blog.aplikacja.info/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />  (We are using excellent <a href="https://github.com/blog/42-commit-comments">GitHub&#8217;s  review mechanism</a>, BTW).</p>
<p>How to <strong>avoid that situation in a future</strong>? Should I rely on my memory? Is it possible for a human to track so many small rules manually? My intuition tells me that enforcement of those small ruleset should be automated.</p>
<p>GIT allows you to specify so called &#8220;<a href="http://book.git-scm.com/5_git_hooks.html">commit hooks</a>&#8221; that can validate many stages of GIT workflow. I&#8217;ll use simplest local verification of commit message, first the rule in plain text:</p>
<p style="padding-left: 30px;"><em>If you are changing moduleB you should notify developerC about this change</em></p>
<p><span id="more-1709"></span></p>
<p>The implementation (.git/hooks/commit-msg):</p>
<pre style="padding-left: 30px;">#!/bin/sh

if git st -s | grep -q moduleB; then
    grep -q '#reviewthis:.*developerC@xyz.com' $1 || {
        echo "Add #reviewthis.*developerC@xyz.com"
        echo "Commit aborted"
        false
    }
else
    true
fi
</pre>
<p>If you make a change in moduleB and developerC is not notified commit operation is aborted. You cannot forget (or else your commit will fail). If you want to <strong>make that rule repository-wide</strong> (in order to block everyone from skipping this rule) you should use different hook: pre-receive on a server.</p>
<p>GIT hooks are very powerful validation / <strong>automation mechanism</strong> that is making our work more efficient.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2012/01/git-hooks-commit-msg-to-enforce-commit-rules/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Hamlet for Geeks ;-)</title>
		<link>http://blog.aplikacja.info/2011/12/the-hamlet-for-geeks/</link>
		<comments>http://blog.aplikacja.info/2011/12/the-hamlet-for-geeks/#comments</comments>
		<pubDate>Thu, 29 Dec 2011 21:17:51 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[joke]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1704</guid>
		<description><![CDATA[OR(B, NOT(B)):

&#8230; that&#8217;s the question.
Author: unknown.
]]></description>
			<content:encoded><![CDATA[<p>OR(B, NOT(B)):</p>
<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/12/shakespeare.jpg"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1705" title="shakespeare" src="http://blog.aplikacja.info/wp-content/uploads/2011/12/shakespeare.jpg" alt="" width="500" height="371" /></a></p>
<p>&#8230; that&#8217;s the question.</p>
<p>Author: unknown.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/12/the-hamlet-for-geeks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CRUD Matrix As a Software Design And Estimation Tool</title>
		<link>http://blog.aplikacja.info/2011/12/crud-matrix-as-a-software-design-and-estimation-tool/</link>
		<comments>http://blog.aplikacja.info/2011/12/crud-matrix-as-a-software-design-and-estimation-tool/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 23:55:36 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[estimation]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1684</guid>
		<description><![CDATA[I don&#8217;t understand UML designers. They skipped in UML very useful design tool: data flow diagrams (DFD) and placed cheap substitute called &#8220;activity diagram&#8221;. Why? Because data flow is not object oriented (no encapsulation). Should we skip this useful tool and use only diagrams defined by UML? I don&#8217;t think so.
On the other hand general [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/12/dfd.png"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1686" title="dfd" src="http://blog.aplikacja.info/wp-content/uploads/2011/12/dfd.png" alt="" width="200" height="165" /></a>I don&#8217;t understand <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language">UML</a> designers. They skipped in UML very useful design tool: <strong>data flow diagrams (DFD)</strong> and placed cheap substitute called &#8220;activity diagram&#8221;. Why? Because data flow is not object oriented (no encapsulation). Should we skip this useful tool and use only diagrams defined by UML? I don&#8217;t think so.</p>
<p>On the other hand general problem with DFD (and any diagramming technique) is <strong>scalability</strong>. If you want to express many flows using DFD you have to make DFD hierarchical, thus overall picture may be hidden here. If you place too many (&gt;9 items) details on one diagram you are lost again.</p>
<p>There&#8217;s simple and very powerful, but forgotten technique called <strong>&#8220;CRUD tables&#8221;</strong>. What&#8217;s &#8220;CRUD&#8221;? It&#8217;s a table (can be implemented by a spreadsheet) that for every <em>process</em> in a system defines it&#8217;s interactions with main <em>entities</em>: <strong>Create, Read, Update, Delete</strong>. CRUD table was used mainly during database design, but I think this technique can be used for every data flow in a system (including external actors and entities).</p>
<p>I&#8217;ll show you how you can utilize CRUD table to make initial design and get software complexity estimation.</p>
<p><span id="more-1684"></span></p>
<p>First of all, a specification:</p>
<address style="padding-left: 30px;">I need to sell products on my website. I&#8217;d like an order is created in my ERP system just after instant payments are finished.</address>
<p>Pretty short, but let&#8217;s <strong>start design</strong>!</p>
<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/12/crud-1.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1687" title="crud-1" src="http://blog.aplikacja.info/wp-content/uploads/2011/12/crud-1.png" alt="" width="477" height="97" /></a>We can see how basic processes interacts with internal data (Product, Order, Item) and external entities (Payment, ERP Order). Let&#8217;s check first rule:</p>
<address style="padding-left: 30px;">Every process should have at least one input (R) and one output (CUD)</address>
<p>We can see rule is not valid for few processes, so let&#8217;s add some Entities to fulfill this rule:</p>
<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/12/crud-2.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1688" title="crud-2" src="http://blog.aplikacja.info/wp-content/uploads/2011/12/crud-2.png" alt="" width="549" height="97" /></a>As you can see we added actor (Customer) to be a source (trigger) for some processes.</p>
<p>Now we can add estimation part. First: for every entity we can add complexity (we know that one entities can be more complicated than another), complexity of processes will result from used entities complexity:</p>
<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/12/crud-3.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1691" title="crud-3" src="http://blog.aplikacja.info/wp-content/uploads/2011/12/crud-3.png" alt="" width="646" height="115" /></a>Formula used for computation of &#8220;complexity&#8221; column:</p>
<pre style="padding-left: 30px;">=counta(C3)*$C$2+counta(D3)*D$2+counta(E3)*E$2+counta(F3)*F$2+counta(G3)*G$2+counta(H3)*H$2</pre>
<p>So we know now that more complicated process will be sending order to an ERP system. If we added proper weights to operations (CRUD) and measure single activity we could <strong>estimate full effort</strong> needed to implement specified system.</p>
<p>Above CRUD translates into the following DFD:</p>
<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/12/crud.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1692" title="crud" src="http://blog.aplikacja.info/wp-content/uploads/2011/12/crud.png" alt="" width="430" height="330" /></a>I&#8217;d like to hear about your experience with CRUD modeling.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/12/crud-matrix-as-a-software-design-and-estimation-tool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>User Process Autostart Under Linux</title>
		<link>http://blog.aplikacja.info/2011/12/user-process-autostart-under-linux/</link>
		<comments>http://blog.aplikacja.info/2011/12/user-process-autostart-under-linux/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 21:52:49 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1680</guid>
		<description><![CDATA[Sometimes you want your user-level program to be automatically started on every Linux reboot. Scared of complicated SYSV startup scripts? Don&#8217;t panic, this task is easier than you think!
First of all you need root access on a machine to install startup script. Default startup scripts are placed in /etc/init.d directory and special symbolic link must [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/12/linux.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1681" title="linux" src="http://blog.aplikacja.info/wp-content/uploads/2011/12/linux.jpg" alt="" width="200" height="238" /></a>Sometimes you want your user-level program to be <strong>automatically started</strong> on every Linux reboot. Scared of complicated SYSV startup scripts? Don&#8217;t panic, this task is easier than you think!</p>
<p>First of all you need <strong>root access on a machine</strong> to install startup script. Default startup scripts are placed in /etc/init.d directory and special symbolic link must be created under /etc/rc5.d (at least on Debian-based systems).</p>
<p>First let&#8217;s create <strong>startup script</strong> for your &#8220;daemon&#8221;-like program:</p>
<p><span id="more-1680"></span></p>
<pre style="padding-left: 30px;">/etc/init.d/myprogram:
----------------------
#! /bin/sh
PATH=/sbin:/bin
case "$1" in
  start)
    su -c /home/darek/bin/myprogram.sh darek &amp;
    ;;
  restart|reload|force-reload)
    killall myprogram.sh
    su -c /home/darek/bin/myprogram.sh darek &amp;
    ;;
  stop)
    killall myprogram.sh
    ;;
  *)
    echo "Usage: $0 start|stop" &gt;&amp;2
    exit 3
    ;;
esac
</pre>
<p>Note that &#8220;darek&#8221; is the user id that will be used for starting up the script.</p>
<p>Then: ensure <strong>it&#8217;s executable</strong> and create symbolic link for default runlevel (5 on Debian):</p>
<pre style="padding-left: 30px;">chmod +x /etc/init.d/myprogram
cd /etc/rc5.d
ln -s ../init.d/myprogram S80myprogram
</pre>
<p>&#8220;S&#8221; means &#8220;start&#8221;, &#8220;80&#8243; allows to ordered execution. Pretty simple!</p>
<p>SYSV init scripts are harded to setup than BSD-style, but are more flexible and easier to manage by installation tools (dpkg under Debian).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/12/user-process-autostart-under-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bug vs Feature</title>
		<link>http://blog.aplikacja.info/2011/11/bug-vs-feature/</link>
		<comments>http://blog.aplikacja.info/2011/11/bug-vs-feature/#comments</comments>
		<pubDate>Sat, 12 Nov 2011 00:04:05 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[quality]]></category>
		<category><![CDATA[specification]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1667</guid>
		<description><![CDATA[How often do you (I assume a developer) trying to make a suit for this small creature? Aren&#8217;t such &#8220;features&#8221; just a mistake in software specification? If it&#8217;s something that is visible just after product is deployed and it&#8217;s OK from specification point of view:

Someone has not predicted errant situation during specification phase
OR: your waterfall [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/11/bug-feature.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1668" title="bug-feature" src="http://blog.aplikacja.info/wp-content/uploads/2011/11/bug-feature.jpg" alt="" width="400" height="300" /></a>How often do you (I assume a developer) trying to <strong>make a suit for this small creature</strong>? Aren&#8217;t such &#8220;features&#8221; just a mistake in software specification? If it&#8217;s something that is visible just after product is deployed and it&#8217;s OK from specification point of view:</p>
<ul>
<li>Someone <strong>has not predicted</strong> errant situation during specification phase</li>
<li>OR: your <strong>waterfall</strong> (yes, it&#8217;s a linear analysis-project-implementation-test flow!) process is basically not working now</li>
</ul>
<p>I believe without formal methods you are <strong>not able to predict</strong> all possible specification inconsistencies before implementation. Even very accurate review process might leave some holes in specification that lead to obvious bugs as a result.</p>
<p><span id="more-1667"></span></p>
<p>Then usually a customer is forced to:</p>
<ul>
<li><strong>accept extra work</strong> that needs to be done to remove a bug to be paid separately (so called &#8220;change request&#8221;, usually pretty expensive at the end of a process)</li>
<li>OR: <strong>accept &#8220;feature&#8221;</strong> as is</li>
</ul>
<p>Why? Because he <strong>signed specification</strong>! He/she wanted to make fixed-price product so contract must be created. Contract is not perfect, so responsibility for validating it is on contracting side, not the contractor. On the other hand we (the software shop side) like &#8220;THE SOFTWARE IS SUPPLIED WITH NO WARRANTY&#8221; (note the usual caps) that keeps our responsibility far away.</p>
<p>So: how often <strong>your software process</strong> introduces such &#8220;(cre/fe)atures&#8221;?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/11/bug-vs-feature/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Building packages from sources using Debian/Ubuntu</title>
		<link>http://blog.aplikacja.info/2011/11/building-packages-from-sources-in-debianubuntu/</link>
		<comments>http://blog.aplikacja.info/2011/11/building-packages-from-sources-in-debianubuntu/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 18:14:42 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1664</guid>
		<description><![CDATA[Sometimes you want to install latest version of selected software package while keeping base system stable. Then installing from source is a safe option to proceed.
First, you have to include sources from fresh system version, below is example taken from Ubuntu, I selected natty (/etc/apt/sources.list):
deb-src http://pl.archive.ubuntu.com/ubuntu/ natty main restricted
Then you should refresh package list:
sudo apt-get [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2009/12/debian.png"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-571" title="debian" src="http://blog.aplikacja.info/wp-content/uploads/2009/12/debian.png" alt="" width="179" height="61" /></a>Sometimes you want to install <strong>latest version of selected software package</strong> while keeping base system stable. Then installing from source is a safe option to proceed.</p>
<p>First, you have to <strong>include sources</strong> from fresh system version, below is example taken from Ubuntu, I selected natty (/etc/apt/sources.list):</p>
<pre style="padding-left: 30px;">deb-src http://pl.archive.ubuntu.com/ubuntu/ natty main restricted</pre>
<p>Then you should <strong>refresh package list</strong>:</p>
<pre style="padding-left: 30px;">sudo apt-get update</pre>
<p>and <strong>install dependencies</strong>:</p>
<pre style="padding-left: 30px;">sudo apt-get build-dep ccache</pre>
<p>and finally <strong>build the new version</strong> of a package (note that no root account is needed for that step):</p>
<pre style="padding-left: 30px;">apt-get -b source ccache</pre>
<p>As a result there&#8217;s a <strong>*.deb package</strong>, install it:</p>
<pre style="padding-left: 30px;">sudo dpkg -i ccache*.deb
</pre>
<p>That&#8217;s all!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/11/building-packages-from-sources-in-debianubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Software Project Enemy: Regression</title>
		<link>http://blog.aplikacja.info/2011/10/software-project-enemy-regression/</link>
		<comments>http://blog.aplikacja.info/2011/10/software-project-enemy-regression/#comments</comments>
		<pubDate>Fri, 28 Oct 2011 22:03:27 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[reliability]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1657</guid>
		<description><![CDATA[
I&#8217;m tracking current project state using automated test suite that is executed 24/7. It gives information about stability by randomly exploring project state space. Test launches are based on fresh builds from auto-build system connected to master branch for this project.
Recently I hit few times typical stability regression scenario: N+1th commit that should not have [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2010/02/dilbert_bugFixMinivan1.gif"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-817" title="dilbert_bugFixMinivan" src="http://blog.aplikacja.info/wp-content/uploads/2010/02/dilbert_bugFixMinivan1.gif" alt="" width="500" height="155" /></a></p>
<p>I&#8217;m tracking current project state using <strong>automated test suite</strong> that is executed 24/7. It gives information about stability by randomly exploring project state space. Test launches are based on fresh builds from auto-build system connected to master branch for this project.</p>
<p>Recently I hit few times typical <strong>stability regression scenario</strong>: N+1th commit that should not have unexpected side effects caused <strong>crash in auto-testing suite</strong> just after 2 minutes of random testing thus blocking full test suite to be executed. OK, we finally had feedback (from auto-test), but let&#8217;s compute the (bug .. detection) delay here:</p>
<ul>
<li><strong>auto-build phase</strong>: 30 minutes .. 1 hour (we build few branches in cycle, sometimes build can wait long time to be performed especially if <a href="http://ccache.samba.org/">build cache</a> has to be refilled for some reason)</li>
<li><strong>test queue</strong> wait phase: 30 minutes (pending tests should be finished before loading new version)</li>
<li><strong>review of testing results</strong> (currently manual): ~1 hour (we send automatic reports, but only twice a day)</li>
</ul>
<p><span id="more-1657"></span></p>
<p>In worst scenario we may <strong>notice the problem (regression) next day</strong>! Too long time in  my opinion &#8211; broken master branch state may block other developers thus slowing down their work. There must be better organization that will allow to react faster on such problems:</p>
<ol>
<li>Ask developers to <strong>launch random test suite locally</strong> before every commit. 5 minute automatic test should eliminate obvious crashes from publishing on shared master branch</li>
<li><strong>Auto-Notify all developers</strong> about every failed test: still need to wait for build/test queue, messages may become ignored after long time</li>
<li>Employ <strong>automatic gate keeper-like</strong> mechanism that will promote (merge) commit after some sanity tests are passed</li>
</ol>
<p>Looks like 1. is more efficient and easiest to implement option. 2. is too &#8220;spammy&#8221; and 3. is hardest to setup (probably in next project with language with ready <a href="http://ldn.linuxfoundation.org/book/decentralized-with-automatic-gatekeeper">support for &#8220;commit promotion&#8221;</a>).</p>
<p>2. will look interesting if applied to latest submitters only. Maybe I&#8217;ll give it a try.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/10/software-project-enemy-regression/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Assert: To Abort Or Not To Abort, That&#8217;s The Question</title>
		<link>http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/</link>
		<comments>http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/#comments</comments>
		<pubDate>Fri, 28 Oct 2011 21:25:18 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[reliability]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1650</guid>
		<description><![CDATA[Everyone agrees that internal state checking using assert(), Q_ASSERT(), assert are good. Programmer can declare expected input (asserting parameters), internal state (invariants) and verify return values (postconditions) and runtime will verify such expectations. There are languages with direct support for assertions in those three variants (Eiffel with his Design By Contract philosophy).
Those assertions typically will [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/10/hamlet.png"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="size-full wp-image-1653 alignright" title="hamlet" src="http://blog.aplikacja.info/wp-content/uploads/2011/10/hamlet.png" alt="" width="600" height="176" /></a>Everyone agrees that internal state checking using <a href="http://www.cplusplus.com/reference/clibrary/cassert/assert/">assert()</a>, <a href="http://doc.qt.nokia.com/latest/qtglobal.html">Q_ASSERT()</a>, <a href="http://java.sun.com/developer/technicalArticles/JavaLP/assertions/">assert</a> are good. Programmer can declare expected input (asserting parameters), internal state (invariants) and verify return values (postconditions) and runtime will verify such expectations. There are languages with direct support for assertions in those three variants (Eiffel with his <a href="http://www.eiffel.com/developers/design_by_contract.html">Design By Contract</a> philosophy).</p>
<p>Those assertions typically will show filename/line number/message information <strong>and abort program / raise an exception</strong> if the condition is not met. Runtime environment then can collect current stacktrace to give developer more information on failed expectation.</p>
<p>One can <strong>disable assertions</strong> entirely (C++, Java) or select subset of assertions (Eiffel) for production releases. Resulting code will be faster, but failed expectations will not be verified by software &#8211; problem reports may be harder to interpret.</p>
<p>On the other hand if an <strong>assertion is too strict</strong> (the assumption may be invalid) it may abort program giving user negative impression about software stability.</p>
<p>What to do then? How can we <strong>keep problem-diagnosing power</strong> of enabled assertions and prevent minor of invalid failed assertions from aborting whole program?</p>
<p>The answer is: <strong>weak assertions</strong> (assertion without abort).</p>
<p><span id="more-1650"></span>OK, you may ask, if we are not calling abort() then we can <strong>loose details about failed assertion</strong>. Nobody will send a bug report if program is not crashing.</p>
<p>But why do we need to rely on end user? <img src='http://blog.aplikacja.info/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  Let&#8217;s send <strong>failed assertion reports automatically</strong> under-the-covers and leave system running!</p>
<p>I&#8217;m attaching solution below for Q_ASSERT (C++, QT), but you should get the idea:</p>
<pre style="padding-left: 30px;">void qt_assert_x(const char *where, const char *what, const char *file, int line) {
    char buf[BUFSIZE];
    snprintf(buf, BUFSIZE, "%s:%d: Q_ASSERT(%s, %s) FAILED", file, line, where, what);
    print_stacktrace_to_logs(buf);
    send_stacktrace_over_network(buf);
    if (getenv("ASSERT_FATAL")) {
        abort();
    }
}
</pre>
<p>If you place this code in LD_PRELOAD-ed library you will <strong>overload symbol from QT library</strong> and catch any reference to qt_assert_x() symbol. Supplied function will save important information into log file, send it using network connection (of possible) then return. I described in <a href="/2011/07/collecting-crash-reports-over-udp-using-netcat/">this post</a> how can we collect such crash reports on a server and <a href="/2010/12/backtraces-for-c/">this post</a> will tell you about implementation of stacktraces for C++.</p>
<p>Optionally you can ask for <strong>abort() call</strong> (typical Q_ASSERT behavior) using some kind of configuration (environment variable in my case). It may be useful in development environment to <a href="http://perldesignpatterns.com/?AssertPattern">die early</a> is something goes wrong to have better diagnostics.</p>
<p>Using custom error handlers you can have both benefits:</p>
<ul>
<li>&#8220;robust&#8221; program that will not die after minor expectation is not met (end user will not care)</li>
<li>automatic diagnostics about failed expectation</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>First Draft Of Public Calendar Specification</title>
		<link>http://blog.aplikacja.info/2011/10/first-draft-of-public-calendar-specification/</link>
		<comments>http://blog.aplikacja.info/2011/10/first-draft-of-public-calendar-specification/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 22:27:09 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[calendar]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1642</guid>
		<description><![CDATA[After making decision to launch online booking service for existing calendars (Google / Microsoft Exchange) it&#8217;s time to make minimal functionality specification. Then landing page will be prepared to check if the subject catch attendance then MVP to prove basic flows will work as expected.
Glossary:

Customer: calendar owner
Client: wants to book an appointment with customer
Time slot: [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/10/calendar.png"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1645" title="calendar" src="http://blog.aplikacja.info/wp-content/uploads/2011/10/calendar.png" alt="" width="256" height="256" /></a>After making decision to <a href="/2011/10/online-booking-for-your-google-iphone-exchange-calendar/">launch online booking service</a> for existing calendars (Google / Microsoft Exchange) it&#8217;s time to make minimal functionality specification. Then <a href="http://www.ashmaurya.com/2009/11/from-minimum-viable-product-to-landing-pages/">landing page</a> will be prepared to check if the subject catch attendance then <a href="http://venturehacks.com/articles/minimum-viable-product">MVP</a> to prove basic flows will work as expected.</p>
<p>Glossary:</p>
<ul>
<li><strong>Customer</strong>: calendar owner</li>
<li><strong>Client</strong>: wants to book an appointment with customer</li>
<li><strong>Time slot</strong>: period of time that can be selected for appointment</li>
</ul>
<p>MVP Use case list below (will define implementation order and priorities):</p>
<ul>
<li><strong>Show customer&#8217;s calendar</strong> on a website with available slots
<ul>
<li>WHY: Proves that we can read existing event source</li>
</ul>
</li>
<li>Allow to <strong>book an appointment</strong> for selected slot
<ul>
<li>WHY: Proves that we can write existing event source</li>
</ul>
</li>
<li>Allow customer to <strong>register new calendar</strong>
<ul>
<li>WHY: Allow for external tests for potential customers</li>
<li>Allows to set timezone, day of week range, hours range</li>
</ul>
</li>
</ul>
<p>Optional use case list:</p>
<p><span id="more-1642"></span></p>
<ul>
<li>SMS book confirmation
<ul>
<li>WHY: prevent abuse</li>
<li>Phone number is required from client</li>
<li>SMS code should be entered on confirmation screen to finish booking a visit</li>
</ul>
</li>
<li>SMS notifications
<ul>
<li>WHY: minimize no-shows</li>
<li>One day before a visit notification SMS is sent</li>
</ul>
</li>
<li>Vacation management by Customer
<ul>
<li>WHY: block booking for selected days</li>
<li>allow to specify date range for &#8220;unavailable&#8221; days</li>
</ul>
</li>
<li>Automatic SMS after moving a reservation
<ul>
<li>WHY: easy change schedule</li>
<li>compares local cache with current calendar state</li>
<li>sends SMS to client and e-mail to customer</li>
</ul>
</li>
<li>Custom SMS messages (with proper character limit check)
<ul>
<li>WHY: more details (address) in a message</li>
</ul>
</li>
<li>Client cancels appointment
<ul>
<li>WHY: minimize no-shows</li>
<li>Maybe as easy as sending SMS to some address with confirmation?</li>
</ul>
</li>
</ul>
<p>To be continued &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/10/first-draft-of-public-calendar-specification/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uptime Statistics Visualisations For Site-uptime.net</title>
		<link>http://blog.aplikacja.info/2011/10/uptime-statistics-visualisations-for-site-uptime-net/</link>
		<comments>http://blog.aplikacja.info/2011/10/uptime-statistics-visualisations-for-site-uptime-net/#comments</comments>
		<pubDate>Fri, 21 Oct 2011 22:37:32 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[s-u]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1635</guid>
		<description><![CDATA[Would you like how your web application performance behaves across longer time periods? Now it&#8217;s possible with site-uptime.net! We&#8217;ve just added visualisation of statistics:
Above sample is not bad system responded in &#60;1s for &#62;88%. It looks like no optimisations needed here. Let&#8217;s see different case:

Ops! We had some performance problems 2010-03 .. 2010-07 (twitter.com, BTW). [...]]]></description>
			<content:encoded><![CDATA[<p>Would you like how your web application performance behaves across longer time periods? Now it&#8217;s possible with <a href="http://site-uptime.net">site-uptime.net</a>! We&#8217;ve just added <strong>visualisation of statistics</strong>:</p>
<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/10/su-stats.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1636" title="su-stats" src="http://blog.aplikacja.info/wp-content/uploads/2011/10/su-stats.png" alt="" width="510" height="394" /></a>Above sample is not bad system responded in &lt;1s for &gt;88%. It looks like <strong>no optimisations needed here</strong>. Let&#8217;s see different case:</p>
<p><span id="more-1635"></span><a href="http://blog.aplikacja.info/wp-content/uploads/2011/10/su-wrong-stats1.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1638" title="su-wrong-stats" src="http://blog.aplikacja.info/wp-content/uploads/2011/10/su-wrong-stats1.png" alt="" width="456" height="355" /></a></p>
<p>Ops! We had some <strong>performance problems</strong> 2010-03 .. 2010-07 (<a href="http://twitter.com">twitter.com</a>, BTW). Looks like they were fixed in next months.</p>
<p>We are going to allow store and show <strong>day-by-day visualisations</strong> as well to give you feedback in shorter amount of time.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/10/uptime-statistics-visualisations-for-site-uptime-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bazaar to GIT migration</title>
		<link>http://blog.aplikacja.info/2011/10/bazaar-to-git-migration/</link>
		<comments>http://blog.aplikacja.info/2011/10/bazaar-to-git-migration/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 20:47:00 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[bzr]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[s-u]]></category>
		<category><![CDATA[vcs]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1632</guid>
		<description><![CDATA[Today I moved using site-uptime.net development from Bazaar repository to GIT using elegant bzr2git script. The why:

In-place branches (I used to use them heavily)
Faster (no Python libs loading during &#8220;cold&#8221; start)
Can&#8217;t live without &#8220;git rebase -i&#8221; now  

]]></description>
			<content:encoded><![CDATA[<p>Today I moved using <a href="http://site-uptime.net">site-uptime.net</a> development from Bazaar repository to GIT using elegant <a href="http://blog.coldtobi.de/1_coldtobis_blog/archive/277_bzr2git_--_make_a_git_repositpry_out_of_a_bazaar_one.html">bzr2git</a> script. The why:</p>
<ul>
<li>In-place branches (I used to use them heavily)<a href="http://blog.aplikacja.info/wp-content/uploads/2011/07/git.gif"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1571" title="git" src="http://blog.aplikacja.info/wp-content/uploads/2011/07/git.gif" alt="" width="500" height="67" /></a></li>
<li>Faster (no Python libs loading during &#8220;cold&#8221; start)</li>
<li>Can&#8217;t live without &#8220;<a href="http://book.git-scm.com/4_interactive_rebasing.html">git rebase -i</a>&#8221; now <img src='http://blog.aplikacja.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/10/bazaar-to-git-migration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Encryption Using GPG: Minimal HOWTO</title>
		<link>http://blog.aplikacja.info/2011/10/encryption-using-gpg-minimal-howto/</link>
		<comments>http://blog.aplikacja.info/2011/10/encryption-using-gpg-minimal-howto/#comments</comments>
		<pubDate>Sat, 15 Oct 2011 10:06:12 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1625</guid>
		<description><![CDATA[I assume you want to encrypt some files using your public GPG key. I&#8217;ll focus on simplicity rather than completeness (minimal steps required to implement encryption).
First you have to generate key pair:
$ mkdir -p ~/.gnupg
$ gpg --gen-key

Then see your new key ID and export it to public key storage:
$ gpg --list-keys # get KEY_ID from [...]]]></description>
			<content:encoded><![CDATA[<p>I assume you want to encrypt some files using your public GPG key. I&#8217;ll focus on simplicity rather than completeness (minimal steps required to implement encryption).</p>
<p>First you have to generate key pair:</p>
<pre style="padding-left: 30px;">$ mkdir -p ~/.gnupg
$ gpg --gen-key
</pre>
<p>Then see your new key ID and export it to public key storage:</p>
<pre style="padding-left: 30px;">$ gpg --list-keys # get KEY_ID from output
$ gpg --keyserver "hkp://subkeys.pgp.net" --send-key &lt;KEY_ID&gt;
</pre>
<p>On remote machine import the key and make it trusted (to avoid warnings during encryption):</p>
<pre style="padding-left: 30px;">$ gpg --keyserver "hkp://subkeys.pgp.net" --recv-keys &lt;KEY_ID&gt;
$ gpg --edit-key &lt;KEY_ID&gt;
&gt; trust
</pre>
<p>Then you can used this key to encrypt files and delete original (if needed):</p>
<pre style="padding-left: 30px;">$ gpg -r &lt;KEY_ID&gt; --output &lt;FILE&gt;.gpg --encrypt &lt;FILE&gt;
$ rm &lt;FILE&gt;
</pre>
<p>And the decryption (on host where private key is stored):</p>
<pre style="padding-left: 30px;">$ gpg -r &lt;KEY_ID&gt; --output &lt;FILE&gt; --decrypt &lt;FILE&gt;.gpg
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/10/encryption-using-gpg-minimal-howto/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Web Framework Selection</title>
		<link>http://blog.aplikacja.info/2011/10/python-web-framework-selection/</link>
		<comments>http://blog.aplikacja.info/2011/10/python-web-framework-selection/#comments</comments>
		<pubDate>Tue, 11 Oct 2011 22:32:18 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web2py]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1621</guid>
		<description><![CDATA[I&#8217;ve been using many different Python Web Frameworks so far:

WebStack + mysqldb + custom template framework (long-term ERP project for small company)
Django (online shop)
CherryPy + Cheetah (online PDF design)
Zope (financial)
WebStack + SimpleTAL (online PDF design)

All frameworks have its strengths and weakness. For new project that will handle appointments using existing calendar I decided to give [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/10/python-logo.gif"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1622" title="python-logo" src="http://blog.aplikacja.info/wp-content/uploads/2011/10/python-logo.gif" alt="" width="211" height="71" /></a>I&#8217;ve been using many different <a href="http://wiki.python.org/moin/WebFrameworks">Python Web Frameworks</a> so far:</p>
<ul>
<li><a href="http://www.boddie.org.uk/python/WebStack.html">WebStack</a> + mysqldb + custom template framework (long-term ERP project for small company)</li>
<li><a href="https://www.djangoproject.com/">Django</a> (online shop)</li>
<li><a href="http://www.cherrypy.org/">CherryPy</a> + <a href="http://www.cheetahtemplate.org/">Cheetah</a> (online PDF design)</li>
<li><a href="http://www.zope.org/">Zope</a> (financial)</li>
<li><a href="http://www.boddie.org.uk/python/WebStack.html">WebStack</a> + <a href="http://www.owlfish.com/software/simpleTAL/">SimpleTAL</a> (online PDF design)</li>
</ul>
<p>All frameworks have its strengths and weakness. For new project that will handle <a href="/2011/10/online-booking-for-your-google-iphone-exchange-calendar/">appointments using existing calendar</a> I decided to give <a href="http://web2py.com/">web2py</a> a try, rationale:</p>
<ul>
<li>all stuff included on board, no manual integration of 3rd party libraries</li>
<li>stable API</li>
<li>small and elegant</li>
<li>integrates with <a href="http://code.google.com/intl/pl/appengine/">GAE</a> (with subset of DB layer)</li>
<li>template selection separated from controller (easier unit testing)</li>
<li>easy template syntax (reuses Python code embedded into markup language)</li>
</ul>
<p>After first phase of product I&#8217;ll report if my expectations above were correct and what kind of problems were located (if any).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/10/python-web-framework-selection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Online Booking For Your Google / iPhone / Exchange Calendar</title>
		<link>http://blog.aplikacja.info/2011/10/online-booking-for-your-google-iphone-exchange-calendar/</link>
		<comments>http://blog.aplikacja.info/2011/10/online-booking-for-your-google-iphone-exchange-calendar/#comments</comments>
		<pubDate>Tue, 04 Oct 2011 22:05:25 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[calendar]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1618</guid>
		<description><![CDATA[We, Aplikacja.info are delivering online booking services for Polish customers using med.aplikacja.info service since 2008. The service is mainly targeted at small/medium medical businesses and allows to integrate seamlessly with existing webpage.
I was asked recently about integration with hosted Microsoft Exchange calendar. Customer (also medical business) is using currently iPhone to record visits and would [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/10/med.png"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1619" title="med" src="http://blog.aplikacja.info/wp-content/uploads/2011/10/med.png" alt="" width="300" height="195" /></a>We, <a href="http://aplikacja.info">Aplikacja.info</a> are delivering <strong>online booking services</strong> for Polish customers using <a href="http://med.aplikacja.info">med.aplikacja.info</a> service since 2008. The service is mainly targeted at small/medium medical businesses and allows to integrate seamlessly with existing webpage.</p>
<p>I was asked recently about integration with hosted <strong>Microsoft Exchange calendar</strong>. Customer (also medical business) is using currently iPhone to record visits and would like to use existing contacts and calendar events and allow his customers to book online.</p>
<p>Our current persistence mechanism is <strong>local SQL database</strong>. In order to integrate with external contact / event source we have the following options:</p>
<p><span id="more-1618"></span></p>
<ul>
<li><strong>keep local SQL storage</strong> and make periodical import/export of events/contacts to Microsoft Exchange</li>
<li>replace local SQL storage with <strong>remote-only storage</strong> thus import/export will not be needed</li>
</ul>
<p>First option drawback is possible <strong>de-synchronisation</strong> / higher probability of conflicts. The benefit is that local storage is more reliable than rely only on remote system availability. Also some customers doesn&#8217;t have existing calendars we can connect to. Then setup is much simpler (just signup to our online service).</p>
<p>The latter gives better guarantees of <strong>eliminating conflicts</strong>, but may be slower / less reliable (when remote system is unavailable for some reason).</p>
<p>We started few weeks ago attempt to integrate with Google Calendar &#8211; <a href="http://code.google.com/intl/pl/apis/calendar/">the interface</a> is pretty well documented. Current option that will probably win is to rely only on remote storage with some data cached locally to make things go faster. Maybe the same approach will be used for MS Exchange (probably <a href="http://www.ietf.org/rfc/rfc4791.txt">CalDAV</a> as transport option).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/10/online-booking-for-your-google-iphone-exchange-calendar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic free disk space monitoring on Linux server</title>
		<link>http://blog.aplikacja.info/2011/09/automatic-free-disk-space-on-server/</link>
		<comments>http://blog.aplikacja.info/2011/09/automatic-free-disk-space-on-server/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 07:09:28 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[monitor]]></category>
		<category><![CDATA[sh]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1610</guid>
		<description><![CDATA[The simplest way to monitor free disk space on Linux serwer, just place it in crontab:
0 8 * * *     df -h &#124; awk '/^\// &#38;&#38; $5 &#62; 95 { print "missing space", $0 }'
and ensure e-mail to this user is forwarded to you then you will see e-mail when occupied space is higher [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2010/11/floppy-disk.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1377" title="floppy-disk" src="http://blog.aplikacja.info/wp-content/uploads/2010/11/floppy-disk.jpg" alt="" width="250" height="225" /></a>The simplest way to <strong>monitor free disk space</strong> on Linux serwer, just place it in crontab:</p>
<pre style="padding-left: 30px;">0 8 * * *     df -h | awk '/^\// &amp;&amp; $5 &gt; 95 { print "missing space", $0 }'</pre>
<p>and ensure e-mail to this user is forwarded to you then you will see e-mail when occupied space is <strong>higher than 95%</strong> on any disk.</p>
<p>Pretty simple.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/09/automatic-free-disk-space-on-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple SSH services status monitoring</title>
		<link>http://blog.aplikacja.info/2011/09/simple-ssh-services-monitoring-status/</link>
		<comments>http://blog.aplikacja.info/2011/09/simple-ssh-services-monitoring-status/#comments</comments>
		<pubDate>Fri, 16 Sep 2011 22:52:07 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sh]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1606</guid>
		<description><![CDATA[Current project I&#8217;m working on benefits from automated test suite run on few Linux-based devices. Tests are running 24&#215;7, but sometimes device hangs (reason is still under investigation) and SSH access is blocked then.
In order to track the problem I redirected syslog (busybox-based, BTW) via network and added local automatic monitoring service that will show [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/04/console.jpg"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1526" title="console" src="http://blog.aplikacja.info/wp-content/uploads/2011/04/console.jpg" alt="" width="240" height="168" /></a>Current project I&#8217;m working on benefits from <strong>automated test suite</strong> run on few Linux-based devices. Tests are running 24&#215;7, but sometimes device hangs (reason is still under investigation) and SSH access is blocked then.</p>
<p>In order to track the problem I redirected syslog (busybox-based, BTW) via network and added local <strong>automatic monitoring service</strong> that will show me when a part of my test installation go down.</p>
<p><span id="more-1606"></span></p>
<p>The script is really simple and uses GNOME notification tool called <a href="http://ubuntuforums.org/showthread.php?t=1411620">notify-send</a>.</p>
<pre style="padding-left: 30px;">#!/bin/sh
if ! ping -q -c 1 google.com &gt; /dev/null
then
    # no network present
    exit
fi
for machine
do
    F=/tmp/$machine
    F2=/tmp/$machine.previous

    if ssh $machine 'echo OK' &gt;$F 2&gt;&amp;1
    then
        rm -f $F $F2
    else
        if test -f $F2
        then
            notify-send "$machine is not present: `cat $F`"
        fi
        mv $F $F2
    fi
done
</pre>
<p>Details:</p>
<ul>
<li>I&#8217;m checking if <strong>network is available</strong> in general (google ping)</li>
<li>List of SSH machines given on <strong>command line</strong></li>
<li>I assume <strong>SSH keys</strong> are setup &#8211; no password prompt</li>
<li><strong>Check state</strong> is held in /tmp/ directory</li>
</ul>
<p>Script is started periodically from <strong>crontab</strong>:</p>
<pre style="padding-left: 30px;">* 9-17 * * 1-5    srv-monitor-ssh alfa beta delta zeus zeus2
</pre>
<p>and reports failure on <strong>second failed check</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/09/simple-ssh-services-monitoring-status/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fixing invalid comment / branch name in GIT</title>
		<link>http://blog.aplikacja.info/2011/09/fixing-invalid-comment-branch-name-in-git/</link>
		<comments>http://blog.aplikacja.info/2011/09/fixing-invalid-comment-branch-name-in-git/#comments</comments>
		<pubDate>Wed, 14 Sep 2011 22:35:33 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[vcs]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1602</guid>
		<description><![CDATA[Recently I was asked to help with fixing branch that had:

invalid name (wrong artifact number)
invalid comment inside (also based on wrong artifact number)

it was a mistake and programmer wanted to preserve changes done on branch, but using different name.
The solution I proposed was to:


clone existing branch under different name
&#8220;amend&#8221; last commit on this new branch [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/07/git.gif"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1571" title="git" src="http://blog.aplikacja.info/wp-content/uploads/2011/07/git.gif" alt="" width="500" height="67" /></a>Recently I was asked to help with fixing branch that had:</p>
<ul>
<li>invalid name (wrong artifact number)</li>
<li>invalid comment inside (also based on wrong artifact number)</li>
</ul>
<p>it was a mistake and programmer wanted to preserve changes done on branch, but using different name.</p>
<p>The solution I proposed was to:</p>
<p><span id="more-1602"></span></p>
<ol>
<li><strong>clone</strong> existing branch under different name</li>
<li><strong>&#8220;amend&#8221;</strong> last commit on this new branch (to fix comment)</li>
<li><strong>push</strong> new branch into correct location</li>
<li><strong>drop</strong> old branch</li>
</ol>
<p>Sequence of GIT commands was:</p>
<pre style="padding-left: 30px;">$ git branch corect-name origin/invalid-name
(We saved desired SHA with new name)
$ git checkout corect-name
$ git commit --amend
(Fix comment of last commit in editor)
$ git push origin corect-name
(Fixed branch published on our default remote)
$ git push origin :invalid-name
(Weird GIT syntax for deleting remote branches)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/09/fixing-invalid-comment-branch-name-in-git/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Show Incoming E-mails In System Notification Area in Gnome</title>
		<link>http://blog.aplikacja.info/2011/09/show-incoming-e-mails-in-system-notification-area-in-gnome/</link>
		<comments>http://blog.aplikacja.info/2011/09/show-incoming-e-mails-in-system-notification-area-in-gnome/#comments</comments>
		<pubDate>Wed, 14 Sep 2011 22:23:49 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1598</guid>
		<description><![CDATA[For delivering e-mail locally I&#8217;m using fetchmail (POP3 based) + local SMTP daemon (for outgoing e-mail). I&#8217;d like to see when new e-mail arrives to my desk. It&#8217;s pretty easy if you connect classic procmail with modern notification tools based on local message buses.
For GNOME command line interface to internal message is notify send. I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>For delivering e-mail locally I&#8217;m using fetchmail (POP3 based) + local SMTP daemon (for outgoing e-mail). I&#8217;d like to see when new e-mail arrives to my desk. It&#8217;s pretty easy if you connect classic procmail with modern notification tools based on local message buses.</p>
<p>For GNOME command line interface to internal message is notify send. I&#8217;m adding call inside my ~/.procmailrc (after filtering out spam e-mail of course):</p>
<pre style="padding-left: 30px;">:0hc
| grep "^From:\|^Subject:" &gt; /tmp/mail.notify-send; DISPLAY=:0.0 notify-send "`cat /tmp/mail.notify-send`"
</pre>
<p>The result looks like this:</p>
<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/09/sample-notification.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-1599" title="sample-notification" src="http://blog.aplikacja.info/wp-content/uploads/2011/09/sample-notification.png" alt="" width="412" height="202" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/09/show-incoming-e-mails-in-system-notification-area-in-gnome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic random testing for QT-based projects</title>
		<link>http://blog.aplikacja.info/2011/09/automatic-random-testing-for-qt-based-projects/</link>
		<comments>http://blog.aplikacja.info/2011/09/automatic-random-testing-for-qt-based-projects/#comments</comments>
		<pubDate>Fri, 09 Sep 2011 21:07:53 +0000</pubDate>
		<dc:creator>dariusz.cieslak</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[qt]]></category>
		<category><![CDATA[reliability]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://blog.aplikacja.info/?p=1589</guid>
		<description><![CDATA[My current project I&#8217;m working on is based on embedded systems and QT platform. Of course the very first task in the project is to implement some kind of testing method to get feedback on software quality. The test system is composed from few components:

Automatic crash reports collected on central server
Automatic random test runners connected [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.aplikacja.info/wp-content/uploads/2011/05/qt-logo.png"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-1556" title="qt-logo" src="http://blog.aplikacja.info/wp-content/uploads/2011/05/qt-logo.png" alt="" width="250" height="250" /></a>My current project I&#8217;m working on is based on <strong>embedded systems and QT platform</strong>. Of course the very first task in the project is to implement some kind of testing method to get feedback on software quality. The test system is composed from few components:</p>
<ul>
<li><a href="/2011/07/collecting-crash-reports-over-udp-using-netcat/">Automatic crash reports</a> collected on central server</li>
<li>Automatic random test runners connected to always-running (24/7) devices to catch crashes</li>
</ul>
<p>First channel collects all crashes (from human and automated tests), second channel is performed fully automatically. Second channel allows to <strong>measure MMTF</strong> (mean time between failures) and analyse changes in time, probably helping with estimating current software quality state.</p>
<p>Second testing channel requires automatic test driver to inject random UI events (key presses, remote in my case). I used QT message queue for that purpose:</p>
<p><span id="more-1589"></span></p>
<pre style="padding-left: 30px;">void TestScript::sendKey(int keyCode) {
 QWSServer::sendKeyEvent(0, keyCode, Qt::NoModifier, 1, false);
 msleep(PRESS_DELAY_MS);
 QWSServer::sendKeyEvent(0, keyCode, Qt::NoModifier, 0, false);
 msleep(WAIT_DELAY_MS);
}</pre>
<p>Because <a href="http://doc.qt.nokia.com/stable/qwsserver.html">QWSServer::sendKeyEvent()</a> must be called in the same process like main application I decided to <strong>implement named pipe</strong> that will accept key names and render sequence of key events, pseudo-code below:</p>
<pre>    while (true) {
        FILE* f = fopen("/tmp/events.pipe", "rt");
        (...)
        while (getline(&amp;buf, &amp;size, f) &gt;= 0) {
            QString line(buf);
            (...)
            if (mapNameToKey.contains(line)) {
                sendKey(mapNameToKey.value(line));
                QCoreApplication::processEvents();
            }
            (...)
        }
        fclose(f);
    }</pre>
<p>And usage:</p>
<pre style="padding-left: 30px;">echo "RCU_RIGHT" &gt; /tmp/events.pipe
echo "RCU_OK" &gt; /tmp/events.pipe</pre>
<p>That&#8217;s way I&#8217;m able to <strong>remotely control application</strong> (need just SSH access to the device). And the last (easiest) part is to generate random sequence of events &#8211; that can be done by any scripting langugae.</p>
<p>Happy automation!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aplikacja.info/2011/09/automatic-random-testing-for-qt-based-projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

