Ivan Porto Carrero

IO(thoughts) flatMap (_.propagandize)

19

Mar
2008

Made Some Changes: The Macbook 5 Weeks In

I’ve been using my macbook as my personal and work pc. So I’ve had windows vista installed on it for all this time. While in the beginning everything seemed to work just fine. This week my vista box didn’t want to move if its live depended on it. So I upgraded my vista install to an XP install. So far the XP machine is heaps faster than the vista box. It has the same software installed as my vista box and yet it works suprisingly better.

The only thing that kept me on vista was IIS7 because I like to use my projects as roots not as virtualdirs. I do most of my development as webdevelopment, but then again it’s rare that I’m working on a project that needs more than one root website, so I let that go.

I care most about speed or lack thereof and in my previous setup it was definitely lack thereof.

So I thought I’d share some of my thoughts around switching.

OSX and windows is the combination that can do it all. I use visual studio with resharper through parallels and with XP it seems to be able to keep up with my typing.

Explorer on Vista is the best file browser I’ve ever used. Finder on OSX is utter crap, the UI is crappy and the UX is just egregious (thanks to sbellware for teaching me this word).

I use paid for and use Pathfinder on my OSX and that is more usable although a bit heavyweight for something that should just enumerate the filesystem.

Somebody didn’t think that menubar through properly because people nowadays use 2 monitors or more, having consistent shortcuts would make this less of an issue.

Consistency on keyboard shortcuts is something I miss but got over it and have a post where I explain what I did to make it work slightly better http://flanders.co.nz/2008/02/07/more-on-mac-keybindings/

And that was about all the bad news I have apart from the fact that my macbook pro can get incredibly hot. This can be remedied to some extent by installing smcfancontrol

Now onto the good news.

Configuration on the filesystem is so much better than having a registry hive that gets corrupted now and again.

The speed of my OSX is great, startup time is much shorter.

The whole experience of organising my personal stuff like photos, music and how it integrates in the OS and other programs is fantastic. I don’t want to go back to a broken model for this.

Sleep just works and i’m not hoping and praying that when i use it my box will recover from it. It’s incredibly light and the battery life of 4 hours without windows running or 2.5 hours with windows running is still very ok for me.

In terms of UI slickness I have to give the advantage to a linux distro with Compiz enabled they give you the freedom to choose how your computer behaves on certain actions instead of no options on windows and 2 choices on OSX.

I don’t think Apple has innovated much on an OS level apart from the Dock. IMHO OSX isn’t perfect but it is really great at its job and stays out of my way.

19

Mar
2008

Made Some Changes: Moved Blogs

First off. Maybe you haven’t noticed but I switched my blogging engine from Subtext to wordpress. I did this not because I think Subtext is bad. I actually liked it, but because of my host. I was hosting my blog with webhost4life. I get a very very modest amount of people over my blog daily but even that wouldn’t work. It doesn’t have anything to do with the blogging engine and everything with them. I tried using that server as a stagingserver for an app I built for a client and in the end we staged it from my pc over and adsl line (NZ to Belgium) and that was faster.

I wasn’t looking forward to moving blogging engines because I don’t want my permalinks to change etc. The whole move was less painful than expected because somebody had already done the work and made a nice write-up. http://www.aaronlerch.com/blog/2007/08/23/breaking-up-moving-blog-engines/

For the moment I’m running wordpress. Everything seems to work ok and I don’t have to restart it 2 or 3 times a day by “changing” my web.config. So in short long live more reliable hosting.

18

Mar
2008

A Status Report on the IronRuby in Action Book

The last couple of months I’ve been fairly busy writing my book. I had a first draft ready and that was submitted for review.

At this moment I’m working through all the remarks that the reviewers gave me. Some of them were quite good and made me realise that not everybody expects what I’m expecting from an IronRuby book. So I’ve been expanding some explanations and rewriting big chunks. I expect that we will have another review round soon. I have to process those remarks again and at that stage we’ll probably be ready to publish it in and EAP style.

Now that my first 3rd is done I’m starting at actually developing applications with IronRuby. I’m pretty curious to a couple of things from the community.

At this stage I have the following things planned for DataAccess.

I’ll include a brief tutorial on how to use IronRuby with:

  • SubSonic
  • Castle ActiveRecord
  • Linq2Sql
  • Rails ActiveRecord
  • LightSpeed

I would like to know which one I should emphasize most and focus on most.

After that I’m starting on WPF and/or Winforms. At this stage I’ve only planned to talk about WPF and not about Winforms. But I’d like to confirm if that is the general idea from the people that are going to take this IronRuby ride with me.

When I start talking about ASP.NET which topics are of most interest ?

That are all the questions I have for now. When I have more questions I’ll surely post them. And I would like to thank everybody that puts his 2c in.

I’ll post more when I have more news around the book.

kick it on DotNetKicks.com

08

Mar
2008

Color Scheme for Visual Studio With Resharper and Ruby in Steel Support

This is certainly an exciting time for me. A release of dynamic silverlight that supports IronRuby, Asp.NET MVC that can be used to in conjunction with that.

I think that web applications and the way the web looks will severely change in the near future.

Anyway not only the people at Microsoft have been busy also the guys from sapphiresteel have been busy lately. They releases a really cool update to their Ruby In Steel product. A visual rails work bench and support for developing IronRuby apps with visual studio !

I finally got round to doing some installs/upgrades on my machine and played around with the color scheme until it suited me. I’ll post that here.

I use Resharper 4 as well as IronRuby and in Resharper I have code analysis turned on with color identifiers. So my scheme needs to support those.

I don’t like bright colors nor a totally black background, they have the same effect as a white background on me. I get migraines and can’t concentrate as long as I need to. (the latter may also be due to undiagnosed ADD).

So in C# with resharper the code looks like this:

CsharpColors

I do lot’s of webdevelopment but I haven’t tuned the colors for xaml yet. Will probably get round to doing that next weekend. This is how the html colors look (this is from rails html but html looks the same).

html

Then there still is ruby to show and a config file.

Here’s ruby:

rubyscheme

And lastly the config files:

webconfigscheme

Get DimmedInkResharperRubyInSteel (Visual Studio 2008)
Get DimmedInkResharperRubyInSteel (Visual Studio 2005)

27

Feb
2008

Visual Studio Gallery

This morning I found an announcement for the visual studio tools gallery. I went and had a look they have collected heaps of tools, some free most of them not into a website.

I promptly downloaded a couple of tools. One of them is something I recently discovered I need, local history. That is in between check-ins a file can also change but that isn’t recorded in source control so i can’t revert or view differences. Turns out that there is a project on codeplex that allows you to do just that. It’s called local history :)

27

Feb
2008

Consuming YouTube Using XLinq

I had to implement an integration with youtube for a client yesterday. Google provides API’s but they are for Java and PHP. I’m using C# for this project. So I decided to use XLinq to fetch the feeds and parse them into classes for what I needed.

I only need titles, movies and a thumbnail for each item. So I haven’t implemented all of the properties. And I am impressed. From having no exposure to XLinq whatsoever to having it parse feeds and being able to use those feeds in my monorail application took me about an hour. Since this is the very first time I use XLinq I imagine there is room for improvement, please tell me so when I’m wrong.

The classes I show here can be used as follows:

YouTubePlayList.LoadForUser("<<username>>").ForEach(pl => Response.Write("<span style="color: blue">" + pl.Id + "</span><br></br>"));

var url = http://gdata.youtube.com/feeds/api/playlists/<<playlistid>;
YouTubeCollection.LoadFrom(url).ForEach(yt => Response.Write(yt.Title + ", " + yt.MovieUrl + "<br></br>"));

public class YouTubeCollection : List<YouTubeItem>
{
    public YouTubeCollection()
    {
    }

    public YouTubeCollection(IEnumerable<YouTubeItem> collection)
        : base(collection)
    {
    }

    public static YouTubeCollection LoadFrom(string uri)
    {
        var feed = XElement.Load(uri);

        XNamespace ns = "http://www.w3.org/2005/Atom";
        XNamespace media = "http://search.yahoo.com/mrss/";

        var list = new YouTubeCollection(from item in feed.Elements(ns + "entry").Elements(media + "group")
                    select new YouTubeItem
                    {
                        Title = item.Element(media + "title").Value,
                        MovieUrl = (from el in item.Elements(media + "content")
                                 where el.Attribute("type").Value == "application/x-shockwave-flash"
                                 select el.Attribute("url").Value).First(),
                         ThumbnailUrl = (from el in item.Elements(media + "thumbnail")
                                         select el.Attribute("url").Value).First()
                    });

        return list;
    }

}

public class YouTubePlayList : List<YouTubePlayListItem>
{
    public YouTubePlayList()
    {
    }

    public YouTubePlayList(IEnumerable<YouTubePlayListItem> collection) : base(collection)
    {
    }

    public static YouTubePlayList LoadForUser(string user)
    {
        var url = string.Format("http://gdata.youtube.com/feeds/api/users/{0}/playlists", user);

        var feed = XElement.Load(url);

        XNamespace ns = "http://www.w3.org/2005/Atom";
        XNamespace gd = "http://schemas.google.com/g/2005";

        var list = new YouTubePlayList(from item in feed.Elements(ns + "entry")
                                       select new YouTubePlayListItem
                                         {
                                             Name = item.Element(ns + "title").Value,
                                             Id = item.Element(gd + "feedLink").Attribute("href").Value
                                         });

        return list;
    }
}

[DataContract]
public class YouTubePlayListItem
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string Id { get; set; }
}

[DataContract]
public class YouTubeItem
{
    private string _id;
    [DataMember]
    public string Id
    {
        get
        {
            return MovieUrl.Split('/').Last();
        }
        set
        {
            _id = value;
        }
    }

    [DataMember]
    public string Title { get; set; }
    
    [DataMember]
    public string MovieUrl { get; set; }
    
    [DataMember]
    public string ThumbnailUrl { get; set; }
}

09

Feb
2008

Using Ruby to Generate LightSpeed Models - Part 4

UPDATE: I have an update here with a new version and the location on google code where the project is hosted now.

In the previous 3 parts (part 1, part 2, part 3) we talked about getting the meta data out of the database and generating the lightspeed entities in memory.

I won’t put the code listings up in this blog post but instead will give you a link to the complete code :) You can download the express edition of LightSpeed and try it for yourself if you want.

Instead I’ll talk about how you can use the ruby script to generate the models from an existing database.

It adds the generated files to the visual studio project file in the same directory or you can specify one.

Currently it only supports Sql Server 2005. You need to create a project first in visual studio so we have a project file to add items to.

To use it you have to tell it which database it has to find by putting a database.yml file in your visual studio project directory.

The content of that database.yml file may look as follows

on windows you can use the following connection string

#
# sqlserver:
# database: northwind
# host: localhost
# username: sa
# password: MaybePassword123
#
#
# on OSX and Linux you can connect to sql server through odbc (iODBC or unixODBC in combination with FreeTDS)
#
# sqlserver:
# dsn: NorthwindSql
# username: sa
# password: MaybePassword123

when you’ve done that you can execute it like shown in the screenshot below:

Terminal-screenshot

I have a database.yml file in the directory and I execute the command ruby <> on linux and OSX you can chmod +x that path and then you don’t have to type ruby anymore.

That will generate the models for your database provided that your database conforms to the conventions needed for LightSpeed.

The next step would be to open visuals studio and build the project. The files got added in visual studio every entity are 2 files one with the generated code and one empty one that you can use to implement behavior on the model if you would want to.

The first picture shows how the solution explorer looks and the second one shows the results of the build without having touched one file after generation.

In the download there is a folder db which contains a slightly modified script from the Northwind database that comes with the samples for lightspeed. I used that database because it has every type of relationship and the script did conform to the lightspeed conventions :)

LightSpeedGenerateTest

LightSpeedGenerateTestBuildResult

kick it on DotNetKicks.com

07

Feb
2008

More on Mac KeyBindings

The biggest problem so far I’ve had when switching from windows to a mac were the shortcut keys, and mostly the inconsistency thereof. It turns out there is a way to manipulate the keybindings for all cocoa apps, which should make them consistent across all good cocoa citizens. Firefox isn’t one of those citizens neither is firefox 3.0.

I uninstalled quicksilver because I couldn’t work out what it would do for me and didn’t want to spend time figuring it out either. This liberated my ctrl-space for visual studio.  I remapped alt-insert to alt-i and that works for me. Then I brought some consistency in the way my keys behave across all cocoa apps.

I solved my problem with the shortcut keys by following the instructions that can be found in the following posts.
They talk about editing a file by hand and saving it, but for those that like a GUI there is one for it.

The GUI application: KeyBindingsEditor

The links with some instructions and background information.

http://blog.macromates.com/2005/key-bindings-for-switchers/

http://www.hcs.harvard.edu/~jrus/site/cocoa-text.html

The last post lists a couple of predefined keybinding files like one for emacs

http://www.hcs.harvard.edu/~jrus/site/KeyBindings/Emacs%20Esc%20Bindings.dict

or windows key bindings

http://www.hcs.harvard.edu/~jrus/site/KeyBindings/Emacs%20Esc%20Bindings.dict

Guess which ones I took and it’s not emacs ;) I actually just took a couple of keybindings. The ones that I use the most

/***** ARROWS *****/ 

    “^\UF700”   = “moveToBeginningOfParagraph:”;    / C-up         Move to beginning of paragraph /
    “^\UF701”   = “moveToEndOfParagraph:”;          / C-down       Move to end of paragraph /

    “^$\UF700”  = “moveToBeginningOfParagraphAndModifySelection:”;
                                                    / C-Shft-up    Select to beginning of paragraph /
    “^$\UF701”  = “moveToEndOfParagraphAndModifySelection:”;
                                                    / C-Shft-down  Select to end of paragraph /

    “^\UF702”   = “moveWordLeft:”;                  / C-left       Move word left /
    “^\UF703”   = “moveWordRight:”;                 / C-right      Move word right /

    “$^\UF702”  = “moveWordLeftAndModifySelection:”;
                                                    / C-Shft-left  Select word left /
    “$^\UF703”  = “moveWordRightAndModifySelection:”;
                                                    / C-Shft-right Select word right /

/ CTRL + LETTERS /

    “^a”        = “selectAll:”;                     / C-a          Select all /

    “^x”        = “cut:”;                           / C-x          Cut /
    “^c”        = “copy:”;                          / C-c          Copy /
    “^v”        = “paste:”;                         / C-v          Paste /

    “^z”        = “undo:”;                          / C-z          Undo /
    “^y”        = “redo:”;                          / C-y          Redo /

    “^s”        = “save:”;                          / C-s          Save /
    “^S”        = “saveAs:”;                        / C-Shft-s     Save as /
 

06

Feb
2008

On Software Development: The Myth of No Maintenance Etc.

Jeremy Miller put a very intersting post up about the First causes in software development 
While I don’t always like the how of delivering his messages, I think Jeremy is generally spot on. In fact he seems to voice my thoughts much more eloquently than I ever could. Anyway his post or series of posts is dealing with some of the choices he made concerning tools and development philosophy and it also tries to explain that while these tools seem to work today, there won’t be anything stopping him if something better comes along.

Now in that article he links to an article by the pragmatic programmers on the principle of DRY and orthogonality. For me the biggest problem of software development is not the techniques or the patterns but it’s the actual language people use. Till this day I still don’t know what orthogonality means although I understand what that word means in a development context. There are countless examples where people overcomplicate things by using difficult words, this is just one more. Anyway I digress :)

The article series he’s referring to is pretty interesting. If you have some time to kill I suggest you read them. It are 10 articles:
Part I - Don’t live with broken windows

Part II - Orthogonality and the DRY Principle

Part III - Good enough software

Part IV - Abstraction and Detail

Part V - Building adaptable systems

Part VI - Programming close to the domain

Part VII - Programming is gardening, not engineering

Part VIII - Tracer Bullets and Prototypes

Part IX - Programming defensively

Part X - Plain text and xml

 

The reason that I put these links up is not only because they are a great read but also because one of the things they say in one of the articles is that after you wrote 10 lines of code or so you’re effectively in maintenance mode the green field is gone. And that couldn’t be more true after I had some internal discussion about it I definitely agree with that statement and as such one of the primary goals of your development should not be on getting it out the door as quickly as possible but building it in such a way that you or somebody else can get in there and make changes without throwing away half the code base.

I hope you enjoy them as much as I did

05

Feb
2008

Using Ruby to Generate LightSpeed Models - Part 3

First off I’m writing with windows live writer again, ecto wasn’t up to the job. It tried to “clean” my html, granted it was messy but it should leave my text untouched. The whole editing experience wasn’t satisfying enough. And Ecto already seemed like the best blog editor for mac, slim pickings indeed. From my tools I expect foremost that they stay out of my way and it didn’t. I just talked with Simone about looking at making a .NET based client that runs on mono, we’ll see where that plan goes because I don’t really have time to do that for the moment.

In the previous posts in this series (part 1, part 2) we discovered how to connect to the database and how to get the meta data about that database out. Maybe I should also explain why I’m doing this series with LightSpeed instead of ActiveRecord from Castle or SubSonic or Linq2Sql for that matter. I will definitely touch on all those orms in the coming week, but I started with LightSpeed because it’s the easiest ORM I’ve ever used.

This post will deal with actually doing something useful with that meta data. Today we’re going to generate the represenation of the entities and their properties. Tomorrow we’ll deal with actually generating the files from the the in-memory presentation we’re generating today.

We’re going to need 2 classes in addition to the LightSpeedRepository class. One to represent an entity and one to represent a property. The goal is for tomorrow to render the entities as complete as possible with validation attributes etc.

And without further ado here are the specs we’re going to build:

LightSpeedRepository Conversion      
- should convert a given table to light speed metadata       
- should convert a given table without relations to a light speed entity definition       
- should convert a given table with a m:1 relation to a light speed entity definition       
- should convert a given table with a 1:m relation to a light speed entity definition       
- should convert a given table with a m:n relation to a light speed entity definition 



LightSpeedProperty      
- should allow for a property to be set       
- should return a predicate for booleans       
- should return a predicate for booleans       
- should return a sql type       
- should be a lightSpeed property 



LightSpeedEntity      
- should have properties, has many, belongs to and through associations       
- should create a valid property name if one doesn't exists already in the through association properties       
- should create a valid property name if one doesn't exists already in the has many properties       
- should create a valid property name if one doesn't exists already in the belongs to properties       
- should create a valid property name if one doesn't exists already in the properties       
- should create a valid property name if one already exists in the through association properties       
- should create a valid property name if one already exists in the has many properties       
- should create a valid property name if one already exists in the belongs to properties       
- should create a valid property name if one already exists in the properties       
- should create a valid property name if two already exist in the through association properties       
- should create a valid property name if two already exist in the has many properties       
- should create a valid property name if two already exist in the belongs to properties       
- should create a valid property name if two already exist in the properties

Let’s start with looking at the LightSpeedProperty first. The attributes on this class are implemented using some simple metaprogramming. This class will represent a field in a LightSpeed entity and will take care of rendering that properly into the c# file. We actually create the data in the LightSpeedRepository class.

class LightSpeedProperty

  attr_accessor :attributes

  def initialize(params = {})
    @attributes = params
    LightSpeedProperty.create_methods params

  end

  def [](attribute)
    attributes[attribute]
  end

  def self.create_methods(params)

    params.each do |k, v|
      define_method("#{k}=") do |val|
        @attributes[k]= val
      end

      predicate = %w(primary_key foreign_key unique nullable).any? { |o| o === k.to_s }

      define_method(predicate ? "#{k}?" : "#{k}") do
        @attributes[k]
      end

    end
  end

end

In the LightSpeed entity class we describe the actual Entity. I monkey patched Array so that I could ask it the question if it has a particular property. To avoid naming conflicts we check for properties that exist already and otherwise give them a generic new name by appending a number.

class Array

  def has_property?(name)
    exists = false

    each do |hm|
      exists = hm[:name] == name
      break if exists
    end

    exists
  end
end

class LightSpeedEntity
  attr_accessor :properties, :belongs_to, :has_many, :through_associations, :name, :namespace


  def initialize
    @properties = []
    @belongs_to = []
    @has_many = []
    @through_associations =[]
  end

  def create_property_name_from(from, idx=0)
    tname = build_property_name_from from, idx
    idx += 1 #when the property exists try with a higher number
    return create_property_name_from(from, idx) if has_property?(tname)
    tname
  end

  private

    def has_property?(tname)
      properties.has_property? tname or has_many.has_property? tname or belongs_to.has_property? tname or through_associations.has_property? tname
    end

    def build_property_name_from(from, idx)
      if idx == 0
        from
      else
        "#{from}#{idx}"
      end
    end


end

And this brings us to our last class of today the Repository class. We mixin the DB::MetaData module we created yesterday. Define a read_only property entities, make sure we can set a namespace for our generated entities. The first step is to transform the meta data into data that we can use to represent a LightSpeed Entity. The second and last step of today is to generate the entities with the lightspeed meta data. We have to skip the primary key because that is defined by convention in LightSpeed.

class LightSpeedRepository

  include DB::MetaData

  attr_reader :entities
  attr_accessor :namespace


  def initialize()
    @entities = []
    super
  end

  def to_light_speed_meta_data
    tables.collect do |table|
      col_infos = column_info_for table[:name]

      field_infos = col_infos.collect do |col_info|
        {
          :name => col_info[:name].underscore,
          :sql_type => col_info[:sql_type],
          :max_length => col_info[:max_length].to_i,
          :nullable => !col_info[:is_nullable].to_i.zero?,
          :precision => col_info[:precision],
          :foreign_key => foreign_key?(col_info),
          :primary_key => primary_key?(col_info),
          :unique => !col_info[:is_unique].to_i.zero?
        }
      end

      { :table_name => table[:name], :class_name => table[:name].singularize.camelize, :fields => field_infos }
    end
  end

  def generate_entities
    meta_data = to_light_speed_meta_data
    meta_data.each do |md|
      @entities << generate_entity(md)
    end
    @entities
  end

  def generate_entity(meta_data)
    entity = LightSpeedEntity.new
    entity.name = meta_data[:class_name]
    entity.namespace = namespace

    meta_data[:fields].each do |fi|
      prop = LightSpeedProperty.new(fi)

      prop.name = entity.create_property_name_from prop.name.underscore.camelize
      entity.properties << prop unless prop.primary_key?
      entity.belongs_to << generate_belongs_to_relation(meta_data, fi, entity) if prop.foreign_key?

    end

    entity.has_many = generate_has_many_relations meta_data, entity
    generate_through_associations meta_data, entity

    entity
  end



  private

    def generate_belongs_to_relation(meta_data, field_info, entity)
      {
        :name => entity.create_property_name_from(field_info[:name].underscore.humanize.titleize.gsub(/\s/,'')),
        :class_name => get_belongs_to_table(meta_data[:table_name], field_info[:name]).underscore.camelize.singularize
      }
    end

    def generate_has_many_relations(meta_data, entity)
      hms = collect_has_many_relations meta_data[:table_name]
      hms.collect do |hm|
         hm[:name] = entity.create_property_name_from hm[:class_name].pluralize
         hm
      end

    end

    def generate_through_associations(meta_data, entity)
      tas = collect_through_associations(meta_data[:table_name])
      tas.each do |ta|
        ta[:end_tables].each do |et|
          entity.through_associations << {
            :through => ta[:through_table].classify.singularize,
            :class_name => et.camelize.singularize,
            :name => entity.create_property_name_from(et.camelize)
          }
        end
      end
    end
end

To top