AutoMapper upgraded to .NET 4 and VS 2010

In the last post, I posed the question on what to do with .NET framework upgrades and OSS support.  I wanted to upgrade AutoMapper to .NET 4, but I didn't want to leave a lot of folks behind because their project isn't .NET 4.  I had a couple of choices:

  • Call the last release (1.1) the last official .NET 3.5 release
  • Branch it and allow both to live side-by-side

Since option #2 didn't really cause me much extra overhead, I went for that one.  To upgrade, I first needed to create a remote branch on github:

image

Creating a remote branch in git is a little esoteric, as for the most part, git wants to be local.  To create this remote branch, I just ran:

  • git push origin origin:refs/heads/NET35

More than a little esoteric, but whatever.  To then start using this remote branch, I needed to create a remote tracking branch to make it easier to push and pull:

  • git checkout –track –b NET35 origin/NET35

And now my local repository has both remote branches being tracked:

image

With both branches going, I now set about upgrading the AutoMapper to .NET 4.

Upgrading the project

Upgrading the AutoMapper code to VS 2010 and .NET 4 was easy enough.  I just opened the VS 2008 solution in VS 2010, and the upgrade wizard properly upgraded everything.  Upgrading the solution files does not change the target framework, so I still needed to modify all of the project files to target .NET 4:

image

That was easy enough, and all tests immediately passed.  I decided to leave the Silverlight 3.0 projects out of the equation, I still need a better way to support multiple runtimes easily.  Some of the app.config files were automatically modified, but there were really no problems upgrading the actual projects to .NET 4.

Upgrading the build, however, was a completely different story.

Upgrading the build

Most of the build tools I used, including NUnit and psake, were still targeting .NET 3.5.  To upgrade these, I first needed to download the latest psake and include the following configuration in my build script:

$framework = '4.0'

This told psake to use the .NET 4 framework.  Next, I needed to tell NUnit to target the .NET 4 framework.  I was able to do this by adding the "supportedRuntime" element:

<startup>
    <requiredRuntime version="v4.0.20506" />
</startup>

I stuck this in my "nunit-console-x86.exe.config" file, where it already had a commented-out section for me to edit.

The last part I needed to fix was the ILMerge call in my build script.  This was much trickier.  I needed to modify the call to ILMerge to include the path to the .NET framework.  Previously, I only needed to include the version.  I created a PS function to get the framework directory:

function Get-FrameworkDirectory()
{
    $([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()
        .Replace("v2.0.50727", "v4.0.30319"))
}

Quite lame, as I get the current runtime path and replace the folder name of the .NET 2 version number with .NET 4.  I'm sure there are better ways, but hey, it works.

Finally, I just created a property to hold this value:

$framework_dir = Get-FrameworkDirectory

And modified the call to ILMerge to include this value:

ilmerge.exe /targetplatform:"v4,$framework_dir"

Once all that was done, I created a second build on the TeamCity CodeBetter build server:

image

That's pretty much it.  It was a little hairy upgrading the build, but that's only because of the tools I use.  If I didn't have Stack Overflow, it would have been much more difficult :)

Support

The idea going forward is to apply pull requests and bug fixes to the .NET 3.5 branch, but not any new feature work.  I'm not going to delete that branch, so anyone wanting to add new features just needs to fork that branch and send pull requests.  Because branches are so easy to manage in github, there's really no reason for me to just kill the .NET 3.5 version.

Otherwise, I'm getting started on the master branch on version 2.0 work.  For those that have forked master and want to now point to the NET35 branch, you can just update your local upstream remote to point to the different branch.

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
Comments are the Devil

I recently read Chris Coyier's article entitled Show Markup in CSS Comments. I was actually a bit angry that so many responses praised this and so few were turned off from the idea. I appreciate the idea of making things easier for working with CSS, but there are just so many better alternatives.

Some were quick to point out that this is a maintenance nightmare. That is my biggest concern with the coding style. Coyier does well to say:

Yes, this would require maintenance. If it doesn’t make it easier for yourself or for the people you are providing the code to, don’t do it.

I'm guessing that those who attempt this "technique" will soon find out that they won't be doing it for long, likely due to the intense headaches it will induce. Coyier also mentions that a tool could be created to automate this. Am I way off here, but isn't there a tool already for this? Another window? Split view? A second (or third) monitor?

Like I mentioned earlier, making things easier is great, but whenever you're considering using comments to make things easier, try again, "Comments are always failures."1

1. Robert Martin - Clean Code

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
This Week in Fail

Last week was a week full of fail. But not the type of fail you might think.

Last week at VSLive Redmond, Microsoft demonstrated a new application framework called LightSwitch. From what I read and saw, LightSwitch is a tool for building small line of business applications for Silverlight and WPF. These applications are constructed using a "point and shoot" interface that allows applications to be built and deployed rapidly.

And this is where the fail happened, but not the type of fail you might think.

The community failed in a big way. How did they fail ? The community FAILED by applying the immediate knee jerk anti-Microsoft sentiment that permeates the air today.

In the post LightSwitch: The Return Of The Secretary, Ayende Rahien,  immediately criticized LightSwitch without (though he did disclose in his post) every laying his hands on the tool. He went as far as making suppositions about stuff that he claims will probably not work well. How can he make these assertions w/o real examination of the tool ?

Later I found another post from Donald Belcham: Microsoft.Data.dll and LightSwitch. In this post Donald talks about small line of business applications that eventually need to "grow up" and become "real" software projects. These applications are/were built in tools like Microsoft Access and Excel and served a critical need of business users in companies large and small. Yes these applications get built and they eventually might become part of the lethargic swamp that defines the standard of most IT shops today. He concludes his post with the statement:

"To the professional developers that read this blog (most of you I'm guessing), prepare to move your hatred and loathing from MS Access to LightSwitch."

His sentiment might come to be a reality but how can such a bold assertion be made without ever using the tool first hand ?

And this is where the community failed. Some leaders of the community failed because they spouted criticisms of a tool they have no first hand experience with. The community at large fails because we continue to put up with un-intellectual kneed jerk reactions from our leaders.

As a community we need to have higher standards. We need to do our homework, criticize and comment from a position of intellectual pursuit and research, and finally we need to leave our bias at the door.

 

There is no substitute for face-to-face reporting and research.

Thomas Friedman

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
Database indexes are your friend

I guess I assumed that creating a foreign key constraint would automatically create a non-clustered index.  I mean, a primary key is a clustered index, why wouldn't a foreign key also create an index?

A batch process today slowed from completing in about 4 hours to an estimated completion time of around 3 days.  Since this was a process that needed to complete daily, well obviously it should complete in less than a day.  First order of business was looking at the profiler to see what was going on.

It was exactly one SELECT statement per transaction, no joins, and one predicate in the WHERE clause, on a foreign key.  And it took an average of 23 seconds to execute.  Yikes.

Next up was checking the execution plan and statistics.  This was on a table that doubled in size in one day, to 7 million rows.  The culprit naturally was a table scan, and the 230K reads showed why the query took so long.  A coworker pointed out that the statistics plan also provided a hint for performance tuning, to add an index.

I really couldn't believe the foreign key didn't have an index, but sure enough, it didn't.  Added the index on the foreign key, and the query time was reduced from 23 seconds to nearly instantaneous, 2-3 orders of magnitude better.

And that 4 hour batch process?  It finished in about 5 minutes.

Yes, database indexes are your friend.  Assuming database indexes are already in place, not your friend.

*sigh*

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
Silverlight UI testing with Selenium and Ruby

I've described before how we use Watir and Ruby at work to drive our UI tests and it's an acceptable solution if you work on a Windows platform. In my other life, however, I work on a Linux system and Watir, although they claim the software works, actually doesn't. Oh, I'm sure Watir works just fine, but the plugin they require you to install on Firefox does not... This means that the acceptable solution I use at work is not so acceptable at home.

Enter Selenium, which at first glance seems to be a more powerful way to do UI testing and actually works great.

The way I've used it is as follows:

  • a selenium-server process runs in the background and listens for commands
  • a cheap web server is running, ready to serve up a test page that contains a Moonlight (Silverlight) control
  • a ruby script is written using the rspec and selenium-client gems. Once launched, it'll connect to the selenium server and issue commands

My, that's a lot of moving parts! Life ain't easy as a Moonlight developer! First things first: go install Selenium RC. The package is really just a bunch of java files. In there, you will find a selenium-server folder. Start the server with this command, from where the jar file is located:

java -jar selenium-server.jar

Then I go to my bin/Debug folder where my Moonlight solution resides and I use the xsp2 command to start a crude and very basic web server. It listens on port 8080 for web requests and that's about it. The html page I'm telling my test to load further below has been generated by MonoDevelop for me. It created the Moonlight control and the only thing I had to do was to go in there and add an id to the object tag:

<object id="silverlightControl" data="data:application/x-silverlight," type="application    /x-silverlight-2" width="100%" height="100%">

So the object id is "silverlightControl", which I'm going to need in a bit. If you're on Windows, Visual Studio will generate a page very similar to the one I got. It might even have named the silverlight object tag for you, so just take note of its name if that's the case. I'm not fully aware of any simple web servers you guys can use on Windows. If you know of one, let me know in the comments! We use IIS at work, but that might be overkill for this simple web app.

My Moonlight app is very minimal:

[ScriptableType]
public partial class Page : UserControl
{
    public Page ()
    {
        this.InitializeComponent ();
        Loaded += new RoutedEventHandler(Page_Loaded);
    }
       
    void Page_Loaded(object o, EventArgs e)
    {
        HtmlPage.RegisterScriptableObject("MainView", this);
    }
       
    [ScriptableMember]
    public void test(string text)
    {
        TextBox.Text = text;
    }
}

The important thing to see in the code above is the inclusion of the ScriptableType attribute on the class, the ScriptableMember attribute on the test method, and the fact that the class must be registered as a scriptable object. This simply makes your scriptable methods accessible through JavaScript, as we'll see in just a bit. Just note that we are calling the class "MainView" in our registration.

So you've got your web server running and selenium-server is waiting impatiently for some testing goodness. We're almost there! Here is the ruby script I'm using for the test (which actually doesn't test anything, it'll just call the test scriptable method and change the text in the text box...)

  1 require 'selenium/client'
  2 require 'selenium/rspec/spec_helper'
  3 require 'spec'
  4
  5 describe "test" do
  6     attr_reader :browser
  7     alias :page :browser
  8
  9     before :all do
 10         @browser = Selenium::Client::Driver.new(
 11             :host => 'localhost',
 12             :port => 4444,
 13             :browser => '*firefox',
 14             :url => 'http://localhost:8080/',
 15             :timeout_in_second => 90)
 16     end
 17
 18     before(:each) do
 19         page.start_new_browser_session
 20     end
 21
 22     append_after(:each) do
 23         page.close_current_browser_session
 24     end
 25
 26     it "test" do
 27         page.open("TestPage.html")
 28         sleep(2)
 29
 30         code = "var control = window.document.getElementById('silverlightControl');
 31                      control.Content.MainView.test('it works!!!');"
 32
 33         page.get_eval(code)
 34     end
 35 end   

The first thing this does is connect to the selenium server, which will start Firefox and connect to the web server. It'll then load up TestPage.html and run some JavaScript. In the Selenium docs, they mention that any JavaScript is run within their own context, which is why you need to use "window.document" instead of the more straight up "document". It grabs control of the silverlight control and calls the test method, passing "it works!!!" as parameter.

In order for this to work, you'll have to install the rspec and selenium-client gems, then type

spec test.rb

from the command line, assuming you named your ruby test file "test.rb".

All in all, this is a good first step. Now I'd like to create a C# layer, or driver, which will allow me to grab control of any Moonlight objects. I believe this has been solved before and I need to investigate some more. At least, the first step is done. Testability has been achieved. Stay tuned!

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
Three Simple Steps to Improve Your Writing

Technical books are longer than they ought to be. Most software books could be improved by shedding a tenth of their heft. It's a product of market pressures, of course: Tech books need to get to market fast, which does not allow for the time-consuming labor of honing and refining a text until it is lean and tight. I have a few simple strategies, though—simple tips that provide a disproportionately beneficial return on a trivial time investment. You can use the following tips to improve your blog posts, books, and presentations.

Replace "basically" with nothing.

This word never adds value. It is usually a manifestation of the author's or speaker's unconscious concern that what he is explaining is too complex. If time allows, revise the material until your readers don't need extra convincing that it is basic. At least get rid of the useless word.

You could have some fun writing a regular expression to correct all instances with a global search-and-replace. If you're amused by the challenge, please feel free to post your regex in the comments. You'd be helping all of us.

Here are the replacements your regex would need to catch:

FindResult
Basically, it can start a sentence. It can start a sentence.
Basically people leave off the comma, too. People leave off the comma, too.
It can basically appear in the middle. It can appear in the middle.
It can, basically, be set off with commas. It can be set off with commas.
It can end a sentence, basically. It can end a sentence.
It might end without a comma basically. It might end without a comma.

Replace "essentially" with nothing.

As above.

Replace "is nothing more than" with "is."

The "is nothing more than" construction falls in the category of noisy hedge words. It's a large category. Folks add words to forestall arguments. Even though it sounds romantically brash—X is nothing but Y, #wristforehead—it actually weakens the association between the subject and its predicate nominative. Be clear; be bold. If you're trying to define X by saying that it is Y, say that X is Y.

I wish the industry allowed more time for editing. I wish I were able to help more people express their ideas. Good editing is liberating, plucking the brambles and cruft off a passage until its central theme floats to the fore—getting the text out of the way of the writing.

I hope you find these tips helpful and easy to implement. Ruthlessly delete useless clutter like "basically," "essentially," and "nothing more than." Let your ideas stand tall.

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
Knowing when to ask

It doesn't matter how much experience you have, what your title is, or whether you are considered a leader in the team / project / company. If you don't know yourself and when you need to ask questions, you're going to be in trouble. You must be able to evaluate your own perspective and whether or not you are stuck down in the weeds or not.

 

I'm mapping individual trees, not surveying the forest

I just got off the phone with a coworker who is the 'point person' on a new feature set. I called him and asked for advice on two separate issues related to the piece that I am currently working on. 1) a design problem with the workflow, and 2) whether or not i should "do it right" or "get it done".

My own perspective and involvement in the process had led me down into the weeds of implementation detail where I needed to be. I recognized an issue in the implementation that was causing problems with the workflow. I also recognized that my current depth and focus were preventing me from seeing the big picture (schedule, budget, etc). My reaction to the design problem was one of "do it right" because I was focused entirely on the implementation issues at hand. I knew that I needed a higher level perspective to understand whether or not "do it right" was the correct response, though. So, I called up my coworker and asked for help. We discovered two possible solutions through the conversation. One of them was "the right way" to make the code conform to all of the principles and patterns that we try to use. The other was "well, you could just do this and get it done without a major rewrite", ignoring many of those principles.

 

Lose the ego and the pride

In the end, I was not capable of making the decision to "do it right" or "get it done" because I was too far down in the weeds of implementation detail. I needed a different perspective and advice on how to proceed and I found that perspective by asking questions and seeking advice. 

I don't care about my title, role, or over-arching responsibilities on the team, the project or within the company. It would have been irresponsible of me to assume that I could make the decision on my own at that point in time. This does not mean that I always have to seek advice and others' perspectives. It only means I know when I need to seek advice and others' perspectives. It also creates opportunities for me to take the opposite role on a regular basis. I am often the person with the high level perspective who is capable of providing advice on whether or not someone else can take the time to "do it right" vs "get it done". And because I know when to ask and I do ask when I need to, others are also willing to ask because they see that it's ok to ask.

If you refuse to ask; if you don't know when to ask; if you are afraid to ask; you are potentially damaging your career, team and project. Lose the ego, drop your guard and give up your pride for a moment. Learn when and how to ask for the help that you need.

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
Why Hg branches are broken (or at least less useful)

In one picture:

image

In Hg, branches are metadata included in each changeset.  In the operation above, I created a branch, but that only marked the current directory with a branch name.  The branch won't actually show up unless I make a commit.  In fact, if I checkout to another revision, it's as if the "hg branch" command never happened.  When I list the branches, you won't see this new branch name.  The name in the PS window just comes from the PowerShell-Hg extension being smart.

One implication is that our team has to make phantom commits for the branch to officially "show up".  You start to see commits like "phantom commit" early on, then later they start saying "stupid commit".  It's the only way we could get a branch to show up locally and on the server.

In Git, a branch is nothing more than a pointer to a commit, and the commit itself carries no information about a branch name.  A much more flexible model in my experience.

This hit me today when I wanted to move a set of commits to a different branch, which turned out to be very difficult as the branch name was embedded in to the commit names.  Rebasing helped, except that the commits were already pushed to the server.  We wound up having to back out of the commits, even though these were on a different logical branch, simply because our build server got confused about these extra commits that were marked with the wrong branch name.

Perhaps Hg branches aren't broken and this design is intentional.  But it's annoying and less powerful and flexible than Git's more simple model, of just a pointer to a commit.

Side note for the Git folks – I've also wasted 2 hours of my life on Git when my .git folder suddenly went empty – and not from me accidentally deleting anything.  Lost all my dangling topic branches on that one.

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
An effective testing strategy

On a recent large project, we had a goal early on that we didn't want to have a lot of QA folks manually testing our software.  Finding bugs through manual testing is incredibly time consuming and expensive, so we opted to try and build as much quality in to the product.  That's not to say that manual testing doesn't have its place, as humans are fantastic about using software in ways you didn't expect.

This was a long project, around 18 months, and will continue to have active development in the future.  Very early on we found that a good testing strategy was critical to the success of the project, especially for our team to be able to 1) continue to increase our velocity over time and 2) have the confidence to make both small and large changes in our application.

It took quite a while for us to settle on an effective strategy.  This was mostly because we had to learn how to design our application for testability, in all layers of the application.  Our team were all experienced in TDD before starting the project, but that wasn't the only skill we needed to create an effective testing strategy.

Levels of tests

Categorizing tests can get annoying.  You have functional tests, integration tests, unit tests, acceptance tests, slow tests, fast tests, UI tests, and on and on.  We found that our tests belonged in three main categories:

  • Full-system tests
  • Subcutaneous tests
  • Unit tests

Each of these differs in the scope of what's being tested.  A full-system test exercises the application through the external interface, whether that's a browser, file drop, queue, WinForms app or whatnot.

Subcutaneous tests work at the layer directly below the external user interface.  In the context of a web application, a subcutaneous test in our case would be a form object sent through a command processor, with all the real classes and implementations in place.  We bypassed the Controller, which only contained UI layer logic, straight to the domain layer.  Send in form object, out pops success/failure.

Finally, we had unit tests.  Unit tests are designed to test one class, and can either be fast or slow tests.  Fast tests are the normal TDD tests, used to build out class design.  Test doubles are used as needed, but strictly interaction-based tests have less value unless we find the interactions very interesting.  We also have slow unit tests, which could also be classified as integration tests.  These would be things like repository tests, persistence tests, etc.

Our ratio of unit:subcutaneous:full-system tests hovered around something like 10:2:1.  We ended the project with something around 5000 unit tests, 1000 subcutaneous tests, and 500 full-system tests that used WatiN and Gallio to drive a browser.  The 6000 unit/subcutaneous tests executed in about 10 minutes, while the 500 UI tests completed in about 50 minutes.

Unit testing strategy

Unit tests were developed in a pretty strict TDD manner.  We write tests before any implementation is in place, and use the tests to drive the design of the code.  These tests help identify design issues, encapsulation problems, code smells and so on.

We strived to not write code that existed solely to enable testing.  That often meant that we had a design issue, and responsibilities were misplaced or encapsulation was violated.

As we got further down the pipeline in our project, we started to value interaction tests less and less.  Interaction testing through mocking is only really interesting if you're truly interested about interactions.  But more often, we were more interested in side-effects, and interactions were just an implementation detail.  What we often did instead is mock out slow or untestable pieces, like repositories, facades over external services, configuration classes, etc.  Otherwise, we limited mocking only to places where mocks were the only observation points for what we were interested in.

At some point in large projects, it can become obvious that your design needs a large-level refactoring, to extract out concepts to enable quicker delivery of features.  On our last project, some concepts unearthed included:

  • AutoMapper
  • Processing forms as individual command messages
  • Input builders

With each of these, unit tests were actually a barrier to these refactorings.  But the barrier only existed because we had relied on these tests to capture all of the interesting behavior in our application.  To effectively allow large- and mid-size refactorings, we needed an additional level of testing.

Subcutaneous testing strategy

Subcutaneous tests, like their name implies, test everything just below the surface of the user interface.  In an MVC application, these would be tests for everything just below the controller.  For a web service, everything just below the endpoint.  The idea is that the topmost layer in an application does not perform any actual business logic, but just connect the external interfaces with the underlying services.

Subcutaneous tests are important because we want to be able to test business logic with the entirety of the system in play, with the exception of external connection points such as the user interface and external services.  While a unit test focuses on small-scale design, a subcutaneous test does not address design, but instead tests basic inputs and outputs of the system as a whole.

To build effective subcutaneous tests, we can try and build uniform pinch points through which common logic flows.  For example, we might build a command message handling system, or a common query interface.  In a recent project that processed batch files, each row in the file was transformed into a message.  We could then craft a message, send it through the system, and then verify all the side effects of processing that message.

Because subcutaneous tests address high-level behavior, rather than design, they are ideal for scenario-based testing strategies such as BDD or the Testcase Class per Fixture pattern.  If we want to be able to perform large refactorings, we need these high-level tests to create that wide-cast safety net for business behavior.  Subcutaneous tests are also great target points for calling features done, as they focus on more end-to-end logic.

While subcutaneous tests allow us to safely perform larger refactorings, they still do not provide a satisfactory level of confidence that our system will work in production.

Full system testing strategy

Our team originally called these tests "UI tests", until more and more of our projects entailed integration strategies where the inputs to our system weren't a browser, but instead messages, a REST endpoint, or FTP drops and batch file processing.  UI testing is a subset of full system testing.  The idea behind a full system test is that we want to test our software as it might be used in production.  For an MVC application, these would be browser-based tests.  For batch files, we would use actual files.  REST, actual HTTP requests.  Messages, real queues and messages.

If we want to know if our application works as expected, before it goes to production, one effective and efficient way to do so is to create an automated test that exercises the full system.  If my UI tests logs in to the application, places an order and I can verify that an order request was generated, I'm feeling pretty good about things.

One common misconception about full system tests is that they are black box tests.  While these have their merit, full system tests should have intimate knowledge about what's going on underneath the covers.  In fact, full system tests can even take advantage of the domain model to build up data, instead of a back-door system built solely for testing purposes.  One big mistake teams run in to is not following the same code paths in testing as they do in production, leading to wacky invalid, impossible states of the system.

In our projects, a full system test is the last code we write before we call a feature/story done, done, done.  Manual testing is just too expensive and unreliable for characterizing "done-ness" of a feature, but if I can do the exact same actions as would happen in production through the exact same external interfaces, that's success.

A holistic approach

In an application without tests, we've actually found it most valuable to start with full system testing, moving down towards unit tests as a means of a strategy for coverage.  We cast the widest net possible, but the simplest assertions first, then slowly move down towards unit-level logic.  In new applications, we tend not to focus on any one area, as all of these tests are critical to us for long-term maintainability of a system.

This testing strategy does require a level of investment.  We've found this holistic approach especially effective when we know that this application is critical to our client's business.  If an application is critical to business, it's going to require change.  If it's going to require change, we better be able to safely change it without affecting our client's business.

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
posh-git Release v0.2

I just tagged the v0.2 release of posh-git, which you can download here. This is the last release supporing msysgit 1.6.5 and 1.7.0. In this release...

PowerShell Module

Thanks to a contribution from David Muhundro, posh-git now exposes its functions through a module (.psm1). The module exposes a number of functions whose usage can be seen in the example profile.

Tab Expansion Updates

  • TortoiseGit commands: tgit <tab>
  • git-svn operations: git svn <tab>
  • Stash completion for git stash operations: show, apply, drop, pop, branch
  • Branch completion for git reset and git rebase
  • Completion of deleted files for git rm
  • For most commands, tab completion should now work if other command flags are in use. For example, git rebase -i <tab> works as expected.

Thanks to Jeremy Skinner and Mark Embling for their contributions to this release.

Next Steps

The most common complaint about posh-git is performance, which has already been addressed for the next release (available in my master branch). However, the fix requires taking a dependency on msysgit 1.7.1, which has not been officially released yet.  Still, it has been working fine for me.

Beyond that, we still need to address the first two items on my list from the last release...

  • Testing! I'd like to figure out a way to run some integration tests that verify a given repository state renders the expected prompt. If you have suggestions how to approach this, or know how other Git integration projects are tested, please let us know over at the Google Group.
  • Documentation! How to get started, what the project provides, etc.

If you have any other feature requests or find issues, please let us know.

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
Use gitk to understand git

Moving from subversion to git can be a struggle, trying to understand what terms like checkout, commit, branch, remote, rebase all mean in the git world. I learned by experimenting in a demo repository, trying out various commands, and using gitk to visualize their impact. This post is broken up into two parts – after reading this, you may want to read the second part.

The gitk screen

I created a simple repository on github to walk through some scenarios. I'll start by creating a local copy of the repository:

d:\code>git clone git@github.com:joshuaflanagan/gitk-demo.git
Initialized empty Git repository in d:/code/gitk-demo/.git/
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 9 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (9/9), done.

d:\code>cd gitk-demo

d:\code\gitk-demo>gitk --all

gitk overview

There is a lot of information in this single screenshot:

  1. The upper left pane shows the series of commits to this repository, with the most recent on top.
  2. There have been three commits, all by Tony Stark.
  3. The commit message for the most recent commit was "third commit"
  4. There is a single local branch, named "master'", it points to the most recent commit
  5. There is a single remote reference branch: the "master" branch from the remote repository named "origin", it also points to the most recent commit
  6. The yellow dot next to the top commit indicates that is the snapshot currently in my working folder (referred to as HEAD)
  7. I've highlighted the second commit, so that I can see its details in the lower pane
  8. The commit SHA (unique identifier, similar to subversion revision number) of the second commit is 3d024dd9e4a83d8c6a9a143a68b75d4b872115a6
  9. The lower right shows the list of files impacted by the second commit
  10. The lower left shows the commit details, including the full diff
  11. Clicking a file in the lower right pane scrolls the diff in the lower left pane to the corresponding section

A note about "master" and "origin"

When you first create a git repository, it starts with a single branch named "master". There is nothing special about this branch, other than it is the default. You are free to create a new one, and delete master (although, I don't see any reason to go against the default convention).

When you first clone a git repository, git will automatically create a remote for you named "origin". A remote is just a name used to manage references (URLs) to other repositories. There is nothing special about the "origin" remote, other than it is created for you. You are free to create a new one and delete origin. In fact, if you are working with multiple remotes, I recommend you delete the origin remote and create a new one for the same repository, but using a more descriptive name. For example, when I work with the FubuMVC source code, in my local repository I have a remote named "darth" which refers to the main repository owned by DarthFubuMVC, and a remote named "josh", which refers to my fork. If I had kept the name "origin", I would always have to remember which one I cloned from.

Branching

What happens when I create a branch?

d:\code\gitk-demo>git branch issue123

Press CTRL-F5 in the gitk window to refresh the repository view

created branch

We see the new branch marker for the issue123 branch points to the same commit as master and origina/master. It is important to note that the "master" is bold, indicating that is still the current branch. The bold branch label is equivalent to the asterisk in the command line output:

d:\code\gitk-demo>git branch
  issue123
* master

Now if I switch to the new branch and refresh gitk:

d:\code\gitk-demo>git checkout issue123
Switched to branch 'issue123'

(We're going to focus on information in the top pane from now on, so I'll hide the bottom part of gitk)

changed branch

Note: For convenience, I could have created and switched to the new branch in a single command: git checkout –b issue123

Making changes

When I refer to the "current branch", I mean "the branch that will advance when I perform a commit". This is where the gitk visualization really starts to help. I'll make some changes to a file and then commit with the message "My first commit":

d:\code\gitk-demo>git commit -am "My first commit"
[issue123 f948bf8] My first commit
 1 files changed, 2 insertions(+), 1 deletions(-)
Commit moves current branch pointer 

The issue123 branch now points to my new commit. Neither the master nor origin/master branch pointers have moved.

As I continue to commit, the current branch pointer moves with me:

d:\code\gitk-demo>git commit -am "Added another fruit"
[issue123 cac3c72] Added another fruit
 1 files changed, 1 insertions(+), 0 deletions(-)

More commits move current branch

But I thought it was a branch

Since I was working in a branch, I expected to see a tree stucture, with nodes turning off from the main "trunk". Something like this:

Expected branch visualization

Instead, gitk shows all of the commits as a single straight line. When first using git, this was very confusing to me. My confusion stemmed from my misunderstanding of branches in git. Thinking about why gitk was showing all of the commits in a straight line finally brought the point home. In git, a branch is a label for a commit. The label moves to new commits as they are created. When you create a git branch, you are not changing anything in the structure of the repository or the source tree. You are just creating a new label.

Fast forward

After completing my work in the issue123 branch, I'll want to merge the changes back into master. Usually when I think of a merge, I think of comparing two trees and applying the differences from one onto the other. I imagine each commit being replayed on the other branch. Merging issue123 into master would require applying each of my two commits to the master branch. However, this work has already been done, when I first performed the commits. Because the master label hasn't moved since my work began on issue123, applying the diffs would end up with the same result. This is where the "single straight line" visualization really proves valuable – I can see that issue123 is directly ahead of master. Git is smart enough to recognize this situation and performs what it calls a fast-forward merge. A fast-forward merge isn't really a merge at all - since no file content comparisons are necessary – it simply moves the master branch label up to point to the commit pointed at by the issue123 label.

To merge the changes from issue123 into master, I first checkout (switch to) the master branch and then do the merge:

d:\code\gitk-demo>git checkout master
Switched to branch 'master'

Back on master, preparing for merge 

d:\code\gitk-demo>git merge issue123
Updating bf37c64..cac3c72
Fast-forward
 fruits.txt     |    1 +
 vegetables.txt |    3 ++-
 2 files changed, 3 insertions(+), 1 deletions(-)

After fast forward merge

A few things to notice:

  • The command-line output indicated the merge was a "Fast-forward".
  • A new commit was not created. There is no new snapshot of the repository required, since there is no new version of any files/folders that didn't already exist in the repository.
  • The remote origin/master branch has not moved. Everything we've done so far (except for the initial clone) has run completely locally, without contacting the github server.

Deleting a branch

The issue123 branch label is now redundant, since it points to the same commit as master. If there is no more work to do for issue123, we can safely get rid of the branch, without losing any historical information. If we later find out we need to make some changes to solve the issue, we can always create another branch (which is just a label). This is what it means when people say that branching in git is easy or lightweight.

d:\code\gitk-demo>git branch -d issue123
Deleted branch issue123 (was cac3c72).
After branch deleted 

Sharing with the world

As noted above, everything we've done so far has been in our local copy of the repository. The "master" branch at the "origin" remote has not moved. If I look at the github page for the repo, I can confirm that none of my commits exist.

Commit History on GitHub

To copy changes from my instance of the repository up to github's servers, I need to push from my master branch to the "master" branch of my remote named "origin".

d:\code\gitk-demo>git push origin master
Counting objects: 9, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 609 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:joshuaflanagan/gitk-demo.git
   bf37c64..cac3c72  master –> master

After push

Take note of the SHA1 ID of the latest commit, cac3c723.... Look back at the previous screenshots and notice that this identifier has not changed through all of the operations (merge, deleting the branch, etc). When we refresh the github page, we can see it has updated with all of the work I did locally. Notice the commit identifier on the web page matches up with the SHA1 ID we see locally. Also, there is no indication that any of the work was done on a separate branch – nobody ever needs to know. You are free to branch as much as you want locally without impacting a shared repository.

Commit History on GitHub after push

 

To be continued

Continue to part 2 to see the difference between merge and rebase.

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
Use gitk to understand git – merge and rebase

This is the second part of my Use gitk to understand git post.

In my initial overview, I demonstrated creating a branch, making a couple commits to that branch, and then merging them back into master. In that scenario, there were no changes in my local master (and since it was contrived, I knew there were no changes in the remote origin/master), so the merge was really just a fast-forward. In the real world, my workflow would be slightly different, as I would have to account for other people making changes to our shared repository (my origin remote).

To demonstrate, I'll rewind time and pretend we're back at the moment where we switched to master as we prepared to merge in the changes from the issue123 branch. The gitk visualization of the repository looked like:

Just before merging issue123 into master

Before I merge my changes into master, I want to make sure my master branch is in synch with the central repository on github (which I refer to using the remote "origin"). We can see in the screenshot that my master branch refers to the same commit as origin/master, but that's because I haven't communicated with origin in a long time. All of my previous operations were done locally. In order to get the latest state from the remote repository, I need to perform a fetch.

d:\code\gitk-demo>git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From github.com:joshuaflanagan/gitk-demo
   bf37c64..ec8d10f  master     -> origin/master

new changes from remote

I've downloaded new commits to my local repository and moved the remote branch pointer, but I haven't changed anything in my local branches. If I were to look in my working folder, I would see that none of my files have changed. To get the latest changes to the master branch from Tony, I need to merge them into my master branch.

d:\code\gitk-demo>git merge origin/master
Updating bf37c64..ec8d10f
Fast-forward
 dairy.txt |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 dairy.txt
After merging in remote x

Once again, since there was a straight line from my local master to origin/master, git was able to perform a fast-forward merge. The master branch has moved to point to Tony's latest commit. My working directory has been updated accordingly to have the changes he made.

Note that none of the changes I made for issue123 have been included in master yet. We need to merge the issue123 branch back into master, and ultimately push them to the shared repository on github. However, there is no straight line between issue123 and master – neither is a direct descendent of the other – which means we cannot do a fast-forward merge. We have to do either a "real" merge, or rebase.

Merge

To perform a "real" merge, we just use the merge command as we have all along. Doing a fast-forward vs. a real merge is handled by git – not something you specify.

d:\code\gitk-demo>git merge issue123
Merge made by recursive.
 fruits.txt     |    1 +
 vegetables.txt |    3 ++-
 2 files changed, 3 insertions(+), 1 deletions(-)

After merge

Previously with our fast-forward merges, no new commits were created – git just moved branch pointers. In this case, since there is a new snapshot of the repository that never existed before (includes Tony's new changes, as well as my changes from issue123), a new commit is required. The commit is automatically created with an auto-generated commit message indicating it was a merge. The merge commit has multiple ancestors (indicated by the red line going to the "Forgot the yogurt" commit" and the blue line going to the "Added another fruit" commit). We can safely delete the issue123 branch now, but unlike in the fast-forward example, when we push our changes to the central server, there will be evidence that the issue123 message existed (in the merge commit message, and the repository history shows the branched paths).

d:\code\gitk-demo>git branch -d issue123
Deleted branch issue123 (was cac3c72).

d:\code\gitk-demo>git push origin master
Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (8/8), 914 bytes, done.
Total 8 (delta 0), reused 0 (delta 0)
To git@github.com:joshuaflanagan/gitk-demo.git
   ec8d10f..5835415  master –> master

After pushing merge to github

Commit History after merge

Rebase

There are a few reasons not to like the merge approach:

  • Branching paths in the history can be harder to understand. Output from historical analysis operations (log, blame, etc) gets more complicated.
  • The extra merge commit.
  • Your branch is now no longer a private, local concern. Everyone now knows that you worked in an issue123 branch. Why should they care?

Git rebase solves all these problems. If you have commits that have never been shared with anyone else, you can have git re-write them with a different starting point. If we go back in time to the point right after we merged in Tony's changes, but before merging in issue123:

Before rebase

Currently, the issue123 commits branch off from the "third commit". The rest of the world doesn't need to know that is where we started our work. We can re-write history so that it appears like we started our work from Tony's latest changes. We want the issue123 commits to branch off from master, the "Forgot the yogurt" commit.

d:\code\gitk-demo>git checkout issue123
Switched to branch 'issue123'

d:\code\gitk-demo>git rebase master
First, rewinding head to replay your work on top of it...
Applying: My first commit
Applying: Added another fruit

After rebase

After a rebase, the "My first commit" now directly follows the "Forgot the yogurt"" commit, making the issue123 branch a direct descendent of the master branch. This means we can now do a fast-forward merge to bring issue123's changes into master.

d:\code\gitk-demo>git checkout master
Switched to branch 'master'

d:\code\gitk-demo>git merge issue123
Updating ec8d10f..b5a86d6
Fast-forward
 fruits.txt     |    1 +
 vegetables.txt |    3 ++-
 2 files changed, 3 insertions(+), 1 deletions(-)

No merge commit required after rebase

When we delete the issue123 branch and push these changes to the remote repository on github, there is no longer any evidence that the issue123 branch ever existed. Anyone that pulls down the repository will see a completely linear history, making it easier to understand.

d:\code\gitk-demo>git branch -d issue123
Deleted branch issue123 (was b5a86d6).

d:\code\gitk-demo>git push origin master
Counting objects: 9, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 626 bytes, done.
Total 6 (delta 1), reused 0 (delta 0)
To git@github.com:joshuaflanagan/gitk-demo.git
   ec8d10f..b5a86d6  master –> master
Pushed to remote x

Commit History after rebase

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
A quick primer on .NET web frameworks

Update: Much to my embarrassment, I forgot to mention OpenRasta!

I've received quite a few questions in the past months and year about web frameworks for .NET (some confusion around the difference between WebForms, ASP.NET MVC, FubuMVC, ASP.NET in general, etc).  So I thought I'd make a quick blog post giving some real basic explanations of these frameworks, what the intended audience is for each, and what the strengths and weaknesses are of each.

Note: This is not an exhaustive list. It does not include all the frameworks that are out there. There are many good ones for .NET each with their own particular take on the matter. If you're shopping for a framework, please do your research and only consider this post as one of many resources.

ASP.NET

ASP.NET is more of a foundational framework. I wouldn't recommend developing a whole app directly against ASP.NET itself. All the frameworks mentioned below are built on TOP of ASP.NET and provide greater convenience and accelerators for making web development easier.  While it is possible to build an entire web application directly using ASP.NET HttpModules and HttpHandlers, I wouldn't recommend it. It's somewhat similar to doing Assembly language programming, but for the web.

Knowing and being familiar with the libraries, services, and facilities that ASP.NET provides is critical for doing development with any of the frameworks mentioned below.  So I highly recommend that you study ASP.NET, read documentation, examples, articles, and books on the subject.

ASP.NET Web Forms

ASP.NET Web Forms was developed at the same time as ASP.NET and was meant to be the primary framework for developers moving from VB6 and ASP (VBScript/JScript) development to the .NET framework.  Web Forms was intended to make web programming a familiar experience for VB6 developers who were used to Windows application event-driven development (i.e. Button1_Click events) and who were used to building user interfaces on designer surfaces by dragging and dropping controls.  Web Forms has some strengths in that it's been around for awhile, it's fairly comprehensive, and it's approachable for many developers.  While you might at first thing that this is a strength, Web Forms' greatest weakness is that it too abstracts the developer from the underlying realities of stateless HTTP-based web development.  Many critical aspects of web development are managed for the developer (sometimes in sub-optimal ways) leaving the web developer into problems when trying to anything outside of the normal Web Forms development path.

Web Forms has its place (for example, in small IT shops where the developer isn't a full-time developer and just needs to quickly assemble a forms-over-data application).  For any serious web development effort, however, I would consider the friction and hand-tying effects of Web Forms too great to bear and so therefore I don't recommend Web Forms for most development scenarios for .NET.

ASP.NET Web Forms is commercial closed-source, built by Microsoft and is still under active development. However, development has slowed recently in favor of the newer ASP.NET MVC framework.

Castle MonoRail

Castle MonoRail is an open source framework that was built, in large part, due to frustrations that web developers in .NET experienced with Web Forms – especially after having worked with several non-.NET frameworks and seeing how much easier many tasks were to perform.  MonoRail is still actively maintained and there are many production deployments using it as the core web framework. MonoRail can use various "view engines" including the "Web Forms" view engine, Brail, NVelocity, and others.  Its strengths are that it is a comprehensive framework, it fits well within the whole Castle family of projects, and allows for much more freedom than Web Forms.  It's weaknesses include being fairly different from other forms of ASP.NET-based development (which some might consider a strength, so weigh this for your own team), and it has heavy dependence upon other Castle frameworks (which may not be an issue for all teams, but for some it is). 

In the interest of full disclosure, I admit that I don't personally have a lot of experience with MonoRail so I cannot effectively discuss it's strengths and weaknesses.  I know that many colleagues, whom I respect, use MonoRail with great effectiveness. So it is a serious contender and worthy of investigation if you are shopping for a web framework.

MonoRail is open source (contributions welcome).  It is under active development.

OpenRasta

OpenRasta is an open source framework. Their doc page explains it best when it says, "OpenRasta is a resource-oriented framework for .NET enabling easy ReST-ful development of web sites and services."  OpenRasta however does have many MVC features and can serve as a full-fledge web application framework (i.e. it's not *just* a REST framework).  OpenRasta's strengths lie in it's comprehensiveness, wide range of features, active development and support community plus good documentation. OpenRasta's weaknesses are similar to other frameworks in that is not as approachable as Web Forms and is intended for experienced developers. 

Also in the interest of full disclosure, like MonoRail, I don't have a lot of personal experience with OpenRasta and so I cannot effectively discuss it's strengths and weaknesses.  Please investigate for yourself and engage the OpenRasta community for more information.

 

ASP.NET MVC

ASP.NET MVC is another framework built on TOP of ASP.NET (but not on top of Web Forms – MVC is parallel to Web Forms).  ASP.NET MVC was developed by Microsoft in response to complaints of .NET web-based developers who complained about design problems with Web Forms.  While you can mix Web Forms and MVC development in the same project, I wouldn't recommend it unless there was a specific need to do it.  MVC does away with the cumbersome "Page Control Lifecycle" of Web Forms and provides a much more stream-lined approach to web development.  MVC is much closer to the inherent stateless request/response nature of HTTP and so therefore makes it much easier for experienced web developers (and even inexperienced ones) to develop complex web applications.  MVC is less focused on designer-based drag-and-drop programming and more on code-centric programming.  There sometimes is confusion about the difference between ASP.NET MVC and Web Forms because MVC can use *some* parts of Web Forms for presentation.  This is known as the "Web Forms View Engine". There are also other view engines for ASP.NET MVC including Spark and Razor.  This allows you to use ASPX and ASCX files and some runat="server" controls in your views, but without having to have code-behind files and Page Control Lifecycle event handling.   MVC's strengths are similar to MonoRail in that it's fairly comprehensive, and allows a lot more freedom of development and puts the developer back in touch with the fundamentals of web/HTTP programming.  It is well documented and has many guides and a great user community around it.

It shares the same weakness as MonoRail in that MVC is less approachable for less experienced developers.  For more experienced, advanced developers, certain design aspects of MVC can be cumbersome (such as the use of too much inheritance, problematic support for dependency injection and IoC tooling, and too much friction when writing unit tests). These weaknesses are not critical, however, and many good developers are using ASP.NET MVC quite effectively.  ASP.NET MVC is a good contender if you're investigating frameworks and definitely worth some time to spike out some examples.

ASP.NET MVC is commercial open-source (contributions are not accepted, but you can view the source). It is currently in active development by Microsoft and is on its 3rd version.

FubuMVC

FubuMVC is another framework built on top of ASP.NET and sits at the same level ("competes" with if you will) Web Forms, MonoRail, and ASP.NET MVC.  FubuMVC was originally designed in response to the perceived issues (identified in the preceding section) with ASP.NET MVC.  The original designers felt that ASP.NET MVC was good, but didn't go far enough in certain areas to be truly great. FubuMVC uses various view engines like ASP.NET MVC and MonoRail. Currently FubuMVC supports Spark and Web Forms view engines and a Razor engine is being considered.  FubuMVC's strengths include being more IoC/DI and SOLID friendly than ASP.NET MVC.  It's more compositional (versus inheritance-based) which allows for greater freedom for the developer. FubuMVC also has greater support for conventional development saving developers a lot of time in both development and testing by standardizing the aspects of their application that are similar. FubuMVC's weaknesses include the same approachability issue that MonoRail and ASP.NET MVC, but I would say FubuMVC fairs worst in this regard. FubuMVC is designed for advanced, experienced developers.  FubuMVC also has a sore lack of documentation and guides at the moment.  FubuMVC is also not as comprehensive as ASP.NET MVC and MonoRail.  In some respects, FubuMVC has more functionality, but in (many) other respects it still has a ways to go.  Though FubuMVC has a small development team currently, but is gaining ground steadily and growing.

FubuMVC is open source (contributions welcome).  It is under active development.

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
My other blog, and dealing with enterprise software, customizations, and upgrades

I have a few blog posts queued up that relate to the product I'm working on for my day job.  The blog posts are generally product-specific and so (I feel) aren't appropriate for posting on this (my Los Techies) blog as it would be crass marketing.  I think that you, dear reader, did not subscribe to this feed to be marketed to, so I won't offend you like that.  If, for whatever reason, you're interested in what I'm working on, or what my company is working on, you can check out my employee blog, or all the Dovetail blogs.

Having said all that, I just posted a recent post that I thought contained a lot of non-product-specific topics that might benefit you when thinking about problems of customizations, upgrades, frameworks, etc.  So if you can overlook a few mentions of my product, I think the rest of the blog post may be beneficial to you. You can read it here:  Upgrade-Safe Customizations.  Please let me know if you disagree with my assessment.

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology
Getting Started with MonoTouch

Recently, I bought an iPad and decided to try my hand at objective-C. It was a pretty fun experience but as I began to think of apps that I'd actually want to write, I knew of a lot of open-source tools (either written by me or others) that I'd want to use. I definitely didn't want to try re-writing them in objective-c. I had remembered a coworker of mine mentioning MonoTouch to me in the past as a C# compiler for the iPhone so I decided to check it out. Sure enough, they target both the iPhone and iPad. So I decided to download it and give it a try.

This guide is intended to help you get started with a project you can deploy to your device. If you want to simply develop with the simulator, not all of these steps will apply to you. You can simply scroll down to 'Your first Monotouch application' and read from there.

Before We Get Started

There has been a fair amount of concern and discussion regarding the apple developer agreement for iPhone OS 4.0. This had put me off for a while as I didn't want to spend a lot of time working on an app that ultimately wouldn't be approved. Having monitored the community for a few months, it appears that people are still getting their apps approved with regular frequency. This isn't to say that Apple won't one day decide to start rejecting apps -- but it is a promising sign nonetheless. The people at MonoTouch certainly don't think this is the end for their platform, but it's up to you to decide if you want to take the risk. I plan to, not only because I like writing code in C#, but because I want to be able to take advantage of several .NET features supported by MonoTouch -- WCF and Reflection, for example, and because I want to be able to use certain technologies like an IoC container.

Getting Started (what will I need?)

  • A mac
  • XCode
  • MonoDevelop (http://monodevelop.com/Download)
  • MonoTouch (http://monotouch.net/DownloadTrial)
  • An Apple Developer Key (http://developer.apple.com/iphone/index.action)

Once you've downloaded MonoDevelop and MonoTouch and installed them, it's time to get your Apple Developer key. Follow the above link and begin enrollment -- you'll need to select "iPhone Developer Program" as your development program. You'll also need to enter the pertinent required information (billing/contact information). Agree to their developer terms ("I agree to sell my soul to Apple...") and head to their checkout process. The privilege of being an apple developer runs about $99 (plus tax), so be prepared to fork over some money if you want to do anything more than develop on a iPhone or iPad simulator, and if you ever want to put your app on the market. Once you've placed your order, wait for your e-mail to arrive. For me, this took a couple of hours. They say it can take up to 24, so try to be patient.

But to be honest, the process wasn't painless for me. I got my activation code, tried to verify and got this dreadful message:

"We are unable to activate your Apple Developer Program membership."

Unfortunately that set this post back a few days while I waited through the weekend to be able to call up their support number and get things settled. Luckily they said they could resolve it on their side and everything got worked out for me. So, now that I have my key, things can move forward!

Provisioning your apps

Before you can deploy with MonoTouch to your iPhone or iPad, you have to provision your environment for deployment. Apple's process requires a lot of manual work, which I will walk you through below. They also include videos on their site to walk you through it. This will install the necessary keys on your machine that will be used to sign and deploy your code. To begin this process, you will need to go to the iphone developer center (developer.apple.com) and request a certificate. To do this, you first need to make a certificate request from the keychain on your mac.

How to create a certificate request

Go to Finder, then Applications, then Keychain Access. Once this comes up, we'll need to check the preferences. In the menu, go to Keychain Access, and then Preferences. Click the Certificates tab and ensure that both Online Certificate Status Protocol and Certificate Revocation List are set to 'off'. Once this is done, close the preferences window. Now, in the menu, go to Keychain Access, and then Certificate Assistant, and then Request a Certificate from a Certificate Authority. We will use this application to generate a certificate request to submit to Apple.

Put in the e-mail address that you used to sign up for the developer program, and put in your name. Select "save to disk" and "Let me specify key pair information". Click continue and select a location to save the request to. In the next menu, ensure the key size is 2048 bits using the RSA algorithm. Click continue to finish the process.

Requesting a certificate from Apple

Go to the developer portal and select the 'Certificates' menu option on the left. You should see an empty list in the 'Development Tab' and a 'Request Certificate' button. Click the button, and upload the certificate request you generated before. You will be e-mailed a notification from Apple once you have done this. After a short amount of time, your request should be approved. Once it has been approved you should be able to download the certificate from apple. Once you have done this, open the certificate to have it automatically added to your keychain in the Keychain Access program.

Adding your device for deployment and debugging

After you have gotten your certificate approved and added to your keychain, we will need to set up your device for deployment. Attach your iPod, iPad or iPhone to your mac and open iTunes. In the 'Devices' section, select your device to view the summary for it. Click the 'Serial Number' label to reveal your identifier, which we will need to enter into the apple portal. Once you have revealed it, select the 'copy' option in the edit menu. Go to the developer portal and select the 'Devices' link in the left menu. Once the 'Devices' page has loaded, click the 'Add Device' button in the upper left. Enter a name for your device, and then paste the identifier we copied from iTunes. Click submit to add the device. 

After you have added your device, you will need to generate an app ID for your application. App IDs are used for a few different purposes (communicating with hardware, supporting in-app purchases, etc), and is a required part of your application setup. Click on the 'App IDs' link on the left menu, and then click the 'New App ID' button.  You will need to add a decription and then put in your app id suffix. Apple recommend you do a reverse domain setup. Fill in the required fields and click 'submit'.

Once you have completed these steps, you'll be ready to create a provisioning profile. Click the 'provisioning' menu option on the left menu and then 'New Profile' when the page loads. Enter a profile name and then select your certificate, appID and device and click submit. You will be taken back to the provisioning page where you can then download your profile. If the status says 'in progress', give it a minute and refresh the page. Download the profile to your mac.

 

Setting up MonoTouch and your Application for Deployment

Now that you have all the requisite parts, you are ready to set up MonoTouch to deploy to your device. First, you will need to install the provisioning profile you just created. Double-click the profile to open it in XCode. It should automatically be installed from there, and you can close XCode once that is complete. 

Your first MonoTouch application

Until this point we've focused on the logistics of getting everything set up. While this was not strictly necessary if you only wanted to do development with the simulator, it is necessary if you want to deploy your application to your device. Open MonoDevelop and start a new project. Expand the C# section, and select the iPhone and iPad node. Select either the iPhone or iPad window based project (I am using the iPad project). Name your application -- I am naming mine Test Application -- and click the 'Ok' button.

Once your project is set up, you can double-click the MainWindow.xib file to bring up the interface builder. I'm not going to go into too much detail here, but basically you will want to put something on the view to show that your application is starting and displaying correctly. I put a label on the page with "Hello World!" as the text. To run this in the simulator, go to the 'Run' menu item and select 'Run'. It will compile and run the application in the simulator. Cool, huh?

Deploying your app to your device

This is all good and fine, but lets get it deployed on your device! Luckily, MonoTouch should automatically pick up the required information now that it is installed on your mac. But if it doesn't, follow these steps:

Go to the 'Project' menu item, and select your projects options. For me, this is called Test Application Options. If you named your solution differently, it will be different. The options window will open, and under the 'Build' section, click the 'iPhone Bundle Signing' item. Select the identity you set up with apple from the 'Identity' drop down and then select the provisioning profile you set up with apple from the 'Provisioning profile' drop down and click the 'OK' button.

Finally, you will need to set the build configuration to debug|iPhone. This will direct MonoTouch to build and deploy your application. Go to the 'Run' menu option and select 'Run'. You may get a message that says 'codesign wants to sign using key (key name) in your keychain' ... select 'Always Allow'. Once it completes, you will get a window that says the app has been built and deployed to your device. Close this window, and start your device. Scroll to the app and touch it. It should start, and once started, you should see a 'Hello World!' message.

Getting started with MonoTouch is very easy and I am very pleased with how well they integrate MonoDevelop with the interface builder, the device simulator, and the device deployment process. Setting up with Apple is a very tedious process, but I am glad to see they did not carry this over into MonoDevelop or MonoTouch. 

 

If you have any questions or problems, please leave a comment and I will do my best to help out.

Happy coding!

Kick It on DotNetKicks.com



Categories: Computers | CSharp | Dot Net | Los Techies | Programming | Technology