Gert Lombard's Blog2016-02-29T06:38:28+00:00http://codeblast.comGert Lombardgert.lombard@gmail.comWhat's the context of this Context?2016-02-10T00:00:00+00:00http://codeblast.com/2016/02/10/android-context<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr"><a href="https://twitter.com/rallat">@rallat</a> Context!</p>— Gert Lombard (@codeblast) <a href="https://twitter.com/codeblast/status/636679726757613568">August 26, 2015</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>When I see Android code like this, it makes me feel uncomfortable:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>class Foo {
private final Context mContext;
public Foo(Context context) {
mContext = context;
}
....
}
</code></pre>
</div>
<p>You may be thinking: <em>“What on earth are you talking about? That’s a super common pattern in Android development to pass <code class="highlighter-rouge">Context</code> around from class to class. We need a <code class="highlighter-rouge">Context</code> instance for all sorts of things like accessing system services etc! Oh wait, I get it, you’re talking about the <code class="highlighter-rouge">m</code> prefix for class member variable names which is specific to Java code in Android!”</em></p>
<p>No, I’m not talking about the weird and unnecessary “Hungarian notation” prefix in <code class="highlighter-rouge">mContext</code>, although I agree it is an eyesore, but that’s a topic for a different blog post! ;-)</p>
<p><strong>tl;dr:</strong> <em>Inject/pass explicit types (e.g. <code class="highlighter-rouge">LayoutInflater</code>) to classes where they are needed, instead of passing <code class="highlighter-rouge">Context</code> all over the place.</em></p>
<p>I find the pervasiveness of this habit of passing a <code class="highlighter-rouge">Context</code> instance into class constructors and method parameters confusing and disturbing. It’s unfortunate that the Android framework provided the <code class="highlighter-rouge">Context</code> base class as a kind of <a href="https://lostechies.com/chrismissal/2009/05/28/anti-patterns-and-worst-practices-monster-objects/">god object</a> or together with things like <code class="highlighter-rouge">getSystemService()</code> as a kind of <a href="http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/">service locator</a> - i.e. it’s the class that knows and does everything!</p>
<p>Why is it a bad idea to pass <code class="highlighter-rouge">Context</code> to a class’s contructor or a method, when everyone does it and you can’t do anything in Android without a <code class="highlighter-rouge">Context</code>?</p>
<p>Some examples of issues:</p>
<ul>
<li>If I’m not the original author of this code, I will wonder: which context is this? Activity, Application, Service?</li>
<li>Can I hold a reference to this context in case I need it later? No, not unless it’s the application context. But how do I know for sure
this is the application context? Especially if this class is used in different context further down the object graph and I don’t know who the caller is. It will eventually cause leaks somewhere e.g. activity leak, because some class will inadvertently hold a reference to the Activity.</li>
<li>Can I use LayoutInflator on it? No, not if it’s not the context of the activity I’m expecting.</li>
<li>It’s a violation of the <a href="http://c2.com/cgi/wiki/LawOfDemeter?LawOfDemeter">Law of Demeter</a>. For example, when I write the unit test for class <code class="highlighter-rouge">Foo</code> which takes <code class="highlighter-rouge">Context</code> as a constructor dependency, how do I know which parts of <code class="highlighter-rouge">Context</code> I need to mock for the test to legitimately pass? If the class is sufficiently complex, I’ll just have to “guess” and figure it out by trial and error. Worse, I may have to mock <code class="highlighter-rouge">A</code> to return a mock of <code class="highlighter-rouge">B</code> to return a mock of <code class="highlighter-rouge">C</code>… Now the unit test is becoming unwieldly.</li>
</ul>
<p><strong>A solution</strong></p>
<p>Assuming you’re convinced at this point that it’s a bad idea to pass <code class="highlighter-rouge">Context</code> down several levels from class to class, what can we do to improve the situation?</p>
<p>Apply this simple principle: <strong>communicate your intention explicitly in your code.</strong></p>
<p>In other words, in many cases, you don’t really want the <code class="highlighter-rouge">Context</code> reference itself, you just want to use it to invoke some action or retrieve some system service. In that case, rather pass the exact service(s) explicitly to the constructor of the class instead of <code class="highlighter-rouge">Context</code>.</p>
<p>As a simple example to demonstrate the point, consider this snippet from a simple hypothetical list adapter:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>private final Context mContext;
private final String[] mValues;
public MyListAdapter(Context context, String[] values) {
this.mContext = context;
this.mValues = values;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View rowView = inflater.inflate(R.layout.rowlayout, parent, false);
...
</code></pre>
</div>
<p>We pass the <code class="highlighter-rouge">Context</code> into the adapter, but the code doesn’t actually need a <code class="highlighter-rouge">Context</code>, it really needs a <code class="highlighter-rouge">LayoutInflater</code> instead! There is no need carrying the <code class="highlighter-rouge">Context</code> around all over the place just in case we need it some day.</p>
<p>Let’s refactor this code to make it slightly easier to understand, reason about and slightly easier to unit test:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>private final LayoutInflater mLayoutInflater;
private final String[] mValues;
public MyListAdapter(LayoutInflater layoutInflater, String[] values) {
this.mLayoutInflater = layoutInflater;
this.mValues = values;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = mLayoutInflater.inflate(R.layout.rowlayout, parent, false);
...
</code></pre>
</div>
<p>Even if you need need to retrieve multiple objects from <code class="highlighter-rouge">Context</code> and not just one as in this example, then it’s still better to pass separate references to those objects.</p>
<p>Of course there are many exceptions to this advice, because often you’ll be forced to pass <code class="highlighter-rouge">Context</code> around through several layers of an object hierarchy because some leaf node which you didn’t write requires it, but even then, you can still be more explicit with your paramter types (and/or parameter names) to communicate your intention more clearly.</p>
<p>For examle, let’s say our list adapter really needs the activity <code class="highlighter-rouge">Context</code>, then I’d propose refactoring the code to accept an <code class="highlighter-rouge">Activity</code> instance instead, so it’s clear what kind of <code class="highlighter-rouge">Context</code> we’re expecting here:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>public MyListAdapter(Activity activityContext, String[] values) {
this.mContext = activityContext;
this.mValues = values;
}
</code></pre>
</div>
<p>Or if you’re using Dagger for dependency injection, you could use qualifier annotations like <code class="highlighter-rouge">@ActivityContext</code> and <code class="highlighter-rouge">@ApplicationContext</code> to differentiate (or even better if possible, separate your Dagger scopes to make it impossible to inject an Activity reference into a service that will outlive the activity…)</p>
<p>Also see: <a href="https://possiblemobile.com/2013/06/context/">Context, What Context?</a> by <a href="https://twitter.com/devunwired">Dave Smith</a></p>
Installing Android Studio on Ubuntu 64 bit2016-01-30T00:00:00+00:00http://codeblast.com/2016/01/30/installing-as-on-ubuntu-64bit<p>Note to self: how to install Oracle JDK 8 and Android Studio on Ubuntu 14.04 64 bit:</p>
<p>When I installed Ubuntu using the x86_64 image, I realized that Android Studio and the Android SDK tools don’t just install on the default Ubuntu 64-bit image, it’s easier to use the 32-bit image, but I wanted to get it working anyway, so here’s the steps for prosperity.</p>
<p>First install some dependencies needed by Android Studio and the Android SDK on Ubuntu x86_64:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ sudo apt-get install libindicator7 libappindicator1
$ sudo apt-add-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
$ javac -version
$ sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0 lib32stdc++6
</code></pre>
</div>
<p>Download Android Studio using Chrome:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ google-chrome-stable
$ cd ~/Downloads/
$ unzip android-studio-ide-141.2456560-linux.zip
$ mv android-studio ..
$ cd ../android-studio/
$ bin/studio.sh
</code></pre>
</div>
<p>Now install the latest Android SDK from within Android Studio and it should work!</p>
<p>I used a few StackOverflow posts to figure this out, like <a href="http://stackoverflow.com/questions/28804863/android-studio-how-to-install-android-platform-tools-on-ubuntu-14-04-64-bit">this one</a>…</p>
Software Modularity Part 22016-01-29T00:00:00+00:00http://codeblast.com/2016/01/29/software-modularity-part2<p>In the <a href="/2016/01/21/software-modularity-part1/">previous post</a>, I described one aspect of modularity: how should you split your app into multiple packages/directories? In this post, I’m continuing on the topic of software modularity…</p>
<p><strong>Single Responsibility Principle</strong></p>
<p>We are all very familiar with the concepts of
<a href="http://c2.com/cgi/wiki?SeparationOfConcerns>">Separation of Concerns</a> and the
<a href="http://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html>">Single Responsibility Principle</a>
(SRP) as they are applied on the class and method level.</p>
<p>Too often, not enough thought is given to applying SRP on the module level. In other words,
a large application should be broken into many small modules instead of growing it into a
large monolithic application over time.</p>
<p><strong>Why?</strong></p>
<p>Some people object to splitting an application into physically separate modules using
arguments like <em>“that’s what packages/namespaces are for”</em>, but that’s not necessarily
enough. Properly structuring the code into packages is definitely a good idea, but we
need to do more. A large application easily becomes a monolithic mess that is
hard to maintain, because changes in one area affect other unrelated areas when
components are so intertwined that it’s difficult to see the boundary between layers.</p>
<p>A modular design allows us to grow the application by adding new modules, with very
little impact to existing modules. That means that separate teams can focus on the
modules applicable to their areas of the application, without being distracted by the
complexity inside unrelated modules.</p>
<p><strong>What is modularity?</strong></p>
<p><a href="http://en.wikipedia.org/wiki/Modularity">Modularity</a> is the degree to which a
system’s components may be separated and recombined. A module is a collection of
related concerns/components. Modules are independent and typically communicate in
a loosely-coupled fashion, e.g. using an <a href="http://square.github.io/otto/">event bus</a>
or well-defined interfaces.</p>
<p>One big advantage of modular design is that it limits the amount of code you need
to consider (i.e. the size of the model you need to load into your brain) when working
on something. You don’t need to understand the entire codebase to see how your change
is going to affect the entire system, you can focus on the module alone, and as long as
the module’s API/interface doesn’t change you can be fairly confident that you’re not
breaking something else.</p>
<p><strong>Goals</strong></p>
<p>What are we trying to accomplish? Some random goals of a modular design:</p>
<ul>
<li>Maintainability: a smaller code base is simply easier to understand and therefore
easier for maintain.</li>
<li>Facilitates teamwork by breaking system down into smaller pieces. A team doesn’t have
to understand or consider the entire application, only their own module(s) and the
interfaces of external modules. Separate teams can work on separate modules without
stepping on each others toes.</li>
<li>Flexibility: can replace/refactor a module’s implementation without affecting the
rest of the system.</li>
<li>Composition: can re-configure an application to include/remove modules as necessary.
Composition of modules can either happen at run-time or statically during compile-time,
for example modules are merged into a single project before compiling. For example,
ideally, new large features would be encapsulated in its own module. When the feature
(experiment) is removed, the separation is clear.</li>
<li>Re-usability: clearly defining and limiting a module’s responsibility means it’s more
likely to be usable in other applications.</li>
<li>Enforces architectural layer integrity: by separating concerns using modules, it’s
easier to enforce the
<a href="http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html">Dependency Rule</a>
which says that “source code dependencies can only point inwards”, for example, your
“networking layer” should not know or care about UI concepts like Activities etc, and
similarly, the Activity code should not attempt to do networking stuff directly. By having
physically separate modules, it makes it easier to visualize the architectural layers of
the application and to understand where a change in the code needs to go.</li>
</ul>
<p>What’s your thoughts on modularity? <a href="https://twitter.com/codeblast">Let me know on Twitter</a>!</p>
How to structure app packages - Modularity Part 12016-01-21T00:00:00+00:00http://codeblast.com/2016/01/21/software-modularity-part1<p>How should you structure your code into separate directories/packages/namespaces?</p>
<p>Another way to phrase that question: How should you modularize your code?</p>
<p>Even if your medium-sized app is small enough that you don’t need physically separate modules,
you likely still need to organize your code into virtual modules by using namespacing,
eg. Java package names. The first and easiest thing you can do to prevent any sufficiently large
codebase from becoming a huge unmaintainable mess is to keep the code modular.
Keep separate things separate and only keep related things together.</p>
<p>This is not a controversial idea. Everyone knows about
“<a href="https://en.wikipedia.org/wiki/Separation_of_concerns">Separation of Concerns</a>” (Soc).
I’m sure we can all agree that SoC is a good idea, however where we may start disagreeing
very quickly once we dig into the details, is exactly what “concerns” should we separate?
How do you decide where to draw the boundary lines between the classes/components of your code?</p>
<p>A very common pattern that I see in Android, AngularJS and other platforms, is to organize
classes by their “type”. For example many, if not most, AngularJS sample apps split the
<code class="highlighter-rouge">.js</code> files into directories like these:</p>
<ul>
<li><code class="highlighter-rouge">controllers</code></li>
<li><code class="highlighter-rouge">directives</code></li>
<li><code class="highlighter-rouge">services</code></li>
</ul>
<p>As another example, let’s take a hypothetical Android “TODO list app”, which might be split
up into directories like this:</p>
<ul>
<li><code class="highlighter-rouge">adapters</code>
<ul>
<li>TaskListAdapter</li>
</ul>
</li>
<li><code class="highlighter-rouge">interfaces</code>
<ul>
<li>LoginResultHandler</li>
</ul>
</li>
<li><code class="highlighter-rouge">model</code>
<ul>
<li>Task</li>
<li>LoginResult</li>
</ul>
</li>
<li><code class="highlighter-rouge">presenters</code>
<ul>
<li>AddEditTaskPresenter</li>
<li>LoginPresenter</li>
<li>TaskListPresenter</li>
</ul>
</li>
<li><code class="highlighter-rouge">utils</code>
<ul>
<li>LoginAPI</li>
<li>TodoDatabase</li>
</ul>
</li>
<li><code class="highlighter-rouge">views</code>
<ul>
<li>LoginActivity</li>
<li>TaskListActivity</li>
<li>AddTaskActivity</li>
<li>EditTaskActivity</li>
</ul>
</li>
</ul>
<p>(Note: my class names above are contrived, a real application will likely need more and different classes.
My point here is the directory naming: <code class="highlighter-rouge">adapters</code>, <code class="highlighter-rouge">views</code>, etc.)</p>
<p>To me the above naming approach seems absurdly arbitrary, because it gives you no useful insight or
visibility into the structure, features, size or scope or any other characteristic of the code.
It only tells you what kind of components (e.g. activities, services, adapters) were used, which
is pretty uninteresting by itself. You might as well separate the classes alphabetically or by date
or by size or any other equally meaningless aspect.</p>
<p>The logical areas / features of the application, namely “Login”, “List tasks” and “Add task” are
scattered all over the place. If I need to make a change to the “Add Task” code, the structure of
the packages don’t assist me at all, in fact they only obscure the structure of the application unnecessarily.</p>
<p>An analogy I like to use: how do we apply SoC when we organize the books in a library? Would it make
sense to organize all the books in a library by the color of their cover? Or by their size?
Thickness? Alphabetically by title or author? No, of course not: books are mainly arranged by <em>subject</em>.</p>
<p>Why would I need <code class="highlighter-rouge">LoginActivity</code> to be in the same package or namespace as the completely unrelated
<code class="highlighter-rouge">TaskListActivity</code>, while their related partner classes, say <code class="highlighter-rouge">LoginPresenter</code> and <code class="highlighter-rouge">TaskListPresenter</code>
respectively, are in a separate package?</p>
<p>Java packages in conjunction with <code class="highlighter-rouge">protected</code> or
<a href="https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html">package-private</a>
access control (or C# namespaces in conjunction with the <code class="highlighter-rouge">internal</code> keyword) provide a mechanism
to isolate and hide related code that should not be accessed externally (albeit a slightly weak
boundary when compared with using physically separate modules, especially in C# where there is no
package-private concept). Consider this when separating code by using packages - do the classes in
the same package really need implicit mutual visibility? In other words, do they really belong together?</p>
<p>It makes a lot more sense to structure the root level of the code according to the separate logical
units, or “modules”, of the app:</p>
<ul>
<li><code class="highlighter-rouge">data</code>
<ul>
<li>Task</li>
<li>TodoDatabase</li>
</ul>
</li>
<li><code class="highlighter-rouge">edit</code>
<ul>
<li>EditTaskActivity</li>
<li>AddTaskActivity</li>
<li>AddEditTaskPresenter</li>
</ul>
</li>
<li><code class="highlighter-rouge">login</code>
<ul>
<li>LoginActivity</li>
<li>LoginAPI</li>
<li>LoginPresenter</li>
<li>LoginResult</li>
<li>LoginResultHandler</li>
</ul>
</li>
<li><code class="highlighter-rouge">list</code>
<ul>
<li>TaskListActivity</li>
<li>TaskListAdapter</li>
<li>TaskListPresenter</li>
</ul>
</li>
</ul>
<p>(Of course, you’re still free to arbitrarily namespace the levels below that into whatever sub-packages
you like, like <code class="highlighter-rouge">views</code>, <code class="highlighter-rouge">services</code>, <code class="highlighter-rouge">utils</code> etc.)</p>
<p>So how did I decide on these directories? Isn’t this also arbitrary? No, the code is now divided into
three logically independent modules: login, add/edit and list. (The <code class="highlighter-rouge">data</code> module is also separated
out because it’s shared by both the <code class="highlighter-rouge">edit</code> and <code class="highlighter-rouge">list</code> modules.)</p>
<p>A module is a logical standalone unit of the application. For example, at least in principle,
the “Add/edit task” functionality can exist and operate independently without having to consider
the “Login” and “List tasks” functionality at all. If I’m a developer tasked to work on the
“Edit task” functionality, I know where I have to focus my attention in the code. I don’t need
to build a mental model of the <code class="highlighter-rouge">login</code> or <code class="highlighter-rouge">list</code> code in order to understand and work on the <code class="highlighter-rouge">edit</code> code.</p>
<p>In John Papa’s Angular Style Guide, he describes the
<a href="https://github.com/johnpapa/angular-styleguide#application-structure-lift-principle">LIFT</a> and
<a href="https://github.com/johnpapa/angular-styleguide#style-y152">Folders-by-Feature Structure</a>
guidelines for naming the directories in a project:</p>
<ul>
<li><em>“Create folders named for the feature they represent… Do not structure your app using
folders-by-type. This requires moving to multiple folders when working on a feature and
gets unwieldy quickly as the app grows to 5, 10 or 25+ views and controllers (and other features),
which makes it more difficult than folder-by-feature to locate files.”</em></li>
<li>LIFT principle: structure your app such that you can
<ul>
<li><strong>L</strong>ocate your code quickly</li>
<li><strong>I</strong>dentify the code at a glance</li>
<li>keep the <strong>F</strong>lattest structure you can</li>
<li><strong>T</strong>ry to stay DRY (Don’t Repeat Yourself)</li>
</ul>
</li>
</ul>
<p>In this post, I’ve only considered using directories/packages as a way to divide code into logical
modules, but in a larger application (especially when working with a team or even multiple teams)
the same concepts would apply when deciding how to break the application up into physically
separate modules, e.g. separate <code class="highlighter-rouge">.jar</code> or <code class="highlighter-rouge">.dll</code> files. I will discuss modularization more in
future posts, e.g. how do we define a module, what are the benefits of modularization,
how does modularization relate to coupling and cohesion.</p>
<p>Links:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Separation_of_concerns">Separation of Concerns</a></li>
<li><a href="https://www.cs.umd.edu/class/spring2003/cmsc838p/Design/criteria.pdf">On the Criteria To Be Used in Decomposing Systems into Modules</a> by <a href="https://en.wikipedia.org/wiki/David_Parnas">David Parnas</a></li>
</ul>
Prettier OSX terminal with iTerm2 and Prezto2015-08-24T00:00:00+00:00http://codeblast.com/2015/08/24/iterm2-zsh-prezto-shell<p>I wanted to describe my current Mac OS X shell setup. I’ve switched from the default Terminal.app to <a href="https://github.com/gnachman/iTerm2/">iTerm2</a>. This includes the following:</p>
<ul>
<li>switched from bash to <a href="http://www.zsh.org">zsh</a></li>
<li>use <a href="https://github.com/sorin-ionescu/prezto">prezto</a> framework for a prettier colorful prompt</li>
<li>set up a few iTerm2 triggers e.g. to capture and highlight or show Android gradle build errors etc.</li>
</ul>
<p>I’ll list every step I took to install all the various pieces:</p>
<p><strong>1. preparation</strong></p>
<p>First install <a href="http://brew.sh">Homebrew</a> if you don’t have it yet:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
</code></pre>
</div>
<p>And we also need <a href="http://caskroom.io">caskroom</a> to install apps with binary installers:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ brew install askroom/cask/brew-cask
</code></pre>
</div>
<p><strong>2. install zsh</strong></p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ brew install zsh
</code></pre>
</div>
<p><strong>3. install iTerm2</strong></p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ brew cask install iterm2
</code></pre>
</div>
<p><strong>4. configure zsh as the new default shell</strong></p>
<p>Just for interest’s sake, this is to show that originally I was on bash:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ echo $SHELL
/bin/bash
$ echo $BASH_VERSION
3.2.57(1)-release
</code></pre>
</div>
<p>Now change my default shell to zsh:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ chsh -s /bin/zsh
</code></pre>
</div>
<p>Re-open iterm2 and check the shell version again to confirm zsh is running:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>% echo $SHELL
/bin/zsh
% echo $ZSH_VERSION
5.0.5
</code></pre>
</div>
<p>Specify custom location for my dot-files so I can save them in a git repository at <a href="http://bitbucket.org">BitBucket</a>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>% mkdir ~/dotfiles
% cat <<EOT > ~/dotfiles/.zshenv
#!/bin/zsh
export ZDOTDIR=~/dotfiles
source "\${ZDOTDIR}/.zprofile"
EOT
% touch ~/dotfiles/.zshrc # will put my fav aliases and functions here
% ln -s ~/dotfiles/.zshenv ~/.zshenv
</code></pre>
</div>
<p>Quick example of some <a href="https://gist.github.com/natelandau/10654137">handy aliases</a> etc in <code class="highlighter-rouge">.zshrc</code>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>% export ZDOTDIR=~/dotfiles
% cat <<EOT >> ~/dotfiles/.zshrc
source "\${ZDOTDIR:-\$HOME}/.zprezto/init.zsh"
export JAVA_HOME="`/usr/libexec/java_home -v '1.7*'`"
alias ll='ls -FGlAhp'
alias gca='git commit -a --amend'
alias gr='./gradlew'
# etc...
EOT
</code></pre>
</div>
<p><strong>5. get prezto</strong></p>
<div class="highlighter-rouge"><pre class="highlight"><code>% git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"
</code></pre>
</div>
<p>Symlink some default prezto config files:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>% setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done
</code></pre>
</div>
<p>Re-open the iterm2 window to see if all the dotfiles are set up correctly (i.e. zprezto modules are loading without errors).</p>
<p>Set the theme (I use <code class="highlighter-rouge">steeef</code> built-in theme), modules (like git) etc in <code class="highlighter-rouge">.zpreztorc</code>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>% vi $ZDOTDIR/.zpreztorc
</code></pre>
</div>
<p>For example, to change the theme in <code class="highlighter-rouge">.zpreztorc</code> from the default, look for the following line and change <code class="highlighter-rouge">sorin</code> to <code class="highlighter-rouge">steeef</code>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>zstyle ':prezto:module:prompt' theme 'sorin' # <-- change 'sorin' to 'steeef'...
</code></pre>
</div>
<p>After setting up vi key bindings, <code class="highlighter-rouge">^R</code> for history substring search stopped working. View the current key bindings - this confirms <code class="highlighter-rouge">^R</code> is currently bound to <code class="highlighter-rouge">redisplay</code> instead of <code class="highlighter-rouge">history-incremental-search-backward</code>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>% bindkey -L | grep '\^R'
bindkey "^R" redisplay
</code></pre>
</div>
<p>I added this line to my <code class="highlighter-rouge">~/dotfiles/.zshrc</code> file to enable <code class="highlighter-rouge">^R</code> history search again:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>bindkey "^R" history-incremental-search-backward
</code></pre>
</div>
<p>This setup was inspired by this <a href="http://mikebuss.com/2014/02/02/a-beautiful-productive-terminal-experience/">post</a> by <a href="https://twitter.com/michaeltbuss">Mike Buss</a>.</p>
This blog has moved (Blogger vs GitHub Pages)2015-08-07T03:26:00+00:00http://codeblast.com/2015/08/07/this-blog-has-moved-blogger-vs-githubHi there! I'm so glad you've found my blog!<br /><b><br /></b><b>My blog is now: <a href="http://codeblast.com/">codeblast.com</a></b><br /><br />Over the years, I've just never been able to find a blogging platform that I'm happy with. Blogger has been really good from an admin perspective, but not so much for WRITING blog posts. I prefer <a href="http://daringfireball.net/projects/markdown/">Markdown</a> as a file format, and GitHub Pages supports [Markdown](https://pages.github.com/) very well.<br /><br />I still haven't found a blogging workflow that motivates me to blog more, but for what it's worth I've decided to switch to <a href="https://pages.github.com/">GitHub Pages</a> for now.<br /><br />I may perhaps try to port my old blogposts from this Blogger site (and maybe even older ones from WordPress) to my new blog some day. But in the future, please look for me at codeblast.com.<br /><br />Also please consider joining Twitter and follow me at <a href="https://twitter.com/codeblast">@codeblast</a>. Hope to hear from you!
<p>Update 2/28/2016:<br />
Today I finally imported my old posts from my previous Blogger website at <a href="http://www.lombard.me">www.lombard.me</a> to GitHub Pages using the <code>jekyll-import</code> Ruby gem... Unfortunately I couldn't import the comments from Blogger, so they'll be lost. I'm now using [Disqus](https://disqus.com/) for the comments system.
Android Dagger 2 Generated annotation JSR2502015-08-06T00:00:00+00:00http://codeblast.com/2015/08/06/dagger2-jsr250-annotations<p>When you’re using Dagger 2.0 in your Android projects, you’ll quickly realize you need to include
an additional dependency to provide the <code class="highlighter-rouge">@Generated</code> annotation (from <a href="https://en.wikipedia.org/wiki/JSR_250">JSR-250</a>). [**]</p>
<p>These are the common options typically seen in online Dagger examples:</p>
<ol>
<li>javax.annotation:jsr250-api:1.0</li>
<li>org.glassfish:javax.annotation:10.0-b28</li>
<li>javax.annotation:javax.annotation-api:1.2</li>
</ol>
<p>So which one should you use?</p>
<p>Let’s do a quick comparison of the 3 jars:</p>
<ol>
<li>
<p><a href="https://bintray.com/bintray/jcenter/javax.annotation%3Ajsr250-api/1.0/view">javax.annotation:jsr250-api:1.0</a></p>
<ul>
<li>Jar file size: 5.7kb</li>
<li>Date of javax directory: Apr 27, 2006</li>
<li>License: https://glassfish.java.net/public/CDDLv1.0.html</li>
<li>Created-By: 1.5.0_05-b05 (Sun Microsystems Inc.)</li>
</ul>
</li>
<li>
<p><a href="https://bintray.com/bintray/jcenter/org.glassfish%3Ajavax.annotation/10.0-b28/view">org.glassfish:javax.annotation:10.0-b28</a></p>
<ul>
<li>Jar file size: 20kb</li>
<li>Date of javax directory: Oct 8, 2008</li>
<li>License: https://glassfish.dev.java.net/nonav/public/CDDL+GPL.html</li>
<li>Created-By: Apache Maven Bundle Plugin</li>
</ul>
</li>
<li>
<p><a href="https://bintray.com/bintray/jcenter/javax.annotation%3Ajavax.annotation-api/1.2/view">javax.annotation:javax.annotation-api:1.2</a></p>
<ul>
<li>Jar file size: 26kb</li>
<li>Date of javax directory: Apr 26, 2013</li>
<li>Created-By: Created-By: 1.7.0_09 (Oracle Corporation)</li>
<li>License: https://glassfish.dev.java.net/nonav/public/CDDL+GPL.html</li>
</ul>
</li>
</ol>
<p>So the second contains slightly more meta-data files and a different license (includes GPL) than the first option, but otherwise they contain essentially the same content - e.g. the same .class files.</p>
<p>The third one contains a few extra annotations, including: <code class="highlighter-rouge">@ManagedBean</code>, <code class="highlighter-rouge">@Priority</code>, but is pretty much the same as the second one.</p>
<p>Verdict: use the first/oldest one: javax.annotation:jsr250-api:1.0</p>
<p>Final note: when you include the dependency in your android project, use the <code class="highlighter-rouge">provided</code> scope instead of <code class="highlighter-rouge">compile</code>, to prevent the JSR-250 annotations from being distributed with your app, in other words:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>dependencies {
compile 'com.google.dagger:dagger:2.0.1'
provided 'javax.annotation:jsr250-api:1.0'
apt 'com.google.dagger:dagger-compiler:2.0.1'
}
</code></pre>
</div>
<p>** PS. if you don’t include one of these JSR-250 jars in your project, you’ll get this compile error in one of the files generated by dagger-compiler:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>Error:(17, 24) error: package javax.annotation does not exist
Error:(20, 2) error: cannot find symbol class Generated
Error:(21, 14) error: dagger.internal.codegen.ComponentProcessor was unable to process this class because not all of its dependencies could be resolved. Check for compilation errors or a circular dependency with generated code.
</code></pre>
</div>
Using Robolectric in offline mode2015-05-13T00:00:00+00:00http://codeblast.com/2015/05/13/using-robolectric-in-offline-mode<h2 id="the-scenario">The scenario</h2>
<ul>
<li>Your CI server doesn’t have direct internet access; or</li>
<li>it requires a proxy for internet access</li>
<li>and your Robolectric test builds are failing as result…</li>
</ul>
<h2 id="the-problem">The problem</h2>
<p>The Robolectric test runner downloads some dependency jars that it needs to run at <em>runtime</em> (not compile-time). Normally you don’t even notice this when running your unit tests locally, but this could be a problem on Jenkins/CI if your company doesn’t allow internet access from the CI boxes (as it should be). What happens is, when the Robolectric tests try to run on your CI box, it will fail with a MultipleArtifactsNotFoundException error like the following:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>com.example.app.MainActivityTest > testFoo FAILED
org.apache.tools.ant.BuildException
Caused by: org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException
</code></pre>
</div>
<p>Or the error may also look like this:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>:app:testDebug
com.example.app.MainActivityTest > testFoo FAILED
org.apache.tools.ant.BuildException
Caused by: org.apache.maven.artifact.resolver.ArtifactResolutionException
Caused by: org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException
Caused by: org.apache.maven.project.ProjectBuildingException
Caused by: org.apache.maven.project.ProjectBuildingException
Caused by: org.apache.maven.artifact.resolver.ArtifactNotFoundException
Caused by: org.apache.maven.wagon.ResourceDoesNotExistException
1 test completed, 1 failed
:app:testDebug FAILED
</code></pre>
</div>
<p>If you run gradlew with <code class="highlighter-rouge">-i</code> or <code class="highlighter-rouge">-d</code> options, you’ll see more details of what’s happening and then you realize it’s because Robolectric is trying to download jars from <code class="highlighter-rouge">repo1.maven.org</code> which you may not have access to if you’re using a local repo such as <a href="http://www.jfrog.com/open-source/">Artifactory</a>.</p>
<p>We want to stop Robolectric from trying to download its jars from Maven Central and force it to use a local copy of the jars, which we can manually copy to the CI build slave servers.</p>
<p>Robolectric 2.4 introduced two new <a href="http://robolectric.org/configuring/">settings</a> to prevent downloading the dependencies from the hardcoded sonatype / maven URL:</p>
<ul>
<li>robolectric.offline</li>
<li>robolectric.dependency.dir</li>
</ul>
<p>However, it’s not completely clear from the documentation how to use these settings. The documentation just mentions that they’re “system properties”.</p>
<p>There were a few questions I had when I started with this:</p>
<ol>
<li>Which jars are needed by the Robolectric test runner?</li>
<li>How do I configure these two system properties in my project’s build.gradle file?</li>
</ol>
<h2 id="the-solution">The solution</h2>
<p><strong>Step 1: Which jars are needed?</strong></p>
<p>In order to place the jars in a known location on the CI build slaves, we first need to figure out exactly which jars are used by Robolectric during run-time.</p>
<p>One way to do this, is to run <code class="highlighter-rouge">gradlew testDebug -d</code> (i.e. with debug output) and examine the logs to figure out which jars were downloaded during test run-time.</p>
<p>I decided to take another approach, and go to the Robolectric sources to see which dependencies it needs. The info we want is in <a href="https://github.com/robolectric/robolectric/blob/master/robolectric/src/main/java/org/robolectric/internal/SdkConfig.java">SdkConfig.java</a>.</p>
<p>From SdkConfig.java I could tell that the following four dependencies are needed by Robolectric 3.0 at run-time:</p>
<ul>
<li>org.robolectric:android-all:5.0.0_r2-robolectric-1</li>
<li>org.robolectric:shadows-core:3.0-rc2:21</li>
<li>org.json:json:20080701</li>
<li>org.ccil.cowan.tagsoup:tagsoup:1.2</li>
</ul>
<p>However, we also need the transitive dependencies of these jars, i.e. the dependencies of these dependencies.</p>
<p>I figured the easiest way to correctly download these 4 jars and all their dependencies, is to let Maven do it. We can create a simple Maven <code class="highlighter-rouge">pom.xml</code> file that just lists these 4 dependency artifacts, and then we let <code class="highlighter-rouge">mvn dependency:copy-dependencies</code> download everything for us.</p>
<p>I wrote a quick ‘n dirty <a href="https://gist.github.com/glombard/2fdb883de1d50fb51d1a">Python script</a> to generate the <a href="https://gist.github.com/glombard/2fdb883de1d50fb51d1a#file-pom-xml"><code class="highlighter-rouge">pom.xml</code> file</a> for me.</p>
<script src="https://gist.github.com/glombard/2fdb883de1d50fb51d1a.js?file=pom.xml"></script>
<p>Now I can use the Maven POM file to download the jars that Robolectric needs to a specific directory like <code class="highlighter-rouge">/tmp/robolectric-files/</code>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>mvn dependency:copy-dependencies -DremoteRepositories=http://repo1.maven.org/maven2/ -DoutputDirectory=/tmp/robolectric-files
</code></pre>
</div>
<p>These are all the files downloaded by <code class="highlighter-rouge">mvn</code>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ mvn dependency:copy-dependencies -DremoteRepositories=http://repo1.maven.org/maven2/ -DoutputDirectory=/tmp/robolectric-files
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building robolectric-files 3.0-rc2
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:copy-dependencies (default-cli) @ robolectric-files ---
[INFO] Copying vtd-xml-2.11.jar to /tmp/robolectric-files/vtd-xml-2.11.jar
[INFO] Copying accessibility-test-framework-1.0.jar to /tmp/robolectric-files/accessibility-test-framework-1.0.jar
[INFO] Copying tagsoup-1.2.jar to /tmp/robolectric-files/tagsoup-1.2.jar
[INFO] Copying json-20080701.jar to /tmp/robolectric-files/json-20080701.jar
[INFO] Copying robolectric-resources-3.0-rc2.jar to /tmp/robolectric-files/robolectric-resources-3.0-rc2.jar
[INFO] Copying shadows-core-3.0-rc2-21.jar to /tmp/robolectric-files/shadows-core-3.0-rc2-21.jar
[INFO] Copying sqlite4java-0.282.jar to /tmp/robolectric-files/sqlite4java-0.282.jar
[INFO] Copying icu4j-53.1.jar to /tmp/robolectric-files/icu4j-53.1.jar
[INFO] Copying android-all-5.0.0_r2-robolectric-1.jar to /tmp/robolectric-files/android-all-5.0.0_r2-robolectric-1.jar
[INFO] Copying robolectric-annotations-3.0-rc2.jar to /tmp/robolectric-files/robolectric-annotations-3.0-rc2.jar
[INFO] Copying robolectric-utils-3.0-rc2.jar to /tmp/robolectric-files/robolectric-utils-3.0-rc2.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 08:55 min
[INFO] Finished at: 2015-05-13T18:26:23-07:00
[INFO] Final Memory: 13M/239M
[INFO] ------------------------------------------------------------------------
</code></pre>
</div>
<p>Now copy all those files from <code class="highlighter-rouge">/tmp/robolectric-files/</code> to some known location on your CI build slave box, say to <code class="highlighter-rouge">/home/jenkins/robolectric-files</code> (assuming <code class="highlighter-rouge">jenkins</code> is your CI build user account).</p>
<p><strong>Step 2: Set the offline-mode System Properties in build.gradle</strong></p>
<p>We need to set the following two Java System Properties for the Robolectric Test Runner to use the local files:</p>
<ul>
<li>robolectric.offline = true</li>
<li>robolectric.dependency.dir = /home/jenkins/robolectric-files</li>
</ul>
<p>One way to do this, is to add the following to our app’s <code class="highlighter-rouge">build.gradle</code> file:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>afterEvaluate {
project.tasks.withType(Test) {
systemProperties.put('robolectric.offline', 'true')
systemProperties.put('robolectric.dependency.dir', '/home/jenkins/robolectric-files')
}
}
</code></pre>
</div>
<p>Now we can run Gradle and our unit tests completely in offline mode:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ ./gradlew clean testDebug --offline
</code></pre>
</div>
<p>(Note: hardcoding a specific user’s home directory in the gradle file isn’t a good idea, but you get the point. Use a directory that works for you.)</p>
<p><strong>Alternate solution:</strong></p>
<p>Instead of Step 2 above, of course you could just install the necessary files into your CI box’s Maven repository (~/.m2/repository/) using something like this for each of them:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>mvn install:install-file -DgroupId=org.robolectric \
-DartifactId=shadows-core -Dversion=3.0-rc2 \
-Dclassifier=21 -Dpackaging=jar \
-Dfile=/tmp/robolectric-files/shadows-core-3.0-rc2-21.jar
</code></pre>
</div>
<p>But in my solution above I opted for overriding the location of the files using the <code class="highlighter-rouge">robolectric.offline</code> and <code class="highlighter-rouge">robolectric.dependency.dir</code> system settings, because that way I have more clear control and visibility over which files I’m responsible for maintaining manually.</p>
<p><strong>Update</strong> 17 July 2015:</p>
<p>My python script above worked for robolectric-3.0-rc2 but not the final 3.0 version <code class="highlighter-rouge">pom.xml</code>… See <a href="https://gist.github.com/glombard/2fdb883de1d50fb51d1a#comment-1464721">@benoberkfel’s comment</a>.</p>
<p><strong>Another solution</strong> suggested by <a href="https://github.com/robolectric/robolectric/issues/571#issuecomment-93361462">@nenick</a>:</p>
<p>Create a file called ~/.m2/settings.xml and specify a mirror URL for your local Artifactory/Nexus repository. That way Robolectric will automatically download the required runtime files from your local mirror and no other hacks are required. This seems like a nicer solution depending on your needs. Something like this:</p>
<div class="highlighter-rouge"><pre class="highlight"><code><settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<mirrors>
<mirror>
<id>nexus</id>
<name>mirror of remote repositories</name>
<mirrorOf>*</mirrorOf>
<url>https://<your address>/nexus/content/groups/public</url>
</mirror>
</mirrors>
</settings>
</code></pre>
</div>
<p>Also see this related issue on GitHub: <a href="https://github.com/robolectric/robolectric/issues/571">Dependency resolution behind proxy #571</a></p>
Using XMLStarlet to query XML docs on the command-line2015-05-12T00:00:00+00:00http://codeblast.com/2015/05/12/query-xml-with-xmlstarlet<p>If you’re a developer or DevOps-type guy, then I bet you like doing things on the command-line and/or in batch files / shell scripts.</p>
<p>This year I’ve discovered two amazing tools for querying XML and JSON documents from the command-line: <a href="http://xmlstar.sourceforge.net/">XMLStarlet</a> for querying XML and <a href="http://stedolan.github.io/jq/">jq</a> for querying JSON from the command-line. Both tools are available on Mac OS X, Windows and Linux. Right now I want to focus on XMLStarlet.</p>
<p>XMLStarlet lets you make XPath style queries and transformations right from the command-line.</p>
<p>This is very handy to query Web APIs or local XML files from scripts.</p>
<p>For example, I often want to parse the results out of <a href="http://checkstyle.sourceforge.net/">checkstyle</a>, <a href="http://pmd.sourceforge.net/">pmd</a>, <a href="http://findbugs.sourceforge.net/">findbugs</a> or <a href="http://help.catchsoftware.com/display/ET/JUnit+Format">junit</a> XML report files in an Android project.</p>
<p>In this post I’ll show how to use <code class="highlighter-rouge">xmlstarlet</code> to query the checkstyle XML report output for an Android project.</p>
<p><strong>Installing xmlstarlet:</strong></p>
<p>On Mac OS X, install it with <a href="http://brew.sh/">Homebrew</a>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>brew install xmlstarlet
</code></pre>
</div>
<p>On Windows, <a href="https://chocolatey.org/packages?q=xmlstarlet">Chocolatey</a> will probably work for you:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>choco install xmlstarlet
</code></pre>
</div>
<p><strong>XMLStarlet select basics:</strong></p>
<p>Do this first: look at the <code class="highlighter-rouge">sel</code> command’s help (i.e. select data using XPath):</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ xmlstarlet sel --help
</code></pre>
</div>
<p>Select command help output:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>XMLStarlet Toolkit: Select from XML document(s)
Usage: xmlstarlet sel <span class="nt"><global-options></span> {<span class="nt"><template></span>} [ <span class="nt"><xml-file></span> ... ]
where
<span class="nt"><global-options></span> - global options for selecting
<span class="nt"><xml-file></span> - input XML document file name/uri (stdin is used if missing)
<span class="nt"><template></span> - template for querying XML document with following syntax:
<span class="nt"><global-options></span> are:
-Q or --quiet - do not write anything to standard output.
-C or --comp - display generated XSLT
-R or --root - print root element <span class="nt"><xsl-select></span>
-T or --text - output is text (default is XML)
-I or --indent - indent output
-D or --xml-decl - do not omit xml declaration line
-B or --noblanks - remove insignificant spaces from XML tree
-E or --encode <span class="nt"><encoding></span> - output in the given encoding (utf-8, unicode...)
-N <span class="nt"><name></span>=<span class="nt"><value></span> - predefine namespaces (name without 'xmlns:')
ex: xsql=urn:oracle-xsql
Multiple -N options are allowed.
--net - allow fetch DTDs or entities over network
--help - display help
Syntax for templates: -t|--template <span class="nt"><options></span>
where <span class="nt"><options></span>
-c or --copy-of <span class="nt"><xpath></span> - print copy of XPATH expression
-v or --value-of <span class="nt"><xpath></span> - print value of XPATH expression
-o or --output <span class="nt"><string></span> - output string literal
-n or --nl - print new line
-f or --inp-name - print input file name (or URL)
-m or --match <span class="nt"><xpath></span> - match XPATH expression
--var <span class="nt"><name></span> <span class="nt"><value></span> --break or
--var <span class="nt"><name></span>=<span class="nt"><value></span> - declare a variable (referenced by $name)
-i or --if <span class="nt"><test-xpath></span> - check condition <span class="nt"><xsl:if</span> <span class="na">test=</span><span class="s">"test-xpath"</span><span class="nt">></span>
--elif <span class="nt"><test-xpath></span> - check condition if previous conditions failed
--else - check if previous conditions failed
-e or --elem <span class="nt"><name></span> - print out element <span class="nt"><xsl:element</span> <span class="na">name=</span><span class="s">"name"</span><span class="nt">></span>
-a or --attr <span class="nt"><name></span> - add attribute <span class="nt"><xsl:attribute</span> <span class="na">name=</span><span class="s">"name"</span><span class="nt">></span>
-b or --break - break nesting
-s or --sort op xpath - sort in order (used after -m) where
op is X:Y:Z,
X is A - for order="ascending"
X is D - for order="descending"
Y is N - for data-type="numeric"
Y is T - for data-type="text"
Z is U - for case-order="upper-first"
Z is L - for case-order="lower-first"
(rest of output omitted for brevity...)
</code></pre>
</div>
<p>The most important ones to note are the <code class="highlighter-rouge">-v</code> (value-of) and <code class="highlighter-rouge">-i</code> (if) expressions. Also useful is <code class="highlighter-rouge">-o</code> (literal string output) and <code class="highlighter-rouge">-n</code> (print newline in the output).</p>
<p><strong>Parsing checkstyle.xml report to list errors:</strong></p>
<p>Let’s break things down. First you need to find all the <code class="highlighter-rouge">checkstyle.xml</code> report files for your project. This will depend on your Gradle setup, but for me this works (from the project root):</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ find . -path '*/build/reports/checkstyle/checkstyle.xml'
</code></pre>
</div>
<p>This lists all the <code class="highlighter-rouge">checkstyle.xml</code> reports under each Android module in my project.</p>
<p>The contents of the <code class="highlighter-rouge">checkstyle.xml</code> file has this syntax:</p>
<div class="highlighter-rouge"><pre class="highlight"><code><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span>
<span class="nt"><checkstyle</span> <span class="na">version=</span><span class="s">"6.2"</span><span class="nt">></span>
<span class="nt"><file</span> <span class="na">name=</span><span class="s">"/Users/glombard/myproject/app/src/main/java/com/codeblast/android/myapp/MyFile.java"</span><span class="nt">></span>
<span class="nt"></file></span>
<span class="nt"><file</span> <span class="na">name=</span><span class="s">"/Users/glombard/myproject/app/src/main/java/com/codeblast/android/myapp/OtherFile.java"</span><span class="nt">></span>
<span class="nt"><error</span> <span class="na">line=</span><span class="s">"7"</span> <span class="na">severity=</span><span class="s">"error"</span> <span class="na">message=</span><span class="s">"Wrong order for &apos;android.animation.ValueAnimator&apos; import. Order should be: android, com, junit, net, org, java, javax. Each group should be separated by a single blank line."</span> <span class="na">source=</span><span class="s">"com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck"</span><span class="nt">/></span>
<span class="nt"></file></span>
... rest omitted...
</code></pre>
</div>
<p>This means that <code class="highlighter-rouge">MyFile.java</code> has no errors, but the second entry, <code class="highlighter-rouge">OtherFile.java</code> has one error with the order of the imports at line 7.</p>
<p>I’d like to parse out the errors from this file.</p>
<p>To make it easier, let’s first just list all the files checked, regardless of whether they’ve got errors or not:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ xmlstarlet sel -t -m /checkstyle/file -v @name -n library/build/reports/checkstyle/checkstyle.xml
</code></pre>
</div>
<p>OK, that gives us a taste for the <code class="highlighter-rouge">-m</code> (match element) and <code class="highlighter-rouge">-v</code> (print value-of) commands (we’re just printing the <code class="highlighter-rouge">name</code> attribute of the <code class="highlighter-rouge"><file></code> element…)</p>
<p>But we’re actually only interested in files containing <code class="highlighter-rouge"><error></code> child elements. Let’s only list files with errors by first matching on <code class="highlighter-rouge">/checkstyle/file</code> and then also matching on <code class="highlighter-rouge">error</code>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>$ xmlstarlet sel -t -m /checkstyle/file -i error -v @name -n library/build/reports/checkstyle/checkstyle.xml
</code></pre>
</div>
<p>This just prints out the filenames of the <code class="highlighter-rouge">file</code> elements that also had <code class="highlighter-rouge">error</code> elements in them.</p>
<p>Now let’s put everything together: we’ll use <code class="highlighter-rouge">find</code> to find all the <code class="highlighter-rouge">checkstyle.xml</code> files in our project, then we want to use <code class="highlighter-rouge">xargs</code> to pipe the contents of all those <code class="highlighter-rouge">checkstyle.xml</code> files to <code class="highlighter-rouge">xmlstarlet</code> and then query for the errors:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>find . -path '*/build/reports/checkstyle/checkstyle.xml' | xargs xmlstarlet sel -t -m /checkstyle/file -i error -v @name -m error -n -v @line -o ': ' -v @message -n -n
</code></pre>
</div>
<p>I hope this helps you to see the possibilities of being able to query XML from scripts (CI etc). If so, let me know how. If not, let me know how I can improve this page. :-)</p>
<p>Remember, also check out <a href="http://stedolan.github.io/jq/">jq</a> for querying JSON files in a similar way.</p>
Why blog?2015-03-18T00:00:00+00:00http://codeblast.com/2015/03/18/why-blog<p>Ever since I created my first website(s) on Xoom and Tripod around 1998, before the days of blogging, I’ve <em>wanted</em> to blog. I have these random thoughts about things and I feel the desire to write it down. More for myself than for any particular audience. Just because I’m attracted by the idea of creating something.</p>
<p>However, I’ve been trying to write blog posts occasionally over the last few years, and I keep getting discouraged by my lack of writing skill. I start typing a few notes for a blog idea, and then once I get to a few bullet points of ideas, I really struggle to figure out how I’m going to expand the handful of bullet points into a full blog post with colors and graphs and code samples etc. Hundreds of potential blog posts only remained as small draft note files somewhere in a “blog ideas” directory.</p>
<p>I look at blogs by some of my blogging heros like <a href="https://twitter.com/shanselman" title="Scott Hanselman on Twitter">Scott Hanselman</a>, <a href="https://twitter.com/jsonmez" title="John Sonmez on Twitter">Jon Sonmez</a>, <a href="https://twitter.com/daedtech" title="Erik Dietrich on Twitter">Erik Dietrich</a> or <a href="https://twitter.com/claireburge" title="Claire Burge on Twitter">Claire Burge</a> (just a few random examples), and I feel both inspired and discouraged at the same time by the quality and quantity of their blogs (and other content!). I know I’ll never have the colorful vocabulary and the skill with words to create something that I could be that proud of. (And I’ve never been very inspired to blog using the tools I’ve tried like WordPress, Blogger, LiveWriter, but I’m hoping that will change now I’m using GitHub Pages.)</p>
<p>I have to keep reminding myself: screw it, let’s do it. The guilt I feel about not blogging at all (or not writing more code for that matter) is worse than my disappointment in my uninspiring writing.</p>
<p>I think a lot of developers don’t find blogging appealing because they think they’ll leave the blogging to the experts and I guess they don’t feel comfortable putting their opinions out there for everyone to see. I don’t really care much about what people think about my blog posts. If a stupid blog post I wrote 2 years ago helps one person to configure their internet settings on their Nexus 7 for O2 Ireland, then I think that’s pretty cool. But ultimately I’m really just doing it for myself. I’m talking to myself, because it allows me to try and structure my thoughts in a way I can’t really do if I keep the thought in my brain. Ideally I would have discussed the ideas instead (or as well) with a friend or a coworker to have a more interesting two-way conversation, but this will have to do.</p>
<p>So thanks for being a listening friend here.</p>
<p>PS. I also <a href="http://www.lombard.me/2012/05/why-blog.html" title="Why blog?">wrote</a> about this same topic back in 2012.</p>
Android Testing2015-03-18T00:00:00+00:00http://codeblast.com/2015/03/18/android-testing<p>Try this: go to GitHub. Search for any open-source Android app you can think of. OK, now take a look at the app’s unit tests. Yes, the unit tests.</p>
<p>No unit tests? (Other than the one generated by Android Studio…)</p>
<p>So why don’t people unit test Android applications?</p>
<p>I’ll guess it’s because of any combination of these factors:</p>
<ol>
<li>The Android platform itself doesn’t really lend itself well to unit testing. For example, your class that represents a screen, extends the Activity class, and you can’t just construct an activity yourself in a unit test, you need to write your test as an Android Instrumentation Test which requires an emulator or a physical device to run the test.</li>
<li>Running Android tests (or even Lint checks or anything with Gradle) is super slow! Really really super slow if you’re coming from a .NET or Web background.</li>
<li>Pure unit test support (i.e. JVM / JUnit4 tests without the need for an emulator or device) was only released in Feb 2015. Several years since people started writing Android apps and tests. Unit testing support is fairly new and it will take a while for people to adopt this new mindset.</li>
</ol>
Markdown blogging on an iPad2015-03-17T00:00:00+00:00http://codeblast.com/2015/03/17/markdown-blogging-on-ipad<p>I just installed the <a href="http://omz-software.com/editorial/">Editorial</a> app on my new iPad and using a bluetooth keyboard for typing. Yay! Blogging is possible on an iPad!</p>
<p>Editorial is a markdown editor for iPad ($6.99). On Windows 8, I used MarkdownPad 2 Pro ($14.99) for markdown preview. On Mac OS X, I use SublimeText along with Marked 2 ($9.99) to preview the Markdown text occasionally.</p>
<p>If you’re a developer and you’re not using Markdown everywhere yet, you don’t know what you’re missing! :-)</p>
<p>The Editorial app easily syncs with Dropbox, so I should be able to set up my GitHub Pages git repository (or at least a symlink to my drafts folder) in the appropriate Dropbox directory, and then I should have a pretty good workflow for writing blogpost drafts on the iPad. Then I can preview it on the Mac when I’m ready to publish and push to the GitHub repo to publish my blog post.</p>
Drawing tools for developers2015-03-12T00:00:00+00:00http://codeblast.com/2015/03/12/drawing-tools-for-developers<p>If you’re like me, then you hate doing documentation. I’d much rather draw a block diagram on a whiteboard and a photo of it. But sometimes you need to create a more official looking diagram, and then you probably want a tool that helps you get the job done as quickly as possible, without having to learn how to use Visio or some complex graphics / drawing application.</p>
<h2 id="seqdiag">seqdiag</h2>
<p><a href="http://blockdiag.com/en/seqdiag/" title="seqdiag">seqdiag</a> allows you to generate UML sequence diagrams using a simple text file format.</p>
<h2 id="drawio">draw.io</h2>
<p><a href="https://www.draw.io/">draw.io</a> is a very nice online drawing tool that allows you to download your drawings, including UML diagrams etc, as .png or lots of other file formats.</p>
<h2 id="graphviz">graphviz</h2>
<p><a href="http://www.graphviz.org/" title="graphviz / dot">GraphViz</a> with its simple .dot file syntax makes it very easy to create directed graphs. It’s easy to write a script that reads some input and generates the .dot file, and then you use graphviz to generate a .png or .pdf file. For example, I’ve used it to generate a graph to visualize the dependencies between projects in a Visual Studio C++ solution etc.</p>
<h2 id="visual-studio">Visual Studio</h2>
<p>Recent versions of Visual Studio support generating a <a href="http://en.wikipedia.org/wiki/DGML" title="Directed graph markup language">.dgml</a> graph to show project dependencies.</p>
<p>But you can also write your own script (PowerShell?) to generate a .dgml file from any hierarchical or graph source and view the .dgml file in Visual Studio.</p>
<h2 id="and">And…</h2>
<p>There are so many other cool free graphics tools I’ve used over the years, I can’t even remember half of them. Also check out Gimp and Inkscape…</p>
Jekyll and Poole2015-02-16T00:00:00+00:00http://codeblast.com/2015/02/16/jekyll-poole<p>OK let’s do this. After talking about this for ages, it’s time to switch my blog to GitHub Pages. After a quick search I found this <a href="http://joshualande.com/jekyll-github-pages-poole/">nice blogpost</a> that describes how to set up GitHub Pages using <a href="https://github.com/poole/poole">poole</a>.</p>
<p>I’ve tried a few different options for running my blog in the past. Years ago I started with WordPress, then for a short while I tried hosting <a href="http://orchardproject.net/">Orchard CMS</a> myself, then switched to Blogger. But I’ve never felt inspired by their workflows, and those blog sites just feel too heavy-weight for me.</p>
<p>I’m a lazy developer, and the only way I’m going to bother writing blogs, is if I can do it with fairly little friction. I don’t want to log into a website or bother with special blogging software. I’ve been using Markdown and <a href="https://bitbucket.org/">git</a> for writing my personal notes for the last 2 years or so, so I figured it would be a good idea to use Markdown and git for my blog as well.</p>
<p>Some things I want out of the blogging platform:</p>
<ul>
<li>write my blog posts using Markdown – no hassles with CSS and syntax highlighters etc</li>
<li>ability to keep my blog posts, especially drafts, offline so I can work on it whenever a new thought pops in my mind</li>
<li>simple workflow for working on drafts until I’m ready to publish a post</li>
<li>not being tied to a specific blogging platform</li>
<li>being able to easily switch themes or add custom pages etc</li>
</ul>
<p>I’m just starting with Jekyll and GitHub Pages now, but so far it seems like this might just work for me.</p>
<p>FYI, my previous blog is <a href="http://lombard.me">lombard.me</a> – I’m still deciding if it’s worth migrating the posts from Blogger to Jekyll.</p>
Moving my blog from lombard.me2015-02-15T00:00:00+00:00http://codeblast.com/2015/02/15/moved-my-blog<p>Hi There! I’m Gert Lombard, a computer nerd from South Africa now living in the San Francisco Bay Area.</p>
<p>I’ve had several “blogs” over the years since 1998. I’ve tried using Blogger, WordPress, Orchard CMS,
a self-hosted <a href="https://web.archive.org/web/20021129130632/http://codeblast.com/~gert/">website</a> on RedHat linux with static html files (running from my living room), and before that <a href="https://en.wikipedia.org/wiki/Xoom_(web_hosting)">Xoom</a> and
<a href="https://en.wikipedia.org/wiki/Tripod.com">Tripod</a> in the early days. I hosted Radon <a href="http://bbs.hmvh.net/lists/the_list.htm">BBS</a> (with a good friend of mine) way before the Internet even existed commercially in South Africa! :-)</p>
<p>Ever since the BBS days in the early 90’s, I’ve liked the idea of having an online presence. The thing I just haven’t figured out yet, is what exactly the point of this presence is! I think it’s mostly to entertain myself and to collect a few random ideas to refer to later myself. If someone happens to come across a page here and finds it useful, that’s awesome!</p>
<p>This here site is my current web presence. Thank you for looking! <a href="http://twitter.com/codeblast">Let me know</a> if you have feedback, questions or ideas for me.</p>
Recusively change the owner of files (chown) on Mac OS X2014-06-18T10:54:00+00:00http://codeblast.com/2014/06/18/recusively-change-owner-of-files-chownI've just changed my OS X / Mac main user - I've created a new 'coder' user account that I want to use for development instead of my old 'lombard' account. I realized that a lot of my applications I've previously installed via Homebrew now had to be changed to be owned by the new coder user. First I ran 'brew doctor' find see what obvious issues I have: <pre><code>Gerts-Mac-mini:src coder$ brew doctor<br />Warning: /usr/local/etc isn't writable.<br />This can happen if you "sudo make install" software that isn't managed by<br />by Homebrew. If a brew tries to write a file to this directory, the<br />install will fail during the link step.<br /><br />You should probably `chown` /usr/local/etc<br />xcode-select: note: no developer tools were found at '/Applications/Xcode.app', requesting install. Choose an option in the dialog to download the command line developer tools.<br />xcode-select: note: no developer tools were found at '/Applications/Xcode.app', requesting install. Choose an option in the dialog to download the command line developer tools.<br /><br />Warning: You have an outdated version of /usr/bin/install_name_tool installed.<br />This will cause binary package installations to fail.<br />This can happen if you install osx-gcc-installer or RailsInstaller.<br />To restore it, you must reinstall OS X or restore the binary from<br />the OS packages.<br /><br />Warning: Git could not be found in your PATH.<br />Homebrew uses Git for several internal functions, and some formulae use Git<br />checkouts instead of stable tarballs. You may want to install Git:<br /> brew install git<br /><br />Warning: No developer tools installed.<br />Install the Command Line Tools:<br /> xcode-select --install<br />xcode-select: note: no developer tools were found at '/Applications/Xcode.app', requesting install. Choose an option in the dialog to download the command line developer tools.<br /></code></pre> Indeed, several files/directories below '/usr/local' were created by Homebrew as user 'lombard': <pre><code>Gerts-Mac-mini:src coder$ ls -l /usr/local<br />total 80<br />-rw-r--r-- 1 lombard admin 3158 5 Jun 09:16 CODEOFCONDUCT.md<br />-rw-r--r-- 1 lombard admin 687 5 Jun 09:16 CONTRIBUTING.md<br />drwxr-xr-x 4 lombard admin 136 17 Jun 17:11 Cellar<br />-rw-r--r-- 1 lombard admin 1253 5 Jun 09:16 LICENSE.txt<br />drwxr-xr-x 9 lombard admin 306 17 Jun 17:11 Library<br />-rw-r--r-- 1 lombard admin 1858 5 Jun 09:16 README.md<br />-rw-r--r-- 1 lombard admin 23719 5 Jun 09:16 SUPPORTERS.md<br />drwxrwxr-x 12 root admin 408 17 Jun 17:11 bin<br />drwxr-xr-x 3 lombard admin 102 17 Jun 17:11 etc<br />drwxrwxr-x 5 root admin 170 17 Jun 17:11 lib<br />drwxr-xr-x 3 root wheel 102 17 Jun 17:11 libexec<br />drwxrwxr-x 4 root admin 136 17 Jun 17:11 share<br /></code></pre> I can't just use 'chown -R' because I only want to change the owner of some specific files. To recursively fix/change the owner only of files specifically owned by another user, use the versatile 'find' command: <pre><code>$ find . -user lombard -exec sudo ch<br />own coder {} \;<br /></code></pre> Now I just took care of the other things that brew doctor complained about: <pre><code>$ xcode-select --install<br />$ brew update<br /></code></pre> That's it! Now I'm ready to install more tools using Homebrew using the new user account. Another Note To Self: Setting up the Mac Mini2014-04-12T19:14:00+00:00http://codeblast.com/2014/04/12/another-note-to-self-setting-up-mac-mini<b><u>Sublime Text 3:</u></b><br /><b><u><br /></u></b>I'm using Sublime Text as my default editor on Mac and Windows (replaced Notepad++ about a year ago as my favourite editor on Windows). One of the things I like about Sublime is that the plugins are written in Python. I haven't tried creating my own plugin but I am trying to use Python more so this is one more thing to keep in mind.<br /><b><u><br /></u></b><b><u>Git:</u></b><br /><br />This time I'm not going to install the Xcode Command-Line Tools just to get git.<br /><br />Two easy alternatives seem to be:<br />1. Install GitHub for Mac and install the Git command-line from the Preferences menu<br />2. Use Homebrew to install git.<br /><br />I've opted for option 1. This installs the git binary to /usr/local/bin/git. You need to add the /usr/local/bin directory to your path.<br /><br />Next I installed SourceTree.<br /><br /><b><u>Terminal:</u></b><br /><br />I want a dark theme for the OSX Terminal and found: https://github.com/tomislav/osx-terminal.app-colors-solarized<br /><br /><span style="font-family: Courier New, Courier, monospace;">curl -O https://raw.githubusercontent.com/tomislav/osx-terminal.app-colors-solarized/master/Solarized%20Dark.terminal</span><br /><br />In Terminal, import the settings with Command+O and select the Solarized file. This gives me a basic dark theme. Not completely happy with it yet but it's a start.<br /><br />Note to self: Upgrading to OS X Mavericks2014-02-01T18:10:00+00:00http://codeblast.com/2014/02/01/note-to-self-upgrading-to-os-x-mavericksAfter upgrading to OS X 10.9 (Mavericks) I had to do the following to get Android Studio working again:<br /><br /><ul><li>Update Xcode to the latest version</li><li>Activate the Xcode Command Line Tools license for example by running on the shell `sudo gcc` and accept the license. Now git should work.</li><li>Install Java 6 when prompted automatically after trying to launch Android Studio.</li><li>Need to update VirtualBox for <a href="http://www.genymotion.com/">Genymotion</a> to work. Use `Oracle VM VirtualBox Manager` to download the latest VirtualBox.</li></ul>I need a quiet office2014-01-23T11:25:00+00:00http://codeblast.com/2014/01/23/i-need-quiet-officeI really struggle to concentrate / focus (i.e. to "get into the zone") when trying to develop or read something technical while people are talking around me in the office. Perhaps the open plan layout works for some people, but I find it very distracting. (And I'm very guilty myself of causing distraction for others as well!)<br /><br />I think ideally some of the office space should be divided into a few smaller work areas to be used by small teams that prefer to have privacy. For example, I'm currently working with a small team (3-5 developers) and we occasionally need to communicate with a remote office via Skype and a webcam. Ideally we shouldn't have to go to a meeting room every time we want to have a chat with the remote team members.<br /><br />At a very least, I wish we had several small 1-person private guest offices for us to use when we need privacy. That way I can keep my desk in the open office, but get away for 3-4 hours a day for productive work.<br /><br />The only way I can fight the distraction, is to listen to music while I work. But this only works for certain type of tasks (like unit testing). When I really need to focus (like learning/reading or designing/writing code), I want no distractions. A single sentence on the other side of the office can bring me out of the "zone".<br /><br />If you Google search for "open plan office productivity" you'll immediately see lots of evidence that Open Plan doesn't work for everyone. (It seems like younger people like open offices more, presumably because it feels more social).<br /><br />From http://en.wikipedia.org/wiki/Open_plan:<br /><blockquote><i>A systematic survey of research upon the effects of open plan offices found frequent negative effects in some traditional workplaces: high levels of noise, stress, conflict, high blood pressure and a high staff turnover.[7] The noise level greatly reduces the productivity, which drops to one third relative to what it would be in quiet rooms ... </i><i>A balance between the office types may be found by employees having an open setting with part-time access to a quiet workspace.</i></blockquote>Or from http://www.newyorker.com/online/blogs/currency/2014/01/the-open-office-trap.html<br /><blockquote><i>a growing body of evidence suggests that the open office undermines the very things that it was designed to achieve.</i> <i>... </i><i>In laboratory settings, noise has been repeatedly tied to reduced cognitive performance.</i></blockquote>More links:<br /><ul><li><a href="http://www.huffingtonpost.com/2013/08/24/open-plan-office-study_n_3810538.html">Open-Plan Offices Detrimental To Worker Productivity, Study Finds</a></li><li><a href="http://www.businessweek.com/articles/2013-10-10/why-we-cant-get-anything-done-in-an-open-plan-office">Why We Can't Get Anything Done in an Open-Plan Office</a></li><li><a href="http://www.fastcompany.com/3019758/dialed/offices-for-all-why-open-office-layouts-are-bad-for-employees-bosses-and-productivity">WHY OPEN-OFFICE LAYOUTS ARE BAD FOR EMPLOYEES, BOSSES, AND PRODUCTIVITY</a></li></ul><br /><br />How to flash Samsung Galaxy Nexus with the latest factory image2013-12-15T22:21:00+00:00http://codeblast.com/2013/12/15/how-to-flash-samsung-galaxy-nexus-with-factory-imageI was running <a href="http://www.cyanogenmod.org/">CyanogenMod</a> on a Google/Samsung Nexus Galaxy and decided to go back to the stock Google image from the <a href="https://developers.google.com/android/nexus/images#takjujwr66y">Factory Images for Nexus Devices</a> page. The latest factory image for the Galaxy Nexus is 4.3 (JWR66Y).<br /><br />Make sure to download the correct image for your Nexus phone. In my case it's "yakju" for the Galaxy Nexus "maguro" (<a href="https://dl.google.com/dl/android/aosp/yakju-jwr66y-factory-09207065.tgz">yakju-jwr66y-factory-09207065.tgz</a>).<br /><div><br /></div><div>I downloaded the yakju archive and extracted the .tgz with <a href="http://chocolatey.org/packages/7zip.commandline">7za</a>:</div><div><br /></div><div><div><span style="font-family: Courier New, Courier, monospace;">cd \temp</span></div><div><span style="font-family: Courier New, Courier, monospace;">curl -k -O https://dl.google.com/dl/android/aosp/yakju-jwr66y-factory-09207065.tgz</span></div><div><span style="font-family: Courier New, Courier, monospace;">7za x yakju-jwr66y-factory-09207065.tgz</span></div><div><span style="font-family: Courier New, Courier, monospace;">7za x yakju-jwr66y-factory-09207065.tar</span></div><div><span style="font-family: Courier New, Courier, monospace;">cd yakju-jwr66y</span></div></div><div><br /></div>I wanted to see if I had the Samsung driver installed on my Windows 8.1 laptop: Go to Device Manager:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-Q88YIWM6ijc/Uq4iy-GPtpI/AAAAAAAAD9I/FLdHTAT6shg/s1600/01-without-samsung-driver.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="465" src="http://2.bp.blogspot.com/-Q88YIWM6ijc/Uq4iy-GPtpI/AAAAAAAAD9I/FLdHTAT6shg/s640/01-without-samsung-driver.png" width="640" /></a></div><br />So, no clearly I didn't have the driver for the phone yet: Device Manager shows the Nexus phone as "Unknown USB Device (Device Descriptor Request Failed)".<br /><br />At this point, I decided to put the phone into fastboot anyway and see if I could flash the factory image without the Samsung driver (hint: no, it didn't work):<br /><div><br /></div><div>To use adb.exe and fastboot.exe, I just used the Android SDK in my <a href="http://developer.android.com/sdk/installing/studio.html">Android Studio</a> installation. I added the <span style="font-family: Courier New, Courier, monospace;">sdk/platform-tools folder</span> to my PATH and put the device into fastboot mode:</div><div><br /></div><div><div><span style="font-family: Courier New, Courier, monospace;">set PATH=%PATH%;D:\Android\android-studio\sdk\platform-tools</span></div><div><span style="font-family: Courier New, Courier, monospace;">adb reboot bootloader</span></div></div><div><br /></div><div>Now the phone is in fastboot mode (while in "fastboot mode" you can "flash" the Android firmware, i.e. modify the system image / operating system):</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-IS76Cd8HbFY/Uq4mdry690I/AAAAAAAAD9U/NiGtbSgsLXA/s1600/02-fastboot-mode.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="http://1.bp.blogspot.com/-IS76Cd8HbFY/Uq4mdry690I/AAAAAAAAD9U/NiGtbSgsLXA/s400/02-fastboot-mode.jpg" width="276" /></a></div><div><br /></div><div>However, as I feared, fastboot.exe couldn't see the phone, because the Samsung driver wasn't installed, i.e. when I ran "<span style="font-family: Courier New, Courier, monospace;">fastboot devices</span>" no devices were listed. While in fastboot mode, Device Manager now shows the phone as "Other Devices" -> "Android 1.0":</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-ZAglbbDcRWc/Uq4nOgpyDAI/AAAAAAAAD9c/QNfZ2qFPHjQ/s1600/03-device-manager-shows-android-1.0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="620" src="http://1.bp.blogspot.com/-ZAglbbDcRWc/Uq4nOgpyDAI/AAAAAAAAD9c/QNfZ2qFPHjQ/s640/03-device-manager-shows-android-1.0.png" width="640" /></a></div><div><br /></div><div><div>I downloaded Samsung_USB_Driver_for_Mobile_Phones_v1.5.14.0.exe from Samsung's website. </div></div><div><br /></div><div>During the process of installing the Samsung USB driver I had to reboot my Windows 8.1 a few times (and I also had to take the battery out of the phone once to get it out of fastboot mode because the phone seemed to hang).</div><div><br /></div><div>I right-clicked on the "Android 1.0" device and clicked "Update Driver Software...". Then I selected "Let me pick from a list of device drivers on my computer" and then selected the "SAMSUNG Android Phone" from the list:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-sT2uwjEde3I/Uq4poH8SHXI/AAAAAAAAD9o/WIVCiXjlLTM/s1600/04-pick-samsung.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="474" src="http://3.bp.blogspot.com/-sT2uwjEde3I/Uq4poH8SHXI/AAAAAAAAD9o/WIVCiXjlLTM/s640/04-pick-samsung.png" width="640" /></a></div><div><br /></div><div>And on the next screen I selected "SAMSUNG Electronics Co., Ltd." -> "<b>SAMSUNG Android ADB Interface</b>":</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-mCBAueFQOBQ/Uq4qGYQMacI/AAAAAAAAD9w/VNH5BdB1tDA/s1600/05-select-samsung-adb-interface.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="474" src="http://2.bp.blogspot.com/-mCBAueFQOBQ/Uq4qGYQMacI/AAAAAAAAD9w/VNH5BdB1tDA/s640/05-select-samsung-adb-interface.png" width="640" /></a></div><div><br /></div><div>Windows confirms that the Samsung driver is installed OK:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-bIT7Fc3qKjU/Uq4qgDNgxnI/AAAAAAAAD94/DJ0gkVFos7Q/s1600/06-samsung-drived-installed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="474" src="http://2.bp.blogspot.com/-bIT7Fc3qKjU/Uq4qgDNgxnI/AAAAAAAAD94/DJ0gkVFos7Q/s640/06-samsung-drived-installed.png" width="640" /></a></div><div><br /></div><div>After updating the "Android 1.0" device's driver to "Samsung Android ADB Interface", Fastboot now shows the device:</div><div><br /></div><div><div><span style="font-family: Courier New, Courier, monospace;">C:\temp\yakju-jwr66y> fastboot devices</span></div><div><span style="font-family: Courier New, Courier, monospace;">0356B9BB0201A005 fastboot</span></div></div><div><br /></div><div><div>Now run <span style="font-family: Courier New, Courier, monospace;">flash-all.bat</span> from the downloaded factory image folder. That's it! That batch file runs fastboot.exe a few times to install the new factory image. Now Android 4.3 is installed successfully on the Nexus phone.</div></div><div><br /></div>Keep it simple2013-12-09T08:17:00+00:00http://codeblast.com/2013/12/09/keep-it-simpleI was browsing around on the <a href="http://quantifiedself.com/2012/01/quantified-self-101-keep-it-simple/">Quantified Self</a> website and saw these nice easy tips / lessons learned on QS, but clearly these are 100% applicable to software development (and practically any aspect of life). They are pretty obvious points, but worth reminding yourself of now and then, especially when you're as easily distracted as I am :-)<br /><ol><li>Something is better than nothing. Engaging yourself in some experiment, no matter how flawed it may be, is better than never starting. The best way to learn is to do. So go out and do something!<br /></li><li>When you decide to start something try and do the simplest thing that you think might give you some insight. It’s great to have ambitious ideas, but keeping it simple ensures your experiment is manageable.<br /></li><li>Mistakes are worthwhile. Some of our best knowledge comes from learning from our failures so don’t be afraid of failing. By keeping it simple you also keep the mistakes small and manageable.<br /></li><li>Seek help from others.</li></ol><div><br /></div>Ireland English dictionary for the non-Irish2013-11-25T20:56:00+00:00http://codeblast.com/2013/11/25/ireland-english-dictionary-for-non-irish<div>Random musings on living in Ireland:</div><div><br /></div>As a South-African who's been living in Ireland for over 4 years, let me show you some of the Irish lingo (I think) I've learned so far. Please feel free to add/correct as necessary.<br /><br />First the Irish-English phrase and then the "international" English phrase would be understood by South-Africans and Americans alike (I would hope).<br /><ul><li>It's <i>half eight</i> = It's half past eight.</li><ul><li>This one I especially used to find confusing because in <a href="http://en.wikipedia.org/wiki/Afrikaans">Afrikaans</a> the direct translation "<i>half agt</i>" actually means the equivalent of "half <i>to</i> eight" i.e. "half past seven".</li></ul><li>What's the craic? = Hey, what's up?</li><li>What's the craic and all? = Hey, what's up? (as said by an Indian living in Ireland - hi Ramesh :-)</li><li>Just <i>call in</i> to pick it up. = Just come in and pick it up. (I <i>still keep</i> falling for this one and actually <i>CALL </i>people on the phone, only to discover I didn't have to <i>call</i> but only have to <i>call in</i>, duh!)</li><li>evening = afternoon</li><ul><li>example: Yesterday evening I worked on...</li><li>translation: Yesterday afternoon I worked on...</li></ul><li>Did you enjoy that <i>dinner</i>? = Did you enjoy that <i>lunch</i>? (I think 'supper' is reserved for 'dinner'..?)</li><li>Do you want to come over for <i>tea</i>? = Do you want to come over for <i>dinner</i>? (Not sure about this one...?)</li><li>Runners = tekkies (South-African), sneakers (American)</li><li>Pants = underwear / underpants</li><li>Cheers! = Thanks! (<i>Not</i> 'bye'!)</li><li>So I told yer man = So I told the guy</li><li>Jumper = Jersey</li><li>Are you <i>dosed</i>? = Do you have the <i>flu</i>?</li><li>I'm <i>wile</i> dosed = I'm <i>very </i>sick</li><li>Bap = bun (bread)</li><li>At the <i>minute</i> = At the <i>moment</i></li></ul><div>I admit that some of these might not necessarily be purely Irish words/phrases but may be influenced by British-English, which is possibly slightly closer to South-African English, but not quite. I'd say South-African English is, when spoken, perhaps the closest to US-English (but closer in spelling to UK-English).<br /><br />Also, just a silly story to add:<br /><br />I've been in love with Ireland my whole life, so on previous occasions (before moving to Ireland) I've bought some Irish wool caps and a very nice (and expensive I want to add) jersey. Then we moved to Ireland in 2009. I got a little book about Ireland and Irish culture. In this book I learned about the concept "More Irish than the Irish"... I realised that if I wore my Irish-made wool cap, which I bought in the same county that I live in now, but years ago (around 2000 or so), then I'll just seem like an idiot tourirst who's trying to look Irish. For the same reason I'm reluctant to wear any Irish-branded stuff (like a nice Ireland t-shirt I also bought years ago) for the fear of looking like a silly foreigner trying to look Irish :-)<br /><br />I must admit, occasionally when I visit a neighbouring town in Donegal, and a shop-keeper doesn't understand my weird accent, it is convenient to pretend that I'm just visiting from SA. It does get weird when you keep pretending to be a visitor from SA every time you visit the same store though (like that from the lovely Mr. McGinty's in Donegal Town - hi Mr. McGinty, I love your shop, but I've bought lots of stuff from your shop over the years and I expect a discount next time... haha ;.)<br /><br />Sometimes when people in Letterkenny don't understand this crazy unfamiliar accent, they assume that I'm Polish. Not sure why. In the US people thought I'm either Scottish or Australian...?<br /><br /></div><div>I hope this post doesn't cause any offense to the occasional Irish or Western-European visitor :-)</div>The correct way to read a text file in Python2013-11-22T10:02:00+00:00http://codeblast.com/2013/11/22/the-correct-way-to-read-text-file-inWhen you search for examples of reading a file on the web, most examples you see show: <br /><br /><pre><code>with open('file') as f:<br /> text = f.read()<br /></code></pre><br />But it's quite hard to find examples of the "correct" or "proper" way to read text files in Python. Of course correct/proper is a matter of opinion and depends on what you're trying to accomplish. In many cases you really want to slurp the full file into memory as above, but in my case I more often need to process one line at a time (perhaps in conjunction with a generator), in which case this is what I need: <br /><br /><pre><code>with open('file') as f:<br /> for line in f:<br /> yield line<br /></code></pre><br />Not to mention that you'd deal with binary files in a different way as well...Automated install of PowerShell on Windows XP2013-11-08T16:14:00+00:00http://codeblast.com/2013/11/08/automated-install-of-powershell-on-xp<b>The problem:</b> I want a batch script to perform an unattended/silent install of PowerShell on Windows XP.<br /><div><br /></div><div>We need to download the PowerShell installer from Microsoft, but it needs to be downloaded from an HTTP server. I'm not aware of an easy way to download files from the command-line or script in Windows XP, other than the FTP command. But what we can do easily, is to download cURL via FTP first.</div><div><br /></div><div>So we need to download 4 things from the batch script:</div><div><ol><li>We need to get 7-Zip to extract cURL.</li><li>We need to get cURL (or wget) to download PowerShell.</li><li>Download and install .NET Framework 2 since it's required by PowerShell.</li><li>Finally we download PowerShell itself from Microsoft via HTTP.</li></ol><div><b>Step 1:</b> download 7-Zip archiver's command-line version (7za.exe) from an FTP server. You need to search for any FTP server that hosts 7za.exe.</div><div><br /></div><div>This FTP script would work to get 7za:</div><pre><code>open ftp.cadwork.ch<br />user<br />anonymous<br /><br />cd /DVD_V17/CADWORK.DIR/COM/<br />bin<br />get 7za.exe<br /></code></pre><div><b>Step 2:</b> download curl from one of the official FTP mirrors if you can. I didn't have any luck with the official mirrors so I just searched around until I found an older version.<br /><br />This FTP script would work to get curl 7.19.3: </div><pre><code>open ftp.gr.freebsd.org<br />user<br />anonymous<br /><br />cd /pub/net/ftp/curl/<br />bin<br />get curl-7.19.3-win32-nossl.zip<br /></code></pre><div>Now we can use 7za.exe to extract the curl zip file.<br /><br /><b>Step 3:</b> download <a href="http://www.microsoft.com/en-ie/download/details.aspx?id=1639">.NET Framework 2.0</a> and install it silently:<br /><pre><code>curl -O http://download.microsoft.com/download/c/6/e/c6e88215-0178-4c6c-b5f3-158ff77b1f38/NetFx20SP2_x86.exe<br /></code></pre><pre><code>start /wait "Installing .NET" NetFx20SP2_x86.exe /qb</code></pre></div><div><b>Step 4:</b> download <a href="http://www.microsoft.com/en-us/download/details.aspx?id=16818">PowerShell for Winfows XP</a> and install it silently:<br /><pre><code>curl -O http://download.microsoft.com/download/E/C/E/ECE99583-2003-455D-B681-68DB610B44A4/WindowsXP-KB968930-x86-ENG.exe<br />start /wait "Installing PowerShell" WindowsXP-KB968930-x86-ENG.exe /passive /log:powershell-install.log<br /></code></pre>The final batch file to put it all together is <a href="https://github.com/glombard/Scripts/blob/master/PowerShell-Installers/Get-PowerShell-WinXP.bat">here</a>.<br /><br />If you're curious why I'd be using Windows XP: I sometimes need to test old software. In this case, I want to install Visual C++ 6 to see if some old C++ code compiles without warnings before I start the process of converting it to a newer Visual Studio.</div><div><br /></div><div>Note: I used <a href="http://www.filewatcher.com/_/?q=7za.exe&p=1">FileWatcher.com</a> to search for FTP servers that host the 7-Zip command-line tool (7za.exe) and cURL.<br /><br /></div></div>Automating software installs2013-10-29T09:57:00+00:00http://codeblast.com/2013/10/29/automating-software-installsThis is my favourite software development topic: automating installs.<br /><br />I'm a lazy programmer, in the sense that Larry Wall talks about when he says <a href="http://c2.com/cgi/wiki?LazinessImpatienceHubris">laziness is one the three great virtues</a> of a programmer: that means I hate doing things manually over and over again. I'd rather spend an hour writing a script to download and install a utility, then doing it manually many times on multiple machines. Automating the installation of tools also has some other benefits: (a) it ensures the consistent replication of environments and (b) it serves as documentation of exactly what was done for future reference.<br /><br />Nowadays I make a lot of use of virtual machines (mostly using Hyper-V recently) for my development on Windows. This allows me to easily delete VMs and start over as often as I like. It also means I can keep my development environments separate: e.g. one VM for Java/Eclipse, one for an older version of Visual Studio, one for playing with Ubuntu, etc.<br /><br />When you install a lot of development environments over and over, you need to be aware of the different tools available to help automate things. In the Linux world, automated/unattended installs are the norm (using things like apt-get), but in Windows it takes a bit more effort to automate the installation of applications.<br /><br />Here's a few ideas for installing utilities/tools from the command-line (i.e. from scripts):<br /><ul><li><a href="http://chocolatey.org/">Chocolatey </a>- very cool tool to install lots of popular applications with a simple command like: <span style="font-family: Courier New, Courier, monospace;">cinst notepadplusplus</span></li><li><a href="http://ninite.com/">Ninite</a> - Pick the applications you want to install and it generates a single installer to package them all.</li><li><a href="http://technet.microsoft.com/en-us/library/dd744566(v=ws.10).aspx">DISM.exe</a> - a Windows tool to Enable/Disable Windows Features from the command-line. Use this to enable things like IIS or Hyper-V from a script.</li><li><a href="http://msdn.microsoft.com/en-us/library/windowsazure/gg433092.aspx">WebPICmd.exe</a> - <a href="http://www.microsoft.com/web/downloads/platform.aspx">Microsoft Web Platform Installer</a> - install certain products like SQL Server Express from the command-line.</li><li>In some cases it's easy enough to just write your own customer silent installer for a product. A lot of applications use InstallShield or other well-known installers and a lot of them behave the same way, so it's usually possible to figure out which command-line parameters to pass to the installer to do an unattend/silent install.</li></ul>In addition to the above tools, you obviously need to be comfortable writing scripts of some sort. In the old days, I used to use Perl for all of my scripting needs. In recent years I've done more plain Batch files and some PowerShell. PowerShell is great because it's so ubiquitous on Windows systems, but it does have a steep learning curve in my opinion. I'm currently trying Python as my primary scripting language instead of plain old Batch files.<br /><br /><b>Using Chocolatey:</b><br /><br />As an example of using Chocolatey on Windows, let's install the first two tools every developer needs on their machine: <a href="http://curl.haxx.se/docs/manpage.html">cURL</a> and the <a href="http://www.7-zip.org/">7-Zip</a> Command Line tool for extracting archives from the command-line:<br /><br />First, install Chocolatey itself (requires .NET Framework 4.0 to be installed) and then we use cinst to install curl and 7za:<br /><pre><code>C:\> powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%systemdrive%\chocolatey\bin<br />C:\><br />C:\> cinst 7zip.commandline<br />C:\> cinst curl<br /></code></pre>And that's it!<br /><br /> <b>Using Web Platform Installer (webpicmd):</b><br /><br />Let's install webpicmd with Chocolatey and then we'll install IIS Express using webpicmd: <pre><code>C:\> cinst webpicmd<br /></code></pre>Now list all packages matching "IIS": <pre><code>C:\> webpicmd /List /ListOption:Available | findstr "IIS"<br /></code></pre>From the above we see that we're looking for the package called just "IISExpress", so install it: <pre><code>C:\> webpicmd /Install /Products:IISExpress /AcceptEula<br /></code></pre> <b>Using PowerShell to install utilities:</b><br /><br />Now, for contrast, let's say you've got a clean Windows 7 machine and Chocolatey won't work yet (because the .NET framework ins't installed), then it's easy enough to roll your own automated installs of 7-Zip and cURL using PowerShell. Once we have 7za and curl, this bootstraps everything: next we can easily script the download and install .NET Framework and Chocolatey...<br /><br />To download 7-Zip command-line version (7za) and extract it using PowerShell:<br /><pre><code>function Unzip-File<br />{<br /> param ([string]$zipFile, [string]$destFolder)<br /> New-Item -ItemType Directory -Force -Path $destFolder<br /> $shell = New-Object -Com Shell.Application<br /> $zip = $shell.NameSpace($zipFile)<br /> $shell.NameSpace($destFolder).CopyHere($zip.Items(), 16)<br />}<br /><br />Write-Host "Installing 7-Zip Command Line (7za)..."<br />$dest = "$env:ProgramFiles\7-Zip"<br />$destFile = "$env:ProgramFiles\7-Zip\7za.exe"<br />if (!(Test-Path $destFile))<br />{<br /> Write-Host "Downloading 7za..."<br /> $wc = New-Object Net.WebClient<br /> $url = 'http://downloads.sourceforge.net/sevenzip/7za920.zip'<br /> $file = "$env:TEMP\7za920.zip"<br /> $wc.DownloadFile($url,$file)<br /> Write-Host "Unzipping to: $dest"<br /> Unzip-File $file $dest<br /> Remove-Item $file<br />}<br />else<br />{<br /> Write-Host "7za already installed."<br />}<br /></code></pre>Next, let's download cURL and copy it into the Windows directory (because it's a single file and then it's already in the PATH for easy use):<br /><pre><code>function Unzip-File<br />{<br /> param ([string]$zipFile, [string]$destFolder)<br /> <br /> $7z = "$env:ProgramFiles\7-Zip\7za.exe"<br /> if (Test-Path $7z)<br /> {<br /> $info = New-Object Diagnostics.ProcessStartInfo<br /> $info.FileName = $7z<br /> $info.Arguments = "x -y -o""$destFolder"" ""$zipFile"""<br /> $info.Verb = "runas"<br /> $proc = [Diagnostics.Process]::Start($info)<br /> $proc.WaitForExit()<br /> }<br /> else<br /> {<br /> $shell = New-Object -Com Shell.Application<br /> $zip = $shell.NameSpace($zipFile)<br /> $shell.NameSpace($destFolder).CopyHere($zip.Items(), 16)<br /> }<br />}<br /><br />Write-Host "Installing cURL..."<br />$wc = New-Object Net.WebClient<br />$url = "http://www.paehl.com/open_source/?download=curl_732_0_ssl.zip"<br />$file = "$env:TEMP\curl.zip"<br />$wc.DownloadFile($url,$file)<br />Write-Host "Unzipping to: $env:windir"<br />Unzip-File $file $env:windir<br />Remove-Item $file<br /></code></pre>Now download the .NET Framework 4.5.1 using cURL (of course you can download it with PowerShell as well, but I like to use cURL):<br /><pre><code>C:\temp> curl -L http://go.microsoft.com/fwlink/?LinkId=322116 -o c:\temp\NDP451-KB2858728-x86-x64-AllOS-ENU.exe<br />C:\temp> NDP451-KB2858728-x86-x64-AllOS-ENU /q<br /></code></pre>Resources:<br /><ul><li><a href="http://unattended.sourceforge.net/installers.php">Instructions for how to silently install MSI and InstallShield installers</a></li><li><a href="http://wpkg.org/Category:Silent_Installers">WPKG Silent Installers List</a> - lots of examples of the silent install parameters for lots of popular applications.</li></ul>Parenting: guilt when your child follows in your footsteps2013-10-23T20:12:00+00:00http://codeblast.com/2013/10/23/parenting-guilt-when-your-child-follows-in-your-footstepsTonight my daughter, Emily (5 in a few months) called me and told me she can't sleep because she can't stop thinking about something even when she tries to think about something else. She asked: "Pappa, how can you stop your brain from thinking about something?" I replied: "It's very difficult to stop your brain from thinking! I know what you mean. I also find it difficult to stop thinking about things sometimes." <br /><br />I was a bit scared to ask what it was that she was trying <i>not</i> to think about. <br /><br />So tried to explain to her a technique I've been using for many years to fall asleep. I do it almost every night. I think I may have read about it (at least in some form or another) from a book about lucid dreaming by Stephen LaBerge when I was probably around 16 years old. It works almost every time, except when I'm really struggling to sleep, such as when I wake up in the middle of the night and start worrying about random stuff (in that kind of situation the only way to get rid of the anxiety is to get out of bed and watch tv or read for a while until I feel really tired). The idea is to think about (focus on) one part of my body at a time, making sure my body is totally relaxed. I start focusing on my left foot: is my foot totally relaxed? OK, move on: is my left leg totally relaxed and flat on the bed? Next leg. Then my lower body. Etc. <br /><br />Emily seemed unsure whether she'd be able to do that, but she said she'd try. <br /><br />Then I dared to ask: "What is it that you're trying not to think about?"<br /><br />And it was what I thought it might be. She suddenly visibly tried not to cry and said: "I think about how I'm playing outside the classroom by myself. And then I look around and there is no one to play with." <br /><br />My heart sank, because my wife and I have been talking about exactly this every day for the last few days. My wife recently discovered that our daughter is not as popular at school as we had assumed for some reason: my wife went with Emily to a classmate's birthday party a few days ago and realized that all the other kids were playing together and apparently didn't even seem to know Emily. I kept telling my wife she was worried about it for no reason, because as long as Emily doesn't see it as a problem, then there is no problem, because she's still young and lots of time to make friends. <br /><br />However, the problem is: Emily has obviously been noticing that she hasn't got friends at school and it clearly bothers her a lot.<br /><br />I told Emily: "Don't worry, once other kids get to know you, you'll make friends." She said: "The other kids <i>do</i> know me." I said: "OK, I'll tell you a trick: look for another kid who is also playing by themselves, even if it's a boy, then go to them and ask if you can play with them. Ask them lots of questions, like what games they like to play, what shows they like to watch, what food they like, and then see if they want to play with you. If not, don't worry, just keep doing that. And one day, you'll have lots of friends!"<br /><br />The topic has been so active on my mind that just this morning I asked my son's (3) teacher Patricia, when dropping him off at preschool, if he's making friends. She said he's making lots of friends, and he's one of a band of about 5 boys who are apparently always playing together. So at least he's doing well socially.<br /><div><br /></div>The reason this has been a fear for us: my wife and I haven't really been the best examples. Not to mention whatever influence our introverted genes might have had on the kids. And living in a new country where we have no friends or family certainly doesn't help either.<br /><br />In my childhood days I never had any friends at school until I was 13. It never bothered me the least bit. I liked being by myself. But it is really sad when the story seems to repeat itself with Emily, and I have no idea what we as the parents can do about it.Do not design for reuse - design for loose coupling2013-10-21T15:48:00+00:00http://codeblast.com/2013/10/21/do-not-design-for-reuse-design-forI came across this cool line today:<br /><blockquote><span style="-webkit-text-stroke-width: 0px; background-color: white; color: black; display: inline !important; float: none; font-size-adjust: none; font-stretch: normal; font: 26px/36px "Open Sans", Arial, sans-serif; letter-spacing: -1px; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">"It can be better to copy a little code than to pull in a big library for one function."</span>-- <a href="http://talks.golang.org/2012/splash.slide#1">Go at Google</a> by Rob Pike</blockquote>Nowadays we keep hearing about all the virtues of code reuse, so much that it's almost becoming unheard of to question it. People may look at you funny when you suggest that some DTO class should be a separate class even though it happens to contain all the same properties as an existing model class.<br /><br />It can be difficult to determine where to draw the line, but remember: just because two classes happen to look the same doesn't mean that it is necessarily the same thing. Sometimes copying & pasting is better than reuse e.g. using inheritance.<br /><br />Reuse means coupling (or a dependency) when there is no need for that dependency.<br /><br />I've always like this <a href="http://sonjayatandon.com/04-2006/ooad-101-lesson-2-coupling-and-cohesion-trump-reuse-and-inheritance/">OOAD 101 blog post</a> about coupling and cohesion:<br /><blockquote>"DO NOT design for reuse. Design for loose coupling, high cohesion. Do that and reuse will happen on its own."</blockquote> Also see: <a href="https://bbs.archlinux.org/viewtopic.php?id=75960">Is code reuse a lie?</a>Mac OSX Keyboard Shortcuts2013-10-16T21:48:00+00:00http://codeblast.com/2013/10/16/mac-osx-keyboard-shortcutsIf you're a Windows user and new to Mac OSX, like me, here are some useful keyboard shortcuts and other tips:<br /><br /><table style="border-collapse: separate; border-spacing: 15px 0px;"><thead style="font-weight: bold;"><tr><td>Key</td><td>Action </td></tr></thead><tbody><tr><td><b>⌘</b>+<b>space</b></td><td>Quick search for an app or file to open</td></tr><tr><td><b>⌘</b>+<b>tab</b></td><td>'Alt Tab' to another application</td></tr><tr><td><b>⌘</b>+<b>`</b></td><td>To 'Alt Tab' between windows of the same app (e.g. another Chrome window)</td></tr><tr><td><b>⌘</b>+<b>control</b>+<b>shift</b>+<b>4</b></td><td>Select an area and take screenshot to clipboard</td></tr><tr></tr><tr><td><b>⌘</b>+<b>shift</b>+<b>4</b> then <b>space</b></td><td>Click on a window to save that window to a file on the Desktop</td></tr><tr><td><b>⌘+option+esc</b></td><td>Force quit applications</td></tr></tbody></table><br />If you're using <b>Remote Desktop Connection</b> to connect to a remote Windows machine:<br /><br /><table style="border-collapse: separate; border-spacing: 15px 0px;"><thead style="font-weight: bold;"><tr><td>Key</td><td>Action </td></tr></thead><tbody><tr><td><b>⌘</b>+<b>`</b></td><td>To 'Alt Tab' between windows within the same app e.g. to another dialog window</td></tr><tr><td><b>fn</b>+<b>option</b>+<b>F1</b></td><td>Windows key (Start menu)</td></tr><tr><td><b>fn</b>+<b>option</b>+<b>F1</b>+<b>R</b></td><td>Run dialog</td></tr></tbody></table><br />You can configure your keyboard shortcuts in the Preferences of the Remote Desktop Connection application: <br /><a href="http://2.bp.blogspot.com/--sCSJbNak8M/Ul8L3ySFlQI/AAAAAAAADGI/20fii9KGAYY/s1600/Screen+Shot+2013-10-16+at+2.26.22+PM.png" imageanchor="1"><img border="0" src="http://2.bp.blogspot.com/--sCSJbNak8M/Ul8L3ySFlQI/AAAAAAAADGI/20fii9KGAYY/s320/Screen+Shot+2013-10-16+at+2.26.22+PM.png" /></a><br />Also see: <br /><ul><li><a href="http://www.danrodney.com/mac/">Dan Rodney's List of Mac OSX Keyboard Shortcuts</a></li><li><a href="http://guides.macrumors.com/Taking_Screenshots_in_Mac_OS_X">See here for more</a> screenshot keyboard shortcuts</li></ul>Free private Git repository on TFS2013-10-15T04:20:00+00:00http://codeblast.com/2013/10/15/free-private-git-repository-on-tfsYou know GitHub of course, but it's not free for private repositories. Another nice option is <a href="https://bitbucket.org/">BitBucket</a> by Atlassian, which supports Git and Mercurial.<br /><div><br /></div><div>In this quick post I'm going to show you an option you may like especially if you're doing work in Visual Studio (like .NET/C#). Not many people seem to know that Microsoft has a free Git hosting option called <a href="http://tfs.visualstudio.com/">Team Foundation Service</a>. This is basically a free online/hosted version of the TFS that we all know and love. (A bit of sarcasm there. Maybe.) The online TFS supports up to 5 users in your project for free.</div><div><br /></div><div>Go to tfs.visualstudio.com, log in with your "Live ID" (like Hotmail/MSN/Outlook email address), and choose your own subdomain under .visualstudio.com. Create your new Git repository, 'test' in the example below.</div><div><br /></div><div><div>When you're just starting with your new repository, initialize the new repo:</div><div></div><div><pre><code>git init</code></pre></div><div></div><div>Let's create our first file in the new repo:</div><div></div><div><pre><code>echo '# Welcome!' > README.md</code></pre></div><div></div><div>Now see what's going on in our repo:</div><div></div><div><pre><code>git status</code></pre></div><div></div><div>This shows us that we have the new README.md file as an "untracked file". Let's add the new file:</div><div></div><div><pre><code>git add .</code></pre></div><div></div><div>If you want, do a <code>git status</code> again, and note that the file is now added and new. </div><div></div><div>Next, commit the change:</div><div></div><div><pre><code>git commit -m "Initial commit"</code></pre></div><div></div><div>Add the remote server called 'origin':</div><div></div><div><pre><code>git remote add origin https://myname.visualstudio.com/DefaultCollection/_git/test</code></pre></div><div></div><div>Now upload your newly created repository:</div><div></div><div><pre><code>git push -u origin --all</code></pre></div><div>(Note that your username and email address defined in your global git config is what will be displayed when you commit changes to this Git repo. This may perhaps be different from your TFS login, which is not necessarily what you want. So just make sure to check your config if you're using multiple Git accounts.)<br /><br />Now add your friends to your private repo, and then they can clone the repository:<br /><pre><code>git clone https://myname.visualstudio.com/DefaultCollection/_git/test</code></pre></div><div>Also see:</div><div><br /></div><div>* <a href="http://www.sourcetreeapp.com/">SourceTree</a> (Very good GUI for Git by Atlassian)</div><div>* <a href="http://windows.github.com/">GitHub for Windows client</a> (also useful to get the PoshGit shell which is nice for command-line work)</div><div>* To create a new Git repository from Visual Studio, see: <a href="http://tfs.visualstudio.com/en-us/learn/publish-new-team-project-vs-git">Publish your code into Team Foundation Service</a></div><div><br /></div></div>Good development team practices2013-10-02T15:44:00+00:00http://codeblast.com/2013/10/02/good-development-team-practicesSome good software development practices:<br /><br /><b>Automate everything.</b><br /><br />It often takes much longer to automate a small task than just doing it manually. I don't know about you, but I hate doing the same mundane task over and over. I admit, it's sometimes possible to take it too far as well. Yesterday I easily spent at least 30 minutes creating a single line <a href="http://curl.haxx.se/">cURL</a> command for downloading JDK 1.4 from the Oracle Archive Download site.<br /><br />Automation also serves as documentation. When you write the steps for installing some utility in a script, then you don't need to explain to another developer later what needs to be installed. Just read the script to see what's needed.<br /><br />Remember that there are lots of existing tools to help automating things, like <a href="http://nuget.org/">NuGet</a> and <a href="http://chocolatey.org/">Chocolatey</a>.<br /><br />Consider choosing a standard scripting tool like PowerShell or Python for everyone in the team to use. You can do a lot with just plain old batch files too.<br /><br />At a very minimum, please, please don't do your builds manually! For builds/compiling your code, you obviously need to use something Jenkins, TeamCity or TFS. Even in very small teams you should do automated builds / continuous integration.<br /><br /><b>Test everything.</b><br /><br />If you're not already doing some kind of automated tests, you absolutely have to start. There is no excuse. Automated testing is not something you wait for your QA team to do - it's a development task.<br /><br />Unit tests are possible even with legacy code. At least start writing any new code in a testable way and build your tests up over time.<br /><br />Integration tests should be possible for most projects. In .NET with WPF, start using Microsoft's Coded UI tests. It's a very easy way to automate your WPF UI. If you're using ASP.NET, then you'll want to use <a href="http://watin.org/">WatiN</a>.<br /><br />Just don't get too religious about testing and code coverage and forget what you're actually trying to accomplish. Sometimes we spend ages unit testing something of pretty low value, while the actual problem areas aren't covered well. There's no point in having 100% code coverage when you don't have enough tests to prove that you've met the acceptance criteria.<br /><br /><b>Follow good check-in/commit etiquette.</b><br /><br /><a href="http://www.codinghorror.com/blog/2008/08/check-in-early-check-in-often.html">Commit often</a> in small chunks. Pull / Get Latest often. This makes it easier for yourself because you reduce the number of conflicts to deal with.<br /><br />Use good comments for your commit messages, not just something vague like "fix".<br /><br />When merging conflicts, be considerate. Don't just throw away someone else's changes because you're too lazy to carefully merge your changes. If you can't tell what's going on and a merge isn't feasible, be considerate and take the server version then carefully put your bits back again.<br /><br /><b>Keep learning.</b><br /><br />Encourage individuals to stay up to date with the continuous changes in technology. Follow famous developers on Twitter and Google+. If you don't know where to start, just follow one famous person you know and go from there. For .NET, follow Scott Hanselman on Twitter and/or Google+.<br /><br />As a team, make time to learn together by: (a) trying new things, (b) doing Patterns & Practices meetings, (c) doing informal "show and tell" presentations. Encourage the team to work on side-projects when you have a spare moment now and then.<br /><br /><strong>Maximize savings / Eliminate waste.</strong><br /><br />Remember why we're working here. We're not here to have fun, to learn, to write unit tests or even to write code. We're here to solve business problems. Bottom line: to make the business money. (But yes, of course we want to have fun and learn while solving the real business problems.)<br /><br />Before you write that cool ORM (or CSV parser or some other way to reinvent the wheel), ask yourself: are we in the business of writing ORMs (or CSV parsers etc)? If a perfectly good open source or commercial solution already exists, then don't reinvent the wheel. I love reinventing the wheel myself, I know how much fun it can be to write libraries that you imagine might be usable by someone else, but use your time wisely.<br /><br />The same goes for other things that costs the company money. Don't waste printer ink & paper! Why are you still printing articles for reading? (or even worse, printing source code!?) Learn to read on a screen. Or buy a Kindle if you claim you don't like reading a computer monitor or tablet. Use Pocket or Instapaper to save articles for later reading on a suitable device.<br /><br /><b>Always look for improvements.</b><br /><br />I often hear a colleague say something like "<i>But that's not Agile/Scrum!</i>", then my response is "<i>We call it Agile because the process itself is agile.</i>" Don't treat your processes/methodologies like a religion. Change things that don't work and do more of what works well. Have regular retrospectives and follow up on improvement actions identified. An exception would be when you're starting with a new process like Scrum: first follow the rules strictly (do "Scrum by the book"), then only tweak your process at the end of each sprint according to issues raised in the retrospective.<br /><br /><strong>Use the team's strengths.</strong><br /><br />Avoid specialization, but know your team's strengths (and weaknesses). Consider team members' interests. People who work on something they find interesting will generally be more happy and more productive. Consider what's the best use of everyone's time. For example, does it make sense for the most senior team member to perform the team's admin (sprint reports, keeping documentation up to date for CMMI, etc)? Does it make sense for the most junior team member to spend a week figuring out how to install the new TFS server when another member could do it in an hour? It's important to let everyone work in as many areas of the project as possible to distribute the knowledge as much as possible, but there's a balance to keep.<br /><br /><strong>Be pragmatic.</strong><br /><br />Don't be scared to go outside of your comfort zone to use the right tool for the job. For example, if you just spent half the day searching for a Markdown to PDF converter, and the only good solution you could find is a Ruby & Linux-based solution, then don't disqualify it just because your team only has experience using Windows.<br /><br />Programming syllabus for the absolute beginner2013-10-01T16:14:00+00:00http://codeblast.com/2013/10/01/programming-syllabus-for-absoluteA friend wants to start learning programming. In fact, she's considering getting a Computer Science degree and changing careers! I want to teach her <i>everything</i> I know: principles of object oriented design, dependency injection, high cohesion & loose coupling, unit testing, code contracts, MVC, jQuery, Python, NoSQL, Android, and .... Aargh, where do I even start?!<br /><br />I need to come up with a learning plan for the absolute beginner. I want to get to the point where we could use <a href="http://learnpythonthehardway.org/book/">Learn Python the Hard Way</a> to work through the usual programming concepts and hopefully eventually build something interesting like a website or a mobile app. But I want to start at the very basics.<br /><br />I'm thinking of starting with the following topics:<br /><ul><li>Introduction to HTML (design a page using a few tags and some minimal CSS)</li><li>Numeric expressions (operator precedence etc)</li><li>Hello world! (string expressions)</li><li>Binary math (bitwise operators, bytes, and, or, xor, not, shifts etc)</li><li>Boolean algebra / if-then-else</li></ul><div>Some links I want to look at for learning Python:</div><ul><li><a href="http://joepitz.wordpress.com/2012/12/09/tutorial-bit-banging-and-boolean-math-without-the-math/">Tutorial – Bit Banging and Boolean Math without the Math</a></li><li>http://lgm.fri.uni-lj.si/PA/PYTHON/PythonProgrammingfortheAbsoluteBeginner.pdf</li><li>https://wiki.python.org/moin/BeginnersGuide/NonProgrammers</li><li>http://learnpythonthehardway.org/book/ex1.html</li><li>http://www.ucs.cam.ac.uk/docs/course-notes/unix-courses/PythonAB</li></ul>Positive team culture2013-09-30T15:34:00+00:00http://codeblast.com/2013/09/30/positive-team-cultureA positive and healthy team can have fun together. A healthy team is mature. Mature doesn't mean super serious - if you can't have fun, I can't see how you can enjoy your job.<br /><br />Mature team members:<br /><ul><li>Don't complain about "too many" meetings but help improve efficiency & communication to reduce the number of meetings.</li><li>Don't play with their phones in meetings, but interact.</li><li>Don't feel embarrassed or under-qualified to question and correct other team members, even more senior team members.</li><li>Don't get offended or hurt when corrected by another member.</li><li>Don't get hung up on team hierarchy. We're all just developers.</li><li>Help and support each other. There is no point in individual success. There's no place for selfish behavior in a team. The product/company doesn't benefit if the team isn't working together.</li><li>Don't complain when asked for help. If you're the guy who always says "I've got my own work to do" then don't expect others to help you next time. I always remember this Ace of Base line from my school days: "<i>To help another person will make you feel important</i>". It's satisfying to help someone and a good learning experience on top of that. There is no better way to learn than to teach.</li><li>Have a sense of humor! Don't take things too seriously. We might as well try to have fun while we're doing this.</li></ul><div>I admit this is much easier said than done. You need the right (i.e. compatible) people in the team and you need the right manager to motivate the team. There will definitely be some exceptions to the above, for example I'm sure there are some highly successful teams who don't see how I could even mention that I value a sense of humor, similarly I'm sure there are lots of funny but incompetent teams out there. However, I think these points above go a long way towards accommodating the widest range of personalities.<br /><br />At a previous company, all teams had names. X-Men character names like Cyclops, Havok, Wolverine, etc. So when I started at my present company, I suggested giving the teams names. It wasn't a popular suggestion :-) Apparently I was the only one who thought that giving teams names like that was a 'fun' idea. Of course, that's perfectly fine, I just had to realize that this team has a different idea of what's <i>fun</i> than I did.</div>How to fix "Install Parse Failed - Inconsistent Certificates" when installing .APK file2013-09-30T05:38:00+00:00http://codeblast.com/2013/09/30/how-to-fix-install-parse-failedIf you install an Android application (.apk file) to your phone from one machine, and then try to install it again later when it's built on another machine with a different apk signature (e.g. from a CI build) then you will get the following message on the phone: (In this example I've tried to install the app from an email attachment directly on the phone.)<br /><div></div><br /><a href="http://2.bp.blogspot.com/-DK968h5SnwM/UkkNlDk3BoI/AAAAAAAACsE/cgVr_i_0j5I/s1600/Screenshot_2013-09-29-20-24-22.png" imageanchor="1"><img border="0" src="http://2.bp.blogspot.com/-DK968h5SnwM/UkkNlDk3BoI/AAAAAAAACsE/cgVr_i_0j5I/s400/Screenshot_2013-09-29-20-24-22.png" /></a><br /><br /><i>"Application not installed. An existing package by the same name with a conflicting signature is already installed."</i><br /><br /><a href="http://1.bp.blogspot.com/-KX2MkcjMwSQ/UkkNyBxN_GI/AAAAAAAACsM/XIPdQt5WBAg/s1600/Screenshot_2013-09-29-20-24-39.png" imageanchor="1"><img border="0" src="http://1.bp.blogspot.com/-KX2MkcjMwSQ/UkkNyBxN_GI/AAAAAAAACsM/XIPdQt5WBAg/s400/Screenshot_2013-09-29-20-24-39.png" /></a><br /><br />Similarly if you try to install the app on another development machine using ADB (or from the IDE) you get the following <i>"install parse failed inconsistent certificates" </i>error message:<br /><br /><pre><code>$ <b>adb install TestProj-debug-unaligned.apk </b><br />1539 KB/s (45347 bytes in 0.028s)<br /> pkg: /data/local/tmp/TestProj-debug-unaligned.apk<br />Failure [INSTALL_FAILED_ALREADY_EXISTS]<br />$ <b>adb install -r TestProj-debug-unaligned.apk </b><br />2659 KB/s (45347 bytes in 0.016s)<br /> pkg: /data/local/tmp/TestProj-debug-unaligned.apk<br />Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]<br /></code></pre><pre><code><br /></code></pre>You also get the exact same message as above if you try to run the application from within <a href="http://developer.android.com/sdk/installing/studio.html">Android Studio</a> of course: <br /><pre><code><br />Waiting for device.<br />Target device: CB5A1QHGNF<br />Uploading file<br /> local path: /Users/lombard/src/TestProjProject/TestProj/build/apk/TestProj-debug-unaligned.apk<br /> remote path: /data/local/tmp/com.example.testproj<br />Installing com.example.testproj<br />DEVICE SHELL COMMAND: pm install -r "/data/local/tmp/com.example.testproj"<br />pkg: /data/local/tmp/com.example.testproj<br />Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]<br /></code></pre><div><br /></div><div>You've got two options:<br /><ol><li>Copy the first machine's <code>debug.keystore</code> file to the second machine. See: <a href="http://stackoverflow.com/questions/3185444/how-to-deal-with-install-parse-failed-inconsistent-certificates-without-uninstal">How to deal with INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES without uninstallation</a> on StackOverflow.</li><li>Completely uninstall the application first and then install again. You may have to do this if you don't have the <code>debug.keystore</code> file for some reason. Perhaps your Jenkins CI build has a different release keystore.</li></ol></div><div>I've had to go for the second option.<br /><br />I was hoping I'd be able to keep the application's data, so I first tried uninstall with the -k option to keep the data files, however that results in an <i>"update incompatible"</i> error:</div><pre><code><br />$ adb shell pm uninstall -k com.example.testproj<br />$ adb install -r TestProj-debug-unaligned.apk<br />1532 KB/s (45347 bytes in 0.028s)<br /> pkg: /data/local/tmp/TestProj-debug-unaligned.apk<br />Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE]</code></pre><div><br /></div><div>The only solution seems to be to uninstall the application completely:<br /><br /><pre><code>$ adb uninstall com.example.testproj<br />Success</code></pre></div><div><br /></div><div>Now the app will install from Android Studio.</div><div><br /></div><div>Ideally I want to find a way to force an app to reinstall without needing to completely uninstall it first.</div>Nexus 7 with wireless keyboard and mouse2013-09-18T21:38:00+00:00http://codeblast.com/2013/09/18/nexus-7-with-wireless-keyboard-and-mouse<p dir="ltr">A few months ago I cracked my Google/Asus Nexus 7 screen/digitizer and the touch is no longer working on 90% of the screen. Only a small part in one corner still detects touch. The display still works fine otherwise, but it was essentially useless. </p><p dir="ltr">I looked into several ways to try and make the Nexus 7 usable again, including:<br>1. Tried to find an app that might all me to use the small working touch area to control apps (e.g. keyboard apps that can be controlled without needing the entire screen);<br>2. Tried to use MonkeyRunner to script apps to control them. However, this required me to accept the PC in USB debugging mode, which I couldn't do without being able to tap on the "OK" button...<br>3. Tried to find a cheap replacement screen/digitizer on eBay but I wasn't willing to spend more than EUR60.<br>4. Seriously considered getting a new Nexus 7 2013 model.</p><p dir="ltr">Eventually I've found an amazingly simple solution to make it fully usable again: A cheap OTG cable (Micro USB male to USB female), which allows me to plug my Logitech K260 wireless keyboard & mouse into the Nexus 7.</p><p dir="ltr">It's not exactly a tablet anymore, but compared to a broken piece of unused electronics lying in my drawer, this is great! The Nexus 7 with keyboard and mouse is now basically like a small Android laptop. Still perfect for surfing the web etc. I'm extremely happy that for only 3 GBP I've now got a working device again.</p>How to configure the Samsung Galaxy 5 / Europa to work with ADB / Android Studio2013-09-17T21:21:00+00:00http://codeblast.com/2013/09/17/how-to-configure-samsung-galaxy-5I want to deploy an Android application from <a href="http://developer.android.com/sdk/installing/studio.html">Android Studio</a> to an old <a href="http://www.gsmarena.com/samsung_i5500b-3371.php">Samsung GT-I5500</a> (known as Galaxy 5 or Galaxy Europa) running Android 2.2 Froyo (<a href="http://developer.android.com/about/versions/android-2.2.html">API level 8</a>). (Yes, it's probably worth testing on old phones too, although I admit Froyo is at the very bottom 2.4% of distributions!)<br /><br />Summary of steps:<br /><ol><li>Enable USB debugging</li><li>Select USB connection mode to "UMS mode only"</li></ol>First enable USB debugging by going to Settings -> Applications -> Development -> enable "USB debugging".<br /><br />Plug in the USB cable from the computer to the phone. The phone will pop up the "Setting USB" dialog and ask you to select "KIES" or "UMS mode only". You want to select the first option: UMS mode only. (<a href="http://en.wikipedia.org/wiki/Samsung_Kies">Kies</a> is Samsung's software for updating the phone's software etc).<br /><br />Now the I5500 shows up on my devices list in Android Studio. My Android application was configured for <code>minSdkVersion 10 </code>so notice the "no" in the Compatible column when I tried to run the application:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-uO2WkTskpz0/UjikkvRnIcI/AAAAAAAACSg/Tu9hHNfvV1c/s1600/samsung-gt-i5500-choose-device.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-uO2WkTskpz0/UjikkvRnIcI/AAAAAAAACSg/Tu9hHNfvV1c/s1600/samsung-gt-i5500-choose-device.png" /></a></div><br />I modified the build.gradle file to <code>minSdkVersion 8</code> and also set <code>android:minSdkVersion="8"</code> in the AndroidManifest.xml file. Now the app deploys OK.<br /><br />Of course ADB.exe also lists the I5500 correctly now:<br /><br /><code>D:\Android\android-studio\sdk\platform-tools> adb devices<br />List of devices attached<br />I550030d7c481 device</code><br /><br />OK, I admit it! I was wrong!2013-09-12T21:21:00+00:00http://codeblast.com/2013/09/12/ok-i-admit-it-i-was-wrongThis morning I saw this tweet:<br /><blockquote class="twitter-tweet">My new favorite experience: realizing that I've been wrong about something and admitting it, with a smile, without shame.<br />— Coenraad Loubser (@dagelf) <a href="https://twitter.com/dagelf/statuses/378031902625918976">September 12, 2013</a></blockquote><script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script> I had a similar thought earlier this week at work. As many others, I've always got a long To Do list and it never seems to get any shorter. As result, I try to prioritize as I go and sometimes I don't make the wisest choices and some very important tasks fall way behind schedule (even though they remain at the top of my To Do list for weeks!) This week one such task culminated in my manager coming over looking for the reasons why I hadn't completed the work yet, as the issue is now highly visible. I went into a half hour rant explaining the various reasons and excuses why I couldn't finish the task. That night, in bed (probably around 3am, the time when I usually reflect on this type of thing), it occurred to me that I was being completely dishonest to myself and my manager. The simple reason I have not yet finished that task, is because I find it boring and I will always pick a more interesting task that I can justify to myself as being more "urgent" at the time. The next morning I talked to my manager and admitted: "The simple answer is: I found it boring and I made some judgement errors in my prioritization and procrastinated too long." It feels good to take responsibility for your mistakes.<br /><br />This ability we have to find excuses to justify our decisions even when we're wrong, is called Cognitive Dissonance. Check out the book called "Mistakes were made (But not by me)". It covers this topic quite well, I recommend it.<br /><br />As developers, we want to prove ourselves. We want to be right about our opinions and we want others to see our point of view. It's difficult to be completely unbiased when there is any room for ambiguity in a debate.<br /><br />I'm sometimes lucky to catch and recognize the feeling of the cognitive dissonance as it sets in, and that makes it easier to control it. It helps a little bit just be aware that we're all susceptible to biases and cognitive dissonance, but I doubt anyone can completely eliminate it.<br /><br />For many years I've been keen to try doing regular Code Reviews at work, but I'm "worried" that my team members may feel insulted when I "criticize" their code. At the same time, I feel like I can handle the criticism myself. Does that mean I'm mature enough not to experience cognitive dissonance when faced with disagreement, or is that a type of bias in itself to think that I'm somehow less susceptible to the emotional effects of criticism and conflict? (By the way, no one should feel offended when their code is criticized - <a href="http://www.hanselman.com/blog/YouAreNotYourCode.aspx">you are not your code</a>).<br /><br />As software developers, I think we are often too scared of making any mistakes. Especially "debilitatingly-perfectionist" and <a href="http://en.wikipedia.org/wiki/DISC_assessment">High C</a> developers like myself. We want certainty and facts. We want to stick with the tools we know. We get religious about our tools (languages, text editors, brands of keyboards, etc) and we can't understand when others can't see that they're wrong and we're right.<br /><br />We have to learn to embrace risk, taking chances, making mistakes, and admitting our mistakes. The Agile mindset is to <a href="http://www.theagileleader.com/2012/02/the-agile-mindset-perceptions-around-failure/">embrace failure</a> (fail early). Learn to make better mistakes in the future. <i>Making mistakes is the key to making progress</i>, as Daniel C. Dennett says in his book "Intuition Pumps and Other Tools for Thinking".<br /><br />Links:<br /><ul><li><a href="http://en.wikipedia.org/wiki/Mistakes_Were_Made_(But_Not_by_Me)">Mistakes Were Made (But Not by Me)</a> - Carol Tavris, Elliot Aronson</li><li><a href="http://www.forbes.com/sites/amyanderson/2013/05/01/admitting-you-were-wrong-doesnt-make-you-weak-it-makes-you-awesome/">Admitting You Were Wrong Doesn't Make You Weak -- It Makes You Awesome!</a></li><li><a href="http://ase.tufts.edu/cogstud/papers/howmista.htm">How to Make Mistakes</a> - Daniel C. Dennett</li></ul><br /><br /><br />Remote Desktop Connection for Mac OSX - cannot verify the identity of the computer2013-09-08T21:33:00+00:00http://codeblast.com/2013/09/08/remote-desktop-connection-for-mac-osxShort version: If you have issues with the <a href="http://www.microsoft.com/mac/remote-desktop-client">Microsoft RDC for Mac</a> client connecting to Windows Server 2012 R2, then give <a href="http://cord.sourceforge.net/">CoRD</a> a try.<br /><br />I'm having a lot fun playing with Azure lately. It's so quick and easy to create new Ubuntu- or Windows-based VM servers for trying something, and then deleting the virtual machine again when I'm done. For the Ubuntu servers I just use ssh of course, but for Windows Servers you need to use a Remote Desktop Connection client.<br /><br />At home I connect to the Azure cloud services on OS X using the "Microsoft Remote Desktop Connection for Mac" RDC client. It's just cool seeing the remote Windows server on the Mac. I don't even need to use VMWare or Parallels to run a local Windows installation.<br /><br />However, I've come across this error on the Mac when trying to connect to a remote Windows Server 2012 R2 on Azure: <br /><blockquote><span style="font-family: Courier New, Courier, monospace;">"<b>Remote Desktop Connection cannot verify the identity of the computer that you want to connect to.</b>Try reconnecting to the Windows-based computer, or contact our administrator."</span></blockquote><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-7hCDq0dq_qY/UitLzNtxpRI/AAAAAAAACQg/QNAO9usO4_M/s1600/Screen+Shot+2013-09-07+at+8.51.52+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="432" src="http://4.bp.blogspot.com/-7hCDq0dq_qY/UitLzNtxpRI/AAAAAAAACQg/QNAO9usO4_M/s640/Screen+Shot+2013-09-07+at+8.51.52+AM.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="p1">When this happens, the only solution currently seems to be to use CoRD instead of the Microsoft RDC client.</div><div class="p2"><br /></div><div class="p1">First ensure you've disabled the "Allow connections only from computers running Remote Desktop with Network Level Authentication (recommended)" setting. To do that, first connect to the remote Windows Server 2012 R2 using RDC on a Windows client, then go to Server Manager:</div><div class="p2"><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-177nNCEoegE/Uizsd-UCUSI/AAAAAAAACRU/W4_0aSIs5Ds/s1600/rdc-settings-NLA1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-177nNCEoegE/Uizsd-UCUSI/AAAAAAAACRU/W4_0aSIs5Ds/s1600/rdc-settings-NLA1.png" /></a></div><br /><br /></div><div class="p1">Go to Local Server -> Remote Desktop. Make sure the NLA setting is unchecked:</div><div class="p2"><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-d36R3NslolY/UizslGs-T1I/AAAAAAAACRc/xF3ummUtgy4/s1600/rdc-settings-NLA2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-d36R3NslolY/UizslGs-T1I/AAAAAAAACRc/xF3ummUtgy4/s1600/rdc-settings-NLA2.png" /></a></div><br /></div><div class="p1">Now get CoRD from http://cord.sourceforge.net/</div><div class="p2"><br /></div><div class="p1">Add the server, making sure you've got the correct domain name for the Windows login:</div><div class="p2"><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-jXHnJmeXUDo/UizoiYhFnEI/AAAAAAAACRM/4YkfCzMzwP4/s1600/Screen+Shot+2013-09-08+at+2.11.44+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="411" src="http://1.bp.blogspot.com/-jXHnJmeXUDo/UizoiYhFnEI/AAAAAAAACRM/4YkfCzMzwP4/s640/Screen+Shot+2013-09-08+at+2.11.44+PM.png" width="640" /></a></div><br /></div><div class="separator" style="clear: both; text-align: left;"></div><div class="p1">Now you should be able to connect successfully to the remote Windows 2012 R2 server in the cloud.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"></div><div class="p1">On other versions of remote Windows servers you may also have success trying the following with the Microsoft RDC client for Mac:</div><div class="separator" style="clear: both; text-align: left;"></div><ol><li>Close Remote Desktop Connection for Mac</li><li>Go to: Finder -> Documents -> RDC Connections</li><li>Move the Default.rdp file to Trash</li><li>Open RDC again and connect to the server.</li><li>When the Enter your credentials window pops up, the Domain field is populated with the DNS name of the host, which isn't necessarily the correct domain name. Try the correct domain name or try <b><i>clearing this field.</i></b></li><li>Just supply the correct username and password. Click OK.</li></ol><div class="separator" style="clear: both; text-align: left;">Sources:</div><ul class="ul1"><li class="li3"><a href="http://cord.sourceforge.net/"><span class="s1">CoRD - Mac OS X remote desktop client</span></a></li><li class="li3"><a href="http://technet.microsoft.com/en-us/library/cc732713.aspx"><span class="s1">Configure Network Level Authentication for Remote Desktop Services Connections</span></a></li><li class="li3"><a href="http://social.technet.microsoft.com/Forums/windows/en-US/e442d972-0039-495d-af6c-303cdabb5254/osx-remote-desktop-client-cannot-connect-to-win-81-or-server-2012-r2-preview"><span class="s1">OSX Remote Desktop Client cannot connect to Win 8.1 or Server 2012 R2 Preview</span></a></li><li class="li3"><a href="http://jens.raaby.co.uk/journal/2011/01/microsoft-remote-desktop-on-mac-os-x/"><span class="s1">Microsoft Remote Desktop Client on Mac OS X: "Cannot Verify the Identity of the Computer That You Want to Connect To"</span></a></li></ul><div class="separator" style="clear: both; text-align: left;"><br /></div>Configure Google Nexus 7 to work with Android SDK Tools / ADB.exe2013-03-25T21:01:00+00:00http://codeblast.com/2013/03/25/configure-google-nexus-7-to-work-with<p>I wanted to deploy my first “hello world” Android application from Eclipse on Windows 8 to my Google Nexus 7 tablet. I plugged the Nexus 7 into my development PC using the USB cable and then I used adb.exe to list the devices, but no devices were found.</p> <p>The summary of steps I took to get the device to show with ADB:</p> <ol> <li>Enabled the USB debugging setting on the tablet</li> <li>Changed the USB connection mode to Camera (PTP)</li> <li>Updated the Google USB Driver in Windows</li></ol> <p>Initially Adb.exe shows no devices:</p> <p><a href="http://lh4.ggpht.com/-ORXtPs9hkmw/UVC6vrJldOI/AAAAAAAAAHI/VYWdHaSkiWo/s1600-h/01-adb-shows-no-devices%25255B3%25255D.png"><img title="01-adb-shows-no-devices" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="01-adb-shows-no-devices" src="http://lh6.ggpht.com/-DPzhEn0p2S0/UVC6wopHdfI/AAAAAAAAAHQ/Y3yUFOVPX9I/01-adb-shows-no-devices_thumb%25255B1%25255D.png?imgmax=800" width="466" height="80"></a></p> <p>If the Android emulator is running, it shows as the only device:</p> <p><a href="http://lh4.ggpht.com/-Nn5H0OqWuzs/UVC6xfTi5MI/AAAAAAAAAHY/WVKHWBaJoGo/s1600-h/02-adb-shows-only-emulator%25255B3%25255D.png"><img title="02-adb-shows-only-emulator" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="02-adb-shows-only-emulator" src="http://lh5.ggpht.com/-BxWAzamTtUc/UVC6yJrYBsI/AAAAAAAAAHg/yBjn4JsXTH0/02-adb-shows-only-emulator_thumb%25255B1%25255D.png?imgmax=800" width="333" height="80"></a></p> <p>The first step is to enable the Developer options the Nexus 7. Go to Settings –> About tablet. Then tap the “Build number” 7 times! </p> <p><a href="http://lh6.ggpht.com/-HklAMxexbYw/UVC6zU7Yw4I/AAAAAAAAAHo/Lu_Dcek3B_M/s1600-h/02-tap-build-number-7-times%25255B3%25255D.png"><img title="02-tap-build-number-7-times" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="02-tap-build-number-7-times" src="http://lh5.ggpht.com/-KLlfhfoJGVY/UVC60m_SxaI/AAAAAAAAAHw/N0Guk3lovzc/02-tap-build-number-7-times_thumb%25255B1%25255D.png?imgmax=800" width="478" height="526"></a></p> <p>Now you will see the “Developer options” setting. Go into Developer options and enable the “USB debugging” setting:</p> <p><a href="http://lh6.ggpht.com/-VsoGark6mS0/UVC62jdTk8I/AAAAAAAAAH4/hYySBL5PoK4/s1600-h/02-enable-usb-debugging%25255B3%25255D.png"><img title="02-enable-usb-debugging" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="02-enable-usb-debugging" src="http://lh3.ggpht.com/-tw3K6_w81ns/UVC64qHgT3I/AAAAAAAAAIA/xXIgB0EsYok/02-enable-usb-debugging_thumb%25255B1%25255D.png?imgmax=800" width="644" height="504"></a></p> <p>When you get the “USB debugging connected” notification, tap the “Connected as a media device” option.</p> <p><a href="http://lh5.ggpht.com/-tY9Fl2P5kz4/UVC66G5oR8I/AAAAAAAAAII/7t3noarehUk/s1600-h/02-usb-connected%25255B3%25255D.png"><img title="02-usb-connected" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="02-usb-connected" src="http://lh5.ggpht.com/-2gdrA7spELA/UVC6773hYgI/AAAAAAAAAIQ/HyAxtzG084g/02-usb-connected_thumb%25255B1%25255D.png?imgmax=800" width="644" height="270"></a></p> <p>The default USB mode is “Media device (MTP)”, change this to “Camera (PTP)”:</p> <p><a href="http://lh3.ggpht.com/-YZGm7YjJ5m4/UVC69oLs3rI/AAAAAAAAAIY/4VoaHAINdqY/s1600-h/02-select-camera-ptp-mode%25255B3%25255D.png"><img title="02-select-camera-ptp-mode" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="02-select-camera-ptp-mode" src="http://lh3.ggpht.com/-8UMNs7Vg_dY/UVC6_6PnbDI/AAAAAAAAAIg/NjKOvAp9cDs/02-select-camera-ptp-mode_thumb%25255B1%25255D.png?imgmax=800" width="644" height="262"></a></p> <p>Install the Google USB Driver using Eclipse / ADT: Window –> Android SDK Manager. In the Android SDK Manager, select Extras –> Google USB Driver. This installs the driver to your android SDK folder under sdk\extras\google\usb_driver.</p> <p>Now update the device driver using Device Manager in Windows 8:</p> <p><a href="http://lh5.ggpht.com/-tFeWzAcAvqc/UVC7A0NB2QI/AAAAAAAAAIo/4QFjHmOWTTw/s1600-h/03-open-device-manager-win8%25255B13%25255D.png"><img title="03-open-device-manager-win8" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="03-open-device-manager-win8" src="http://lh6.ggpht.com/-WeVfC_nFt2E/UVC7CMmFmTI/AAAAAAAAAIw/ltwKXJ1o1QI/03-open-device-manager-win8_thumb%25255B7%25255D.png?imgmax=800" width="644" height="244"></a></p> <p>Find the “Nexus 7” device in the Device Manager under “Other devices”, then right click and select “Update Driver Software…”:</p> <p><a href="http://lh4.ggpht.com/-PEnSoc_qNlo/UVC7DEyDcfI/AAAAAAAAAI4/8iRKl213c88/s1600-h/04-device-manager%25255B3%25255D.png"><img title="04-device-manager" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="04-device-manager" src="http://lh3.ggpht.com/-Vyj8L22kdoA/UVC7EEpucQI/AAAAAAAAAJA/ZpC5u6EwTFc/04-device-manager_thumb%25255B1%25255D.png?imgmax=800" width="477" height="276"></a></p> <p>Provide the path to the Google USB Driver:</p> <p><a href="http://lh6.ggpht.com/-6KPUtApGs_I/UVC7FPrpfzI/AAAAAAAAAJI/uVftaTJUfuw/s1600-h/05-select-driver%25255B3%25255D.png"><img title="05-select-driver" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="05-select-driver" src="http://lh5.ggpht.com/-4OlaW0sTITE/UVC7GJlMVnI/AAAAAAAAAJQ/1lGdc6vSW0I/05-select-driver_thumb%25255B1%25255D.png?imgmax=800" width="632" height="470"></a></p> <p>Select “Always trust software from Google Inc” and install the driver:</p> <p><a href="http://lh5.ggpht.com/-iPsyh7w_EAI/UVC7HXUbGXI/AAAAAAAAAJY/BojGhFRCzBU/s1600-h/06-install-driver%25255B3%25255D.png"><img title="06-install-driver" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="06-install-driver" src="http://lh4.ggpht.com/-HWCklVvTRBs/UVC7Ico-tjI/AAAAAAAAAJg/3ZeUjSFg-fw/06-install-driver_thumb%25255B1%25255D.png?imgmax=800" width="625" height="470"></a></p> <p>Now the “Android Composite ADB Interface” will show in the Device Manager:</p> <p><a href="http://lh4.ggpht.com/-6lHas_sZstg/UVC7Je7GGaI/AAAAAAAAAJo/9fVx8fVcEOc/s1600-h/07-android-device-in-device-manager%25255B6%25255D.png"><img title="07-android-device-in-device-manager" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="07-android-device-in-device-manager" src="http://lh5.ggpht.com/-QUtq4BsE5YY/UVC7KbGzIVI/AAAAAAAAAJw/vIF6UNpHUo8/07-android-device-in-device-manager_thumb%25255B2%25255D.png?imgmax=800" width="377" height="190"></a></p> <p>Run ADB.exe again and confirm the new device is available. It may show as offline:</p> <p><a href="http://lh3.ggpht.com/-PQUkBkeZOlQ/UVC7LGoSAnI/AAAAAAAAAJ4/5RwJT-nfckU/s1600-h/08-adb-shows-new-device%25255B7%25255D.png"><img title="08-adb-shows-new-device" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="08-adb-shows-new-device" src="http://lh4.ggpht.com/-mgnFHCrVJ3w/UVC7L66gsQI/AAAAAAAAAKA/0dAEazOfFIY/08-adb-shows-new-device_thumb%25255B3%25255D.png?imgmax=800" width="429" height="118"></a></p> <p>If the device shows as “offline”, then make sure to confirm on the tablet that you allow USB debugging:</p> <p><a href="http://lh5.ggpht.com/-1CU6hZaTUiw/UVC7NMIc6VI/AAAAAAAAAKI/AIZ2LVJFfo4/s1600-h/08-allow-usb-debugging%25255B3%25255D.png"><img title="08-allow-usb-debugging" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="08-allow-usb-debugging" src="http://lh6.ggpht.com/-eo2EOx0p0dM/UVC7OZVgZYI/AAAAAAAAAKQ/fS_j06W0yc8/08-allow-usb-debugging_thumb%25255B1%25255D.png?imgmax=800" width="594" height="278"></a></p> <p>Now the device is online:</p> <p><a href="http://lh5.ggpht.com/--sSGxZavO60/UVC7PFfQLpI/AAAAAAAAAKY/NlEQPDe-U44/s1600-h/09-nexus-online%25255B3%25255D.png"><img title="09-nexus-online" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="09-nexus-online" src="http://lh5.ggpht.com/-bQ7B5fXSvYs/UVC7QNjw8SI/AAAAAAAAAKg/J13O4r89bTQ/09-nexus-online_thumb%25255B1%25255D.png?imgmax=800" width="607" height="57"></a></p> <p>That’s it!</p> <p>I’m using Windows 8 64bit, Android Developer Tools (ADT) v21.1.0-569685 and the Nexus 7 is running Android 4.2.2. I used the information on <a href="http://stackoverflow.com/questions/11974700/nexus-7-not-visible-over-usb-via-adb-devices-from-windows-7-x64">this StackOverflow post</a> to figure everything out.</p> Asus Google Nexus 7 3G – Setting up O2 Ireland mobile broadband micro SIM2013-03-24T18:26:00+00:00http://codeblast.com/2013/03/24/asus-google-nexus-7-3g-setting-up-o2<p>When I got my new Google Nexus 7 32GB/3G tablet, I immediately went to the O2 store in town and bought a prepay data Micro SIM for €20. (I actually first went to Carphone Warehouse, but they don’t have data-only Micro SIMs for O2). I went to the O2 website and activated the free 24 hour pass.</p> <p>First thing I did was, I used the wee SIM ejection tool which was included with the Nexus, and plugged in the new SIM. Not too surprisingly, the mobile broadband didn’t just start working by itself. The Nexus showed the “H” mobile icon (HSPA) but the internet wasn’t working. I expected to receive an SMS text message from O2 to active the SIM, but nothing happened after waiting a few hours.</p> <p>The next day, it occurred to me to plug the SIM into my iPhone 4S to see if I receive the activation SMS that way, but still nothing. I contacted O2 customer service (twice) and tried to explain my situation. Even though the second support person was completely unfamiliar with using the data SIM in a tablet, he did give me a good tip: a mobile data-only SIM doesn’t work at all in an iPhone, so even if the SIM had been activated, it still wouldn’t have worked in my iPhone, secondly, he reset the SIM completely, at which point I finally received the SIM activation code SMS on my phone. Luckily that was all it took, I went to the O2 website and activated the SIM using the code I received in the SMS, and put the SIM back into the Nexus tablet. But still no internet on the tablet.</p> <p>(As a side note, after the SIM was activated, my iPhone automatically sent an SMS to some +44 international number, which cost me a few cents, at which point my €20 prepaid credit was no longer enough to activate a 30-day pass, so I had to buy €20 more of credit, but that’s another story).</p> <p>Next, it occurred to me that I probably need to configure the internet settings specifically for O2 on the Nexus tablet (DNS, O2 Ireland APN and that stuff). After a little bit of Googling, I found a few APN tips for other types of modems and after some trial and error, this is what worked for me.</p> <p>Go to Settings. Under “WIRELESS & NETWORKS” select “More…”, then select “Mobile networks”:</p> <p><a href="http://lh4.ggpht.com/-1Gl2lR3K6SU/UU9EPDXMEjI/AAAAAAAAAF8/wwKlpHak0bY/s1600-h/01-network-settings%25255B9%25255D.png"><img title="01-network-settings" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="01-network-settings" src="http://lh6.ggpht.com/-FuPUDWkNNQM/UU9Eh8HnI8I/AAAAAAAAAGE/42SG2geiMzE/01-network-settings_thumb%25255B6%25255D.png?imgmax=800" width="644" height="446"></a></p> <p>Under “Mobile network settings” select “Access Point Names”:</p> <p><a href="http://lh4.ggpht.com/-RyIoWN85muM/UU9E2N7sh_I/AAAAAAAAAGM/odajdOgxbx8/s1600-h/02-select-access-point-names%25255B3%25255D.png"><img title="02-select-access-point-names" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="02-select-access-point-names" src="http://lh3.ggpht.com/-q_LhBAKtK_I/UU9FBGSrq6I/AAAAAAAAAGU/7zhBQQjQ9HE/02-select-access-point-names_thumb%25255B1%25255D.png?imgmax=800" width="644" height="678"></a></p> <p>Now create a new APN by clicking the “three dots” icon and select “New APN”:</p> <p><a href="http://lh4.ggpht.com/-3julHwdjAQY/UU9FGFuEdyI/AAAAAAAAAGc/et99CNfdDzA/s1600-h/03-new-apn%25255B11%25255D.png"><img title="03-new-apn" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="03-new-apn" src="http://lh6.ggpht.com/-ortPh1aedvs/UU9FQ-7n7HI/AAAAAAAAAGk/DgefEuOOdO4/03-new-apn_thumb%25255B5%25255D.png?imgmax=800" width="644" height="202"></a></p> <p>Enter the following fields:</p> <ul> <li>Name: O2.ie (or any name you like) <li>APN: open.internet</li></ul> <p><a href="http://lh4.ggpht.com/-YBkLueQk2yA/UU9FUEgYeUI/AAAAAAAAAGs/gjdjRMr6gF0/s1600-h/04-o2-ie-internet%25255B3%25255D.png"><img title="04-o2-ie-internet" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="04-o2-ie-internet" src="http://lh6.ggpht.com/-HwVFDibfoCA/UU9FVloYNoI/AAAAAAAAAG0/InPV4_n0Tz0/04-o2-ie-internet_thumb%25255B1%25255D.png?imgmax=800" width="644" height="718"></a></p> <p>After adding the new APN and returning back to the “APNs” setting screen, I believe I had to check the radio button next to the new “O2.ie Internet” APN setting to enable it.</p> <p>And that’s it! Now your O2 mobile broadband will work on your Nexus 7.</p> <p>Other Android 4.2 tips:</p> <ul> <li>To take the <a href="http://howto.cnet.com/8301-11310_39-57474203-285/how-to-take-a-screenshot-on-the-nexus-7/">screenshots</a> above on the Nexus 7, I pressed the power button and the "volume down” button simultaneously for about a second or two.</li> <li>If you’re a developer (or even just a curious to play with the Android SDK tools), you will want to enable the <a href="http://www.androidcentral.com/how-enable-developer-settings-android-42">Developer options</a>.</li></ul> Cargo cult unit testing2013-03-11T17:01:00+00:00http://codeblast.com/2013/03/11/cargo-cult-unit-testing<p>Writing unit tests is really time consuming. We strive for 100% code coverage. I often spend more time writing unit tests than I did writing the functionality itself. (And yes, we write unit tests afterwards, we don't do strict TDD, but that's another story).</p> <p>Sometimes I feel like my unit testing is just cargo cult behaviour. Am I just blindly following best practices like unit testing because the experts told me so?</p> <p>Then occasionally I experience that happy moment when a old unit test catches a stupid mistake I just introduced into the code, and my faith is reaffirmed.</p> <p>Overall I can definitely see an improvement in code quality over the crappy code I used to write years ago, so the tests are definitely helping, but I can't help but think sometimes if there isn't another (more productive) way to go? </p> <p>I'm tempted to wonder: wouldn't higher level testing (integration testing) yield the same quality but at less cost? For example, isn't it sufficient to test the acceptance criteria using BDD style tests? I've experimented with SpecFlow previously and found it a very natural way to test. I’d like to give it a try again one day…</p> <p>One example of the side effects of writing testable code is that you’re forced to keep the code cohesive. You really start thinking about coding principles and clean code. If you don’t keep the code clean (cohesive, loosely coupled), you’re going to struggle to write (and worse, maintain) those unit tests. Follow the SOLID principles (e.g. Single Responsibility principle) and your code is going to get so much easier to test. When you’re testing a class that has multiple responsibilities, e.g. a ViewModel (MVVM) in WPF/Silverlight, you easily end up multiplying test cases. For example, when you split a large ViewModel with multiple responsibilities into smaller sub-ViewModels, you’ll likely end up with a smaller number of test cases at the end.</p> <p>If you don’t test everything, every scenario, you’ll loose track of what functionality is actually tested, and you will make a small change to the code, run all tests, the tests pass. But does that really mean that your new change is correct or not? You’ll become complacent and assume you can rely on the unit tests when it’s convenient, but you won’t really know if your code is stable. You need to maintain 100% coverage. As they say “test coverage starts with 100%”</p> Enabling and disabling Windows Features from the command line2012-08-12T13:13:00+00:00http://codeblast.com/2012/08/12/enabling-and-disabling-windows-features<p>This blog post briefly describes how to use the DISM.EXE command to enable or disable Windows Features from the command line. Normally you’d use the <em>Programs and Features</em> –> <em>Turn Windows features on or off</em> dialog in the Control Panel to enable a Windows feature such as IIS or MSMQ. I prefer to use the command line for anything I can, partly because of a left-over habit from my DOS (and some Linux) days, but mostly because it means I can automate things in batch files.</p> <p>Start an elevated command prompt. (Right-click on Command Prompt and click "Run as administrator").</p> <p>To find the name of the feature you want to enable or disable, first list all the installed features. To list all the features available on the PC, whether enabled or not, run:</p> <blockquote> <p><font style="background-color: #000000" face="Courier New"></font><font face="Courier New">C:\> dism /Online /Get-Features</font></p></blockquote> <p>This will display the long list of all the available features and their Enabled/Disabled state.</p> <p>Filter to the list to find the name of the specific feature you're looking for. For example, to find the Hyper-V features:</p> <blockquote> <p><font face="Courier New">C:\> dism /Online /Get-Features /Format:Table | find "Hyper"<br>Microsoft-Hyper-V-All | Disabled<br>Microsoft-Hyper-V-Tools-All | Disabled<br>Microsoft-Hyper-V | Disabled<br>Microsoft-Hyper-V-Management-Clients | Disabled<br>Microsoft-Hyper-V-Management-PowerShell | Disabled</font></p></blockquote> <p>When you find the name of the feature (for example Microsoft-Hyper-V), you can enable it with:</p> <blockquote> <p><font face="Courier New">C:\> dism /Online /Enable-Feature /FeatureName:Microsoft-Hyper-V /All</font></p> <p><font face="Courier New">Deployment Image Servicing and Management tool<br>Version: 6.2.9200.16384</font></p> <p><font face="Courier New">Image Version: 6.2.9200.16384</font></p> <p><font face="Courier New">Enabling feature(s)<br>[==========================100.0%==========================]<br>The operation completed successfully.<br>Restart Windows to complete this operation.<br>Do you want to restart the computer now? (Y/N)</font></p></blockquote> <p>Similarly, to disable the feature again, run:</p> <blockquote> <p><font face="Courier New">C:\> dism /Online /Disable-Feature /FeatureName:Microsoft-Hyper-V-All</font></p> <p><font face="Courier New">Deployment Image Servicing and Management tool<br>Version: 6.2.9200.16384</font></p> <p><font face="Courier New">Image Version: 6.2.9200.16384</font></p> <p><font face="Courier New">Disabling feature(s)<br>[==========================100.0%==========================]<br>The operation completed successfully.<br>Restart Windows to complete this operation.<br>Do you want to restart the computer now? (Y/N)</font></p></blockquote> <p>This should work on Windows 8 as well as Windows 7 and Windows Server 2008 R2.</p> Using SQL UPDATE with ROW_NUMBER()2012-06-09T17:21:00+00:00http://codeblast.com/2012/06/09/using-sql-update-with-rownumber<p><strong><u>The problem:</u></strong></p> <p>The application is displaying a list of “To-do” tasks from a SQL Server database table, but the rows are currently displayed in an arbitrary order which is not necessarily in the order the user wants them to be displayed. We want to add a new feature to the application to allow the user to specify the order of the To-do items in the list (i.e. a priority for each To-do item).</p> <p>We want to introduce a new “sort order” (or sequence number) column to the table to allow the user to specify the order in which the rows are to be displayed.</p> <p>Adding a new column to the “create table” script (for new databases) is obviously straightforward. But the problem is that we also need to be able to upgrade (migrate) existing customers to the new table structure.</p> <p>Therefore we need to create a SQL migration script to add a new priority / sort-order column to the existing Todo table.</p> <p>Currently the Todo table structure looks like this:</p><pre><code>create table Todo<br />(<br /> TodoId bigint not null primary key identity,<br /> Priority nvarchar(10) not null,<br /> Title nvarchar(200) not null,<br /> DateDone datetime null<br />)</code></pre><br /><p>The following query used by the application to retrieve the Todo list illustrates the problem:</p><pre><code>select * from Todo order by Priority</code></pre><br /><p>Result:</p><br /><table cellspacing="0" cellpadding="2" border="1"><br /><tbody><br /><tr><br /><td valign="top"><strong>TodoId</strong></td><br /><td valign="top"><strong>Priority</strong></td><br /><td valign="top"><strong>Title</strong></td><br /><td valign="top"><strong>DateDone</strong></td></tr><br /><tr><br /><td valign="top" width="84">4</td><br /><td valign="top" width="88">High</td><br /><td valign="top" width="220">Call Joe</td><br /><td valign="top" width="99">NULL</td></tr><br /><tr><br /><td valign="top" width="84">2</td><br /><td valign="top" width="88">High</td><br /><td valign="top" width="220">Backup computer</td><br /><td valign="top" width="99">NULL</td></tr><br /><tr><br /><td valign="top" width="84">3</td><br /><td valign="top" width="88">Low</td><br /><td valign="top" width="220">Wash car</td><br /><td valign="top" width="99">NULL</td></tr><br /><tr><br /><td valign="top" width="84">5</td><br /><td valign="top" width="88">Low</td><br /><td valign="top" width="220">Mow the lawn</td><br /><td valign="top" width="99">NULL</td></tr><br /><tr><br /><td valign="top" width="84">6</td><br /><td valign="top" width="88">Low</td><br /><td valign="top" width="220">Groceries</td><br /><td valign="top" width="99">NULL</td></tr><br /><tr><br /><td valign="top" width="84">7</td><br /><td valign="top" width="88">Medium</td><br /><td valign="top" width="220">Pick up package at post office</td><br /><td valign="top" width="99">NULL</td></tr><br /><tr><br /><td valign="top" width="84">1</td><br /><td valign="top" width="88">Medium</td><br /><td valign="top" width="220">Take the dog for a walk</td><br /><td valign="top" width="99">NULL</td></tr></tbody></table><br /><p>Notice above that the first two ‘High’ priority items are shown in an arbitrary order. We may want to order it by the “TodoId” column which is perhaps slightly better, but still not necessarily in the order the user wants to see the tasks.</p><br /><p><strong><u>The solution:</u></strong></p><br /><p>We have to produce two SQL scripts: one is the script used for new installations, the second is to upgrade/migrate existing databases to the new structure.</p><br /><p>The first part is easy: for new installation script we just add the new column:</p><pre>sortOrder int not null</pre><br /><p>But in the migration script for existing databases, we initially have to add the new “sortOrder” column as a nullable field since there are already rows in the table and we need to provide reasonable initial/default value for the new column first. So we first add the column as a nullable, and we’ll alter the table afterwards to make it ‘not null’.</p><br /><p>So the first step in the migration script is to add the new field to the existing Todo table:</p><pre><code>alter table Todo add sortOrder int null</code></pre><br /><p>Now we need to update the Todo table to provide an appropriate initial value for the new sortOrder field in each row.</p><br /><p>Our Todo tasks are priortised as ‘High’, ‘Medium’ or ‘Low’. We want the sortOrder value to start from 1 and increment for each subsequent row within each of these 3 priorties. In other words, we want the two ‘High’ priority tasks to be given a sortOrder value of 1 and 2, the same for the two ‘Medium’ tasks, and the three ‘Low’ priority tasks need to be given a sortOrder of 1, 2, and 3.</p><br /><p>The trick is to use the SQL UPDATE statement together the SQL Server ROW_NUMBER() function.</p><br /><p>First, let’s just select the data using the ROW_NUMBER() function to see how we can get an appropriate initial value for sortOrder for each row:</p><pre><code>select TodoId, Priority, Title,<br /> ROW_NUMBER() over(partition by Priority order by TodoId) as rowIndex<br /> from Todo<br /> order by Priority, rowIndex</code></pre><br /><p>Result:</p><br /><table cellspacing="0" cellpadding="2" border="1"><br /><tbody><br /><tr><br /><td valign="top" width="100"><strong>TodoId</strong></td><br /><td valign="top" width="84"><strong>Priority</strong></td><br /><td valign="top" width="237"><strong>Title</strong></td><br /><td valign="top" width="81"><strong>rowIndex</strong></td></tr><br /><tr><br /><td valign="top" width="100">2</td><br /><td valign="top" width="84">High</td><br /><td valign="top" width="237">Backup computer</td><br /><td valign="top" width="81">1</td></tr><br /><tr><br /><td valign="top" width="100">4</td><br /><td valign="top" width="84">High</td><br /><td valign="top" width="237">Call Joe</td><br /><td valign="top" width="81">2</td></tr><br /><tr><br /><td valign="top" width="100">3</td><br /><td valign="top" width="84">Low</td><br /><td valign="top" width="237">Wash car</td><br /><td valign="top" width="81">1</td></tr><br /><tr><br /><td valign="top" width="100">5</td><br /><td valign="top" width="84">Low</td><br /><td valign="top" width="237">Mow the lawn</td><br /><td valign="top" width="81">2</td></tr><br /><tr><br /><td valign="top" width="100">6</td><br /><td valign="top" width="84">Low</td><br /><td valign="top" width="237">Groceries</td><br /><td valign="top" width="81">3</td></tr><br /><tr><br /><td valign="top" width="100">1</td><br /><td valign="top" width="84">Medium</td><br /><td valign="top" width="237">Take the dog for a walk</td><br /><td valign="top" width="81">1</td></tr><br /><tr><br /><td valign="top" width="100">7</td><br /><td valign="top" width="84">Medium</td><br /><td valign="top" width="237">Pick up package at post office</td><br /><td valign="top" width="81">2</td></tr></tbody></table><br /><p>The “rowIndex” value in the result above gives us the correct value we’d like to update the new sortOrder column with for each row.</p><br /><p>Now we need to combine this query with a SQL UPDATE statement to update sortOrder:</p><pre><code>update t<br /> set sortOrder = rowIndex<br />from<br />(<br /> select sortOrder, ROW_NUMBER() over(partition by Priority order by TodoId) as rowIndex<br /> from Todo<br /> where sortOrder is null<br />) as t</code></pre><br /><p>Now “sortOrder” has the desired values partitioned by priority.</p><br /><p>The last step is just to make the sortOrder column not null:</p><pre><code>alter table Todo alter column sortOrder int not null</code></pre><br /><p>Also see:</p><br /><ul><br /><li><a href="http://stackoverflow.com/questions/5686058/how-to-use-row-number-in-sql-server">How to use row_number() in SQL Server</a> (StackOverflow)</li></ul> Why blog?2012-05-29T21:11:00+00:00http://codeblast.com/2012/05/29/why-blogI've decided to give blogging a try once again.<br /><br />I have new questions every day and I learn something new every day. I'm very fortunate to work with an extremely talented team at the moment, and I've never learned so much from others as I am on my current project. <br /><br />It would be a shame not to share some of the useful patterns and practices I'm learning from them (assuming my attempt at conveying the ideas will do it justice!).<br /><br />As a developer, you inevitably have to "research" various bits and pieces every day anyway. I often feel the need to write down what I learn to help myself remember it. Sometimes I send an email to colleagues explaining something (e.g. like why I think we should use xUnit.net instead of MSTest) and then think afterwards: "I just spent 30 minutes working on this email that might get read by one or two people, I should've written it as a blog post instead!"<br /><br />I'm hoping that blogging about a few of the things that I'm learning, will <br />(a) encourage me to dig a little deeper into the topics that I'm "researching";<br />(b) document my findings for my own future reference;<br />(c) hopefully help the occasional anonymous beginner programmer doing a Google search and somehow coming across this blog.<br /><br />However, blogging isn't easy for me. I think about an idea or concept. In my mind I imagine the idea might be worth a blog post. "I've got an idea for a blog post! It's going to be epic!" My blog post ideas are usually formed around a few keywords. But as I start fleshing out the post, the structure just doesn't work. My thoughts don't come out into words the way I imaged it would when I started. Then the post just remains unfinished forever in a lost text file somewhere.<br /><br />That is why I almost never blog. I'm never satisfied with the result. But I've decided to stop caring so much and just start doing it. Even the current plain theme of this blog is an example of how I'm deliberately trying to get over this time-wasting "perfectionism".<br /><br />It does mean I'm revealing my perhaps unpopular opinions, biases, weaknesses and sometimes chaotic thoughts to the world (assuming anyone actually reads it) which is a slightly scary thought. <br /><br /><a href="http://www.hanselman.com/blog/YourBlogIsTheEngineOfCommunity.aspx">Your Blog Is The Engine of Community</a>.Why do you prefix stored proc names with sp?2008-04-17T08:30:00+00:00http://codeblast.com/2008/04/17/why-do-you-prefix-stored-proc-namesYou don't call variable "x" in your C# code <code>xVariable</code> or <code>var_x</code>.<br /><br />You don't call a table "Products" in your database <code>ProductsTable</code> or <code>table_Products</code>.<br /><br />So why do you call your stored procedures <code><b>sp_</b>GetProducts</code>?<br /><br />Are prefixes really necessary in stored proc names? Isn't it obvious enough that it's a stored procedure?<br /><br />Just wondering.<br /><br />(If you have to prefix your stored procs, don't use "sp" because then they appear to be system stored procs...)Summary of X.509 certificate file types2008-03-03T13:42:00+00:00http://codeblast.com/2008/03/03/summary-of-x509-certificate-file-typesWhat is the difference between .spc and .cer? .pvk and .pfx?<br /><br />As part of my ongoing mission to try to understand X509 certificates I wanted to figure out how to copy a test SSL certificate from one PC to another. The problem is <code>makecert.exe</code> generated a .cer file and I needed a .pfx file to import the certificate on the other server.<br /><br />Use the <code>-pe</code> option with <code>makecert.exe</code> to create and install a certificate with an exportable private key. This should allow you to export the .pfx file from Certificates console.<br /><br />Otherwise, use <code>cert2spc.exe</code> and <code>pvkimprt.exe</code> to convert the .cer and .pvk created by <code>makecert.exe</code> to a .pfx file:<br /><pre><code>makecert -pe -n "CN=My Root CA, O=Test, OU=For Testing Only!" -ss my -sr LocalMachine -a sha1 -sky signature -r -sv test.pvk test.cer<br />cert2spc test.cer test.spc<br />pvkimprt -pfx test.spc test.pvk</code></pre>Or use <code>pvk2pfx</code> instead of the above:<br /><pre><code>pvk2pfx -pvk test.pvk -spc test.cer -pfx test.pfx -po pfx_password_here -f</code></pre><b>X.509 File Types:</b><br /><ul><li>.CER = "DER" encoded binary X.509 Certificate file, e.g. as created by makecert. Contains only the public key.</li><li>.CRT = base-64 encoded X.509 certificate. (Not the same as a Microsoft standard base-64 .cer file...?)</li><li>.SPC = Software Publisher's Certificate. PKCS #7 standard that contains X.509 certificates. The cert2spc.exe utility converts a .cer file to .spc. .spc files are used as input to signcode.exe.</li><li>.PVK = private key file, e.g. as created by makecert.</li><li>.PFX = Personal Exchange file, contains certs with both the public and private key. PKCS#12 standard, binary DER encoded.</li></ul><b>Some Windows certificate tools:</b><br /><ul><li>makecert.exe</li><li>pvkimprt.exe</li><li>cert2spc.exe</li><li>selfssl.exe</li><li>pvk2pfx.exe</li><li>certmgr.exe</li></ul><b>See also:</b><br /><ul><li><a href="http://msdn2.microsoft.com/en-us/library/aa906332.aspx">pvk2pfx Tool</a></li><li><a href="http://msdn2.microsoft.com/en-us/library/bfsktky3%28VS.80%29.aspx">Makecert Tool</a></li></ul>The use of IDisposable and finalizers2008-02-28T14:50:00+00:00http://codeblast.com/2008/02/28/the-use-of-idisposable-and-finalizersAn explanation of how the Garbage Collector handles <code>IDisposable</code> and finalizers.<br /><br />At my work we have lots of code like this in our ASP.NET apps:<br /> <pre name="code" class="c-sharp"><code>class LogonPage : IDisposable<br />{<br /> public LogonPage()<br /> {<br /> }<br /> <br /> ~LogonPage()<br /> {<br /> this.Dispose();<br /> }<br /> <br /> public void Dispose()<br /> {<br /> }<br /> <br /> // rest of code here<br />}</code></pre> <br />In other words, a class that implements <code>IDisposable</code> with an empty <code>Dispose</code> method and a finalizer (aka destructor) that calls <code>Dispose</code>.<br /><br />The intention of this code appears to be to somehow give a "hint" to the Garbage Collector to free the memory associated with this object when the "destructor" is called.<br /><br />Implementing a finalizer in this case has no benefit at all, in fact, it probably has the opposite effect of what was expected. It will not cause the GC to free the object's memory any earilier than an object not implementing a finalizer and it places additional load on the GC.<br /><br />There are two problems with the assumption that implementing <code>IDisposable</code> and a finalizer will somehow affect the GC to free the memory earlier:<br /><br />1. C# finalizers are not deterministic;<br /><br />2. Objects with finalizers are kept in memory longer than objects without and require additional GC processing.<br /><br /><strong>Non-determistic finalization</strong><br /><br />It is a common misconception that a C# destructor is similar to a C++ destructor. In C# the "~" method is often called a destructor, but that's a misnomer. It's not a destructor in the C++ sense. Instead the "~" method is really just an override for <code>Object.Finalize()</code>. It was a mistake of the .NET implementors to even use the "~" character to indicate a finalizer.<br /><br />In C++ the destructor is deterministic, in other words, the developer is responsible for allocating and freeing memory and destructor is called at an exact predictable time: e.g. when an object on the stack reaches the end of its lifetime (i.e. when it leaves the scope of the code block) or when an object on the heap is explicitly freed with the <code>delete</code> keyword.<br /><br />But .NET finalization is "non-deterministic". That means you don't know when and in what order the GC will call the finalizers and you have no control over when the object will be freed. Unlike with C++ destructors, the programmer has no way of explicitly calling a .NET finalizer.<br /><br /><strong>Generations and finalization</strong><br /><br />The .NET GC uses a generational algorithm. This means the GC divides the managed heap in three logical sections, or generations, called gen 0, gen 1 and gen 2. Each of these generations have a maximum size, initially 256kb, 2MB and 10MB respectively. New objects are usually allocated on gen 0.<br /><br />When a new object is allocated and the gen 0 memory is too full to accomodate the new object, the GC will reclaim the memory allocated to unreachable objects by compacting the gen 0 memory. Next the GC promotes all gen 0 objects to gen 1. This empties gen 0 for new objects.<br /><br />Similarly when the gen 1 heap becomes full, the GC reclaims unused memory and promotes the gen 1 objects to gen 2.<br /><br />The GC performs collection more frequently on lower generations than higher generations.<br /><br />The GC frees finalizable objects much later than those wihout finalizers.<br /><br />When a finalizable object is created, a reference to it is added to the "finalization list". When the GC determines that an object is no longer reachable, but it's in the finalization list, it's not freed immediately. Instead the finalizable object is put on another special queue called the "f-reachable queue" and promoted to the next generation. A special thread called the "finalizer thread" monitors the f-reachable queue and calls the finalizers when necessary. These objects will eventually be freed the next time a gen 1 or 2 garbage collection is performed. Therefore it takes at least two garbage collection cycles to free finalizable objects.<br /><br /><strong>Recommended IDispoable pattern</strong><br /><br />Implementing <code>IDisposable.Dispose</code> has no effect on the GC at all. It's little more than just a standard interface for providing a "Close" method on your class to allow the user to close/unload resources.<br /><br />Use the following "Dispose pattern" when your class uses other managed classes that implement <code>IDisposable</code> (note a finalizer is <em>not</em> needed here). This is the most common scenario.<br /><pre><code>class MyClass : IDisposable <br />{<br /> private bool disposed = false;<br /> private FileStream file;<br /> <br /> public MyClass()<br /> {<br /> file = new FileStream(...);<br /> }<br /> <br /> public void Dispose()<br /> {<br /> if (!disposed)<br /> {<br /> file.Close();<br /> disposed = true;<br /> }<br /> }<br /> <br /> public void Close()<br /> {<br /> Dispose();<br /> }<br />}</code></pre><br />If you have to implement <code>IDisposable</code> and a finalizer, use the recommended pattern as described in MSDN.<br /><pre><code>class MyClass : IDisposable <br />{<br /> private bool disposed = false;<br /> private IntPtr file = IntPtr.Zero; // Unmanaged resource<br /> <br /> public MyClass()<br /> {<br /> file = ...; // allocate unmanaged resource<br /> }<br /> <br /> ~MyClass()<br /> {<br /> Dispose(false);<br /> }<br /> <br /> public void Dispose()<br /> {<br /> Dispose(true);<br /> GC.SuppressFinalize(this);<br /> }<br /> <br /> public void Close()<br /> {<br /> Dispose();<br /> }<br /> <br /> protected virtual void Dispose(bool disposing)<br /> {<br /> if (!disposed)<br /> {<br /> if (disposing)<br /> {<br /> // dispose managed resources<br /> }<br /> if (file != IntPtr.Zero)<br /> {<br /> // free unmanaged resource<br /> file = IntPtr.Zero;<br /> }<br /> disposed = true;<br /> }<br /> }<br />}</code></pre><br /><strong>Summary</strong><br /><br />Only implement <code>IDisposable</code> if you have a reason to do so, e.g. if your class has member fields that implement <code>IDisposable</code> so you need to provide a <code>Dispose</code> method call <code>Dispose</code> on the member fields.<br /><br />The simplest guideline regarding the use of finalizers is: <em>don't use it at all</em> unless your class directly wraps unmanaged resources (such as a native file handle) and you want to make sure that <code>Dispose</code> gets called at some point, which really almost never happens in a typical ASP.NET application. Don't create empty finalizers.<br /><br />A class implementing <code>IDisposable</code> doesn't always require a finalizer, but a class that implements a finalizer should always implement <code>IDisposable</code>.<br /><br />This was just my interpretation of the GC process. For a more complete and accurate description, see Jeffrey Richter's book "CLR via C#".<br /><br />Also see:<br /><ul><br /><li><a href="http://msdn.microsoft.com/msdnmag/issues/04/05/NETMatters/">.NET Matters: Finalizers, Assembly Names, MethodInfo, and More</a></li><br /><li><a href="http://dn.codegear.com/article/29365">Object Destructors and Finalizers in .NET Using C# and Delphi for .NET</a></li><br /><li><a href="http://www.devx.com/dotnet/Article/33167/0/page/1">When and How to Use Dispose and Finalize in C#</a></li></ul>Returning a byte array from C++ to Visual Basic 62008-02-06T06:17:00+00:00http://codeblast.com/2008/02/06/i-had-to-figure-out-how-to-return-byteI had to figure out how to return a byte array from a C++ DLL to VB6 (using unmanaged C++ in Visual Studio 2005).<br /><br />This is the general idea:<br /><br /><pre>__declspec(dllexport) int __stdcall modifyArrayTest(SAFEARRAY** fileData)<br />{<br /> HRESULT hr;<br /> SAFEARRAYBOUND bound[1];<br /> if (*fileData != NULL)<br /> {<br /> TCHAR msg[128];<br /> _stprintf(msg, "Received %lu byte array, destroying it and reallocating", (*fileData)->rgsabound[0].cElements);<br /> OutputDebugString(msg);<br /> SafeArrayDestroy(*fileData);<br /> }<br /> else<br /> {<br /> OutputDebugString("Received null array, reallocating");<br /> }<br /> bound[0].cElements = 10; // 10 byte array<br /> bound[0].lLbound = 0;<br /> *fileData = SafeArrayCreate(VT_UI1, 1, bound);<br /> hr = SafeArrayLock(*fileData);<br /> if (hr)<br /> {<br /> OutputDebugString("SafeArrayLock failed");<br /> return -1;<br /> }<br /> unsigned char *data = (unsigned char*)(*fileData)->pvData;<br /> for (int n = 0; n < 10; n++)<br /> {<br /> data[n] = n;<br /> }<br /> SafeArrayUnlock(*fileData);<br /> return 0;<br />}</pre><br /><br />Now the function is imported as follows in VB6:<br /><br /><code>Private Declare Function modifyArrayTest _<br />Lib "ArrayTest.dll" (ByRef a() As Byte) As Long</code><br /><br />And used like this:<br /><br /><code>Dim data() as Byte<br />Dim returnedBytes as Long<br />Call modifyArrayTest(data)<br />returnedBytes = UBound(data) + 1</code><br /><br />Notes:<br /><ul><li>I found it useful to use OutputDebugString to log debug messages in my DLL code and then using <a href="http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx">DebugView</a> from SysInternals to view the messages.</li><li>I noticed the DLL has to be compiled using ANSI (i.e. Character Set = Not Set) instead of Unicode (the default) to be able to pass strings back to VB6.</li></ul>Reference: <a href="http://vb.mvps.org/tips/vb5dll.asp"><span style="font-family: Courier New,Courier;">VB5DLL.TXT</span></a>Testing SSL and Certificate Authentication using makecert2008-01-10T14:10:00+00:00http://codeblast.com/2008/01/10/testing-ssl-and-certificate<blockquote></blockquote>I wanted to set up a development environment, all on my local PC, that would allow me to do Certificate Authentication in an ASP.NET application.<br /><br />Tools used:<br /><ul><li>IIS 5.1 / Windows XP</li><li>Web browser: IE 6.0</li><li>IIS Resources / WFetch for troubleshooting HTTP issues</li></ul>The first step is to set up SSL on IIS. You need a server certificate for this, which you usually get from a Certificate Authority, but for development/testing purposes you just use makecert.exe (installed in the Visual Studio directory).<br /><br />First we create a "Root CA" for our two certificates:<br /><blockquote style="font-family: courier new;">makecert -pe -n "CN=Dev Root Auth" -ss my -sr LocalMachine -a sha1 -sky signature -r "DevRootAuth.cer"</blockquote>Open MMC. Add the Certificates snap-in for Local Computer.<br /><br />Copy and paste the above "Dev Root Auth" certificate from the Personal path to the "Trusted Root Certification Authorities" path. Or use certmgr to copy it:<br /><blockquote style="font-family: courier new;">certmgr -add -all -c "DevRootAuth.cer" -s -r LocalMachine Root</blockquote>Now create the server certificate (to use for SSL), using the first certificate created above as the Issuer:<br /><blockquote style="font-family: courier new;">makecert -pe -n "CN=localhost" -ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -in "Dev Root Auth" -is MY -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 localhost.cer</blockquote>Note the "Extended Key Usage" value of 1.3.6.1.5.5.7.3.1 which indicates that this cert is for Server Authentication.<br /><br />Now enable SSL: open Inetnet Information Services management console. Right-click Default Web Site and go to Properties -> Directory Security -> Server Certificate -> Assign an existing certificate. Select the "localhost" cert. Finish the wizard.<br /><br />You should now be able to access pages on your localhost with HTTPS.<br /><br />For example, create a directory C:\inetpub\wwwroot\SecureTest with a file named Default.aspx containing the following three lines:<br /><blockquote>Cert present: <%=Page.Request.ClientCertificate.IsPresent%><br /><br />Subject: <%=Page.Request.ClientCertificate.Subject%><br /></blockquote>Open now open the file in IE as https://localhost/SecureTest/default.aspx. The output will show:<br /><blockquote>Cert present: False<br />Subject:</blockquote>This verifies HTTPS is working. When you click the padlock icon in Internet Explorer you should see the "localhost" certificate is OK. We're done setting up SSL.<br /><br />The next step is to create the Client Authentication certificate, which IE will pass to IIS to authenticate the user.<br /><blockquote><span style="font-family:courier new;">makecert -pe -n "CN=Test Client, O=Test company, OU=Testing, E=test@test.com, C=ZA" -ss my -sr CurrentUser -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.2 -in "Dev Root Auth" -is Root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 testclient.cer</span><br /></blockquote>Note this time the Extended Key Usage value is 1.3.6.1.5.5.7.3.2 which indicates that this cert is for Client Authentication.<br /><br />The Subject string (-n parameter) must conform to the X.500 distinguished names standard. See <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC2253</a> for a description of the possible X.500 attributes. You can also use E to specify an email address. I found that the UID attribute doesn't work with makecert, which is too bad, because it would be nice to be able to assign a custom field to the cert to easily identify the user.<br /><br />You can now configure the SecureTest application in IIS to require Certificate Authentication. In IIS manager, right-click on the SecureTest directory and to Properties -> Directory Security -> Edit. Click "Require secure channel (SSL)". Click "Require client certificates". Click OK and OK again.<br /><br />Now open https://localhost/SecureTest/default.aspx in IE again. This time the output should show:<br /><blockquote>Cert present: True<br />Subject: C=ZA, E=test@test.com, OU=Testing, O=Test company, CN=Test Client</blockquote>This verifies the Certificate Authentication works.<br /><br />To make this more useful, you would use the certificate ("what you have") in your Login screen in addition to (or instead of) a username/password ("what you know") for a two-factor authentication scheme. You could map the client certificate to a Windows user in IIS, or write custom authentication code (e.g. Forms Authentication) using the certificate information to uniquely identify the user... (Although some might argue that using a certificate doesn't mean it's a two-factor scheme).<br /><br />Remember to use WFetch during the whole process to test everything - it's much easier troubleshooting HTTP issues (e.g. to see the HTTP request and response headers and status codes) than just testing with IE.VMWare vmmod.tar missing during installation2007-09-19T11:02:00+00:00http://codeblast.com/2007/09/19/vmware-vmmodtar-missing-duringYesterday I had to reinstall VMWare Workstation 6.0 on my Ubuntu 7.04 PC, and again I got stuck during the installation with the error about vmmod.tar not being found under /usr/lib/vmware/modules/source/<br /><br />The solution is simple and widely publicized but still many people seem to sit with this problem.<br /><br />Just create the /usr/lib/vmware/modules/<span style="font-weight: bold;">source</span>/ directory if necessary, then get the vmware-any-any patch from http://knihovny.cvut.cz/ftp/pub/vmware/ (e.g. vmware-any-any-update113.tar.gz) and run the runme.pl to continue the installation.Oracle treats an empty string as NULL2007-08-23T08:08:00+00:00http://codeblast.com/2007/08/23/oracle-treats-empty-string-as-nullAs a Microsoft SQL / MySQL developer I was surprised to find out today that Oracle doesn't support empty strings in "NOT NULL" fields! This is because Oracle treats an empty string, i.e. '', the same as NULL.<br /><br />Of course this is old news to Oracle users, but even some of my colleagues who'd been using Oracle longer than me were unaware of this.<br /><br />I realized this after trying to figure out why an INSERT statement like the following kept complaining that column B cannot be NULL:<br /><br /><span style="font-family: courier new;">insert into MYTABLE ( A, B ) values ( 'hello', '' )</span><br /><br />I think that's not very clever at all.<br /><br />That means, for example, if your code performs a search on a field, the following can never work:<br /><br />select * from MYTABLE where B = :value<br /><br />if the :value parameter is an empty string, since you'd have to say "where B is null" instead.<br /><br />Google "oracle empty string null" for more descriptions.Wherever I May Roam2006-10-22T19:45:00+00:00http://codeblast.com/2006/10/22/wherever-i-may-roam<span style="color:#cccccc;"><strong>Metallica</strong></span><br /><span style="color:#cccccc;"><strong>Wherever I May Roam </strong><br /><br />...and the road becomes my bride<br />I have stripped of all but pride<br />so in her I do confide<br />and she keeps me satisfied<br />gives me all I need<br /><br />...and with dust in throat I crave<br />only knowledge will I save<br />to the game you stay a slave<br />rover wanderer<br />nomad vagabond<br />call me what you will<br /><br />but I'll take my time anywhere<br />free to speak my mind anywhere<br />and I'll redefine anywhere<br />anywhere I may roam<br />where I lay my head is home<br /><br />...and the earth becomes my throne<br />I adapt to the unknown<br />under wandering stars I've grown<br />by myself but not alone<br /><em><strong>I ask no one </strong></em><br /><br />...and my ties are severed clean<br />the less I have the more I gain<br />off the beaten path I reign<br />rover wanderer<br />nomad vagabond<br />call me what you will<br /><br />but I'll take my time anywhere<br />I'm free to speak my mind anywhere<br />and I'll never mind anywhere<br />anywhere I may roam<br />where I lay my head is home<br /><br />but i'll take my time anywhere<br />free to speak my mind<br />and I'll take my find anywhere<br />anywhere I may roam<br />where I lay my head is home<br /><br />carved upon my stone<br />my body lie, but still I roam<br />wherever I may roam<br /><br /></span><span style="color:#cccccc;"></span>