<?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>The Mixed Bag of Tech</title>
	<atom:link href="http://monitzer.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://monitzer.com</link>
	<description>Another blog about life, the universe and everything.</description>
	<lastBuildDate>Mon, 09 Jul 2012 14:42:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Continuous Integration for Cocoa</title>
		<link>http://monitzer.com/?p=75</link>
		<comments>http://monitzer.com/?p=75#comments</comments>
		<pubDate>Mon, 09 Jul 2012 14:42:53 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Software Engineering]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=75</guid>
		<description><![CDATA[In this post, I&#8217;d like to outline what MacLemon and I worked on for the metalab Hackathon 8. The project stems from a problem with one of the most basic rules of software development: Let software developers develop software, don&#8217;t hog them with repeated configuration/administration stuff. This rule is violated with large-scale Cocoa development for [...]]]></description>
			<content:encoded><![CDATA[<p>In this post, I&#8217;d like to outline what <a title="MacLemon" href="http://twitter.com/MacLemon">MacLemon</a> and I worked on for the <a title="metalab" href="http://metalab.at">metalab</a> <a title="Hackathon 8" href="https://metalab.at/wiki/Hackathon_8">Hackathon</a> 8. The project stems from a problem with one of the most basic rules of software development:</p>
<p style="text-align: center;"><em>Let software developers develop software, don&#8217;t hog them with repeated configuration/administration stuff.</em></p>
<p>This rule is violated with large-scale Cocoa development for the iPhone that also has beta testers: If you want to allow them, you need something like <a title="HockeyApp" href="http://www.hockeyapp.net/">HockeyApp</a> (or TestFlight, but we didn&#8217;t use that one). Further, somebody might break the build without realizing it (that&#8217;s not specific in any way to Cocoa development). Different versions of Xcode use different compilers, which might not accept the same source code.</p>
<p>Apple sketched a solution for some of these problems in WWDC 2012, session 404: You can integrate Xcode into <a title="Jenkins CI" href="http://jenkins-ci.org/">Jenkins CI</a>, a continuous integration platform written in Java. We chose to improve on this solution, to let it do much more.</p>
<p>What you need:</p>
<ul>
<li>A build server that runs Mac OS X, accessible by all developers and itself able to access the HockeyApp website.</li>
<li>A server runnig git. This might be the same server as the above, but doesn&#8217;t have to be. Our instructions are for the case where it&#8217;s on the same server, as this is easier to do (only &#8220;localhost&#8221; as hostname).</li>
<li>Development must happen using git &amp; Xcode (we tested version 4.3, 4.4DP4 and 4.5DP2)</li>
<li>A very solid knowledge of the command line, since just about everything will be done there.</li>
</ul>
<p>What this solution provides:</p>
<ul>
<li>On every push, the app is checked for build errors (and the test suites can be run, if you happen to have some).</li>
<li>Working versions are automatically tagged, so you can easily correlate build logs to the git history.</li>
<li>Pushing a release to HockeyApp only requires adding a tag to a revision before pushing it to the server.</li>
</ul>
<p>Some ideas in what way this solution can be extended very easily:</p>
<ul>
<li>Push working git revisions to a different git server.</li>
<li>Email a build breaker to communicate this fact.</li>
</ul>
<p><span id="more-75"></span></p>
<h1>Concepts</h1>
<p>The system is configured so that on every push of a new commit, Jenkins downloads the revision and builds it. When it works, Jenkins also tags it with the name jenkins_&lt;build number&gt;. The build number is also displayed in its web interface.</p>
<p>When you push, and the HEAD is also tagged with release_&lt;major&gt;_&lt;minor&gt;_&lt;patch&gt; (where all the &lt;&gt; are numbers, everything except the major number are optional), Jenkins automatically uploads the result to HockeyApp. Supply your release notes as the message for that tag (-m on the command line).</p>
<p>The most recent <code>release_</code>-tag in the commit tree is used to update the version number inside the Info.plist of the application (no matter whether it is uploaded to HockeyApp or not).</p>
<h1>Initial Setup</h1>
<p>Obviously, you need Xcode installed on your build server. Note the application name of all the versions you have installed (for example, &#8220;Xcode45-DP2&#8243;). Xcode comes with git, which is very handy.</p>
<p>First, I installed gitolite for easy repository configuration. For this, we need a git user first.</p>
<p>To keep things as minimalistic as possible, this is not a regular user as created by the UI, we created it using the command line (as root):</p>
<p>First, create the group:</p>
<pre style="padding-left: 30px;">dscl . create /Groups/git PrimaryGroupID 1025</pre>
<p>The unique ID was chosen based on not having a conflict with the other groups.</p>
<p>Next, create the user:</p>
<pre style="padding-left: 30px;">dscl . create /Users/git
dscl . create /Users/git UserShell /usr/bin/false
dscl . create /Users/git RealName git
dscl . create /Users/git UniqueID 1025
dscl . create /Users/git PrimaryGroupID 1025
dscl . create /Users/git NFSHomeDirectory /Users/Shared/git
dscl . append /Groups/git GroupMembership git</pre>
<p><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px; white-space: normal;">The unique ID was chosen based on not having a conflict with automatically created users. Afterwards, create the user&#8217;s home directory at <code>/Users/Shared/git</code>, and change its owner and group to <code>git:git</code>.</span></p>
<p>You might want to use /bin/bash as the shell instead as long as you&#8217;re setting the whole system up, it makes things a bit simpler. Without it, you can change the active user (as root) to git with</p>
<pre style="padding-left: 30px;">sudo -u git -s</pre>
<p>Which unfortunately doesn&#8217;t update the whole environment (like <code>$HOME</code>). If you have a proper shell, you can use <code>-i</code> instead of <code>-s</code>, which does update everything.</p>
<p>gitolite includes a nice installation setup in its <a title="gitolite readme" href="https://github.com/sitaramc/gitolite/blob/master/README.txt">README.txt</a>. Just follow the (short) instructions there, then create a new repository for your project (we called ours &#8220;CIDemo&#8221;).</p>
<p>Jenkins is easier to do (with a caveat, see next paragraph), since there&#8217;s a <a title="Jenkins CI Mac OS X Installer" href="http://jenkins-ci.org/content/thank-you-downloading-os-x-installer">fully-fledged installer for Mac OS X</a> available. We just used that one, and it worked fine. Select using a separate jenkins user (it will be created automatically).</p>
<p>You need at least version 1.439 of Jenkins. Right now, this version is not released yet. Thus I had to fetch the <a title="Jenkins on GitHub" href="https://github.com/jenkinsci/jenkins">version 1.437 from github</a>, and cherry-pick the one fix that&#8217;s required, <a title="Fix NPE during loading matrix job" href="https://github.com/jenkinsci/jenkins/commit/a811f406e785a8c8e6cb4b9246829dce9c7b97ae">a811f406e785a8c8e6cb4b9246829dce9c7b97ae</a>. Otherwise, restarting Jenkins removes the jobs due to a parsing error.</p>
<h1>Keychain Fun</h1>
<p>Since you want to sign your apps, you have to supply the signing keys and the provisioning profile. The profile you can just copy to <code>~jenkins/</code>. For the script below, we use the file name &#8220;<code>${HOME}/Development.mobileprovision</code>&#8220;.</p>
<p>The certificate and private key are more complicated, since they have to be in a keychain. Since the jenkins user does not have UI support, you can&#8217;t just log in and use Keychain Access.</p>
<p>The solution I found was to launch Keychain Access from your regular user, setup the keychain there and then copy it to the jenkins user. Use &#8220;New Keychain&#8221; from the File menu (name it something like &#8220;jenkins&#8221;, use whatever password you want), then option-drag you developer certificate(s) to the new one. Then, delete the keychain (but do not remove it from the file system), and then in the shell, copy <code>~/Library/Keychains/jenkins.keychain</code> to <code>~jenkins/Library/Keychains/login.keychain</code> (create the directory on the destination, and also change the owner and group to jenkins). Don&#8217;t forget to set the keychain permissions to 600. Then, you can set this keychain as the default and remove the password (this is not possible from the UI):</p>
<pre style="padding-left: 30px;">security default-keychain -d user -s login.keychain
security set-keychain-password</pre>
<p>The old password is the one you entered when you created it, just press return for the new one.</p>
<h1>Jenkins Setup</h1>
<p>In Jenkins&#8217; web interface (port 8080 on the machine), add the following plugins:</p>
<ul>
<li>Jenkins GIT plugin</li>
<li>Post Build Task</li>
</ul>
<p>In the Jenkins configuration, in the &#8220;Git&#8221; section, change the git executable path to &#8220;<code>/Applications/{your Xcode appname}.app/Contents/Developer/usr/bin/git</code>&#8220;. In the &#8220;Git plugin&#8221; section, set up &#8220;Global Config user.name Value&#8221; and &#8220;Global Config user.email Value&#8221;. Also setup the SMTP setup for the email notifications there.</p>
<p>Also, you should <a title="Standard Security Setup" href="https://wiki.jenkins-ci.org/display/JENKINS/Standard%20Security%20Setup">enable security</a> in the configuration, with whatever system you like. Otherwise, everyone who can reach this server via HTTP can execute arbitrary shell commands as the jenkins user, which is kinda bad.</p>
<p>Back on the command line, create a (standard) ssh key for the jenkins user (use sudo like explained above to switch to that user). Add its public key to your project in gitolite (with RW permissions).</p>
<p>You also have to accept the Xcode license agreement for all users on the system, which can be done on the command line:</p>
<pre style="padding-left: 30px;">sudo xcodebuild -license</pre>
<p>Next, we created a new job in the Jenkins web interface with the &#8220;<strong>Build multi-configuration project</strong>&#8221; type. Name it distinctively.</p>
<p>In the &#8220;Source Code Management&#8221; section, select git. The repository URL is &#8220;<code>git@localhost:{project name}.git</code>&#8221; (see your gitolite config). In the Advanced section there, enter &#8220;<code>origin</code>&#8221; as the name. In &#8220;branches to build&#8221;, you can enter what fits your build workflow. We entered &#8220;<code>master</code>&#8220;.</p>
<p>In &#8220;Build Triggers&#8221;, activate &#8220;Poll SCM&#8221;. This doesn&#8217;t really poll, but it enables automatic building after a push.</p>
<p>In &#8220;Configuration Matrix&#8221;, add two dimensions:</p>
<ul>
<li>name=<code>XcodeApplication</code>, values=<code>Xcode Xcode44-DP4 Xcode45-DP2</code></li>
<li>name=<code>SDKName</code>, values=<code>macosx iphone iphonesimulator</code></li>
</ul>
<p>Of course, you have to alter these to fit your setup (which Xcode apps and which platforms you want to build-test). The values for the SDKs are defined by Apple, so you usually don&#8217;t want to change them.</p>
<p>Push &#8220;Add build step&#8221;, &#8220;Execute shell&#8221;. Insert the following script:</p>
<pre style="padding-left: 30px;">#!/bin/bash
export DEVELOPER_DIR=/Applications/${XcodeApplication}.app/Contents/Developer
security unlock-keychain -p "" login.keychain
if [ "${SDKName}" == "macosx" ]; then
  SchemeName="CIDemo Mac"
else
  SchemeName="CIDemo iOS"
fi
xcodebuild -workspace CIDemo.xcworkspace \
  -scheme "${SchemeName}" -sdk "${SDKName}" \
  -configuration Release \
  DSTROOT=$WORKSPACE/build.dst \
  OBJROOT=$WORKSPACE/build.obj \
  SYMROOT=$WORKSPACE/build.sym \
  SHARED_PRECOMPS_DIR=$WORKSPACE/build.pch</pre>
<p>&nbsp;</p>
<p>Next is adding the automatic tagging of succeeding builds (or all builds, whatever you think is reasonable).</p>
<p>In &#8220;Post-build Actions&#8221;, add Git Publisher. There, activate &#8220;Push Only If Build Succeeds&#8221; (if you want that), in Tags, use &#8220;Tag to push:&#8221; = &#8220;<code>jenkins_$BUILD_NUMBER</code>&#8220;. Create new tag active, &#8220;Target remote name&#8221; = &#8220;<code>origin</code>&#8220;.</p>
<p>Next, add &#8220;E-mail Notification&#8221;, and configure it to your liking.</p>
<p>The post build task to add is a bit more complicated (you might want to leave this for now and add it later). It involves uploading the result to HockeyApp (but only the iOS version built on Xcode 4.3 here):</p>
<pre style="padding-left: 30px;">#!/bin/bash
# by Andreas Monitzer (@anlumo1) and Pepi Zawodsky (@MacLemon)
#</pre>
<pre style="padding-left: 30px;"># This script published under WTF license
# http://en.wikipedia.org/wiki/WTFPL
# Improvements to this script are welcome though.
if [ "${SDKName}" == "iphoneos" -a "${XcodeApplication}" == "Xcode" ]; then
 	TAG=$(git describe --exact-match --match "release_*" 2&gt; /dev/null)
  	if [ "$?" -eq "0" ]; then
 		# publish the app
 		# get tag annotation to use as the release notes
 		NOTES=$(git tag -l -n9999 $TAG|sed -e "s/^$TAG//;s/^ *//")
  		API_TOKEN="&lt;HockeyApp API token&gt;"
 		SIGNING_IDENTITY="iPhone Developer"
 		PROVISIONING_PROFILE="${HOME}/Development.mobileprovision"
 		PRODUCT_NAME="CIDemo"
  		DSYM="$WORKSPACE/build.sym/Release-iphoneos/${PRODUCT_NAME}.app.dSYM"
 		APP="$WORKSPACE/build.sym/Release-iphoneos/${PRODUCT_NAME}.app"
  		HOCKEY="$WORKSPACE/build.HockeyApp/"
 		mkdir "$HOCKEY" 2&gt; /dev/null
  		echo "Creating .ipa for ${PRODUCT_NAME}..."
  		/bin/rm -f "${HOCKEY}${PRODUCT_NAME}.ipa"
 		/usr/bin/xcrun -sdk iphoneos PackageApplication \
 					   -v "${APP}" \
 					   -o "${HOCKEY}${PRODUCT_NAME}.ipa" \
 					   --sign "${SIGNING_IDENTITY}" \
 					   --embed "${PROVISIONING_PROFILE}" &gt; ${HOCKEY}${PRODUCT_NAME}.log
  		echo "Zipping .dSYM for ${PRODUCT_NAME}..."
  		/bin/rm -f "${HOCKEY}${PRODUCT_NAME}.dSYM.zip"
 		/usr/bin/zip -r "${HOCKEY}${PRODUCT_NAME}.dSYM.zip" "${DSYM}"
  		echo "Uploading to HockeyApp..."
  		/usr/bin/curl "https://rink.hockeyapp.net/api/2/apps/&lt;HockeyApp app id&gt;/app_versions" \
 					  -F "status=2" \
 					  -F "notify=0" \
 					  -F ipa=@"${HOCKEY}${PRODUCT_NAME}.ipa" \
 					  -F dsym=@"${HOCKEY}${PRODUCT_NAME}.dSYM.zip" \
 					  -F notes="${NOTES}" \
 					  -H "X-HockeyAppToken: ${API_TOKEN}"
  		echo "Uploaded to HockeyApp" 	fi fi</pre>
<p>It&#8217;s important that you actually understand what this script is doing, so you can alter it to fit your needs!</p>
<h1>Git Setup</h1>
<p>What&#8217;s missing here is informing Jenkins that a new commit was pushed. For this, you have to create a new file in &#8220;<code>/Users/Shared/git/repositories/&lt;project name&gt;.git/hooks</code>&#8221; called <code>post-receive</code>. This is the content:</p>
<pre style="padding-left: 30px;">#!/bin/bash
curl http://localhost:8080/git/notifyCommit?url=git@localhost:&lt;repository name&gt;.git</pre>
<p>As you can see, you could easily change this to inform another server about the new push (this is a common issue with automatic build actions which have to run a script locally to trigger something). Set this script to 755 permissions.</p>
<h1>Updating the Bundle Version</h1>
<p>In every OS X and iOS project you need to access certain information from the Info.plist present in every .app bundle. Some of that information is automatically created by Xcode, other stuff you need to provide manually, like entering a version number for your app in Xcode. Every time you have to manually add fields or increase a version number this is not only error prone but simply annoying.</p>
<div id="attachment_93" class="wp-caption alignnone" style="width: 310px"><a href="http://monitzer.com/wp-content/uploads/2012/07/Screen-Shot-2012-07-09-at-03.01.07.png"><img class="size-medium wp-image-93" title="Screen Shot 2012-07-09 at 03.01.07" src="http://monitzer.com/wp-content/uploads/2012/07/Screen-Shot-2012-07-09-at-03.01.07-300x155.png" alt="Screenshot of Xcode Target settings showing the Version and Build fields with 1.0." width="300" height="155" /></a><p class="wp-caption-text">Screenshot of Xcode Target settings showing the Version and Build fields with 1.0.</p></div>
<p>This is why this script takes care to add all the useful information like a build revision and git short hash to the Info.plist automatically. This not only works for automated build systems like Jenkins but also for local builds.</p>
<p>Version numbers are taken from a git tag in the form of release___. You can add a release version tag by running this command: <code> git tag -a "release_2_4_8"</code>. You&#8217;ll be prompted to enter release notes for this tag and if you&#8217;re using Hockey they will be used there automatically as well. Nifty! Don&#8217;t forget to push your new tag to the build server by issuing <code>git push --tags origin</code>.</p>
<p>This script needs to be added as a “run script” build phase in Xcode.</p>
<pre style="padding-left: 30px;">#!/bin/bash
# by Andreas Monitzer (@anlumo1) and Pepi Zawodsky (@MacLemon)
#
# This script published under WTF license
# http://en.wikipedia.org/wiki/WTFPL
# Improvements to this script are welcome though.

# Augments the Info.plist with a lot of nice stuff.
# It's suggested to call this script from a "run script" build phase, not copy the script's contents there.

# All Values are available from Objective-C like this:
# Example
# NSDictionary *infoPList = [[NSBundle mainBundle] infoDictionary];
# NSLog(@"CFBundleShortVersionString: %@", [infoPList objectForKey:@"CFBundleShortVersionString"]);

 echo "Checking for file ${PROJECT_DIR}/.git"

# When using git SCM
if [ -e "${PROJECT_DIR}/../.git" ]
then

    # Get a svn-like revision number that keeps increasing with every commit.
    REV=$(git log --pretty=format:'' | wc -l | sed 's/[ \t]//g')
    echo "git rev: $REV"

    # Getting the current branch
    GITBRANCH=$(git branch | grep "*" | sed -e 's/^* //')
    echo "Git Branch: $GITBRANCH"
    # To prevent local builds from displaying incorrent branches we need to delete and readd.
    /usr/libexec/PlistBuddy -c "Delete :GitBranch string" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
    /usr/libexec/PlistBuddy -c "Add :GitBranch string $GITBRANCH" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

    # full build hash
    GITHASH=$(git rev-parse HEAD)
    echo "Git Hash: $GITHASH"
    /usr/libexec/PlistBuddy -c "Delete :GitHash string" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
    /usr/libexec/PlistBuddy -c "Add :GitHash string $GITHASH" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

    # commonly used short hash
    GITHASHSHORT=$(git rev-parse --short HEAD)
    echo "Git Hash Short: $GITHASHSHORT"
    /usr/libexec/PlistBuddy -c "Delete :GitShortHash string" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
    /usr/libexec/PlistBuddy -c "Add :GitShortHash string $GITHASHSHORT" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

    # parsing tags to build the CFBundleVersion in the form of &lt;MAJOR&gt;.&lt;MINOR&gt;.&lt;PATCH&gt;.&lt;REV&gt;
    # Parts of the version number that are missing are substituted with zeros.
    NEAREST=$(git describe --abbrev=0 --match "release_[0-9]*")
    echo "Nearest release Tag: \"$NEAREST\""

    MAJOR="0"
    MINOR="0"
    PATCH="0"
    if [ "$NEAREST" == "" ]
    then
        echo "No release tag found!"
    else
        MAJOR=$(echo $NEAREST | cut -d "_" -f 2)
        if [ $MAJOR == "" ]
        then
            MAJOR="0"
        else
            MINOR=$(echo $NEAREST | cut -d "_" -f 3)
            if [ $MINOR == "" ]
            then
                MINOR="0"
            else
                PATCH=$(echo $NEAREST | cut -d "_" -f 4)
                if [ $PATCH == "" ]
                then
                    PATCH="0"
                fi
            fi
        fi
    fi

    echo "Version String: $MAJOR.$MINOR.$PATCH.$REV"

    # Setting in the Info.plist file
     /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $MAJOR.$MINOR.$PATCH.$REV" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
     /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $MAJOR.$MINOR.$PATCH.$REV ($GITHASHSHORT)" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

    # Setting the same version number in the .dSYM file needed for symbolication in the Hockeyapp.net webinterface
     /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $MAJOR.$MINOR.$PATCH.$REV" "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist"
     /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $MAJOR.$MINOR.$PATCH.$REV ($GITHASHSHORT)" "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist"

elif [ -e "${PROJECT_DIR}/../.svn" ]
then
    # Support for SVN would be happy if you'd actually implement it!
    REV=$(svnversion -nc "${PROJECT_DIR}" | sed -e 's/^[^:]*://;s/[A-Za-z]//')
    echo -n "SVN rev: $REV"
fi

if [ "$BUILD_NUMBER" == "" ]
then
    /usr/libexec/PlistBuddy -c "Delete :JenkinsBuild string" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
    /usr/libexec/PlistBuddy -c "Add :JenkinsBuild string $BUILD_NUMBER" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
else
    /usr/libexec/PlistBuddy -c "Delete :JenkinsBuild string" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
    /usr/libexec/PlistBuddy -c "Add :JenkinsBuild string Local build (not via Jenkins)" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
fi

#EOF</pre>
<h1>Wrapping Up</h1>
<p>So, that&#8217;s as far as we&#8217;ve come. If you have any comments/additions, feel free to send them to me! I hope that the information we&#8217;ve covered here can help you construct a continuous integration solution that fits right into your development process.</p>
<p>There&#8217;s a lot of ways you can go from here. Maybe uploading to iTunes Connect is also something to think about, although I&#8217;d personally like that process to be a bit manual, in order to remove unintentional results.</p>
<p><em>(Note that the code covered here is under the WTFPL, but the text is not.)</em></p>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=75</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mac OS X Range Selection Behavior</title>
		<link>http://monitzer.com/?p=67</link>
		<comments>http://monitzer.com/?p=67#comments</comments>
		<pubDate>Wed, 02 May 2012 11:20:40 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=67</guid>
		<description><![CDATA[Sorry for the long silence, I&#8217;m really busy with work! This is only a quick note about the list view range selection behavior (shift-click) I&#8217;m observing in Mac OS X Lion&#8217;s Finder. There&#8217;s quite more to it than you might think! First off, when there&#8217;s nothing selected and you shift-click on an item, all items [...]]]></description>
			<content:encoded><![CDATA[<p>Sorry for the long silence, I&#8217;m really busy with work!</p>
<p>This is only a quick note about the list view range selection behavior (shift-click) I&#8217;m observing in Mac OS X Lion&#8217;s Finder. There&#8217;s quite more to it than you might think!</p>
<ul>
<li>First off, when there&#8217;s nothing selected and you shift-click on an item, all items from the top up to the clicked one (including itself) are selected.</li>
<li>When there is an existing selection, the result depends on the previous non-range selection action:
<ul>
<li>Regular selection: The range between that item and the clicked one is selected (including both items).</li>
<li>Deselection (cmd-click on a previously selected item): The range between the clicked item and the next selected one below it is selected. If there is none, the range between the previous selected item and the clicked one is selected.</li>
</ul>
</li>
<li>In the previous step, if the previously selected item is part of a contiguous range, all other items of that range are deselected.</li>
</ul>
<p>Did I miss anything? Please tell me via Twitter (@anlumo) or comment below!</p>
<p>UPDATE: @<a title="5minpause" href="https://twitter.com/5minpause">5minpause</a> pointed me to an article, describing the same behavior in a much more elaborate way: <a title="Legendary Selections, Dude" href="http://le.mu.rs/motherfucker/Entries/2011/1/24_Legendary_Selections,_Dude.html">Legendary Selections, Dude</a></p>
<p>UPDATE 2: Alright, discovered another peculiarity in the Finder selection behavior: When clicking onto the file name or file icon without any modifiers, the selection is changed on mouseUp: (the previous selection is also not changed in mouseDown: yet). When either any modifier is held down or the row is clicked somewhere else, the selection is changed in mouseDown:. I guess this is implemented so that you can drag a file without changing the selection.</p>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=67</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cocoa Blocks Pitfall</title>
		<link>http://monitzer.com/?p=60</link>
		<comments>http://monitzer.com/?p=60#comments</comments>
		<pubDate>Thu, 08 Sep 2011 23:59:40 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=60</guid>
		<description><![CDATA[Just because it bit me again for a millionth time: int a = 0; void(^block)(void) = ^{ printf("%d", a); }; a = 1; block(); outputs 0, because the value of a is copied to the block when it is declared. If you want it to track the variable instead, you have to do: __block int [...]]]></description>
			<content:encoded><![CDATA[<p>Just because it bit me again for a millionth time:</p>
<pre>int a = 0;
void(^block)(void) = ^{ printf("%d", a); };
a = 1;
block();</pre>
<p>outputs 0, because the value of a is copied to the block when it is declared.</p>
<p><span id="more-60"></span></p>
<p>If you want it to track the variable instead, you have to do:</p>
<pre>__block int a = 0;
void(^block)(void) = ^{ printf("%d", a); };
a = 1;
block();</pre>
<p>This outputs 1, as you would expect, since the block only gets a reference to a. It might look obvious this way, but consider this code:</p>
<pre>void(^calc)(int,int) = ^(int a, int b) {
    printf("%d ", a);
    if(b&lt;10000) calc(b, a+b);
};
calc(0, 1);</pre>
<p>(Bonus points if you know what sequence this should output!) Since the variable block isn&#8217;t defined when the block is declared, it points to a bogus value and crashes. You have to do it this way:</p>
<pre>__block void(^calc)(int,int) = ^(int a, int b) {
    printf("%d ", a);
    if(b&lt;10000) calc(b, a+b);
};
calc(0, 1);</pre>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=60</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>About Apple&#8217;s Bug Reporter</title>
		<link>http://monitzer.com/?p=56</link>
		<comments>http://monitzer.com/?p=56#comments</comments>
		<pubDate>Sat, 06 Aug 2011 19:11:59 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=56</guid>
		<description><![CDATA[I posted a comment on Apple&#8217;s private developer forums about an issue that might be interesting for others to read, even the ones who don&#8217;t have read access there. Thus, read on for the (slightly rephrased for context) comment. The bug reporting process at Apple is horribly broken from a user experience design point of [...]]]></description>
			<content:encoded><![CDATA[<div id="jive-body-maincol-container">
<div id="jive-body-maincol">
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div id="message-content-505255">
<div id="apple-reply-body-content-505255">
<div>
<p>I posted a comment on Apple&#8217;s private developer forums about an issue that might be interesting for others to read, even the ones who don&#8217;t have read access there. Thus, read on for the (slightly rephrased for context) comment.</p>
<p><span id="more-56"></span></p>
<p>The bug reporting process at Apple is horribly broken from a user experience design point of view. There is absolutely <strong>no</strong> feedback whatsoever on what I&#8217;m filing in the Bug Reporter. It&#8217;s like talking to a wall. Well, not exactly, because talking to a wall is way easier, because you don&#8217;t have to phrase your reports in a specific way.</p>
<p>I have bugs open since November 2007, which are (in my web interface) still in the state I left them back then. I even have a bug report in there from July 2008, that has already been fixed, and I asked for it to be closed, but it&#8217;s still marked as open (it&#8217;s 6059084 in case somebody cares). This behavior tells the developers that nobody actually reads them, so why file them at all?</p>
<p>&nbsp;</p>
<p>I came to assume that Apple does employ some kind of user experience designers. Let them have a look at the process and fix it, otherwise don&#8217;t be surprised that developers (which are also users after all) don&#8217;t file all reports that should be filed, and rather wine on public blogs or on Twitter.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=56</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Book Review: The Art of Community</title>
		<link>http://monitzer.com/?p=51</link>
		<comments>http://monitzer.com/?p=51#comments</comments>
		<pubDate>Tue, 21 Jun 2011 11:55:55 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[Book Review]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=51</guid>
		<description><![CDATA[So, after a brief work-related hiatus, I&#8217;d like to get started with a book review. Generally, I like to read fiction, but every now and then I have to work through some nonfiction book to gain some knowledge. I&#8217;ve tried to read technical books about programming APIs etc, but in recent years I&#8217;ve found these [...]]]></description>
			<content:encoded><![CDATA[<p>So, after a brief work-related hiatus, I&#8217;d like to get started with a book review.</p>
<p>Generally, I like to read fiction, but every now and then I have to work through some nonfiction book to gain some knowledge. I&#8217;ve tried to read technical books about programming APIs etc, but in recent years I&#8217;ve found these to be quite boring, since they&#8217;re a bit too far on the basics side of things. Why should I buy and read a whole book about something I can learn with a few free online beginner&#8217;s tutorials just as well?</p>
<p>So, I&#8217;ve moved more into the &#8220;general concepts&#8221;-genre of nonfiction books. One big example of that is &#8220;<a href="http://www.artofcommunityonline.org/" target="_blank">The Art of Community</a>&#8221; by Jono Bacon. The author is the manager of the Ubuntu community, and he shares some of his experience with the reader.</p>
<p><span id="more-51"></span></p>
<p>Communities are everywhere, from knitting clubs and programming workshops to political parties. There are certain rules that underlie these groups, which everybody knows instinctively. However, when you want to manage such a group, you have to know these rules explicitly, so you can act upon them. The book does a good job of giving you the feeling of what&#8217;s involved there.</p>
<p>The hard part about being a community manager is that you have to steer the community, without being seen as a leader. The majority of the book content is about what you have to do to get the community where you want it to be, by letting the members do what <em>they</em> want to do. This is done mostly by nudging and removing obstacles at the right places.</p>
<p>The author also provides very nice checklists for what you have to do to get things started and how to expand the community leadership into a board when it&#8217;s necessary. The chapter about governing a community is very large and reminds me a lot about our political system. However, it&#8217;s probably only relevant to a very small group of people, because communities of a size where such a system is necessary are very rare.</p>
<p>In general, the book tries to explain things in a general manner, so even though it&#8217;s of a technical origin, a knitting club manager can understand and apply the knowledge. However, some parts of it are probably completely incomprehensible to those. For example, there&#8217;s an extended discussion about what version control system to use, which is far too specific. In my experience, people are very bad at ignoring things they don&#8217;t understand and just give up instead, so that&#8217;s probably a roadblock for technically challenged readers. Some concrete examples also suffer from this issue, but for me they were very illustrative.</p>
<p>As a side effect, the book also explains the way the Ubuntu community works and its principles. That alone is very insightful, and allowed me to spot some BS in some online publications writing about Ubuntu.</p>
<p>So, what&#8217;s my verdict? If you know a bit about open source software development, the book is very enlightening, even when you don&#8217;t plan to manage a community, because you get a better understanding of the mechanisms that are at work in every one you are a part of (and I think everybody is part of some, even when they&#8217;re not aware of it). However, when you&#8217;re actually working on creating/expanding one, the book is great. Actually, I think everyone who is working on such a thing should read it, in order to avoid easy mistakes that can break everything. Just make sure to have to general knowledge about software development methods and open source software, otherwise you&#8217;d not understand a large part of the explanations.</p>
<p>The book is available as an ebook for free at <a href="http://www.artofcommunityonline.org/" target="_blank">http://www.artofcommunityonline.org/</a>, but also from O&#8217;Reilly.</p>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=51</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AquaticPrime and python/PyCrypto</title>
		<link>http://monitzer.com/?p=46</link>
		<comments>http://monitzer.com/?p=46#comments</comments>
		<pubDate>Fri, 13 May 2011 21:28:19 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=46</guid>
		<description><![CDATA[Alright, another post for the same topic: How to generate AquaticPrime licenses in python with PyCrypto (also for the Google App Engine in my case). This took me quite a long time (8h), because debugging crypto is very complicated (the wrong result is returned, so what now?). I actually had to learn how to encrypt [...]]]></description>
			<content:encoded><![CDATA[<p>Alright, another post for the same topic: How to generate <a href="http://www.aquaticmac.com/">AquaticPrime</a> licenses in python with PyCrypto (also for the <a href="https://code.google.com/appengine/">Google App Engine</a> in my case). This took me quite a long time (8h), because debugging crypto is <em>very</em> complicated (the wrong result is returned, so what now?). I actually had to learn how to encrypt using RSA (quite simple actually).<br />
<span id="more-46"></span><br />
Note that you should understand my article on this topic for Java, because I won&#8217;t got into that detail this time.</p>
<p>The imports are pretty similar to Java:</p>
<pre type="python">
from Crypto.Hash import SHA
from Crypto.PublicKey import RSA
import base64
</pre>
<p>Note that you have to install PyCrypto for this to work. If you&#8217;re using Google App Engine, you might have a few issues with that, since the directory the library is installed to is ignored by the App Engine environment. For now I moved the library into the app directory, but I&#8217;ll have to fix that eventually.</p>
<p>The public and private keys can be stored as a regular integer in python:</p>
<pre type="python">
privateKey = int("...", 16)
publicKey = int("...", 16)
</pre>
<p>This time around, python even recognizes the &#8217;0x&#8217; prefix, so you don&#8217;t have to remove it (but it works fine without).</p>
<p>The next line is the one that took me around 7h to come up with:</p>
<pre type="python">
RSAkey = RSA.construct((self.publicKey, 3, self.privateKey))
</pre>
<p>The parameters are &#8216;n&#8217;, &#8216;e&#8217;, &#8216;d&#8217;, &#8216;p&#8217;, &#8216;q&#8217;, &#8216;u&#8217; (I&#8217;m only supplying the first three here, the others are not needed). &#8216;n&#8217; is the public key, &#8216;e&#8217; is the exponent (constant 3 in AquaticPrime) and &#8216;d&#8217; the private key. When I reverse-engineered the PyCrypto-code, I discovered that the right way to get my signature is actually to <em>decrypt</em> the message. Encrypting only uses the public key, decrypting the private key.</p>
<p>First, I have to hash the sorted values from the dictionary using SHA1:</p>
<pre type="python">
hash = SHA.new("user@email.comUserCockpit 2 Single User".encode("utf-8")).digest()
</pre>
<p>I used some placeholders for the fields here, they have to be filled in for proper licenses.</p>
<p>Next up is decryption (signing). However, openssl uses PKCS#1 padding. Java does that automatically, PyCrypto does not, so we have to do that manually:</p>
<pre type="python">
signature = RSAkey.decrypt('\x00\x01' + ('\xff' * 105) + '\x00' + hash)
</pre>
<p>That&#8217;s nearly the same padding code as the PHP implementation, except for the string multiplication, which was a for-loop (yay for that shortcut).</p>
<p>So, all that&#8217;s left here is the base64 encoding, which is quite easy again:</p>
<pre type="python">
base64.b64encode(signature)
</pre>
<p>That&#8217;s it! All that&#8217;s left is creating the plist string again, but that&#8217;s the same as in the Java code and not that exciting.</p>
<p>This is actually quite easy once you have the code for it <img src='http://monitzer.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=46</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AquaticPrime and Java Servlets</title>
		<link>http://monitzer.com/?p=31</link>
		<comments>http://monitzer.com/?p=31#comments</comments>
		<pubDate>Fri, 13 May 2011 18:07:41 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=31</guid>
		<description><![CDATA[Hi, Maybe somebody is interested in this code. It&#8217;s relatively easy to create AquaticPrime license keys in Java once you know how. I used it last year on Google App Engine to generate my licenses for a promotion. First, you need the imports: import java.security.KeyFactory; import java.security.MessageDigest; import java.security.spec.RSAPrivateKeySpec; Next, you have to store the [...]]]></description>
			<content:encoded><![CDATA[<p>Hi,</p>
<p>Maybe somebody is interested in this code. It&#8217;s relatively easy to create <a href="http://www.aquaticmac.com/">AquaticPrime</a> license keys in Java once you know how. I used it last year on <a href="https://code.google.com/appengine/">Google App Engine</a> to generate my licenses for a promotion.</p>
<p><span id="more-31"></span></p>
<p>First, you need the imports:</p>
<div class="geshi no java">
<ol>
<li class="li1">
<div class="de1"><span class="co2">import java.security.KeyFactory;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">import java.security.MessageDigest;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">import java.security.spec.RSAPrivateKeySpec;</span></div>
</li>
</ol>
</div>
<p>Next, you have to store the public and private keys in the Java class:</p>
<div class="geshi no java">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">private</span> <span class="kw2">static</span> <span class="kw2">final</span> <span class="kw3">String</span> privkeyStr = <span class="st0">&quot;&#8230;&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">private</span> <span class="kw2">static</span> <span class="kw2">final</span> <span class="kw3">String</span> pubkeyStr = <span class="st0">&quot;&#8230;&quot;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>You can get those from the AquaticPrime Developer application. Don&#8217;t include the &#8220;0x&#8221; prefix! Use a single line for the whole key.</p>
<p>Next, you have to generate the data to sign. The keys-value-pairs included in the dictionary have to be sorted by key (case insensitively). For simplicity, I only did the following for my Cockpit licenses:</p>
<div class="geshi no java">
<ol>
<li class="li1">
<div class="de1"><span class="kw3">String</span> total = email + name + <span class="st0">&quot;Cockpit Single User&quot;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>This data has to be hashed using SHA1:</p>
<div class="geshi no java">
<ol>
<li class="li1">
<div class="de1"><span class="kw3">MessageDigest</span> digest = <span class="kw3">MessageDigest</span>.<span class="me1">getInstance</span><span class="br0">&#40;</span><span class="st0">&quot;SHA1&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">digest.<span class="me1">update</span><span class="br0">&#40;</span>total.<span class="me1">getBytes</span><span class="br0">&#40;</span><span class="st0">&quot;utf8&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> hash = digest.<span class="me1">digest</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>The data has to be encrypted using RSA with the private and public keys mentioned above. For this, you first have to convert the hex strings to BigIntegers, and then create a new RSAPrivateKeySpec object out of them:</p>
<div class="geshi no java">
<ol>
<li class="li1">
<div class="de1"><span class="kw3">RSAPrivateKeySpec</span> privkey = <span class="kw2">new</span> <span class="kw3">RSAPrivateKeySpec</span><span class="br0">&#40;</span><span class="kw2">new</span> <span class="kw3">BigInteger</span><span class="br0">&#40;</span>pubkeyStr, <span class="nu0">16</span><span class="br0">&#41;</span>, <span class="kw2">new</span> <span class="kw3">BigInteger</span><span class="br0">&#40;</span>privkeyStr, <span class="nu0">16</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>Next, the RSA cipher can be initialized:</p>
<div class="geshi no java">
<ol>
<li class="li1">
<div class="de1"><span class="kw3">KeyFactory</span> factory = <span class="kw3">KeyFactory</span>.<span class="me1">getInstance</span><span class="br0">&#40;</span><span class="st0">&quot;RSA&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">Cipher cipher = Cipher.<span class="me1">getInstance</span><span class="br0">&#40;</span><span class="st0">&quot;RSA&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">cipher.<span class="me1">init</span><span class="br0">&#40;</span>Cipher.<span class="me1">ENCRYPT_MODE</span>, factory.<span class="me1">generatePrivate</span><span class="br0">&#40;</span>privkey<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>Your final license key looks like this:</p>
<div class="geshi no java">
<ol>
<li class="li1">
<div class="de1"><span class="st0">&quot;&lt;?xml version=<span class="es0">\&quot;</span>1.0<span class="es0">\&quot;</span> encoding=<span class="es0">\&quot;</span>UTF-8<span class="es0">\&quot;</span>?&gt;&quot;</span> +</div>
</li>
<li class="li1">
<div class="de1"><span class="st0">&quot;&lt;!DOCTYPE plist PUBLIC <span class="es0">\&quot;</span>-//Apple//DTD PLIST 1.0//EN<span class="es0">\&quot;</span> <span class="es0">\&quot;</span>http://www.apple.com/DTDs/PropertyList-1.0.dtd<span class="es0">\&quot;</span>&gt;&quot;</span> +</div>
</li>
<li class="li1">
<div class="de1"><span class="st0">&quot;&lt;plist version=<span class="es0">\&quot;</span>1.0<span class="es0">\&quot;</span>&gt;&quot;</span> +</div>
</li>
<li class="li1">
<div class="de1"><span class="st0">&quot;&lt;dict&gt;&lt;key&gt;Email&lt;/key&gt;&lt;string&gt;&quot;</span> + email + <span class="st0">&quot;&lt;/string&gt;&quot;</span> +</div>
</li>
<li class="li1">
<div class="de1"><span class="st0">&quot;&lt;key&gt;Name&lt;/key&gt;&lt;string&gt;&quot;</span> + name + <span class="st0">&quot;&lt;/string&gt;&quot;</span> +</div>
</li>
<li class="li1">
<div class="de1"><span class="st0">&quot;&lt;key&gt;Product&lt;/key&gt;&lt;string&gt;Cockpit Single User&lt;/string&gt;&quot;</span> +</div>
</li>
<li class="li1">
<div class="de1"><span class="st0">&quot;&lt;key&gt;Signature&lt;/key&gt;&lt;data&gt;&quot;</span> + Base64.<span class="me1">toString</span><span class="br0">&#40;</span>cipher.<span class="me1">doFinal</span><span class="br0">&#40;</span>hash<span class="br0">&#41;</span><span class="br0">&#41;</span> + <span class="st0">&quot;&lt;/data&gt;&quot;</span> +</div>
</li>
<li class="li1">
<div class="de1"><span class="st0">&quot;&lt;/dict&gt;&lt;/plist&gt;&quot;</span></div>
</li>
</ol>
</div>
<p>Note that there are a lot of exceptions to catch there, but the compiler informs you about them anyways <img src='http://monitzer.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=31</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Legally Distributed Software Development</title>
		<link>http://monitzer.com/?p=28</link>
		<comments>http://monitzer.com/?p=28#comments</comments>
		<pubDate>Sat, 07 May 2011 18:22:30 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[Software Engineering]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=28</guid>
		<description><![CDATA[This time I&#8217;d like to talk about a phenomenon we don&#8217;t learn about at school and never hear from happening in the US, but apparently being pretty common in our area: Legally Distributed Software Development. The reason is that I consider it very nice, and it deserves a highlight. First off, a definition (since I [...]]]></description>
			<content:encoded><![CDATA[<p>This time I&#8217;d like to talk about a phenomenon we don&#8217;t learn about at school and never hear from happening in the US, but apparently being pretty common in our area: Legally Distributed Software Development. The reason is that I consider it very nice, and it deserves a highlight.</p>
<p><span id="more-28"></span>First off, a definition (since I just invented that name). I call it legally distributed, because distributed development is very common. A few years ago I worked at a company where some programmers were in Tunesia, some in Shenzen/China, some in Paris, some in Vienna, some in Bratislava, etc (nobody knew the exact amount of people involved, but it was estimated at around 200). All of those spread-out teams had to be coordinated and it wasn&#8217;t a lot of fun — some coworkers voiced their opinion that a single team in one location could have done the same work with better quality with 1/4 of people or less.</p>
<p>However, what I&#8217;m calling legally distributed is quite the opposite: the people are all working in the same (general) geographic area, but aren&#8217;t hired by any company which oversees the process. They&#8217;re all what is called one-person-companies (EPU) here. They&#8217;re working together on a project-by-project basis, splitting the costs, risk and earnings. This is a true agile business: For one project, you might work with person A, B and C, on another project with person D and E. This way, you always have some project going on (or more at the same time if you&#8217;re not careful), and you can always pick a team of people that have the talent for the tasks required and the necessary capacities. The risk for everyone is reduced, because it is spread around multiple projects.</p>
<p>Now, there&#8217;s a problem with it that causes this whole structure to be quite fragile: there&#8217;s no legal framework for any of this, except for the very basics (that you&#8217;re allowed to do business at all), which means that there&#8217;s no protection if something goes wrong. There&#8217;s no standard contract for this kind of arrangement (like there is for many other things), and nobody can afford a lawyer to write one. Most of the agreements are based on oral contracts, which any lawyer strongly disapproves of.</p>
<p>However, in an ever-accelerating world, this is definitely the direction software development is heading towards. Some time ago I participated in a conversation with friends of mine, and one of them mentioned that he&#8217;s been working for the same company for four years. The immediate reaction from one of the others was &#8220;What? You should look for a new job very soon, otherwise it looks bad on your CV.&#8221; Considering that my mother worked at a single company for thirty years (until they closed shops) and that&#8217;s not considered unusual in that age group, there&#8217;s a definite trend there. However, getting hired and then quitting are both lengthy processes, which is not adequate for agile project-based development. Thus, many companies have shifted to hidden employment, where you&#8217;re treated like you&#8217;re an employee, but legally are not. This is a very bad thing, because you get the worst thing of both worlds.</p>
<p>Of course, this one-man-company-distribution doesn&#8217;t scale all that well to more than three or maybe four people (I&#8217;ve never had more than three on a team), but when looking at software sales e.g. in one of Apple&#8217;s App Stores, it&#8217;s clear that the profits per developer are heavily favoring smaller teams nowadays anyways.</p>
<p>So, is that kind of development here to stay? Or will those who do it right now just found their own companies in the end, fearing the legal issues arising from it? I don&#8217;t know, but I&#8217;ll definitely stay for a while and see what will happen.</p>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=28</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Software Pattern Fetishism</title>
		<link>http://monitzer.com/?p=23</link>
		<comments>http://monitzer.com/?p=23#comments</comments>
		<pubDate>Mon, 02 May 2011 12:09:57 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[Software Engineering]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=23</guid>
		<description><![CDATA[I&#8217;m sure this article is going to be a bit offending for some software developers, but there&#8217;s something with software design patterns that has been irking me for years, and recently I discovered the reason for that. In the hopes that there are others that think alike, I&#8217;m going to explain the reasons here. Maybe [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m sure this article is going to be a bit offending for some software developers, but there&#8217;s something with software design patterns that has been irking me for years, and recently I discovered the reason for that. In the hopes that there are others that think alike, I&#8217;m going to explain the reasons here. Maybe it does something good.<br />
<span id="more-23"></span><br />
In my UAS (and I&#8217;m sure in most of the others with software development), the software engineering lectures consist of memorizing software design patterns. I&#8217;m pretty sure it&#8217;s that way because it&#8217;s convenient for the teacher, it&#8217;s quantifyable (&#8220;We have explained 15 design patterns in this lecture! The other UAS only does 13!&#8221;), and it&#8217;s testable (&#8220;To which design pattern does this UML diagram fit?&#8221; — That&#8217;s a real question from a Software Engineering test).</p>
<p>However, it completely misses the concept behind software engineering and programming itself. I think design patterns are a bit like LEGO™ pieces: You put in an iterator pattern piece, stick it to a singleton pattern piece and attach an observer pattern piece at the top, and there you have your helicopter that can be built by a five-year old.</p>
<p>That&#8217;s completely not how software programming is really done by professionals. When you have a problem to be solved during development, you just think about it and come up with a solution (usually within minutes). Programming has a very limited solution space, so there are a very limited number of solutions you could come up with. When you do that, you usually do something that somebody incidentally wrote down as a software pattern, even without you knowing about it. So, why should I learn those patterns? The ideas behind them come naturally when they&#8217;re needed anyways.</p>
<p>Maybe I should differentiate a bit at this point. There&#8217;s the MVC pattern (&#8220;Model-View-Controller&#8221;). This pattern is different, because it does not describe a class hierarchy, it describes a way of thinking. That&#8217;s what you really should learn when you want to do professional programming. Programming is not about &#8220;should I subclass this class&#8221;, it&#8217;s about &#8220;what are the general structures of my program?&#8221;. Those are things that cannot be learned by memorizing, they have to be learned by experience (and doing it wrong the first time around — that&#8217;s what antipatterns would cover). Either that, or the explanations of what to do and what not to do become very vague. There&#8217;s no UML in there! <em>Sidenote: I actually considered writing a book about this (working title &#8220;The Art of Software Design&#8221;), but then I remembered the horrible experience of my last book attempt and let it go.</em></p>
<p>So, one of the major things I hate in blog posts is when they go on forever, without adding anything more after a point (or having tons of fillers between the important stuff), so I&#8217;ll just stop here. If you have any comments/questions/complaints, feel free to comment below, twitter me or send me an email.</p>
<p>Maybe I&#8217;ll visit this topic again in the future with some concrete examples (let&#8217;s call them the &#8220;Software Design Pattern Antipatterns&#8221;).</p>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=23</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sproutcore</title>
		<link>http://monitzer.com/?p=20</link>
		<comments>http://monitzer.com/?p=20#comments</comments>
		<pubDate>Mon, 25 Apr 2011 16:23:40 +0000</pubDate>
		<dc:creator>Andreas Monitzer</dc:creator>
				<category><![CDATA[web2.0]]></category>

		<guid isPermaLink="false">http://monitzer.com/?p=20</guid>
		<description><![CDATA[Right up to my first topic: Sproutcore. I&#8217;ve held a workshop about it in the last two weekends, where I demonstrated how to build a basic groupchat application. Unfortunately, the 8h I allocated for it weren&#8217;t enough (but it was close) due to some typical JavaScript issues, namely that it doesn&#8217;t do any name verification [...]]]></description>
			<content:encoded><![CDATA[<p>Right up to my first topic: <a href="http://www.sproutcore.com">Sproutcore</a>.</p>
<p>I&#8217;ve held a workshop about it in the last two weekends, where I demonstrated how to build a basic groupchat application. Unfortunately, the 8h I allocated for it weren&#8217;t enough (but it was close) due to some typical JavaScript issues, namely that it doesn&#8217;t do any name verification at all.</p>
<p>You can get my <a href="https://github.com/anlumo/sproutcore-workshop">demo application from github</a>.</p>
<p><span id="more-20"></span></p>
<p>But, back on topic. Sproutcore is a JavaScript framework for developing modern browser-side web applications. This means that only a single URL is fetched from the server, the rest of the page is run locally. Of course, the application can do AJAX requests back to the server, but the user never has to wait for it after the initial load.</p>
<p>This totally changes the concepts of web pages, and leads to a model that&#8217;s very close to desktop development.</p>
<p>So far, this is actually nothing unusual. There are many other frameworks like this, like GWT and Cappucino. The special thing about Sproutcore is that it&#8217;s based on concepts known from Cocoa, like Key-Value Observing, Key-Value Coding and Binding. These allow creating a very dynamic application without having to write any code to update the content after the initial setup. For example, if the storage layer receives new data from the server, it can be inserted into the data store, which automatically updates the user interface, while still adhering to the MVC concept.</p>
<p>In my demo application for the workshop, for the communication with the server I chose XMPP as the protocol. The reason for this is that via <a href="http://xmpp.org/extensions/xep-0124.html">BOSH</a> the whole server-side infrastructure was already in place, and there&#8217;s a nice JavaScript-library available for it, <a href="http://radikal.net/antikommunistsurf/browse.php?u=Oi8vc3Ryb3BoZS5pbS9zdHJvcGhlanMv&amp;b=13">strophe.js</a>. Besides, it&#8217;s a very popular standard protocol, and I&#8217;m a big fan of it.</p>
<p>I used the storage layer I mentioned earlier for communicating with the server. Creating a message locally means sending it to the server, new messages that are received are created from the storage layer. This allows a clear separation between network protocol and application logic. Due to the dynamic nature of Sproutcore, this works perfectly.</p>
<p>I&#8217;ll probably followup with more specific Sproutcore-related things later, since I&#8217;m using it for multiple rather large projects. There&#8217;s a lot to discover and learn.</p>
]]></content:encoded>
			<wfw:commentRss>http://monitzer.com/?feed=rss2&#038;p=20</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
