<?xml version="1.0"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007" xmlns:atom="http://www.w3.org/2005/Atom">
   <channel>
      <title>montrealhackers</title>
      <description>Pipes Output</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=ea5b9241c485847c66dcaba37a0a5178</link>
      <atom:link rel="next" href="http://pipes.yahoo.com/pipes/pipe.run?_id=ea5b9241c485847c66dcaba37a0a5178&amp;_render=rss&amp;page=2"/>
      <pubDate>Thu, 01 Oct 2015 19:25:38 +0000</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <item>
         <title>Using Redis in Asp.Net in an Enterprise System</title>
         <link>http://patrickdesjardins.com/blog/using-redis-in-asp-net-in-an-enterprise-system</link>
         <description>I wrote about how to integrate Redis into Asp.Net MVC few days ago. Here is a way how to integrate Redis into your solution with dependency injection and abstracting Redis. This additional layer will be helpful if in the future we change from Redis to Memcached or simply. The first step is to create the [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4281</guid>
         <pubDate>Thu, 01 Oct 2015 09:49:45 +0000</pubDate>
         <content:encoded><![CDATA[<p>I wrote about how to integrate Redis into Asp.Net MVC few days ago. Here is a way how to integrate Redis into your solution with dependency injection and abstracting Redis. This additional layer will be helpful if in the future we change from Redis to Memcached or simply.</p>
<p>The first step is to create the interface that will be used.</p>
<pre>
public interface ICache
{
    void SetString(string key, string objectToCache, TimeSpan? expiry = null);
    void Set&lt;T&gt;(string key, T objectToCache, TimeSpan? expiry = null) where T : class;
    string GetString(string key);
    T Get&lt;T&gt;(string key) where T : class;
    void Delete(string key);
    void FlushAll();
}
</pre>
<p>This interface gives primary operations that can be execute against Redis (or any other cache system). It&#8217;s possible to enhance this interface with more methods, This is the basic operations that  is required to run a cache. The first two methods are to set a value inside the cache. One set a simple string, the second take a class of type T. The second one will be mostly used to take an object and serialize it. The next two methods are to get from a key the unserialized data. The next two methods is to delete. One use a key to delete a specific object and the other one delete everything from the cache.</p>
<p>A second interface is used. This one will allow us to get some status about if the cache is enable and if the cache is running properly.</p>
<pre>
public interface ICacheStatus
{
    bool IsCacheEnabled { get;}
    bool IsCacheRunning { get;}
}
</pre>
<p>The difference between <strong>IsCacheEnable </strong>and <strong>IsCacheRunning </strong>is that the first one is controlled by us. Normally from the web.config, you should have a key to turn on and off the cache. In case you notice a problem with the cache, it is always a good option to be able to turn off. The Second property is about getting the status of the caching server, Redis. If this one become inactive, it&#8217;s interesting to get the status from an administration panel for example.</p>
<p>Despite this interface, we need to have an abstract class with shared logic for any cache system (not only Redis). This is where we will have the serialization process, the error logging and the handling of the on/off mechanism. This is where the Circuit Pattern could also be used. I will discuss about it in a future article. Keep in mind for the moment that </p>
<pre>
public abstract class Cache : ICache, ICacheStatus
{
    private readonly bool isCacheEnable;

    public Cache(bool isCacheEnable)
    {
        this.isCacheEnable = isCacheEnable;
    }

    public void Set&lt;T&gt;(string key, T objectToCache, TimeSpan? expiry = null) where T : class
    {
        if (string.IsNullOrEmpty(key))
        {
            throw new ArgumentNullException(&quot;key&quot;);
        }
        if (this.isCacheEnable)
        {
            try
            {
                var serializedObjectToCache = JsonConvert.SerializeObject(objectToCache
                     , Formatting.Indented
                     , new JsonSerializerSettings
                     {
                         ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                         PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                         TypeNameHandling = TypeNameHandling.All
                     });

                this.SetStringProtected(key, serializedObjectToCache, expiry);
            }
            catch (Exception e)
            {
                Log.Error(string.Format(&quot;Cannot Set {0}&quot;, key), e);
            }
        }
    }

    public T Get&lt;T&gt;(string key) where T : class
    {
        if (string.IsNullOrEmpty(key))
        {
            throw new ArgumentNullException(&quot;key&quot;);
        }
        if (this.isCacheEnable)
        {
            try{
                var stringObject = this.GetStringProtected(key);
                var obj = JsonConvert.DeserializeObject&lt;T&gt;(stringObject
                     , new JsonSerializerSettings
                     {
                         ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                         PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                         TypeNameHandling = TypeNameHandling.All
                     });
                return obj;
            }
            catch (Exception e)
            {
                Log.Error(string.Format(&quot;Cannot Set key {0}&quot;, key), e);
            }
        }
        return null;
    }

    public void Delete(string key)
    {
        if (string.IsNullOrEmpty(key))
        {
            throw new ArgumentNullException(&quot;key&quot;);
        }
        if (this.isCacheEnable)
        {
            try{
                this.DeleteProtected(key);
            }
            catch (Exception e)
            {
                Log.Error(string.Format(&quot;Cannot Delete key {0}&quot;,key), e);
            }
        }
    }

    public void DeleteByPattern(string prefixKey)
    {
        if (string.IsNullOrEmpty(prefixKey))
        {
            throw new ArgumentNullException(&quot;prefixKey&quot;);
        }
        if (this.isCacheEnable)
        {
            try
            {
                this.DeleteByPatternProtected(prefixKey);
            }
            catch (Exception e)
            {
                Log.Error(string.Format(&quot;Cannot DeleteByPattern key {0}&quot;, prefixKey), e);
            }
        }
    }

    public void FlushAll()
    {
        if (this.isCacheEnable)
        {
            try{
                this.FlushAllProtected();
            }
            catch (Exception e)
            {
                Log.Error(&quot;Cannot Flush&quot;, e);
            }
        }
    }

    public string GetString(string key)
    {
        if (string.IsNullOrEmpty(key))
        {
            throw new ArgumentNullException(&quot;key&quot;);
        }
        if (this.isCacheEnable)
        {
            try
            {
                return this.GetStringProtected(key);
            }
            catch (Exception e)
            {
                Log.Error(string.Format(&quot;Cannot Set key {0}&quot;, key), e);
            }
        }
        return null;
    }

    public void SetString(string key, string objectToCache, TimeSpan? expiry = null)
    {
        if (string.IsNullOrEmpty(key))
        {
            throw new ArgumentNullException(&quot;key&quot;);
        }
        if (this.isCacheEnable)
        {
            try
            {
                this.SetStringProtected(key, objectToCache, expiry);
            }
            catch (Exception e)
            {
                Log.Error(string.Format(&quot;Cannot Set {0}&quot;, key), e);
            }
        }
    }
    public bool IsCacheEnabled
    {
        get { return this.isCacheEnable; }

    }
    
    protected abstract void SetStringProtected(string key, string objectToCache, TimeSpan? expiry = null);
    protected abstract string GetStringProtected(string key);
    protected abstract void DeleteProtected(string key);
    protected abstract void FlushAllProtected();
    protected abstract void DeleteByPatternProtected(string key);
    public abstract bool IsCacheRunning { get;  }
}
</pre>
<p>As you can see, this abstract class will delegate all methods into a protected abstract methods which contains the cache implementation code. This one does not know about concrete implementation, just how to handle general caching knowledge. It also abstract a single method which save a string. This mean that the implementer does not need to care about anything other than string. However, the one that will use the class has access to a Set method that allow to pass a string or an object. The next class, is the one that does the real job. Here is a simple Redis implementations of this abstract class.</p>
<pre>
public class RedisCache : Definitions.Cache
{
    private ConnectionMultiplexer redisConnections;

    private IDatabase RedisDatabase {
        get {
            if (this.redisConnections == null)
            {
                InitializeConnection();
            }
            return this.redisConnections != null ? this.redisConnections.GetDatabase() : null;
        }
    }

    public RedisCache(bool isCacheEnabled):base(isCacheEnabled)
    {
        InitializeConnection();
    }

    private void InitializeConnection()
    {
        try
        {
             this.redisConnections = ConnectionMultiplexer.Connect(System.Configuration.ConfigurationManager.AppSettings[&quot;CacheConnectionString&quot;]);
        }
        catch (RedisConnectionException errorConnectionException)
        {
            Log.Error(&quot;Error connecting the redis cache : &quot; + errorConnectionException.Message, errorConnectionException);
        }
    }

    protected override string GetStringProtected(string key)
    {
        if (this.RedisDatabase == null)
        {
            return null;
        }
        var redisObject = this.RedisDatabase.StringGet(key);
        if (redisObject.HasValue)
        {
            return redisObject.ToString();
        }
        else
        {
            return null;
        }
    }

    protected override void SetStringProtected(string key, string objectToCache, TimeSpan? expiry = null)
    {
        if (this.RedisDatabase == null)
        {
            return;
        }

        this.RedisDatabase.StringSet(key, objectToCache, expiry);
    }

    protected override void DeleteProtected(string key)
    {
        if (this.RedisDatabase == null)
        {
            return;
        }
        this.RedisDatabase.KeyDelete(key);
    }

    protected override void FlushAllProtected()
    {
        if (this.RedisDatabase == null)
        {
            return;
        }
        var endPoints = this.redisConnections.GetEndPoints();
        foreach (var endPoint in endPoints)
        {
            var server = this.redisConnections.GetServer(endPoint);
            server.FlushAllDatabases();
        }
    }

    public override bool IsCacheRunning
    {
        get { return this.redisConnections != null &amp;&amp; this.redisConnections.IsConnected; }
    }
}
</pre>
<p>The Redis connection get its setting from the web.config. The instantiation of the Redis object is done by using the <strong>ConnectionMultiplexer</strong> that come from the StackExchange API. This one is thread save and this is why the Cache will be a singleton from the dependency container.</p>
<pre>
    container.RegisterType&lt;RedisCache&gt;(new ContainerControlledLifetimeManager()
                                                                , new InjectionConstructor(
                                                                        Convert.ToBoolean(ConfigurationManager.AppSettings[&quot;IsCacheEnabled&quot;])
                                                                )); //Singleton ( RedisCache use thread-safe code)
    container.RegisterType&lt;ICache, RedisCache&gt;(); //Re-use the singleton above
    container.RegisterType&lt;ICacheStatus, RedisCache&gt;(); //Re-use the singleton above
</pre>
<p>This is how to register the cache with Microsoft Unity. The first one register the <strong>RedisCache </strong>class with a new object object shared by every queries to the cache, thus every requests. The two next registrations associate the two interfaces to that cache instance.</p>
<p>From there, it&#8217;s possible to use anywhere the interface. It&#8217;s also easy to unit test since you can mock the <strong>ICache </strong>interface which is the only interface that you need to pass through all your code. About what need to be used, it&#8217;s clear from the dependency injection code that we use <strong>ICache </strong>as the interface to use and not the concrete <strong>RedisCache </strong>class. The cache shouldn&#8217;t be used in the controller class, neither in your service class or in your repository class. This belong to the accessory classes which are between your service and repository class. Here is the a graphic of the layers that is recommended to have when using a cache system and a database.</p>
<p><a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4283"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/07/Layers-400x277.png" alt="Layers" width="400" height="277" class="aligncenter size-medium wp-image-4283"/></a></p>
<p>The idea is that that the only layer to know about the cache is the accessor. The service layer does not know about the cache or the database &#8212; it only know about to get and set from the accessor. The repository does not know about caching, it&#8217;s responsibility is to get from the persistence storage the data. This can be with Entity Framework (or any other ORM) or directly with Ado.Net. On the other hand, the cache does not know about the database, it only know how to store data in a fast access way. This mean that the accessor class is the only one to get the cache injected. Here is a small example.</p>
<pre>
public class ContestAccessor: IContestAccessor
{
	private readonly IContestRepository contestRepository;
	private readonly ICache cache;
	public ContestAccessor(IContestRepository repository, ICache cache)
	{
		//...
	}
}
</pre>
<p>This class can have methods to get specific information. Here is an example to get a contest by id.</p>
<pre>
public Contest GetById(int id)
{
    var key = string.Format(&quot;contest_by_id_&quot;, id);
    var contestObject = this.cache.Get&lt;Contest&gt;(key);
    if (contestObject == null)
    {
        contestObject = this.contestRepository.GetById(id);
        this.cache.Set(key, contestObject);
    }
    return contestObject;
}
</pre>
<p>This is a basic example, that get the contest from the cache, if this one does not find it, than get it from the repository and store it inside the cache for the next call. Every time, we return the object whatever where it comes from. The service layer uses the injected accessor (the interface IContest for example). It does not know anything about the repository or the cache &#8212; the service just knows about getting its object by an id.</p>]]></content:encoded>
      </item>
      <item>
         <title>Integrating Redis in your Asp.Net MVC Project</title>
         <link>http://patrickdesjardins.com/blog/integrating-redis-in-your-asp-net-mvc-project</link>
         <description>I have been using Memcached for the last decade and wanted to try Redis on a new project. Redis is also a cache system that allow you to cache data in the ram memory for fast access, like Memcached. Redis offers the same key-value experiences. Redis is newer and is having more functionalities. Where Memcached [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4269</guid>
         <pubDate>Sun, 27 Sep 2015 10:13:20 +0000</pubDate>
         <content:encoded><![CDATA[<p>I have been using Memcached for the last decade and wanted to try <strong>Redis </strong>on a new project. Redis is also a cache system that allow you to cache data in the ram memory for fast access, like Memcached. Redis offers the same key-value experiences. Redis is newer and is having more functionalities. Where Memcached can be limited, for example in the choice of eviction strategies, Redis will offer several solutions. Memcached is also more restrictive concerning the key&#8217;s size whilst Redis is way less. Redis offers the possibility of not be restricted to string for value but can use the Redis Hash system. It is also possible to do operation, like SQL, on the server side instead of having to retrieve the data to manipulate it. The goal of this article is not to sell you Redis but the tell you how to use it with C# and an Asp.Net MVC project.</p>
<p>The first thing to do is to install Redis on your machine. It is created for Linux but has a simple installation for Windows. In fact, Microsoft has a open source implementation where you can download the installation from this <a rel="nofollow" target="_blank" href="https://github.com/MSOpenTech/redis/releases">GitHub page</a>. I hear a lot of good feedback about it. Most say that Microsoft try not to inject any Microsoft&#8217;s flavor into it and keep it just as in implementation from the Linux ones &#8212; which is great. I also believe that this will be keep up-to-date since Microsoft offers a Redis service in part of Azure. Once you download the file and install, you will have a running service in your machine.</p>
<p><a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4272"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/07/RedisServer-400x203.png" alt="RedisServer" width="400" height="203" class="aligncenter size-medium wp-image-4272"/></a></p>
<p>Once it&#8217;s running, you can do a quick test with the Redis-cli console. You can set and get a value with a simple <strong>set</strong> and <strong>get</strong> command.<br />
<a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4273"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/07/RedisCliExample-400x72.png" alt="RedisCliExample" width="400" height="72" class="aligncenter size-medium wp-image-4273"/></a><br />
It&#8217;s also possible to get all keys by using the <strong>keys *</strong> command. Once everything work as expected, you can delete everything with the <strong>flushall</strong> delete command.</p>
<p>Next step, is to be able to set and get from the Asp.Net C# application. This is where it can be tricky. There is multiple clients available. Do not waste your time with the servicestack one. Even if a lot of documentation is available, that library became not free since version 4. The version 3 is still available to download via Nuget but it&#8217;s more than 1 year old, the documentation does not fit quite well with the version 4 and it requires a lot of tricky hack to make everything work with all dependency packages. After wasted 3 hours I decided to use the stackexchange version one. The name is similar so do not get confuse.</p>
<p><a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4274"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/07/StackExchangeRedis-400x65.png" alt="StackExchangeRedis" width="400" height="65" class="aligncenter size-medium wp-image-4274"/></a></p>
<p>Once installed, you&#8217;ll be able to access Redis with almost no effort for basic command like setting and getting. Here is a short example of possible use.</p>
<pre>
public class RedisCache : ICache
{
    private readonly ConnectionMultiplexer redisConnections;

    public RedisCache()
    {
        this.redisConnections = ConnectionMultiplexer.Connect(&quot;localhost&quot;);
    }
    public void Set&lt;T&gt;(string key, T objectToCache) where T : class
    {
        var db = this.redisConnections.GetDatabase();
        db.StringSet(key, JsonConvert.SerializeObject(objectToCache
                    , Formatting.Indented
                    , new JsonSerializerSettings
                    {
                        ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                        PreserveReferencesHandling = PreserveReferencesHandling.Objects
                    }));
    }


    public T Get&lt;T&gt;(string key) where T :class 
    {
        var db = this.redisConnections.GetDatabase();
        var redisObject = db.StringGet(key);
        if (redisObject.HasValue)
        {
            return JsonConvert.DeserializeObject&lt;T&gt;(redisObject
                    , new JsonSerializerSettings
                    {
                        ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                        PreserveReferencesHandling = PreserveReferencesHandling.Objects
                    });
        }
        else
        {
            return (T)null;
        }
    }
</pre>
<p>From here, you can inject the ICache with your IOC and use RedisCache. You can get and set any object. Voila! Of course, this class is not ready for any production code. The real ICache should have more methods like deleting and you should not hardcode &#8220;localhost&#8221;, but this should give you enough to get started with Redis and .Net.</p>]]></content:encoded>
      </item>
      <item>
         <title>Serializing Complex Object for Redis</title>
         <link>http://patrickdesjardins.com/blog/serializing-complex-object-for-redis</link>
         <description>I have been using Redis since few weeks now and I stumble into a weird problem after few days. At first, my serialization was fine. I was able to serialize, cache and deserialize without problem. After few times, I wasn&amp;#8217;t able to unserialize my serialize. First of all, I am using JSON.Net for serialization and [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4277</guid>
         <pubDate>Tue, 22 Sep 2015 10:09:36 +0000</pubDate>
         <content:encoded><![CDATA[<p>I have been using Redis since few weeks now and I stumble into a weird problem after few days. At first, my serialization was fine. I was able to serialize, cache and deserialize without problem. After few times, I wasn&#8217;t able to unserialize my serialize.</p>
<p>First of all, I am using <a rel="nofollow" target="_blank" href="http://www.newtonsoft.com/json">JSON.Net</a> for serialization and deserialization. It is the common serializer library for a long time, it&#8217;s even the one Microsoft is using now for all its new projects. Second, I was already using some configurations to handle references. The problem was that one of the object had a collection of an interface which it was not deserialized correctly because JSON.Net did not know to which concrete type to instanciate.</p>
<p>To fix this issue and have during serialization the concrete type added to the serialization, you need to use <strong>JsonSerializerSettings</strong> with the <strong>TypeNameHandling</strong> property to <strong>All</strong>. The result look like the following code:</p>
<pre>
var serializedObjectToCache =  JsonConvert.SerializeObject(objectToCache
                       , Formatting.Indented
                       , new JsonSerializerSettings
                       {
                           ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                           PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                           TypeNameHandling = TypeNameHandling.All
                       });
</pre>
<p>The result of the serialization is a JSON attribute named <strong>&#8220;$type&#8221;</strong> which has the complete namespace and class name. You can find more detail on <a rel="nofollow" target="_blank" href="http://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm">JSON.Net documentation about TypeNameHandling</a>.</p>
<p>The deserialization contains also the same <strong>JsonSerializerSettings</strong>.</p>
<pre>
var obj = JsonConvert.DeserializeObject&lt;T&gt;(serializedObject
                        , new JsonSerializerSettings
                        {
                            ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                            PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                            TypeNameHandling = TypeNameHandling.All
                        });
</pre>
<p>With the three settings used in this article, you can serialize complex object with recursive references, with abstract type or interface type and not have to worry about serializing an Entity Framework object. So, why this is not the default configuration? Because this add a lot of information in the JSON. This shouldn&#8217;t be a huge problem if you are using it with Redis, more a problem is you transfer the information through an Ajax call.</p>]]></content:encoded>
      </item>
      <item>
         <title>Can you smell it? Javascript is at a turning point.</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/c2S_tTid4W0/</link>
         <description>&lt;p&gt;Things are going fast in front-end, when I think my back about my 10 years careers, I would say the 6 first years were pretty calm, we had jquery &amp;#038; plugins, and were living a small life. But last 4&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=5200</guid>
         <pubDate>Mon, 14 Sep 2015 18:25:19 +0000</pubDate>
         <content:encoded><![CDATA[<p>Things are going fast in front-end, when I think my back about my 10 years careers, I would say the 6 first years were pretty calm, we had jquery &#038; plugins, and were living a small life. But last 4 years went really fast, always getting better and better tools to do, really, anything you want in javascript, you&#8217;re not bound only to the web anymore.</p>
<p>Still tools you picked up along the way you still can use them today. I&#8217;m a backbone/grunt guy, I did not get into any other framework bandwagon and until now my tools served me well.</p>
<p>The way I see it that&#8217;s all about to change, with ES6, ES7 and Babel, the language is about to be transformed drastically. With frameworks like Angular2, Aurora &#038; React taking advantages from the new language features and new front-end programming paradigm to better handle UI states, I feel that yet again we are leaving another era and the community will shift to new high.</p>
<p>Can you feel it? There&#8217;s something in the air and that&#8217;s not necessarily a bad thing, to the next 5 years!</p>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/c2S_tTid4W0" height="1" width="1" alt=""/>]]></content:encoded>
         <category>Trends</category>
      </item>
      <item>
         <title>Asp.Net Identity 2.2 Localization of error messages</title>
         <link>http://patrickdesjardins.com/blog/asp-net-identity-2-2-localization-of-error-messages</link>
         <description>It&amp;#8217;s interesting to see that Microsoft is trying to better in term of localization but still fail to provide a perfect solution. Asp.Net Identity is by default English oriented but at least not hardcoded. It uses inside the Identity library a resource file. Here is what you can see if your decompile Asp.Net Identity assembly. [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4260</guid>
         <pubDate>Mon, 14 Sep 2015 09:50:19 +0000</pubDate>
         <content:encoded><![CDATA[<p>It&#8217;s interesting to see that Microsoft is trying to better in term of localization but still fail to provide a perfect solution. Asp.Net Identity is by default English oriented but at least not hardcoded. It uses inside the Identity library a resource file.<br />
<a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4263"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/BadExample-400x135.png" alt="BadExample" width="400" height="135" class="aligncenter size-medium wp-image-4263"/></a></p>
<p>Here is what you can see if your decompile Asp.Net Identity assembly. You will see a resource file with defined strings.</p>
<p><a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4261"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/IdentityResourceFile.png" alt="IdentityResourceFile" width="248" height="336" class="aligncenter size-full wp-image-4261"/></a></p>
<p>The problem is that you cannot just define your own resource file and setup the string you desire. You must use one of Microsoft&#8217;s package for your language. Here is the one for French.</p>
<pre>
Install-Package Microsoft.AspNet.Identity.Core.fr
</pre>
<p><a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4265"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/AspNetIdentityCore-400x304.png" alt="AspNetIdentityCore" width="400" height="304" class="aligncenter size-medium wp-image-4265"/></a></p>
<p>The problem with that solution is that you must be lucky to have your language available and you must like the string they chose for you. Some other options available is to create your own <strong>UserValidator</strong> and <strong>PasswordValidator</strong> and by inheriting the Identity ones can still have the benefit of <strong>Identity</strong>. Overall, there is some workaround but still is time consuming for nothing. Better solution like just having to drop a resource file of your own would have been way easier and easily custom for solution. Nevertheless, it starts to get in the right direction after more than a decade trying to create a better Identity framework.</p>]]></content:encoded>
      </item>
      <item>
         <title>How to Use Third Party Dll Reference in a SQL CLR Function</title>
         <link>http://patrickdesjardins.com/blog/how-to-use-third-party-dll-reference-in-a-sql-clr-function</link>
         <description>In a previous article, I was using a SQL CLR function written in C# to be executed by SQL server during a migration of account. The reason was to use the hashing code from Asp.Net Identity that is used by Entity Framework and Asp.Net. In that article, instead of using a copy of the code [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4257</guid>
         <pubDate>Wed, 09 Sep 2015 10:33:45 +0000</pubDate>
         <content:encoded><![CDATA[<p>In a previous article, I was using a SQL CLR function written in C# to be executed by SQL server during a migration of account. The reason was to use the hashing code from Asp.Net Identity that is used by Entity Framework and Asp.Net. In that article, instead of using a copy of the code of the real implementation, we are going to use the real Asp.Net Identity dll. Our C# Dll will just be a proxy to the third party.</p>
<pre>
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString HashPassword2(string plainPassword)
{
   var hasher = new Microsoft.AspNet.Identity.PasswordHasher();
   return hasher.HashPassword(plainPassword);
}
</pre>
<p>The code is way simpler, and reuse the Microsoft Asp.Net code which is interesting. The problem is that SQL project does not allow to use NuGet. It&#8217;s not possible to get the reference from a NuGet package. So, we need to select the DLL from the browse window of the reference. The simple way to do it is to select the one in the Bin folder of you Asp.Net MVC project. Once done, we still need to do something to allow SQL to read it. If you do not, it will compile but not publish.</p>
<pre>
Creating [MySqlToMsSql]...
(63,1): SQL72014: .Net SqlClient Data Provider: Msg 6503, Level 16, State 12, Line 1 Assembly 'microsoft.aspnet.identity.core, version=2.0.0.0, culture=neutral, publickeytoken=31bf3856ad364e35.' was not found in the SQL catalog.
(63,0): SQL72045: Script execution error.  The executed script:
CREATE ASSEMBLY [MySqlToMsSql]
    AUTHORIZATION [dbo]
    FROM 0x4D5A9000...
An error occurred while the batch was being executed.
</pre>
<p>To fix that issue, we need to go in the property of the third-party DLL added to the project. </p>
<p><a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4258"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/PropertyOfThirdParty-400x130.png" alt="PropertyOfThirdParty" width="400" height="130" class="aligncenter size-medium wp-image-4258"/></a></p>
<p>The property about <strong>Model Aware</strong>, <strong>Is Visible</strong> and <strong>Generate Sql Script</strong> must be set to true.</p>]]></content:encoded>
         <category>Sql</category>
      </item>
      <item>
         <title>Montréal-Python 54: Virtualized Utopia</title>
         <link>http://montrealpython.org/2015/09/mp54/</link>
         <description>&lt;p&gt;We've got so many great propositions of talks for our first event of the season. We are very excited to welcome you next Monday at UQAM. It is your opportunity to meet the Python Community of Montreal ! &lt;/p&gt;
&lt;p&gt;Also we would like to thank again our generous sponsors for renewing their support to our community. Particularly, we would like to thank w.illi.am/, Outbox and Savoir-faire Linux for their continuous support. &lt;/p&gt;
&lt;h2&gt;Flash presentations:&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;David Taylor: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/Prooffreader/chorogrid&quot;&gt;Chorogrid a Python module to produce vector choropleth maps&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;David Taylor will introduce his module chorogrid, which makes regular and tiled choropleth maps for geographical data visualization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Jordi Gutiérrez Hermoso: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://pypi.python.org/pypi/pudb&quot;&gt;pudb, the IDE debugger without an IDE!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mathieu Gauthier-Pilote: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://2015.sqil.info/&quot;&gt;Présentation de la Semaine québécoise de l'informatique libre&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Main program:&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Melanie Dubois (Office National du Film): &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://www.onf.ca/&quot;&gt;Le mystère des tests unitaires&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Vous sera conté, une tranche de vie sur les tests à l'Office National du Film du Canada. Pendant la présentation, nous verrons quelques trucs qui ont permis d'accélérer la performance de ces tests mystérieux, ceci, accompagné d'exemples concrets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stéphane Wirtel: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://speakerdeck.com/matrixise/python-and-postgresql-a-wonderful-wedding-english&quot;&gt;Python &amp;amp; PostgreSQL, a Wonderful Wedding&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Python and PostgreSQL, two tools we like to use for our projects but do you know everything about them?&lt;/p&gt;
&lt;p&gt;The talk will give an overview of psycopg2, Peewee, SQLAlchemy, Alembic and PL/Python, these libraries can be used with PostgreSQL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Justin Churchill: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ceph.com/&quot;&gt;Ceph a simple understanding&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;How CEPH differs from legacy storage solutions and what are the top three features of CEPH.&lt;/p&gt;
&lt;h2&gt;When:&lt;/h2&gt;
&lt;p&gt;Monday, September 14th 2015&lt;/p&gt;
&lt;h2&gt;Where:&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://goo.gl/maps/S0AoS&quot;&gt;UQÀM, Pavillion PK&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;201, avenue du Président-Kennedy&lt;/p&gt;
&lt;p&gt;Room PK-1140&lt;/p&gt;
&lt;h2&gt;Schedule:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;6:00pm&lt;/strong&gt; — Doors open&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;6:30pm&lt;/strong&gt; — Presentations start&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;7:30pm&lt;/strong&gt; — Break&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;7:45pm&lt;/strong&gt; — Second round of presentations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;9:00pm&lt;/strong&gt; — One free beer (or equivalent) offered at Bénélux just across the street&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;We’d like to thank our sponsors for their continued support:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;UQÀM&lt;/li&gt;
&lt;li&gt;Bénélux&lt;/li&gt;
&lt;li&gt;w.illi.am/&lt;/li&gt;
&lt;li&gt;Outbox&lt;/li&gt;
&lt;li&gt;Savoir-faire Linux&lt;/li&gt;
&lt;li&gt;Caravan&lt;/li&gt;
&lt;li&gt;iWeb&lt;/li&gt;
&lt;/ul&gt;</description>
         <guid isPermaLink="false">http://montrealpython.org/2015/09/mp54/</guid>
         <pubDate>Tue, 08 Sep 2015 04:00:00 +0000</pubDate>
      </item>
      <item>
         <title>How to use C# code within SQL</title>
         <link>http://patrickdesjardins.com/blog/how-to-use-c-code-within-sql</link>
         <description>This is the first time I had to have something that require a special business logic inside the database that I could not do directly in TSQL. Usually, I get around or I simply do something outside SQL like a small C# console that will handle everything. I decided to take a look a CLR [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4245</guid>
         <pubDate>Tue, 01 Sep 2015 10:11:16 +0000</pubDate>
         <content:encoded><![CDATA[<p>This is the first time I had to have something that require a special business logic inside the database that I could not do directly in TSQL. Usually, I get around or I simply do something outside SQL like a small C# console that will handle everything. I decided to take a look a <strong>CLR SQL Server User-Defined Function</strong>. This article describes how to create your own C# method and use it within your TSQL. Albeit the feasibility and the success of the method, I removed the code at the end to make a console application and I will explain to you why.</p>
<p>First thing to do is to create a SQL Server Project.<br />
<a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4246"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/SqlServerDatabaseProject-400x147.png" alt="SqlServerDatabaseProject" width="400" height="147" class="aligncenter size-medium wp-image-4246"/></a><br />
Second task is to add a file that will have the code. You can right click the new project and add a new item. Select <strong>user defined function</strong>.<br />
<a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4247"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/SqlUserDefinedFunction-400x180.png" alt="SqlUserDefinedFunction" width="400" height="180" class="aligncenter size-medium wp-image-4247"/></a><br />
This will create a partial class named &#8220;UserDefinedFunctions&#8221;. You can rename the file with a custom name &#8212; what is important is to have the class as partial.</p>
<p>Finally, you write your own method. Mine was returning a single string so I had to return a <strong>SqlString</strong>. </p>
<pre>
public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlString HashPassword(string plainPassword)
    {
        byte[] salt;
        byte[] buffer2;
        using (var bytes = new Rfc2898DeriveBytes(plainPassword, 0x10, 0x3e8))
        {
            salt = bytes.Salt;
            buffer2 = bytes.GetBytes(0x20);
        }
        byte[] dst = new byte[0x31];
        Buffer.BlockCopy(salt, 0, dst, 1, 0x10);
        Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20);
        return new SqlString (Convert.ToBase64String(dst));
    }
}
</pre>
<p>This is the code I used. It does the hash of a plain password and return the hashed password. This algorithm is compatible with Entity Framework so it was a way to convert legacy password into Entity Framework format. You can see that not only that class is partial to a specific class, but it also has an attribute. The <strong>Microsoft.SqlServer.Server.SqlFunction</strong> is required to specify the type of the method for SQL. It also allows to add additional information like if the function is deterministic. </p>
<p>The last step is to <strong>publish</strong>. You need to right click the project, select Publish. This will raise a dialog where you need to select the database server, the database name, and the script to generate. This will build (if not already done) the project. The bin folder will contains the code (dll) but also a dacpac and a SQL file.<br />
<a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4247"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/SqlUserDefinedFunction-400x180.png" alt="SqlUserDefinedFunction" width="400" height="180" class="aligncenter size-medium wp-image-4247"/></a></p>
<p><a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4248"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/SqlUserDefinedFunctionBinFolder.png" alt="SqlUserDefinedFunctionBinFolder" width="210" height="139" class="aligncenter size-medium wp-image-4248"/></a></p>
<p>The dacpac is what is installed by Visual Studio into Sql Server. This is a file that contains SQL objects. It is used not only by C# code but could contains any SQL object like Sql Procedure for example. The format cannot be read by NotePad because it is a compressed file. You can unzip it if you are curious. And we are curious! So here is the code above dacpac unzipped file structures.<br />
<a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4250"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/dacpactunzipped-400x94.png" alt="dacpactunzipped" width="400" height="94" class="aligncenter size-medium wp-image-4250"/></a></p>
<p>The interesting file is the <em>model.xml</em>. It contains a reference to the DLL file but also the function metadata we created and the source of the code inside a CDATA.<br />
<a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4251"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/insidedacpac-400x260.png" alt="insidedacpac" width="400" height="260" class="aligncenter size-medium wp-image-4251"/></a><br />
That said, if you used Visual Studio, the function is already been installed for you. You can see it under the <strong>Scalar-valued Functions</strong>.</p>
<p><a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4252"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/06/ScalarValueFunctionSqlServer.png" alt="ScalarValueFunctionSqlServer" width="263" height="183" class="aligncenter size-full wp-image-4252"/></a></p>
<p>From here, you can just use a simple select, pass your parameter and you are all set.</p>
<p>If you cannot have you database working with CLR, it maybe because it is disabled. To enable, you need to do the following command once.</p>
<pre>
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'clr enabled', 1;
GO
RECONFIGURE;
GO
</pre>
<p>The problem I ran into is the performance. This is very slow compared to any native SQL code. It is also slower than execute the same code directly inside a simple Console application that loop through all the data. For example, removing that call take 7 seconds. Even if it wasn&#8217;t converting the password and keeping this one plain, the time was reasonable. Using the CRL SQL Server User-Defined Function the time raise to 11 minutes. Doing the loop in a console by reading the data and updating the value with ADO.Net took half of the time. The time is getting high because of the code itself which is not a simple task. Even if it takes few milliseconds to execute in a console, the hashing process is still little expensive to do. Also, CRL in SQL add a layer of slowness because the SQL engine need to stub inside your SQL query Microsoft intermediate language (MSIL) a bridge to the function. This generated stub is compiled into optimized code for the SQL Server you are executing this one to.</p>
<p>That said, the performance was quite slow from few seconds to several minutes. I had a huge script that was converting a lot of data, gigs and gigs of data across a lot of tables from one database to another. The overhead was not something I wanted to paid during the conversion and could be executed afterward by a small console job later. I could also use the CLR function in a second script later because even if the performance was several minutes, creating the console application wasn&#8217;t saving much more. That said, during the creation of the CLR function for SQL I got curious about performance and I learned that this is far from being a subject that is black or white. Most of the time, it depends of the operation executed to know if it worth it or not to use a C# CLR function. I personally believe it should be limited. Even if it is possible to debug with Visual Studio those function remotely, I believe that business logic should remain in the application tier &#8211;t he database should be used only for persisting the information. Nevertheless, special case like using Regex on string, doing special data manipulations can be not possible with SQL only. This is a great tool to have on your belt and should be used wisely.</p>]]></content:encoded>
      </item>
      <item>
         <title>Call for Speakers - Montréal-Python 54: Virtualized Utopia</title>
         <link>http://montrealpython.org/2015/08/cfp-mp54/</link>
         <description>&lt;p&gt;It's back to school so, at Montréal-Python, we are preparing for the first event of the season!&lt;/p&gt;
&lt;p&gt;We are back every second Monday of the month, so our next meeting will take place on Monday, September the 14th at 6:30pm at UQÀM.&lt;/p&gt;
&lt;p&gt;For the occasion, we are looking for speakers to give talks of 5, 10, 20, or even 45 minutes.&lt;/p&gt;
&lt;p&gt;Come tell us about your latest discoveries, your latest module, or your latest professional or personal realizations. It is your chance to meet with the local Python community.&lt;/p&gt;
&lt;p&gt;Send us your propositions at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;mailto:mtlpyteam@googlegroups.com&quot;&gt;mtlpyteam@googlegroups.com&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;When:&lt;/h2&gt;
&lt;p&gt;Monday, September 14th 2015&lt;/p&gt;
&lt;h2&gt;Schedule:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;6:00pm&lt;/strong&gt; — Doors open&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;6:30pm&lt;/strong&gt; — Presentations start&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;7:30pm&lt;/strong&gt; — Break&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;7:45pm&lt;/strong&gt; — Second round of presentations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;9:00pm&lt;/strong&gt; — One free beer offered at Bénélux just across the street&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;We’d like to thank our sponsors for their continued support:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;UQÀM&lt;/li&gt;
&lt;li&gt;Bénélux&lt;/li&gt;
&lt;li&gt;w.illi.am/&lt;/li&gt;
&lt;li&gt;Outbox&lt;/li&gt;
&lt;li&gt;Savoir-faire Linux&lt;/li&gt;
&lt;li&gt;Caravan&lt;/li&gt;
&lt;li&gt;iWeb&lt;/li&gt;
&lt;/ul&gt;</description>
         <guid isPermaLink="false">http://montrealpython.org/2015/08/cfp-mp54/</guid>
         <pubDate>Fri, 28 Aug 2015 04:00:00 +0000</pubDate>
      </item>
      <item>
         <title>Change the URL with JavaScript without redirecting</title>
         <link>http://patrickdesjardins.com/blog/change-the-url-with-javascript-without-redirecting</link>
         <description>If you have a part of your website that need to change the URL in the browser without having to refresh the whole page, than you shouldn&amp;#8217;t use the window.location.href because this one will redirect into that page. window.location contains 2 others method that can do the job for you. The first one is assign. [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4241</guid>
         <pubDate>Wed, 26 Aug 2015 11:47:02 +0000</pubDate>
         <content:encoded><![CDATA[<p>If you have a part of your website that need to change the URL in the browser without having to refresh the whole page, than you shouldn&#8217;t use the window.location.<strong>href</strong> because this one will redirect into that page. <strong>window.location</strong> contains 2 others method that can do the job for you. The first one is <em>assign</em>. window.location.assign(<em>url</em>) is a method that will change the url and set in your history the new url. Sometime, we want to browser to change but not the history. A second method does that job &#8212; it&#8217;s called replace.</p>
<p>On the other hand, doing that mean that the user can navigate directly into your webpage by the url in the browser. If you changed the URL by just changing a hash tag that define a specific action in your website, you may have that action trigged by the click event but not when the user access the webpage directly from the url. </p>
<p>For example, you have several link for action like &#8220;open item1&#8221; and &#8220;open item2&#8221;. You change the url with <strong>window.location.assign</strong> because you want the user to be able to use the back button &#8212; use the history. So the history looks like this:</p>
<ul>
<li>http://yourwebsite.com/page1</li>
<li>http://yourwebsite.com/page1#item1</li>
<li>http://yourwebsite.com/page1#item2</li>
</ul>
<p>If someone go directly to the <em>item2</em> than you need to execute the code behind this hash tag. To have your code executed you need to use the window event called <strong>onhashchange</strong>.</p>
<pre>
    window.onhashchange = function() {
        //Get the hash value from the url and execute your code       
    };
</pre>
<p>The <strong>onhashchange</strong> become a hub if all time the url change which can be convenient to have a central place has a content controller. This method removes the need to have action handled in every click that has hash url to just have the click event of these links to change the url and let the <strong>onhashchange</strong> handles which action to execute.</p>
<p>Here is an example:</p>
<pre>
&lt;a id=&quot;report&quot;&gt;Current Order Report&lt;/a&gt;
&lt;a id=&quot;edit&quot;&gt;Edit Current Order&lt;/a&gt;
</pre>
<pre>
$('#report').click(function(){
    window.location.assign(&quot;#open-current-report&quot;);
});

$('#edit').click(function(){
    window.location.assign(&quot;#edit-order&quot;);
});

window.onhashchange = function(){
    if(window.location.hash) {
        var hashFragment = window.location.hash.substring(1); // Get hash value (without #)
        switch(hashFragment) {
            case &quot;open-current-report&quot;:
                //Do your action
                break;
            case &quot;edit-order&quot;:
                //Do your action
                break;
        }  
  }
};
</pre>
<p>This example use JQuery to attach the click event but this is not required for the location assign, neither for the <strong>onhashchange</strong> &#8212; they are both pure JavaScript method and event.</p>]]></content:encoded>
         <category>Javascript</category>
      </item>
      <item>
         <title>How to create a bottom-right fixed button in CSS with expanding hover animation</title>
         <link>http://patrickdesjardins.com/blog/how-to-create-a-bottom-right-fixed-button-in-css-with-expanding-hover-animation</link>
         <description>If you need to have a button with minimal information and when the user hover this one give more input before executing the action, here is something interesting. The code illustrates a use case that the button is fixed to the browser at the bottom-right of the screen but this kind of button can be [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4234</guid>
         <pubDate>Tue, 18 Aug 2015 10:25:27 +0000</pubDate>
         <content:encoded><![CDATA[<p>If you need to have a button with minimal information and when the user hover this one give more input before executing the action, here is something interesting. The code illustrates a use case that the button is fixed to the browser at the bottom-right of the screen but this kind of button can be used everywhere. The main purpose is to have a rich user experience with pro-active feedback in a minimal way. The initial state of the button is just a single icon.<br />
<a rel="nofollow" target="_blank" href="http://patrickdesjardins.com/blog/?attachment_id=4237"><img src="http://patrickdesjardins.com/blog/wp-content/uploads/2015/05/PlusImage.png" alt="PlusImage" width="88" height="95" class="aligncenter size-full wp-image-4237"/></a><br />
For that example, I haven&#8217;t use a glyph icon, neither an image, just a single plus character. This could be replaced with what ever you want. The idea is that when the user hover the icon that we have a transition to a bigger button.</p>
<p>Here is the button&#8217;s Html. The container is not required and is just there for the purpose of having this button sticky at the bottom-right of the window. The button element is the real button. This one will grows when hovering. It contains two texts: one when collapsed and one when extended.</p>
<pre>
&lt;div class=&quot;right-corder-container&quot;&gt;
    &lt;button class=&quot;right-corder-container-button&quot;&gt;
        &lt;span class=&quot;short-text&quot;&gt;+&lt;/span&gt;
        &lt;span class=&quot;long-text&quot;&gt;Add Me&lt;/span&gt;
    &lt;/button&gt;
&lt;/div&gt;
</pre>
<p>The css does 90% of the job. The remaining 10% is that we need to have a hover JavaScript to add and remove a class to add the long text visibility. The first CSS style is about fixing the container at the bottom-right of the browser&#8217;s window.</p>
<pre>
.right-corder-container {
    position:fixed;
    right:20px;
    bottom:20px;
}
</pre>
<p>The next CSS style is what round up the button into a perfect circle. This is also where we setup the transition effect timing.</p>
<pre>
.right-corder-container .right-corder-container-button {
    height: 62px;
    width: 62px;
    border:none;
    background-color:#6FB583;
    border-radius: 62px;        /*Transform the square into rectangle, sync that value with the width/height*/
    transition: all 300ms;      /*Animation to close the button (circle)*/
    box-shadow:2px 2px 5px rgb(25, 73, 15)  ;
    cursor:pointer;
}
</pre>
<p>The span specify the plus sign to be placed in the middle. We use absolute position to have fined precision about where to place the text. Also, this is easier to ensure that even during the effect that this one remains at the same place.</p>
<pre>
.right-corder-container .right-corder-container-button span {
    font-size: 72px;
    color:white;
    position: absolute;
    left: 10px;
    top: 16px;
    line-height: 28px;
}
</pre>
<p>The hover is where we specify the size of the final stage of the button. We also change the right side to be less round. This way, the button appears to be less than an oval, more to a label.</p>
<pre>
.right-corder-container .right-corder-container-button:hover {
    transition: all 400ms cubic-bezier(.62,.1,.5,1);      
    width:200px;                                            
    border-top-right-radius: 5px;                           
    border-bottom-right-radius: 5px;                        
}
</pre>
<p>The next style block is about the long text effect. We want this text to appear slowly. We need to tweak some properties to be sure that the vertical scroll-bar does not get affected.</p>
<pre>
/*
    Long text appears slowly with an animation. That code prepare the animation by hidding the text.
    The use of display is not there because it does not work well with CSS3 animation.
*/
.right-corder-container .right-corder-container-button .long-text {
    transition: opacity 1000ms; /*Only the text fadein/fadeout is animated*/
    opacity:0;                /*By default we do not display the text, we want the text to fade in*/
    color:white;
    white-space: nowrap;      
    font-size: 0;             /*Set to 0 to not have overflow on the right of the browser*/
    width: 0;                 /*Set to 0 to not have overflow on the right of the browser*/
    margin:0;                 /*Set to 0 to not have overflow on the right of the browser*/
}
</pre>
<p>This is how we show the long text. We need to add a delay in the transition opacity because we do not want to start showing the text too early. Mostly because the contain size is animated and not big enough to receive the text yet.</p>
<pre>
/*
    Animation to have a text that appear progressively. We need to play with a delay
    on the width and the font-size to not have the browser have the text appears on the right
    side of the browser view port. This has the side-effect of having an horizontal bar.
*/
.right-corder-container .right-corder-container-button .long-text.show-long-text{
  transition: opacity 700ms,
              width 1ms linear 270ms,       /*two thirds of the animation on the container width*/
              font-size 1ms linear 270ms;   /*two thirds of the animation on the container width*/
  opacity:1;
  margin-top: 2px;                          /*Center the position vertically*/
  margin-left: 65px;                        /*Center between the + and the right end side*/
  font-size: 20px;                          /*Text size, cannot be defined initially without moving the scrollbar*/
  width: auto;                              /*Required to be set with a delay (see animation) to not have scrollbar. Delay is to wait container to size up*/
}
</pre>
<p>The JavaScript is minimal and you do not have to use JQuery for a simple task as this. However, I had this one already available to here is the code with JQuery.</p>
<pre>
$(&quot;.right-corder-container-button&quot;).hover(function() {
    $(&quot;.long-text&quot;).addClass(&quot;show-long-text&quot;);   
}, function () {
    $(&quot;.long-text&quot;).removeClass(&quot;show-long-text&quot;);
});
</pre>
<p>This code is available in <a rel="nofollow" target="_blank" href="http://jsfiddle.net/mrdesjardins/tbtn7wow/">JSFiddle.</a></p>
<p></p>]]></content:encoded>
      </item>
      <item>
         <title>August Dinner – Souper du mois d’août</title>
         <link>http://www.montrealrb.com/2015/08/august-dinner-souper-du-mois-daout/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=august-dinner-souper-du-mois-daout</link>
         <description>&amp;#160; Français: Il est maintenant une tradition que la rencontre du mois d’août soit un souper dans un restaurant. Le rendez-vous est au McKibbins sur Saint-Laurent à 18h30. &amp;#160; Quand: 18 août à 18h30 Où: McKibbins sur Saint-Laurent &amp;#8211; 245 Sherbrooke Ouest Qui: Tout le monde! Combien: L&amp;#8217;entrée est gratuite, mais la nourriture et les [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=6021</guid>
         <pubDate>Tue, 18 Aug 2015 00:51:43 +0000</pubDate>
         <content:encoded><![CDATA[<p>&nbsp;</p>
<h3>Français:</h3>
<hr />
<p>Il est maintenant une tradition que la rencontre du mois d’août soit un souper dans un restaurant. Le rendez-vous est au <a rel="nofollow" target="_blank" href="https://www.google.ca/maps/dir//Mckibbins+Irish+Pub,+C%C3%A9gep+du+Vieux+Montr%C3%A9al,+3515+Boul+St-Laurent,+Montr%C3%A9al,+QC+H2X+2T6/@45.5133953,-73.5711568,17z/data=!4m13!1m4!3m3!1s0x4cc91a4a605763e3:0xbae2dfa79c915c2b!2sMckibbins+Irish+Pub!3b1!4m7!1m0!1m5!1m1!1s0x4cc91a4a605763e3:0xbae2dfa79c915c2b!2m2!1d-73.5711568!2d45.5133953">McKibbins sur Saint-Laurent</a> à 18h30.</p>
<p>&nbsp;</p>
<p>Quand: 18 août à 18h30</p>
<p>Où: <a rel="nofollow" target="_blank" href="https://www.google.ca/maps/dir//Mckibbins+Irish+Pub,+C%C3%A9gep+du+Vieux+Montr%C3%A9al,+3515+Boul+St-Laurent,+Montr%C3%A9al,+QC+H2X+2T6/@45.5133953,-73.5711568,17z/data=!4m13!1m4!3m3!1s0x4cc91a4a605763e3:0xbae2dfa79c915c2b!2sMckibbins+Irish+Pub!3b1!4m7!1m0!1m5!1m1!1s0x4cc91a4a605763e3:0xbae2dfa79c915c2b!2m2!1d-73.5711568!2d45.5133953">McKibbins sur Saint-Laurent</a> &#8211; 245 Sherbrooke Ouest</p>
<p>Qui: Tout le monde!</p>
<p>Combien: L&#8217;entrée est gratuite, mais la nourriture et les consommations ne sont pas inclus.</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenu</p>
<p>Questions?: Contactez <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a></p>
<p>&nbsp;</p>
<h3>English:</h3>
<p>It is now a tradition that the meeting of August is a dinner in a restaurant. The meeting place is the <a rel="nofollow" target="_blank" href="https://www.google.ca/maps/dir//Mckibbins+Irish+Pub,+C%C3%A9gep+du+Vieux+Montr%C3%A9al,+3515+Boul+St-Laurent,+Montr%C3%A9al,+QC+H2X+2T6/@45.5133953,-73.5711568,17z/data=!4m13!1m4!3m3!1s0x4cc91a4a605763e3:0xbae2dfa79c915c2b!2sMckibbins+Irish+Pub!3b1!4m7!1m0!1m5!1m1!1s0x4cc91a4a605763e3:0xbae2dfa79c915c2b!2m2!1d-73.5711568!2d45.5133953">McKibbins on Saint-Laurent street</a> at 6:30pm.</p>
<p>&nbsp;</p>
<p>When: August 18th, 2015 at 18:30</p>
<p>Where: <a rel="nofollow" target="_blank" href="https://www.google.ca/maps/dir//Mckibbins+Irish+Pub,+C%C3%A9gep+du+Vieux+Montr%C3%A9al,+3515+Boul+St-Laurent,+Montr%C3%A9al,+QC+H2X+2T6/@45.5133953,-73.5711568,17z/data=!4m13!1m4!3m3!1s0x4cc91a4a605763e3:0xbae2dfa79c915c2b!2sMckibbins+Irish+Pub!3b1!4m7!1m0!1m5!1m1!1s0x4cc91a4a605763e3:0xbae2dfa79c915c2b!2m2!1d-73.5711568!2d45.5133953">McKibbins on Saint-Laurent street</a> &#8211; 3515 Boulevard Saint-Laurent</p>
<p>Who: Everybody!</p>
<p>How much: Free, but food and drinks are not included</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: Contact <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a></p>]]></content:encoded>
         <category>Uncategorized</category>
      </item>
      <item>
         <title>PyCon Canada: Call for Speaker is ending soon</title>
         <link>http://montrealpython.org/2015/08/pycon-ca-cfp-ending-soon/</link>
         <description>&lt;p&gt;Pythonistas,&lt;/p&gt;
&lt;p&gt;The Call for Proposals for PyCon Canada 2015 is ending soon. We've heard that they have been receiving many amazing proposals. It is quite exciting to see the Canadian Python community all together again in November in Toronto.&lt;/p&gt;
&lt;p&gt;If you have not yet submitted a talk or had not considered giving one, please be aware that talk slots can be either 5-10 minutes or 25-30 minutes, so whether you have a long form presentation or a quick lightning talk, it is quite exciting and looking forward to see your talk. A few suggestions: something Python related that you find interesting, something you’ve been working on, a tool that you have found helpful, tips and tricks you’d like to share, or ways in which you’ve used Python poorly, but would like to save others the same pain would all be great talks! Submissions are due by this Friday, August 14 so please get yours in today!&lt;/p&gt;
&lt;p&gt;As well, if you are interested in running a tutorial session on your favourite topic. Please get in touch with the PyCon Canada team at &lt;a rel=&quot;nofollow&quot;&gt;proposals@pycon.ca&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The PyCon Canada team is also actively seeking sponsors to help make this event possible. Sponsoring PyCon Canada 2015 is a great way to foster and strengthen your ties with the community, so please reach out to &lt;a rel=&quot;nofollow&quot;&gt;sponsorship@pycon.ca&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Please share the word!&lt;/p&gt;
&lt;p&gt;And you have need any help at creating your proposal please reach us at &lt;a rel=&quot;nofollow&quot;&gt;mtlpyteam@googlegroups.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For more informations about PyCon Canada 2015, please have a look at the website at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://2015.pycon.ca/&quot;&gt;https://2015.pycon.ca/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;logo&quot; src=&quot;https://2015.pycon.ca/images/logo.png&quot;/&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://montrealpython.org/2015/08/pycon-ca-cfp-ending-soon/</guid>
         <pubDate>Wed, 12 Aug 2015 04:00:00 +0000</pubDate>
      </item>
      <item>
         <title>How to unit test private method</title>
         <link>http://patrickdesjardins.com/blog/how-to-unit-test-private-method</link>
         <description>This is something that I got asked from little start-up up to Microsoft. How to you test private method? I often see horrible things. For example, if your class as 1 public method that call 5 privates method and you want to unit test 1 of the 5 methods, calling the public method to do [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4228</guid>
         <pubDate>Mon, 10 Aug 2015 08:42:11 +0000</pubDate>
         <content:encoded><![CDATA[<p>This is something that I got asked from little start-up up to Microsoft. How to you test private method? I often see horrible things. For example, if your class as 1 public method that call 5 privates method and you want to unit test 1 of the 5 methods, calling the public method to do so is wrong. Something can change anywhere in the class and break that test. Also, creating test this way is painful because it takes time to setup all variables to value that make all others method not fail. Once you reach the method you want to test you can start really testing what you are there for. An other horrible thing is to start using advanced shimming stuff that rely on reflection. The solution is simple : create more cohesive classes.</p>
<p>I think an example is better before continuing about how to divide code to help creating more efficient unit test. Here is a snippet that illustrate many problem. We have an Order class that has a list of item that can be bought. At some point, we want to pass a transaction so we have a method called Purchase which return the list of item that we can really purchase based on different business logic. For example, we allows only item that is between 0$ and 100$ to be bought, only item that is not discontinued, we can only buy 1 item of any kind per transaction, not more than 3 items at the same time can be in the basket and finally nothing above an order of 50$ is allowed (so we only add item to be purchase under 50$).</p>
<pre>
public class ShoppingBasket
{
    public List&lt;Item&gt; Items { get; set; }

    public List&lt;Item&gt; Purchase()
    {
        var canBeBought = new List&lt;Item&gt;();
        foreach (var item in Items)
        {
            bool canBuy = true;
            if (item.Money &lt; 0 || item.Money &gt; 100)
            {
                canBuy = false;
            }

            if (item.IsDiscontinued)
            {
                canBuy = false;
            }

            if (!this.IsUnique(item.Id))
            {
                canBuy = false;
            }

            if (this.IsShoppingBasketFull())
            {
                canBuy = false;
            }

            if (this.HasReachMaximumAmountPerOrder(canBeBought))
            {
                canBuy = false;

            }
            if (canBuy)
            {
                canBeBought.Add(item);
            }
        }
        return canBeBought;
    }

    private bool IsUnique(int id)
    {
        return this.Items.Count(d =&gt; d.Id == id) &gt; 1;
    }

    private bool IsShoppingBasketFull()
    {
        return this.Items.Count &gt;= 5;
    }

    private bool HasReachMaximumAmountPerOrder(List&lt;Item&gt; canBeBought)
    {
        return canBeBought.Sum(d=&gt;d.Money) &gt; 50;
    }
}

public class Item
{
    public int Id { get; set; }

    public double Money { get; set; }

    public bool IsDiscontinued { get; set; }
}
</pre>
<p>If you want to test if the Lambda expression is well formed for the <em>IsUnique</em> method, you will have to create a list of items and pass it to the <em>ShoppingBasket</em> class. So far, this is fine. However, you cannot call the method IsUnique because this one is private. You have two choices. You break the encapsulation of the <em>ShoppingBasket</em> by changing the visibility from private to public or you refactor your class to something more testable, more cohesive and more object oriented. Changing the encapsulation is fine. In fact, in that case it does not really matter because it does not disrupt the system. Someone could call <em>IsUnique</em> any time and it does not change any operational flow. However, is it really the responsability of the <em>ShoppingBasket</em> to handle the unique?</p>
<p>Let&#8217;s start trying to unit test this actual code to illustrate how it is not a good idea to test through the public method to reach a private method.</p>
<pre>
[TestMethod]
public void TestIfIsUniqueMethodWorksWhenListHasNotUniqueItem()
{
    // Arrange
    var shoppingBasket = new ShoppingBasket();
    var item1 = new Item() {Id = 1, IsDiscontinued = false, Money = 5};
    var item2 = new Item() {Id = 2, IsDiscontinued = false, Money = 10};
    var item3 = new Item() {Id = 3, IsDiscontinued = false, Money = 50};
    var item4 = new Item() {Id = 1, IsDiscontinued = false, Money = 5};
    shoppingBasket.Items = new List&lt;Item&gt; {item1, item2, item3, item4};

    // Act
    var itemThatWeCanPurchase = shoppingBasket.Purchase();

    // Assert
    Assert.AreEqual(2, itemThatWeCanPurchase.Count);
}
</pre>
<p>You will tell me that this is fine. In fact, it is. In that case the problem is not the amount of preparation. It is often the case, but not that time. The problem is that if tomorrow the threshold of 50$ go down to 10$ that this unit test will fail. Right now, the item id 2 and 3 are returned but if this limit goes from 50$ to 10$ than the id 2 is out which will return only one item. The unit test about unique fail because of the maximum amount per order. This is wrong.</p>
<p>A unit test must test a unit. It has to test a single thing. It has to be atomic. This is why we need to refactor that code.</p>
<p>The first thing to do is to ask who is the expert of the field for each logic. The first logic concern the logic about that we can only buy item with money between 0$ and 100$. This raise multiple questions.</p>
<ol>
<li>Is it a shopping basket logic?</li>
<li>Does that logic is universal on the software we are building or just for specific case? Does this range may change during the lifetime of this software?</li>
<li>Do we have different kind of Item?</li>
</ol>
<p>The first question make sense. Maybe depending of the type of shopping basket that logic can change. For example you could have &#8220;SmallShoppingBasket&#8221; and a &#8220;BigShoppingBasket&#8221; and depending of the basket the threshold change. This is why we cannot build a software without knowing the specification: the code changes depending of what are the rules. Creating a generic system for all case increase the time to build this one by a huge magnitude of time. That said, for that first condition, we need to extract that code out of the loop in all case. The reason is that this condition is independent of all items &#8212; it is a condition on a single item. Since we are not planning to have multiple basket and the amount belong to an item, for that use case, it makes sense to set the condition inside the Item class. This change result having one more method in Item and the unit test to call that method.</p>
<pre>
public class Item
{
    public int Id { get; set; }

    public double Money { get; set; }

    public bool IsDiscontinued { get; set; }

    public bool IsPriceLegitForPurchase()
    {
        return this.Money &lt; 0 || this.Money &gt; 100;
    }
}
</pre>
<p>The second condition is checking if the item is discontinued. The call is already on the item which is great. However, already have a condition on the item done one line above since our last refactoring on the price.</p>
<pre>
foreach (var item in Items)
{
    bool canBuy = true;
    if (!item.IsPriceLegitForPurchase())
    {
        canBuy = false;
    }

    if (item.IsDiscontinued)
    {
        canBuy = false;
    }
    // ...
</pre>
<p>Instead of calling twice the item we should think. These two operations has something in common: it validates the item for purchase. We should have a method in the item that does that for us. Not only it will self-document what it is going on but that logic could be reused later without having to duplicate both calls. We end up having a single validation method for purchase in item.</p>
<pre>
public bool IsValidForPurchase()
{
        if (!this.IsPriceLegitForPurchase())
        {
            return false;
        }

        if (this.IsDiscontinued)
        {
            return false;
        }
    return true;
}
</pre>
<p>The test is also clearer.</p>
<pre>
//...
if(!item.IsValidForPurchase())
{
   canBuy = false;
}
//...
</pre>
<p>The third condition was to check if the shopping basket is full. The logic belong to the basket because this one is the one who know its size, which is 5. The problem is that when we will test that logic, we do not want to have to create items that necessary pass condition for &#8220;IsValidForPurchase&#8221; method. We just want to create a list of item and test the count. That said, this is a perfect case that this method should be public.</p>
<p>The next condition is about if the list of item that is valid to purchase has still some place to add additional item. This is an interesting case. This logic does not belong to item, it belongs to the list. It means that this list is an entity which some properties, states, etc. </p>
<pre>
public class ItemValidToPurchase : List&lt;Item&gt;
{
    public bool HasReachMaximumAmountPerOrder()
    {
        return this.Sum(d =&gt; d.Money) &gt; 50;
    }
}
</pre>
<p>The condition in the Shopping Basket is just to call the method.</p>
<pre>
if (canBeBought.HasReachMaximumAmountPerOrder())
{
    canBuy = false;
}
</pre>
<p>So the final code looks like this for the test <strong>about unique</strong>.</p>
<pre>

private ShoppingBasket GetShoppingBasket()
{
    var shoppingBasket = new ShoppingBasket();
    var item1 = new Item() {Id = 1, IsDiscontinued = false, Money = 5};
    var item2 = new Item() {Id = 2, IsDiscontinued = false, Money = 10};
    var item3 = new Item() {Id = 3, IsDiscontinued = false, Money = 20};
    var item4 = new Item() {Id = 1, IsDiscontinued = false, Money = 5};
    shoppingBasket.Items = new List&lt;Item&gt; {item1, item2, item3, item4};
    return shoppingBasket;
}

[TestMethod]
public void TestIfIsUniqueMethodWorksWhenListHasNotUniqueItem()
{
    // Arrange
            var shoppingBasket = this.GetShoppingBasket();

    // Act
    var isUnique = shoppingBasket.IsUnique(1);

    // Assert
    Assert.IsFalse(isUnique);
}

[TestMethod]
public void TestIfIsUniqueMethodWorksWhenListHasUniqueItem()
{
    // Arrange
    var shoppingBasket = this.GetShoppingBasket();

    // Act
    var isUnique = shoppingBasket.IsUnique(2);

    // Assert
    Assert.IsTrue(isUnique);
}
</pre>
<p>And the classes code look.</p>
<pre>
public class Item
{
    public int Id { get; set; }

    public double Money { get; set; }

    public bool IsDiscontinued { get; set; }

    public bool IsPriceLegitForPurchase()
    {
        return this.Money &lt; 0 || this.Money &gt; 100;
    }

    public bool IsValidForPurchase()
    {
            if (!this.IsPriceLegitForPurchase())
            {
                return false;
            }

            if (this.IsDiscontinued)
            {
                return false;
            }
        return true;
    }
}
public class ItemValidToPurchase : List&lt;Item&gt;
{
    public bool HasReachMaximumAmountPerOrder()
    {
        return this.Sum(d =&gt; d.Money) &gt; 50;
    }
}
public class ShoppingBasket
{
    public List&lt;Item&gt; Items { get; set; }

    public ItemValidToPurchase Purchase()
    {
        var canBeBought = new ItemValidToPurchase();
        foreach (var item in Items)
        {
            bool canBuy = true;
            if(!item.IsValidForPurchase())
            {
                canBuy = false;
            }

            if (!this.IsUnique(item.Id))
            {
                canBuy = false;
            }

            if (this.IsShoppingBasketFull())
            {
                canBuy = false;
            }

            if (canBeBought.HasReachMaximumAmountPerOrder())
            {
                canBuy = false;
            }

            if (canBuy)
            {
                canBeBought.Add(item);
            }
        }
        return canBeBought;
    }

    public bool IsUnique(int id)
    {
        return this.Items.Count(d =&gt; d.Id == id) == 1;
    }

    public bool IsShoppingBasketFull()
    {
        return this.Items.Count &gt;= 5;
    }
}
</pre>
<p>As you can see, the condition has changed on the IsUnique method. Because and error was present and only could have been detected with a valid set of unit test on that method. We could go even further by refactoring even more this code. I&#8217;ll write a second post about what we could have done with a more flexible code that allow to have dynamic validation using other design pattern.</p>
<p>You can find the initial code and the final code in this <a rel="nofollow" target="_blank" href="https://github.com/MrDesjardins/UnitTestPrivateMethods">Git Repository</a>.</p>]]></content:encoded>
         <category>Test</category>
      </item>
      <item>
         <title>Quick Add Html Button with CSS3 and JQuery</title>
         <link>http://patrickdesjardins.com/blog/quick-add-html-button-with-css3-and-jquery</link>
         <description>This is a small JavaScript and CSS control that allows to have some edition from a textbox in a fashion that this one is only a button to minimize space and once clicked become a more extended version. The goal is to have a way to add information in a quick way without taking too [&amp;#8230;]</description>
         <guid isPermaLink="false">http://patrickdesjardins.com/blog/?p=4217</guid>
         <pubDate>Tue, 04 Aug 2015 09:52:03 +0000</pubDate>
         <content:encoded><![CDATA[<p>This is a small JavaScript and CSS control that allows to have some edition from a textbox in a fashion that this one is only a button to minimize space and once clicked become a more extended version. The goal is to have a way to add information in a quick way without taking too much space. This is perfect for situation where adding information is not the main task. The use case is that a user want to add information which require a text box. The user click the button to open the edition which reveal a text box. The button does not need to stay there because we want to save space so the button transforms into a closing button which cancel the operation if required. When the user starts to type, a save button is added. From there, the user can click the cancel button or hit save. In both case, the text box is rolling back and the user interface come back to the initial state. This design is intended to be minimal. There is not label. This is why we need to use a watermark, also known as placeholder in the text box. Since we want to limit button, the expand button and cancel (collapse) button is the same. To make sure that the user knows what the button is doing we display a tooltip but also we have an animation that transform visually the button to its intend.</p>
<p>To keep it simples, let&#8217;s start with a division that will hold all our Html elements.</p>
<pre>
&lt;div id=&quot;container&quot;&gt;
&lt;/div&gt;
</pre>
<p>Next, we need to create our three main controls. The first one is the input where the user will write any information that will be saved. The second one is the toggle button that expand or collapse the input box and the third one is the save button that will be displayed only when the user save.</p>
<pre>
var $controlContainer = $('#container');

var $inputBox = $(&quot;&lt;input&gt;&quot;)
	.attr('id', 'inline-editor-textbox')
        .attr('type', 'text')
	.attr('value', '')
	.attr('maxlength', 20 )
	.attr('style', 'display:none')
	.attr('placeholder', &quot;This is some watermark&quot;)
	.addClass('hide-input-inline')
	;
$inputBox.appendTo($controlContainer);

var $buttonToggle = $(&quot;&lt;button&gt;&quot;)
	.attr('id', 'toggleButton')
	.attr('title', 'Open')
	.attr('type', 'button');
var $spanIcon = $('&lt;span&gt;')
	.addClass(&quot;glyphicon glyphicon-plus&quot;);
$spanIcon.appendTo($buttonToggle);
$buttonToggle.appendTo($controlContainer);

var $buttonOk = $(&quot;&lt;button&gt;&quot;)
	.attr('id', 'okButton')
	.attr('style', 'display:none')
	.attr('title', 'Ok')
	.addClass('hide-ok-button')
	.attr('type', 'button');
var $spanIconOk = $('&lt;span&gt;')
	.addClass(&quot;glyphicon glyphicon-save&quot;);
$spanIconOk.appendTo($buttonOk);
$buttonOk.appendTo($controlContainer);

</pre>
<p>The next step is to add events. The toggle will open and close the input. It will also change the icon of the button from a &#8220;+&#8221; to a &#8220;x&#8221;. The okay button will save the information and collapse the input if everything is fine. The keyup is there to show the save button if the text box contains text.</p>
<pre>
$buttonToggle.click({ input: $inputBox, buttonToggle: $buttonToggle, buttonOk: $buttonOk},onToggle);
$buttonOk.click({ input: $inputBox, buttonToggle: $buttonToggle, buttonOk: $buttonOk},onOk);
$inputBox.keyup( { input: $inputBox, buttonOk: $buttonOk }, onKeyUp);
</pre>
<p>The toggle function has reference to some of our controls. This is a great way to pass reference without having to communicate through JQuery selector. Depending of the state of the toggle, which is the class &#8220;hide-input-inline&#8221; we make it appears or not. We add a delay because we have CSS3 animation and we want everything to be smooth together.</p>
<pre>
function onToggle(jqueryEvent) {
	var data = jqueryEvent.data;
	var $input = data.input;
	var $buttonToggle = data.buttonToggle;
	var $buttonOk = data.buttonOk;

	var isHidden = $input.hasClass(&quot;hide-input-inline&quot;);
	if (isHidden) {
		$input.fadeIn();                            
		$input.removeClass(&quot;hide-input-inline&quot;);    
		$input.addClass(&quot;show-input-inline&quot;);       
		$input.val('');                             
		$buttonToggle.addClass(&quot;add-to-close&quot;);     
		$buttonToggle.attr('title', 'Close');
	}
	else {
		$input.removeClass(&quot;show-input-inline&quot;);   
		$input.addClass(&quot;hide-input-inline&quot;)      
			.delay(600)
			.fadeOut();                             
		$buttonToggle.removeClass(&quot;add-to-close&quot;);  
		$buttonOk.addClass(&quot;hide-ok-button&quot;);     
		$buttonOk.removeClass(&quot;show-ok-button&quot;)
			.delay(600)
			.fadeOut();                             
		$buttonToggle.attr('title', 'Open');
	}
}
</pre>
<p>The key up is to check the length but we could also check for &#8220;Enter&#8221; to be pressed and invoke the Ok code. The code is adding or removing classes, with a delay to let CSS animation to be executed.</p>
<pre>
function onKeyUp(jqueryEvent) {
	var data = jqueryEvent.data;
	var $input = data.input;
	var $buttonOk = data.buttonOk;
	if ($input.val().length === 0) {
		$buttonOk.removeClass(&quot;show-ok-button&quot;);
		$buttonOk.addClass(&quot;hide-ok-button&quot;)
			.delay(600)
			.fadeOut(); 
		htmlElementWithIconState($buttonOk, true);
	} else {
		$buttonOk.fadeIn();
		$buttonOk.addClass(&quot;show-ok-button&quot;);
		$buttonOk.removeClass(&quot;hide-ok-button&quot;);
		htmlElementWithIconState($buttonOk, false);
	}
}
</pre>
<p>This helper method is used to mark the save icon into a disable state. At this moment, this is not really used but if validation is added we could still have the button add without having to remove it until the user fix the problem.</p>
<pre>	
function htmlElementWithIconState($element, disabled) {
    $element.prop(&quot;disabled&quot;, disabled);
    $element.find('.glyphicon').css('opacity', (disabled === true) ? .4 : 1);	
}
</pre>
<p>Finally, we have the okay button hit which close up the text box and every buttons. In real life, a callback into a real save or okay code would be executed. If successful than close, otherwise keep everything open for the user to adjust his or her input.</p>
<pre>	
function onOk(jqueryEvent) {
	var data = jqueryEvent.data;
	var $input = data.input;
	var $buttonOk = data.buttonOk;
	
	onToggle(jqueryEvent);
}
</pre>
<pre>
#toggleButton,
#okButton
 {
    padding:0 2px 4px 2px;         
    margin-left:3px;               
    height: 22px;                  
    width: 22px;                   
    vertical-align: top;           
}


#toggleButton span.glyphicon
{
    transition: all 1000ms ease;
}


#okButton {
    transition: all 1000ms ease;
}


.hide-input-inline {
    width:0;
    transition: width 1000ms ease-in-out;
}


.show-input-inline {
    width:210px;
    transition: width 1000ms ease-in-out;
}


.add-to-close span {
    transform: rotate(135deg);
}


.hide-ok-button {
    opacity:0;

}


.show-ok-button {
    opacity:1;
}

	
#inline-editor-textbox::-webkit-input-placeholder { /* WebKit browsers */
    color:#7f7f7f

}
#inline-editor-textbox {
    border: none;
    background-color: #E2E2E2;
    color:#7f7f7f;
    padding-left:4px;
    height:22px;/*To fix the size of the button since we do not have any border*/
}

#inline-editor-textbox:focus {
    outline: none; 
    background-color:white; 
}
</pre>
<p></p>]]></content:encoded>
      </item>
      <item>
         <title>Meetup du 21 Juillet – July 21th Meetup</title>
         <link>http://www.montrealrb.com/2015/07/meetup-du-21-juillet-july-21th-meetup/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=meetup-du-21-juillet-july-21th-meetup</link>
         <description>&amp;#160; Français: Pour le meetup de Juillet, on fait une pause des présentation et on se rend directement au Benelux (18h30 comme d&amp;#8217;habitude). Ce sera beaucoup plus amical et détendu comme soirée. &amp;#160; Quand: 21 Juillet à 18h30 Où: Benelux &amp;#8211; 245 Sherbrooke Ouest Qui: Tout le monde! Combien: Gratuit Inscription: Pas besoin, tout le [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=5951</guid>
         <pubDate>Tue, 21 Jul 2015 01:37:09 +0000</pubDate>
         <content:encoded><![CDATA[<p>&nbsp;</p>
<h3>Français:</h3>
<hr />
<p>Pour le meetup de Juillet, on fait une pause des présentation et on se rend directement au Benelux (18h30 comme d&#8217;habitude). Ce sera beaucoup plus amical et détendu comme soirée. </p>
<p>&nbsp;</p>
<p>Quand: 21 Juillet à 18h30</p>
<p>Où: <a rel="nofollow" target="_blank" href="http://brasseriebenelux.com/">Benelux</a> &#8211; 245 Sherbrooke Ouest</p>
<p>Qui: Tout le monde!</p>
<p>Combien: Gratuit</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenu</p>
<p>Questions?: Contactez <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a></p>
<p>&nbsp;</p>
<h3>English:</h3>
<p>July&#8217;s meetup will take place at the Benelux (6:30 PM as usual). There won&#8217;t be any presentation to have a relax and friendly evening together. </p>
<p>&nbsp;</p>
<p>When: July 21th, 2015 at 18:30</p>
<p>Where: <a rel="nofollow" target="_blank" href="http://brasseriebenelux.com/">Benelux</a> &#8211; 245 Sherbrooke West</p>
<p>Who: Everybody!</p>
<p>How much: Free</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: Contact <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a></p>]]></content:encoded>
         <category>Uncategorized</category>
      </item>
      <item>
         <title>Email on Acid support added to Inker</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/eHzGucyDI-I/</link>
         <description>&lt;p&gt;You can now test your campaigns with email on acid as an alternative to Litmus with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://inker.position-absolute.com&quot;&gt;Inker&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Email renders differently in every email client. Gmail or Outlook? iPhone or Android?  Email on Acid preview your email in 42 different email&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=5192</guid>
         <pubDate>Sun, 19 Jul 2015 15:14:06 +0000</pubDate>
         <content:encoded><![CDATA[<p>You can now test your campaigns with email on acid as an alternative to Litmus with <a rel="nofollow" target="_blank" href="http://inker.position-absolute.com">Inker</a>. </p>
<p>Email renders differently in every email client. Gmail or Outlook? iPhone or Android?  Email on Acid preview your email in 42 different email clients and mobile devices in minutes.</p>
<p><a rel="nofollow" target="_blank" href="https://www.emailonacid.com/">Email on Acid</a> also decided to sponsor Inker development, a big thank you for that!</p>
<p><a rel="nofollow" target="_blank" href="https://www.emailonacid.com/"><img width="260px" height="122px" src="http://inker.position-absolute.com/eoa.png"></a></p>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/eHzGucyDI-I" height="1" width="1" alt=""/>]]></content:encoded>
         <category>Trends</category>
      </item>
      <item>
         <title>Inter-community BBQ</title>
         <link>http://montrealpython.org/2015/07/inter-community-bbq/</link>
         <description>&lt;p&gt;You must also register on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tinyurl.com/yulbbq15&quot;&gt;Eventbrite&lt;/a&gt; in order to participate to this event.  There will be an attendance list at the event.&lt;/p&gt;
&lt;p&gt;This year, We are inviting you with YulDev to invites you to its inter-community BBQ, in collaboration with HTML5mtl, Laravel Montréal, PHP Québec and PyLadies Montréal (and perhaps a few others!), as well as our current sponsors (let us know if you want to participate).&lt;/p&gt;
&lt;p&gt;The event will take place at the Jarry Park, in the picnic area closest to the corner of St-Laurent and Gary-Carter. &lt;/p&gt;
&lt;p&gt;The 5$ fee will be used to cover the expenses. Hot-dogs (100% beef ans vegetarian) will be served, as well as a few beverages. If you want, you can also bring your own drinks and chairs.&lt;/p&gt;
&lt;p&gt;In case of rain, the event will be held the next day, on Sunday the 26th (check your email on the morning of the 25th). See you soon, on an afternoon of networking under the sun!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Saturday July 25th 2015 at 12:00pm&lt;/p&gt;
&lt;p&gt;&lt;strong&gt; Where &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;285 Rue Gary-Carter, Montreal, QC (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://www.google.com/maps?f=q&amp;amp;hl=en&amp;amp;q=285+Rue+Gary-Carter,+Montr%C3%A9al,+QC,+ca&quot;&gt;map&lt;/a&gt;) &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Please register on eventbrite at: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tinyurl.com/yulbbq15&quot;&gt;http://tinyurl.com/yulbbq15&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://montrealpython.org/2015/07/inter-community-bbq/</guid>
         <pubDate>Mon, 13 Jul 2015 04:00:00 +0000</pubDate>
      </item>
      <item>
         <title>Code Sprint Odoo on July 27th</title>
         <link>http://montrealpython.org/2015/07/code-sprint-odoo/</link>
         <description>&lt;p&gt;The organizers of Odoo Montreal Meetup are organizing a code sprint on Odoo on Monday July 27 at 5:30.&lt;/p&gt;
&lt;p&gt;Many tasks and subjects are going to be proposed but don't hesitate to add yours to the list::&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Canadian localisation&lt;/li&gt;
&lt;li&gt;Quebec Pay&lt;/li&gt;
&lt;li&gt;Translation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to confirm your interest and your place in advance on:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.meetup.com/Odoo-Montreal/events/223675145/&quot;&gt;http://www.meetup.com/Odoo-Montreal/events/223675145/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please note that they are also organizing next Wednesday a meeting where they will discuss about the Quebec Pay system module:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.meetup.com/Odoo-Montreal/events/223500956/&quot;&gt;http://www.meetup.com/Odoo-Montreal/events/223500956/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See you there&lt;/p&gt;</description>
         <guid isPermaLink="false">http://montrealpython.org/2015/07/code-sprint-odoo/</guid>
         <pubDate>Tue, 07 Jul 2015 04:00:00 +0000</pubDate>
      </item>
      <item>
         <title>Being a student at DesignLab</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/4ADCwUjAipU/</link>
         <description>&lt;p&gt;&lt;img style=&quot;float:right;max-width:250px;margin-left:10px;&quot; src=&quot;http://d1ijjxzthis87e.cloudfront.net/static/main/images/homepage_v2/header-devices.982e3cb19078.png&quot; alt=&quot;http://d1ijjxzthis87e.cloudfront.net/static/main/images/homepage_v2/header-devices.982e3cb19078.png&quot;/&gt;&lt;em&gt;Don&amp;#8217;t you feel that everybody is a UX designer these days?&lt;br /&gt;
&lt;/em&gt;&lt;br /&gt;
 It&amp;#8217;s one of those things that everyone has an opinion on, but not everyone is good at it. These days a lot of online schools have come to fill some&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=5087</guid>
         <pubDate>Fri, 05 Jun 2015 12:55:20 +0000</pubDate>
         <content:encoded><![CDATA[<p><img style="float:right;max-width:250px;margin-left:10px;" src="http://d1ijjxzthis87e.cloudfront.net/static/main/images/homepage_v2/header-devices.982e3cb19078.png" alt="http://d1ijjxzthis87e.cloudfront.net/static/main/images/homepage_v2/header-devices.982e3cb19078.png"/><em>Don&#8217;t you feel that everybody is a UX designer these days?<br />
</em><br />
 It&#8217;s one of those things that everyone has an opinion on, but not everyone is good at it. These days a lot of online schools have come to fill some specific gaps like learning to be a front-end developer. </p>
<p>Design is a bit of another story, it&#8217;s much harder to learn to be a good designer online &#038; results may vary greatly.<br />
<br clear="all"><br />
Recently I was contacted by <a rel="nofollow" target="_blank" href="http://trydesignlab.com/">Designlab</a> to try their online course. For 2 years now I have moved into product management, which changed a bit how I usually works with UX &#038; UI designers, I thought it was the right time to deepen my knowledge into user experience design.</p>
<h2>The Premise</h2>
<p><a rel="nofollow" target="_blank" href="http://trydesignlab.com/mentors/"><img style="float:right;margin-left:10px;max-width:200px;" src="http://www.position-absolute.com/http://www.position-absolute.com/wp-content/uploads/2015/05/Screen-Shot-2015-05-18-at-12.53.21-PM.png" alt="" title="Screen Shot 2015-05-18 at 12.53.21 PM" width="281" height="345" class="alignnone size-full wp-image-5159"/></a><br />
For me the really interesting thing about Designplab is <a rel="nofollow" target="_blank" href="http://trydesignlab.com/mentors/"> their mentor list</a>. They have designers coming from Facebook, Amazon, Pinterest, Yahoo, Lyft &#038; etc. </p>
<p>Needless to say if you are building a startup just having these kinds of external opinions about your app is worth the price of admission.  </p>
<h2>While in the course</h2>
<p>The designlab courses are built in a way where each week one course unit is unlocked, I would say that I spent about 6 hours per week on the course. This is followed by a session with your mentor where you review your work. This is one of those things where the more work you put into it, the more you will get out, especially with your mentor.</p>
<p>On my side, I was looking to gain a better knowledge of all the &#8220;steps&#8221; a user experience designer walks through when building an application. On that side I was not disappointed, You start from an Empathy map &#038; Design-lab walk you through every steps so that the last week you are able to a/b test your prototype.</p>
<p>The courses are made up of a series of lectures &#038; projects.These projects can be directly commented on by your mentor &#038; other students. Unfortunately I did not have much interaction with the other students, it felt weird to me to add comments to someone else’s submission, even seeing them, sometimes you see horrible things &#038; you think oh my..</p>
<p>However I also saw much stronger submissions than mine, which pushed me to rework my projects.</p>
<h2>Would I recommend?</h2>
<p>At $300 a piece I really liked the course, obviously if you are already a designer this make no sense, but if you are a developer or a product manager looking to better understand the process these guys go through it is a very good course.</p>
<p>In the end what really sells it up is the 4 sessions you will get with your mentor. You can also request a mentor on their profile page, if you signup I would do that.</p>
<p>Design-lab is running a <a rel="nofollow" target="_blank" href="http://trydesignlab.com/responsive-web-design/">free course on responsive design</a> written by Patrick Wong a product designer at Lyft. Check it out!</p>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/4ADCwUjAipU" height="1" width="1" alt=""/>]]></content:encoded>
      </item>
      <item>
         <title>Meetup du 16 juin / June 16th Meetup</title>
         <link>http://www.montrealrb.com/2015/06/meetup-du-16-juin-june-16th-meetup/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=meetup-du-16-juin-june-16th-meetup</link>
         <description>&amp;#160; Français: Ce mois-ci, nous aurons une présentation qui va intéresser les développeurs de nombreuses sphères. Amenez vos collègues et amis! &amp;#160; Intro to Riak par Florencia Herra-Vega Riak est un système de base de donées NoSQL distribué très tolérant aux pannes. L&amp;#8217;idée derrière Riak est que vous pouvez dormir tranquilement même si un noeud es littéralement [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=5881</guid>
         <pubDate>Wed, 03 Jun 2015 19:04:42 +0000</pubDate>
         <content:encoded><![CDATA[<p>&nbsp;</p>
<h3>Français:</h3>
<hr />
<p>Ce mois-ci, nous aurons une présentation qui va intéresser les développeurs de nombreuses sphères. Amenez vos collègues et amis!</p>
<p>&nbsp;</p>
<blockquote>
<div>
<p><strong><img src="https://pbs.twimg.com/profile_images/495110391022628864/BU8x_2WN.jpeg" alt="" width="73" height="73"/>Intro to Riak</strong> par <a rel="nofollow" target="_blank" href="https://twitter.com/flohdot">Florencia Herra-Vega</a></p>
</div>
<div>
<p>Riak est un système de base de donées NoSQL distribué très tolérant aux pannes. L&#8217;idée derrière Riak est que vous pouvez dormir tranquilement même si un noeud es littéralement en flammes, et de rendre facile le remplacement et la réparation du cluster. Nous parlerons de l&#8217;approche de Riak à la scalabilité et à la redondance de données, en expliquant un peu de théorie sur les systèmes distribués. Nous parlerons aussi des différentes configurations de consistence dans Riak, et de comment utiliser la magie mathématique des types de données &#8220;CRDT” pour éviter les conflits et bien structurer les modèles de votre application.</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>Comme d&#8217;habitude, vous êtes tous conviés au Bénélux ensuite pour continuer les discussions autour d&#8217;une bonne bière!</p>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify commandite la pizza comme les derniers mois. Ils <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">cherchent</a> toujours des développeurs pour leurs bureaux à Montréal. N&#8217;hésitez pas à les contacter.</p></blockquote>
<p>&nbsp;</p>
<p>Quand: 16 juin 2015 à 18:30</p>
<p>Où: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> &#8211; 51 Sherbrooke Ouest, 3ème étage</p>
<p>Qui: Tout le monde intéressé par Ruby et/ou Ruby on Rails</p>
<p>Combien: Gratuit</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenu</p>
<p>Questions?: Contactez <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a> ou <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Martin</a></p>
<hr />
&nbsp;
<h3>English:</h3>
<p>This month we will have a presentation that will interest developers many areas. Bring your colleagues and friends!</p>
<p>&nbsp;</p>
<blockquote>
<div>
<p><strong><img src="https://pbs.twimg.com/profile_images/495110391022628864/BU8x_2WN.jpeg" alt="" width="73" height="73"/>Intro to Riak</strong> par <a rel="nofollow" target="_blank" href="https://twitter.com/flohdot">Florencia Herra-Vega</a></p>
</div>
<div>
<p>Riak is a NoSQL datastore built to run as a highly fault-tolerant distributed cluster. The idea behind Riak is that you can literally set a node on fire and the cluster will be able to function reliably while you sleep on, and bounce back to normal when the node is replaced. This presentation will go over Riak&#8217;s approach to replication and scaling, covering a tiny bit of distributed systems theory in the process. We will also go over Riak&#8217;s consistency configurations and the mathemagically conflict-free CRDT datatypes and how you can create sensible data models for your application while making the most of these options.</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>As usual, you&#8217;re all invited for a beer at Benelux!</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify is sponsoring pizzas like in the past months. They are still <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">searching</a> developers for their Montreal office. Don&#8217;t hesitate to contact them.</p></blockquote>
<p>&nbsp;</p>
<p>When: June 16th, 2015 at 18:30</p>
<p>Where: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> &#8211; 51 Sherbrooke West, 3rd floor</p>
<p>Who: Everyone who is interested in Ruby on Rails or Ruby</p>
<p>How much: Free</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: Contact <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a> or <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Martin</a></p>]]></content:encoded>
         <category>Uncategorized</category>
      </item>
      <item>
         <title>The Fibonacci Clock In The Classroom</title>
         <link>http://basbrun.com/2015/05/29/the-fibonacci-clock-in-the-classroom/</link>
         <description>Here is an awesome story from England involving my Fibonacci Clock project. A few days ago I received a message from Mr. Elliot Malkin, a mathematics teacher at Churchill Academy &amp;#038; Sixth Form in Bristol UK . He decided to offer his 13 years old students some questions regarding the clock. They had to watch the videos, read about it [&amp;#8230;]</description>
         <guid isPermaLink="false">http://basbrun.com/?p=1938</guid>
         <pubDate>Fri, 29 May 2015 18:09:44 +0000</pubDate>
         <content:encoded><![CDATA[<p><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2015/05/einsteinshow.jpg"><img class="alignnone size-full wp-image-1941" src="http://basbrun.com/wp-content/uploads/2015/05/einsteinshow.jpg" alt="einsteinshow" width="500" height="375"/></a></p>
<p>Here is an awesome story from England involving my Fibonacci Clock project. A few days ago I received a message from Mr. Elliot Malkin, a mathematics teacher at <a rel="nofollow" target="_blank" href="http://www.churchill-academy.org/page/default.asp?title=Home&pid=1">Churchill Academy & Sixth Form</a> in Bristol UK . He decided to offer his 13 years old students some questions regarding the clock. They had to watch the videos, read about it on Kickstarter and then pick one of the proposed questions. He kindly sent me some of the student’s responses I wanted to share it with you.</p>
<p>Thanks to Mr. Malkin for sharing this with us and best of luck to all his lucky students!</p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2015/05/29/the-fibonacci-clock-in-the-classroom/">See image gallery at basbrun.com</a>] </p>
<p> </p>]]></content:encoded>
         <category>Kickstarter</category>
      </item>
      <item>
         <title>Fibonacci Clock on Kickstarter</title>
         <link>http://basbrun.com/2015/05/04/fibonacci-clock/</link>
         <description>UPDATE: The Fibonacci Clock is now live on Kickstarter! I have 30 days to fund this project … head up to Kickstarter to support me! I present to you the Fibonacci Clock, a clock for nerds with style. Beautiful and fun at the same time, the clock uses the famous Fibonacci sequence to display time [&amp;#8230;]</description>
         <guid isPermaLink="false">http://basbrun.com/?p=1901</guid>
         <pubDate>Tue, 05 May 2015 01:54:19 +0000</pubDate>
         <content:encoded><![CDATA[<p><strong>UPDATE: The Fibonacci Clock is now live on <a rel="nofollow" target="_blank" href="https://www.kickstarter.com/projects/basbrun/fibonacci-clock-an-open-source-clock-for-nerds-wit">Kickstarter</a>! I have 30 days to fund this project … head up to <a rel="nofollow" target="_blank" href="https://www.kickstarter.com/projects/basbrun/fibonacci-clock-an-open-source-clock-for-nerds-wit">Kickstarter </a>to support me!</strong></p>
<p>I present to you the Fibonacci Clock, a clock for nerds with style. Beautiful and fun at the same time, the clock uses the famous Fibonacci sequence to display time in a brand new way.</p>
<p><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2015/05/G1cks.jpg"><img class="alignnone size-full wp-image-1924" src="http://basbrun.com/wp-content/uploads/2015/05/G1cks.jpg" alt="G1cks" width="1024" height="683"/></a></p>
<p><span class='embed-youtube' style='text-align:center;display:block;'></span></p> 
<h1>How do I tell time?</h1>
<p>The Fibonacci sequence is a sequence of numbers created by the Italian mathematician Fibonacci in the 13th century. This is a sequence starting with 1 and 1, where each subsequent number is the sum of the previous two. For the clock I used the first 5 terms: 1, 1, 2, 3 and 5.</p>
<div>
<p>The screen of the clock is made up of five squares whose side lengths match the first five Fibonacci numbers: 1, 1, 2, 3 and 5. The hours are displayed using red and the minutes using green. When a square is used to display both the hours and minutes it turns blue. White squares are ignored.</p>
<p>To tell time on the Fibonacci clock you need to do some math. To read the hour, simply add up the corresponding values of the red and blue squares. To read the minutes, do the same with the green and blue squares. The minutes are displayed in 5 minute increments (0 to 12) so you have to multiply your result by 5 to get the actual number.</p>
<div class="template asset">
<img class="fit" src="https://ksr-ugc.imgix.net/assets/003/666/758/b12c4af6c7b34453f0b739426c224188_original.png?v=1429820247&w=700&h=&fit=max&auto=format&lossless=true&s=7ce59cf34a0244edb1ece8f54358636e" alt=""/> 
</div>
<p>Often, there are multiple ways to display a single time. To add to the challenge, the combinations are picked randomly from all the different ways a number can be displayed. There are, for example, 16 different ways to display 6:30 and you never know which one the clock will use!</p>
</div>
<h1>Circuit</h1>
<p>I built the Fibonacci clock using an Atmega328P micro-controller using Arduino. You could buy an Arduino board and a DS1307 real-time clock break-out board and build a custom shield for your circuit but I preferred to build my own circuit board. That allows me to keep size small and price low.</p>
<p><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2015/05/H4c.jpg"><img class="alignnone size-full wp-image-1915" src="http://basbrun.com/wp-content/uploads/2015/05/H4c.jpg" alt="H4c" width="1024" height="683"/></a></p>
<h2>Buttons</h2>
<p>The three buttons attached to Arduino pins #3,#4 and #6 are used together to change time. Button on pin #3 can be used alone to change the color palette of the LEDs. An extra button is attached to pin #5 to change between different modes of the clock. Two modes are lamp modes and the default mode is the clock. All buttons are connected to the Arduino pins with a 10K pull-down resistor in parallel.</p>
<h2>Real-Time Clock</h2>
<p>The real-time clock chip DS1307 is connected to the Arduino analog pins 4 and 5 with two 2.2K pull-up resistors. The clock pin 5 (SDA) is connected to the Atmega328P pin 27 (Arduino A4) and the clock pin 6 (SCL) is connected to the Atmega329P pin 29 (Arduino A5). To keep time while unplugged the DS1307 chip needs a 3V battery connected to pint 3 and 4 of the chip. Finally, the real-time clock is driven by a 32KHz crystal connected on pins 1 and 2. A 5V power is applied on pin 8.</p>
<p><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2015/05/fibonacci_bb.png"><img class="alignnone wp-image-1902 size-large" src="http://basbrun.com/wp-content/uploads/2015/05/fibonacci_bb-1024x328.png" alt="fibonacci_bb" width="1024" height="328"/></a></p>
<h2>LED Strip</h2>
<p>I am using LED pixels built on top of the WS2811 drivers. These microcontrollers allows me to set the color of each individual LED with a single output on the Arduino microcontroller. The Arduino pin used to control the LEDs in this project is pin #8 (Atmega328P pin #14).</p>
<h2>Atmega328P</h2>
<p>You will find all the details on how to connect the Atmega328P to make an Arduino clone on my post “<a rel="nofollow" target="_blank" href="http://basbrun.com/2011/03/04/build-an-arduino-clone/">Build an Arduino Clone</a>“. I added a new feature in this project, an FTDI port to program your Arduino microcontroller directly on this circuit. You connect pin one to the reset pin of the Arduino trough a 0.1uF capacitor to synchronize your uploader with the chip bootup sequence.</p>
<p>Pin 2 (RX) of the FTDI port connects to pin 3 of the Atmega328P(Arduino 1-TX) and pin 3 (TX) of the FTDI connector connects to pin 2 of the Atmega328P (Arduino 0 – RX). Finally FTDI pin 4 goes to 5V and 5 and 6 to ground.</p>
<h1>The enclosure</h1>
<p><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2015/05/H3c.jpg"><img class="alignnone wp-image-1916 size-full" src="http://basbrun.com/wp-content/uploads/2015/05/H3c.jpg" alt="H3c" width="1024" height="683"/></a></p>
<p>The following video presents all the steps for the construction of the Fibonacci clock enclosure. The idea is to create 5 square compartments in the clock, two inches deep, matching the size of the five first terms of the Fibonacci sequence, 1, 1, 2, 3 and 5. The LEDs are distributed in all squares and connected in the back of the clock to the circuit board.</p>
<p><span class='embed-youtube' style='text-align:center;display:block;'></span></p> 
<p>The enclosure is built out of birch plywood. The frame is 1/4″ thick and the back panel is 1/8″ thick. The separators are 1/16″ thick and can be made of any opaque material. The dimensions of the clock are 8″x5″x4″. The front of the clock is a piece of 1/8″ thick semi-transparent plexiglass. The separators are marked using a Sharpie pen.</p>
<p><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2015/05/J3c.jpg"><img class="alignnone wp-image-1917 size-full" src="http://basbrun.com/wp-content/uploads/2015/05/J3c.jpg" alt="J3c" width="1024" height="768"/></a></p>
<p>The wood finish is a water based varnish applied after a good sanding using 220 sand paper.</p>
<h1>Pick your colors</h1>
<p>There are 5 different color palettes built in the clock. The default RGB mode, a Mondrian mode with red, blue and yellow and some more contemporary color palettes I would not be able to name!</p>
<div id="attachment_1933" style="width:1034px;" class="wp-caption alignnone"><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2015/05/ec.jpg"><img class="wp-image-1933 size-full" src="http://basbrun.com/wp-content/uploads/2015/05/ec.jpg" alt="ec" width="1024" height="683"/></a><p class="wp-caption-text">Fibonacci Clock with the Mondrian color palette</p></div>
<h1>Make it a lamp</h1>
<p>The Fibonacci clock can also be converted into an ambiant lamp! The code published already support two lamp modes. Simply push the mode button to toggle between the three modes. The code is open for you to hack, feel free to implement your own modes!</p>
<p><span class='embed-youtube' style='text-align:center;display:block;'></span></p> 
<h1>The source code</h1>
<p>You can find my source code on my github account:<br />
<a rel="nofollow" target="_blank" href="https://github.com/pchretien/fibo">https://github.com/pchretien/fibo</a></p>
<p> </p>
<h1></h1>]]></content:encoded>
      </item>
      <item>
         <title>Rethinking how we manage email development &amp; transactional delivery</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/WjxzBmbxWBE/</link>
         <description>&lt;p&gt;Coding emails is one of the most depressing tasks in front-end development. From coding to sending we tend to want to push those tasks as far from us as we possibly can, but emails are a very important part of&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=5091</guid>
         <pubDate>Tue, 05 May 2015 01:44:01 +0000</pubDate>
         <content:encoded><![CDATA[<p>Coding emails is one of the most depressing tasks in front-end development. From coding to sending we tend to want to push those tasks as far from us as we possibly can, but emails are a very important part of any system, and it is important that we take the time to do it right.</p>
<h2>A deeper look at email rendering engines</h2>
<p>Prior to 2007, coding emails wasn&#8217;t actually so bad. Depending on the type of campaign you would be doing you could even use divs and floats. Yes, you heard me. You could absolutely use anything IE6 had to offer at that point in time.</p>
<p>Then, something catastrophic happened. Microsoft decided to replace the IE engine from Outlook with the Microsoft Word engine. As you can guess, the community went crazy. Multiple blog posts and campaigns were launched to try to convince Microsoft to take a step back. Unfortunately, the opposite happened. Microsoft confirmed their choice of engine and published a blog article &#8220;<strong>The Power of Word in Outlook</strong>&#8221; (that is <a rel="nofollow" target="_blank" href="http://web.archive.org/web/20090627004005/http://blogs.msdn.com/outlook/archive/2009/06/24/the-power-of-word-in-outlook.aspx">still available on archive.org</a>). The blog article can be summarized in one simple quote:</p>
<div class="quote">
<div class="quote-text" style="text-align:center;font-size:20px;font-style:italic;">&#8220;We’ve made the decision to continue to use Word for creating e-mail messages because we believe it’s the best e-mail authoring experience around…&#8221;</div>
<div class="quote-name" style="padding-bottom:20px;padding-top:5px;text-align:center;font-size:13px;font-style:italic;">
William Kennedy<br />
Corporate Vice President, Office Communications and Forms Team
</div>
</div>
<p>Congrats on that ugly 3rd bar chart,  guys&#8230; And just like that, the email development landscape changed completely.</p>
<p><img src="http://www.position-absolute.com/http://www.position-absolute.com/wp-content/uploads/2015/05/Screen-Shot-2015-05-04-at-8.31.46-AM.png" alt="" title="Screen Shot 2015-05-04 at 8.31.46 AM" width="966" height="428" class="alignnone size-full wp-image-5098"/></p>
<p>Outlook 2000 and 2003 use the IE version installed on your computer for rendering emails, so you could actually use Outlook 2003 with IE 11 right now. However, that might not be the best idea. There are quite a few bugs because <a rel="nofollow" target="_blank" href="https://www.google.ca/search?q=outlook+2003+ie11&#038;oq=outlook+2003+ie11&#038;aqs=chrome..69i57j0l2.2507j0j7&#038;sourceid=chrome&#038;es_sm=119&#038;ie=UTF-8">IE 11 was not built for that</a>.</p>
<p>Also, something else to know that is quite depressing- there was no amelioration from 2007 to 2013 in the rendering engine. It&#8217;s virtually the same thing with a new coat of paint. Now that&#8217;s all said and done, let&#8217;s get past Outlook and take a more general view of the email landscape right now.</p>
<p><img src="http://www.position-absolute.com/http://www.position-absolute.com/wp-content/uploads/2015/05/Screen-Shot-2015-05-04-at-8.36.46-AM.png" alt="" title="Screen Shot 2015-05-04 at 8.36.46 AM" width="1208" height="798" class="alignnone size-full wp-image-5101"/>.</p>
<p>Yahoo, Gmail, Hotmail- they all use a custom engine that mashes up your html and spits out a &#8220;secured&#8221; version of your content. They also remove any style tags. Since they load the email directly into the interface instead of into an iframe they cannot risk you breaking their interface with your custom CSS.</p>
<p>The mobile landscape is quite peculiar. On one side, you have the default IOS and Android mail that are using webkit. It&#8217;s generally quite amazing what you can do with them. On the other side, you have the gmail app and inbox that are still using the same crap that the desktop gmail version uses. I&#8217;m not sure why Google went that way; one thing is for sure, they don&#8217;t care much about responsive email. If you absolutely must, there is a technique to achieve responsive email in gmail, but be ready to lose countless hours to testing. Plus, it&#8217;s more of a hack than it is gmail allowing you to make responsive email.</p>
<p>Now you can understand why your devs go insane when your marketing director comes back to you with some small spacing issues.</p>
<p><img alt="" src="http://cdn.playbuzz.com/cdn/4d4e97cf-6c97-4886-b9a6-8c185e65e0f6/685dd17a-6078-42f4-880e-abf19b63de44.gif" title="cat" class="alignnone" width="400" height="300"/></p>
<h2> Optimizing development time</h2>
<p>There is a real issue with the time spent coding emails. Even an experienced dev can lose an atrocious amount of time testing all of the possible configurations, time that he could be spending doing things more useful to the company. And I&#8217;m not even talking about when you give this task to an intern (which happens a lot); not only will he spend days trying to figure this thing out, he has no idea where he is going and the code will probably be of very poor quality.</p>
<p>So today I will review for you the best tools that you can give to your team to achieve two goals, one of <strong>saving time</strong>, a lot of it, and the second of <strong>keeping a clean code base</strong>, that respects standards and is something you can build on top of when you have this new transactional email to code.</p>
<h2>Zurb Ink CSS framework</h2>
<p><a rel="nofollow" target="_blank" href="http://zurb.com/ink/">Ink</a> is a breath of fresh air in an environment of despair. Ink is a  battle-tested responsive email framework that mainly handles your email layout. It should really be your starting point for any email project.</p>
<p>Ink is, however, not a silver bullet. For one thing, it has no sass and less file structure. You are stuck with one mangled CSS file. It also requires some decisions about margin and paddings that will conflict with your design. It might also increase the number of tables you are using. Don&#8217;t get me wrong; it is still the best CSS framework around for email. It&#8217;s just not as drop-in as we would like it to be.</p>
<h3>The magic behind the Ink responsive system</h3>
<p><img src="http://www.position-absolute.com/http://www.position-absolute.com/wp-content/uploads/2015/05/Screen-Shot-2015-05-03-at-8.55.10-PM.png" alt="" title="Screen Shot 2015-05-03 at 8.55.10 PM" width="325" height="460" class="alignnone size-full wp-image-5114"/></p>
<p>Ink uses a row system with a <strong>TD wrapper</strong>, shown up here, and when the window width is smaller than 600px it puts it at <strong>display:block</strong>. This changes the column&#8217;s layout to stack on top of each other. The <strong>expander td</strong> is used to fix some bugs to make the table go to a full width in mobile layout.</p>
<p>As explained before, this won&#8217;t work in gmail, but it is the best future proof technique available right now.</p>
<h3>Premailer, or how to keep your code clean</h3>
<p><a rel="nofollow" target="_blank" href="https://github.com/premailer/premailer">Premailer</a> is not a new tool. Three years ago I was using it at CakeMail to inline CSS files to HTML. However, what changed in the last 3 years is that it is now much more usable. For a project that seemed dead at the time it is now running at full steam, and the support is extremely good. It will even fix stuff you don&#8217;t know about to make your email more compatible. There is a grunt plugin, so it should be easy to integrate into your current stack. You can now keep your HTML files clean and generate CSS inline versions on the fly. </p>
<p>If you have a guy that goes onto a website and copy/pastes his code to get an inline version, please automate that process because otherwise it wastes so much time.</p>
<h3>Automating tools</h3>
<p>There are a couple of Javascript tools that can help you test your email&#8217;s code faster. For one, you have litmus with a <a rel="nofollow" target="_blank" href="https://www.npmjs.com/package/grunt-litmus">grunt plugin</a>. With a simple command you can push a new test to litmus. </p>
<pre><code>// Send a specific template to litmus
grunt litmus:dist/output/sidebar_hero/index.html
</code></pre>
<p>Then there is <a rel="nofollow" target="_blank" href="https://www.npmjs.com/package/grunt-nodemailer">grunt nodemailer</a>, which makes it easy to send a test email to anyone. </p>
<pre><code>
// Send a template to any email address
grunt email --fileSrc=dist/output/example.html
</code></pre>
<h3>Team workflow</h3>
<p>Time and time again I have seen email being miss-managed with a tangle of  non-reusable HTML tags. Email templates beg to be used with a templating engine with an architecture component. The more you abstract the ugly, the faster your devs will be able to implement new templates based on previous work.</p>
<p>The reality is that when starting a new project, your typical team has no transactional templates completed. The guy decides to code them and they generate an output version of their templates. They then plug their sendgrid library on to it. They forget they even exist.</p>
<p><img src="http://www.position-absolute.com/http://www.position-absolute.com/wp-content/uploads/2015/05/Screen-Shot-2015-05-07-at-1.24.58-PM.png" alt="" title="Screen Shot 2015-05-07 at 1.24.58 PM" width="428" height="292" class="alignnone size-full wp-image-5148"/></p>
<p>But then the company grows, more teams start sharing templates, and they find they are not always using the same languages or templating engines. They start customizing all of their own templates, and you end up with three sets of very similar email templates. Then what happens is what was bound to happen- one day, the marketing team wants to change the email header, and now you are stuck re-doing the work for three different teams and trying to coordinate the releases. There is frustration about something that should be so simple, and a lot of time is lost.</p>
<p><img src="http://www.position-absolute.com/http://www.position-absolute.com/wp-content/uploads/2015/05/Screen-Shot-2015-05-07-at-1.39.25-PM.png" alt="" title="Screen Shot 2015-05-07 at 1.39.25 PM" width="776" height="590" class="alignnone size-full wp-image-5149"/></p>
<p>In reality, they should have all extended the same template, coded with the same templating engine. If you use a lib for sending emails, when they give data they receive the HTML code. Then, to modify the header, you just need one guy to modify the base templates and all of the apps will use the same header at the same time. That way you can also build a library of components and hide those ugly tables behind it. This will enable other devs to build new emails faster, with fewer errors.</p>
<p><img src="http://www.position-absolute.com/http://www.position-absolute.com/wp-content/uploads/2015/05/Screen-Shot-2015-05-07-at-1.41.15-PM.png" alt="" title="Screen Shot 2015-05-07 at 1.41.15 PM" width="764" height="780" class="alignnone size-full wp-image-5150"/></p>
<p>Personally, I use Nunjucks to handle my email HTML components. It enables me to do things like this:</p>
<pre><code>// Cross compatible button for email services
{% macro button(label='default', link='#', class='', align='left') %}
&nbsp;&lt;table class="button {{class}}" align="{{align}}"&gt;
&nbsp;&nbsp;&lt;tr&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a href="{{link}}"&gt;{{label}}&lt;/a&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;
&nbsp;&nbsp;&lt;/tr&gt;
&nbsp;&lt;/table&gt;
{% endmacro %}

// import component in template
{% from "/html-components/component.button.html" import button %}

//Usage
button('Google', 'http://www.google.com', 'button-green', 'left');</code></pre>
<h2>Being smarter about transactional email delivery</h2>
<p>Chances are, right now you are currently using a library given to you by your provider to deliver transactional emails for your app. That&#8217;s a good first step. However, you need to think about what is going to happen when the provider goes down (and it will).</p>
<p>A delivery service should be more than just sending and receiving a response. There are three core things to look for when integrating transactional email delivery for your application:</p>
<h3>1. Back-up</h3>
<p>You should not be locked in with any one provider. When a provider goes down, there should be a way to re-route that request to another provider. Especially since most of them offer a couple of thousand free emails, this can be a life-saver. Your &#8220;forgot password&#8221; email should not be dependent on only one service.</p>
<p>Also, while some offer a &#8220;templating engine&#8221; please don&#8217;t lock in to it. Use the one your company uses and then send the template through their API, that way you do not destroy reusability.</p>
<h3>2. Asynchronous</h3>
<p>You should not have to wait for any delivery service to respond. If you can build a service that responds in 100 ms vs. the 200 ms from any email service provider you should. You won&#8217;t know if it is sent, anyway.</p>
<h3>3. Logs</h3>
<p>You should log any errors that you encounter. You also need to be alerted when your provider goes down so you can react with your back-up provider.</p>
<h2>I&#8217;m still here, what&#8217;s next?</h2>
<p>There is a tool that does everything I just talked about. It&#8217;s called <a rel="nofollow" target="_blank" href="http://inker.position-absolute.com">Inker</a>. It handles your coding stack to your delivery server. If you are wondering how you can do email better, it should probably be <a rel="nofollow" target="_blank" href="http://inker.position-absolute.com">your first stop</a>.</p>
<h3>Inker Features:</h3>
<p><strong>Coding</strong></p>
<ul>
<li>Built on top of Zurb Ink</li>
<li>Sane CSS components structure with sass</li>
<li>Sane HTML components structure with Nunjucks</li>
<li>Localization</li>
<li>Auto generate template to HTML documents with inline CSS</li>
<li>Auto deployment on litmus for testing</li>
<li>Auto deployment to any email address for testing</li>
</ul>
<h3>REST API Transactional Email Delivery service (nodejs)</h3>
<ul>
<li>Asynchronous for a warp speed response (you can use it in sync mode too)</li>
<li>Generate emails with custom data on the fly</li>
<li>Integrate all major email delivery providers</li>
<li>Back-up, when one goes down we redirect the request to another provider</li>
<li>Logs! hipchat, slack, logtenries, winston, push notifications with push bullet, are all in there, but you can easily add your own too</li>
</ul>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/WjxzBmbxWBE" height="1" width="1" alt=""/>]]></content:encoded>
         <category>Trends</category>
      </item>
      <item>
         <title>Meetup du 19 mai – May 19th meetup</title>
         <link>http://www.montrealrb.com/2015/05/meetup-du-19-mai-may-19th-meetup/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=meetup-du-19-mai-may-19th-meetup</link>
         <description>&amp;#160; Français: Railsconf cette année a été fantastique! Avec l&amp;#8217;annonce de Rails 5 et de ses nouveaux features par DHH, Sandi Metz qui sait toujours nous éblouir avec du Ruby si pur, clair et magnifique et Aaron Paterson travaillant fort pour améliorer les performances de RubyGems, Rails et Minitest, on a beaucoup à discuter. Pour [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=5771</guid>
         <pubDate>Sat, 02 May 2015 19:27:25 +0000</pubDate>
         <content:encoded><![CDATA[<p>&nbsp;</p>
<h3>Français:</h3>
<hr />
<p>Railsconf cette année a été fantastique! Avec l&#8217;annonce de Rails 5 et de ses nouveaux features par DHH, Sandi Metz qui sait toujours nous éblouir avec du Ruby si pur, clair et magnifique et Aaron Paterson travaillant fort pour améliorer les performances de RubyGems, Rails et Minitest, on a beaucoup à discuter. Pour ceux qui y étaient, vous pourrez partager ce qui vous a marqué le plus. Pour ceux qui n&#8217;ont pas eu cette chance, préparez vos questions!</p>
<p>Nous aurons aussi une excellente présentation qui saura intéresser tout le monde, des hobbyists aux gurus de Ruby: </p>
<p>&nbsp;</p>
<blockquote>
<div>
<p><strong><img src="https://pbs.twimg.com/profile_images/733948208/IndianaTux.png" alt="" width="73" height="73"/>IoT/IoE&#8230;and some ruby to rule them all</strong> by <a rel="nofollow" target="_blank" href="https://twitter.com/IndianaTux">André Courchesne</a></p>
</div>
<div>
<p>Vous avez toujours rêver de contrôler le monde physique a partir de votre code Ruby?<br />
Peut-être lire un senseur de température et l&#8217;afficher sur un graphique dans une application web ?<br />
Contrôler l&#8217;arrosage de vos plantes en vous basant sur les données d&#8217;un senseur d’humidité ?<br />
Mais ou commencer? Si vous étés un ingénieur logiciel et/ou avec passer votre vie a faire des site web, l’idée de brancher un senseur de température qui utilise un protocole 1-wire peut sembler complexe.<br />
Plus maintenant ! Le un des marcher le plus en demande dans présentement sont les appareils connecter (IoT/IoE) et le mouvement DIY/Maker le rend très abordable et facile.<br />
Dans cette courte présentation je vais vous parler des 3 plateforme les plus populaire sur le marcher: Arduino, RaspberryPi et BeagleBoneBlack.<br />
La présentation va inclure:</p>
<p>    &#8211; Qu&#8217;est-ce que les IoT/IoE<br />
    &#8211; Comment est-ce que je peut embarquer ?<br />
    &#8211; Quel carte/plateforme choisir<br />
    &#8211; Bien entendu un peut de Ruby pour contrôler tout ca<br />
    &#8211; Un exemple réel<br />
    &#8211; Démo d&#8217;une application amusante</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>Comme d&#8217;habitude, vous êtes tous conviés au Bénélux ensuite pour continuer les discussions autour d&#8217;une bonne bière!</p>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify commandite la pizza comme les derniers mois. Ils <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">cherchent</a> toujours des développeurs pour leurs bureaux à Montréal. N&#8217;hésitez pas à les contacter.</p></blockquote>
<p>&nbsp;</p>
<p>Quand: 19 mai 2015 à 18:30</p>
<p>Où: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> &#8211; 51 Sherbrooke Ouest, 3ème étage</p>
<p>Qui: Tout le monde intéressé par Ruby et/ou Ruby on Rails</p>
<p>Combien: Gratuit</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenu</p>
<p>Questions?: Contactez  <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a> ou <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Martin</a></p>
<p>&nbsp;</p>
<h3>English:</h3>
<p>RailsConf this year was fantastic! With the announcement of Rails 5 by DHH and its new features, Sandi Metz who always knows to dazzle us with so pure, clear and beautiful Ruby and Aaron Paterson working hard to improve the performance of RubyGems, Rails and Minitest, much has to discuss. For those who were there, you can share what marked you most. For those who have not been so lucky, get your questions ready!</p>
<p>We also have an excellent presentation that will interest everyone, from hobbyists to Ruby gurus:</p>
<p>&nbsp;</p>
<blockquote>
<div>
<p><strong><img src="https://pbs.twimg.com/profile_images/733948208/IndianaTux.png" alt="" width="73" height="73"/>IoT/IoE&#8230;and some ruby to rule them all</strong> by <a rel="nofollow" target="_blank" href="https://twitter.com/IndianaTux">André Courchesne</a></p>
</div>
<div>
<p>Ever wanted to control something physical from your Ruby code?<br />
Maybe read some temperature sensor values and display them on a graph?<br />
Control the watering of your garden based on soil humidity ?<br />
But where to start? If you dedicated your life to software engineering and/or web design, the idea of connecting a temperature sensor to some board and reading from a sensor that uses a 1-wire protocol may sound far fetched and beyond reach.<br />
Not anymore ! One of the hottest trends in today&#8217;s DIY/Maker market is making internet connected devices (IoT/IoE for shorts) and it&#8217;s easy as Pi !<br />
During this short presentation I&#8217;ll introduce you to the world of Arduino, RaspberryPi and BeagleBoneBlack, the 3 most popular platform for hardware hacking and making your own IoT/IoE.<br />
Presentation will include:<br />
	- What is IoT/IoE<br />
	- How can I get in on it ?<br />
	- Which board to choose depending on your needs<br />
	- And off course how can Ruby be used in this<br />
	- A real world example<br />
	- Live demo just for fun</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>As usual, you&#8217;re all invited for a beer at Benelux!</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify is sponsoring pizzas like in the past months. They are still <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">searching</a> developers for their Montreal office. Don&#8217;t hesitate to contact them.</p></blockquote>
<p>&nbsp;</p>
<p>When: May 19th, 2015 at 18:30</p>
<p>Where: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> &#8211; 51 Sherbrooke West, 3rd floor</p>
<p>Who: Everyone who is interested in Ruby on Rails or Ruby</p>
<p>How much: Free</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: Contact  <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a> or <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Martin</a></p>]]></content:encoded>
         <category>Meetings</category>
      </item>
      <item>
         <title>Making a Fibonacci Clock</title>
         <link>http://basbrun.com/2015/04/24/making-a-fibonacci-clock/</link>
         <description>Soon I will launch a Kickstarter campaign to fund the Fibonacci Clock project. This clock uses the Fibonacci sequence to display time using a colored tiling representation of the number sequence. The following video is the making of the clock, from woodworking to electronics. All the code and schematics will be published under the GPL [&amp;#8230;]</description>
         <guid isPermaLink="false">http://basbrun.com/?p=1889</guid>
         <pubDate>Fri, 24 Apr 2015 20:40:00 +0000</pubDate>
         <content:encoded><![CDATA[<p>Soon I will launch a Kickstarter campaign to fund the Fibonacci Clock project. This clock uses the Fibonacci sequence to display time using a colored tiling representation of the number sequence.</p>
<div id="attachment_1898" style="width:523px;" class="wp-caption aligncenter"><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2015/04/G1c1.jpg"><img class="wp-image-1898" src="http://basbrun.com/wp-content/uploads/2015/04/G1c1.jpg" alt="G1c" width="513" height="342"/></a><p class="wp-caption-text">Fibonacci Clock</p></div>
<p>The following video is the making of the clock, from woodworking to electronics. All the code and schematics will be published under the GPL licence at the end of the campaign.</p>
<p><span class='embed-youtube' style='text-align:center;display:block;'></span></p>]]></content:encoded>
      </item>
      <item>
         <title>April 21th meetup</title>
         <link>http://www.montrealrb.com/2015/04/april-21th-meetup/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=april-21th-meetup</link>
         <description>&amp;#160; Français: Ce mois-ci, le meetup sera animé par Gary puisque les organisateurs habituels seront tous à l&amp;#8217;extérieur du pays. Ce meetup ayant lieu en même temps que Railsconf 2015, nous vous offrons une présentation digne de ce nom! &amp;#160; Abstract Feature Branch by Andy Maleh Combien de fois vous êtes-vous retrouvés près de la ligne d’arrivée de [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=5651</guid>
         <pubDate>Wed, 08 Apr 2015 16:25:29 +0000</pubDate>
         <content:encoded><![CDATA[<p>&nbsp;</p>
<h3>Français:</h3>
<hr />
<p>Ce mois-ci, le meetup sera animé par <a rel="nofollow" target="_blank" href="https://twitter.com/garyharan">Gary</a> puisque les organisateurs habituels seront tous à l&#8217;extérieur du pays. Ce meetup ayant lieu en même temps que Railsconf 2015, nous vous offrons une présentation digne de ce nom!</p>
<p>&nbsp;</p>
<blockquote>
<div>
<p><strong><img src="https://media.licdn.com/mpr/mpr/shrink_200_200/AAEAAQAAAAAAAAGoAAAAJDgxYmVmMmIxLWYxYzItNDRmYi05OTBiLTE2NzRjNzNlODA3Ng.jpg" alt="" width="73" height="73"/>Abstract Feature Branch</strong> by <a rel="nofollow" target="_blank" href="https://www.linkedin.com/in/andymaleh">Andy Maleh</a></p>
</div>
<div>
<p>Combien de fois vous êtes-vous retrouvés près de la ligne d’arrivée de la mise en prod d’un nouveau feature excitant, mais retirés à la dernière minute par les gestionnaires pour régler des problèmes plus urgents? Que faites-vous avec le code incomplet de votre feature si une bonne part est fonctionnelle et déjà intégrée dans Master? Faut-il l’extraire dans une branche à part? Faut-il commenter le code qui n’est pas prêt à être exposé au client? Et qui faire des améliorations de design, amenés par le nouveau feature qui sont déjà utiles à l’équipe aujourd’hui? Est-ce qu’on laisse les améliorations de design sur la glace jusqu’à ce que le feature reviennent en priorité?</p>
<p>Ces décisions sont généralement prises par l’équipe au cas par cas et viennent souvent avec des gros compromis sur la qualité et sur la livraison.</p>
<p>Consultant pour Sears en 2009 et travaillant chez Groupon.com en 2012, j&#8217;ai travaillé dans des équipe qui ont adoptés une solution efficace et peu couteuse au problème appelée &#8221;<em>Branch by Abstraction</em>&#8220;, une technique popularisée par Martin Fowler, auteur de <em>UML Distilled and Patterns of Enterprise Application Architecture</em>.</p>
<p>Dans cette présentation, je vais expliquer <em>Branch by Abstraction</em> et démontrer comment l&#8217;appliquer à Ruby en utilisant un gem que j&#8217;ai créé appelé <em>Abstract Feature Branch</em>, partiellement inspiré par les librairies internes utilisées par Sears et Groupon. Ce gem a au dessus de 50000 téléchargements sur rubygems.org et a été utilisé dans une multitude de mes projets, incluant le lancement de EarlyShares.com et l&#8217;amélioration de Factor75.com.</p>
<p>À la fin de la présentation, l&#8217;audience aura une compréhension de base des concepts de <em>Branch by Abstraction</em> et suffisamment de connaissances de <em>Abstract Feature Branch</em> pour être en mesure d&#8217;explorer le concept dans ses propres projets.</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>Comme d&#8217;habitude, vous êtes tous conviés au Bénélux ensuite pour continuer les discussions autour d&#8217;une bonne bière!</p>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify commandite la pizza comme les derniers mois. Ils <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">cherchent</a> toujours des développeurs pour leurs bureaux à Montréal. N&#8217;hésitez pas à les contacter.</p></blockquote>
<p>&nbsp;</p>
<p>Quand: 21 avril 2015 à 18:30</p>
<p>Où: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> - 51 Sherbrooke Ouest, 3ème étage</p>
<p>Qui: Tout le monde intéressé par Ruby et/ou Ruby on Rails</p>
<p>Combien: Gratuit</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenu</p>
<p>Questions?: Contactez  <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a> ou <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Martin</a></p>
<p>&nbsp;</p>
<h3>English:</h3>
<p>This month, the meetup will be hosted by <a rel="nofollow" target="_blank" href="https://twitter.com/garyharan">Gary</a> since the usual organizers will all be out of the country. Since the meetup will occur at the same time as the Railsconf2015, we offer a presentation worthy of its name!</p>
<p>&nbsp;</p>
<blockquote>
<div>
<p><strong><img src="https://media.licdn.com/mpr/mpr/shrink_200_200/AAEAAQAAAAAAAAGoAAAAJDgxYmVmMmIxLWYxYzItNDRmYi05OTBiLTE2NzRjNzNlODA3Ng.jpg" alt="" width="73" height="73"/>Abstract Feature Branch</strong> by <a rel="nofollow" target="_blank" href="https://www.linkedin.com/in/andymaleh">Andy Maleh</a></p>
</div>
<div>
<p>How many times do you find yourself near the software release finish line on an exciting new feature only to be pulled off by management in the last minute to sneak in some higher priority emergency fix? What do you do with the unfinished feature&#8217;s code if parts of it were already functional and merged into master? Do you pluck it out and move to a remote feature branch? Do you simply comment out the code not ready for exposure to the customer? What about some of the nice software design improvements that were done as part of the feature and are being put to good use by the team today? Do you also put design improvements off till the feature is deemed by management high priority again?</p>
<p>These questions typically get decided on by the team on a case by case basis, and often with big compromises affecting both project delivery and code quality.</p>
<p>While consulting for Sears in 2009 and working at Groupon.com in 2012, I happened to work in teams that adopted a very effective and inexpensive solution to the problem called &#8220;<em>Branch by Abstraction</em>&#8220;, a technique originally popularized by Martin Fowler, author of <em>UML Distilled and Patterns of Enterprise Application Architecture</em>.</p>
<p>In this talk, I aim to explain<em> Branch by Abstraction</em> and demonstrate how to apply in Ruby using a gem I wrote called <em>Abstract Feature Branch</em>, partly inspired by the internal team libraries used at Sears and Groupon. The gem has already had over 50,000 downloads from rubygem.org and has been utilized in several of my newer projects, including launch of EarlyShares.com and enhancements of Factor75.com.</p>
<p>Attendees should walk out with basic understanding of <em>Branch by Abstraction</em> and enough knowledge of <em>Abstract Feature Branch</em> to be able to explore further in their own projects after the talk.</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>As usual, you&#8217;re all invited for a beer at Benelux!</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify is sponsoring pizzas like in the past months. They are still <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">searching</a> developers for their Montreal office. Don&#8217;t hesitate to contact them.</p></blockquote>
<p>&nbsp;</p>
<p>When: April 21th, 2015 at 18:30</p>
<p>Where: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> - 51 Sherbrooke West, 3rd floor</p>
<p>Who: Everyone who is interested in Ruby on Rails or Ruby</p>
<p>How much: Free</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: Contact  <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a> or <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Martin</a></p>]]></content:encoded>
         <category>Uncategorized</category>
      </item>
      <item>
         <title>Gucumber is Cucumber for Go</title>
         <link>http://feedproxy.google.com/~r/connectnothing/~3/zWod0BuI1IE/</link>
         <description>This last week I finished initial work on a Cucumber implementation in Go called Gucumber and released it on GitHub. Gucumber is a BDD-style testing framework that allows you to execute Gherkin .feature files in the Go programming language. Gucumber supports most of the basic Gherkin syntax, including features, scenarios, scenario outlines, docstring and tabular [&amp;#8230;]</description>
         <guid isPermaLink="false">http://gnuu.org/?p=682</guid>
         <pubDate>Mon, 30 Mar 2015 19:08:57 +0000</pubDate>
         <content:encoded><![CDATA[<p>This last week I finished initial work on a <a rel="nofollow" target="_blank" href="http://cukes.info">Cucumber</a> implementation in Go called <a rel="nofollow" target="_blank" href="https://github.com/lsegal/gucumber">Gucumber</a> and released it on GitHub. Gucumber is a BDD-style testing framework that allows you to execute Gherkin <code>.feature</code> files in the <a rel="nofollow" target="_blank" href="http://golang.org">Go programming language</a>.</p>
<p>Gucumber supports most of the basic <a rel="nofollow" target="_blank" href="https://github.com/cucumber/cucumber/wiki/Gherkin">Gherkin syntax</a>, including features, scenarios, scenario outlines, docstring and tabular data. In addition, the CLI and step definitions also support tag filters and before-after hooks.</p>
<h2>Installing</h2>
<p>Installing with Go should be as simple as:</p>
<pre><code class="sh">$ go get -u github.com/lsegal/cmd/gucumber
</code></pre>
<h2>Usage</h2>
<p>If you&#8217;ve used Cucumber before, the library and CLI are fairly straightforward and similar to other language implementations. You can see an example in the <a rel="nofollow" target="_blank" href="https://github.com/lsegal/gucumber/tree/master/features/basic">features directory</a> of the Gucumber package itself.</p>
<p>Given a <code>.feature</code> file:</p>
<pre><code># features/basic/basic.feature
Feature: Basic support
  This package should support the use of scenarios.

  Scenario: Basic usage
    Given I have an initial value of 3
    And I add 3 to the value
    Then I should have 6
</code></pre>
<p>And a step definition file:</p>
<pre><code># features/basic/step_definitions.go
package basic

import (
    . "github.com/lsegal/gucumber"
    "github.com/stretchr/testify/assert"
)

func init() {
    var initVal int

    Given(`^I have an initial value of (d+)$`, func(val int) {
        initVal = val
    })

    And(`^I add (d+) to the value$`, func(val int) {
        initVal += val
    })

    Then(`^I should have (d+)$`, func(val int) {
        assert.Equal(T, val, initVal)
    })
}
</code></pre>
<p>You can run <code>gucumber</code> to run these tests, which executes from the <code>features</code> directory by default, but can any path can be passed to the CLI:</p>
<pre><code class="sh">$ gucumber
Feature: Basic support
  Scenario: Basic usage                 # features/basic/basic.feature:3
    Given I have an initial value of 3  # features/basic/basic.feature:4
    And I add 3 to the value            # features/basic/basic.feature:5
    Then I should have 6                # features/basic/basic.feature:8

Finished (3 passed, 0 failed, 0 skipped).
</code></pre>
<h2>Writing Step Definitions</h2>
<p>Gucumber by default pulls in all <code>.go</code> files in the features directory being executed. You might have noticed a few things about these files:</p>
<ol>
<li>The <code>Given</code>, <code>When</code> and other step definition functions are used without the <code>gucumber</code> package prefix. In my examples, I choose to import <code>gucumber</code> into the global namespace to simplify definitions. While this is not <em>required</em> (you can just as easily import in a more traditional way), I would recommend it for simplicity in these files.</li>
<li>The global (also can be prefixed) <code>T</code> value, which seems to represent a test context and is passed into test assertions. I use <code>testify/assert</code> as a personal choice, but Gucumber should support most testing libraries, including Go&#8217;s own <a rel="nofollow" target="_blank" href="http://golang.org/pkg/testing/#T">testing.T</a> style. If the assertion library you use is not working, please <a rel="nofollow" target="_blank" href="https://github.com/lsegal/gucumber/issues">open an issue</a>.</li>
</ol>
<h2>Future Work</h2>
<p>Gucumber is not yet complete, but it is also in a fairly usable state. Error reporting of test failures and other runner summary information can be improved, and patches would be accepted to bring this implementation up to speed with others. Check it out and let me know how it works for you.</p>
<h2>Get It Now!</h2>
<p>You can get Gucumber and/or more information on <a rel="nofollow" target="_blank" href="https://github.com/lsegal/gucumber">GitHub</a>!</p><img src="http://feeds.feedburner.com/~r/connectnothing/~4/zWod0BuI1IE" height="1" width="1" alt=""/>]]></content:encoded>
         <category>post</category>
      </item>
      <item>
         <title>March 17th Meet-up</title>
         <link>http://www.montrealrb.com/2015/03/march-17th-meet-up/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=march-17th-meet-up</link>
         <description>&amp;#160; Français: À la suite d&amp;#8217;une présentation à Confoo, Leonard a accepté de nous donner un talk qu&amp;#8217;il a originalement écrit pour les employés de Ballistiq. Pour limiter leurs coûts en CDN, ils ont décidé d&amp;#8217;implémenter leur propre serveur à partir de l&amp;#8217;interface Rack. Cette présentation sera une excellente suite à la présentation de Marc-André [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=5551</guid>
         <pubDate>Sun, 15 Mar 2015 16:19:51 +0000</pubDate>
         <content:encoded><![CDATA[<p>&nbsp;</p>
<h3>Français:</h3>
<hr />
<p>À la suite d&#8217;une présentation à Confoo, Leonard a accepté de nous donner un talk qu&#8217;il a originalement écrit pour les employés de Ballistiq. Pour limiter leurs coûts en <a rel="nofollow" target="_blank" href="http://fr.wikipedia.org/wiki/Content_delivery_network">CDN</a>, ils ont décidé d&#8217;implémenter leur propre serveur à partir de l&#8217;<a rel="nofollow" target="_blank" href="http://rack.github.io/">interface Rack</a>. Cette présentation sera une excellente suite à la présentation de Marc-André Cournoyer de janvier: Re-implementing Rails (ActionController &amp; ActionDispatch).</p>
<p>&nbsp;</p>
<blockquote>
<div>
<p><strong>H<img class="alignleft" src="https://pbs.twimg.com/profile_images/428555514931187712/mJFLFcUd_400x400.jpeg" alt="" width="73" height="73"/>ow to build your own CDN and save tons</strong></p>
</div>
<div>
<p>Lors de cette présentation, <a rel="nofollow" target="_blank" href="https://twitter.com/leonardteo">Leonard Teo</a> de <a rel="nofollow" target="_blank" href="http://www.ballistiq.com/">Ballistiq</a> montrera comment ils ont écrit leurs propre CDN pour ArtStation, le plus gros site d&#8217;artistes de jeux et de films, et sauvé &gt;90% de leur coût sur Cloudfront.</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>Comme d&#8217;habitude, vous êtes tous conviés au Bénélux ensuite pour continuer les discussions autour d&#8217;une bonne bière!</p>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify commandite la pizza comme les derniers mois. Ils <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">cherchent</a> toujours des développeurs pour leurs bureaux à Montréal. N&#8217;hésitez pas à les contacter.</p></blockquote>
<p>&nbsp;</p>
<p>Quand: 17 Mars 2015 à 18:30</p>
<p>Où: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> - 51 Sherbrooke Ouest, 3ème étage</p>
<p>Qui: Tout le monde intéressé par Ruby et/ou Ruby on Rails</p>
<p>Combien: Gratuit</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenu</p>
<p>Questions?: Contactez  <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a> ou <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Martin</a></p>
<p>&nbsp;</p>
<h3>English:</h3>
<p>After a presentation at Confoo, Leonard accepted to give us a talk meant for Ballistiq employees. To limit their <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Content_delivery_network">CDN</a> costs, they decided to build their own server from the <a rel="nofollow" target="_blank" href="http://rack.github.io/">Rack interface</a>. This presentation is a nice follow up to Marc-André Cournoyer&#8217;s January presentation: Re-implementing Rails (ActionController &amp; ActionDispatch).</p>
<p>&nbsp;</p>
<blockquote>
<div>
<p><strong>H<img class="alignleft" src="https://pbs.twimg.com/profile_images/428555514931187712/mJFLFcUd_400x400.jpeg" alt="" width="73" height="73"/>ow to build your own CDN and save tons</strong></p>
</div>
<div>
<p>In this talk, <a rel="nofollow" target="_blank" href="https://twitter.com/leonardteo">Leonard Teo</a> from <a rel="nofollow" target="_blank" href="http://www.ballistiq.com/">Ballistiq</a> shows you how they wrote their own CDN for ArtStation, the world&#8217;s largest site for game and movie artists, and saved &gt; 90% on costs over using Cloudfront.</p>
</div>
</blockquote>
<p>&nbsp;</p>
<p>As usual, you&#8217;re all invited for a beer at Benelux!</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify is sponsoring pizzas like in the past months. They are still <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">searching</a> developers for their Montreal office. Don&#8217;t hesitate to contact them.</p></blockquote>
<p>&nbsp;</p>
<p>When: March 17th, 2015 at 18:30</p>
<p>Where: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> - 51 Sherbrooke West, 3rd floor</p>
<p>Who: Everyone who is interested in Ruby on Rails or Ruby</p>
<p>How much: Free</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: Contact  <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Sophie</a> or <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Martin</a></p>]]></content:encoded>
         <category>Meetings</category>
      </item>
      <item>
         <title>Where did my Google Drive “shared with me” tab go?</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/YpV0v0A2Cws/</link>
         <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update:&lt;/strong&gt; Google changed Incoming back to Shared with me.&lt;/em&gt;&lt;br /&gt;
&lt;img src=&quot;http://www.position-absolute.com/http://www.position-absolute.com/wp-content/uploads/2015/02/incoming1.png&quot; alt=&quot;&quot; title=&quot;incoming&quot; style=&quot;width:100%;height:auto;&quot; class=&quot;alignnone size-full wp-image-5083&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Without even probably realizing it Google Drive have become an integral part of my day to day toolset, everyone in my company use it to share documents across teams &amp;#38; departments.&lt;/p&gt;
&lt;p&gt;For a tool&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=4950</guid>
         <pubDate>Mon, 16 Feb 2015 13:52:48 +0000</pubDate>
         <content:encoded><![CDATA[<p><em><strong>Update:</strong> Google changed Incoming back to Shared with me.</em><br />
<img src="http://www.position-absolute.com/http://www.position-absolute.com/wp-content/uploads/2015/02/incoming1.png" alt="" title="incoming" style="width:100%;height:auto;" class="alignnone size-full wp-image-5083"/></p>
<p>Without even probably realizing it Google Drive have become an integral part of my day to day toolset, everyone in my company use it to share documents across teams &amp; departments.</p>
<p>For a tool to be useful It is important that our workflow is as painless as possible, forgetting to share a document to someone or having a coworker unable to find a document can impacts the company productivity.</p>
<p>This get me to last week when one of my coworker asked me where was all the documents shared by the company on the drive, I was a bit baffled. Personally I always hit the &#8220;shared with me&#8221; button to look at company documents. But that tab was gone, he had the new interface. Goodbye &#8220;shared with me&#8221; tab, please welcome the <strong>incoming</strong> tab.</p>
<p><img src="http://www.position-absolute.com/shared.jpg" style="max-width:675px;padding:0;border:0;"></p>
<p>Unfortunately Incoming is much less useful than it&#8217;s predecessor. Instead of being a document drive it is a timeline of your sharing activity.</p>
<p>Worst, to have all those documents in one place you have to &#8220;move&#8221; them. Forget about moving all  your documents at once, you will have to do it one by one &amp; subject yourself to one quirky popup behaviour.</p>
<p></p> 
<p>Considering you can have years of documents in there, that&#8217;s just an awful process to get through.</p>
<h2>Why did google changed the shared with me tab?</h2>
<p>What was so wrong with it? One possibility is that Google found out that in general people will look for the last item shared by co-workers &amp; then the longer it has been shared, the more it become irrelevant. </p>
<p>That seems to be the behaviour that drive the new ui.  You can also now choose items you want to move into your personal drive as opposite of having a bunch of things you are not using anymore.</p>
<p>However this is no excuse, Google should have a process to either import everything, or at least push a walkthrough the first time you open the new Incoming ui that let you import what you want, also explaining  how this is gonna work for now on.</p>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/YpV0v0A2Cws" height="1" width="1" alt=""/>]]></content:encoded>
      </item>
      <item>
         <title>Inker, transactional &amp; marketing email development workflow evolved</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/JQVFL220u6s/</link>
         <description>&lt;p&gt;tl:dr &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/posabsolute/inker&quot;&gt;Download&lt;/a&gt; &amp;#124; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://posabsolute.github.io/inker/&quot;&gt;Documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Any front-end dev will tell you that email template integration is one of the worst part of their job. It is often a task given to interns or to one of those cheap third party companies, &amp;#38; for&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=4956</guid>
         <pubDate>Wed, 11 Feb 2015 02:59:09 +0000</pubDate>
         <content:encoded><![CDATA[<p>tl:dr <a rel="nofollow" target="_blank" href="https://github.com/posabsolute/inker">Download</a> | <a rel="nofollow" target="_blank" href="http://posabsolute.github.io/inker/">Documentation</a></p>
<p>Any front-end dev will tell you that email template integration is one of the worst part of their job. It is often a task given to interns or to one of those cheap third party companies, &amp; for good reasons.</p>
<p>It takes experience/time to build solid email templates, testing in different browsers/email clients is also hard &amp; costly. If you use a senior dev it costs even more money, oh and you will also probably piss him off.</p>
<p>I understand this too much, not only did I work for web agencies, I also worked a couple of years at CakeMail building 2 wysiwyg email editors. If you think building an email template is hard, try building a <strong>good</strong> wysiwyg email creation tool.</p>
<h2>A beacon of hope, ink</h2>
<p>When Zurb launched Ink I was ecstatic, a solid grid system for building emails, could it be possible? Ink is the starting point for a new generation of sane email templates, unfortunately it only solve 1 issue, having a solid css framework for building email.</p>
<p>You are still stuck with a shitty workflow to make all the magic happen.</p>
<h2>Enter Inker</h2>
<p>Inker solves the issues ink does not. For one it incorporates ink slapped with a sass structure instead of plain css for better encapsulation. Then it solves the template html management problem with <a rel="nofollow" target="_blank" href="http://mozilla.github.io/nunjucks/">Mozilla Nunjucks</a>, it give you a sane html component architecture that can be rendered into one html file. Then Inker inline your css for you &amp; can send it to litmus or an email address for testing.</p>
<p>What does it mean in the end? Inker is the glue that makes everything easier while developing emails. In one command you can generate an email template from a sane CSS &amp; HTML markup that can be deployed on litmus. Saving you time, money &amp; frustration.</p>
<h2>An API to rule them all</h2>
<p>Inker also comes with a basic email sending server. This server is a rest api that can handle two things, for one it can return the template with parsed custom variables. It will also, guess what, send emails to any smtp service you want to (ex: Mailgun, sendgrid, etc).</p>
<p>In general, a company having multiple applications will handle emails separately for all its apps. This means multiple ways of building the templates, multiple templating engines, multiple ways of sending the emails.</p>
<p>Inker optimizes all this, you have one clearly define way of building templates, that has been tested &#038; is not error prone. You have one simple email server that handle all sending requests, it can handle multiple providers if one should go down, or if you get a better deal somewhere else.</p>
<p>Inker API is easy to implement in any application you build, removing the SMTP nonsense from your apps &#038; helping you focus on more important things.</p>
<h2>The bullet point</h2>
<ul>
<li>Built on top of Zurb Ink</li>
<li>Sane CSS components structure with SASS</li>
<li>Sane HTML components structure with nunjucks</li>
<li>Auto generate template to HTML documents with inlined CSS</li>
<li>Auto deployment on litmus for testing</li>
<li>Auto deployment to email for testing</li>
<li>Basic internal email sending server</li>
</ul>
<p><a rel="nofollow" target="_blank" href="https://github.com/posabsolute/inker">Download</a> | <a rel="nofollow" target="_blank" href="http://posabsolute.github.io/inker/">Documentation</a></p>
<h2>Special thanks</h2>
<p>Thanks to <a rel="nofollow" target="_blank" href="https://litmus.com">Litmus</a> for the free email client testing for this project.</p>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/JQVFL220u6s" height="1" width="1" alt=""/>]]></content:encoded>
      </item>
      <item>
         <title>Changing the pricing model for Where’s it Up</title>
         <link>http://blog.preinheimer.com/index.php?/archives/431-Changing-the-pricing-model-for-Wheres-it-Up.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/431-guid.html</guid>
         <pubDate>Tue, 10 Feb 2015 00:00:31 +0000</pubDate>
         <content:encoded><![CDATA[<p>When I first started working on <a rel="nofollow" target="_blank" href="http://api.wheresitup.com">Where&#8217;s it Up API</a>, I struggled with its pricing model. What should I charge? How should I organize customers? How much should I charge each group? etc. My friend Sean asked me if the tests people were running cost me anything. I replied that they didn&#8217;t; they were merely a rounding error in my network traffic. He suggested a flat-rate-per-month model. I made up a few plans, at reasonable price points in the $20-$60/month range, and launched. We&#8217;ve enjoyed a reasonable amount of revenue using this model. </p>

<p>Quite a bit has changed since then:
<ul>
<li>Our network is larger</li>
<li>The backend code has been completely refactored (moving from thousands of requests per day to millions will do that to you)</li>
<li>We&#8217;ve managed to acquire a bunch of great customers.</li>
</ul>
</p>
<p>Two other major adjustments have changed how I look at Where&#8217;s it Up:

<ol>
<li>We have customers running more tests, faster, than I ever imagined. Where&#8217;s it Up users now create enough network traffic to represent a real number of dollars. </li>
<li>We&#8217;ve expanded the number and type of tests we&#8217;re running, such that some are orders of magnitude more bandwidth- and CPU-intensive than anything we considered at launch. Compare: generating a screenshot of a web page, compressing it, and uploading it to AWS S3 (our shot test, powering <a rel="nofollow" target="_blank" href="http://www.shotsherpa.com/">ShotSherpa</a>), to a single DNS lookup.</li>
</ol></p>
<p>I tried to make the old pricing model work. We tiered some of our job types, limiting them to customers on even more expensive plans. Then we capped our plans at a total number of tests per month. Ultimately, the flat-rate model had two problems: customers couldn&#8217;t use some of the test types unless they were giving us $200/month, and running a million screenshots from our expensive Alaska server would cost us more than $200.</p>

<h3>New Model</h3>

<p>Our new <a rel="nofollow" target="_blank" href="http://api.wheresitup.com/pricing">pricing model</a> is to sell credits, and charge a different number of credits for different test types. Running a quick DNS costs one credit, whereas a screenshot costs ten. This model allows us to offer every test type to every user, and to bill users more accurately for their usage.</p>

<p>Rather than giving every user one free month when they sign up, we&#8217;ll give them 10,000 free credits (at least until my accountant finds out). This is enough to:
<ul>
<li>Confirm that one <b>HTTP endpoint</b> is accessible <b>10,000 times</b>; or</li>
<li>Confirm that one <b>HTTP endpoint</b> is accessible on <b>every continent</b>, <b>every hour</b>, for <b>35 days</b>; or</li>
<li>Check <b>DNS</b> results for your domain from <b>70 countries</b>, <b>daily</b>, for the next <b>142 days</b>; or</li>
<li>Take a <b>screenshot</b> of your website <b>every morning</b> for the next <b>2.74 years</b></li>
</ul>
</p>
<h3>Conclusion</h3>

<p>It&#8217;s too soon to call this a success, but I&#8217;m more happy with the credits model than I have been with anything else we tried or considered. It allows every customer to execute every job type, while ensuring we don&#8217;t sell more than we can support.</p>]]></content:encoded>
      </item>
      <item>
         <title>6 things an email marketing manager should know</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/81kkc-GdMGY/</link>
         <description>&lt;p&gt;It&amp;#8217;s sometimes hard for a marketing manager to move into email marketing management, going into it head down can sometimes even cause a melt down on their first campaign. &lt;/p&gt;
&lt;p&gt;Doing email marketing is special, you have a lot of tools&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=4983</guid>
         <pubDate>Wed, 28 Jan 2015 02:26:25 +0000</pubDate>
         <content:encoded><![CDATA[<p>It&#8217;s sometimes hard for a marketing manager to move into email marketing management, going into it head down can sometimes even cause a melt down on their first campaign. </p>
<p>Doing email marketing is special, you have a lot of tools available but at the same time you are dealing with a <strong>very  outdated</strong> technology. Here is my top 6 things an email marketing manager should know.</p>
<div style="float:right;margin-left:20px;width:290px;text-align:center;"><img src="http://www.cityleads.ca/wp-content/uploads/2013/06/email-marketing_en.gif" style="width:290px;margin-top:0;padding:0;margin-bottom:3px;">
<div style="color:#999;font-size:10px;">Generic marketing image</div>
</div>
<h2>Supporting 20 email clients is not going to be easy</h2>
<p>You are having a hard time getting your website glitches fixed on internet explorer 8?</p>
<p>Now imagine that on top of web browsers like chrome, firefox &#038; IE, you need to support each of those on Gmail, hotmail, yahoo &#038; then you need to test on outlook 2003, 2007, 2010, 2013, apple mail. Having responsive design? alright add IOS &#038; android to the mix. </p>
<p>Yup that makes for a lot of testing &#038; that&#8217;s no easy testing unless you have something like litmus, &#038; even then. Litmus provides you with a screenshot of the different email clients but you have no way to inspect that code, that makes for a lot of back &#038; forth, a lot of waiting in between tests &#038; a lot of frustration.</p>
<h2>Coding email templates is an art (&#038; design too)</h2>
<p>Thinking of giving your superb new design to your web developer intern, <strong>be careful</strong>. Coding emails is not like coding a website, you need to employ a lot of techniques (using table over divs being one of the most important) to make your design work. </p>
<p>Just to give you an idea, here are some important guidelines:</p>
<ul style="margin-left:20px;">
<li>Use tables over divs like in 1996.</li>
<li>Background images do not work on outlook 2007,2010,2013 (unless you do some VML voodoo)</li>
<li>You must inline all your css directly on the html tags</li>
<li>Don&#8217;t ask about flash (no flash)</li>
<li>Don&#8217;t ask about javascript (no javascript)</li>
<li>It&#8217;s possible to use simple responsive design</li>
<li>You can use gifs, you can <a rel="nofollow" target="_blank" href="http://www.emailonacid.com/blog/details/C13/a_how_to_guide_to_embedding_html5_video_in_email">kinda use video</a>.</li>
<li>CSS support is a mess, if you are going to ask a dev if you can do this &#038; that why don&#8217;t you <a rel="nofollow" target="_blank" href="https://www.campaignmonitor.com/css/"><strong>refer yourself to campaign monitor css chart</strong></a> before (because that&#8217;s what your dev is going to look at anyway)</li>
</ul>
<p>More information:<br />
<a rel="nofollow" target="_blank" href="https://litmus.com/blog/html-email-coding-101-infographic">The Foundations of Coding HTML Email</a><br />
<a rel="nofollow" target="_blank" href="http://www.activecampaign.com/email-design-guide/">Email Design Guideline</a></p>
<h2>If your devs do not deliver quality, use a third party</h2>
<p>Integrating emails sucks, I get it. You need to test on 20 email clients, that&#8217;s a given you are going to have some small discrepancies between platforms &#038; it is going to take an enormous amount of stackoverflow time to fix them all. If you see your developers can&#8217;t deliver good quality go AWOL.</p>
<p>There is a lot of third party companies that will do it for you &#038; they know every tidbits about email templating. I will name 2 companies here that I know deliver good quality from my time at CakeMail, <a rel="nofollow" target="_blank" href="http://www.emailmonks.com/">Email Monk</a> &#038; <a rel="nofollow" target="_blank" href="http://mailbakery.com/">Mail Bakery</a>. Look around, compare prices, there is a ton of them.</p>
<h2>Shop your email marketing platform</h2>
<p>Campaign monitor, Mailchimp, CakeMail, MadMini, GetResponse, you get it, there is also a ton of them. Don&#8217;t read reviews, <strong>test them</strong>. Most have a free tier &#038; pricing are generally similar, if you have a big email list you can deal your price too, don&#8217;t be afraid to try.</p>
<h2>Excited about a/b split testing? why don&#8217;t you start by testing that on your subject, sender name &#038; sent time.</h2>
<p>Thinking about optimizing your campaign? <strong>Don&#8217;t start with changing your call to action button from blue to red</strong>, it&#8217;s not only one of the most costly change, it is probably one of the least profitable. If your clients do not open your campaign there is nothing to test.</p>
<p><strong>Your subject line</strong> directly affects how many people will see your campaign, try changing the keywords to get people attention. </p>
<p>Test:</p>
<ul style="margin-left:20px;">
<li>Short &#038; long subject lines,</li>
<li>Adding numbers -<em> 6 reasons why you will love our chocolate &#038; 10% off</em></li>
<li>Personalize with name or city &#8211; <em>Mike how did your like your experience shopping at Walmart Edmonton?</em></li>
</ul>
<p><strong>Your sender name</strong> can also have a huge impact on your open rate. First avoid the noreply@ approach, this is a big teller that your email is just marketing content. It is also generally agreed that a combination of personal &#038; corporate name is the way the go, exemple: <strong>Cedric Dugas, CakeMail</strong>.</p>
<p><strong>Your sending time</strong> will also affect your open rate. Your campaign is received at the same time that those 10 other marketing campaign? Big chances it&#8217;s not going to be opened. Also please choose a platform where your email can be sent separately by timezone over a 24 hours period. Meaning if you schedule it to be launched at 4am, it must be 4am everywhere in the world.</p>
<p><em>* Side note, Mailchimp offer a feature that <a rel="nofollow" target="_blank" href="http://kb.mailchimp.com/delivery/deliverability-research/find-your-best-sending-time">optimize your sending time</a> by itself &#038; they are pretty good at it.</em></p>
<h2>Do your homework. You&#8217;re not the first doing a/b split test on a email marketing campaign.</h2>
<p>There is a ton of articles &#038; papers on email marketing optimizations, put your house in order before going to war.</p>
<ul style="margin-left:20px;">
<li><a rel="nofollow" target="_blank" href="https://litmus.com/blog/email-marketing-best-practices-in-action-with-lots-of-examples">Email Marketing Best Practices In Action</a></li>
<li><a rel="nofollow" target="_blank" href="http://blog.hubspot.com/blog/tabid/6307/bid/33618/25-Little-Email-Marketing-Experiments-That-Deliver-BIG-Results.aspx">25 Little Email Marketing Experiments That Deliver BIG Results</a></li>
<li><a rel="nofollow" target="_blank" href="http://www.silverpop.com/blogs/email-marketing/from-name-perhaps-your-most-important-email-marketing-decision.html">The “From” Name: Perhaps Your Most Important Email Marketing Decision</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/81kkc-GdMGY" height="1" width="1" alt=""/>]]></content:encoded>
      </item>
      <item>
         <title>February 17th meetup</title>
         <link>http://www.montrealrb.com/2015/01/february-17th-meetup/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=february-17th-meetup</link>
         <description>&amp;#160; Français: Ce mois-ci, nous avons deux présentations qui (comme toujours) s&amp;#8217;annoncent captivantes! Nous sommes de retour à la Maison Notman. Présentation de Ember.js Par : Jean-François Couture Fatigué du spagetti JQuery pour ajouter de nouvelles fonctionnalités côté client? Ajoutez cette présentation à votre calendrier! &amp;#160; Outside-In agile testing Par : Michael Elfassy Michael nous [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=4951</guid>
         <pubDate>Fri, 23 Jan 2015 22:45:24 +0000</pubDate>
         <content:encoded><![CDATA[<p>&nbsp;</p>
<h3>Français:</h3>
<hr />
<p>Ce mois-ci, nous avons deux présentations qui (comme toujours) s&#8217;annoncent captivantes! Nous sommes de retour à la Maison Notman.</p>
<blockquote>
<h3>Présentation de Ember.js</h3>
<p><img class="alignleft" src="https://pbs.twimg.com/profile_images/467316831141629952/l_nKDY7a_400x400.jpeg" alt="" width="73" height="73"/></p>
<p>Par : <a rel="nofollow" target="_blank" href="https://twitter.com/jfcouture">Jean-François Couture</a></p>
<p>Fatigué du spagetti JQuery pour ajouter de nouvelles fonctionnalités côté client? Ajoutez cette présentation à votre calendrier!</p>
<p>&nbsp;</p>
</blockquote>
<blockquote>
<h3>Outside-In agile testing</h3>
<p><img class="alignleft" src="https://pbs.twimg.com/profile_images/459121485097865217/Z2FHhBG7_400x400.jpeg" alt="" width="73" height="73"/></p>
<p>Par : <a rel="nofollow" target="_blank" href="https://twitter.com/michaelelfassy">Michael Elfassy</a></p>
<p>Michael nous fera la démonstration d&#8217;une méthode pour tester nos applications Rails qui a pour but d&#8217;être la plus intuitive, efficace et fiable possible. Tout en étant amusante pour le développeur. Challenge accepted!</p>
<p>&nbsp;</p>
</blockquote>
<blockquote><p>Comme d&#8217;habitude, vous êtes tous conviés au Bénélux ensuite pour continuer les discussions autour d&#8217;une bonne bière!</p></blockquote>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify commandite la pizza comme les derniers mois. Ils <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">cherchent</a> toujours des développeurs pour leurs bureaux à Montréal. N&#8217;hésitez pas à les contacter.</p></blockquote>
<p>Quand: 17 Février 2015 à 18:30</p>
<p>Où: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> - 51 Sherbrooke Ouest, 3ème étage </p>
<p>Qui: Tout le monde intéressé par Ruby et/ou Ruby on Rails</p>
<p>Combien: Gratuit</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenu</p>
<p>Questions?: <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Contactez moi</a></p>
<p>&nbsp;</p>
<h3>English:</h3>
<hr />
<p>This month we have two presentations and they will be captivating (as always)! Montreal.rb will take place in the Notman House.</p>
<blockquote>
<h3>Ember.js Introduction</h3>
<p><img class="alignleft" src="https://pbs.twimg.com/profile_images/467316831141629952/l_nKDY7a_400x400.jpeg" alt="" width="73" height="73"/></p>
<p>With : <a rel="nofollow" target="_blank" href="https://twitter.com/jfcouture">Jean-François Couture</a></p>
<p>If you are tired of jquery spaghetti when adding functionality browser side, mark your calendar!</p>
<p>&nbsp;</p>
</blockquote>
<blockquote>
<h3>Outside-In agile testing</h3>
<p><img class="alignleft" src="https://pbs.twimg.com/profile_images/459121485097865217/Z2FHhBG7_400x400.jpeg" alt="" width="73" height="73"/></p>
<p>With : <a rel="nofollow" target="_blank" href="https://twitter.com/michaelelfassy">Michael Elfassy</a></p>
<p>Michael will demonstrate a method for testing our Rails applications that aims to be as intuitive, efficient and reliable as possible. As well as being fun for the developer. Challenge accepted!</p>
<p>&nbsp;</p>
</blockquote>
<blockquote><p>As usual, you&#8217;re all invited for a beer at Benelux!</p></blockquote>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/></p>
<p>Shopify is sponsoring pizzas like in the past months. They are still <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">searching</a> developers for their Montreal office. Don&#8217;t hesitate to contact them.</p></blockquote>
<p>When: February 17th, 2015 at 18:30</p>
<p>Where: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> - 51 Sherbrooke West, 3rd floor</p>
<p>Who: Everyone who is interested in Ruby on Rails or Ruby</p>
<p>How much: Free</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: <a rel="nofollow" target="_blank" href="mailto:courrier@sophiedeziel.com">Contact me</a></p>]]></content:encoded>
         <category>Meetings</category>
      </item>
      <item>
         <title>January 20th Meet-up</title>
         <link>http://www.montrealrb.com/2015/01/january-20th-meet-up/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=january-20th-meet-up</link>
         <description>Nous voici au premier Montreal.rb de 2015. Cette fois, le meet-up sera chez RPM Montréal. 1) Marc-André Cournoyer &amp;#8211; Re-implementing Rails (ActionController &amp;#38; ActionDispatch). 2) Gem Club &amp;#8211; Présentez un Gem que vous aimez aux autres participants &amp;#160; Ce mois-ci, RPM Montréal va nous recevoir. Ils sont situés au 420 Guy. &amp;#160; &amp;#160; Shopify commandite [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=4771</guid>
         <pubDate>Mon, 12 Jan 2015 18:38:04 +0000</pubDate>
         <content:encoded><![CDATA[<p>Nous voici au premier Montreal.rb de 2015. Cette fois, le meet-up sera chez RPM Montréal.</p>
<blockquote><p>1) Marc-André Cournoyer &#8211; Re-implementing Rails (ActionController &amp; ActionDispatch).</p>
<p>2) Gem Club &#8211; Présentez un Gem que vous aimez aux autres participants</p></blockquote>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" style="background-color:#ffffff;" src="http://rpm.startupcentre.ca/wp-content/uploads/2013/03/RPM_s1.png" alt="" width="235" height="73"/> Ce mois-ci, <a rel="nofollow" target="_blank" href="http://rpm.startupcentre.ca/">RPM Montréal</a> va nous recevoir. Ils sont situés au <a rel="nofollow" target="_blank" href="http://rpm.startupcentre.ca/map/">420 Guy</a>.</p>
<p>&nbsp;</p></blockquote>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/>Shopify commandite la pizza comme les derniers mois. Ils <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">cherchent</a> toujours des développeurs pour leurs bureaux à Montréal. N&#8217;hésitez pas à les contacter.</p></blockquote>
<div></div>
<div></div>
<div>
<div>
<p>&nbsp;</p>
<p>Quand: 20 Janvier 2015 à 18:30</p>
</div>
<div>
<p>Où: <a rel="nofollow" target="_blank" href="http://rpm.startupcentre.ca/map/">RPM Montréal</a> &#8211; 420 Guy</p>
<p>Qui: Tout le monde intéressé par Ruby et/ou Ruby on Rails</p>
<p>Combien: Gratuit</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenue</p>
<p>Questions?: <a rel="nofollow" target="_blank" href="mailto:christ.blais@gmail.com">Contactez moi</a></p>
</div>
</div>
<div></div>
<hr />
<p>&nbsp;</p>
<p>We are at the first Montreal.rb of 2015. This time, the meet-up will be at RPM Montreal.</p>
<blockquote><p>1) Marc-André Cournoyer &#8211; Re-implementing Rails (ActionController &amp; ActionDispatch).</p>
<p>2) Gem Club &#8211; Present a Gem you like to the other participants</p></blockquote>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" style="background-color:#ffffff;" src="http://rpm.startupcentre.ca/wp-content/uploads/2013/03/RPM_s1.png" alt="" width="235" height="73"/> This month, <a rel="nofollow" target="_blank" href="http://rpm.startupcentre.ca/">RPM Montreal</a> will host Montreal.rb. There address is: <a rel="nofollow" target="_blank" href="http://rpm.startupcentre.ca/map/">420 Guy</a>.</p>
<p>&nbsp;</p></blockquote>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/>Shopify is sponsoring pizzas like in the past months. They are still <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">searching</a> developers for their Montreal office. Don&#8217;t hesitate to contact them.</p></blockquote>
<div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>When: January 20th, 2015 at 18:30</p>
</div>
<div>
<p>Where: <a rel="nofollow" target="_blank" href="http://rpm.startupcentre.ca/map/">RPM Montreal</a> &#8211; 420 Guy</p>
<p>Who: Everyone who is interested in Ruby on Rails or Ruby</p>
<p>How much: Free</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: <a rel="nofollow" target="_blank" href="mailto:christ.blais@gmail.com">Contact me</a></p>
</div>]]></content:encoded>
         <category>Meetings</category>
      </item>
      <item>
         <title>December 16th Meet-up</title>
         <link>http://www.montrealrb.com/2014/12/december-16th-meet-up/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=december-16th-meet-up</link>
         <description>On y est déjà, dernier meet-up de l&amp;#8217;année! Encore une fois, Montreal.rb aura lieu dans le café du Notman House. 1) Simon Génier &amp;#8211; MRuby 2) Étienne Barrié &amp;#8211; Kwargs 3) Christian Blais &amp;#8211; 15 slides in 15 minutes Comme d&amp;#8217;habitude, vous êtes tous conviés au Bénélux ensuite pour continuer les discussions autour d&amp;#8217;une bonne [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=4701</guid>
         <pubDate>Fri, 12 Dec 2014 17:14:30 +0000</pubDate>
         <content:encoded><![CDATA[<p>On y est déjà, dernier meet-up de l&#8217;année! Encore une fois, Montreal.rb aura lieu dans le café du Notman House.</p>
<blockquote><p>1) Simon Génier &#8211; MRuby</p>
<p>2) Étienne Barrié &#8211; Kwargs</p>
<p>3) Christian Blais &#8211; 15 slides in 15 minutes</p></blockquote>
<p>Comme d&#8217;habitude, vous êtes tous conviés au Bénélux ensuite pour continuer les discussions autour d&#8217;une bonne bière!</p>
<p>&nbsp;</p>
<blockquote><p><img src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/>Shopify commandite la pizza comme les derniers mois. Ils <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">cherchent</a> toujours des développeurs pour leurs bureaux à Montréal. N&#8217;hésitez pas à les contacter.</p></blockquote>
<div></div>
<div>
<div>
<p>Quand: 16 Décembre 2014 à 18:30</p>
</div>
<div>
<p>Où: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> - 51 Sherbrooke Ouest, café au sous-sol</p>
<p>Qui: Tout le monde intéressé par Ruby et/ou Ruby on Rails</p>
<p>Combien: Gratuit</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenue</p>
<p>Questions?: <a rel="nofollow" target="_blank" href="mailto:christ.blais@gmail.com">Contactez moi</a></p>
</div>
</div>
<div></div>
<hr />
<p>&nbsp;</p>
<p>Here we are, last ruby meet-up of the year! This time again, Montreal.rb will take place in the Notman House Café.</p>
<blockquote><p>1) Simon Génier &#8211; MRuby</p>
<p>2) Étienne Barrié &#8211; Kwargs</p>
<p>3) Christian Blais &#8211; 15 slides in 15 minutes</p></blockquote>
<p>As usual, you&#8217;re all invited for a beer at Benelux!</p>
<p>&nbsp;</p>
<blockquote><p><img src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/>Shopify is sponsoring pizzas like in the past months. They are still <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">searching</a> developers for their Montreal office. Don&#8217;t hesitate to contact them.</p></blockquote>
<div>
<p>&nbsp;</p>
<p>When: November 18th, 2014 at 18:30</p>
</div>
<div>
<p>Where: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> - 51 Sherbrooke West, café downstair</p>
<p>Who: Everyone who is interested in Ruby on Rails or Ruby</p>
<p>How much: Free</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: <a rel="nofollow" target="_blank" href="mailto:christ.blais@gmail.com">Contact me</a></p>
</div>]]></content:encoded>
         <category>Uncategorized</category>
      </item>
      <item>
         <title>Mongo Replicaset Issue - NAT'd server</title>
         <link>http://blog.preinheimer.com/index.php?/archives/430-Mongo-Replicaset-Issue-NATd-server.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/430-guid.html</guid>
         <pubDate>Mon, 24 Nov 2014 00:19:21 +0000</pubDate>
         <content:encoded><![CDATA[<p>We just ran into an issue joining a new server to our MongoDB replica set powering Where&#8217;s it Up &#38; <a rel="nofollow" target="_blank" href="http://shotsherpa.com/">ShotSherpa</a>. We copied the data over to give it a good starting point, then added it to the replica set. We waited a while, it still hadn&#8217;t joined, looking at the tail of the log showed many connection lines, nothing telling. When I restarted MongoDB I saw: </p>

<span class="code">replSet info self not present in the repl set configuration</span>

<p>I tried pinging the server&#8217;s hostname to ensure it was successful. No problem. I tried connecting to the server using the mongo command line on the primary server (`mongo server.example.com:27017`). No problem. </p>

&#8230;<br />

<p>Eventually I copied the mongo hostname from the replica set configuration, and tried to use it to connect to mongo on the new secondary. No dice! As it turns out the NAT hadn&#8217;t been configured to allow that hostname to work locally. A few new entries in our /etc/hosts file later, and our server was joined successfully. </p>


<h3>MongoDB Tip:</h3>
<p>When MongoDB has trouble connecting, try the connection strings listed in the replica set config from all relevant hosts.</p>]]></content:encoded>
         <category>PHP</category>
      </item>
      <item>
         <title>Enough with your parallax already</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/TzMzushPMpA/</link>
         <description>&lt;p&gt;&lt;img src=&quot;http://b2b.cbsimg.net/blogs/12042012figure_a.gif&quot; style=&quot;padding:20px 0;float:right;width:200px;margin-left:10px;&quot;/&gt;Sometime &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Parallax_scrolling#Parallax_scrolling_in_Web_design&quot;&gt;5 years ago&lt;/a&gt; a web designer decided that having a header with a background image &amp;#038; the text on top not scrolling at the same speed would be a fun idea. Since then, parallax effects have been all the rage.&lt;/p&gt;
&lt;p&gt;From&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=4913</guid>
         <pubDate>Tue, 18 Nov 2014 02:50:38 +0000</pubDate>
         <content:encoded><![CDATA[<p><img src="http://b2b.cbsimg.net/blogs/12042012figure_a.gif" style="padding:20px 0;float:right;width:200px;margin-left:10px;">Sometime <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Parallax_scrolling#Parallax_scrolling_in_Web_design">5 years ago</a> a web designer decided that having a header with a background image &#038; the text on top not scrolling at the same speed would be a fun idea. Since then, parallax effects have been all the rage.</p>
<p>From simple header to whole website scrolling effects, the parallax must be one of the longest trend to happen in web design. In fact I never had one product manager in 5 years that did not ask at some point or another to add a parallax effect to that text, or content block, or header. Why? My guess is that they want to spice up their app or website but they don&#8217;t really know how, so adding parallax is something simple to think about that &#8220;add&#8221; to a page. Hey everyone has one,  me too!</p>
<p>Linkedin, Medium, I&#8217;m surprised how big companies still use it a lot. Me? I hate parallax, it slows down my computer &#038; every time I see one I only see a product manager saying..</p>
<div style="font-size:22px;font-style:italic;text-align:center;padding:24px 0 22px 0;">Hey! we could add a parallax here!</div>
<h2>But the real interesting question is, does parallax hinder user experience?</h2>
<p>Unfortunately not enough studies have been done on this subject, so it&#8217;s really hard to have a real understanding on the effects parallax have on user experience. The <a rel="nofollow" target="_blank" href="http://docs.lib.purdue.edu/cgttheses/27/">only study</a> I found was done by a student of the Purdue University. He found out that there was no significant differences between the 2 groups he tested in terms of website usability, except that the group having the parallax found it fun&#8230;..</p>
<p><img src="http://fc04.deviantart.net/fs70/f/2012/227/c/7/kill_me_now_mem_by_shatrdexistnc-d5b6jql.jpg"></p>
<p>It&#8217;s quite an interesting read &#038; there is a very good summary of the study (if you do not want to pay) <a rel="nofollow" target="_blank" href="http://www.fastcodesign.com/3023690/evidence/snow-fail-do-readers-really-prefer-parallax-web-design">here</a>.</p>
<h2>So anyway</h2>
<p>I guess I&#8217;m stuck with your stupid parallax for still some time until it fades away, I look forward for the time where we will be all laughing about the parallax trend. Until then, yes I will use that plugin to do that parallax thing you want, can we move on to something more important?</p>
<p>// Rant mode off</p>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/TzMzushPMpA" height="1" width="1" alt=""/>]]></content:encoded>
      </item>
      <item>
         <title>November 18th Meet-up</title>
         <link>http://www.montrealrb.com/2014/11/november-18th-meet-up/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=november-18th-meet-up</link>
         <description>Cette première neige de l&amp;#8217;année s&amp;#8217;abat sur nous en ce mois de Novembre. Peu importe les intempéries, Montreal.rb aura lieu quand même dans le café du Notman House. 1) Guillaume Malette &amp;#8211; How to handle uniqueness constraints in Rails 2) David Lazar &amp;#8211; Fork you gem, I am gonna fix yer wagon Comme d&amp;#8217;habitude, vous [...]</description>
         <guid isPermaLink="false">http://www.montrealrb.com/?p=4591</guid>
         <pubDate>Mon, 17 Nov 2014 18:28:57 +0000</pubDate>
         <content:encoded><![CDATA[<p>Cette première neige de l&#8217;année s&#8217;abat sur nous en ce mois de Novembre. Peu importe les intempéries, Montreal.rb aura lieu quand même dans le café du Notman House.</p>
<blockquote><p>1) Guillaume Malette &#8211; How to handle uniqueness constraints in Rails</p>
<p>2) David Lazar &#8211; Fork you gem, I am gonna fix yer wagon</p></blockquote>
<p>Comme d&#8217;habitude, vous êtes tous conviés au Bénélux ensuite pour continuer les discussions autour d&#8217;une bonne bière!</p>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/> Shopify commandite la bière et la pizza comme les derniers mois. Ils <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">cherchent</a> toujours des développeurs pour leurs bureaux à Montréal. N&#8217;hésitez pas à les contacter.</p></blockquote>
<div></div>
<div>
<div>
<p>Quand: 18 Novembre 2014 à 18:30</p>
</div>
<div>
<p>Où: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> &#8211; 51 Sherbrooke Ouest, café au sous-sol</p>
<p>Qui: Tout le monde intéressé par Ruby et/ou Ruby on Rails</p>
<p>Combien: Gratuit</p>
<p>Inscription: Pas besoin, tout le monde est le bienvenue</p>
<p>Questions?: <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Contactez moi</a></p>
</div>
</div>
<div></div>
<hr />
<p>&nbsp;</p>
<p>Here it is, the first snow of the year. Even with the snow, Montreal.rb will take place in the Notman House Café.</p>
<blockquote><p>1) Guillaume Malette &#8211; How to handle uniqueness constraints in Rails</p>
<p>2) David Lazar &#8211; Fork you gem, I am gonna fix yer wagon</p></blockquote>
<p>As usual, you&#8217;re all invited for a beer at Benelux!</p>
<p>&nbsp;</p>
<blockquote><p><img class="alignleft" src="http://cdn.shopify.com/assets/images/affiliates-badges-banners/badges/shopify-buttons-125x125-green.png?1397243529" alt="Shopify" width="73" height="73"/> Shopify is sponsoring beers and pizzas like in the past months. They are still <a rel="nofollow" target="_blank" href="http://www.shopify.com/careers">searching</a> developers for their Montreal office. Don&#8217;t hesitate to contact them.</p></blockquote>
<div>
<p>&nbsp;</p>
<p>When: November 18th, 2014 at 18:30</p>
</div>
<div>
<p>Where: <a rel="nofollow" target="_blank" href="http://notman.org/en/contact">Notman House</a> &#8211; 51 Sherbrooke West, café downstair</p>
<p>Who: Everyone who is interested in Ruby on Rails or Ruby</p>
<p>How much: Free</p>
<p>Register: No need, just come, you&#8217;re welcome</p>
<p>Questions?: <a rel="nofollow" target="_blank" href="mailto:mprovencher86@gmail.com">Contact me</a></p>
</div>]]></content:encoded>
         <category>Meetings</category>
      </item>
      <item>
         <title>Revisiting the design workflow in a scrum team</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/N3JmoQuAN3o/</link>
         <description>&lt;p&gt;The Design process seems to never quite perfectly fit with scrum teams. There are many reasons for this but the most obvious one is that clients often wanna see the design well before the coding is started to have their&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=4891</guid>
         <pubDate>Mon, 17 Nov 2014 02:11:13 +0000</pubDate>
         <content:encoded><![CDATA[<p>The Design process seems to never quite perfectly fit with scrum teams. There are many reasons for this but the most obvious one is that clients often wanna see the design well before the coding is started to have their say on the final product look.</p>
<p>At SSENSE we recently had to build a CMS for our content team, this project was interesting because our content team creates custom layouts for each article &#038; this is not something you can easily do using a platform like Wordpress for example. Unfortunately like too much internal project, time was short. We had to build something fast, iterate fast &#038; deliver it as soon as possible.</p>
<p>A perfect project to be done using scrum &#038; include the design in the process!</p>
<h2>About designing one sprint ahead</h2>
<p><a rel="nofollow" target="_blank" href="http://www.position-absolute.com/product-management/about-including-design-in-the-same-sprint-than-developement-or-to-do-it-1-sprint-ahead-2/">Couple of months ago</a> I spoke about how hard it was for us to find a balance between having the design done directly in the sprint, with demanding stakeholders we had no choice but to move the design one sprint ahead.</p>
<p>However with the CMS we were reign free, I built very strong user stories, very driven on the acceptance criteria &#038; we started our sprint without design.</p>
<h2 style="text-align:center;">Our workflow</h2>
<p style="text-align:center;">
Front-end does basic wireframe integration based on our grid system<br />
↓<br />
Designer applies styling with css/rework base integration<br />
↓<br />
Integrator adds functionalities<br />
↓<br />
Designer applies styling/rework integration<br />
↓<br />
The team iterate together if any user experience issues popup or we find better solutions.
</p>
<p>Obviously that means our designer had to use more his CSS/HTML chops than its Photoshop skills, if your designer is completely unable to use CSS that&#8217;s another thing. However we were very fortunate to have a designer than can also code very well &#038; with a good CSS framework, all is possible.</p>
<h2>Is it really better?</h2>
<p>For us this workflow allowed to find UX issues sooner &#038; iterate faster than our usual workflow, in the end it made us more agile you could say : P.</p>
<p>I really liked how this worked out with the team &#038; everyone seemed happier with the workflow as wells. Now how can we replicate this workflow on all our projects?</p>
<p>Looking at other teams in the wild that do design ahead they are generally not happy with it, it&#8217;s not a lack of trying to integrate it, but it&#8217;s hard to find solutions to that problem since design involve generally more than the scrum team &#038; stakeholders have generally some control over design &#038; processes.</p>
<p>More ressources about scrum &#038; design processes:<br />
<a rel="nofollow" target="_blank" href="http://www.practicallyux.com/the-sprint-ahead-sprint-behind-tango/">The Sprint Ahead — Sprint Behind Tango</a><br />
<a rel="nofollow" target="_blank" href="http://www.andersramsay.com/2010/08/22/designing-ahead-the-good-the-bad-and-the-ugly/">Designing Ahead: The Good, The Bad, and The Ugly</a><br />
<a rel="nofollow" target="_blank" href="http://www.practicallyux.com/the-sprint-ahead-sprint-behind-tango/">UX working a Sprint ahead is full of FAIL. Work as a single team instead.</a></p>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/N3JmoQuAN3o" height="1" width="1" alt=""/>]]></content:encoded>
      </item>
      <item>
         <title>First CNC project</title>
         <link>http://basbrun.com/2014/10/18/first-cnc-project/</link>
         <description>I just finished building a CNC kit from Shapeoko and started cutting stuff. I needed a simple project that would be a bit more challenging than engraving my name on a piece of scrap wood. I decided to give a try to the Wobbly Circle presented by Matt Parker on the Numberphile Youtube channel. In [&amp;#8230;]</description>
         <guid isPermaLink="false">http://basbrun.com/?p=1536</guid>
         <pubDate>Sat, 18 Oct 2014 17:54:05 +0000</pubDate>
         <content:encoded><![CDATA[<p><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2014/10/IMG_20141017_135924-e1413654953950.jpg"><img class="alignnone wp-image-1541 size-full" src="http://basbrun.com/wp-content/uploads/2014/10/IMG_20141017_135924-e1413654953950.jpg" alt="" width="1024" height="768"/></a></p>
<p>I just finished building a CNC kit from <a rel="nofollow" title="Shapeoko 2" target="_blank" href="http://www.shapeoko.com/">Shapeoko</a> and started cutting stuff. I needed a simple project that would be a bit more challenging than engraving my name on a piece of scrap wood. I decided to give a try to the <a rel="nofollow" title="Wobbly Circle" target="_blank" href="http://www.numberphile.com/videos/wobbly_circles.html">Wobbly Circle</a> presented by <a rel="nofollow" title="Matt Parker" target="_blank" href="https://twitter.com/standupmaths">Matt Parker</a> on the <a rel="nofollow" title="Numberphile" target="_blank" href="https://www.youtube.com/channel/UCoxcjq-8xIDTYp3uz647V5A">Numberphile Youtube</a> channel.</p>
<p>In this video, Matt Parker explains the mathematics required to assemble two disks perpendicular one to the other in such a way that their combined center of gravity always remains at the same height, making the assembly behave like a ball when rolling on a plane surface.</p>
<p>I wanted to use Free and Open Source software as much as possible for this project. I designed the profile in <a rel="nofollow" title="DraftSight" target="_blank" href="http://www.3ds.com/products-services/draftsight/overview/">DraftSight</a>, a free CAD program from Dassault Système. I then exported the drawing in DXF and converted it to SVG using <a rel="nofollow" title="Inkscape" target="_blank" href="http://www.3ds.com/products-services/draftsight/overview/">Inkscape</a>. This conversion is not optimal because of the way Inkscape handles line thicknesses. Finally I opened the SVG in <a rel="nofollow" title="Makercam" target="_blank" href="http://www.makercam.com/">Makercam.com</a>, an online CAM software to generated the G-Code for the milling machine.</p>
<p>Inkscape is great to produce art pieces and engraving but not really usable as a CAD program. I am still searching for the best free and Open Source solution out there, if you have any suggestion please let me know in the comment section.</p>
<p>All the files for this simple project are available on my Github account: <a rel="nofollow" title="Github - centerofgravity" target="_blank" href="https://github.com/pchretien/centerofgravity">https://github.com/pchretien/centerofgravity</a></p>
<p> </p>
<p></p>]]></content:encoded>
      </item>
      <item>
         <title>Managed Accounts at WonderProxy</title>
         <link>http://blog.preinheimer.com/index.php?/archives/429-Managed-Accounts-at-WonderProxy.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/429-guid.html</guid>
         <pubDate>Fri, 22 Aug 2014 01:14:32 +0000</pubDate>
         <content:encoded><![CDATA[<p>I&#8217;ve made plenty of mistakes in the code powering <a rel="nofollow" target="_blank" href="https://wonderproxy.com/">WonderProxy</a>, perhaps most famously equating 55 with &#8734; for our higher-level accounts (issues with unsigned tinyint playing a close second). Something I think I got right though, was the concept of &#8220;managed accounts&#8221;. It&#8217;s a simple boolean flag on contracts, and when it&#8217;s set, the regular account de-activation code is skipped.</p>


<p>Having this flag allows us to handle a few things gracefully:
<ul>
<li>Large value contracts<br />
By marking them as managed, they don&#8217;t expire because someone was on vacation when the account expired. They stay happy, the revenue continues, the expiry date remains accurate.</li>
<li>Contracts with tricky billing processes<br />
The majority of our contracts pay us with PayPal or Stripe. A selection of contracts however have complex hoops involving anti-bribery policies, supplier agreements etc. This gives us some time to get this ironed out.</li>
<li>Contracts where we&#8217;ve failed to bill well<br />
We occasionally make mistakes when billing our clients. When we&#8217;ve screwed up in the past, this helps ensure that there&#8217;s time for everything to resolve amicably.</li></ul></p>

<p>This doesn&#8217;t mean the system has been without flaw. We currently get daily emails reporting on new signups, expired accounts, etc. It mentions all accounts that were not expired because of the managed flag.</p>

<p>Like most features, that was added after mistakes were made: we&#8217;d left some managed accounts unpaid for months. With better reporting, though, now, we couldn&#8217;t be happier with it. </p>]]></content:encoded>
         <category>PHP</category>
      </item>
      <item>
         <title>Score Display Box</title>
         <link>http://basbrun.com/2014/08/15/score-display-box/</link>
         <description>A few years back I built a Quiz Buzzer System for my mother. She loves it but she is still keeping track of scores using a pencil and a piece of paper. I decided to fix that using an Adafruit Trinket microcontroller board, a 4 digits 7 segments display and two arcade style buttons. You will [&amp;#8230;]</description>
         <guid isPermaLink="false">http://basbrun.com/?p=1478</guid>
         <pubDate>Fri, 15 Aug 2014 20:13:37 +0000</pubDate>
         <content:encoded><![CDATA[<p>A few years back I built a <a rel="nofollow" title="Quiz Buzzer System" target="_blank" href="http://basbrun.com/2012/05/30/quiz-buzzer-system/">Quiz Buzzer System</a> for my mother. She loves it but she is still keeping track of scores using a pencil and a piece of paper. I decided to fix that using an <a rel="nofollow" title="Adafruit Trinket Board" target="_blank" href="https://www.adafruit.com/products/1501">Adafruit Trinket microcontroller board</a>, a 4 digits 7 segments display and two arcade style buttons. You will find good tutorials about the Trinket on the Adafruit learning center.</p>
<p><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/ngg_featured/img_20140708_130155.jpg"><img class="alignnone wp-image-1482" src="http://basbrun.com/wp-content/uploads/ngg_featured/img_20140708_130155.jpg" alt="img_20140708_130155" width="512" height="384"/></a></p>
<h3>Shift Registers & Prototyping</h3>
<p>The 7 segment display I am using doesn’t provide any logic and must be driven directly by the micro-controller. Since it would require more output pins than what is available on the Trinket, we will use two shift registers.</p>
<p>I am using the 74HC595 shift register to drive each segment and the TPIC6B595 to sink whole digits. Because sinking a digit potentially requires 7 times more current than driving a segment, we use the TPIC6B595 high power shift register. The popular 74HC595 will be more than adequate to drive each segment.</p>
<p>To control one or more shift registers you need three outputs on your micro-controller, one for the clock, one for the data and one for the latch. The latch pin is used to clear the register memory and write to the outputs when the data has been written using the clock and data pins. To send a bit of data you sink the clock, set the data pin to the value you want to write and pull the clock back up.</p>
<p>I did not used the ShiftOut library but used the schematics presented on their page to wire my circuit. You can find this very well written tutorial at <a rel="nofollow" title="Arduino ShifOut" target="_blank" href="http://arduino.cc/en/tutorial/ShiftOut">http://arduino.cc/en/tutorial/ShiftOut</a>.</p>
<p>I soldered all the parts for this project on an Adafruit breadboard prototyping board.  All the Trinket code for this project can be found on my Github account at <a rel="nofollow" title="Github - scorecounter" target="_blank" href="https://github.com/pchretien/scorecounter">https://github.com/pchretien/scorecounter</a>. The code comments contains info on which Trinket pin to use for each part.</p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2014/08/15/score-display-box/">See image gallery at basbrun.com</a>] </p>
<h3>Woodworking</h3>
<p>To build the enclosure any box would do. For this project I decided to make a nice looking wooden enclosure using pine and mahogany. The technique used here is almost the same as for building bandsaw boxes.</p>
<p>First step, glue a stack of wood together and flatten the face that will become the bottom of the box. Once the blank has cured, cut the excess wood and make all faces flat and square.</p>
<p>It is now time to cut the front and back of the box on the band-saw. Cut a 1 inch piece for the front so you have enough room to fit the seven segment display. For the back, remove about 1/4 inch of material. This will be the door to access the internal circuit.</p>
<p>It’s now time to cut the interior of the box on the band-saw. Make the entry cut on the bottom of the box so it will not show on the final project. I suggest using a maximum of 6 tooth per inch (tpi) blade to make the cut since a lot of wood needs to be cleared when cutting a piece this tick.</p>
<p>Now, do the same on the front panel to fit the seven segment display. Use the display to mark the dimensions of the hole and start cutting at the bottom to hide the entry cut. Make the hole a bit smaller and finish it with a file to get a snug fit.</p>
<p>The last cuts you have to make are the two holes for the buttons and the hole in the back for the USB cable. You may want to install all the electronic inside the box before to drill the hole for the USB cable to make sure it aligns with the Trinket connector.</p>
<p>Cutting the interior of the body and the front panel with the band-saw leaved two entry cuts you now have to close. Simply apply some wood glue in the cut and close it using clamps. Let dry for about an hour.</p>
<p>Finally sand and apply some finish on the box and screw the back in place using #4 wood screws.</p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2014/08/15/score-display-box/">See image gallery at basbrun.com</a>] </p>
<h3>Final Product</h3>
<p>You are done.</p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2014/08/15/score-display-box/">See image gallery at basbrun.com</a>] </p>]]></content:encoded>
      </item>
      <item>
         <title>Where's it Up - System Upgrades.</title>
         <link>http://blog.preinheimer.com/index.php?/archives/428-Wheres-it-Up-System-Upgrades..html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/428-guid.html</guid>
         <pubDate>Sun, 10 Aug 2014 00:22:45 +0000</pubDate>
         <content:encoded><![CDATA[<p>We've made significant updates to the infrastructure supporting Where's it up this year. Many of these changes were necessitated by some quick growth from a few thousand tests per day to several million. Frankly without the first two, I'm not sure we could have remained stable much past a million tests per day.</p>

<h1>MongoDB Changes</h1>
<p>I blogged about our <a rel="nofollow" target="_blank" href="http://blog.preinheimer.com/index.php?/archives/391-Improving-Wheres-it-Up-by-slowing-it-down.html">switch to MongoDB</a> for <a rel="nofollow" target="_blank" href="http://wheresitup.com/">Where&#8217;s it Up</a> a while back, and we&#8217;ve been pretty happy with it. When designing our schema, I embraced the &#8220;schema free world&#8221; and stored all of the results inside a single document. This is very effective when the whole document is created at once, but it can be problematic when the document will require frequent updates. Our document process was something like this:</p>
<ul>
<li>User asks Where&#8217;s it up something like: Test google.com using HTTP, Trace, DNS, from Toronto, Cairo, London, Berlin.</li>
<li>A bare bones Mongo document is created identifying the user, the URI, tests, and cities.</li>
<li>One gearman job is submitted for each City-Test pair against the given URI. In this instance, that&#8217;s 12 separate jobs.</li>
<li>Gearman workers pick up the work, perform the work, and update the document created earlier using <a rel="nofollow" target="_blank" href="http://docs.mongodb.org/manual/reference/operator/update/set/#up._S_set">$set</a></li></ul>
<p>This is very efficient for reads, but that doesn&#8217;t match our normal usage: users submit work, and poll for responses until the work is complete. Once all the data is available, they stop. We&#8217;ve optimized for reads in a write heavy system. </p>

<p>The situation for writes is far from optimal. When Mongo creates a document, under exact fit allocation, it considers the size of the data being provided, and applies a padding factor. The padding factor maxes out at 1.99x. Because our original document is very small, it&#8217;s essentially guaranteed to grow by more than 2x, probably with the first Traceroute result. As our workers finish, each attempting to add additional data into the document, it will need to be moved, and moved again. MongoDB stores records contiguously on disk, so every time it needs to grow the document it must read it off disk, and drop it somewhere elsewhere. Clearly a waste of I/O operations.</p>

<p>It&#8217;s likely that <a rel="nofollow" target="_blank" href="http://docs.mongodb.org/manual/core/storage/#power-of-2-sized-allocations">Power of 2 sized allocations</a> would better suit our storage needs, but they wouldn&#8217;t erase the need for moving entirely, just reduce the number of times it&#8217;s done.</p>

<b>Solution:</b>

<p>Normalize, slightly. Our new structure has us storing the document framework in the results collection, and each individual work result from the gearman worker is stored in results_details in its own document. This is much worse for us on read: we need to pull in the parent document, then the child documents. On write, we&#8217;re saved the horrible moves we were facing previously. Again, the usage we&#8217;re actually seeing is: Submit some work, poll until done, read complete dataset, never read again. So this is much better overall.</p>

<p>We had some slight work to manage to make our front end handle both versions, but this change has been very smooth. We continue to enjoy how MongoDB handles replica sets, and automatic failover.</p>


<h1>Worker Changes</h1>

<p>We&#8217;ve recently acquired a new client which has drastically increased the number of tasks we need to complete throughout the day: checking a series of URLs using several tests, from every location we have. This forced us to re-examine how we&#8217;re managing our gearman workers to improve performance. Our old system:</p>

<ul>
<li>Supervisor runs a series of workers, no more than ~204. (Supervisor&#8217;s use of python&#8217;s select() limits it to 1024 file descriptors, which is allows for ~204 workers)</li>
<li>Each worker, written in PHP, connects to gearman stating it&#8217;s capable of completing all of our work types</li>
<li>When work arrives, the worker runs a shell command that executes the task on a remote server using a persistent ssh tunnel. Waits for the results, then shoves them into MongoDB.</li>
</ul>

<p>This gave us a few problems:
<ul>
<li>Fewer workers than we&#8217;d like, no ability to expand</li>
<li>High memory overhead for each worker</li>
<li>The PHP process spends ~99.9% of its time waiting, either for a new job to come in, or for the shell command it executed to complete.</li>
<li>High load with 1 PHP process per executing job (that actually does work)</li>
</ul></p>
<p>We examined a series of options to replace this, writing a job manager as a threaded Java application was seriously considered. It was eventually shot down due to the complexities of maintaining another set of packages, and due to the reduced number of employees who could help maintain it. <a rel="nofollow" target="_blank" href="https://github.com/brianlmoon/GearmanManager">Brian L Moon&#8217;s Gearman Manager</a>  was another option, but it left us running a lot of PHP we weren&#8217;t using. We could strip down PHP to make it smaller, but it wouldn&#8217;t solve all our problems. </p>

<p style="margin-left:10px;color:#7C8699;">Minimizing the size of PHP is pretty easy. Your average PHP install probably includes many extensions you&#8217;re not using on every request, doubly so if you&#8217;re looking at what&#8217;s required by your gearman workers. Look at <span class="code-inline">./configure  --disable-all</span> as a start.</p>


<b>Solution:</b>
<p>Our solution involves some lesser-used functions in PHP: proc_open, stream_select, and occasionally posix_kill. </p>

<p>We set Gearman to work in a non-blocking fashion. This allows us to poll and check for available work without blocking until it becomes available. </p>

<p>Our main loop is pretty basic:
<ol>
<li>Check to see if new work is available, and if so start it up. </li>
<li>Poll currently executing work to see if there&#8217;s data available, if so record it. </li>
<li>Check for defunct processes that have been executing for too long, kill those. </li>
<li>Kill the worker if it's been running too long.</li>
</ol></p>

<p>Check for available work<br />
Available work is fired off using proc_open() (our work tends to look something like this: <span class="code-inline">
sudo -u lilypad /etc/wheresitup/shell/whereisitup-trace.sh seattle wonderproxy.com</span>). We save the read pipe for later access, and set it to non-blocking. We only allow each non-blocking worker to execute 40 jobs concurrently, though we plan to increase the limit after more testing. </p>

<p>Poll currently executing work for new data <br />
Check for available data using stream_select() using a very low poll time. Some of our tests, like dig or host, tend to return the data in one large chunk; others, like traceroute, return data slowly over time. Longer running processes (traceroute seems to average 30 seconds) will have their data accumulated over time and appended together. If the read pipe is done (checked with feof()) close them off, and close the process (proc_close)</p>

<p>Check for defunct processes<br />
We track the last successful read from each process, if it was more than 30 seconds ago we close all the pipes then recursively kill the process tree. </p>

<p>Kill the worker<br />
Finally, the system keeps track of how much work it&#8217;s done. Once it hits a preset limit, it stops executing new jobs. Once its current work is done, it dies. Supervisor automatically starts a new worker.</p>


<h1>Site Changes</h1>

<p>Our original site wasn&#8217;t actually hugely problematic. We had used a large framework, which often left me feeling frustrated. I&#8217;ve lost days fighting with it, on everything from better managing 404s to handling other authentication methods. It was the former that lead to me rage-quitting the framework  and installing Bullet. That said, we&#8217;re not afraid to pull in a library to solve specific problems, we&#8217;ve been happily using <a rel="nofollow" target="_blank" href="http://framework.zend.com/manual/1.10/en/zend.mail.html">Zend_Mail</a> for a long time. </p>

<b>Solution:</b>
<p>We&#8217;ve re-written our site to use the <a rel="nofollow" target="_blank" href="http://bulletphp.com/">Bullet framework</a>. Apart from appreciating micro frameworks in generally, they&#8217;re particularly apt for delivering APIs. We&#8217;ve had great success writing tests under Bullet, and being able to navigate code in minutes rather than hours is an everlasting bonus. This leaves the code base heavily weighted to business logic, rather than a monolithic framework. </p>]]></content:encoded>
         <category>PHP</category>
      </item>
      <item>
         <title>The lights are way too bright</title>
         <link>http://blog.preinheimer.com/index.php?/archives/427-The-lights-are-way-too-bright.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/427-guid.html</guid>
         <pubDate>Thu, 31 Jul 2014 01:41:31 +0000</pubDate>
         <content:encoded><![CDATA[<p>Yesterday either the city or Toronto Hydro went through and replaced the streetlights in my neighbourhood. This seemed good, keep the lights working. Then night fell, and while walking to bed I wondered why there was a car with xenon headlights on my front lawn pointing its headlights at my bathroom. That was the only logical reason I could think of for my bathroom to be so bright. It wasn't a car. It was the new streetlights. My entire street now looks like a sports field.</p><br />
<br />
<p>Here is Palmerston, a nice street with pretty street lights (much prettier than ours):<br /><br />
<img class="serendipity_image_left" width="640" height="427" src="http://blog.preinheimer.com/uploads/DSC_4880.jpg" alt=""/></p><br />
<br style="clear:both;"/><br />
<p>Here is Markham, with the sports field effect:<br /><img class="serendipity_image_left" width="640" height="427" src="http://blog.preinheimer.com/uploads/DSC_4883.jpg" alt=""/></p><br />
<br style="clear:both;"/><br />
<p>I took those two pictures on the same camera, with the same settings. I exported them both using the same white balance value. Full resolution options are posted <a rel="nofollow" target="_blank" href="http://preinheimer.smugmug.com/Lights/n-DWTHd/">at smugmug</a>. I have emailed Toronto 311, who has forwarded me on to Toronto Hydro. In the meantime I'm going to need upgraded blinds, and to start wearing my sunglasses at night.</p>]]></content:encoded>
      </item>
      <item>
         <title>Our Mongo Replication &amp;#38; Read Preference Whoopsie</title>
         <link>http://blog.preinheimer.com/index.php?/archives/426-Our-Mongo-Replication-38;-Read-Preference-Whoopsie.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/426-guid.html</guid>
         <pubDate>Fri, 27 Jun 2014 01:45:10 +0000</pubDate>
         <content:encoded><![CDATA[<p>We recently expanded the number of disks for the raid on the main server handling <a rel="nofollow" target="_blank" href="http://wheresitup.com/">Where&#8217;s it Up</a> requests. Rebuilding that array took roughly 28 hours, followed by background indexing which took another 16 hours.</p>

<p>During the rebuild, the raid controller was doing its best to monopolize all the I/O operations. This left the various systems hosted on that server in a very constrained I/O state, iowait crested over 50% for many of them, while load breached 260 on a four core vm. Fun times.</p>

<p>To help reduce the strain we shut down all un-needed virtual machines, and demoted the local Mongo instance to secondary. Our goal here was to reduce the write load on the constrained machine. This broke the experience for our users on wheresitup.com.</p>

<p>We&#8217;ve got the PHP driver configured with a read preference of <a rel="nofollow" target="_blank" href="http://www.php.net/manual/en/mongo.readpreferences.php">MongoClient::RP_NEAREST</a>. This normally isn&#8217;t a problem, we&#8217;re okay with some slightly stale results, they&#8217;ll be updated in a moment. Problems can occur if the nearest member of the replica set doesn&#8217;t have a record at all when the user asks. This doesn&#8217;t occur during normal operations as there&#8217;s a delay between the user making the request, and being redirected to the results page that would require them. </p>

<p>Last night, with the local Mongo instance so backed up with IO operations, it was taking seconds not ms for the record to show up. </p>

<p>We shut that member of the replica set off completely, and <a rel="nofollow" target="_blank" href="http://www.amazon.com/gp/product/B00I6JOBTI?ie=UTF8&camp=213733&creative=393185&creativeASIN=B00I6JOBTI&linkCode=shr&tag=preinheimerco-20&linkId=CIEIQEMG6PFR5JBZ&qid=1403833589&sr=8-2&keywords=lego+movie">everything was awesome</a>. Well, apart from the 260 load.</p>]]></content:encoded>
         <category>PHP</category>
      </item>
      <item>
         <title>To include design in your dev sprint or get it done ahead of time?</title>
         <link>http://feedproxy.google.com/~r/position-absolute/nyJv/~3/sQRYFALMLAM/</link>
         <description>&lt;p&gt;One tough question that product managers seem to be split in half. In web development, design is often a big part of the product &amp;#038; takes a bigger place than in a conventional software product. That means you need to&amp;#8230;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.position-absolute.com/?p=4870</guid>
         <pubDate>Tue, 17 Jun 2014 12:02:19 +0000</pubDate>
         <content:encoded><![CDATA[<p>One tough question that product managers seem to be split in half. In web development, design is often a big part of the product &#038; takes a bigger place than in a conventional software product. That means you need to take more time for design, have multiple breeds of devs, front-end &#038; back-end &#038; fit all that in a scrum mindset.</p>
<p>That makes for some headache, that is why product managers will often opt to put design one sprint ahead. It&#8217;s just easier to manage, but at what cost?</p>
<p><img src="http://izquotes.com/quotes-pictures/quote-it-is-a-mistake-to-try-to-look-too-far-ahead-the-chain-of-destiny-can-only-be-grasped-one-link-at-winston-churchill-282075.jpg"><br />
On one side you get people that say you should never split design from development, all in one sprint. </p>
<p>1. Your user stories take two sprints for being done instead of one, big iterations are slower.<br />
2. Design &#038; development get split a bit, less collaboration on design creation, may miss some important answers.<br />
3. Developers takes less accountability of the design<br />
4. Designers get caught up between two guns, must deliver next sprint user stories but also help developers do mini iterations when the design does not work as expected.</p>
<p>Then on the other side, keeping both separate has also great advantages:</p>
<p>1. Most teams already worked somewhat like that, ease workflow between design &#038; development<br />
2. Easier to manager front-end devs workflow, always work to do<br />
2. Make sure devs understand the user stories well, better estimation<br />
3. Easier to manage designs flow, can get inputs from users &#038; stackholder before going to development stage</p>
<h2>For me..</h2>
<p>I&#8217;m frankly not sure one option is always better than the other one. I guess it depends a lot on the team, the company, the culture you are in.</p>
<p>For now I opt to do design one sprint ahead, on some projects it makes sense to do it in the same sprint, but in a lot of projects, user stories can have more development than design, so figuring out how to make all that work in every sprint is a big headache.</p>
<p>I still integrate the designers in the agile team, they are there at the daily scrum, the devs know what the designers are working on, it&#8217;s a base to build upon, it all can change in the development sprint but at least we have some foundation we can start working with, and iterating on.</p>
<img src="http://feeds.feedburner.com/~r/position-absolute/nyJv/~4/sQRYFALMLAM" height="1" width="1" alt=""/>]]></content:encoded>
         <category>Product management</category>
      </item>
      <item>
         <title>Introducing packagecloud.io</title>
         <link>http://feedproxy.google.com/~r/JamesOnSoftware/~3/VcWN1G5oxMg/introducing-packagecloud.html</link>
         <description>&lt;p&gt;Every operation of any sufficient complexity winds up accumulating a bunch of internal debs, rpms, rubygems, and whatever other package types are relevant to the company. Unfortunately, finding a place to put them is usually a big headache.&lt;/p&gt;

&lt;p&gt;The tooling for managing package repositories is buggy, frustrating, and outdated at best. Even if you do manage to get a repository setup, getting https, gpg signing, backups, and all the other stuff right takes forever, and even then, deployment of new packages is usually some bizarre process involving &lt;tt&gt;scp&lt;/tt&gt; and running a script.&lt;/p&gt;

&lt;p&gt;Having managed this process (poorly) several times ourselves, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://twitter.com/joedamato&quot;&gt;Joe&lt;/a&gt; and I set out to try to come up with a better solution. We've been in private beta for a couple of months, and we're finally ready to do a public release.&lt;/p&gt;

&lt;p&gt;If you've ever managed a package repository before, I bet this'll make you as excited as it makes me:&lt;/p&gt;

&lt;div style=&quot;text-align:center;&quot;&gt;
  &lt;img/&gt;
&lt;/div&gt;




&lt;br /&gt;


&lt;p&gt;Check it out at: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://packagecloud.io&quot;&gt;packagecloud.io&lt;/a&gt; and join us in #packagecloud on freenode. We'd love to hear your feedback.&lt;/p&gt;
&lt;img src=&quot;http://feeds.feedburner.com/~r/JamesOnSoftware/~4/VcWN1G5oxMg&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">tag:jamesgolick.com,2014-04-13:1397438597</guid>
         <pubDate>Mon, 14 Apr 2014 01:23:17 +0000</pubDate>
      </item>
      <item>
         <title>The Kissability Test</title>
         <link>http://blog.preinheimer.com/index.php?/archives/425-The-Kissability-Test.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/425-guid.html</guid>
         <pubDate>Sat, 29 Mar 2014 14:40:39 +0000</pubDate>
         <content:encoded><![CDATA[<p>Back in the fall of 2010 I was kicked out of my apartment for a few hours by my fantastic cleaning lady, and I wandered the streets of Montr&#233;al on Cloud 9. Not because of the cleaning mind you, but because I&#8217;d kissed Allison for the first time the night before, while watching a movie on my couch (Zombieland). Great night. My wanderings took me to the flagship Hudson&#8217;s Bay store in Montreal, and inevitably to the electronics department. I decided to check out the 3D televisions.</p>

<p>The first problem I ran into with the 3D TVs was the glasses, they didn&#8217;t work. I tried on the first pair (which had an ugly, heavy, security cable attaching them to a podium), no dice. I tried on the second pair, no luck there either. Looking at the glasses in more detail, I found a power button! Pushed, tried them on, nothing. Repeated the process on the other pair, still nothing. There I was, big electronics department, with a range of 3D TVs in front of me, and the glasses didn&#8217;t work.</p>

<p style="margin-left:10px;color:#7C8699;">If I was going to describe the target market for 3d televisions in 2010, I might have included a picture of myself. Male, 30, into technology, owns a variety of different entertainment products and consoles, decent disposable income. As far as I could tell I represented the exact person they were hoping would be the early adopters on these. </p>

<p>While wandering off I finally encountered a sales person, I mentioned that the glasses for the TVs didn&#8217;t work. He told me they were fine, and motioned for me to follow him. It turned out that you had to push and hold the power button down for a few seconds in order to turn them on. As I put them on the sales person walked away, and I got to enjoy a demo video in 3D. </p>

<p>Well, sort of. First the glasses had to sync with the television, then I was all set, great demo video on directly in front of me. Of course, I wasn&#8217;t in a room with a single television, there was several along the wall to the right and left of the central television, and since my glasses had sync&#8217;d with the one directly in front of me (not the others), the other televisions had essentially been turned into strobe lights. Incessantly blinking at me. When I turned my head towards the blinking lights the glasses re-sync&#8217;d with a different television, a disorienting procedure that allowed me to view it properly, but turned the one directly in front of me into a strobe light. </p>

<p>So, after requiring aid to put on a pair of glasses that were practically chained down, I was being forced to view very expensive televisions adjacent to a series of strobing pictures with an absentee salesman. </p>

<p>Despite all of the issues, this was really cool! This was 3D, for my living room! No red-blue glasses either, this was the real thing! Maybe I could get one, then invite Allison over again for a 3D MOVIE! Clearly owning impressive technology was the way to any woman&#8217;s heart. While those thoughts were racing through my mind I caught my own reflection in a mirror, the glasses were not pretty. If you picture a pair of 3d glasses in your head right now, you&#8217;re probably imagining the modern polarized set you get at the movie theatre. Designed to fit anyone, over prescription glasses, rather ugly so people don&#8217;t steal them. Those glasses were years away back in 2010, and these were active shutter glasses. Rather than just two panes of polarized plastic, they each lens was a small LCD panel capable of going from transparent to opaque and back many times a second. They looked a little like this, but in black:
<a rel="nofollow" class="serendipity_image_link" target="_blank" href='http://en.wikipedia.org/wiki/File:CrystalEyes_shutter_glasses.jpg'><img style="display:block;margin-left:auto;margin-right:auto;padding-top:15px;padding-bottom:15px;" width="320" height="256" src="http://blog.preinheimer.com/uploads/CrystalEyes_shutter_glasses.png" alt=""/></a>
</p>

<p>As I put the glasses back on the presentation pedestal and rubbed my sore nose I realized: There was absolutely no way I could try to kiss a girl for the first time wearing a pair of those. I left the TVs behind, I think I picked up some apples I could slice and flamb&#233; to serve over ice cream instead. </p>


<p><b>The kissability test</b>: When considering a product, could you imagine kissing someone you care about for the first time while using it. </p>]]></content:encoded>
         <category>Op-Ed</category>
      </item>
      <item>
         <title>Stuart McLean</title>
         <link>http://blog.preinheimer.com/index.php?/archives/424-Stuart-McLean.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/424-guid.html</guid>
         <pubDate>Sun, 23 Mar 2014 14:23:20 +0000</pubDate>
         <content:encoded><![CDATA[<p>Stuart McLean is a fantastic story teller. I’ve enjoyed his <a rel="nofollow" target="_blank" href="http://www.amazon.com/gp/search/?ie=UTF8&camp=213733&creative=393193&linkCode=shr&tag=preinheimerco-20&h=n%3A283155%2Ck%3Astuart+mclean%2Cp_n_feature_browse-bin%3A2656022011&keywords=stuart+mclean&qid=1395584795&rnid=618072011">books</a> immensely, but most of all, I’ve enjoyed listening to him tell me his stories on the radio, either directly through CBC Radio 2, or through the podcast made of the show. This past Christmas, I was gifted tickets to see and hear him live here in Toronto, a wonderful time.</p>

<p>When I listen to him on the radio, as his calming voice meanders through the lives in his stories, I often picture him. In my mind, he’s sitting in a library on overstuffed leather chair, with a tweed coat laid over the arm, a side table with a lamp and glass of water beside him… perhaps a large breed dog dozing at his feet.  As each page came to an end he leisurely grasps the corner, sliding his fingers under the page, gently turning it, just as an avid reader moving through a treasured novel. This is the man I picture when I hear the measured voice regaling me with tales from the mundane to the fantastic.</p>

<p>This could not be further from the truth.</p>

<p>The man I saw at the Sony Centre for the Performing Arts has nothing in common with the man I pictured but the voice. As his story began, as he lapsed into those measured tones, his feet never stopped moving. He danced around the microphone like a boxer, stepping closer to make a point, jumping to the side in excitement, waving his arms in exclaim, always ready to strike us with another adverb. When he reached the bottom of each page, he’d frantically reach forward and throw it back, as eager as a child on Christmas morning. It’s easy to fall under the spell of a great storyteller, to stop seeing and only listen, but his fantastically animated demeanour shook that away, and spiced the story in ways I couldn’t have imagined over years of radio listening.</p>

<p>Listen to his <a rel="nofollow" target="_blank" href="http://www.cbc.ca/vinylcafe/home.php">podcast</a> for a while, then go see him live, he’s an utter delight. </p>]]></content:encoded>
         <category>Op-Ed</category>
      </item>
      <item>
         <title>Motion Detector Box</title>
         <link>http://basbrun.com/2014/03/21/motion-detector-box/</link>
         <description>The initial goal for this project was to build a project enclosure out of wood. I initially had no idea what project I would do with it. I designed the dimensions so that an Arduino could fit inside the box and allow for some space on top for a shield, some sensors and buttons. The [&amp;#8230;]</description>
         <guid isPermaLink="false">http://basbrun.com/?p=1392</guid>
         <pubDate>Fri, 21 Mar 2014 16:40:38 +0000</pubDate>
         <content:encoded><![CDATA[<p><span style="line-height:1.5em;">The initial goal for this project was to build a project enclosure out of wood. I initially had no idea what project I would do with it. I designed the dimensions so that an Arduino could fit inside the box and allow for some space on top for a shield, some sensors and buttons. The project ended up as a motion detector lamp. Combined with a small python script running on a computer, it locks the computer when motion is detected. Of course, what the python script does when motion is detected is up to you, this is just a simple proof of concept.</span></p>
<div style="width:522px;" class="wp-caption alignnone"><img class="ngg-singlepic ngg-none" style="border:1px solid black;" title="Motion Detector Lamp" alt="Motion Detector Lamp" src="http://basbrun.com/wp-content/gallery/motionbox/20140217_1358211.jpg" width="512" height="384"/><p class="wp-caption-text">Motion Detector Lamp</p></div>
<p><strong>Woodworking</strong></p>
<p>The enclosure is made out of yellow birch and mahogany. The technique is a derivative of the <a rel="nofollow" title="Band-saw Box" target="_blank" href="http://en.wikipedia.org/wiki/Bandsaw_box">band-saw box technique</a> used to build small boxes out of a piece of solid wood. The first step is to make a solid block of wood by gluing several pieces together. I decided to sandwich a piece of yellow birch between two pieces of mahogany. Clamp the pieces together and let dry for about an hour.</p>
<p>Next, remove the clamps and square the block on a table-saw or using a jointer. Once the block is squared, cut the two side panels and carve the interior of the box on the band-saw. Make sure you leave enough material for the screws that will hold the side panels. Finally, put it all back together, sand all visible surfaces and apply the finish of your choice.</p>
<p><strong>Tip: </strong>Make sure you drill some pilot holes when screwing the side panels to avoid splitting the wood.</p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2014/03/21/motion-detector-box/">See image gallery at basbrun.com</a>] </p>
<p><strong>Electronic</strong></p>
<p>Your project box is now done, it’s now time to fill it with electronic gear. For my project I’ll use a motion detector, 6 neo-pixels, an LED and a push button. The motion detector sits on top of the box and the six neo-pixels will be equally spaced on two sides of the box.</p>
<p>This is the build of material you’ll need to build this simple project:</p>
<ul>
<li>(1)Arduino Board</li>
<li>(1) <a rel="nofollow" title="Adafruit Proto Shield" target="_blank" href="http://www.adafruit.com/products/55">Adafruit Prototyping Shield</a></li>
<li>(6) <a rel="nofollow" title="Adafruit Neo-Pixels" target="_blank" href="http://www.adafruit.com/products/1558">Adafruit Neo-pixels</a></li>
<li>(1) Push button</li>
<li>(1) Motion detector</li>
</ul>
<p>The motion detector is quite simple to use. You power it using the Vcc/Grnd of the Arduino board and when movement is detected it sets the signal pin to 1 (5v). You should then use the ReadDigital() function in your Arduino sketch to read the state. There are two potentiometers on the motion detector, one to set the sensibility of the detector and the other to set the delay the signal pin stays up when movement is detected.</p>
<p>The Neo-pixels are even easier to use. I’ll not go into many details since Adafruit provides tons of samples on their <a rel="nofollow" title="Adafruit Learning System" target="_blank" href="http://learn.adafruit.com/">Learning System</a> . All you have to know is that only one output pin is required to drive as many Neo-Pixels as you want.</p>
<p>The button input is monitored using an interrupt. I am using an interrupt because some of the lamp mode sequences are not listening for inputs while executing. The debounce is made in the interrupt callback function. Make sure to read the<a rel="nofollow" title="Arduino Interrupt Pins" target="_blank" href="http://arduino.cc/en/Reference/attachInterrupt#.UyxnXvldXBY"> Arduino spec to know what pin of your board is associated with the interrupts you want</a> to use. For the Leonardo board interrupt 1 is associated to the pin #2 of the board.</p>
<p>Finally, I added a 3mm LED to indicate that the lamp is powered on. Not really necessary since the product is a lamp. The LED is driven through a 1K resistor connected directly to the Vcc pin of the Arduino.</p>
<p>If you want to use the project sketch with no modification connect the devices to the following pins. Note that you can change the pins you use simply by updating the values in the Arduino sketch.</p>
<ul>
<li>The IR receiver on pin #4</li>
<li>The Neo-Pixels data line on pin #3</li>
<li>The button on pin #2 (For the Leonardo board)</li>
<li>The power LED on the Vcc pin with a 1K resistor</li>
</ul>
<p> </p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2014/03/21/motion-detector-box/">See image gallery at basbrun.com</a>] </p>
<p>That’s it … What I love about these little project is that I can use it as sandbox for other projects. I make sure the USB connector is accessible so I can reprogram the board whenever I want to.</p>
<p>You will find all the source code on my github account at: <a rel="nofollow" title="Github" target="_blank" href="https://github.com/pchretien/motionbox">https://github.com/pchretien/motionbox</a></p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2014/03/21/motion-detector-box/">See image gallery at basbrun.com</a>] </p>]]></content:encoded>
      </item>
      <item>
         <title>My Week With GitHub’s Atom Editor</title>
         <link>http://feedproxy.google.com/~r/connectnothing/~3/LLHGo5tdpzc/</link>
         <description>Atom is a very promising new editor written by GitHub. It&amp;#8217;s very much in beta right now, so this post comes with some strong caveats that a lot of these facts may change in the future. That said, my motivation for posting this now is to provide early feedback about what works, and what doesn&amp;#8217;t. [&amp;#8230;]</description>
         <guid isPermaLink="false">http://gnuu.org/2014/03/10/my-week-with-githubs-atom-editor/</guid>
         <pubDate>Mon, 10 Mar 2014 16:38:59 +0000</pubDate>
         <content:encoded><![CDATA[<p><a rel="nofollow" target="_blank" href="http://atom.io">Atom</a> is a very promising new editor written by GitHub. It&#8217;s very much in beta right now, so this post comes with some strong caveats that a lot of these facts may change in the future. That said, my motivation for posting this now is to provide early feedback about what works, and what doesn&#8217;t.</p>
<p>I&#8217;m writing this with mixed emotions. Atom is an editor that feels very much like <a rel="nofollow" target="_blank" href="http://www.sublimetext.com/">Sublime Text</a> in pretty much all respects. They even borrowed most of the default keyboard shortcuts, so if you&#8217;ve been using Sublime, you will likely be able to easily migrate to Atom. That said, the &#8220;feel&#8221; is where the similarities end. Instead of a Python core, Atom is based on Node.js and WebKit, using JS (CoffeeScript), HTML, and CSS to customize and implement most of the features. Generally speaking, this is a good foundation&mdash; the problem is, Atom seems to have gotten it all wrong when it comes to laying down a strong architecture for both the plugin API and core components. If I could summarize this editor in one sentence, it would be: <em>&#8220;a promising and extensible editor sitting on a very shaky technical foundation&#8221;</em>.</p>
<p>Because Atom is being marketed as a &#8220;hackable&#8221; editor, I want to focus most of this article on the API and actual functionality that can be customized. I spent my last week both using Atom and writing a handful of plugins, 3 of which I published (<a rel="nofollow" target="_blank" href="http://atom.io/packages/atom-runner">atom-runner</a>, <a rel="nofollow" target="_blank" href="http://atom.io/packages/go-format">go-format</a>, and <a rel="nofollow" target="_blank" href="http://atom.io/packages/rst-preview">rst-preview</a>), so I would say I&#8217;ve had a good run-through of the current functionality of the editor and its API.</p>
<p>But before we get there, I do want to cover some of the basics.</p>
<h2>Feature Check? Check.</h2>
<p>First, let&#8217;s start with the easy stuff. On Atom&#8217;s landing page, GitHub bills this editor as &#8220;extensible&#8221;, &#8220;web native&#8221;, &#8220;modular&#8221;, and &#8220;full-featured&#8221;. It&#8217;s hard to argue with the first 3, because giving someone untethered access to a WebKit browser (it actually seems to be running <a rel="nofollow" target="_blank" href="https://github.com/rogerwang/node-webkit">node-webkit</a>) and displaying the entire UI inside of a DOM implicitly gives you web nativity and pretty extensive control over the entire application. Extensibility, specifically extensibility provided through the HTML, CSS, and JS web technologies that most developers (and some non-developers) know and use every day, is basically the strongest selling point this editor has. Say what you want about using HTML in a desktop application, but exposing your plugin architecture as a bunch of HTML/CSS is something even some of my non-tech friends could pick up and hack on. Foundationally, GitHub made smart technology choices.</p>
<p>That leaves us with the last point: &#8220;full-featured&#8221;. This is the one I take issue with. Although Atom already has pretty decent parity with an editor like Sublime, it&#8217;s definitely missing quite a lot of the behavior you would expect from a polished code editor. And yes, I know this is beta, and I know things will change, but things only change if there is feedback, so here it is:</p>
<h3>The Irony of Git Support</h3>
<p>So let&#8217;s take a step back and remember that this is GitHub publishing this editor. GitHub, as in, creators of the canonical social Git hosting site that most of us use. And yet, clearly lacking in this editor is any sense of actual Git support. Sure, there are line diffs and some basic diff / branch status listings in the status bar, but come on, not even a built-in &#8220;Git Commit&#8221; command? For what it&#8217;s worth, there is a cool &#8220;view [history/blame] on GitHub&#8221; command, which is alright, but I imagine for those of us hacking on planes or on non-GitHub-backed projects, that&#8217;s not really going to&#8230; fly.</p>
<h3>Runner? Builders?</h3>
<p>TextMate came with some pretty good script running support, a feature I&#8217;ve always liked more than Sublime&#8217;s variant of &#8220;Build Systems&#8221;. That said, both of these other editors have pretty good functionality for running code in the editor. I was shocked to find out that there was basically no such built-in support inside of Atom, which is what prompted me to write <a rel="nofollow" target="_blank" href="http://atom.io/packages/atom-runner">atom-runner</a>. A final version of Atom <em>must</em> support some kind of equivalent, and it <em>should</em> be built-in.</p>
<h3>Miscellaneous UI Fails</h3>
<p>Call me spoiled, but these are features I expect every editor to have, if they claim even partial support for:</p>
<ol>
<li>Tab completion is almost useless in its current state. There is no intelligent memory of the last / most used completion in the document like Sublime manages.</li>
<li>Ditto for file switching (Cmd+T in Sublime/TextMate). There is no memory of the last file, so you can&#8217;t hit the quick Cmd+T &#8211; Enter keystroke to switch between two files. You have to fuzzy-find from scratch each time&mdash; and the fuzzy-finder is extremely loose in its matching policy.</li>
<li><strike>Middle-clicking does not close tabs.</strike> &mdash; <strong>Edit</strong>: This looks to have been added into a recent build (as of 03/11/2014). Nice!</li>
<li><strike>Unless I haven&#8217;t found it, no keyboard shortcuts to split windows or move windows between tab groups.</strike> &mdash; <strong>Edit</strong>: Cmd+K, ArrowKey is how you do it. Thanks <a rel="nofollow" target="_blank" href="https://twitter.com/bryanl/status/443167886287593472">@bryanl</a>.</li>
<li>Finally, this one is probably a bug, but history support is fairly weak and often times simply switching tabs or windows will completely clobber your history. History should be the most stable part of any text editor. If I can&#8217;t trust the history management, it&#8217;s kind of a deal breaker to adoption, for me.</li>
</ol>
<h3>Performance Woes</h3>
<p>I can&#8217;t stress this one enough. <strong>Atom is extremely slow, and this is extremely disappointing</strong>. Performance-wise, running Atom today feels a lot like running Eclipse back in 2006; slow startup, visible lag when switching tabs or loading files, scroll and typing lag. To quantify this with an example, starting up the editor from the command-line in a reasonably sized project (~8 root directories, ~200 files) can take a good 7-8 seconds before the main window comes into view. Similarly, switching between tabs when clicking in the file view or tabs at the top has a noticeable lag on larger files&mdash; I&#8217;m talking up to 500ms to 1sec. Scrolling those files shows similar lag. Granted, it&#8217;s not horribly bad, but it&#8217;s enough to feel the pain when switching between Sublime and Atom.</p>
<p>My biggest fear with Atom&#8217;s performance problem is that it does not seem conceivable to me that things can get better. Given that Atom is still not &#8220;complete&#8221;, the &#8220;1.0&#8221; build will likely only have <em>more</em> code and <em>more</em> DOM nodes to render; and when more plugins are published, you will only have people running more of them at a time hogging up all that processing power. Unless there is some seriously inefficient core code running under Atom, the performance problems really seem like a fundamental architectural limitation, not just a lack of optimization. Just like Eclipse learned, you can&#8217;t optimize yourself out of bad architecture, and Moore&#8217;s law no longer moves fast enough to be able to save you from scaling CPU intensive applications&mdash; especially when your architecture is threadless and single-core-bound.</p>
<p>The only real solution here is to go the route that Chrome went and use separate processes for each tab / component. This would give you the core-scalability that CPU intensive apps need. Unfortunately, shoehorning in such a fundamental piece of infrastructure into a sizeable codebase is not an easy task&mdash; if it&#8217;s even technically possible (since everything is displayed in a single DOM, I don&#8217;t know if it is). This is really something that has to be built from the ground up, but it wasn&#8217;t. This might be the most costly mistake GitHub has made with Atom.</p>
<h2>Shaky Foundation: The API Is On One Too</h2>
<p>A common theme running through my time with Atom is that much of the core infrastructure seems half-baked or completely lacking. It&#8217;s almost as if they decided they were going to write a text editor app half way through implementing the text editor component. Much like the lack of a strong performant foundation, there are parts of the API that seem inconsistent, unnecessarily evolutionary, and just generally under-engineered. Here are a handful of <a rel="nofollow" target="_blank" href="https://www.destroyallsoftware.com/talks/wat">wat</a> moments:</p>
<h3>Documentation Where Art Thou?!</h3>
<p>The <a rel="nofollow" target="_blank" href="http://atom.io/docs">documentation</a> ranges from decent to misleading to lies to simply not there. It&#8217;s almost impossible to rely on the documentation as is, and I had to resort to simply reading other <a rel="nofollow" target="_blank" href="http://github.com/atom">core Atom plugins</a> instead of looking at docs. At the time of posting, the <code>Editor.getPath()</code> method is still missing from the docs&mdash; arguably the most important method if you&#8217;re doing anything with the files, and necessary for all 3 of the plugins I published. Similar inconsistencies and notable missing things arise, like lack of event documentation (again, necessary for each of the 3 plugins I published), and lack of explanation for seemingly similar methods.</p>
<p>I&#8217;m a little biased when it comes to docs. I happen to believe that the best way to audit an API design is by writing good documentation around it, effectively <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Eating_your_own_dog_food">dogfooding</a> your documentation as the API contract. GitHub seems to have missed the mark here in thinking that docs are an optional artifact that you build up after you&#8217;ve finished coding. It doesn&#8217;t surprise me, at least, to see that attitude translate into weak APIs and inconsistent use of those APIs across different core plugins in the editor. When there is no document guiding usage, it&#8217;s not surprising that you end up with a smorgasbord of implementations.</p>
<h3>There Are 4 Ways To Use Events</h3>
<p>Searching for a way to register events in my plugins, I ended up reading a handful of different core Atom plugins that do event registration. A came across 4 distinct ways to actually register events:</p>
<ol>
<li>You can use <code>atom.subscribe()</code>, which I found by accident. This was the easiest one, since it didn&#8217;t require any magic mixins.</li>
<li>You can use the <code>Subscriber</code> module which you can use some fancy syntax to mix into your classes. This, of course, only works if you have a &#8220;class&#8221;, something Atom does not generate for you by default (it just throws you a bare Object returned in <code>module.exports</code>).</li>
<li>You can just do your event registration in the View class, if you have one, which has <code>Subscriber</code> already mixed in.</li>
<li>Or, finally, you can use Node.js style events and just call <code>buffer.on 'event'</code> instead of going through a Subscriber.</li>
</ol>
<p>This begs the obvious question: why 4 separate ways? It also begs the more subtle but subversive question: why would you ever register an event from a <em>view</em>?</p>
<p>Again, the lack of documentation means everyone is going to find their own slightly different way to register events. After a while, you end up with a really messy API. If you missed it&mdash; events have no docs. I guess based on that fact, it&#8217;s not too surprising that the above happened.</p>
<h3>The Plugin Architecture Is Not MVC, It&#8217;s Just &#8220;V&#8221;</h3>
<p>Atom has a strong concept of a View, which is good and expected. Less expected, though, is the lack of any other kind of architectural components. Basically, the only thing you ever operate on/with are views&mdash; until you are not. There is a &#8220;View&#8221; superclass, but there is no &#8220;Controller&#8221; superclass. That&#8217;s why you have to use a View to subscribe to events, which Views shouldn&#8217;t even be doing.</p>
<p>Another great example is that in order to register a plugin command you actually have to call a method on <a rel="nofollow" target="_blank" href="https://github.com/atom/markdown-preview/blob/master/lib/markdown-preview.coffee#L16"><code>workspaceView</code></a>. Not the Workspace object, but rather, its associated view. The weird part is that the commands are not registered <em>from</em> views, they are actually registered from the pseudo-controller thingies, but they are registered <em>on</em> views. Wat.</p>
<h3>Other Various Mishaps And Crazies</h3>
<ol>
<li>You can get from an <code>EditorView</code> to its associated editor (<code>getEditor()</code>) but you cannot get back to the view. Generally in a DOM like arrangement, you should be able to get back to the parent of a child node (especially since these things <em>actually</em> are DOM nodes). Of course, this is absolutely necessary when some events are only emitted with an editor handle and not the view (like <code>atom.project</code>&#8216;s <a rel="nofollow" target="_blank" href="https://github.com/lsegal/atom-go-format/blob/master/lib/go-format.coffee#L16"><code>editor-created</code> event</a>), because you need the view to actually do anything useful (remember, it&#8217;s all in the &#8220;V&#8221;).</li>
<li><code>atom.workspace</code> has a <code>getActiveEditor()</code>, but <code>workspaceView</code> does not have <code>getActiveEditorView()</code>. Instead the latter only has <code>getActiveView()</code> (which may not be an editor).</li>
<li>There is a (undocumented, of course) <code>configDefaults</code> hook and a <code>atom.config.setDefaults</code> command. Why both?</li>
<li>There are magical &#8220;attach&#8221; and &#8220;detach&#8221; methods associated with the main module but it&#8217;s unclear how they differ from &#8220;activate&#8221; and &#8220;destroy&#8221;.</li>
<li>Serialization is apparently handled by the <a rel="nofollow" target="_blank" href="https://github.com/lsegal/atom-go-format/blob/master/lib/go-format.coffee#L28-L29">&#8220;controller&#8221;</a>, but views can <a rel="nofollow" target="_blank" href="https://github.com/lsegal/atom-runner/blob/master/lib/atom-runner-view.coffee#L8">also</a> serialize/deserialize themselves. It&#8217;s unclear which you should use and when.</li>
<li>There is a gutter API (the git-diff package uses it) but it is completely unexposed and subject to churn. Again, dogfooding is the answer, here. </li>
</ol>
<h2>But I Want To Like It</h2>
<p>I really tried hard to like Atom. I still really do like it. It&#8217;s beta, and I&#8217;m willing to bet that it will get (functionally) better. I am still, however, seriously concerned about performance, and although I thought I wouldn&#8217;t mind it too much, I found myself getting extremely frustrated with the lagginess by the end of the week, to the point where I launched Sublime a couple of times when I knew I was going to touch larger files.</p>
<p>Atom has a ton of potential. The power of using WebKit to render a UI opens a ton of doors, because it literally lets you customize every single pixel in the window. That&#8217;s power I don&#8217;t even think Vim or Emacs have. There are so many plugin ideas I have with that kind of power, including local <a rel="nofollow" target="_blank" href="http://jsfiddle.net">Fiddle</a> support, live updating game IDE features (you can use a Canvas to live-render your game) like <a rel="nofollow" target="_blank" href="http://processing.org/">Processing</a>, live <a rel="nofollow" target="_blank" href="http://brackets.io/">Brackets</a>-style web editing, and more.</p>
<p>I want Atom to work, I really do, but it&#8217;s not quite working, yet. If GitHub can resolve performance problems, lay down a solid foundation for an API, <em>document it</em>, and fix some of the minor UI glitches, they would have something I&#8217;d be happy to switch to. Until then, I&#8217;m probably going to play around with it for a little longer and then inevitably switch back to Sublime.</p><img src="http://feeds.feedburner.com/~r/connectnothing/~4/LLHGo5tdpzc" height="1" width="1" alt=""/>]]></content:encoded>
         <category>post</category>
      </item>
      <item>
         <title>Valentines Day Neck Warmer</title>
         <link>http://blog.preinheimer.com/index.php?/archives/423-Valentines-Day-Neck-Warmer.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/423-guid.html</guid>
         <pubDate>Sat, 15 Feb 2014 01:22:30 +0000</pubDate>
         <content:encoded><![CDATA[<p>I&#8217;ve had a few valentines days over the years. I&#8217;ve spent far too much money, I&#8217;ve planned in exacting detail, I&#8217;ve left things until the last minute, and I&#8217;ve spent a fair few alone. This year, I wanted something special. </p>

<p>Just after Christmas Allison was kind enough to give me a hand knit sweater she&#8217;d been working on  for over a year. It&#8217;s fantastic. Around the same time she&#8217;d commented that she was jealous of my neck warmer. An idea stuck! I&#8217;d knit her a neck warmer!</p>

<p>Small problem: I&#8217;ve never knit a thing in my life. </p>

<a rel="nofollow" class="serendipity_image_link" target="_blank" href='http://blog.preinheimer.com/uploads/2014-02-0413.17.49.jpg'><img style="padding-right:10px;padding-bottom:10px;float:left;" width="83" height="110" src="http://blog.preinheimer.com/uploads/2014-02-0413.17.49.serendipityThumb.jpg" alt=""/></a><p>I&#8217;ve never let not knowing how to do something stop me before, and this didn&#8217;t seem like the time to start. I headed up to <a rel="nofollow" target="_blank" href="http://www.eweknit.ca/">Ewe Knit</a>, where Caroline was able to administer a private lesson. First I had to use a swift to turn my skien of yarn into a ball. They appear to sell yarn in a useless format to necessitate the purchase of swifts, a good gig if you can get it. </p>
<br />

<p><a rel="nofollow" class="serendipity_image_link" target="_blank" href='http://blog.preinheimer.com/uploads/2014-02-0413.22.26.jpg'><img style="padding-right:10px;padding-bottom:10px;float:right;" width="83" height="110" src="http://blog.preinheimer.com/uploads/2014-02-0413.22.26.serendipityThumb.jpg" alt=""/></a>Once I had my nice ball of yarn I &#8220;casted on&#8221; a process I promptly forgot how to accomplish. The process mostly consisted of looping things around one of my knitting needles the prescribed number of times. That number was 17 according to the pattern. Once I&#8217;d casted on the regular knitting started, each row involved an arcane process where I attached a new loop to the loop on the previous row. The first few rows were quite terrifying, but eventually I slipped into a rhythm, and was quite happy with my progress by the time I&#8217;d made it to the picture shown below.</p>
<br />
<p><a rel="nofollow" class="serendipity_image_link" target="_blank" href='http://blog.preinheimer.com/uploads/2014-02-08-16.24.35.jpg'><img style="padding-right:10px;padding-bottom:10px;float:left;" width="83" height="110" src="http://blog.preinheimer.com/uploads/2014-02-08-16.24.35.serendipityThumb.jpg" alt=""/></a>Just a few rows later I made a terrifying discovery: I&#8217;d invented a new form of knitting. Rather than knitting a boring rectangle, I was knitting a trapezoid, and there was a hole in it. My 17 stitch pattern was now more like 27. There was nothing for it but to pull it out and basically start over.</p>
<br />
<p><a rel="nofollow" class="serendipity_image_link" target="_blank" href='http://blog.preinheimer.com/uploads/2014-02-0819.11.27.jpg'><img style="float:right;" width="83" height="110" src="http://blog.preinheimer.com/uploads/2014-02-0819.11.27.serendipityThumb.jpg" alt=""/></a>Several hours, and many episodes of The Office later, I&#8217;d slipped into a great rhythm, and developed a mild compulsion to count after every row to ensure I had 15 stitches. The neck warmer was looking great! Just another season of The Office, and some serious &#8220;help&#8221; from the cat, and I&#8217;d be finishing up.</p>
<br />
<p><a rel="nofollow" class="serendipity_image_link" target="_blank" href='http://blog.preinheimer.com/uploads/2014-02-10-13.15.46.jpg'><img style="padding-right:10px;padding-bottom:10px;float:left;" width="83" height="110" src="http://blog.preinheimer.com/uploads/2014-02-10-13.15.46.serendipityThumb.jpg" alt=""/></a>I headed back to Ewe Knit for instructions on casting off, where I tied off the loops I&#8217;d been hooking into with each row. Then I sewed the ends together, and wove in my lose ends. A neck warmer was born!</p>
<br />
<p>This felt like a success before I&#8217;d even wrapped it. I&#8217;d spent a lot of time working on something she&#8217;d value, I&#8217;d learned more about one of her hobbies, and gained new appreciation for the sweater she&#8217;d knit for me. She just needed to unwrap it.</p>
<br /><br />

<p style="font-size:2em;font-weight:bold;">She loved it. </p>
<a rel="nofollow" class="serendipity_image_link" target="_blank" href='http://blog.preinheimer.com/uploads/allisonneckwarmer.jpg'><img style="float:right;" width="816" height="612" src="http://blog.preinheimer.com/allisonneckwarmer.jpg" alt=""/></a>]]></content:encoded>
      </item>
      <item>
         <title>Samus Helps You Publish Your Open Source Software</title>
         <link>http://feedproxy.google.com/~r/connectnothing/~3/xhBtZ9uH1NM/</link>
         <description>Today I&amp;#8217;m announcing Samus, a project I&amp;#8217;ve been working on over the last few weeks that helps you automate many of the repetitive tasks involved in releasing code. Inspired by real-world events, Samus simplifies things like bumping your version, tagging your commit, pushing your changes, cutting a gem, and more. It operates via a manifest [&amp;#8230;]</description>
         <guid isPermaLink="false">http://gnuu.org/2014/02/01/samus-helps-you-publish-your-open-source-software/</guid>
         <pubDate>Sun, 02 Feb 2014 02:55:35 +0000</pubDate>
         <content:encoded><![CDATA[<p>Today I&#8217;m announcing <a rel="nofollow" target="_blank" href="http://github.com/lsegal/samus"><strong>Samus</strong></a>, a project I&#8217;ve been working on over the last few weeks that helps you automate many of the repetitive tasks involved in releasing code. Inspired by real-world events, Samus simplifies things like bumping your version, tagging your commit, pushing your changes, cutting a gem, and more. It operates via a manifest file which contains simple and discrete actions to build and publish your code. Samus knows how to clean up a failed build, and can do sanity checks to ensure everything will succeed when you finally hit the big red button. <a rel="nofollow" target="_blank" href="https://github.com/lsegal/samus/commit/7fc98c8175635ac31fc8ae8c5bb15020952e6a9e">Samus is also used to publish Samus</a>, so you can use its generic manifest in your own Ruby projects.</p>
<p>Samus is Open Source and available on <a rel="nofollow" target="_blank" href="http://github.com/lsegal/samus">GitHub</a>. You can read a lot more about how Samus works in the <a rel="nofollow" target="_blank" href="https://github.com/lsegal/samus/blob/master/README.md">README</a>, but read on if you want more example usage.</p>
<h2>Samus Goals</h2>
<p>There are a couple of problems I&#8217;m trying to solve with Samus. I noticed these problems when releasing versions of other OSS projects I maintain</p>
<ol>
<li><strong>Automate the obvious release-time tasks</strong> like bumping your library version, adding a version tag, building the RubyGem, and more. Although tools like <code>npm</code> have language specific ways to handle some of these things, Samus gives me a generic solution I can use on pretty much all the code I release, from C, to JS, to Ruby code.</li>
<li><strong>Simplify credential management</strong> so that you know your machine has the right keys <em>before</em> you try to push code. I release code from different machines. I usually have Git setup on these machines, but API keys for package managers is occasionally a different story. Samus allows me to share credentials in a way that is as secure as I need it to be</li>
<li><strong>Package an archive of the release</strong> so I can batch releases. If I&#8217;m doing a release of multiple libraries at once, I usually want them all staged before I push them out. Having a separate &#8220;stage&#8221; step lets me make sure everything is ready and working before I start a release. More on this at the end of the post.</li>
</ol>
<h2>Quick Start</h2>
<p>Here&#8217;s a simple example of how I published Samus, today:</p>
<p>First, I created a file <code>~/.samus/personal/credentials/lsegal.rubygems</code> with my RubyGems access key. The contents of the file are:</p>
<pre><code>Secret: MY_API_KEY
</code></pre>
<p>Samus looks inside <code>~/.samus</code> for <a rel="nofollow" target="_blank" href="https://github.com/lsegal/samus/blob/master/README.md#custom-commands--credentials">custom commands and credentials</a>. The sub-directories can be local-only directories, or they can be Git-backed (and optionally private) repositories that I can share with other maintainers. Organizing this is mostly up to you, so there is a lot of power here.</p>
<p>Next, I ran <code>samus build 1.0.0</code>, which used the <a rel="nofollow" target="_blank" href="https://github.com/lsegal/samus/blob/master/samus.json">samus.json</a> manifest file to run the tasks needed to build the release-v1.0.0.tar.gz file.</p>
<p>Finally, as the last step, I publish with: <code>samus publish release-v1.0.0.tar.gz</code>.</p>
<p>That&#8217;s it. In short:</p>
<pre><code>mkdir -p ~/.samus/personal/credentials
echo "Secret: API_KEY" &gt; ~/.samus/personal/credentials/lsegal.rubygems
samus build 1.0.0
samus publish release-v1.0.0.tar.gz
</code></pre>
<h2>Why Separate Build &amp; Release Steps?</h2>
<p>One big change from the normal work flow is separating &#8220;staging&#8221; a release from the release itself. Typically, when you release code, you go into your project, update version, build the gem, push code, and push the gem. This all happens from your workspace. Although this works for a single project, it does not work quite as well when you are releasing multiple versions of the same project (like, say an RC candidate and a stable release, or multiple libraries that depend on each other) at the same time. A lot of build time tasks can take a while, like running test, building docs (if necessary), occasionally compiling code, so if I&#8217;m going to release multiple things at once I want to make sure everything is good to go before I hit the button. It&#8217;s sort of the same way &#8220;git commit&#8221; and &#8220;git push&#8221; are separate tasks. You often want to make sure everything is setup locally before you &#8220;push-to-live&#8221;.</p>
<p>That said, Samus could very well include some simplistic &#8220;build-and-push&#8221; single-command syntax, if it were useful.</p>
<h2>Samus TODO &amp; Contributing</h2>
<p>Although Samus is designed to be a simplistic tool, there is still a few extra features it could use. Here are a handful of ideas:</p>
<ol>
<li><strong>Samus could use more build and publish commands</strong>. For example, a command to update your changelog at build-time, more control over Git workflow management, and integration with more package managers (only RubyGems and npm are currently supported) would be great.</li>
<li><strong>Improving the credential management to support different setups</strong>. Currently Samus does rely on SSH keys being available on the machine for Git commands. I would like to fix that.</li>
<li><strong>Self-contained releases could be useful</strong>. Right now you still need some local setup to use Samus, like credentials on your machine, and occasionally some binaries (custom commands, if you use them). Being able to build a self-contained archive with all the custom commands and credentials in the zip would make publishing much more reliable (though a little less secure if that archive got leaked).</li>
</ol>
<p>Extra commands are always welcome, so if you have an idea for a generic command, feel free to submit a pull request to have it included in Samus.</p>
<p>If you think Samus would be useful, feel free to give it a spin and let me know what you think. I <a rel="nofollow" target="_blank" href="https://github.com/lsegal/yard/commit/77a02c827c6c0efc6fb8f9c22ead741aa9fd9743">just updated YARD</a> to use Samus by adding the manifest file in the Quick Start above&#8211; for most Ruby projects, this would be enough to get you started.</p><img src="http://feeds.feedburner.com/~r/connectnothing/~4/xhBtZ9uH1NM" height="1" width="1" alt=""/>]]></content:encoded>
         <category>post</category>
      </item>
      <item>
         <title>The hack a day effect</title>
         <link>http://basbrun.com/2013/12/18/the-hack-a-day-effect/</link>
         <description>On November 24th of this year I published an article on my blog on how to build an RGB lamp controlled by RFID tags. I first announced the post on LinkedIn, Facebook and Twitter. Because of my very limited number of contacts in these social medias, the effect was unnoticeable. I then published the post [&amp;#8230;]</description>
         <guid isPermaLink="false">http://basbrun.com/?p=1307</guid>
         <pubDate>Thu, 19 Dec 2013 04:04:44 +0000</pubDate>
         <content:encoded><![CDATA[<p>On November 24th of this year I published an article on my blog on how to build an RGB lamp controlled by RFID tags. I first announced the post on LinkedIn, Facebook and Twitter. Because of my very limited number of contacts in these social medias, the effect was unnoticeable.</p>
<p>I then published the post on <a rel="nofollow" title="Reddit" target="_blank" href="http://www.reddit.com">reddit.com</a>. The post generated about 75 more visits in the hours following the post. That was cool but nothing that deserve a complete blog post.</p>
<p><a rel="nofollow" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/12/visits1.jpg"><img class="alignnone size-full wp-image-1312" alt="visits" src="http://basbrun.com/wp-content/uploads/2013/12/visits1.jpg" width="600" height="371"/></a></p>
<p>A few days later, for the second time in the short  life of this blog, I have been published on<a rel="nofollow" title="Hack A Day" target="_blank" href="http://www.hackaday.com"> hackaday.com</a>. In less than 2 hours I got more than 500 visits. This is quite unusual for my blog! :) Of course, that is far from what has been described as the slashdot effect, capable of killing your web server for hours, but I was pretty proud of that appearance.</p>
<p>A week later, I published my article on the DIY site <a rel="nofollow" title="Instructables" target="_blank" href="http://www.instructables.com">instructables.com</a>. This site shows the number of visits on the project page. The page view was going up pretty fast when I got featured on the front page of the site. From that moment on the visits exploded. After five days on the site I have more than 10 000 views. This is more than 10 times the number of visits from hack a day.</p>
<p>An other thing I learned this month is that you can share links with other websites. <a rel="nofollow" title="EEWeb" target="_blank" href="http://www.eeweb.com/websites/basbrun">Eeweb.com</a> offered me to publish my website as the website of the day. I thought that sounds a bit 90’s but I decided to give it a try. After two days featured as the site of the day I received 19 visitors from their website. That’s not a lot of visibility for my projects and now I have to put a link to their website on mine. Done.</p>
<p>But then, can we compare visits on my blog to page views on instructables … I don’t think so. It is much harder to bring visitors on your website than to get page views on a site like instructables. The question is, what ratio of the hack a day visitors actually click on the link to my website. For most visitors the text published by the hack a day staff is enough and they don’t feel the need to visit my blog.</p>
<p>Some people will argue that we must also consider the “quality” of the visitors. That would mean that the 1000 visitors from hack a day are of “less quality” because they come from a site that only gives an overview of the post. That would also mean that  the 300 or so visitors from instructables are “high quality” visitors because they come from a site that publishes the complete article, which means they visit the blog to learn more about your work.</p>
<p>Well, I don’t really know much about all this web mathematics but since it gets real close to marketing I have a tendency to believe this is … bullshit. I like as much my 75 extra visitors from Reddit than the 10 000 viewers of my instructables project. I write a blog to share my project and ideas, the more I am read, the more I am happy.</p>]]></content:encoded>
         <category>Ideas</category>
      </item>
      <item>
         <title>RGB Lamp Controlled by RFID Tags Built As An Arduino Shield</title>
         <link>http://basbrun.com/2013/11/24/rgb-rfid-lamp/</link>
         <description>Making the Scary Monkey project with my son has been a lot of fun so I decided to make another project for the kids. I built an interactive RGB lamp. The lamp has no switch and no dimmer, it’s entirely controlled with radio frequency identification (RFID) tags. The RFID reader is hidden in the lamp [&amp;#8230;]</description>
         <guid isPermaLink="false">http://basbrun.com/?p=1253</guid>
         <pubDate>Mon, 25 Nov 2013 02:36:10 +0000</pubDate>
         <content:encoded><![CDATA[<p>Making the <a rel="nofollow" title="&#x00201c;Scary&#x00201d; Stuffed Monkey" target="_blank" href="http://basbrun.com/2013/10/09/scary-stuffed-monkey/">Scary Monkey</a> project with my son has been a lot of fun so I decided to make another project for the kids. I built an interactive RGB lamp. The lamp has no switch and no dimmer, it’s entirely controlled with radio frequency identification (RFID) tags. The RFID reader is hidden in the lamp body and the RFID tags are embedded in colored wooden disks.</p>
<div id="attachment_1271" style="width:650px;" class="wp-caption alignnone"><a rel="nofollow" title="RGB / RFID Lamp Project" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/11/all_colors.jpg"><img class=" wp-image-1271 " style="border:1px solid black;" title="RGB / RFID Lamp Project" alt="RGB / RFID Lamp Project" src="http://basbrun.com/wp-content/uploads/2013/11/all_colors.jpg" width="640" height="373"/></a><p class="wp-caption-text">RGB / RFID Lamp Project</p></div>
<p>You can change the color of the lamp by placing a colored disc into the circular recess in front of the lamp body. When no disc is placed in the receptacle, the lamp changes color randomly. Place the white disc to produce a white light and the black disk to turn off the lamp. You can also turn the lamp into a stroboscope or produce other special effects by combining different sequences of colors.</p>
<p>The body of the lamp and the RFID disks are made out of scrap wood I had in my shop. The shade is made from a transparent drawing tube and tracing paper.</p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2013/11/24/rgb-rfid-lamp/">See image gallery at basbrun.com</a>] </p>
<h2>The material</h2>
<p>There are many different ways this project can be built. The following list only includes the essentials electronic components required for the project.</p>
<ul>
<li>RGB LEDs strip</li>
<li>3 N-Channel Mosfet transistors</li>
<li>RFID reader and tags.</li>
<li>One 3mm or 5mm LED</li>
<li>Arduino micro-controller.</li>
<li>Piezo speaker (optional)</li>
</ul>
<h2> The Circuit</h2>
<p>The circuit for this project has many uses:</p>
<ul>
<li>Drive the three color channels (RGB) of the LED strip</li>
<li>Read data sent by the RFID reader</li>
<li>Drive the “ready” LED</li>
<li>Send tones to the piezo speaker if any</li>
</ul>
<p>Since all this is controlled by an Arduino micro-controller, building the circuit as an Arduino shield would make it more compact and reusable. The arduino shield PCB design will be explained in the next section.</p>
<div id="attachment_1276" style="width:522px;" class="wp-caption alignnone"><a rel="nofollow" title="RGB / RFID Lamp Circuit (Breadboard View)" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/11/rgbrfid3_bb.jpg"><img class=" wp-image-1276" style="border:1px solid black;" title="RGB / RFID Lamp Circuit (Breadboard View)" alt="RGB / RFID Lamp Circuit (Breadboard View)" src="http://basbrun.com/wp-content/uploads/2013/11/rgbrfid3_bb.jpg" width="512" height="411"/></a><p class="wp-caption-text">RGB / RFID Lamp Circuit (Breadboard View)</p></div>
<p>The RGB channels are driven by the Arduino pulse with modulation (PWM) output pins 3, 5 and 6. The three Arduino logic pins are connected to the gate of three N-Channel Mosfet transistors. You can control the intensity of each channel by writing values from 0 to 255 on any of these pins.</p>
<p>The RFID reader communicates with the Arduino micro-controller through a serial connection. I wanted to be able to re-program the lamp without having to disconnect the RFID reader so I decided to use the SoftwareSerial library. This library allows you to use the IO pin of your choice for serial communication, freeing the pins 0 & 1 for communication with the computer. I used pins 8 and 9 of the micro-controller to communicate with the RFID reader.</p>
<p>The power is provided by a 12v 600mA wall transformer. The 12v pin of the transformer is connected to the power wire of the LED strip and to the Vin pin of the Arduino.</p>
<p>I added a small LED to indicate when the RFID reader is ready to read a new tag. This LED is connected on pin 7 of the Arduino micro-controller. Finally, an optional piezo speaker can be attached to pin #10 of the Arduino bord to integrate sounds in the project. The “ready” LED and the piezo are optionals.</p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2013/11/24/rgb-rfid-lamp/">See image gallery at basbrun.com</a>] </p>
<h2>The Arduino Shield</h2>
<p>This project was a perfect fit for a custom Arduino shield. I designed the shield using Fritzing, an open source application that allows you to build your circuit and PCB at the same time. The circuit has been designed as a single side PCB shield. You can find the Fritzing project on my Github repo at: <a rel="nofollow" title="RGB/RFID Project on Github" target="_blank" href="https://github.com/pchretien/rgbrfid">https://github.com/pchretien/rgbrfid</a></p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2013/11/24/rgb-rfid-lamp/">See image gallery at basbrun.com</a>] </p>
<h2>Woodworking</h2>
<p>I love woodworking and I love electronics so mixing both into a single project was pure fun. I used Stketchup to do draw the lamp and test the design. The plans are available on my Github account at <a rel="nofollow" target="_blank" href="https://github.com/pchretien/rgbrfid">https://github.com/pchretien/rgbrfid</a>.</p>
<div id="attachment_1290" style="width:522px;" class="wp-caption alignnone"><a rel="nofollow" title="RGB / RFID Lamp Sketchup Drawing" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/11/rgbrfid1.png"><img class=" wp-image-1290" style="border:1px solid black;" title="RGB / RFID Lamp Sketchup Drawing" alt="RGB / RFID Lamp Sketchup Drawing" src="http://basbrun.com/wp-content/uploads/2013/11/rgbrfid1.png" width="512" height="245"/></a><p class="wp-caption-text">RGB / RFID Lamp Sketchup Drawing</p></div>
<p>To build the body of the lamp I cut two pieces of 1/4″ plywood and four pieces of 3/4″ pine. To cut the shape of the lamp I printed a 1:1 template of the lamp using a TOP / Wire-frame view in Sketchup and glued it on top of the boards. To make sure the boards stayed aligned during cutting, I put some carpet tape between all pieces. (this trick from the best woodworking show on Youtube <a rel="nofollow" title="Woodworking For Mere Mortals" target="_blank" href="http://woodworkingformeremortals.com">woodworkingformeremortals.com</a>).</p>
<p>Once the shape of the lamp is cut, remove the two plywood boards and trace a line 3/4″ inside the outline of the lamp. Again, using the band-saw, cut the inside of the lamp. It’s now time to sand all the pieces and apply several coats of spay paint.</p>
<p>The six wooden disks are cut from a piece of 1/4″ plywood. Each disk is made gluing two 1/4″ disks together. Do not forget to place the RFID tags between the two pieces of plywood. I used a 1 1/2″ Fostner bit to make a shallow recess to fit the RFID tags. Sand and paint the disks with the colors of your choice.</p>
<p>Finally, I used a PVC pipe to hold the LED strip. I painted it white, cut a hole on top of the lamp and placed the pipe into the hole with epoxy glue.</p>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2013/11/24/rgb-rfid-lamp/">See image gallery at basbrun.com</a>] </p>
<h2>Assembly</h2>
<p>I assembled the lamp with my youngest kid… Here is an overview of the process.</p>
<ol>
<li>Wrap the LED strip around the PVC pipe and mark where it should be glued to cover the whole length of the pipe</li>
<li>Glue the LED strip onto the pipe and pass the wires through a hole at the bottom of the pipe</li>
<li>Attach the RFID reader under the disk holder with small wood screws</li>
<li>Attach the Arduino to the bottom of the lamp</li>
<li>Glue the small LED in the center of the disk receptacle through a small hole</li>
<li>Strip the transformer connector, pass it through a hole on the back of the lamp and make a knot</li>
<li>Connect all the wires and connectors to the Arduino shield</li>
<li>Screw the bottom of the lamp and install the rubber pads</li>
<li>Et voilà!</li>
</ol>
<p> [<a rel="nofollow" target="_blank" href="http://basbrun.com/2013/11/24/rgb-rfid-lamp/">See image gallery at basbrun.com</a>] </p>
<p> </p>
<h2>The Code</h2>
<p>You will find the Arduino code, the Sketchup drawing and the Fritzing circuit schematics on my github account at: <a rel="nofollow" target="_blank" href="https://github.com/pchretien/rgbrfid">https://github.com/pchretien/rgbrfid</a></p>
<p> </p>
<p> </p>]]></content:encoded>
      </item>
      <item>
         <title>Spending $80 to send $20</title>
         <link>http://blog.preinheimer.com/index.php?/archives/422-Spending-80-to-send-20.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/422-guid.html</guid>
         <pubDate>Wed, 20 Nov 2013 02:22:27 +0000</pubDate>
         <content:encoded><![CDATA[<p>WonderProxy will be announcing availability of a new server in Uganda any day now. We&#8217;re very excited. When we first launched WonderProxy the concept of having a server anywhere in Africa seemed far-fetched. Uganda is shaping up to be our fifth.</p>

<p>Our provider asked us to pay them by wire transfer, so I dutifully walked to the bank, stood in line, then paid $40CAD in fees &#38; a horrible exchange (to USD) rate to send them money. Not a great day, so I grabbed a burrito on the way home. A few days later we were informed that some intermediary bank had skimmed $20USD off our wire transfer, so our payment was $20USD short. Swell.</p>

<p>In order to send them $20USD, I&#8217;d need to go back to the bank, stand in line, hope I got a teller who knew how to do wire transfers (the first guy didn&#8217;t), buy $20USD for the provider, $20USD for the intermediate bank, and pay $40CAD for the privilege. $80 to send them $20. Super.</p>

<p>Luckily XE came in to <a rel="nofollow" target="_blank" href="http://blog.preinheimer.com/index.php?/archives/418-Paying-across-borders.html">save the day again</a>. Using their convenient online interface I was able to transfer $40USD for only $63CAD, including my wire fee. I paid a much better exchange rate, lower wire fees, and didn&#8217;t have to put pants on. The only downside was a lack of burrito. Bummer.</p>

<p>If you&#8217;re dealing with multiple currencies and multiple countries, and these days it&#8217;s incredibly likely that you are, I&#8217;d highly recommend <a rel="nofollow" target="_blank" href="http://www.xe.com/xetrade/">XE</a>. </p>]]></content:encoded>
         <category>Op-Ed</category>
      </item>
      <item>
         <title>Using GeoIP at WonderProxy</title>
         <link>http://blog.preinheimer.com/index.php?/archives/421-Using-GeoIP-at-WonderProxy.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/421-guid.html</guid>
         <pubDate>Wed, 06 Nov 2013 19:04:36 +0000</pubDate>
         <content:encoded><![CDATA[<p>At WonderProxy we&#8217;ve been helping people test their GeoIP sensitive applications since launch. It&#8217;s why we launched. Perhaps ironically it&#8217;s never been a technology we&#8217;ve used on our own website. With our upcoming <a rel="nofollow" target="_blank" href="https://admin.wonderproxy.com/">re-design</a> that&#8217;s changing. </p>


<h2>Using GeoIP:</h2>

<ol>
<li>How to use it</li>
<p>Deciding how you&#8217;ll use GeoIP information will affect how much you end up spending for a GeoIP database, how often you&#8217;ll renew, and what safeguards you&#8217;ll need to put in place. Country level granularity is relatively easy to come by, city level within the US and Canada however tends to be much more expensive. </p>


Our integration goal is to support a nice slogan, for us that&#8217;s &#8220;<a rel="nofollow" target="_blank" href="https://admin.wonderproxy.com/">You&#8217;re in .., Your customers aren&#8217;t. WonderProxy: Test Globally</a>&#8221;. We opted for Region level as opposed to City, or Country level. We felt like &#8220;Ontario&#8221; or &#8220;Texas&#8221; was more impressive than &#8220;Canada&#8221; and &#8220;United States&#8221;, but were also wary of the lower accuracy level with city rate (Telling someone they&#8217;re in Brooklyn, when they&#8217;re really in Manhatten wouldn&#8217;t inspire confidence). 


<li>Acquire a database</li>
<p>There&#8217;s several options available. This step was easy, we bought ours from <a rel="nofollow" target="_blank" href="http://maxmind.com/">MaxMind</a>. We feel relatively familiar with the GeoIP data provider marketplace, and MaxMind has seemed both quite accurate and responsive to updates throughout WonderProxy&#8217;s existence. <a rel="nofollow">IP2Location</a> is another provider with downloads available. </p>


<p>MaxMind also provides API access to its data. We&#8217;ve been leveraging this for a long time in our monitoring systems (we check all our servers to ensure they&#8217;re geo-locating correctly), but they&#8217;re all batched processes. Waiting for a remote API to return during page load, in particular for a landing page is folly. IP2Location also offers an API, as does <a rel="nofollow" target="_blank" href="http://www.infosniper.net/">InfoSniper</a>. APIs work really well in batched process, or anything somehow detached from page loads. </p>


<li>Rebuild Apache &#38; PHP</li>
<p>Our initial build only required the <a rel="nofollow" target="_blank" href="http://dev.maxmind.com/geoip/legacy/mod_geoip2/">Apache module</a>, this way additional superglobals were provided in PHP. I can grab &lt;?=$_SERVER['GEOIP_REGION_NAME']; ?&gt; get someone&#8217;s location, it&#8217;s really easy. We later installed the <a rel="nofollow" target="_blank" href="http://pecl.php.net/package/geoip">PHP module</a> (using the same database) to support arbitrary IP lookup within our administration systems. We also encoded the <a rel="nofollow" target="_blank" href="http://dev.maxmind.com/geoip/codes/iso3166">MaxMind ISO 3166 data</a> into our application to convert country codes to names.</p>

<p>If you&#8217;re taking the API approach life should be easy, there&#8217;s plenty of code examples for every major API provider. If you&#8217;re using an API you also have the ability to choose different levels of granularity on the fly, full data some of the time, minimal data most of the time to save on credits. </p>

<li>Handle edge cases</li>
<p>Not every IP will have a result, it&#8217;s important to catch these and handle correctly. We&#8217;ve simply decided to test the variable and replace with &#8220;Your Office&#8221; when the lookup fails. </p>

<p>On the API front It&#8217;s worth spending a few minutes to make a request fail on purpose and ensure your code handles it well. I&#8217;ve had a few important daily reports fail because the API we were using was unavailable, frankly it&#8217;s embarrassing. </p>
</ol>
<p>We've been really happy with how easy the integration has been. I've already added several new integration points throughout our administrative system (providing lookups on banned users, the IP associated with transactions, etc.). For us the integration is really supporting the slogan and looking nice, but there's plenty of practical uses like estimating shipping charges, localizing prices, and adjusting content.</p>]]></content:encoded>
         <category>PHP</category>
      </item>
      <item>
         <title>Ticket Derby</title>
         <link>http://blog.preinheimer.com/index.php?/archives/420-Ticket-Derby.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/420-guid.html</guid>
         <pubDate>Sun, 03 Nov 2013 20:17:14 +0000</pubDate>
         <content:encoded><![CDATA[I&#8217;ve been having a one-man ticket derby this weekend, the goal of a Ticket Derby (as I&#8217;m defining it) is to close as many tickets as possible. I&#8217;ve closed 15 so far, aiming for quantity of tickets, not quality of tickets. I&#8217;ve resolved sorting issues, one line fixes to change the From address on some email notifications; changed the name servers on old domains, etc. Lots of easy stuff. But it&#8217;s closed and out of the way!<br />
<br />
I decided to do this because I was finding our ticket system a bit overwhelming: pages of tickets all awaiting my attention. I had over 60 assigned tickets a week ago. Now I&#8217;m down to 39. As a small shop, and without a project manager (dedicated or otherwise), I was doing my best to prioritize tickets based on criteria like: customer impact, revenue generation, time saved, etc. Tickets that fared well in those categories tended to be large affairs, requiring a decent amount of effort. This left me with an intimidating, seemingly endless wall-of-work. Adding Date Opened to the view just made it depressing. The derby seemed like a great way to clear out the work and make the wall less intimidating. <br />
<br />
I&#8217;m finding my open &#38; assigned ticket screen manageable now. If your team has been working on big issues for a while, why not give them a few days to plow through some easy stuff? I awarded prizes for my derby, giving out chocolate in a few categories: oldest ticket closed, most tickets closed, most humorous commit message.<br />
<br />
Now, if you&#8217;ll excuse me, I&#8217;ve got a bellyache.]]></content:encoded>
      </item>
      <item>
         <title>Administrative Systems</title>
         <link>http://blog.preinheimer.com/index.php?/archives/419-Administrative-Systems.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/419-guid.html</guid>
         <pubDate>Sat, 02 Nov 2013 19:10:26 +0000</pubDate>
         <content:encoded><![CDATA[<p>For a long time at WonderProxy we neglected internal systems, instead directing our efforts to things used by our customers. We&#8217;ve built <a rel="nofollow" target="_blank" href="http://wheresitup.com/">new products</a>, launched redesigns, then a <a rel="nofollow" target="_blank" href="https://wondernetwork.com/loadtesting">few more</a> <a rel="nofollow" target="_blank" href="http://wheresitfast.com">products</a>, all the while maintaining user accounts by directly interacting with the database (including a few update queries lacking a WHERE clause).</p>

<p style="color:#FFCC6F;font-size:20px;display:block;text-align:center;padding-top:10px;padding-bottom:10px;">This was a huge mistake</p>

<p>As I worked on the redesign for WonderProxy (<a rel="nofollow" target="_blank" href="https://wonderproxy.com/">Original</a> vs <a rel="nofollow" target="_blank" href="https://admin.wonderproxy.com/">Redesign</a>) I added a few basic admin features almost by accident, and all our lives got remarkably easier. I added a few more, and things got easier still. Tasks that used to be a chore (like setting up a free trial) almost became fun. Researching account history is just a few easy clicks, with nice graphs using nvd3, and pretty data tables. Editing accounts in place, with code that understands <span class="code-inline">30GB = 32212254720 bytes</span>.</p>

<p style="margin-left:10px;color:#7C8699;">Saying things &#8220;creating trial accounts is fun&#8221; may sound like gross exaggeration, but it&#8217;s not. I&#8217;m pretty happy with the code i&#8217;ve got there, which may add to it. The form supports pasting in an address like <span class="code-inline">Paul Reinheimer &lt;paul@preinheimer,com&gt;</span>, parsing it out to its component parts, and generating an available username. Then in for expiry, I leverage php&#8217;s <span class="code-inline">strtotime()</span> function so I can enter in something simple like &#8220;+2 weeks&#8221; or &#8220;next thursday&#8221; and have that parsed and work properly.</p>

<p>The speed at which we&#8217;re both willing and able to resolve requests has greatly increased. Trial accounts (which convert with great regularity) are easy to do in a minute, rather than 10, so we&#8217;re more likely to do them when they roll in, rather than waiting until we&#8217;re on the server for another reason. When it comes to customizing accounts, getting an accurate history, and being able to quickly modify accounts has helped everyone. I&#8217;m lacking a basis for comparison, but our revenue has also been climbing nicely since the change, having a dashboard to find clients exceeding their plan limits has certainly helped.</p>

<p>If you&#8217;re looking at the next big thing to improve for your team, I&#8217;d strongly suggest taking a harder look at your internal tools. </p>]]></content:encoded>
      </item>
      <item>
         <title>Paying across borders</title>
         <link>http://blog.preinheimer.com/index.php?/archives/418-Paying-across-borders.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/418-guid.html</guid>
         <pubDate>Fri, 01 Nov 2013 15:56:27 +0000</pubDate>
         <content:encoded><![CDATA[<p>Since we launched <a rel="nofollow" target="_blank" href="https://wonderproxy.com">WonderProxy</a> we’ve had lots of bills to pay, often to ourselves or contractors. WonderProxy is a Canadian company, with a Canadian bank account, when we need to pay someone in the US we’ve had a few options: cheque, wire transfer, PayPal.</p>

<ul>
<li><b>Cheque</b></li>
<p>These are easy, we open a filing cabinet, pull out a cheque, sign it and put it in the mail. Then the contractor waits for a week or so for the cheque to arrive, deposits in the bank, receives a horrible exchange rate, and waits two or more weeks for it to clear.</p>

<li><b>Wire Transfer</b></li>
This requires me to go to the branch in person, wait in a line, pay a lot in fees, then the money shows up in a day or three, possibly with additional fees being deducted along the way. 

<li><b>PayPal</b></li>
These are easy, open up our PayPal account, make a transfer, log out out again. The recipient ends up paying like 3.5% in fees, receives a mediocre at best exchange rate, then waits longer for the money to appear in their account.
</ul>
<p>So, everything sucks, bad rates, fees, and possibly involving me going to a bank in person.</p>

<p>
Eventually we got frustrated with the money we were effectively losing with crappy exchange rates, and took a look further. We came across XE's <a rel="nofollow" target="_blank" href="http://www.xe.com/xetrade/?WT.mc_id=XTR-TL-XHOM-XIN-XX-V01-131001">currency trading services</a>. It took a fair amount of effort to sign up (various forms to be scanned and sent in), but it’s been fantastic. I log on to execute a trade, enter that I would like to buy USD with $1000CAD, and get a spot rate on the transfer. I choose to execute the trade, with the USD funds being deposited in the recipients US account. I pay XE through my bank’s online bill payment services, then about a week later the US funds arrive in the recipient’s account. </p>

<p>I get to do it all from my desk, we get a fantastic exchange rate, and the transfer service makes its money on the spread, so there’s no extra fees. </p>

<p>If you’re paying across borders, I would heartily recommend investigating <a rel="nofollow" target="_blank" href="http://www.xe.com/xetrade/?WT.mc_id=XTR-TL-XHOM-XIN-XX-V01-131001">XE</a> to see if they can meet your needs. </p>]]></content:encoded>
      </item>
      <item>
         <title>Women in Open Source</title>
         <link>http://feedproxy.google.com/~r/JamesOnSoftware/~3/2x24uJJp7Ik/women-in-open-source.html</link>
         <description>&lt;p&gt;&lt;em&gt;tl;dr&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Doing open source work is a path to success in the software industry.&lt;/li&gt;
&lt;li&gt;Women are underrepresented in open source, and therefore largely not currently capitalizing on this substantial opportunity.&lt;/li&gt;
&lt;li&gt;The open source world is daunting for everyone, and it's especially bad for women.&lt;/li&gt;
&lt;li&gt;I am offering my time to mentor a woman who is interested in getting involved in open source &amp;mdash; particularly deeply technical and/or low level work. Also, &lt;a rel=&quot;nofollow&quot; href=&quot;#informal&quot;&gt;this&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The last paragraph explains how to get in touch if you're interested.&lt;/li&gt;
&lt;/ul&gt;


&lt;hr/&gt;


&lt;p&gt;The work that I've done in open source has led to nearly every major leap I've made since I started working as a programmer. It's how I got my last job (an executive position), how I get speaking gigs, and how I met nearly every one of my current set of friends and mentors.&lt;/p&gt;

&lt;p&gt;That last point is important: research shows a link between something called &quot;social capital&quot; and career advancement. Your circle of friends &amp;mdash; a representation of your social capital &amp;mdash; acts as a source of information, resources, and credibility &lt;sup&gt;[&lt;a rel=&quot;nofollow&quot; href=&quot;#foot1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;. In other words, your friends teach you stuff, help you out, and if they're successful and prominent, they make you look good (twitter retweets might make this an especially big deal in our world).&lt;/p&gt;

&lt;p&gt;I've experienced this first hand. In my last job, I was &amp;mdash; quite frankly &amp;mdash; failing miserably until I met a couple of guys who helped me understand how to think about what I was doing in the right way. With their help, I turned things around so well that I get invited to speak all over the world about my successes in that area. I met those guys as a result of open source work. Quite a snowball.&lt;/p&gt;

&lt;p&gt;I have personal examples for days, but thankfully, you don't need to take my word for it. The bibliography for &lt;sup&gt;[&lt;a rel=&quot;nofollow&quot; href=&quot;#foot1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt; is literally a list of research on this topic.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;Women are terribly underrepresented in open source &lt;sup&gt;[&lt;a rel=&quot;nofollow&quot; href=&quot;#foot2&quot;&gt;2&lt;/a&gt;]&lt;/sup&gt;. Since open source is an effective way to accumulate social capital in the software world, womens' underrepresentation is an enormous missed opportunity for career advancement, success, and &amp;mdash; frankly &amp;mdash; making money.&lt;/p&gt;

&lt;p&gt;I get it, though: the open source world is inhospitable to basically everyone, and it's a lot worse for women. Whether we consciously intend it to be or not, open source is a boys club. Although I have observed the men I hang around with be very welcoming and inclusive towards women who are interested in joining our circle, being passively inclusive isn't enough. We need to actively recruit and mentor women until we reach critical mass &lt;sup&gt;[&lt;a rel=&quot;nofollow&quot; href=&quot;#foot3&quot;&gt;3&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;That's why I've decided to offer my time as a mentor to a woman who is interested in getting involved in open source &amp;mdash; particularly in something deeply technical and/or low level, since that's my area of interest and one where women are particularly poorly represented. Specifically, I'm talking about working on things like databases (distributed or otherwise), memory allocators, virtual machines, operations tooling, etc. The kinds of things I &lt;a rel=&quot;nofollow&quot;&gt;write&lt;/a&gt; about on this blog.&lt;/p&gt;

&lt;p&gt;I'm willing to offer half a day a week of my time for whatever I can do to help, whether it's teaching, pair programming, debugging, connecting with smart people I know, or any and every combination of those things and whatever else. I'm new at this, so we'll have to figure it out as we go.&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; name=&quot;informal&quot;&gt;&lt;/a&gt;
If you don't have time for &amp;mdash; or interest in &amp;mdash; open source work, but feel that you might benefit from more informal regular chats (IMs, IRC, whatever) about whatever it is that you're working on, I'd love to help in any way I can, so definitely still get in touch. This is the type of relationship that I have with many of my mentors and it's tremendously useful.&lt;/p&gt;

&lt;p&gt;Drop me an &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;mailto:jamesgolick@gmail.com&quot;&gt;email&lt;/a&gt; with a bit of background about who you are and the type of thing you might be interested in working on. &lt;strong&gt;You don't already have to be working on low level or deeply technical stuff.&lt;/strong&gt; A few years ago, I wasn't either. All you need to be successful is interest and motivation.&lt;/p&gt;

&lt;ol style=&quot;font-size:12px;&quot;&gt;
  &lt;li&gt;&lt;a rel=&quot;nofollow&quot; name=&quot;foot1&quot;&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.aom.pace.edu/amj/April2001/seibert.pdf&quot;&gt;A Social Capital Theory of Career Success, Scott E. Seibert, Maria L. Kraimer and Robert C. Liden&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a rel=&quot;nofollow&quot; name=&quot;foot2&quot;&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.flosspols.org/deliverables/FLOSSPOLS-D16-Gender_Integrated_Report_of_Findings.pdf&quot;&gt;Gender: Integrated Report of Findings, Dawn Nafus, James Leach, Bernhard Krieger&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a rel=&quot;nofollow&quot; name=&quot;foot3&quot;&gt;&lt;/a&gt;Incidentally, the research shows that mentoring is a key contributor to career advancement, higher salaries, and more job satisfaction. It also shows that women typically have less access to mentoring, arguably a key facet of the glass ceiling.
    &lt;ol&gt;
      &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://onlinelibrary.wiley.com/doi/10.1111/j.1468-0432.2010.00521.x/pdf&quot;&gt;Impressing for Success: A Gendered Analysis of a Key Social Capital Accumulation Strategy, Savita Kumra, Susan Vinnicombe&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;img src=&quot;http://feeds.feedburner.com/~r/JamesOnSoftware/~4/2x24uJJp7Ik&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">tag:jamesgolick.com,2013-10-16:1381935656</guid>
         <pubDate>Wed, 16 Oct 2013 15:00:56 +0000</pubDate>
      </item>
      <item>
         <title>“Scary” Stuffed Monkey</title>
         <link>http://basbrun.com/2013/10/09/scary-stuffed-monkey/</link>
         <description>Last month we went to the zoo with the kids. We played fair games and won a few cheap stuffed animals. They were so crappy we decided we would try to make something fun out of it. Around the same time, at my son’s summer camp, the instructor was telling them scary stories. That gave [&amp;#8230;]</description>
         <guid isPermaLink="false">http://basbrun.com/?p=1209</guid>
         <pubDate>Thu, 10 Oct 2013 00:56:10 +0000</pubDate>
         <content:encoded><![CDATA[<p><span style="font-size:13px;">Last month we went to the zoo with the kids. We played fair games and won a few cheap stuffed animals. They were so crappy we decided we would try to make something fun out of it.</span></p>
<p>Around the same time, at my son’s summer camp, the instructor was telling them scary stories. That gave him the idea to convert the stuffed monkey into a scary monkey with red bright eyes and playing a spooky melody! This post details the building process. I hope you’ll enjoy!</p>
<div id="attachment_1216" style="width:522px;" class="wp-caption alignnone"><a rel="nofollow" title="" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/09/monkey01.jpg"><img class="size-full wp-image-1216" style="border:1px solid black;" title="" alt="" src="http://basbrun.com/wp-content/uploads/2013/09/monkey01.jpg" width="512" height="409"/></a><p class="wp-caption-text">“Scary” Stuffed Monkey Project</p></div>
<h2>The plan</h2>
<p>A small pressure button will be placed in one hand of the monkey. When pressed, the  monkey’s eyes, two red LEDs, will turn on and a spooky melody will be played.</p>
<p>Since we had more IOs at our disposal, we decided to add a light sensitive resistor at the top of the head that would control a green 3mm LED in the nose. When the light is turned off or when you place your hand on the head, the LED starts blinking.</p>
<p>Finally, I decided it would be nice not to have any power button. Kids always forget to turn these off anyways. This implies some sort of sleep mode for the toy to save power.</p>
<h2>The Micro-Controller (08M2)</h2>
<p>The project circuit is built around a PICAXE 08M2 micro-controller. This micro-controller has four inputs and outputs. Several reasons have led to the choice of this micro-controller:</p>
<ol>
<li><strong>Size</strong> The PICAXE 08M2 is one of the smallest through hole micro-controller on the market. An Arduino microcontroller board would have been too large for the project.</li>
<li><strong>Power</strong> I wanted the circuit to be powered by three 1.5V button cells and run for days beforereplacing the batteries. This micro-controller consumes very little power and offers a sleep mode that almost totally shuts down the chip. Using this great feature I managed to build a circuit that can run for weeks on three LR44 batteries.</li>
<li><strong>Simplicity</strong> This microcontroller is very robust and simple to integrate into a circuit without complex power regulation circuit and no external crystal is required to drive the chip clock.</li>
<li><strong>Price</strong> Price is always a concern when you build something. The PICAXE 08M2 chip cost around 3.00$ CN. Compared to the 25$ Arduino board this is a bargain!</li>
</ol>
<div id="attachment_1218" style="width:522px;" class="wp-caption alignnone"><a rel="nofollow" title="PICAXE 08M2 micro-controller" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/09/08M2.jpg"><img class=" wp-image-1218" style="border:1px solid black;" title="PICAXE 08M2 micro-controller" alt="PICAXE 08M2 micro-controller" src="http://basbrun.com/wp-content/uploads/2013/09/08M2.jpg" width="512" height="111"/></a><p class="wp-caption-text">PICAXE 08M2 micro-controller</p></div>
<h2>Inputs / Outputs</h2>
<p>The circuit must drive three different components. Two red LEDs for the eyes, one green LED for the nose and one piezo for the scary melody are controlled by a pressure button and a photo-resistor.</p>
<div id="attachment_1224" style="width:522px;" class="wp-caption alignnone"><a rel="nofollow" title="Scary Monkey components" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/09/io.jpg"><img class=" wp-image-1224" style="border:1px solid black;" title="Scary Monkey components" alt="Scary Monkey components" src="http://basbrun.com/wp-content/uploads/2013/09/io.jpg" width="512" height="237"/></a><p class="wp-caption-text">Scary Monkey components</p></div>
<p>The two red LEDs are connected in parallel to the same digital output pin of the micro-controller. Each LED is connected to a 220 Oms resistor to reduce the current driven through the LED.</p>
<p>The green LED is connected to an other digital output of the micro-controller. As for the red LEDs, a 220 Oms resistor limits the current passing through the LED.</p>
<p>The piezo needs an output that supports PWM (Pulse With Modulation) to play the different tones of the melody. The PICAXE API offers the function tune() to play music on pin #2 of the 08M2 micro-controller.  The PICAXE IDE offers a simple wizard to  help you program the melody.</p>
<p><span style="font-size:13px;">Two different inputs are used to interact with the stuffed animal. A pressure button in one hand of the monkey triggers the melody and lights up the eyes. The LED in the nose of the stuffed animal is controlled by a photo-resistor located in the head. When the lights are turned off or when you place your hand over the photo-resistor, the nose of the monkey blinks green.</span></p>
<p>Since I am using standard electronic components I had to find a way to stitch it to the stuffed animal. I used small pieces of perforated prototyping board and stitched through the holes around the components. Next time I’ll use the <a rel="nofollow" title="Adafruit Flora" target="_blank" href="http://www.adafruit.com/category/92">Adafruit Wearable Electronics!</a></p>
<h2>The Circuit</h2>
<p>The circuit for this project is very simple. Because we are not using motors and because the PICAXE micro-controller is pretty resistant to small power fluctuations, I decided to power the circuit directly from a 4.5V stack of button cell batteries. No need for power supply or power regulation.</p>
<div id="attachment_1236" style="width:522px;" class="wp-caption alignnone"><a rel="nofollow" title="Scary Monkey Circuit" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/09/julie3.jpg"><img class=" wp-image-1236" style="border:1px solid black;" title="Scary Monkey Circuit" alt="Scary Monkey Circuit" src="http://basbrun.com/wp-content/uploads/2013/09/julie3.jpg" width="512" height="420"/></a><p class="wp-caption-text">Scary Monkey Circuit</p></div>
<p>At the exception of <strong>pin #2</strong> (Serial In) , all the micro-controller pins are used. As recommended by the manufacturer, I connected pin #2 to the ground through a 10KH resistor.</p>
<p><strong>Pin #3</strong> is used as a digital output to control the eyes of the monkey. Both red LEDs are connected in parallel to the micro-controller pin through a 220H resistor to limit the current flowing in.</p>
<p>The micro-controller <strong>pin #4</strong> is home for the push button. This is the button that will be fitted in the hand of the stuffed monkey. A 10 KOms pull-down resistor is keeping the input pin to zero when the button is not pressed. When pressed, the button connects the 4.5V trace to pin #4.</p>
<p>The piezo is attached to the PWM output on pin#5 of the micro-controller.<strong> Pin #5</strong> is mapped to input #2 of the PICAXE 08M2, the only output supporting pulse with modulation (PWM) required to play music tones.</p>
<p>To detect the level of light we hooked a photo-resistor to <strong>pin #6</strong> of the 08M2. In conjunction with a 10 KOms resistor, the photo-resistor acts as a voltage divider connected to pin #6 of the PICAXE.</p>
<p>Finally, the green LED located in the nose is connected to output<strong> pin #7</strong> of the micro-controller. As for the eyes LEDs, a 220 Oms resistor is connected in series to LED to limit current.</p>
<p>To power the micro-controller, connect the positive wire of your battery pack to <strong>pin #1</strong> of the chip. The negative pole of the batteries goes to<strong> pin #8</strong> of the PICAXE 08M2.</p>
<h2> The Printed Circuit Board (PCB)</h2>
<p>As mentioned earlier, size was critical in this project. I didn’t want to end-up with a bulky circuit squeezed into the stuffed animal. To minimize the size I decided to make my own PCB.</p>
<div id="attachment_1227" style="width:522px;" class="wp-caption alignnone"><a rel="nofollow" title="Custom PCB" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/09/pcb.jpg"><img class=" wp-image-1227" style="border:1px solid black;" title="Custom PCB" alt="Custom PCB" src="http://basbrun.com/wp-content/uploads/2013/09/pcb.jpg" width="512" height="338"/></a><p class="wp-caption-text">Custom PCB</p></div>
<p>Building a PCB requires a lot of preparation and many steps to complete with success. I used the open source application Fritzing to design the PCB. You will find the schematics on my Githug account at: <a rel="nofollow" target="_blank" href="https://github.com/pchretien/julie">https://github.com/pchretien/julie</a>.</p>
<p>The first step is to print the circuit onto the copper board. There are many tools and products out there to do that but I used the simplest and cheapest way: toner transfer. Toner transfer consists of printing the circuit on a glossy paper using a laser printer and then using an iron to transfer the circuit onto the copper board. This is made possible because the glossy paper will not absorb the toner. When heated with the iron, the toner can be “transferred” to an other surface.  Here are a few things to remember when doing toner transfer:</p>
<ol>
<li>Use a glossy and thick paper. I used an empty Avery sticker sheet to build this circuit.</li>
<li>Clean the copper surface before to applying the toner. I used soap and acetone. Do not touch the surface with your fingers.</li>
<li>Stick the piece of paper onto the copper board so they remain aligned. Make sure the toner side touches the copper board.</li>
<li>Use an iron at max temperature and apply pressure on the entire surface of the circuit. This will take several minutes to complete.</li>
</ol>
<p>After a while, the toner will be transferred to the copper surface. The result will vary from one time to the other. Complete the traces with a Sharpee marker where the toner has not been transferred properly.</p>
<p>The next step is to remove the copper layer where there is no toner or Sharpee. I used ferric chloride to do this. Place your circuit board into a plastic container and cover it with ferric chloride. Gently move the container from one side to the other for a couple of minutes. It may take 10 to 15 minutes for the copper to completely dissolve.</p>
<p>You’re almost done. All that’s left to do is to clean the circuit to remove the toner and drill holes. I used acetone to clean the circuit for this project but I would not recommend it. It spreads the toner all over the circuit surface and makes it look dirty. I would recommend using a brush and soap. It takes longer but the final result is nicer. To drill the holes I used a 1/32″ drill bit. You may have to use a larger bit for some components like a power connector or a USB connector.</p>
<h2>Assembly</h2>
<p>It’s now time to assemble the circuit and to fit it into the monkey. You must remove the existing stitches using a utility knife or a proper <a rel="nofollow" title="Seam Ripper" target="_blank" href="http://en.wikipedia.org/wiki/Seam_ripper">seam ripper</a>. Start with the back where you will insert the circuit board and wires. You will also need to rip the hand stitches to insert the button. You should be able to insert the eyes and nose LEDs and the photo resistor from the back. If not, remove more stitches.</p>
<p>This part of the project is where you can involve younger kids. Stitching is pretty easy and you don’t really care about the look of the final result. Placing the components in place is something any kids can do and it really gives them the impression that they actually build the whole thing by themselves.</p>
<div id="attachment_1233" style="width:522px;" class="wp-caption alignnone"><a rel="nofollow" title="Assembly Of The Scary Monkey" target="_blank" href="http://basbrun.com/wp-content/uploads/2013/09/assembly2.jpg"><img class=" wp-image-1233" style="border:1px solid black;" title="Assembly Of The Scary Monkey" alt="Assembly Of The Scary Monkey" src="http://basbrun.com/wp-content/uploads/2013/09/assembly2.jpg" width="512" height="373"/></a><p class="wp-caption-text">Assembly Of The Scary Monkey</p></div>
<h2>The Code</h2>
<p>The PICAXE micro-controller comes with a free to download programming IDE . You connect your computer to a development board using a special cable connected at one end to the development board and at the other end to a USB port of your computer.</p>
<p>The language used is good old Basic. As a software developer I must admit I would have preferred a C compiler as with the Arduino but, hey, to light up a few LEDs and play music, Basic will do the job just fine.</p>
<p>You can download the code from my Github account at: <a rel="nofollow" target="_blank" href="https://github.com/pchretien/julie">https://github.com/pchretien/julie</a></p>
<h2>It’s open and free</h2>
<p>This project is published under the GPL2 license. You can use, make and duplicate this project as you which …</p>]]></content:encoded>
      </item>
      <item>
         <title>See James. See James rocking it.</title>
         <link>http://thecarefulprogrammer.blogspot.com/2013/09/see-james-see-james-rocking-it.html</link>
         <description>&lt;p dir=&quot;ltr&quot;&gt;Don't miss James Ladd presenting the innards of Redline Smalltalk on the JVM at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://oracleus.activeevents.com/2013/connect/search.ww?eventRef=javaone#loadSearch-event=null&amp;searchPhrase=Smalltalk&amp;searchType=session&amp;tc=0&amp;sortBy=&amp;p=&amp;i(11180)=20801&quot;&gt;JavaOne&lt;/a&gt; in a few days!&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/redline_st/status/371401360136101888&quot;&gt;Tweet&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/redline_st/status/371401360136101888&quot;&gt; &lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/redline_st/status/371401360136101888&quot;&gt;announcement&lt;/a&gt;&lt;/p&gt;</description>
         <author>noreply@blogger.com (The Careful Programmer)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8932258692847145228.post-7460520509329909423</guid>
         <pubDate>Fri, 20 Sep 2013 11:59:00 +0000</pubDate>
      </item>
      <item>
         <title>The Atmosphere Framework 2.0 released</title>
         <link>https://jfarcand.wordpress.com/2013/09/20/the-atmosphere-framework-2-0-released/</link>
         <description>The Async-IO dev team are pleased to announce the release of The Atmosphere Framework 2.0! You can download it here Besides all of the performance and cache memory improvements made between Atmosphere 1.0, version 2.0 comes with a host of improvements and new features. Probably the biggest improvement that our users will notice is much [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=jfarcand.wordpress.com&amp;#038;blog=11001265&amp;#038;post=1238&amp;#038;subd=jfarcand&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jfarcand.wordpress.com/?p=1238</guid>
         <pubDate>Fri, 20 Sep 2013 10:00:35 +0000</pubDate>
         <content:encoded><![CDATA[<p>The Async-IO dev team are pleased to announce the release of The Atmosphere Framework 2.0! You can download it <a rel="nofollow" target="_blank" href="http://async-io.org/download.html">here</a></p>
<p>Besides all of the performance and cache memory improvements made between Atmosphere 1.0, version 2.0 comes with a host of improvements and new features. Probably the biggest improvement that our users will notice is much better memory usage under high load and improved WebSocket/fallbacks transport performance. This changes alone makes it worth upgrading!</p>
<p><a rel="nofollow" target="_blank" href="http://async-io.org/release.html">Read the announcement here</a>!</p><br />  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jfarcand.wordpress.com/1238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jfarcand.wordpress.com/1238/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=jfarcand.wordpress.com&#038;blog=11001265&#038;post=1238&#038;subd=jfarcand&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/9ae00d1d5f0b4479065431c13ca54013?s=96&amp;amp;d=identicon&amp;amp;r=G">
            <media:title type="html">jfarcand</media:title>
         </media:content>
         <category>Uncategorized</category>
      </item>
      <item>
         <title>Strength Training</title>
         <link>http://macournoyer.com/blog/2013/08/22/strength/</link>
         <description>&lt;p&gt;&lt;img src=&quot;http://www.vigile.net/IMG/arton56564.jpg&quot; style=&quot;float:right;&quot; title=&quot;Louis Cyr. Source: Source: http://www.vigile.net/Sur-Louis-Cyr&quot; alt=&quot;Louis Cyr. Source: Source: http://www.vigile.net/Sur-Louis-Cyr&quot;/&gt;&lt;/p&gt;&amp;#x000A;&lt;p&gt;So you&amp;#8217;re sitting at a computer all day packing on the pounds? Thinking about signing up to the gym to keep in shape? But hey! Most of us have been there. Sign-up for a few months and give up after a few weeks right? I&amp;#8217;ve been there many times. But for the last two years and a half I did manage to keep in good shape by going to the gym. So I would like to share with you what worked for me.&lt;/p&gt;&amp;#x000A;&lt;p&gt;First a quick recap (and bragging) of the progress I&amp;#8217;ve made. Three years ago I could barely run around the block without thinking I was going to die. Now I can run 5 km three times a week pushing a stroller with my two kids in it. I was also very weak. Here&amp;#8217;s the progress I&amp;#8217;ve made with my strength over the last three years.&lt;/p&gt;&amp;#x000A;&lt;p&gt;Bench press: 160 pounds to 275 pounds&lt;br /&gt;&amp;#x000A;Squat: 225 pounds to 360 pounds&lt;br /&gt;&amp;#x000A;Deadlift: 185 pounds to 405 pounds&lt;/p&gt;&amp;#x000A;&lt;h4&gt;Getting in shape&lt;/h4&gt;&amp;#x000A;&lt;p&gt;Training &amp;#8220;to get in shape&amp;#8221; never worked for me. You pump irons looking at yourself in the mirror and thinking you&amp;#8217;ll look like Arnie in just a few months. But that never works. For two simple reasons.&lt;/p&gt;&amp;#x000A;&lt;p&gt;No measurable goals and no lasting motivation. Looking better, being in better shape, that doesn&amp;#8217;t work. Losing weight is easily trackable. But&amp;#8230; &amp;#8220;losing&amp;#8221; is incredibly boring and depressing. How about &lt;strong&gt;gaining&lt;/strong&gt;!&lt;/p&gt;&amp;#x000A;&lt;p&gt;Gaining some strength! (And muscles too.)&lt;/p&gt;&amp;#x000A;&lt;p&gt;Strength training is the perfect type of training for &amp;#8220;office&amp;#8221; workers like most of us.&lt;/p&gt;&amp;#x000A;&lt;ul&gt;&amp;#x000A;	&lt;li&gt;It is intense without being mentally draining.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;You can be done in an hour or so.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;It&amp;#8217;s the best way to wake up and get you pumped for the day.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;It is easily trackable.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;You can set achievable goals.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;You&amp;#8217;ll progress very fast at the beginning, this likely stay motivated.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;The path to your goals is pretty straight forward.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;The first time you lift more than 300 pounds, you&amp;#8217;ll feel like a superhero. And that feeling keeps coming back each time you break a new personal record.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;Strength training pushes you to be consistent. If you miss a workout, you&amp;#8217;ll never break that record of yours this week!&lt;/li&gt;&amp;#x000A;&lt;/ul&gt;&amp;#x000A;&lt;h4&gt;Pick a simple program&lt;/h4&gt;&amp;#x000A;&lt;p&gt;The simpler the better. I recommend &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://startingstrength.wikia.com/wiki/FAQ:Introduction&quot;&gt;Starting Strength&lt;/a&gt;, also check out the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.com/Starting-Strength-3rd-Mark-Rippetoe/dp/0982522738&quot;&gt;book&lt;/a&gt;.&lt;/p&gt;&amp;#x000A;&lt;p&gt;The nice thing about a program like this one is that you&amp;#8217;ll actually know what you&amp;#8217;re doing! The worst thing to do in the gym is to improvise. Starting Strength will make you master the barbell and a few very important movements you use every day.&lt;/p&gt;&amp;#x000A;&lt;p&gt;But the most important point is, your progress needs to be easily trackable. With Starting Strength it&amp;#8217;s pretty simple, your goal is to add ~5 pounds each time you go to the gym.&lt;/p&gt;&amp;#x000A;&lt;p&gt;If strength is not your goal, there are many programs available. Check out this &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rohitnair.net/pp/&quot;&gt;program picker&lt;/a&gt;.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;Track your progress&lt;/h4&gt;&amp;#x000A;&lt;p&gt;I&amp;#8217;ve tried many iPhone apps to track my progress. The most fun is &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://fitocracy.com&quot;&gt;Fitocracy&lt;/a&gt;. There&amp;#8217;s a game aspect to it that helped me a lot at the beginning. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://www.fitocracy.com/profile/macournoyer&quot;&gt;Follow me here&lt;/a&gt; on Fitocracy.&lt;/p&gt;&amp;#x000A;&lt;p&gt;A lot of my progress at the beginning was made by improving my techniques. Mastering something new is also a very rewarding experience and I found learning about better ways the squat, bench press and deadlift to be fascinating.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;Set goals&lt;/h4&gt;&amp;#x000A;&lt;p&gt;I like to use this site to set my goals: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.strstd.com/&quot;&gt;Strength Standards&lt;/a&gt;.&lt;/p&gt;&amp;#x000A;&lt;p&gt;A simple goal could be to go from Novice to Intermediate level. Don&amp;#8217;t be too audacious and revise your goals if you&amp;#8217;re losing motivation. But make sure you&amp;#8217;re always progressing, ie. increasing weigths.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;Consistency and intensity&lt;/h4&gt;&amp;#x000A;&lt;p&gt;Those are the two keys to make progress. Make a schedule that is reasonable and that you can follow in the long term.&lt;/p&gt;&amp;#x000A;&lt;p&gt;And here&amp;#8217;s the most important part. When you go to the gym: make it INTENSE! If you&amp;#8217;re not progressing, you&amp;#8217;re either not eating, sleeping or trying hard enough. Forget what you though your body could do. It can lift way more than you think!&lt;/p&gt;&amp;#x000A;&lt;p&gt;I&amp;#8217;ve been through some incredible pain to make the progress that I have. But this increases the feeling of accomplishment you get afterwards. It also thought me a lot about pushing harder and more brave in other parts of my life.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;A few more tips&lt;/h4&gt;&amp;#x000A;&lt;p&gt;One big problem I had at the beginning was caused by breathing. I was thought that it&amp;#8217;s bad to hold your breath when pushing. It&amp;#8217;s actually important to hold your breath when lifting heaving to protect your internal organs. This is called the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Valsalva_maneuver&quot;&gt;Valsalva Maneuver&lt;/a&gt;. It&amp;#8217;s all explained in details in the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.com/Starting-Strength-3rd-Mark-Rippetoe/dp/0982522738&quot;&gt;Starting Strength book&lt;/a&gt;.&lt;/p&gt;&amp;#x000A;&lt;p&gt;Regarding supplements. After some research, I ended up with the following combination. Whey protein isolate, creatine, Omega 3 and Vitamin D everyday. And BCAA around trainings. Check out &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://examine.com/&quot;&gt;Examine.com&lt;/a&gt; to get the details about all those.&lt;/p&gt;&amp;#x000A;&lt;p&gt;One last thing that helped me a lot was to get a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.com/Valeo-6-Inch-Padded-Leather-Belt/dp/B0007KN6ZY&quot;&gt;training belt&lt;/a&gt;. I&amp;#8217;d recommend getting one once you reach intermediate level. It will help you stabilize your back and torso.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;Diet&lt;/h4&gt;&amp;#x000A;&lt;p&gt;I use to follow &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://macournoyer.com/blog/2011/12/06/if/&quot;&gt;a strict diet&lt;/a&gt;. I tried a few. Nowadays I don&amp;#8217;t, but I still do intermittent fasting. But one thing is for sure. If you want to increase you strength, the more you eat the better. The math is pretty simple, try to optimize to get the most protein per calories you consume.&lt;/p&gt;&amp;#x000A;&lt;p&gt;In summary, lifting heavy things is incredibly rewarding, a nice way to get in shape and a great excuse to stuff your face with copious amounts of meat. Seriously. What more could you want?&lt;/p&gt;&amp;#x000A;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://www.fitocracy.com/profile/macournoyer&quot;&gt;Join me on Fitocracy&lt;/a&gt; and lets lift together!&lt;/p&gt;</description>
         <guid isPermaLink="false">tag:macournoyer.com,2013-08-22:1377190151</guid>
         <pubDate>Thu, 22 Aug 2013 16:49:11 +0000</pubDate>
      </item>
      <item>
         <title>New blog</title>
         <link>https://technotales.wordpress.com/2013/08/21/new-blog/</link>
         <description>I decided to move on from WordPress and start a new blog. You can read about my reasons here. Follow me along and read my new post about Vim: How to Configure Syntastic.&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=technotales.wordpress.com&amp;#038;blog=761277&amp;#038;post=695&amp;#038;subd=technotales&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://technotales.wordpress.com/?p=695</guid>
         <pubDate>Wed, 21 Aug 2013 15:57:12 +0000</pubDate>
         <content:encoded><![CDATA[<p>I decided to move on from WordPress and start a <a rel="nofollow" title="new blog" target="_blank" href="http://blog.jpalardy.com/">new blog</a>. You can read about my reasons <a rel="nofollow" target="_blank" href="http://blog.jpalardy.com/posts/new-blog/">here</a>.</p>
<p>Follow me along and read my new post about Vim: <a rel="nofollow" title="how to configure syntastic" target="_blank" href="http://blog.jpalardy.com/posts/how-to-configure-syntastic/">How to Configure Syntastic</a>.</p><br />  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/technotales.wordpress.com/695/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/technotales.wordpress.com/695/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=technotales.wordpress.com&#038;blog=761277&#038;post=695&#038;subd=technotales&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://2.gravatar.com/avatar/ecfd1bdc5d3aab1e40f25658817712ba?s=96&amp;amp;d=identicon&amp;amp;r=G">
            <media:title type="html">jpalardy</media:title>
         </media:content>
         <category>development</category>
      </item>
      <item>
         <title>My $20 Tip</title>
         <link>http://blog.preinheimer.com/index.php?/archives/417-My-20-Tip.html</link>
         <author>nospam@example.com (Paul Reinheimer)</author>
         <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/417-guid.html</guid>
         <pubDate>Thu, 15 Aug 2013 01:12:49 +0000</pubDate>
         <content:encoded><![CDATA[When I finished high school I spent about 8 months working as a cable-internet installer before heading off to college. It paid well, and I was basically a glorified network card delivery boy. I&#8217;d drive to your house, install a network card in your computer (this was like 1999-2000), reboot it, and you&#8217;d be on the internet. Someone else was in charge of actually drilling holes and running the cable to your computer. Fun times. Well, unless you had NT4, then I needed to goof around with IRQ addresses for like half an hour and miss my lunch <img src="http://blog.preinheimer.com/templates/default/img/emoticons/smile.png" alt=":-)" style="display:inline;vertical-align:bottom;" class="emoticon"/>.<br />
<br />
I turned down tips when they came up, heck, I also turned down drinks. Though the occasional mother would rephrase her question as &#8220;water or juice&#8221; and force the pimply dehydrated teenager to drink something. I&#8217;d take the water.<br />
<br />
Our role was pretty clearly defined, we install the NIC, we give them a 5 minute &#8220;tutorial&#8221; on how to use the Internet, we leave. We don&#8217;t do anything else on their computer, and under no circumstances do we ever use the CD that came with the install package, it bricks computers.<br />
<br />
One day I did the install for an older gentleman from the middle east. After I connected him to the web he tried to load up a webpage, some news site from his home country. It wouldn&#8217;t render. He was missing the Microsoft font packs. Now our role was drilled into us pretty hard, if we did anything else and it went wrong there was liability on our company, and a serious amount of flak was about to come in our general direction. It could also create skewed expectations &#8220;Hey! The guy who did Sally&#8217;s internet installed a free virus scanner, and upgraded her Windows, why won&#8217;t you do that?&#8221;. Lots of problems.<br />
<br />
But I installed those font packs.<br />
<br />
Now, the gentleman didn&#8217;t speak a lot of English, so I had no idea how long he&#8217;d been in Canada, or how much news he&#8217;d been getting from home. But the emotion on his face when that page loaded&#8230; I understood what I&#8217;d really done. He handed me a crisp $20 bill, I tried to hand it back but I&#8217;d already lost him into that screen, there might have been a tear on his face I don&#8217;t remember, but it wouldn&#8217;t have been out of place.<br />
<br />
That was a great day, and the $20 had nothing to do with it.<br />]]></content:encoded>
         <category>Op-Ed</category>
      </item>
      <item>
         <title>Rebuilding Node's Event Loop</title>
         <link>http://macournoyer.com/blog/2013/06/25/event-loop/</link>
         <description>&lt;p&gt;&lt;em&gt;This post is based on a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://dailyjs.com/2012/09/27/truth-about-event-loops/&quot;&gt;guest post I wrote on DailyJS&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&amp;#x000A;&lt;h4&gt;The Heart of the Node Event Loop&lt;/h4&gt;&amp;#x000A;&lt;p&gt;I am a big believer in mastering your tools to become a better developer. And the best way to master your tools is to understand how they are made.&lt;/p&gt;&amp;#x000A;&lt;p&gt;Do you know what’s happening inside Node.js or EventMachine?&lt;/p&gt;&amp;#x000A;&lt;p&gt;There’s an event loop. So there must be a loop somewhere, right? A loop handling events. Let’s take a look…&lt;/p&gt;&amp;#x000A;&lt;h4&gt;The Loop&lt;/h4&gt;&amp;#x000A;&lt;p&gt;Event loops like the one in Node or EventMachine are designed to react to I/O events. This could be an incoming connection, data arriving on a socket, etc. What’s more, it must react to these events extremely quickly. Like most things in software, the simplest design is usually the fastest. And event loops are usually very simple.&lt;/p&gt;&amp;#x000A;&lt;p&gt;First, it consists of an endless loop:&lt;/p&gt;&amp;#x000A;&lt;div class=&quot;UltraViolet&quot;&gt;&amp;#x000A;&lt;pre class=&quot;twilight&quot;&gt;&amp;#x000A;&lt;span class=&quot;Keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;) {&amp;#x000A;  ...&amp;#x000A;}&amp;#x000A;&lt;/pre&gt;&amp;#x000A;&lt;/div&gt;&amp;#x000A;&lt;p&gt;Everything will happen in that loop. All of your Node programs will be running inside that loop. Which is similar to the loop you’ll find in virtual machines and emulators, where an actual processor is simulated instead.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;A Turn in the Loop&lt;/h4&gt;&amp;#x000A;&lt;p&gt;Somewhere in the loop, your process will wait for I/O events to happen. Luckily, most operating systems come with a function that allows us to do just that. Several options exist, such as kqueue on Mac OS, epoll on Linux. The most portable (but slowest) one is &lt;code&gt;select&lt;/code&gt;. For more on this, see &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kernel.org/doc/man-pages/online/pages/man2/select.2.html&quot; title=&quot;2&quot;&gt;select&lt;/a&gt;.&lt;/p&gt;&amp;#x000A;&lt;p&gt;&lt;code&gt;select&lt;/code&gt; watches a bunch of I/O objects (files, sockets) and lets you know when something happens. It looks something like this:&lt;/p&gt;&amp;#x000A;&lt;div class=&quot;UltraViolet&quot;&gt;&amp;#x000A;&lt;pre class=&quot;twilight&quot;&gt;&amp;#x000A;&lt;span class=&quot;Keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;) { &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;//&lt;/span&gt; That's our loop&lt;/span&gt;&amp;#x000A;  &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; events &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;SupportFunction&quot;&gt;select&lt;/span&gt;(&lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&lt;/span&gt;I/O objects to watch&lt;span class=&quot;Keyword&quot;&gt;&amp;gt;&lt;/span&gt;)&amp;#x000A;}&amp;#x000A;&lt;/pre&gt;&amp;#x000A;&lt;/div&gt;&amp;#x000A;&lt;h4&gt;React&lt;/h4&gt;&amp;#x000A;&lt;p&gt;At this point in the loop, we know an event has occurred. We must react to those events. In Node and many other event-based systems, this is done via callbacks.&lt;/p&gt;&amp;#x000A;&lt;p&gt;In your Node program, you’ll define callbacks like so:&lt;/p&gt;&amp;#x000A;&lt;div class=&quot;UltraViolet&quot;&gt;&amp;#x000A;&lt;pre class=&quot;twilight&quot;&gt;&amp;#x000A;object.on(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;read&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;() { ... })&amp;#x000A;&lt;/pre&gt;&amp;#x000A;&lt;/div&gt;&amp;#x000A;&lt;p&gt;This will register the callback inside the event loop, so that it knows what to do when this event happens. Introducing that in our loop, we’ll end up with the following:&lt;/p&gt;&amp;#x000A;&lt;div class=&quot;UltraViolet&quot;&gt;&amp;#x000A;&lt;pre class=&quot;twilight&quot;&gt;&amp;#x000A;&lt;span class=&quot;Keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;) {&amp;#x000A;  &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; events &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;SupportFunction&quot;&gt;select&lt;/span&gt;(&lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&lt;/span&gt;I/O objects to watch&lt;span class=&quot;Keyword&quot;&gt;&amp;gt;&lt;/span&gt;)&amp;#x000A;  &amp;#x000A;  events.forEach(&lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;Support&quot;&gt;event&lt;/span&gt;) {&amp;#x000A;    &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; callback &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; findCallbackForEvent(&lt;span class=&quot;Support&quot;&gt;event&lt;/span&gt;)&amp;#x000A;    callback() &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;//&lt;/span&gt; This calls the callback function&lt;/span&gt;&amp;#x000A;  });&amp;#x000A;}&amp;#x000A;&lt;/pre&gt;&amp;#x000A;&lt;/div&gt;&amp;#x000A;&lt;p&gt;After we’re done executing all of the callbacks, we’re ready for another turn in the loop – it’ll patiently wait for other I/O events to happen.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;But There’s More!&lt;/h4&gt;&amp;#x000A;&lt;p&gt;This is a simplification of how things work internally. However, even if the Node event loop is a little more complex than that, the structure is the same. It’s still a loop using &lt;code&gt;select&lt;/code&gt; (or a variation), and triggering callbacks.&lt;/p&gt;&amp;#x000A;&lt;p&gt;Still not sure how this allows huge amounts of concurrent connections to be handled by a server? Or you’d like to dive deeper into event loops and how it works in Node, and how other features such as &lt;code&gt;setTimeout&lt;/code&gt; are implemented? Join the next edition of my online class.&lt;/p&gt;&amp;#x000A;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://truthabouteventloops.com/&quot;&gt;&lt;img src=&quot;http://classes.codedinc.com/assets/pages/truthabouteventloops/preview.jpg&quot; alt=&quot;&quot;/&gt;&lt;/a&gt;&lt;/p&gt;&amp;#x000A;&lt;p&gt;Everything is online. You can ask questions. You’ll get exercises. And you’ll also get recordings of the class to watch again at your leisure.&lt;/p&gt;&amp;#x000A;&lt;p&gt;The class already helped a number of developers master Node and EventMachine. Here’s what one of them had to say:&lt;/p&gt;&amp;#x000A;&lt;blockquote&gt;&amp;#x000A;&lt;p&gt;I don&amp;#8217;t know where to begin. I am blown away. Other online &amp;#8220;classes&amp;#8221; that I have attended are very lackluster compared to your class.  &lt;br /&gt;&amp;#x000A;  The format was amazing, [&amp;#8230;], building on top of each lesson as we progressed.  &lt;br /&gt;&amp;#x000A;  [&amp;#8230;]  &lt;br /&gt;&amp;#x000A;  I am not sure it could have been done better. This is complicated stuff, and I feel you have gone well above expectations to help understand the event loop.  &lt;br /&gt;&amp;#x000A;  I can easily say that I have leveled up &amp;#8211; it has changed my thinking on event driven programs. Not just in Node but for Ruby as well.  &lt;br /&gt;&amp;#x000A;  &lt;em&gt;- Tom Buchok&lt;/em&gt;&lt;/p&gt;&amp;#x000A;&lt;/blockquote&gt;&amp;#x000A;&lt;p&gt;The previous edition was a great success and sold out quickly. I&amp;#8217;m expecting this one to sold out very soon too. So if you’re interested, &lt;strong&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://truthabouteventloops.com/&quot;&gt;book now&lt;/a&gt;&lt;/strong&gt;!&lt;/p&gt;</description>
         <guid isPermaLink="false">tag:macournoyer.com,2013-06-25:1372190981</guid>
         <pubDate>Tue, 25 Jun 2013 20:09:41 +0000</pubDate>
      </item>
      <item>
         <title>The Audio Diaries Ch. 2 – Using RubyAudio</title>
         <link>http://feedproxy.google.com/~r/connectnothing/~3/RiFLhT6ibUs/</link>
         <description>I&amp;#8217;m still working on embedding an interpreter into a VST 2.x plugin. I have most of the code, in place, but surprisingly, finding a simple VST host to test my plugin with is proving much harder; I&amp;#8217;m trying to stick to open source tools. Once loaded, the other challenge will be how to get Ruby [&amp;#8230;]</description>
         <guid isPermaLink="false">http://gnuu.org/?p=663</guid>
         <pubDate>Fri, 21 Jun 2013 03:55:22 +0000</pubDate>
         <content:encoded><![CDATA[<p>I&#8217;m still working on embedding an interpreter into a VST 2.x plugin. I have most of the code, in place, but surprisingly, finding a simple VST host to test my plugin with is proving much harder; I&#8217;m trying to stick to open source tools. Once loaded, the other challenge will be how to get Ruby code into the plugin, and then fixing up the processReplacing function such that whatever Ruby code is loaded can read and write float Array buffers.</p>
<p>Until then, I&#8217;ve decided to post some of my early audio tests with the ruby-audio gem. Installing it is pretty easy, but it relies on libsndfile which you will need to brew install (or other package manager). This worked for me:</p>
<pre><code>$ brew install libsndfile
$ gem install ruby-audio
</code></pre>
<p>Then it&#8217;s just a matter of using the API, which is not very heavily documented but not too hard to figure out. I managed to create a simple sine wave with the following code:</p>
<pre class="ruby"><code>require 'ruby-audio'
include RubyAudio

sample_rate = 48000
len = 10   # 10 seconds
freq = 440 # Play the C note
amp = 0.9  # Almost full volume

# The sample_rate dictates how many samples (or data points) make up
# ONE SECOND of audio. To get 10 seconds of data points we multiply
# our duration by the sample_rate.
buf = Buffer.float(sample_rate * len)
buf.size.times do |i| # for each data point
  sine_rad = ((freq * Math::PI * 2) / sample_rate) * i
  buf[i] = amp * Math.sin(sine_rad)
end

# Create the .wav file and write it with our buffer
format = FORMAT_WAV | FORMAT_PCM_16
info = SoundInfo.new(channels: 1, samplerate: sample_rate, format: format)
snd = Sound.new('out.wav', 'w', info)
snd.write(buf)
snd.close
</code></pre>
<p>After reading Robin Schmidt&#8217;s tutorial on <a rel="nofollow" target="_blank" href="http://rs-met.com/documents/tutorials/SinosoidsAndFrequencyDomain.pdf">Sinusoids and the Frequency Domain</a>, I was recalled back to my algebra days when we talked about sinusoidal periods, at which point I remembered that the sine function has a natural frequency of 2π (6.28&#8230;). That means if we want to generate a sine wave at 440Hz we first have to normalize the period to 1, and that is done by multiplying the frequency by 2π. Robin explains it better than me. Unfortunately, the part about sample rates was omitted from that document, and we need to take that into account too. Multiplying by 2π normalizes the function so that a period occurs from t=0..1, t=1..2, etc. (&quot;one second&quot;), but our one second is actually at sample_rate on the x axis, so we have to re-normalize for that by dividing. That&#8217;s what our sine_rad variable refers to.</p>
<p>Writing the wave file is fairly straightforward. You give it a sample rate, number of channels (our buffer only contains one channel, which means the file is mono, not stereo). The only somewhat confusing part is the format, which I took from the documentation.</p>
<p>For reference, here is how a square wave could be created:</p>
<pre class="ruby"><code>buf.size.times do |i|
  buf[i] = amp * (-1) ** (freq * i.to_f / sample_rate).floor
end</code></pre>
<p>Using (–1)<sup>x</sup> is a nifty little trick to oscillate from [-1,+1] as long as x is an integer (the value is a complex number if x is not an integer, and that&#8217;s complicated!).</p>
<p>The next post will hopefully have more progress on the VST plugin.</p><img src="http://feeds.feedburner.com/~r/connectnothing/~4/RiFLhT6ibUs" height="1" width="1" alt=""/>]]></content:encoded>
         <category>post</category>
      </item>
      <item>
         <title>The Audio Diaries Ch. 1 — May I Have Your Attenuation Please?</title>
         <link>http://feedproxy.google.com/~r/connectnothing/~3/COztEOZdUKQ/</link>
         <description>In an effort to resurrect my blog, I&amp;#8217;ve decided to journal my foray into digital audio processing. I&amp;#8217;ve been dabbling in electronic music for many, many, years now, but I don&amp;#8217;t feel like I ever had a true understanding of the fundamentals of digital audio. There are a lot of mathematical concepts that are core [&amp;#8230;]</description>
         <guid isPermaLink="false">http://gnuu.org/?p=660</guid>
         <pubDate>Tue, 18 Jun 2013 07:46:56 +0000</pubDate>
         <content:encoded><![CDATA[<p>In an effort to <a rel="nofollow" target="_blank" href="https://www.youtube.com/watch?v=Ctz39oFOUVo">resurrect</a> my blog, I&#8217;ve decided to journal my foray into digital audio processing. I&#8217;ve been dabbling in electronic music for many, many, years now, but I don&#8217;t feel like I ever had a true understanding of the fundamentals of digital audio. There are a lot of mathematical concepts that are core to how sound works (duh) that I&#8217;ve mostly glossed over for the sake of time. Instead, and like most people, I learned about <em>the effects</em> of these fundamentals (low-pass filter cuts out high frequencies, high-pass filter cuts out low frequencies). Given how much I&#8217;m interested in the art, I think it&#8217;s important that I spend time understanding exactly how this stuff works. There&#8217;s a lot to learn, so hopefully there will also be a lot to post.</p>
<p>So here we go. Down the rabbit hole.</p>
<h2>Resources</h2>
<p><strong><a rel="nofollow" target="_blank" href="http://rs-met.com/tutorials.html">Robin Schmidt&#8217;s Music Engineering Tools</a></strong> — The first important resource I came across happened years ago when I made attempt number one to learn about how digital audio worked. It was then that I came across probably the most important beginner&#8217;s resource to digital audio anybody could possibly find. I found this resource again a few days ago while researching the same basic principles and was instantly reminded why this site is so important: the articles provided here are well written with just enough math to understand the concepts but without going into crazy abstract mathematical details. In short, this is probably the closest to a set of &quot;explain to me like I&#8217;m 5&quot; articles without the impractical analogies&#8230; and maybe a little bit more math. I don&#8217;t think you will find any simpler explanations of these concepts anywhere else on the internet, though.</p>
<p><strong><a rel="nofollow" target="_blank" href="http://rubygems.org/gems/ruby-audio">The ruby-audio gem</a></strong> — It&#8217;s a little dated and extremely limiting, but the <code>ruby-audio</code> gem let&#8217;s you quickly create .wav files with a bunch of data fairly quickly. I&#8217;ve been using this to experiment with simple sine waves (I&#8217;ll show this in the next post) to get a practical understanding of the concepts I&#8217;m reading about.</p>
<h2></h2>
<h2>The First Goal: A VSTi Plugin</h2>
<p>One of the things I want to do is make it really easy to prototype sounds and filters I&#8217;m implementing, and Ruby is the obvious choice when it comes to quick prototyping. The ruby-audio gem works alright, but being forced to write a wav file to disk and load it up into an audio editor makes my workflow slow. Being able to stream audio signals directly to a DAW (Digital Audio Workstation, i.e., Ableton Live, Reason, Pro Tools, Cubase, etc.) would make things much simpler, but this means I need to write a <a rel="nofollow" target="_blank" href="http://www.steinberg.net/en/products/vst.html">VST plugin</a> in order to get that audio into those programs.</p>
<p>The problem is, VST&#8217;s are pretty much only developed via a C++ SDK that Steinberg has tight control over, and there is very little documentation on how to roll your own VST plugin without the SDK (there <em>are</em> open source implementations, but I won&#8217;t waste my time reverse engineering this stuff). Furthermore, the Ruby landscape is pretty much void of anything that even comes close to any audio libraries (ruby-audio is one of the very few exceptions), so I&#8217;m working in the dark here.</p>
<p>Fortunately I have experience embedding a Ruby interpreter into C applications, so my next step will be to take a really simple VST plugin base and bind all of the hooks down to a Ruby script running in the background that I can change at runtime, or at least load up without recompiling. I already compiled the AGain VST sample that comes with the SDK and have a good idea how to hook this up to a Ruby interpreter, but there are two things I haven&#8217;t yet figured out:</p>
<ol>
<li>A VST host (DAW) has to load a VST plugin as a DLL (I say DLL to disambiguate &quot;library&quot;, which might be confused with a RubyGem or some plaintext .rb file; these DLLs are compiled down to machine code with exported symbols to be loaded by a process) file on disk, and a plugin does not control the process, so I can&#8217;t just &quot;create a plugin&quot; by launching a Ruby process and requiring some library code. I have to create a single C++ VST plugin (by compiling a DLL) that calls out to Ruby from the hooks provided by the SDK&#8217;s API. The problem is that I don&#8217;t really know how I&#8217;m going to load arbitrary Ruby code if I can&#8217;t control the process, and more importantly, how I&#8217;m going to change the code on the fly, since I won&#8217;t have an interactive console. I&#8217;ll probably have to point to a file on disk that gets reloaded on modification, unless I can spawn up a mini web-server from the plugin that evaluates code passed in via some fake irb console. DRb won&#8217;t work, since I can&#8217;t pass Procs across the wire, and that will definitely be necessary.</li>
<li>The AGain sample is a &quot;VST&quot; plugin. This is different from &quot;VSTi&quot; in a way that I am not fully aware of. Ultimately I want a VST plugin that <em>produces</em> new audio samples, not filters existing audio samples, and that is what a VSTi (or VST instrument) plugin is for. The problem here is that I&#8217;m not sure if I need to use a different API to create a VSTi. I&#8217;ll have to keep digging for a sample on this. It might be pretty easy to make, but I just don&#8217;t yet know how.</li>
</ol>
<p>Once the VSTi plugin is finished, I should be able to load up Ableton Live and play my data directly into a buffer, record it, and analyze the differences&#8230; as well as hear it live. It will also give me a chance to create a VST library that seems to be missing in the Ruby ecosystem.</p>
<p>That&#8217;s it for now.</p><img src="http://feeds.feedburner.com/~r/connectnothing/~4/COztEOZdUKQ" height="1" width="1" alt=""/>]]></content:encoded>
      </item>
      <item>
         <title>Good coders copy, great coders steal</title>
         <link>http://macournoyer.com/blog/2013/06/14/great-coders/</link>
         <description>&lt;p&gt;&lt;img src=&quot;http://g4.std3.ru/G/1/8C/DA/17418-987be959d5936a7fa61f280595154c18.jpg&quot; title=&quot;Source: http://img.d3.ru/comments/416555/&quot; alt=&quot;Source: http://img.d3.ru/comments/416555/&quot;/&gt;&lt;br&gt;&lt;em&gt;Source: http://img.d3.ru/comments/416555/&lt;/em&gt;&lt;/p&gt;&amp;#x000A;&lt;blockquote&gt;&amp;#x000A;&lt;p&gt;Good artists copy, great artists steal. &lt;strong&gt;- Pablo Picasso&lt;/strong&gt;&lt;/p&gt;&amp;#x000A;&lt;/blockquote&gt;&amp;#x000A;&lt;p&gt;What Picasso meant is that good artists duplicate the work of other artists without changing it. But great artists take the work of other artists and make it their own.&lt;/p&gt;&amp;#x000A;&lt;p&gt;I believe programming can be an art, or at least something we should aim for. (For the record, here&amp;#8217;s my favorite piece of art&amp;#8230; err! code, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://underpop.free.fr/l/lua/docs/a-no-frills-introduction-to-lua-5.1-vm-instructions.pdf&quot;&gt;Lua&amp;#8217;s bytecode&lt;/a&gt;. If you have the patience to wrap you head around it, I guarantee you&amp;#8217;ll believe me when I say this is a piece of art. But let&amp;#8217;s stay on track here&amp;#8230;)&lt;/p&gt;&amp;#x000A;&lt;p&gt;To become a better programmer you have to first copy, and then steal.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;Copying&lt;/h4&gt;&amp;#x000A;&lt;p&gt;A painter that copies another painter&amp;#8217;s work, for example, will reproduce every lines and colors one at the time. This makes you realize how many parts come into play to make an amazing piece of art (or software). So when I say copy, I certainly don&amp;#8217;t mean &lt;em&gt;copy-paste&lt;/em&gt; code from StackOverflow. I mean: &lt;strong&gt;recode the thing&lt;/strong&gt;, line for line or in your own style or language, by looking at the original.&lt;/p&gt;&amp;#x000A;&lt;p&gt;This might seem dumb at first, but it works for the same reason taking notes helps you remember things. Even if you don&amp;#8217;t go back to read them. It&amp;#8217;s also better than simply reading the code. As you can&amp;#8217;t get lazy and skim over some parts.&lt;/p&gt;&amp;#x000A;&lt;p&gt;The first open source project I ever created was called &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://webaccept.sourceforge.net/&quot;&gt;WebAccept&lt;/a&gt;. An horrible idea I know&amp;#8230; But I learned so much! I copied most of the design and code from NAnt, also a copy, or as they said: a .NET port of Ant, the Java build too, which probably started as a copy of Make. That project taught me more than I ever learned in school and at work about good software design, documentation, tests and all.&lt;/p&gt;&amp;#x000A;&lt;p&gt;I&amp;#8217;ve been applying the same approach ever since. With Thin, I copied Mongrel. With TinyRB, I copied TinyPy and Lua. Each time learning more and more.&lt;/p&gt;&amp;#x000A;&lt;p&gt;That&amp;#8217;s why I think the best way to learn is to copy, recode, recreate from scratch. And also why I use this approach in all my presentations and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://classes.codedinc.com&quot;&gt;classes&lt;/a&gt;.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;Stealing&lt;/h4&gt;&amp;#x000A;&lt;p&gt;Stealing is the next level. You can copy some code and still not understand how it works. You can also copy some code and not see a better way to do it. But, you become great when you adapt the code to make it better.&lt;/p&gt;&amp;#x000A;&lt;p&gt;This is how the world of software evolves. Making baby steps towards greatness by building on the work of others before us. Making things a tiny bit better each time. There should be no shame in this kind of stealing.&lt;/p&gt;&amp;#x000A;&lt;p&gt;After copying Thin from Mongrel almost line for line, I rewrote it six times to &lt;em&gt;steal it&lt;/em&gt; and make it my own.&lt;/p&gt;&amp;#x000A;&lt;h4&gt;Lets copy together!&lt;/h4&gt;&amp;#x000A;&lt;p&gt;OK! Want to give it a try?&lt;/p&gt;&amp;#x000A;&lt;p&gt;To get you started and show you how I do it, I&amp;#8217;ll be teaching a new class in which I&amp;#8217;ll rebuild a Ruby web server from scratch.&lt;/p&gt;&amp;#x000A;&lt;p&gt;And here&amp;#8217;s the kick&amp;#8230; it&amp;#8217;s free!&lt;/p&gt;&amp;#x000A;&lt;p&gt;Sign-up bellow and join me this &lt;strong&gt;Friday, June 21st at 1PM ET&lt;/strong&gt;. It should last about an hour and I&amp;#8217;ll take some questions at the end.&lt;/p&gt;&amp;#x000A;&lt;p&gt;However, because of technical limitations, only 100 people can attend it live. But, recordings will be available if you sign up.&lt;/p&gt;&amp;#x000A;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://j.mp/rebuildawebserver&quot;&gt;&lt;img&gt;&lt;/a&gt;&lt;/p&gt;&amp;#x000A;&lt;p&gt;All you need is basic understanding of web dev with Ruby (with Rails, Sinatra or other) and a browser with Flash.&lt;/p&gt;&amp;#x000A;&lt;p&gt;I hope to see you in class! :)&lt;/p&gt;</description>
         <guid isPermaLink="false">tag:macournoyer.com,2013-06-14:1371257922</guid>
         <pubDate>Sat, 15 Jun 2013 00:58:42 +0000</pubDate>
      </item>
      <item>
         <title>How tcmalloc Works</title>
         <link>http://feedproxy.google.com/~r/JamesOnSoftware/~3/5YnRn6M51xc/how-tcmalloc-works.html</link>
         <description>&lt;p&gt;&lt;em&gt;tl;dr&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a long blog post that goes in to a bunch of detail about one of the highest performance memory allocators around.&lt;/li&gt;
&lt;li&gt;You should probably read &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gperftools.googlecode.com/svn/trunk/&quot;&gt;the code&lt;/a&gt; instead of reading this article.&lt;/li&gt;
&lt;li&gt;If you aren't familiar with the topic of memory allocation, you should read my last blog post &lt;a rel=&quot;nofollow&quot;&gt;Memory Allocators 101&lt;/a&gt; first.&lt;/li&gt;
&lt;/ul&gt;


&lt;hr /&gt;


&lt;p&gt;&lt;code&gt;tcmalloc&lt;/code&gt; is a memory allocator that's optimized for high concurrency situations. The &lt;code&gt;tc&lt;/code&gt; in &lt;code&gt;tcmalloc&lt;/code&gt; stands for &lt;code&gt;thread cache&lt;/code&gt; &amp;mdash; the mechanism through which this particular allocator is able to satisfy certain (often most) allocations locklessly. It's probably the most well-conceived piece of software I've ever had the pleasure of reading, and although I can't realistically cover every detail, I'll do my best to go over the important points.&lt;/p&gt;

&lt;p&gt;Like most modern allocators, &lt;code&gt;tcmalloc&lt;/code&gt; is page-oriented, meaning that the internal unit of measure is usually pages rather than bytes. This has the effect of making it easier to reduce fragmentation, and increase locality in various ways. It also makes keeping track of metadata far simpler. &lt;code&gt;tcmalloc&lt;/code&gt; defines a page as &lt;code&gt;8192&lt;/code&gt; bytes&lt;sup&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#footnote1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;, which is actually 2 pages on most linux systems.&lt;/p&gt;

&lt;p&gt;Chunks can be thought of as divided in to two top-level categories. &quot;Small&quot; chunks are smaller than &lt;code&gt;kMaxPages&lt;/code&gt; (defaults to 128) and are further divided in to size classes and satisfied by the thread caches or the central per-size class caches. &quot;Large&quot; chunks are &lt;code&gt;&amp;gt;= kMaxPages&lt;/code&gt; and are always satisfied by the central &lt;code&gt;PageHeap&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;Size Classes&lt;/h3&gt;

&lt;p&gt;By default, &lt;code&gt;tcmalloc&lt;/code&gt; creates &lt;code&gt;86&lt;/code&gt; size classes for &quot;small&quot; chunks, each of which have several important properties which define thread cache behaviour as well as fragmentation and waste characteristics.&lt;/p&gt;

&lt;p&gt;The number of pages allocated at once for a particular size class is one such property. It is carefully defined such that transfers between the central and thread caches are within a range that strikes a balance between wasting chunks sitting around unused in thread caches, and having to go to the central cache too often, causing contention for its lock. The code which determines this number also guarantees that the amount of waste per size class is at most &lt;code&gt;12.5%&lt;/code&gt;, and that the alignment guarantees of the &lt;code&gt;malloc&lt;/code&gt; API are respected.&lt;/p&gt;

&lt;p&gt;Size class data is stored in &lt;code&gt;SizeMap&lt;/code&gt; and the first thing to be initialized on startup.&lt;/p&gt;

&lt;h3&gt;Thread Caches&lt;/h3&gt;

&lt;p&gt;Thread caches are a lazily initialized &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Thread-local_storage&quot;&gt;thread-local&lt;/a&gt; data structure which contains one free list (singly-linked) per size class. They also contain metadata regarding the current total size of their contents.&lt;/p&gt;

&lt;p&gt;Allocations and deallocations from thread caches are lockless and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Time_complexity&quot;&gt;constant-time&lt;/a&gt; in the best case. If the thread cache doesn't already contain a chunk for the size class that is being allocated, it has to fetch some chunks for that class from the central cache, of which there is one per size class. If the thread cache becomes too full (more on what that means in a second) on deallocation, chunks are migrated back to the central cache. Each central cache has its own lock to reduce contention during such migrations.&lt;/p&gt;

&lt;p&gt;As chunks are migrated in and out of a thread cache, it bounds its own size in two interesting ways.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, there is an overall total size of all the combined thread caches. Each cache keeps track of its total contents as chunks are migrated to and from the central caches, as well as allocated or deallocated. Initially, each cache is assigned an equal amount of space from the overall total. However, as some caches inevitably need more or less space, there is a clever algorithm whereby one cache can &quot;steal&quot; unused space from one of its neighbours.&lt;/li&gt;
&lt;li&gt;Second, each free list has a maximum size, which gets increased in an interesting way as objects are migrated in to it from the central cache. If the list exceeds its maximum size, chunks are released to the central cache.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;If a thread cache has exceeeded its maximum size after a migration from the central cache or on deallocation, it first attempts to find some extra headroom in its own free-lists by checking to see if they have any excess that can be released to the central caches. Chunks are considered excess if they have been added to a free list since the last allocation that the list satisfied&lt;sup&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#footnote3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;. If it can't free up any space that way, it will attempt to &quot;steal&quot; space from one of its neighbouring thread caches, which requires holding the &lt;code&gt;pageheap_lock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Central caches have their own system for managing space across all the caches in the system. Each is capped at either &lt;code&gt;1MB&lt;/code&gt; of chunks or 1 entry, whichever is greater. As central caches need more space, they can &quot;steal&quot; it from their neighbours, using a similar mechanism to the one employed by thread caches. If a thread cache attempts to migrate objects back to a central cache that is full and unable to acquire more space, the central cache will release those objects to the &lt;code&gt;PageHeap&lt;/code&gt;, which is where it got them in the first place.&lt;/p&gt;

&lt;h3&gt;Page Heap&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;PageHeap&lt;/code&gt; can be thought of as the root of the whole system. When chunks aren't floating around the caches or allocated in the running application, they're living in one of the &lt;code&gt;PageHeap&lt;/code&gt;'s free lists. This is where chunks are allocated in the first place, using &lt;code&gt;TCMalloc_SystemAlloc&lt;/code&gt; and ultimately released back to the operating system, using &lt;code&gt;TCMalloc_SystemRelease&lt;/code&gt;. It's also where &quot;large&quot; allocations are satisfied and provides the interface for tracking heap metadata.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;PageHeap&lt;/code&gt; manages &lt;code&gt;Span&lt;/code&gt; objects, which represent a contiguous run of pages. Each &lt;code&gt;Span&lt;/code&gt; has several important properties.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PageID start&lt;/code&gt; is the start address of the memory the &lt;code&gt;Span&lt;/code&gt; describes. &lt;code&gt;PageID&lt;/code&gt; is &lt;code&gt;typedef&lt;/code&gt;'d to &lt;code&gt;uintptr_t&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Length length&lt;/code&gt; is the number of pages in the &lt;code&gt;Span&lt;/code&gt;. &lt;code&gt;Length&lt;/code&gt; is also &lt;code&gt;typedef&lt;/code&gt;'d to &lt;code&gt;uintptr_t&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Span *next&lt;/code&gt; and &lt;code&gt;Span *prev&lt;/code&gt; are pointers for when the &lt;code&gt;Span&lt;/code&gt; is in one of the doubly linked free-listsb in the &lt;code&gt;PageHeap&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A bunch more stuff, but this post is getting really long.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The &lt;code&gt;PageHeap&lt;/code&gt; has &lt;code&gt;kMaxPages + 1&lt;/code&gt; free lists &amp;mdash; one for each span length from &lt;code&gt;0...kMaxPages&lt;/code&gt; and one for lengths greater than that. The lists are doubly linked and split in to &lt;code&gt;normal&lt;/code&gt; and &lt;code&gt;returned&lt;/code&gt; sections.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;normal&lt;/code&gt; section contains &lt;code&gt;Span&lt;/code&gt;s whose pages are definitely mapped in to the process's address space.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;returned&lt;/code&gt; section contains &lt;code&gt;Span&lt;/code&gt;s whose pages have been returned to the operating system using &lt;code&gt;madvise&lt;/code&gt; with &lt;code&gt;MADV_FREE&lt;/code&gt;. The OS is free to reclaim those pages as necessary. However, if the application uses that memory before it has been reclaimed, the call to &lt;code&gt;madvise&lt;/code&gt; is effectively negated. Even in the case that the memory &lt;em&gt;has&lt;/em&gt; been reclaimed, the kernel will remap those addresses to a freshly zero'd region of memory. So, not only is it safe to reuse pages that have been returned, it's an important strategy for reducing heap fragmentation.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The &lt;code&gt;PageHeap&lt;/code&gt; also contains the &lt;code&gt;PageMap&lt;/code&gt;, which is a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Radix_tree&quot;&gt;radix tree&lt;/a&gt; that maps addresses to their respective &lt;code&gt;Span&lt;/code&gt; objects, and the &lt;code&gt;PageMapCache&lt;/code&gt;, which  maps a chunk's &lt;code&gt;PageID&lt;/code&gt; to its size class for chunks that are in the cache system. This is the mechanism through which &lt;code&gt;tcmalloc&lt;/code&gt; stores its metadata, rather than using headers and footers to the actual pointers. Although it is somewhat less space efficient, it is substantially more cache efficient since all of the involved data structures are slab allocated.&lt;/p&gt;

&lt;p&gt;Allocations from the &lt;code&gt;PageHeap&lt;/code&gt; are performed via &lt;code&gt;PageHeap::New(Length n)&lt;/code&gt;, where &lt;code&gt;n&lt;/code&gt; is the number of pages being requested.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, the free lists &lt;code&gt;&amp;gt;=&lt;/code&gt; to &lt;code&gt;n&lt;/code&gt; (unless &lt;code&gt;n&lt;/code&gt; is &lt;code&gt;&amp;gt;= kMaxPages&lt;/code&gt;) are traversed looking for a &lt;code&gt;Span&lt;/code&gt; big enough to satisfy &lt;code&gt;n&lt;/code&gt;. If one is found, it is removed from the list and returned. This type of allocation is best-fit, but because it's not address ordered, it is suboptimal as far as fragmentation is concerned &amp;mdash; presumably a performance tradeoff. The &lt;code&gt;normal&lt;/code&gt; lists are all checked before moving on to checking the &lt;code&gt;returned&lt;/code&gt; lists. I'm not sure exactly why.&lt;/li&gt;
&lt;li&gt;If none of those lists have a fitting &lt;code&gt;Span&lt;/code&gt;, the large lists are traversed, looking for an address-ordered best fit. This algorithm is &lt;code&gt;O(n)&lt;/code&gt; accross all the &lt;code&gt;Span&lt;/code&gt;s in both large lists, which can get very expensive in situations where concurrency is fluctuating dramatically and the heap has become fragmented. I have written &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://code.google.com/p/gperftools/issues/detail?id=532&amp;amp;thanks=532&amp;amp;ts=1369179481&quot;&gt;a patch&lt;/a&gt; which reorganizes the large lists in to a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Skip_list&quot;&gt;skip list&lt;/a&gt; if they exceed a configurable total size to improve large allocation performance for applications which encounter this circumstance.&lt;/li&gt;
&lt;li&gt;If the &lt;code&gt;Span&lt;/code&gt; that has been found is at least one page bigger than the requested allocation, it is split in to a chunk sufficient to satisfy the allocation, and whatever is leftover is re-added to the appropriate free list before returning the newly allocated chunk.&lt;/li&gt;
&lt;li&gt;If no suitable &lt;code&gt;Span&lt;/code&gt; is found, the &lt;code&gt;PageHeap&lt;/code&gt; attempts to grow itself by at least &lt;code&gt;n&lt;/code&gt; pages before starting the process again from the beginning. If it is unsuccessful at finding a suitable chunk the second time around, it returns &lt;code&gt;NULL&lt;/code&gt;, which ultimately results in &lt;code&gt;ENOMEM&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Deallocations to the &lt;code&gt;PageHeap&lt;/code&gt; are performed via &lt;code&gt;PageHeap::Delete(Span* span)&lt;/code&gt;. Their effect is that the &lt;code&gt;Span&lt;/code&gt; is merged in to the appropriate free-list.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, the adjacent &lt;code&gt;Span&lt;/code&gt; objects (both left and right) are acquired from the &lt;code&gt;PageMap&lt;/code&gt;. If either or both of them are free, they are removed from whatever free-list they happen to be on and coalesced together with &lt;code&gt;span&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then, &lt;code&gt;span&lt;/code&gt; is prepended to whichever free list it now belongs on.&lt;/li&gt;
&lt;li&gt;Finally, the &lt;code&gt;PageHeap&lt;/code&gt; checks to see whether it's time to release memory to the operating system, and releases some if it is.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Each time a &lt;code&gt;Span&lt;/code&gt; is returned to &lt;code&gt;PageHeap&lt;/code&gt;, its member &lt;code&gt;scavenge_counter_&lt;/code&gt; is decremented by the &lt;code&gt;length&lt;/code&gt; of that &lt;code&gt;Span&lt;/code&gt;. If &lt;code&gt;scavenge_counter_&lt;/code&gt; drops below &lt;code&gt;0&lt;/code&gt;, the last &lt;code&gt;Span&lt;/code&gt; is released from one of the free lists or the &lt;code&gt;large&lt;/code&gt; list, removed from the &lt;code&gt;normal&lt;/code&gt; list, and then added to the appropriate &lt;code&gt;returned&lt;/code&gt; list for possible reuse later. &lt;code&gt;scavenge_counter_&lt;/code&gt; is then reset to &lt;code&gt;min(kMaxReleaseDelay, (1000.0 / FLAGS_tcmalloc_release_rate) * number_of_pages_released)&lt;/code&gt;. So, tuning &lt;code&gt;FLAGS_tcmalloc_release_rate&lt;/code&gt; has a substantial effect on when memory gets released.&lt;/p&gt;

&lt;h3&gt;Conclusions&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;This blog post is incredibly long. Congratulations for getting here. And yet I barely feel like I've covered anything.&lt;/li&gt;
&lt;li&gt;If this kind of problem is interesting to you, I &lt;em&gt;highly&lt;/em&gt; recommend reading the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gperftools.googlecode.com/svn/trunk/&quot;&gt;source code&lt;/a&gt;. Although &lt;code&gt;tcmalloc&lt;/code&gt; is very complex, the code is extremely approachable and well commented. I barely know &lt;code&gt;C++&lt;/code&gt; and was still able to write a substantial patch. Particularly with this blog post as a guide, there's not much to be afraid of.&lt;/li&gt;
&lt;li&gt;I'll cover &lt;code&gt;jemalloc&lt;/code&gt; in a future episode.&lt;/li&gt;
&lt;li&gt;Listen to my (and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://timetobleed.com&quot;&gt;Joe Damato&lt;/a&gt;'s) &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://realtalk.io&quot;&gt;podcast&lt;/a&gt; &amp;mdash; it's about this kind of stuff.&lt;/li&gt;
&lt;/ul&gt;


&lt;div style=&quot;font-size:12px;&quot;&gt;
  &lt;a rel=&quot;nofollow&quot; name=&quot;footnote1&quot;&gt;&lt;/a&gt;[1] Unless the experimental feature `TCMALLOC_LARGE_PAGES` is enabled. 
  &lt;a rel=&quot;nofollow&quot; name=&quot;footnote2&quot;&gt;&lt;/a&gt;[2] This is sort of a simplification of a more complicated system, but should be good enough for this purpose. 
&lt;/div&gt;




&lt;br/&gt;

&lt;img src=&quot;http://feeds.feedburner.com/~r/JamesOnSoftware/~4/5YnRn6M51xc&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">tag:jamesgolick.com,2013-05-19:1368979797</guid>
         <pubDate>Sun, 19 May 2013 16:09:57 +0000</pubDate>
      </item>
      <item>
         <title>Memory Allocators 101</title>
         <link>http://feedproxy.google.com/~r/JamesOnSoftware/~3/Yh8_0HkN2kY/memory-allocators-101.html</link>
         <description>&lt;p&gt;For the last few weeks, I've been working on a couple of patches to tcmalloc, Google's super high performance memory allocator. I'm going to post about them soon, but first I thought it would be cool to give some background about what a memory allocator actually does. So, if you've ever wondered what happens when you call &lt;code&gt;malloc&lt;/code&gt; or &lt;code&gt;free&lt;/code&gt;, read on.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;A memory allocator's responsibility is to manage free blocks of memory. If you've never read a &lt;code&gt;malloc&lt;/code&gt; implementation, you may have assumed that calling &lt;code&gt;free&lt;/code&gt; simply causes memory to be released to the operating system. But acquiring memory from the OS has a cost, so allocators tend to keep free chunks around for a while for possible re-use before deciding to release them.&lt;/p&gt;

&lt;p&gt;Managing &lt;code&gt;free&lt;/code&gt;d memory is an incredibly interesting and hard problem with two main concerns: performance and reducing heap fragmentation / waste:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do we organize free blocks of memory such that we can quickly locate a sufficiently large block (or determine that we lack one) when someone calls &lt;code&gt;malloc&lt;/code&gt; without making calls to &lt;code&gt;free&lt;/code&gt; prohibitively expensive?&lt;/li&gt;
&lt;li&gt;What can we do to reduce fragmentation and waste in the face of sometimes drastically changing allocation patterns over the lifetime of a (potentially long-running) program? It's worth noting that heap fragmentation can have a substantial impact on CPU cache efficiency.&lt;/li&gt;
&lt;li&gt;As a bonus, there's also the matter of concurrency, but that's probably beyond the scope of this post.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The most fun part of this problem is that our two primary objectives are often in direct opposition. For example, keeping one linked list of free blocks per allocation size (say, rounded up to number of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Page_(computer_memory)&quot;&gt;pages&lt;/a&gt;) can make calls to &lt;code&gt;malloc&lt;/code&gt; best case constant time, but unless some waste is accepted and chunks are kept around long enough to be reused, the worst case path will be taken more often than not.&lt;/p&gt;

&lt;p&gt;Of course, there also are a multitude of other issues to consider, such as how to decide to release memory to the operating system, and how to avoid becoming the bottleneck in a concurrent program (I'm looking at you, glibc). And the implementation details are interesting, too.&lt;/p&gt;

&lt;h3&gt;Implementation&lt;/h3&gt;

&lt;p&gt;A very basic &lt;code&gt;malloc&lt;/code&gt; implementation might use the linux system call &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://linux.die.net/man/2/sbrk&quot;&gt;&lt;code&gt;sbrk(2)&lt;/code&gt;&lt;/a&gt; to acquire memory from the operating system and a linked list to store free chunks. That would make calls to &lt;code&gt;free&lt;/code&gt; constant time, but &lt;code&gt;malloc&lt;/code&gt; would be &lt;code&gt;O(n)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Of course, the allocator needs to store metadata about each chunk it manages, such as its size, free/in-use status, free-list pointer(s), etc. But since you can't exactly call &lt;code&gt;malloc&lt;/code&gt; in an allocator, it's common to store metadata in a &quot;header&quot; that just precedes the address that is handed to the application. So, if the header is 16 bytes in size, then the header would start at &lt;code&gt;ptr - 16&lt;/code&gt;. Pointer arithmetic galore.&lt;/p&gt;

&lt;div style=&quot;text-align:center;&quot;&gt;&lt;img/&gt;&lt;/div&gt;


&lt;br/&gt;




 


&lt;p&gt;In order to reduce fragmentation and promote memory reuse, it's common for &lt;code&gt;malloc&lt;/code&gt; implementations to attempt to coalesce free blocks of memory with adjacent ones, if they happen to also be free. If metadata is being stored in a header, then it's easy to determine the size and status of the pointer to the right.&lt;/p&gt;

&lt;div style=&quot;text-align:center;&quot;&gt;&lt;img/&gt;&lt;/div&gt;


&lt;br/&gt;




 


&lt;p&gt;But the header doesn't provide any way of determining the size of the chunk to the left, so coalescing &lt;code&gt;malloc&lt;/code&gt;s frequently put the size of each block in a footer, which is typically sized to fit a &lt;code&gt;size_t&lt;/code&gt;. Then finding the chunk to the left would look something like this:&lt;/p&gt;

&lt;div style=&quot;text-align:center;&quot;&gt;&lt;img/&gt;&lt;/div&gt;


&lt;br/&gt;




 


&lt;p&gt;Things get even more complicated because subsequent invocations of system calls like &lt;code&gt;sbrk&lt;/code&gt; or &lt;code&gt;mmap&lt;/code&gt; aren't guaranteed to return contiguous virtual addresses. So, when looking for chunks to coalesce, care has to be taken to make sure that invalid pointers aren't dereferenced by adding to a pointer that's on the edge of what's being managed.&lt;/p&gt;

&lt;p&gt;Typically this means creating and maintaining a separate data structure with which to keep track of the regions of virtual address space that the allocator is managing. Some allocators, such as &lt;code&gt;tcmalloc&lt;/code&gt;, simply store their metadata in that data structure rather than in headers and footers, which avoids a lot of error-prone pointer arithmetic.&lt;/p&gt;

&lt;hr /&gt;


&lt;p&gt;I could probably continue writing about this forever, but this seems like a good place to stop for now. If your interest is piqued and you'd like to learn more about memory allocators, I highly recommend diving in to writing your own &lt;code&gt;malloc&lt;/code&gt; implementation. It's a challenging project, but it's fun and it'll give you a lot of insight in to an important part of how your computer works.&lt;/p&gt;

&lt;p&gt;Soon I'll follow up on this post with one about the allocator work I've been doing lately. Also, if you're interested in this kind of stuff, check out my new &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://realtalk.io&quot;&gt;podcast&lt;/a&gt; where &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://timetobleed.com&quot;&gt;Joe Damato&lt;/a&gt; and I talk about systems programming. We'll definitely be covering allocators in the next few weeks sometime.&lt;/p&gt;

&lt;p&gt;Some allocator resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://man7.org/linux/man-pages/man3/malloc.3.html&quot;&gt;malloc(3) man page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cs.cmu.edu/afs/cs/academic/class/15213-f10/www/lectures/17-allocation-basic.pdf&quot;&gt;http://www.cs.cmu.edu/afs/cs/academic/class/15213-f10/www/lectures/17-allocation-basic.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://goog-perftools.sourceforge.net/doc/tcmalloc.html&quot;&gt;tcmalloc docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jeremie-koenig/glibc/tree/master-beware-rebase/malloc&quot;&gt;glibc malloc source&lt;/a&gt; &amp;mdash; this is some random github repo, so I have no idea how much its been fucked with&lt;/li&gt;
&lt;/ul&gt;

&lt;img src=&quot;http://feeds.feedburner.com/~r/JamesOnSoftware/~4/Yh8_0HkN2kY&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">tag:jamesgolick.com,2013-05-15:1368632222</guid>
         <pubDate>Wed, 15 May 2013 15:37:02 +0000</pubDate>
      </item>
      <item>
         <title>Introducing The Real Talk Podcast</title>
         <link>http://feedproxy.google.com/~r/JamesOnSoftware/~3/K8mZVK2PInw/introducing-the-real-talk-podcast.html</link>
         <description>&lt;p&gt;[Joe Damato] and I have released the inaugural episode of our new, highly technical podcast realtalk.io.&lt;/p&gt;

&lt;p&gt;We will be doing frequent technical deep dives and releasing our conversations raw and unedited with all errors, omissions, awkward pauses, and curse words intact.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://realtalk.io&quot;&gt;website&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot;&gt;soundcloud&lt;/a&gt;, and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/realtalkio&quot;&gt;subscribe&lt;/a&gt;.&lt;/p&gt;
&lt;img src=&quot;http://feeds.feedburner.com/~r/JamesOnSoftware/~4/K8mZVK2PInw&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">tag:jamesgolick.com,2013-04-29:1367209602</guid>
         <pubDate>Mon, 29 Apr 2013 04:26:42 +0000</pubDate>
      </item>
      <item>
         <title>Distributed Coding at sweetiQ</title>
         <link>http://lovehateubuntu.blogspot.com/2013/04/distributed-coding-at-sweetiq.html</link>
         <description>It's been a long time since I really wrote anything on this blog, so it is time for a little update.&lt;br/&gt;&lt;br/&gt;Just over a year ago I joined another startup called &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sweetiq.com/&quot;&gt;sweetiQ&lt;/a&gt;. It's a step up from the other startups that I've worked for in that it has actually gone live and it is actually making money. It's also interesting because this is the longest amount of time I've spent working for a single company.&lt;br/&gt;&lt;br/&gt;The system uses &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt; for driving a distributed computing cluster that essentially implements &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Actor_model&quot;&gt;Actor model&lt;/a&gt; of computation, except rather than working with threads within a single machine we're using multiple processes on multiple machines (100+). Each process has a set of endpoints that listen on different queues, RabbitMQ manages dispatching these messages to the different worker nodes.&lt;br/&gt;&lt;br/&gt;One of my major contributions is what I'm calling a &quot;distributed job control system.&quot; There are many steps in each &quot;job&quot; that the system must do, and each step of the job may be handled by a different process across different machines. As a particular computing job becomes more complex, several problems arise:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;	&lt;li&gt;managing the dependency structure between various components of each job. In a simple sequential system you can do A, then B, then C; the dependency structure is very simple: if x depends on y, do y after x. In a distributed system B may not depend on A, so you can do them in parallel, but C depends on the output of both A and B so the system cannot start C until both A and B are done. It is not possible to just have the node handling C wait for a response of both A and B, because the messages from A and B may not be delivered to the same node that can handle C. Even more complex, in certain cases C may not need the computation from A but in other times it does - for example if we're aggregating social data from different networks but the user hasn't linked their Twitter account, we don't need to fetch data from Twitter.&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;the possibility of failure increases - sometimes a node will lose its database connection. Sometimes a node will die (exmaple: we use Amazon spot instances that at any time can just shut down). Sometimes a node that attempts to fetch something on the Internet may fail for whatever reason (the API version of Twitter's fail whale is something that has happened relatively frequently). In this case the process needs some sort of elegant failure handling - often the solution is just to try again later. Other times we need to send a message to the user informing them that they need to take some sort of action (if a user changes their Facebook password, it will invalidate the stored OAuth token).&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;need to rate-limit certain jobs - some jobs can have many sub-components done in parallel, we have encountered some problems sending out too many messages in parallel. The first and most obvious problem that we hit is that the database will choke, however once we learned how to use MongoDB properly this became a non-issue (having scaled both MySQL databases and MongoDB databases, I can tell you I am fully sold on MongoDB at this point). The bigger issue was a problem of process starvation: at peak times jobs will begin spawning at an enormous rate, and if we keep sending parallel messages for stage 1, the computation nodes spend most their time processing messages for stage 1 (Rabbit has no concept of priority). There is a need for the control system to detect starvation and alleviate it (a variety of different ways we can do this).&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;recursive job types - our data is hierarchical. A user can categorize components of what they &quot;own&quot; in groups and sub-groups, and may want to be able to break down aggregated information at each level. Each job may need to perform itself separately on a child node, which may in turn need to perform itself on its own children, etc. Having some sort of way to easily specify recursive sub-jobs saves a ton of time.&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;What I ended up building is a system that takes a high-level description of a distributed job and controls that job across the different nodes. Rather than having each endpoint communicate directly with one another, they communicate with the central controller that tracks their progress and makes decisions on what control points to activate. The huge benefit of this is that it is a separation of concerns: the endpoints can focus on doing their particular computation well, while the &quot;bigger picture&quot; concerns like starvation and node failure can be handled by the control system.&lt;br/&gt;The system can handle recursive job structures and in fact it can handle any type of sub-job: any job can trigger any other job as a child, including itself. This makes it trivially easy to run one component of a job so that you don't need to go through everything in order to do what needs to be done. It also allows you to remain DRY: you can abstract out certain commonly-used components and use them as a &quot;library&quot; of sorts to compose more complex jobs.&lt;br/&gt;&lt;br/&gt;The code is not currently available, however we are trying to figure out the legal implications of open-sourcing the software. Ideally we'll figure all this out in the near future, and I'll be happy to release it for everyone to play with.&lt;br/&gt;&lt;br/&gt;Shameless company promotion: If this type of work interests you, send me a message. Like most dev shops, we're always happy to bring in smart folks.&lt;img src=&quot;http://feeds.feedburner.com/~r/UbuntuALove/hateRelationship/~4/JoIT8qugWKQ&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <author>Rob Britton</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-165807313160822069.post-9104047325161699491</guid>
         <pubDate>Tue, 16 Apr 2013 12:15:00 +0000</pubDate>
      </item>
      <item>
         <title>MRI's Method Caches</title>
         <link>http://feedproxy.google.com/~r/JamesOnSoftware/~3/YUhhYm647ic/mris-method-caches.html</link>
         <description>&lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method resolution is expensive, so method caches are crucial to invocation performance.&lt;/li&gt;
&lt;li&gt;Your Ruby code probably calls methods kind of often, so invocation performance matters.&lt;/li&gt;
&lt;li&gt;MRI's method cache invalidation strategy is quite naive, leading to very low hit rates in most Ruby code.&lt;/li&gt;
&lt;li&gt;I wrote &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/tree/jamesgolick&quot;&gt;some patches&lt;/a&gt; that substantially improve the situation.&lt;/li&gt;
&lt;li&gt;This blog post is surprisingly uninflammatory.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;The Long Version&lt;/h3&gt;

&lt;p&gt;One of MRI's big performance problems is that method cache expiry is global. That is, any time you make a change to any class anywhere, the entire VM's method caches get busted at the same time. This is why you'll frequently hear people saying that &quot;calling &lt;code&gt;Object#extend&lt;/code&gt; is bad&quot;.&lt;/p&gt;

&lt;p&gt;Actually, it's not just &lt;code&gt;Object#extend&lt;/code&gt;. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/charliesome&quot;&gt;Charlie Somerville&lt;/a&gt; put together what I believe to be an &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://charlie.bz/blog/things-that-clear-rubys-method-cache&quot;&gt;exhaustive list&lt;/a&gt; of things that clear MRI's method caches. Method cache busting is so pervasive that it's almost impossible to avoid using somebody's code that does it. Disaster.&lt;/p&gt;

&lt;p&gt;Let's back up for a second, though. What is a method cache and why are they important?&lt;/p&gt;

&lt;h3&gt;Method Cache Basics&lt;/h3&gt;

&lt;p&gt;Take the following class hierarchy:&lt;/p&gt;

 


&lt;p&gt;Internally, MRI stores methods in a hash table on the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/include/ruby/ruby.h#L630&quot;&gt;&lt;code&gt;RClass struct&lt;/code&gt;&lt;/a&gt;. When you call an inherited method on a descendent, MRI has to walk up the class hierarchy to find it, checking the method table at each step to see if there's anything there to call.&lt;/p&gt;

&lt;p&gt;So, in our above example, if we wanted to call &lt;code&gt;hello&lt;/code&gt; on an instance of &lt;code&gt;E&lt;/code&gt;, MRI would have to execute method lookups on &lt;code&gt;E&lt;/code&gt;, &lt;code&gt;D&lt;/code&gt;, &lt;code&gt;C&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, only to finally find the method in &lt;code&gt;A&lt;/code&gt;'s method table.&lt;/p&gt;

&lt;p&gt;It turns out that method resolution is actually quite expensive, which is why method caches exist. Rather than resolving a method each time we want to call it, we cache a reference to the method somewhere we can get to it cheaply, substantially reducing the cost of subsequent invocations.&lt;/p&gt;

&lt;p&gt;But Ruby is dynamic, so those caches can't necessarily live forever. If we call &lt;code&gt;String#gsub&lt;/code&gt;, for example, and then &lt;code&gt;undef&lt;/code&gt; it without expiring the method cache, it'll still be reachable. Cache invalidation is hard, as we know, so MRI takes a somewhat brute force approach.&lt;/p&gt;

&lt;h3&gt;How MRI's Method Caches Work&lt;/h3&gt;

&lt;p&gt;Currently, MRI has two types of method caches. Ruby code is compiled down to MRI's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/insns.def&quot;&gt;instructions&lt;/a&gt;. Each instruction has some data associated with it. The &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/insns.def#L998&quot;&gt;send&lt;/a&gt; instruction has an &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/vm_core.h#L128&quot;&gt;&lt;code&gt;iseq_inline_cache_entry&lt;/code&gt;&lt;/a&gt;, which acts as an inline method cache.&lt;/p&gt;

&lt;p&gt;You can read the logic &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/vm_insnhelper.c#L1369&quot;&gt;here&lt;/a&gt;. Basically, it works like this: look at the inline cache. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/vm_insnhelper.c#L1374-L1375&quot;&gt;If it's valid&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/vm_insnhelper.c#L1376&quot;&gt;use it&lt;/a&gt;. If not, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/vm_insnhelper.c#L1379-1382&quot;&gt;go actually look up the method and cache it&lt;/a&gt;. Pretty much exactly what you'd expect.&lt;/p&gt;

&lt;p&gt;In the case of an inline instruction cache miss, there's actually a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/vm_method.c#L25&quot;&gt;secondary, global method cache&lt;/a&gt;. Oddly, though, the global method cache is limited to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/vm_method.c#L8&quot;&gt;2048&lt;/a&gt; entries, and its semantics for deciding what to keep and what to dump are &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/vm_method.c#L10&quot;&gt;essentially random&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's not as unlikely as you might hope for two methods in a tight loop to be clobbering each others' entries in the global method cache table.&lt;/p&gt;

&lt;p&gt;Both caches' entries have a field that stores the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/094f2f438ae79f0b9afe9b4f5966c5bf1a6a3d9c/vm_insnhelper.h#L224&quot;&gt;&lt;code&gt;ruby_vm_global_state_version&lt;/code&gt;&lt;/a&gt; from when they were filled. A cache entry is considered valid if it matches the &lt;code&gt;klass&lt;/code&gt; pointer and the current &lt;code&gt;ruby_vm_global_state_version&lt;/code&gt;. So, incrementing the global state version by &lt;code&gt;1&lt;/code&gt; invalidates all of the inline instruction caches as well as the global method cache.&lt;/p&gt;

&lt;p&gt;This has the effect of making invalidation very cheap, but far reaching. Whenever you make a change to any class, call extend, or do any of the other things detailed in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://charlie.bz/blog/things-that-clear-rubys-method-cache&quot;&gt;Charlie's article&lt;/a&gt;, all of the method caches that have built up since your program started become invalid and you have to repay the cost of method resolution all over again.&lt;/p&gt;

&lt;h3&gt;The Numbers&lt;/h3&gt;

&lt;p&gt;After years of complaining about Ruby's method caching behaviour, I finally decided to instrument it a couple of weeks ago. I found that for our application, the method cache was being invalidated at least 20 times per request, and that around 10% of our request profile was spent performing method resolution. For our application, the cost of Ruby's global method cache invalidation was extremely high.&lt;/p&gt;

&lt;p&gt;The average cost of each method resolution for our production application is around one microsecond, which doesn't sound like a lot but it adds up. We were seeing at least 8000 cache misses per request, totalling 8ms or more.&lt;/p&gt;

&lt;p&gt;As part of my instrumentation patchset, I also created a mechanism that logs a stacktrace each time the method cache is invalidated. I found that the majority of invalidations in our app were from inside of ActiveRecord - &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/rails/rails/pull/10058&quot;&gt;some&lt;/a&gt; easier to fix than others. Many were also caused by random gems doing things like instantiating &lt;code&gt;OpenStruct&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;At this point, it started seeming somewhat impractical to go and patch rails and all these other gems that I use, so I decided to investigate the amount of effort that would be required to actually solve the problem in MRI.&lt;/p&gt;

&lt;h3&gt;Hierarchical Method Cache Invalidation&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;I'll be using &lt;code&gt;class&lt;/code&gt; to mean &lt;code&gt;class&lt;/code&gt; or &lt;code&gt;module&lt;/code&gt; here, since they have the same backing structure in the VM.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ruby's inheritance tree is a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Directed_acyclic_graph&quot;&gt;directed acyclic graph&lt;/a&gt;, and the semantics of method resolution mean that a change to a given class only affects it and its descendents. So, in an ideal scenario, we would only need to invalidate the method caches for those branches of the inheritance tree.&lt;/p&gt;

&lt;p&gt;I've written a patch for MRI that implements such an algorithm, and it's currently serving 100% of our production traffic. We've seen around a 9% reduction in average latency with this patch. Others who've tried it haven't seen such big jumps. Your mileage may vary.&lt;/p&gt;

&lt;p&gt;The algorithm is actually quite simple (credit to Charlie Nutter / JRuby for the idea). We have a 64 bit global (one per VM instance) sequence that is monotonically increasing. Every time we alloc a new &lt;code&gt;RClass&lt;/code&gt;, we increment the sequence, and assign the class a unique value.&lt;/p&gt;

&lt;p&gt;Method and inline cache entries are tagged with the class's sequence value when they're filled. When a class is modified, we traverse the class hierarchy downwards from the modification point, assigning each class a new sequence number.&lt;/p&gt;

&lt;p&gt;A method cache entry is considered valid if its sequence number matches the current sequence of the class. So, if the class or one of its parents has been modified since the cache entry was created, its class will have a new sequence number, and it will have therefore been invalidated.&lt;/p&gt;

&lt;h3&gt;Performance&lt;/h3&gt;

&lt;p&gt;For our application, this cache invalidation strategy substantially reduces the number of method cache misses we see in production and has reduced request latency by ~8-9%, but there &lt;em&gt;are&lt;/em&gt; tradeoffs involved. Since invalidation requires a graph traversal, it's a lot more expensive than the current strategy of merely incrementing an integer.&lt;/p&gt;

&lt;p&gt;If your application makes frequent modifications to classes and modules which have a large number of descendents, the cost of invalidation may outweigh the increase in method cache hit rate. That said, I would imagine that such modifications are relatively uncommon and should be considered a bad practice either way.&lt;/p&gt;

&lt;p&gt;It's also worth noting here that while this patch will likely improve the performance of apps that employ the strategy of extending arbitrary objects to implement &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Data,_context_and_interaction&quot;&gt;DCI&lt;/a&gt;, that pattern is still a performance problem, because it creates tons of one-off metaclasses whose methods wind up being mostly uncacheable.&lt;/p&gt;

&lt;h3&gt;The Code&lt;/h3&gt;

&lt;p&gt;My patchset includes several things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subclass tracking: &lt;code&gt;Class#subclasses&lt;/code&gt;, and &lt;code&gt;Module#included_in&lt;/code&gt;. Rails implements this with an O(n) traversal of &lt;code&gt;ObjectSpace&lt;/code&gt;. With my patches, that's no longer necessary.&lt;/li&gt;
&lt;li&gt;Hierarchical method cache invalidation: the subject of this whole article.&lt;/li&gt;
&lt;li&gt;Method cache instrumentation: &lt;code&gt;RubyVM::MethodCache&lt;/code&gt; has several useful singleton methods you may want to track, including &lt;code&gt;hits&lt;/code&gt;, &lt;code&gt;misses&lt;/code&gt;, &lt;code&gt;miss_time&lt;/code&gt;, &lt;code&gt;invalidation_time&lt;/code&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;You can find the code in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/tree/jamesgolick&quot;&gt;my branch&lt;/a&gt; or install it with &lt;code&gt;rvm install jamesgolick&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I am planning to submit these patches back upstream, but I have to port them to Ruby 2.0 first, so I guess that's my next project. Huge thanks and credit to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/tmm1&quot;&gt;Aman Gupta&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/charliesome&quot;&gt;Charlie Somerville&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/headius&quot;&gt;Charles Nutter&lt;/a&gt;, and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/funny-falcon&quot;&gt;funny-falcon&lt;/a&gt; for all their code, help, and testing!&lt;/p&gt;
&lt;img src=&quot;http://feeds.feedburner.com/~r/JamesOnSoftware/~4/YUhhYm647ic&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">tag:jamesgolick.com,2013-04-14:1365955274</guid>
         <pubDate>Sun, 14 Apr 2013 16:01:14 +0000</pubDate>
      </item>
      <item>
         <title>Two Years Ago and A Quarter Million Dollar Later</title>
         <link>http://macournoyer.com/blog/2013/04/10/two-years-ago/</link>
         <description>&lt;p&gt;Two years ago, I left my job with a very ambitious goal: never work for anyone else but me. This included contract work.&lt;/p&gt;&amp;#x000A;&lt;p&gt;It was real test in self-confidence and determination. &lt;a rel=&quot;nofollow&quot;&gt;But my first month of working for myself was a great success&lt;/a&gt;. I was off to a good start. And I&amp;#8217;m glad to say that things continued going increasingly well after that.&lt;/p&gt;&amp;#x000A;&lt;p&gt;Here are the details.&lt;/p&gt;&amp;#x000A;&lt;h3&gt;Products&lt;/h3&gt;&amp;#x000A;&lt;p&gt;With consulting out of the question, products were my only source of income. As you&amp;#8217;ll see, most of my products are info-products, packaging information in various formats.&lt;/p&gt;&amp;#x000A;&lt;p&gt;In the last two years I released five products:&lt;/p&gt;&amp;#x000A;&lt;ul&gt;&amp;#x000A;	&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://owningrails.com/&quot;&gt;Owning Rails Masterclass&lt;/a&gt;&lt;/li&gt;&amp;#x000A;	&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://proglangmasterclass.com/&quot;&gt;The Programming Language Masterclass&lt;/a&gt;&lt;/li&gt;&amp;#x000A;	&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://truthabouteventloops.com/&quot;&gt;The Truth About Event Loops Online Masterclass&lt;/a&gt;&lt;/li&gt;&amp;#x000A;	&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://dresssed.com/&quot;&gt;Dresssed &amp;#8211; Premium Rails Themes&lt;/a&gt;&lt;/li&gt;&amp;#x000A;	&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://copywritingforgeeks.com/&quot;&gt;Copywriting For Geeks&lt;/a&gt;&lt;/li&gt;&amp;#x000A;	&lt;li&gt;And updated &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://createyourproglang.com/&quot;&gt;Create Your Own Programming Language&lt;/a&gt;&lt;/li&gt;&amp;#x000A;&lt;/ul&gt;&amp;#x000A;&lt;p&gt;I applied a systematic approach in validating and launching each one of those. All became profitable from day one (I describe some of my techniques in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://copywritingforgeeks.com/&quot;&gt;Copywriting For Geeks bonuses&lt;/a&gt;). But my classes are the ones generating most of my revenues. This is why I have three. When you find something that works well and that you love to do, you crank it to eleven.&lt;/p&gt;&amp;#x000A;&lt;p&gt;I also created a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://codedinc.com/&quot;&gt;proper company&lt;/a&gt; and moved all of my products there.&lt;/p&gt;&amp;#x000A;&lt;h3&gt;Numbers&lt;/h3&gt;&amp;#x000A;&lt;p&gt;Those two years also marked another important milestone. I recently crossed the $250,000 mark in sales. While I don&amp;#8217;t think this is exceptional, I&amp;#8217;m extremely proud of it. Especially proud of the fact that all of it came from my products, that I created from scratch. I&amp;#8217;m now making a living entirely with the things I passionately create in my tiny home office and that feels awesome!&lt;/p&gt;&amp;#x000A;&lt;p&gt;I should also note that I took a lot of weeks and sometimes several months off instead of expanding my business. Had I been more proactive, that number could easily be higher. But I made it a rule not get into any business which would take control of my time. And allowed myself to wander without too much guilt.&lt;/p&gt;&amp;#x000A;&lt;h3&gt;It&amp;#8217;s not that hard&lt;/h3&gt;&amp;#x000A;&lt;p&gt;A lot of people will say you have to make plenty of sacrifices to have a successful business. Sacrifice your health, time with your family and everything else. I found that a business is everything you want it to be. So it &lt;b&gt;can&lt;/b&gt; be a bunch of sacrifices if you want it to be or it can be something else. That is the beauty of it all. If you want to work more, you can, and you will be compensated. Not by a pat on the back from your boss, but by more money in your pockets and more customers thanking you. It&amp;#8217;s up to you to make those decisions and part of what makes building a business such an empowering and scary adventure.&lt;/p&gt;&amp;#x000A;&lt;p&gt;If you read somewhere that you have to max 10 credit cards, gain 20 pounds and work 15 hours a day to make your business succeed, it&amp;#8217;s a lie. In fact, my finances are going great, I actually lost 20 pounds and have worked fewer than 15h per week.&lt;/p&gt;&amp;#x000A;&lt;p&gt;The hard part is not the sacrifices, but the change in mindset you need to make. Putting your stuff out there and asking people to pay you money, constantly promoting your stuff, accepting that some will dislike your products, living in the fear of losing it all and occasional self-doubt can be though challenges.&lt;/p&gt;&amp;#x000A;&lt;h3&gt;You Can Do It!&lt;/h3&gt;&amp;#x000A;&lt;p&gt;Be my own boss and not have anyone dictate my schedule or interests has been my grand professional goal for as long as I can remember. So don&amp;#8217;t be fooled in thinking it took me two years to get where I am today, it took me twelve or more.&lt;/p&gt;&amp;#x000A;&lt;p&gt;Twelve years ago, I was unable to get any job as a software developer. Sitting in my room at my parents house, I furiously coded a VB6 application with the intention of selling it. But didn&amp;#8217;t know a thing about where to go from there. Didn&amp;#8217;t know anyone who knew anything about that either. Didn&amp;#8217;t believe starting a business was possible for people with questionable social skills like me.&lt;/p&gt;&amp;#x000A;&lt;p&gt;If you&amp;#8217;re dreaming of being your own boss and creating a business too, here are a few advices:&lt;/p&gt;&amp;#x000A;&lt;ul&gt;&amp;#x000A;	&lt;li&gt;Start small (give away stuff, open source, etc.) and use your successes to build up your confidence, credibility and authority.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;Start by copying and adapting successful businesses (but make sure they are successful first).&lt;/li&gt;&amp;#x000A;	&lt;li&gt;Your new passions are sales, marketing and advertising.&lt;/li&gt;&amp;#x000A;	&lt;li&gt;Create the best products you can. I promise, people will notice how much you care someday (if they haven&amp;#8217;t already).&lt;/li&gt;&amp;#x000A;	&lt;li&gt;Be patient, but determined.&lt;/li&gt;&amp;#x000A;&lt;/ul&gt;&amp;#x000A;&lt;h3&gt;Thank You!&lt;/h3&gt;&amp;#x000A;&lt;p&gt;You know what makes or breaks a business? Customers. And boy did I found great ones!&lt;/p&gt;&amp;#x000A;&lt;p&gt;If I have anyone to thank for my success it&amp;#8217;s you who bought my products. Thank you! None of this would have been possible without your trust, feedback, patience and encouragements. You have changed my life and I can&amp;#8217;t never thank you enough for it.&lt;/p&gt;&amp;#x000A;&lt;p&gt;Most of my customers are now referred by other customers who enjoyed my products enough not only to buy and use them, but who tell others about it. That feels incredibly great!&lt;/p&gt;</description>
         <guid isPermaLink="false">tag:macournoyer.com,2013-04-10:1365643934</guid>
         <pubDate>Thu, 11 Apr 2013 01:32:14 +0000</pubDate>
      </item>
      <item>
         <title>wAsync: WebSockets with Fallbacks transports for Android, Node.js and Atmosphere</title>
         <link>https://jfarcand.wordpress.com/2013/04/04/wasync-websockets-with-fallbacks-transports-for-android-node-js-and-atmosphere/</link>
         <description>wAsync aims to make realtime apps possible in Android&amp;#8217;s mobile device and Java/JVM clients communicating with framework like Node.js and Atmosphere, blurring the differences between the different transport mechanisms. Transports supported are WebSockets, Server Side Events, Long-Polling and Http Streaming. You can download all samples from wAsync&amp;#8217;s main page. wAsync is really simple to use. For [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=jfarcand.wordpress.com&amp;#038;blog=11001265&amp;#038;post=1195&amp;#038;subd=jfarcand&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jfarcand.wordpress.com/?p=1195</guid>
         <pubDate>Thu, 04 Apr 2013 16:37:58 +0000</pubDate>
         <content:encoded><![CDATA[<p><a rel="nofollow" target="_blank" href="https://github.com/Atmosphere/wasync"><strong>wAsync</strong></a> aims to make realtime apps possible in Android&#8217;s mobile device and Java/JVM clients communicating with framework like <a rel="nofollow" target="_blank" href="http://nodejs.org/">Node.js</a> and <a rel="nofollow" target="_blank" href="https://github.com/Atmosphere/atmosphere">Atmosphere</a>, blurring the differences between the different transport mechanisms. Transports supported are WebSockets, Server Side Events, Long-Polling and Http Streaming. You can <a rel="nofollow" target="_blank" href="http://search.maven.org/#search%7Cga%7C1%7Cwasync">download all samples</a> from wAsync&#8217;s main page.</p>
<p>wAsync is really simple to use. For this blog, let&#8217;s write a simple chat using <a rel="nofollow" target="_blank" href="http://nodejs.org/">Node.js</a>. First, let&#8217;s define a super simple Node.js WebSockets server with static files support. I&#8217;m dropping the entire code here assumining you know how Node.js works.</p>
 
<p>Now let&#8217;s write a wAsync&#8217;s Android client that can communiate with this server. Graphically, it will looks like</p>
<p><a rel="nofollow" target="_blank" href="https://jfarcand.files.wordpress.com/2013/04/screen-shot-2013-04-04-at-10-49-26-am.png"><img class="alignnone size-medium wp-image-1199" alt="Screen Shot 2013-04-04 at 10.49.26 AM" src="https://jfarcand.files.wordpress.com/2013/04/screen-shot-2013-04-04-at-10-49-26-am.png?w=300&#038;h=225"/></a></p>
<p>Pretty simple Android application</p>
 
<p>As with for the Node.js server, I assume you are familiar with Android development.</p>
 
<p>Now let&#8217;s explain the code. First, we create a new client (line 19)</p>
<pre>Client client = ClientFactory.getDefault().newClient();</pre>
<p>Next, let&#8217;s create a Request to send:</p>
<pre>RequestBuilder request = client.newRequestBuilder()
   .method(Request.METHOD.GET)
   .uri(serverIpAddress)</pre>
<p>This demo is using JSON, and we want to use <a rel="nofollow" target="_blank" href="https://github.com/FasterXML/">Jackson</a> for marshalling/unmarshalling Java POJO. So just we define a really simple Encoder:</p>
<pre>.encoder(new Encoder&lt;Data, String&gt;() {
           @Override
           public String encode(Data data) {
              try {
                return mapper.writeValueAsString(data)
              } catch (IOException e) {
                throw new RuntimeException(e);
              }
           }
})</pre>
<p>This code will be invoked before the message is sent to Node.js and will covert the POJO to JSON. Next we define a decoder that will handle Node.js&#8217;s JSON response. We only decode messages, we aren&#8217;t interested by other events wAsync propagates:</p>
<pre>.decoder(new Decoder&lt;String, Data&gt;() {
           @Override
           public Data decode(Transport.EVENT_TYPE type, 
                              String data) {
 
             if (type.equals(Transport.EVENT_TYPE.MESSAGE)) {
                try {
                   return mapper.readValue(data, Data.class);
                } catch (IOException e) {
                }
             }
             return null;        
})</pre>
<p>Next, we create our Socket to Node.js (line 49)</p>
<pre>final org.atmosphere.wasync.Socket socket = client.create();</pre>
<p>And define two functions, one for handling the message, one for handling unexpected exceptions, and finally open the Socket</p>
<pre>socket.on("message", new Function&lt;Data&gt;() {
           @Override
           public void on(final Data t) {
               uiHandler.post(new Runnable() {
               @Override
               public void run() {
                 Date d = new Date(t.getTime());
                 tv.append("Author " + t.getAuthor() + "@ " 
                   + d.getHours() + ":" + d.getMinutes() + ": "
                   + t.getMessage() + "&#92;n");
                  }
              });
            }
            }).on(new Function&lt;Throwable&gt;() {
                @Override
                public void on(Throwable t) {
                    tv.setText("ERROR 3: " + t.getMessage());
                    t.printStackTrace();
                }
        }).open(request.build());</pre>
<p>Finally, we just display what we are receiving on the Android screen:</p>
<pre>  bt.setOnClickListener(new OnClickListener() {

           String name = null;
           public void onClick(View v) {
               try {
                 EditText et = (EditText) findViewById(R.id.EditText01);
                 String str = et.getText().toString();
                 if (name == null) {
                   name = str;
                 }
                 socket.fire(new Data(name, str));
                 et.setText("");
                 Log.d("Client", "Client sent message");
               } catch (Throwable e) {
                 tv.setText("ERROR " + e.getMessage());
                 e.printStackTrace();
                }
            }
       });</pre>
<p>That&#8217;s all. If you want to chat between Android and a browser, you can <a rel="nofollow" target="_blank" href="https://gist.github.com/jfarcand/5311355">install this HTML file</a>, which will use atmosphere.js, the Atmosphere Framework&#8217;s client side to communicate with Node.js. You can use the Javascript WebSocket API directly as well, but with atmosphere.js, <strong>you get transports fallback support for free</strong>.</p>
<p>Now let&#8217;s write the same client, but this time using the <a rel="nofollow" target="_blank" href="http://async-io.org">Atmosphere Framework</a> instead of Node.js. wAsync supports natively the Atmosphere protocol with fallback transports like long-polling, so we can tell wAsync to use long-polling in case the server doesn&#8217;t support websockets. For the server, instead of Node.js, we use the <a rel="nofollow" target="_blank" href="https://github.com/Atmosphere/nettosphere">NettoSphere</a> server.</p>
 
<p>The full code can be <a rel="nofollow" target="_blank" href="https://github.com/Atmosphere/wasync/blob/master/samples/chat/src/main/java/org/atmosphere/wasync/samples/wAsyncChat.java#L37">browsed here</a>. The two differences are:</p>
<pre>AtmosphereClient client =
   ClientFactory.getDefault().newClient(AtmosphereClient.class);</pre>
<p>Here we create a specialized client, which will allow use to set some Atmosphere&#8217;s protocol specific property:</p>
<pre>RequestBuilder request = client.newRequestBuilder()
   .method(Request.METHOD.GET)
   .uri(serverIpAddress)
   .trackMessageLength(true)
      [...]
   .transport(Request.TRANSPORT.WEBSOCKET)
   .transport(Request.TRANSPORT.LONG_POLLING);
</pre>
<p>The track message lenght feature make sure two JSON messages are never delivered to the function as a single message. To supports that with Node.js, we would have needed to install <a rel="nofollow" target="_blank" href="http://socket.io/">Socket.IO</a>.  </p>
<p>What&#8217;s next with wAsync? Add support for both <a rel="nofollow" target="_blank" href="http://socket.io/">Socket.IO</a> and <a rel="nofollow" target="_blank" href="https://github.com/sockjs/sockjs-client">SocksJs</a> protocol. Want to contribute? <a rel="nofollow" target="_blank" href="https://github.com/Atmosphere/wasync">Fork us</a>! For more information, ping me on <a rel="nofollow" target="_blank" href="http://twitter.com/jfarcand">Twitter</a> or follow the <a rel="nofollow" target="_blank" href="http://twitter.com/atmo_framework">Atmosphere Framework</a>! </p>
<p><strong>The wAsync developpement is powered by <a rel="nofollow" target="_blank" href="http://async-io.org">Async-IO.org</a>, the company behind the Atmosphere Framework!</strong></p><br />  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jfarcand.wordpress.com/1195/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jfarcand.wordpress.com/1195/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=jfarcand.wordpress.com&#038;blog=11001265&#038;post=1195&#038;subd=jfarcand&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/9ae00d1d5f0b4479065431c13ca54013?s=96&amp;amp;d=identicon&amp;amp;r=G">
            <media:title type="html">jfarcand</media:title>
         </media:content>
         <media:content medium="image" url="https://jfarcand.files.wordpress.com/2013/04/screen-shot-2013-04-04-at-10-49-26-am.png?w=300">
            <media:title type="html">Screen Shot 2013-04-04 at 10.49.26 AM</media:title>
         </media:content>
      </item>
      <item>
         <title>Snakes on the NettoSphere!</title>
         <link>https://jfarcand.wordpress.com/2013/03/26/snakes-on-the-nettosphere/</link>
         <description>Want to build a game using Atmosphere? Take a look at Building Games using WebSocket, Server-Side Events and Long-Polling with the Netty Framework and Atmosphere, from the Async-IO.org team.&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=jfarcand.wordpress.com&amp;#038;blog=11001265&amp;#038;post=1192&amp;#038;subd=jfarcand&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jfarcand.wordpress.com/?p=1192</guid>
         <pubDate>Tue, 26 Mar 2013 15:33:00 +0000</pubDate>
         <content:encoded><![CDATA[<h2>Want to build a game using Atmosphere?</h2>
<p>Take a look at <strong><a rel="nofollow" target="_blank" href="http://async-io.org/games.html">Building Games using WebSocket, Server-Side Events and Long-Polling with the Netty Framework and Atmosphere</a>, </strong>from the Async-IO.org team.</p><br />  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jfarcand.wordpress.com/1192/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jfarcand.wordpress.com/1192/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=jfarcand.wordpress.com&#038;blog=11001265&#038;post=1192&#038;subd=jfarcand&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/9ae00d1d5f0b4479065431c13ca54013?s=96&amp;amp;d=identicon&amp;amp;r=G">
            <media:title type="html">jfarcand</media:title>
         </media:content>
      </item>
      <item>
         <title>Clojure: from zero to grok</title>
         <link>http://thecarefulprogrammer.blogspot.com/2013/03/clojure-from-zero-to-grok.html</link>
         <description>&lt;div dir=&quot;ltr&quot;&gt;What's often missing when trying to learn a programming language is something between the 10 thousand feet overview and the medium to high tutorial assuming you've bootstrap yourself.&lt;/div&gt;&lt;div dir=&quot;ltr&quot;&gt;Eric Normand is offering insanely affordable Clojure learning videos. It's a Kickstarter campaign with only 6 hours left!&lt;/div&gt;&lt;div dir=&quot;ltr&quot;&gt;You can donate in all confidence, the main goal has been reached, but we need your help to reach the first stretch goal.&lt;/div&gt;&lt;div dir=&quot;ltr&quot;&gt;If you've ever wondered what all the hoopla about Clojure is, you can find out for a few bucks.&lt;/div&gt;&lt;div dir=&quot;ltr&quot;&gt;You'll learn enough to put it aside if you don't like it, or if you're lucky, you'll ignite a passion!&lt;/div&gt;&lt;div dir=&quot;ltr&quot;&gt;Click on the link. Do it now 8)&lt;/div&gt;&lt;div dir=&quot;ltr&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kickstarter.com/projects/376627045/lispcast-introduction-to-clojure-videos&quot;&gt;LispCast&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kickstarter.com/projects/376627045/lispcast-introduction-to-clojure-videos&quot;&gt; &lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kickstarter.com/projects/376627045/lispcast-introduction-to-clojure-videos&quot;&gt;introduction&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kickstarter.com/projects/376627045/lispcast-introduction-to-clojure-videos&quot;&gt; &lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kickstarter.com/projects/376627045/lispcast-introduction-to-clojure-videos&quot;&gt;to&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kickstarter.com/projects/376627045/lispcast-introduction-to-clojure-videos&quot;&gt; &lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kickstarter.com/projects/376627045/lispcast-introduction-to-clojure-videos&quot;&gt;Clojure&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kickstarter.com/projects/376627045/lispcast-introduction-to-clojure-videos&quot;&gt; videos&lt;/a&gt;&lt;/div&gt;&lt;div dir=&quot;ltr&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div dir=&quot;ltr&quot;&gt;&lt;span style=&quot;color:red;&quot;&gt;Update July 25th 2013&lt;/span&gt;&lt;/div&gt;&lt;div dir=&quot;ltr&quot;&gt;The videos are now available on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://www.bitcast.io/b/lispcast-introduction-to-clojure&quot;&gt;Bitcast.io&lt;/a&gt;&lt;/div&gt;</description>
         <author>noreply@blogger.com (The Careful Programmer)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8932258692847145228.post-3207330882701858390</guid>
         <pubDate>Thu, 14 Mar 2013 11:57:00 +0000</pubDate>
      </item>
      <item>
         <title>Can I make a living out of my open source projects in 5 months?</title>
         <link>https://jfarcand.wordpress.com/2013/03/04/can-i-make-a-living-out-of-my-open-source-projects-in-5-months/</link>
         <description>I&amp;#8217;m in the open source world for the last 12 years&amp;#8230;it all started in 2002 as a member of the Tomcat team, then in 2005 I have created the Grizzly framework, lead the team that open sourced GlassFish, released the Grizzly Comet Framework, created the Atmosphere Framework in 2007 and its related projects. I also created the [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=jfarcand.wordpress.com&amp;#038;blog=11001265&amp;#038;post=1182&amp;#038;subd=jfarcand&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jfarcand.wordpress.com/?p=1182</guid>
         <pubDate>Mon, 04 Mar 2013 19:56:25 +0000</pubDate>
         <content:encoded><![CDATA[<p>I&#8217;m in the open source world for the last 12 years&#8230;it all started in 2002 as a member of the <a rel="nofollow" target="_blank" href="http://web.archiveorange.com/archive/v/2dGxzW0NpzAxlezGWFCF">Tomcat team</a>, then in 2005 I have created the <a rel="nofollow" target="_blank" href="https://jfarcand.wordpress.com/2005/06/16/grizzly-an-http-listener-using-java-technology-nio-2/">Grizzly framework</a>, lead the team that open sourced <a rel="nofollow" target="_blank" href="http://glassfish.markmail.org/search/?q=#query:%20from%3A%22jfarcand%40dev.java.net%22+page:1+state:facets">GlassFish</a>, released the <a rel="nofollow" target="_blank" href="https://jfarcand.wordpress.com/2006/07/06/the-grizzly-comet-or-why-space-shuttle-discovery-launch-was-delayed/">Grizzly Comet Framework</a>, created the <a rel="nofollow" target="_blank" href="https://github.com/Atmosphere/atmosphere">Atmosphere Framework</a> in 2007 and its <a rel="nofollow" target="_blank" href="https://github.com/Atmosphere">related project</a>s. I also created the <a rel="nofollow" target="_blank" href="http://www.ning.com/code/2010/03/introducing-nings-asynchronous-http-client-library/">AsyncHttpClient</a> library in 2009 and recently designed and implemented the <a rel="nofollow" target="_blank" href="http://blog.wordnik.com/introducing-swaggersocket-a-rest-over-websocket-protocol">Swagger Socket Protocol</a> in 2012. I think I can say I have a little experience with <a rel="nofollow" target="_blank" href="http://markmail.org/search/?q=jfarcand">open source development and management</a>  <span class='wp-smiley wp-emoji wp-emoji-smile' title=':-)'>:-)</span></p>
<p><a rel="nofollow" target="_blank" href="https://jfarcand.files.wordpress.com/2013/03/blog.jpg"><img class="alignnone size-medium wp-image-1170" title="IMG_1976" alt="" src="https://jfarcand.files.wordpress.com/2013/03/blog.jpg?w=300&#038;h=225"/></a></p>
<p>All of that work was done under several companies umbrella: Sun Microsystems, <a rel="nofollow" target="_blank" href="http://ning.com">Ning</a>, <a rel="nofollow" target="_blank" href="http://sonatype.com">Sonatype</a> and more recently <a rel="nofollow" target="_blank" href="http://helloreverb.com">Reverb</a>. In all cases, I was allowed to work on those frameworks because they were used internally. For example, I&#8217;ve spent the last 18 months <a rel="nofollow" target="_blank" href="http://www.helloreverb.com/#developers">working at Reverb</a>, significantly improving the Atmosphere Framework and even deploying it on <a rel="nofollow">Wall Street Journal</a>, one of the biggest/live deployment I&#8217;ve ever made so far supporting WebSockets and Internet Explorer 6/7/8/9 at the same time. <strong>Phew!!!</strong></p>
<p>During that 18 months at Reverb, I was finally able to release the <a rel="nofollow" target="_blank" href="https://jfarcand.wordpress.com/2012/09/04/atmosphere-1-0-the-asynchronous-javascriptjava-framework-now-available/">1.0 version of Atmosphere</a>, which was a major accomplishment for me after working on the framework for the last 4 years. Then, the popularity of the framework sky rocked and everything jumped: download are almost 200% up every months, <a rel="nofollow" target="_blank" href="https://github.com/Atmosphere/atmosphere">Github &#8220;watcher&#8221; doubled</a>, mailing list is now <a rel="nofollow" target="_blank" href="https://groups.google.com/group/atmosphere-framework?pli=1">close to 500 users</a>, <a rel="nofollow" target="_blank" href="https://twitter.com/atmo_framework">Twitter account reached 1100 followers</a> and <a rel="nofollow" target="_blank" href="http://atmosphere.markmail.org/">emails traffic are stable months after months</a>. More important, in December I&#8217;ve started getting requests for professionnal services with Atmosphere, contract support, etc.</p>
<p>So, with the current Atmosphere success, I&#8217;ve had a hard decision to take: work at Reverb and let the Atmosphere&#8217;s community grow and &#8220;leave by itself&#8221;,  or resign from Reverb and try to build a company to support Atmosphere. Last January was difficult for me as I was constantly under fire by having to work on Atmosphere and at the same time help scaling the Reverb&#8217;s platform. Not a nice situation!</p>
<p>So, I&#8217;ve decided to tale a leave on absent from Reverb and try to build my own company around the Atmosphere Framework, called <a rel="nofollow" target="_blank" href="http://async-io.org/">Async-IO.org</a>. The website is live and the traffic is already passing 500 unique hit per day, so this is positive&#8230;but, <strong>It&#8217;s a major challenge for the following reasons</strong>:</p>
<ul>
<li><span style="line-height:12.994791030884px;">I cannot stay unemployed for several months. Hence I allocate myself <strong>5 months</strong> to succeed with my crazy decision. I know it&#8217;s a very  small amount of time, but that&#8217;s all I can allocate.</span></li>
<li>I&#8217;m based in Canada (in Québec), not in California or in a city like London or Berlin where I can have funds from Venture Capitals Companies. Montréal is unfortunately stuck in the early 200o where IBM and Microsoft rules the city, so no luck on that side as well!</li>
<li>I want to try to do everything all by myself, from <a rel="nofollow" target="_blank" href="http://async-io.org">designing the website</a> (thanks Github) and learn from existing open source projects that succeeded. I&#8217;m event sketching the official logo this week!</li>
<li>I don&#8217;t want to spend large amount of money on infrastructure. Instead, <strong>I would like to reward people that have been working with me in Atmosphere</strong> as soon as I can. But I need a solid foundation before I can do that.</li>
<li>I don&#8217;t have a large corporation financing my work. Since Atmosphere compete with framework like Socket.IO/Node.js, Vert.x and Play 2 (<strong>they are all powered by a big company</strong>), it&#8217;s a real challenge!</li>
<li>Atmosphere work with all browsers, mobile browsers and Java WebServers, and from version released sometimes 5 years ago. The testing matrix here is really complex and right now I  strongly need to rely on the community to help, and in return I&#8217;ve adopted a short release cycle to make every body happy. That way too much time consuming so I need to improve that situation.</li>
<li>Continue being active with the community like I have been for the last 4 years!</li>
</ul>
<p><strong>Now, after reading this you can call me crazy and I would fully understand</strong>! Interested to help? Pretty simple:</p>
<ul>
<li><span style="line-height:12.994791030884px;">Follow <a rel="nofollow" target="_blank" href="https://twitter.com/asyncio">Async-IO.org</a>, <a rel="nofollow" target="_blank" href="https://twitter.com/atmo_framework">Atmosphere</a> or <a rel="nofollow" target="_blank" href="https://twitter.com/jfarcand">myself</a> on Twitter</span></li>
<li><a rel="nofollow" target="_blank" href="https://github.com/Atmosphere/atmosphere">Follow/Watch/Start the Atmosphere Framework on Github</a>. The project is on page 2 for most popular framework, and being on the first would help.</li>
<li>If you are using Atmosphere, consider buying an annual <a rel="nofollow" target="_blank" href="http://async-io.org/subscription.html">subscription</a> or get in house <span style="color:#0000ee;"><span style="text-decoration:underline;">training</span></span> with Async-IO.org.</li>
</ul>
<p>So, for the <strong>next 5 months I will use this blog</strong> to share my experience with this colossal adventure! Stay tuned!</p><br />  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jfarcand.wordpress.com/1182/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jfarcand.wordpress.com/1182/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=jfarcand.wordpress.com&#038;blog=11001265&#038;post=1182&#038;subd=jfarcand&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/9ae00d1d5f0b4479065431c13ca54013?s=96&amp;amp;d=identicon&amp;amp;r=G">
            <media:title type="html">jfarcand</media:title>
         </media:content>
         <media:content medium="image" url="https://jfarcand.files.wordpress.com/2013/03/blog.jpg?w=300">
            <media:title type="html">IMG_1976</media:title>
         </media:content>
      </item>
      <item>
         <title>Redline Smalltalk: so long and thanks for all the fish</title>
         <link>http://thecarefulprogrammer.blogspot.com/2013/02/redline-smalltalk-so-long-and-thanks.html</link>
         <description>&lt;p dir=&quot;ltr&quot;&gt;This is the last push for the Redline Smalltalk indiegogo campaign.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;I give my heartfelt thanks to everybody who lent a hand, be it a donation or getting the word out.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;We got an amazing spectrum of persons helping, from friends who donated so I would stop pestering them about Redline to pillars of our field like Grady Booch.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;From the Redliners emerge these qualities: kindness, excellent programming chops, and a non-negligible amount of geekness 8)&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;To those who already donated: Please push out our campaign far and wide with your communication canals. Challenge your friends and coworkers to match or exceed your donation. Make a friendly competition out of it. Get your company to make a corporate donation.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;To those who have yet to donate:&amp;#160; be kind, be excellent, be a really hoopy frood who knows where his or her towel is. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://igg.me/p/263169/x/1780403&quot;&gt;Be a Redliner!&lt;/a&gt;&lt;/p&gt;</description>
         <author>noreply@blogger.com (The Careful Programmer)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8932258692847145228.post-1187053841681684634</guid>
         <pubDate>Mon, 25 Feb 2013 21:41:00 +0000</pubDate>
      </item>
      <item>
         <title>Typing as seen by Fanboys</title>
         <link>http://lovehateubuntu.blogspot.com/2013/02/typing-as-seen-by-fanboys.html</link>
         <description>Thought this was kind of funny:&lt;br/&gt;&lt;br/&gt;&lt;img src=&quot;http://www.robbritton.com/wp-content/uploads/languages.png&quot; alt=&quot;&quot;/&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/UbuntuALove/hateRelationship/~4/Z3qrixNwKuU&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <author>Rob Britton</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-165807313160822069.post-1574730391409826941</guid>
         <pubDate>Thu, 21 Feb 2013 11:59:00 +0000</pubDate>
      </item>
      <item>
         <title>So I made over 52,000 mistakes today</title>
         <link>http://feedproxy.google.com/~r/SolutiousPerformanceBlog/~3/fGwMz7DMZeg/</link>
         <description>&lt;p&gt;Earlier today I &lt;a rel=&quot;nofollow&quot;&gt;updated&lt;/a&gt; the net-ssh family of Ruby gems and I broke one of the rules of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://semver.org/&quot;&gt;semantic versioning&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specifically, rule #8:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;8. Minor version Y (x.Y.z | x &amp;gt; 0) MUST be incremented if new,
backwards compatible functionality is introduced to the public API.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I broke &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tickets.opscode.com/browse/CHEF-3835&quot;&gt;Chef&lt;/a&gt;. I broke &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/mitchellh/vagrant/issues/1355&quot;&gt;Vagrant&lt;/a&gt;. net-ssh is pretty far upstream so in just a couple hours there were over 52,000 installs of the offending gems, &lt;em&gt;much to the chagrin of sysadmins and devops folks everywhere.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: If you have any of the following gems installed on your system, you should remove them: net-ssh-gateway-1.1.1, net-ssh-gateway-1.1.2, net-ssh-multi-1.1.1, net-ssh-multi-1.1.2, net-scp-1.0.5, and net-scp-1.0.6. See my &lt;a rel=&quot;nofollow&quot;&gt;previous post&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;The err of my ways&lt;/h2&gt;

&lt;p&gt;I released three gems with the PATCH incremented instead of the MINOR version number. This makes a huge difference downstream because of the &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://twiddlewakka.com/&quot;&gt;twiddle-wakka&lt;/a&gt;&quot;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Meanwhile, in chef.gemspec
s.add_dependency &quot;net-ssh&quot;, &quot;~&amp;gt; 2.2.2&quot;
s.add_dependency &quot;net-ssh-multi&quot;, &quot;~&amp;gt; 1.1.0&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;~&amp;gt;&lt;/code&gt; will &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://robots.thoughtbot.com/post/2508037841/rubys-pessimistic-operator&quot;&gt;fuzzily match&lt;/a&gt; any gems less than &lt;code&gt;1.2&lt;/code&gt; but greater than or equal to &lt;code&gt;1.1.0&lt;/code&gt;. This feature strikes a balance between &lt;code&gt;&quot;&amp;gt;= 1.1.0&quot;&lt;/code&gt; (which is too loose) and &lt;code&gt;&quot;= 1.1.0&quot;&lt;/code&gt; (which is too strict). The problem is that net-ssh-multi-1.1.2 &lt;em&gt;changed the net-ssh dependency to 2.6.5&lt;/em&gt; which made Chef uninstallable due to the conflict between chef.gemspec and net-ssh-multi.gemspec (2.2.x vs 2.6.5). Feels bad man.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So if I ruined your day, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://onetimesecret.com/feedback&quot;&gt;send me&lt;/a&gt; your email, Twitter, Skype, or phone number and I will reply with a personal apology.&lt;/strong&gt;&lt;/p&gt;

&lt;p style=&quot;color:#999;font-size:80%;&quot;&gt;(Offer expires Feb 12th at 07:59 UTC).&lt;/p&gt;


&lt;h2&gt;On a more positive note&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A big thank you to everyone who emailed, tweeted, and opened issues to help get this resolved quickly.&lt;/strong&gt; Although regrettable, this is the only significant issue with net-ssh and friends in the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://solutious.com/blog/2009/06/19/net-ssh-repository/&quot;&gt;4 years&lt;/a&gt; (and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://rubygems.org/profiles/delano&quot;&gt;18M downloads&lt;/a&gt;) that I've been maintaining them. I feel pretty good about that.&lt;/p&gt;

&lt;p&gt;Incidentally, I updated the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/net-ssh/net-ssh/blob/v2.6.5/THANKS.txt&quot;&gt;THANKS.txt&lt;/a&gt; that's part of every net-ssh release today too. I added the names of all the people who contributed code since I've been maintaining it. Here they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GOTOU Yuuzou&lt;/li&gt;
&lt;li&gt;Guillaume Marçais&lt;/li&gt;
&lt;li&gt;Daniel Berger&lt;/li&gt;
&lt;li&gt;Chris Andrews&lt;/li&gt;
&lt;li&gt;Lee Jensen&lt;/li&gt;
&lt;li&gt;Hiroshi Nakamura&lt;/li&gt;
&lt;li&gt;Andreas Wolff&lt;/li&gt;
&lt;li&gt;mhuffnagle&lt;/li&gt;
&lt;li&gt;ohrite&lt;/li&gt;
&lt;li&gt;iltempo&lt;/li&gt;
&lt;li&gt;nagachika&lt;/li&gt;
&lt;li&gt;Nobuhiro IMAI&lt;/li&gt;
&lt;li&gt;arturaz&lt;/li&gt;
&lt;li&gt;dubspeed&lt;/li&gt;
&lt;li&gt;Andy Brody&lt;/li&gt;
&lt;li&gt;Marco Sandrini&lt;/li&gt;
&lt;li&gt;Ryosuke Yamazaki&lt;/li&gt;
&lt;li&gt;muffl0n&lt;/li&gt;
&lt;li&gt;pcn&lt;/li&gt;
&lt;li&gt;musybite&lt;/li&gt;
&lt;li&gt;Mark Imbriaco&lt;/li&gt;
&lt;li&gt;Joel Watson&lt;/li&gt;
&lt;li&gt;Woon Jung&lt;/li&gt;
&lt;li&gt;Edmund Haselwanter&lt;/li&gt;
&lt;li&gt;robbebob&lt;/li&gt;
&lt;li&gt;Daniel Pittman&lt;/li&gt;
&lt;li&gt;Markus Roberts&lt;/li&gt;
&lt;li&gt;Gavin Brock&lt;/li&gt;
&lt;li&gt;Rich Lane&lt;/li&gt;
&lt;li&gt;Lee Marlow&lt;/li&gt;
&lt;li&gt;xbaldauf&lt;/li&gt;
&lt;li&gt;Delano Mandelbaum&lt;/li&gt;
&lt;li&gt;Miklós Fazekas&lt;/li&gt;
&lt;li&gt;Andy Lo-A-Foe&lt;/li&gt;
&lt;li&gt;Jason Weathered&lt;/li&gt;
&lt;li&gt;Hans de Graaff&lt;/li&gt;
&lt;li&gt;Travis Reeder&lt;/li&gt;
&lt;li&gt;Akinori MUSHA&lt;/li&gt;
&lt;li&gt;Alex Peuchert&lt;/li&gt;
&lt;li&gt;Daniel Azuma&lt;/li&gt;
&lt;li&gt;Will Bryant&lt;/li&gt;
&lt;li&gt;Gerald Talton&lt;/li&gt;
&lt;li&gt;ckoehler&lt;/li&gt;
&lt;li&gt;Karl Varga&lt;/li&gt;
&lt;li&gt;Denis Bernard&lt;/li&gt;
&lt;li&gt;Steven Hazel&lt;/li&gt;
&lt;li&gt;Alex Holems&lt;/li&gt;
&lt;li&gt;Andrew Babkin&lt;/li&gt;
&lt;li&gt;Bob Cotton&lt;/li&gt;
&lt;li&gt;Yanko Ivanov&lt;/li&gt;
&lt;li&gt;Angel N. Sciortino&lt;/li&gt;
&lt;li&gt;arilerner@mac.com&lt;/li&gt;
&lt;li&gt;David Dollar&lt;/li&gt;
&lt;li&gt;Timo Gatsonides&lt;/li&gt;
&lt;li&gt;Matthew Todd&lt;/li&gt;
&lt;li&gt;Brian Candler&lt;/li&gt;
&lt;li&gt;Francis Sullivan&lt;/li&gt;
&lt;li&gt;James Rosen&lt;/li&gt;
&lt;li&gt;Mike Timm&lt;/li&gt;
&lt;li&gt;guns&lt;/li&gt;
&lt;li&gt;devrandom&lt;/li&gt;
&lt;li&gt;kachick&lt;/li&gt;
&lt;li&gt;Pablo Merino&lt;/li&gt;
&lt;li&gt;thedarkone&lt;/li&gt;
&lt;li&gt;czarneckid&lt;/li&gt;
&lt;li&gt;jbarnette&lt;/li&gt;
&lt;li&gt;watsonian&lt;/li&gt;
&lt;li&gt;Grant Hutchins&lt;/li&gt;
&lt;li&gt;Michael Schubert&lt;/li&gt;
&lt;li&gt;mtrudel&lt;/li&gt;
&lt;li&gt;and of course, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/jamis&quot;&gt;Jamis Buck&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I know I'm not the only one who appreciates your time and effort. Thank you for making net-ssh better!&lt;/p&gt;
&lt;img src=&quot;http://feeds.feedburner.com/~r/SolutiousPerformanceBlog/~4/fGwMz7DMZeg&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">http://solutious.com/blog/2013/02/06/so-i-made-52000-mistakes-today</guid>
         <pubDate>Wed, 06 Feb 2013 00:00:00 +0000</pubDate>
      </item>
      <item>
         <title>All future Net-SSH gem releases will now be signed (as of 2.6.5)</title>
         <link>http://feedproxy.google.com/~r/SolutiousPerformanceBlog/~3/tmFhVN0d-F0/</link>
         <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Updated (2013-02-06@13:00PST): Doh. Some previously updated gems were broken. See below. &lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In response to the &lt;a rel=&quot;nofollow&quot;&gt;recent vulnerabilities&lt;/a&gt; with rubygems.org, I spent the morning signing and re-releasing the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/net-ssh&quot;&gt;Net-SSH family&lt;/a&gt; of ruby gems. The discussion on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://guides.rubygems.org/publishing/#gem-security&quot;&gt;how to properly handle code signing&lt;/a&gt; is still ongoing so this could be just an interrim measure; however, the severity of the problem makes it necessary to have a solution in place now.&lt;/p&gt;

&lt;h2&gt;Current Signed Releases&lt;/h2&gt;

&lt;p&gt;As of today, all net-ssh releases will be &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://docs.rubygems.org/read/chapter/21&quot;&gt;signed&lt;/a&gt; and verifiable with the public certificate at the end of this post.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;net-ssh 2.6.5+&lt;/strong&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://rubygems.org/gems/net-ssh/versions/2.6.5&quot;&gt;rubygems&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/net-ssh/net-ssh/tree/v2.6.5&quot;&gt;github&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;net-scp 1.1.0+&lt;/strong&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://rubygems.org/gems/net-scp/versions/1.1.0&quot;&gt;rubygems&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/net-ssh/net-scp/tree/v1.1.0&quot;&gt;github&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;net-sftp 2.2.0&lt;/strong&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://rubygems.org/gems/net-sftp/versions/2.2.0&quot;&gt;rubygems&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/net-ssh/net-sftp/tree/v2.2.0&quot;&gt;github&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;net-ssh-gateway 1.2.0&lt;/strong&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://rubygems.org/gems/net-ssh-gateway/versions/1.2.0&quot;&gt;rubygems&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/net-ssh/net-ssh-gateway/tree/v1.2.0&quot;&gt;github&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;net-ssh-multi 1.2.0&lt;/strong&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://rubygems.org/gems/net-ssh-multi/versions/1.2.0&quot;&gt;rubygems&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/net-ssh/net-ssh-multi/tree/v1.2.0&quot;&gt;github&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Installation&lt;/h2&gt;

&lt;p&gt;You can still &lt;code&gt;gem install net-ssh&lt;/code&gt; like you do already but if you want to verify the gem is authentic, you will now be able to run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gem install net-ssh -P HighSecurity
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To do this, you need to add the public certificate to local trust gem certs (otherwise you'll see an error like &lt;code&gt;&quot;Couldn't verify data signature&quot;&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ curl -O https://raw.github.com/net-ssh/net-ssh/master/gem-public_cert.pem
$ gem cert --add gem-public_cert.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Broken versions&lt;/h2&gt;

&lt;p&gt;The following gems were broken:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;net-ssh-gateway-1.1.1&lt;/li&gt;
&lt;li&gt;net-ssh-gateway-1.1.2&lt;/li&gt;
&lt;li&gt;net-ssh-multi-1.1.1&lt;/li&gt;
&lt;li&gt;net-ssh-multi-1.1.2&lt;/li&gt;
&lt;li&gt;net-scp-1.0.5&lt;/li&gt;
&lt;li&gt;net-scp-1.0.6&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;They've been yanked from rubygems.org but if already have them on your system, you will need to remove them manually.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gem uninstall -v 1.1.1 net-ssh-multi
$ gem uninstall -v 1.1.2 net-ssh-multi
$ gem uninstall -v 1.1.1 net-ssh-gateway
$ gem uninstall -v 1.1.2 net-ssh-gateway
$ gem uninstall -v 1.0.5 net-scp
$ gem uninstall -v 1.0.6 net-scp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have any trouble let me know at net-ssh@solutious.com.&lt;/p&gt;

&lt;h2&gt;Public certificate&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;
-----BEGIN CERTIFICATE-----
MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMQ8wDQYDVQQDDAZkZWxh
bm8xGTAXBgoJkiaJk/IsZAEZFglzb2x1dGlvdXMxEzARBgoJkiaJk/IsZAEZFgNj
b20wHhcNMTMwMjA2MTE1NzQ1WhcNMTQwMjA2MTE1NzQ1WjBBMQ8wDQYDVQQDDAZk
ZWxhbm8xGTAXBgoJkiaJk/IsZAEZFglzb2x1dGlvdXMxEzARBgoJkiaJk/IsZAEZ
FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDg1hMtl0XsMuUK
AKTgYWv3gjj7vuEsE2EjT+vyBg8/LpqVVwZziiaebJT9IZiQ+sCFqbiakj0b53pI
hg1yOaBEmH6/W0L7rwzqaRV9sW1eJs9JxFYQCnd67zUnzj8nnRlOjG+hhIG+Vsij
npsGbt28pefuNZJjO5q2clAlfSniIIHfIsU7/StEYu6FUGOjnwryZ0r5yJlr9RrE
Gs+q0DW8QnZ9UpAfuDFQZuIqeKQFFLE7nMmCGaA+0BN1nLl3fVHNbLHq7Avk8+Z+
ZuuvkdscbHlO/l+3xCNQ5nUnHwq0ADAbMLOlmiYYzqXoWLjmeI6me/clktJCfN2R
oZG3UQvvAgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFMSJOEtHzE4l0azv
M0JK0kKNToK1MAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAtOdE73qx
OH2ydi9oT2hS5f9G0y1Z70Tlwh+VGExyfxzVE9XwC+iPpJxNraiHYgF/9/oky7ZZ
R9q0/tJneuhAenZdiQkX7oi4O3v9wRS6YHoWBxMPFKVRLNTzvVJsbmfpCAlp5/5g
ps4wQFy5mibElGVlOobf/ghqZ25HS9J6kd0/C/ry0AUtTogsL7TxGwT4kbCx63ub
3vywEEhsJUzfd97GCABmtQfRTldX/j7F1z/5wd8p+hfdox1iibds9ZtfaZA3KzKn
kchWN9B6zg9r1XMQ8BM2Jz0XoPanPe354+lWwjpkRKbFow/ZbQHcCLCq24+N6b6g
dgKfNDzwiDpqCA==
-----END CERTIFICATE-----
&lt;/code&gt;&lt;/pre&gt;

&lt;img src=&quot;http://feeds.feedburner.com/~r/SolutiousPerformanceBlog/~4/tmFhVN0d-F0&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">http://solutious.com/blog/2013/02/06/net-ssh-gem-code-signed</guid>
         <pubDate>Wed, 06 Feb 2013 00:00:00 +0000</pubDate>
      </item>
      <item>
         <title>Why Smalltalk?</title>
         <link>http://thecarefulprogrammer.blogspot.com/2013/02/why-smalltalk.html</link>
         <description>&lt;div style=&quot;text-align:justify;&quot;&gt;Why would anybody be interested in an old language like Smalltalk?&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;I know quite a few of my readers are,&amp;nbsp;among&amp;nbsp;other languages I am sure, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.scala-lang.org/&quot;&gt;Scala&lt;/a&gt; programmers. I quite like Scala and its balance of OO and functional programming on a serving of static typing with inference. Scala has been the perfect&amp;nbsp;vehicle&amp;nbsp;for me to grok functional programming.&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;I am fond of learning different languages who makes different trade-offs and are suited for different architectures or goals.&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;What I find in Smalltalk, is a message-passing approach to OO mixed with functional-like features like blocks on a serving of dynamic typing. This is definitively a different beast that what we have been accustomed to consider as OO languages. Ironically, that old-school language feels like a breeze of fresh air!&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;Smalltalk has a wonderful variety of implementations, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.pharo-project.org/&quot;&gt;Pharo&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.squeak.org/&quot;&gt;Squeak&lt;/a&gt; being the dominant open-source options, along with the notable &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://amber-lang.net/&quot;&gt;Amber&lt;/a&gt; who targets JavaScript.&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;There is yet another implementation that deserves attention, for it makes the same decision as Scala to target the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.redline.st/discover/why-the-jvm.html&quot;&gt;JVM&lt;/a&gt;. It is called &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.redline.st/&quot;&gt;Redline Smalltalk&lt;/a&gt;, is definitively a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.redline.st/discover/is-it-smalltalk.html&quot;&gt;real Smalltalk&lt;/a&gt;,&amp;nbsp;and I believe is poised to reinvigorate Smalltalk.&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;I urge you to take on Redline as your &quot;new&quot; language to learn for 2013, or if only to help foster a healthy, varied ecosystem on the JVM, to make a small donation on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://igg.me/p/263169/x/1780403&quot;&gt;Redline's indiegogo campaign&lt;/a&gt;. Read the article and watch the video on the campaign site to learn more about the rationale and the dedicated, passionate and friendly human beings behind Redline Smalltalk!&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;Help Redline, and you help all the JVM languages by having one more compelling reason for the JVM infrastructure.&lt;/div&gt;&lt;div style=&quot;text-align:justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;</description>
         <author>noreply@blogger.com (The Careful Programmer)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8932258692847145228.post-160933164900967402</guid>
         <pubDate>Tue, 05 Feb 2013 02:21:00 +0000</pubDate>
      </item>
      <item>
         <title>Dependency Injection is NOT Just for Testing</title>
         <link>http://feedproxy.google.com/~r/connectnothing/~3/BC3XRqPgpvo/</link>
         <description>There was a recent bit of noise in the Ruby community as DHH posted about the supposed evils of using Dependency Injection (DI for short). For DHH, DI is just too Java-ey, which is supposed to be a diss, I think. This brought out some agreement as well as some strong criticisms. The problem with [&amp;#8230;]</description>
         <guid isPermaLink="false">http://gnuu.org/?p=655</guid>
         <pubDate>Mon, 07 Jan 2013 01:43:21 +0000</pubDate>
         <content:encoded><![CDATA[<p>There was a recent bit of noise in the Ruby community as <a rel="nofollow" target="_blank" href="http://david.heinemeierhansson.com/2012/dependency-injection-is-not-a-virtue.html">DHH posted about the supposed evils</a> of using <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Dependency_Injection">Dependency Injection (DI for short)</a>. For DHH, DI is just too Java-ey, which is supposed to be a diss, I think. This brought out <a rel="nofollow" target="_blank" href="https://www.tbray.org/ongoing/When/201x/2013/01/06/Unit-testing-and-dependency-injection">some agreement</a> as well as some <a rel="nofollow" target="_blank" href="http://codeulate.com/2013/01/a-criticism-of-dhhs-post-on-dependency-injection/">strong criticisms</a>. The problem with this entire argument, though, is that it&#8217;s poised upon a dangerously faulty premise:</p>
<h2></h2>
<h2>DI is just for testing (?)</h2>
<p>The entire arguments, both for and against, are based on the assumption that because there are different ways to test things in Ruby, DI is awkward to use; therefore you should <em>never</em> use it. This is shown through the framing of all of the above posts as though DI only exists to answer the question of, &quot;okay, now how do I test it?&quot;.</p>
<p>Unfortunately this premise is faulty and wrong, and thus the arguments fall flat on both sides. Yes, we don&#8217;t need to use DI to test in Ruby, but that does not mean DI has no value in the language. Quite simply, DHH is attempting to throw out the baby with the bath water on this issue.</p>
<h2>DI is not a magical concept</h2>
<p>Let&#8217;s start from the top with a simple revisiting of what dependency injection <em>is:</em></p>
<p>DI is a way to expose relationships made through composition in order to influence (or control) those composed objects. Put simply, DI is basically when you pass objects into a constructor or method instead of creating them inside the method itself. That&#8217;s it. It sounds insanely simple, right? It is.</p>
<p>We actually do this all the time, and it&#8217;s not special. DI is just a fancy name for this concept <em>when the compositions we influence happen to be special</em>, like databases, or dates, or, you know, heavy external components that need to be stubbed out in testing. From the start, this <em>does</em> sound very useful for testing in statically typed languages where you cannot hook into any method that&#8217;s already been defined. However, that behaviour you immediately think about is <em>a side-effect of DI</em>, not its inherent purpose.</p>
<h2>DI is for reuse</h2>
<p>The real purpose of DI is that of reuse. DI allows us to take a component&#8217;s logic and substitute different compositions so that we can reuse the logic in different scenarios. Some of those compositions we might substitute might be mocks or stubs, but they might also be used in production code too, like:</p>
<ol>
<li><em><strong>A different UI backend</strong></em>. A good example of this is testing <em>frameworks</em> (not tests themselves) which might have different test runners for different UIs—a console runner, a JUnit style XML output runner, a fancy GUI runner, and more. Because this is typically abstracted inside of a generic global &quot;run my tests&quot; controller class/method, there has to be a good way to inject our new backend into this controller (if we&#8217;re looking at this from MVC). Yes, we could explicitly pick our backend and run that directly with our tests, but now we&#8217;ve inverted our API; the UI is no longer a detail of the controller, it&#8217;s the primary interface with which we access the program logic. In other words, instead of asking the Controller setup the View, we&#8217;re asking the View to setup the Controller. </li>
<li><em><strong>A different transport backend</strong></em>. <a rel="nofollow" target="_blank" href="https://www.tbray.org/ongoing/When/201x/2013/01/06/Unit-testing-and-dependency-injection">Tim Bray</a> talks about the example of substituting <code>Net::HTTP</code> with <code>FakeWeb</code> in his testing example, but this may as well be an example of a real world application and not just a testing scenario. Maybe we want to take our monolithic Request class and instead run our requests over some <em>HTTP-like</em> protocol over UDP, or maybe even a serial port. If calling <code>Net::HTTP.new</code> is buried somewhere in an internal <code>#send</code> method, there&#8217;s not much we can do without DI. We can monkeypatch or redefine methods directly on an instance, but these are not thread-safe or elegant solutions to the problem. DI is the elegant solution, here. </li>
<li><em><strong>A different database?</strong></em> I&#8217;m not sure why this example was lost on DHH, of all people, as DI is being used inside of his own framework and he completely forgot about it. Arguably, I&#8217;m no expert on the implementation of ActiveRecord, but conceptually speaking, almost any database-agnostic library like AR handles selecting the DB backend through DI. I&#8217;ve roughly tracked this behaviour down to <a rel="nofollow" target="_blank" href="https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_handling.rb#L37-L43">AR&#8217;s <code>#establish_connection</code> method</a>, which allows you to <em>inject</em>, via arguments, values that will influence which backend database drivers are being used in AR. That is <em>basically</em> DI, right there (it&#8217;s not a great form of DI, since you can only <em>influence</em>, not fully <em>control</em>, the composition, but I&#8217;m sure deeper down in the framework is a method that exposes more control). </li>
</ol>
<h2>TL;DR: you can&#8217;t hate DI because you already use it</h2>
<p>If you use ActiveRecord and have a bunch of settings in your database.yml file, you are making use of dependency injection. You are influencing a composition through arguments passed into the connection manager. You probably use this all over your own code, too—whenever you defer the creation of an object and allow that object to be overridden by something passed in via arguments. These are all cases of DI.</p>
<p>In other words: DI is not magical. Don&#8217;t hate it.</p>
<h2>But&#8230;</h2>
<p>If you&#8217;re in Ruby-land, or any dynamic language that lets you swap out method implementations, you shouldn&#8217;t use DI <em>solely</em> for testability of your APIs. And that, my friends, is really the only real point about DI being made in these posts. </p>
<p>To qualify the argument a little more: you <em>should</em> be thinking about using DI in your APIs if there are interesting compositions you want to be able to influence or substitute out—specifically large components, like databases, UIs, etc.</p><img src="http://feeds.feedburner.com/~r/connectnothing/~4/BC3XRqPgpvo" height="1" width="1" alt=""/>]]></content:encoded>
         <category>post</category>
      </item>
      <item>
         <title>How RethinkDB Says Thanks</title>
         <link>http://feedproxy.google.com/~r/SolutiousPerformanceBlog/~3/AXlOWOa97Bs/</link>
         <description>&lt;p&gt;I posted a couple weeks ago about &lt;a rel=&quot;nofollow&quot;&gt;my experience installing RethinkDB&lt;/a&gt;. Today I got this in the mail:&lt;/p&gt;

&lt;p&gt;&lt;img title=&quot;Who doesn't love getting mail?&quot; alt=&quot;Thank you RethinkDB&quot;/&gt;&lt;/p&gt;

&lt;p&gt;That's a moleskin and a usb key (with a metal case). The handwritten note is fine touch too.&lt;/p&gt;

&lt;p&gt;Thank you &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/al3xandru&quot;&gt;@al3xandru&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rethinkdb.com/&quot;&gt;RethinkDB&lt;/a&gt;.&lt;/p&gt;
&lt;img src=&quot;http://feeds.feedburner.com/~r/SolutiousPerformanceBlog/~4/AXlOWOa97Bs&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">http://solutious.com/blog/2012/12/26/how-rethinkdb-says-thanks</guid>
         <pubDate>Wed, 26 Dec 2012 00:00:00 +0000</pubDate>
      </item>
      <item>
         <title>Are you a Redliner?</title>
         <link>http://thecarefulprogrammer.blogspot.com/2012/11/are-you-redliner.html</link>
         <description>&lt;p dir=&quot;ltr&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.redline.st&quot;&gt;Redline Smalltalk&lt;/a&gt; is a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.redline.st/discover/is-it-smalltalk.html&quot;&gt;real Smalltalk&lt;/a&gt; for the JVM.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;Redline Smalltalk is nearly done, but needs a little push to get out polished and in a timely manner.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;Don't miss out on getting Redline passed the tipping point!&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://igg.me/p/263169?a=1780403&quot;&gt;Click here to donate to the &lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://igg.me/p/263169?a=1780403&quot;&gt;indiegogo&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://igg.me/p/263169?a=1780403&quot;&gt; campaign 8)&lt;/a&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;The above link also contains additional information about the goals of Redline and why you should donate.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;If you've contributed before to a language you liked that got successful, here's your chance to be part of the revolution... again!&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;If not, now is the time to be part of something great from the start!&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;I'm a Redliner. Are you?&lt;/p&gt;</description>
         <author>noreply@blogger.com (The Careful Programmer)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8932258692847145228.post-7440869496750783846</guid>
         <pubDate>Mon, 26 Nov 2012 22:15:00 +0000</pubDate>
      </item>
      <item>
         <title>WordPress plugins for complex websites</title>
         <link>http://feedproxy.google.com/~r/JulienDesrosiers/~3/BE63uBw-9rU/wordpress-plugins-for-complex-websites</link>
         <description>&lt;p&gt;Here is my list of the most useful plugins that I’ve found to rely on when creating complex websites with WordPress.&lt;/p&gt;

Custom content

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;With the ACF plugin, I can declare custom post types in my functions.php and with this plugin attach very cool &amp;hellip;&lt;/p&gt;</description>
         <guid isPermaLink="false"></guid>
         <pubDate>Tue, 20 Nov 2012 00:00:00 +0000</pubDate>
      </item>
      <item>
         <title>The Cost of Ruby 1.9.3's GC::Profiler</title>
         <link>http://feedproxy.google.com/~r/JamesOnSoftware/~3/XVpbdSZXQ44/the-cost-of-ruby-1.9.3-s-gc-profiler.html</link>
         <description>&lt;p&gt;This is a long one, and y'all are busy I'm sure so here's the tl;dr:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you run ruby in production, you need to keep track of GC stats.&lt;/li&gt;
&lt;li&gt;Ruby 1.9.3's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ruby-doc.org/core-1.9.3/GC/Profiler.html&quot;&gt;&lt;code&gt;GC::Profiler&lt;/code&gt;&lt;/a&gt; does a bunch of really weird shit.

&lt;ul&gt;
&lt;li&gt;It keeps a 104 byte sample of every GC run since it was enabled forever.&lt;/li&gt;
&lt;li&gt;Calling &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ruby-doc.org/core-1.9.3/GC/Profiler.html#method-c-total_time&quot;&gt;&lt;code&gt;GC::Profiler.total_time&lt;/code&gt;&lt;/a&gt; loops over every sample in memory to calculate the total.&lt;/li&gt;
&lt;li&gt;The space used to keep those samples in memory is &lt;strong&gt;never freed&lt;/strong&gt;. However, it does get reused when you call &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ruby-doc.org/core-1.9.3/GC/Profiler.html#method-c-clear&quot;&gt;&lt;code&gt;GC::Profiler.clear&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Therefore: if you are using &lt;code&gt;GC::Profiler&lt;/code&gt; in production, and you're not calling &lt;code&gt;GC::Profiler.clear&lt;/code&gt; regularly, you're leaking a substantial amount of memory (&amp;gt;1GB / machine for us), slowing down garbage collection somewhat, and the cost of retreiving the stats (&lt;code&gt;GC::Profiler.total_time&lt;/code&gt;) will continue to increase unbounded until the process is restarted&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I am working on an alternative, low-overhead GC Profiler that is designed to be run in production. It's called &lt;code&gt;GC::BasicProfiler&lt;/code&gt;. You can find the patch &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/commit/576cba1e79842f7c5ee80d3668958e1571da13d7#L0R3992&quot;&gt;here&lt;/a&gt; and follow development &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/commit/576cba1e79842f7c5ee80d3668958e1571da13d7#L0R3992&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Also, you may want to check out &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/thecodeshop/ruby/commits/tcs-ruby_1_9_3&quot;&gt;this fork&lt;/a&gt; for some backports from ruby 2.0 &amp;mdash; including the COW-friendly garbage collector. Good stuff.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;The Long Version&lt;/h3&gt;

&lt;p&gt;Ruby's GC is a steaming pile of shit &amp;mdash; but that's not news to anybody. If you're running ruby in production, tracking GC behaviour is essential so that you can minimize its effects on perceived performance (hence &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://unicorn.bogomips.org/Unicorn/OobGC.html&quot;&gt;oob_gc&lt;/a&gt;, etc). Fortunately, Ruby 1.9.3 ships with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ruby-doc.org/core-1.9.3/GC/Profiler.html&quot;&gt;GC::Profiler&lt;/a&gt;, which provides detailed instrumentation on GC runs.&lt;/p&gt;

&lt;p&gt;Over the last month or so, I've been working on some rails performance tooling. Last night, I noticed that requests with my instrumentation enabled were taking around an order of magnitude longer than those without it. Weird. So, I installed &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/tmm1/perftools.rb&quot;&gt;perftools.rb&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/bhb/rack-perftools_profiler&quot;&gt;rack-perftools_profiler&lt;/a&gt; and got a really surprising result (irrelevant lines ommitted):&lt;/p&gt;

 


&lt;p&gt;Apparently calling &lt;code&gt;GC::Profiler.total_time&lt;/code&gt; is so slow that more than 50% of request time was spent in there? Is that actually possible? My instrumentation calls &lt;code&gt;GC::Profiler.total_time&lt;/code&gt; frequently under the assumption that it's inexpensive, but obviously that was a faulty assumption unless perftools.rb is wrong. Let's take a look at the implementation. (the code in context is &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ruby/ruby/blob/ruby_1_9_3/gc.c#L3627-3647&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;

 


&lt;p&gt;There's a loop in &lt;code&gt;total_time&lt;/code&gt;? What the fuck is going on here?&lt;/p&gt;

&lt;p&gt;Turns out that if you have &lt;code&gt;GC::Profiler&lt;/code&gt; enabled, the VM records a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ruby/ruby/blob/ruby_1_9_3/gc.c#L106-124&quot;&gt;&lt;code&gt;gc_profile_record&lt;/code&gt;&lt;/a&gt; every time the garbage collector runs.&lt;/p&gt;

 


&lt;p&gt;Then, when you call &lt;code&gt;total_time&lt;/code&gt;, it loops over all of the &lt;code&gt;gc_profile_record&lt;/code&gt;s that have been created in order to sum the total. According to my profile, &lt;code&gt;total_time&lt;/code&gt; was responsible for more than 50% of request time. How many &lt;code&gt;gc_profile_record&lt;/code&gt;s could there actually be?&lt;/p&gt;

 


&lt;p&gt;Oh. Well I guess that explains that. So &amp;mdash; stupid question, but when do these things get freed? Apparently only in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ruby/ruby/blob/ruby_1_9_3/gc.c#L479-506&quot;&gt;&lt;code&gt;rb_objspace_free&lt;/code&gt;&lt;/a&gt; which only ever gets called &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ruby/ruby/blob/ruby_1_9_3/vm.c#L1624&quot;&gt;when the VM terminates&lt;/a&gt;, so the answer is &lt;em&gt;never&lt;/em&gt;. Cool.&lt;/p&gt;

&lt;p&gt;Upon further investigation, it's pretty clear that this whole system was designed with the expectation that you'd call &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ruby-doc.org/core-1.9.3/GC/Profiler.html#method-c-clear&quot;&gt;&lt;code&gt;GC::Profiler.clear&lt;/code&gt;&lt;/a&gt; regularly. The profiler keeps its samples in an array at &lt;code&gt;objspace-&amp;gt;profile.record&lt;/code&gt; that it &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ruby/ruby/blob/ruby_1_9_3/gc.c#L168-171&quot;&gt;increases in size by 1000&lt;/a&gt; every time it runs out of space.&lt;/p&gt;

 


&lt;p&gt;&lt;strong&gt;If you don't call &lt;code&gt;GC::Profiler.clear&lt;/code&gt;, that array keeps increasing in size forever.&lt;/strong&gt; This is not documented. Obviously.&lt;/p&gt;

&lt;p&gt;On our production systems, unicorn workers that have been running for a few hours had an &lt;code&gt;objspace-&amp;gt;profile.size&lt;/code&gt; of around 350000. On x86_64, &lt;code&gt;sizeof(struct gc_profile_record)&lt;/code&gt; == 104, so around 35MB of overhead per process multiplied by 25 processes per machine for a total of nearly 1GB per machine &amp;mdash; after only 3 hours. That will grow forever until the processes are restarted.&lt;/p&gt;

&lt;p&gt;That's the bad news.&lt;/p&gt;

&lt;h3&gt;The good news: GC::BasicProfiler&lt;/h3&gt;

&lt;p&gt;Ultimately, &lt;code&gt;GC::Profiler&lt;/code&gt; was designed to provide detailed information about every GC run &amp;mdash; probably for the VM implementers to use when tuning the GC (haha yeah right). But seriously, somebody probably wants that, but it isn't me. For those of us who simply want to keep track of GC stats on our production applications, we need a less expensive implementation.&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/commit/576cba1e79842f7c5ee80d3668958e1571da13d7&quot;&gt;&lt;code&gt;GC::BasicProfiler&lt;/code&gt;&lt;/a&gt; is a first step towards something like that. It has a very simple, low-overhead implementation, and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/tcs-ruby_1_9_3/gc.c#L3915-3921&quot;&gt;&lt;code&gt;GC::BasicProfiler.total_time&lt;/code&gt;&lt;/a&gt; works the way you might expect.&lt;/p&gt;

 


&lt;p&gt;Enabling and disabling &lt;code&gt;BasicProfiler&lt;/code&gt; works exactly the same as &lt;code&gt;Profiler&lt;/code&gt; but you don't need to call &lt;code&gt;clear&lt;/code&gt; to avoid leaking memory. In fact, there's no &lt;code&gt;clear&lt;/code&gt; method at all.&lt;/p&gt;

&lt;p&gt;If you're interested in following the development of this patch, it'll be &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/jamesgolick/ruby/blob/tcs-ruby_1_9_3&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;One more lol for the road&lt;/h3&gt;

 


&lt;p&gt;It's the little things. Don't worry, though &amp;mdash; fixed in &lt;code&gt;BasicProfiler&lt;/code&gt;.&lt;/p&gt;

 

&lt;img src=&quot;http://feeds.feedburner.com/~r/JamesOnSoftware/~4/XVpbdSZXQ44&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">tag:jamesgolick.com,2012-11-19:1353356029</guid>
         <pubDate>Mon, 19 Nov 2012 20:13:49 +0000</pubDate>
      </item>
      <item>
         <title>Installing RethinkDB on Ubuntu</title>
         <link>http://feedproxy.google.com/~r/SolutiousPerformanceBlog/~3/pjxB1l_gC6s/</link>
         <description>&lt;p&gt;&lt;strong&gt;Update: The &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rethinkdb.com/docs/install/&quot;&gt;installation docs&lt;/a&gt; for Ubuntu have been updated to make the requirements more clear.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rethinkdb.com/&quot;&gt;RethinkDB&lt;/a&gt; has been getting some more attention in the past few days, starting with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://news.ycombinator.com/item?id=4763879&quot;&gt;a Hacker News post last Friday&lt;/a&gt;. The project (and company) was founded in 2009, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://techcrunch.com/2011/06/06/rethinkdb-expands-beyond-ssds-launches-its-speedy-database-to-the-public/&quot;&gt;launched the 1.0 release&lt;/a&gt; last year, and although there's still some work to do in terms of stability and portability, it looks promising.&lt;/p&gt;

&lt;p&gt;In their words:&lt;/p&gt;

&lt;blockquote&gt;&lt;i&gt;RethinkDB is built to store JSON documents, and scale to multiple machines with very little effort. It has a pleasant query language that supports really useful queries like table joins and group by, and is easy to setup and learn.&lt;/i&gt;&lt;/blockquote&gt;


&lt;p&gt;&lt;img title=&quot;The built-in admin Interface&quot; alt=&quot;The built-in RethinkDB admin interface&quot;/&gt;&lt;/p&gt;

&lt;h2&gt;Installation Steps for Ubuntu&lt;/h2&gt;

&lt;p&gt;I only just got it running after much trial and error so I documented the experience to help others in the same boat. The team is working full steam on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/rethinkdb/rethinkdb/issues&quot;&gt;resolving issues&lt;/a&gt; as they arise so my intent here is one of observation rather than to criticize. Here's what I've gathered so far.&lt;/p&gt;

&lt;h4&gt;Requirements/Limitations&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Only runs on x86_64 Linux&lt;/li&gt;
&lt;li&gt;Depends on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/rethinkdb/rethinkdb/issues/6#issuecomment-10263097&quot;&gt;kernel 2.6.37&lt;/a&gt; or greater&lt;/li&gt;
&lt;li&gt;No RPM (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/rethinkdb/status/267785958278176769&quot;&gt;soon&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Possible issue with ext4 with journaling and/or encrypted partitions&lt;/strike&gt; (update from Slava below)&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Some compilation issues on Debian/CentOS&lt;/strike&gt; (working on a Debian post now)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Update (Nov 12 @ 16:50 PST): Success with ext2 and ext3/ext4 with journaling enabled.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update (Nov 13): Comment from Slava (below):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;We'll be providing binaries for most platforms and even old kernels, though it will take a bit of time to work out. The portability team here is working around the clock to make it happen.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Rethink doesn't work on encrypted file systems because they don't support direct io. It makes sense in production, but it'd be nice to have a backup mode for trying in dev. See &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/rethinkdb/rethinkdb/issues/47&quot;&gt;issue #47&lt;/a&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;So make sure you're running the 64-bit of version Ubuntu with a non-encrypted ext2, ext3 or ext4 partition and that the kernel version is 2.6.37 or greater. Then:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo apt-get install software-properties-common  # installs add-apt-repository
$ sudo add-apt-repository ppa:rethinkdb/ppa
$ sudo apt-get update
$ sudo apt-get install rethinkdb
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Things are changing almost hourly so be sure to check their &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rethinkdb.com/community/&quot;&gt;community page&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/rethinkdb&quot;&gt;follow RethinkDB on Twitter&lt;/a&gt; for the latest info.&lt;/p&gt;

&lt;h4&gt;Checking whether journaling is enabled&lt;/h4&gt;

&lt;p&gt;Look for the &lt;code&gt;has_journal&lt;/code&gt; option in the following output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo debugfs -R features /dev/sda1
debugfs 1.42.5 (29-Jul-2012)
Filesystem features: filetype sparse_super
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You may need to change &lt;code&gt;/dev/sda1&lt;/code&gt; for your disk device which you can get from the output of &lt;code&gt;mount&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;Checking the kernel version&lt;/h4&gt;

&lt;p&gt;The kernel version is displayed immediately to the right of the hostname:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ uname -a
Linux bs-dev-01 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
&lt;/code&gt;&lt;/pre&gt;
&lt;img src=&quot;http://feeds.feedburner.com/~r/SolutiousPerformanceBlog/~4/pjxB1l_gC6s&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">http://solutious.com/blog/2012/11/12/installing-rethinkdb-ubuntu</guid>
         <pubDate>Mon, 12 Nov 2012 00:00:00 +0000</pubDate>
      </item>
      <item>
         <title>The WordPress database diagram</title>
         <link>http://feedproxy.google.com/~r/JulienDesrosiers/~3/hB5M4UfW0Ls/the-wordpress-database-diagram</link>
         <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Today I found this very useful picture that describes the WordPress Database tables relationships.&lt;/p&gt;

&lt;p&gt;Source: http://codex.wordpress.org/Database&amp;#95;Description&lt;/p&gt;</description>
         <guid isPermaLink="false"></guid>
         <pubDate>Thu, 08 Nov 2012 00:00:00 +0000</pubDate>
      </item>
      <item>
         <title>Automatically prefix Custom Post Type slugs with the Author name</title>
         <link>http://feedproxy.google.com/~r/JulienDesrosiers/~3/EUmNAsEaO-A/automatically-prefix-custom-post-type-slugs-author-name</link>
         <description>&lt;p&gt;These days i’ve been working on a WordPress-powered job listing site. And one thing I needed to do is to prepend the author name (user_nicename) at the beginning of the “job_listing” post slugs.&lt;/p&gt;

&lt;p&gt;Here’s how I did it:&lt;/p&gt;

&amp;lt;?php

// usage: &amp;hellip;</description>
         <guid isPermaLink="false"></guid>
         <pubDate>Sat, 27 Oct 2012 00:00:00 +0000</pubDate>
      </item>
      <item>
         <title>Google and LinkedIn: Stop im(mobile)izing me!</title>
         <link>http://thecarefulprogrammer.blogspot.com/2012/10/google-and-linkedin-stop-immobileing-me.html</link>
         <description>A rant.&lt;br /&gt;&lt;br /&gt;Google newsgroup mobile site:&lt;br /&gt;If there's a place I need my &quot;mark all as read&quot; option, it's more on my cell phone than my desktop.&lt;br /&gt;&lt;br /&gt;Gmail Android mobile app:&lt;br /&gt;I can create a new label using the mobile website but I can't using the app?&lt;br /&gt;&lt;br /&gt;LinkedIn app on the iPad:&lt;br /&gt;I can't edit my profile or add a new group? Is my iPad a read only device?&lt;br /&gt;&lt;br /&gt;Hopefully these options are there but I just haven't figured out where/how.&lt;br /&gt;&lt;br /&gt;PS: is there a mobile friendly way of writing a Blogger post on a mobile device?&lt;br /&gt;&lt;br /&gt;Update November 25th 2012&lt;br /&gt;Since the original publication, LinkedIn app on the iPad  now allows profile modification. Thank you.&lt;br /&gt;&lt;br /&gt;Also, I discovered there was a Blogger iPad app while perusing the list of Google apps on the iTunes Store for the first time 8)</description>
         <author>noreply@blogger.com (The Careful Programmer)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8932258692847145228.post-3589749074024305460</guid>
         <pubDate>Tue, 23 Oct 2012 11:40:00 +0000</pubDate>
      </item>
      <item>
         <title>Spacehi</title>
         <link>https://technotales.wordpress.com/2012/10/13/spacehi/</link>
         <description>I&amp;#8217;ve been using spacehi for years. It highlights invisible characters: trailing spaces and tab characters. Here&amp;#8217;s how it looks if you toggle it on and off: In my dotfiles setup, it&amp;#8217;s turned on by default. In most cases, whitespace characters do not matter. But sometimes they do. For example, Go and Python are picky about [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=technotales.wordpress.com&amp;#038;blog=761277&amp;#038;post=682&amp;#038;subd=technotales&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://technotales.wordpress.com/?p=682</guid>
         <pubDate>Sun, 14 Oct 2012 02:08:18 +0000</pubDate>
         <content:encoded><![CDATA[<p>I&#8217;ve been using <a rel="nofollow" title="spacehi" target="_blank" href="http://www.vim.org/scripts/script.php?script_id=443">spacehi</a> for years. It highlights invisible characters: trailing spaces and tab characters.</p>
<p>Here&#8217;s how it looks if you toggle it on and off:</p>
<p><img src="https://i0.wp.com/mps.s3.amazonaws.com/images/spacehi/spacehi.gif"/></p>
<p>In my dotfiles setup, it&#8217;s <a rel="nofollow" title="vimrc" target="_blank" href="https://github.com/jpalardy/dotfiles/blob/ee813da183980c16efb30d9a82db87e377d625d2/vimrc#L66">turned on by default</a>.</p>
<p>In most cases, whitespace characters do not matter. But sometimes they do. For example, Go and Python are picky about spaces. Also, a mix of spaces and tabs will look different for different people and their editors &#8212; because nobody can agree how many spaces at tab character is (4 or 8?!). This is something I&#8217;ve <a rel="nofollow" title="inconsitent whitespace" target="_blank" href="https://technotales.wordpress.com/2008/02/26/inconsistent-whitespace/">talked about before</a>.</p>
<p>This week, for the second time in a couple of weeks, I lost a bunch of time on another whitespace: character 160, the <a rel="nofollow" title="nbsp" target="_blank" href="http://en.wikipedia.org/wiki/Nbsp">non-breaking space</a>. To make a long story short, it was a copy and paste from Skype, and the JSON parser I was using choked on it.</p>
<p>It seems spacehi hasn&#8217;t been touched in (almost exactly) 10 years. I found its <a rel="nofollow" title="spacehi on github" target="_blank" href="https://github.com/vim-scripts/spacehi.vim">mirror on github</a>. But it didn&#8217;t handle non-breaking spaces, so <a rel="nofollow" title="my spacehi on github" target="_blank" href="https://github.com/jpalardy/spacehi.vim">I forked it</a>.</p>
<p>I&#8217;m willing to maintain it, it a very simple Vim plugin. <a rel="nofollow" title="github issues" target="_blank" href="https://github.com/jpalardy/spacehi.vim/issues">Bug reports and improvements are welcomed</a>.</p><br />  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/technotales.wordpress.com/682/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/technotales.wordpress.com/682/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=technotales.wordpress.com&#038;blog=761277&#038;post=682&#038;subd=technotales&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://2.gravatar.com/avatar/ecfd1bdc5d3aab1e40f25658817712ba?s=96&amp;amp;d=identicon&amp;amp;r=G">
            <media:title type="html">jpalardy</media:title>
         </media:content>
         <media:content medium="image" url="http://mps.s3.amazonaws.com/images/spacehi/spacehi.gif"/>
      </item>
      <item>
         <title>New projects: scxml-viz, scion-shell, and scion-web-simulation-environment</title>
         <link>http://blog.echo-flow.com/2012/10/07/new-projects-scxml-viz-scion-shell-and-scion-web-simulation-environment/</link>
         <description>I have released three new projects under an Apache 2.0 license: scxml-viz: A library for visualizing SCXML documents. scion-shell: A simple shell environment for the SCION SCXML interpreter. It accepts SCXML events via stdin, and thus can be used to integrate SCXML with Unix shell programming. It integrates scxml-viz, so can also allow graphical simulation of SCXML models. [&amp;#8230;]</description>
         <guid isPermaLink="false">http://blog.echo-flow.com/?p=211</guid>
         <pubDate>Sun, 07 Oct 2012 05:02:53 +0000</pubDate>
         <content:encoded><![CDATA[<div>I have released three new projects under an Apache 2.0 license:</div>
<div>
<ul>
<li><a rel="nofollow" target="_blank" href="https://github.com/jbeard4/scxml-viz">scxml-viz</a>: A library for visualizing SCXML documents.</li>
<li><a rel="nofollow" target="_blank" href="https://github.com/jbeard4/scion-shell">scion-shell</a>: A simple shell environment for the SCION SCXML interpreter. It accepts SCXML events via stdin, and thus can be used to integrate SCXML with Unix shell programming. It integrates scxml-viz, so can also allow graphical simulation of SCXML models.</li>
<li><a rel="nofollow" target="_blank" href="https://github.com/jbeard4/scion-web-simulation-environment">scion-web-simulation- environment</a> : A simple proof-of-concept web sandbox environment for developing SCXML. Code can be entered on the left, and visualized on the right. Furthermore, SCION is integrated, so code can be simulated and graphically animated. A demo can be found here: <a rel="nofollow" target="_blank" href="http://goo.gl/wG5cq">http://goo.gl/wG5cq</a></li>
</ul>
</div>]]></content:encoded>
      </item>
      <item>
         <title>Is the Future Functional? by Rob Harrop</title>
         <link>http://feedproxy.google.com/~r/dev-logger/~3/la5TBsPXq3A/is-future-functional-by-rob-harrop.html</link>
         <description>&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Here are my notes on Rob Harrop's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://skillsmatter.com/podcast/home/qcon-future-functional/&quot;&gt;presentation about functional programming&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;h4&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Functional is important because&lt;/span&gt;&lt;/h4&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;b&gt;1) Simplicity&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;it's declarative&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;you write what you want to achieve, rather than give instructions how to achieve it&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;express solutions, not worry about individual steps&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;b&gt;2) Agility&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;functional fits well with Agile methodology&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;testing is much easier (because of purity, no side-effects)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;b&gt;3) Contentment&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;self-content while you are working&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;b&gt;4) Concurrency&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;e.g. parallelization&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;often the reason why people switch to functional&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;h4&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Imperative vs functional languages&lt;/span&gt;&lt;/h4&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Functional:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;function application (calculations to data), not state change&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;immutable state (makes testing easier)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Imperative:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;focus on decisions (instructions), and state change&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;mutable state&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Functional:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;recursion not looping&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;descriptions (of solutions), not statements&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h4&gt;&lt;h4&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Functional features&lt;/span&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;higher-order functions&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;pure functions (same args in always lead to same results)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;recursion&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;type systems (Haskell: strong typing; Erlang, LISP: loosely typed)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;strict/lazy evaluation&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;b&gt;DDD&lt;/b&gt;: primary focus should be on the domain and domain logic&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;h4&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;DDD concepts&lt;/span&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;ubiquitous language&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;strategic design (identify which bits are harder to model and put time on it)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;models&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;context&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Domain-driven with imperative programming leads to anxiety. Always wondering if you got your model right, because there are a myriad of ways to implement a solution.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;h4&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Functional DDD&lt;/span&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;core concepts still apply&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;everything is just a function or data structure&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Why is functional better?&lt;/span&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;fewer concepts (no factories, no patterns)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;easier concepts&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;lower model overhead&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;Modelling&lt;/span&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;UML doesn't really work for functional&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color:white;&quot;&gt;fortunately, we all know how to model in functional languages&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/dev-logger/~4/la5TBsPXq3A&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <author>noreply@blogger.com (Martin Carel)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-5286603484073646452</guid>
         <pubDate>Tue, 25 Sep 2012 00:10:00 +0000</pubDate>
      </item>
      <item>
         <title>Transferring Large Files: Easy And Free!</title>
         <link>http://feedproxy.google.com/~r/dev-logger/~3/T23Ui_O9xIQ/transferring-large-files-easy-and-free.html</link>
         <description>I needed to transfer a 4GB file the other day. Unfortunately, there is no easy free way to do it. So I went the tech way.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;How to&lt;/h4&gt;Upload the file to my_server (e.g. your server slice) via scp:&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:'Courier New', Courier, monospace;&quot;&gt;scp my_large_file my_server:.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In case your connection breaks up, you can resume the upload like this:&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:'Courier New', Courier, monospace;&quot;&gt;rsync --partial --progress my_large_file my_server:.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Log to your slice and move the file to a directory of its own:&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:'Courier New', Courier, monospace;&quot;&gt;ssh my_server&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:'Courier New', Courier, monospace;&quot;&gt;mkdir public_data&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:'Courier New', Courier, monospace;&quot;&gt;mv my_large_file public_data/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Start a simple HTTP server on the port of your choice (in this case 8080) from that newly-created directory, by running:&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:'Courier New', Courier, monospace;&quot;&gt;python -mSimpleHTTPServer 8080 &amp;amp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;That's it! Your file is now available for download at:&lt;br /&gt;http://my_server_hostname:8080/my_large_file&lt;br /&gt;&lt;br /&gt;If you want to have that HTTP server process running even after logging out, find out its PID by running the &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:'Courier New', Courier, monospace;&quot;&gt;jobs&lt;/span&gt; command, and then you can disown that process from the shell like so (assuming the PID was 1):&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:'Courier New', Courier, monospace;&quot;&gt;disown %1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Advantages&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;no need to go through the hassle of installing a FTP server on your own machine.&lt;/li&gt;&lt;li&gt;don't care about leaving your machine turned on because you don't know exactly when the other party will be fetching the file.&lt;/li&gt;&lt;li&gt;the other party is not slowed down by your ISP's upload limits while trying to fetch the file from you.&lt;/li&gt;&lt;/ul&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/dev-logger/~4/T23Ui_O9xIQ&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <author>noreply@blogger.com (Martin Carel)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3837840012614392958.post-4432127596123419602</guid>
         <pubDate>Thu, 13 Sep 2012 15:10:00 +0000</pubDate>
      </item>
   </channel>
</rss>
<!-- fe2.yql.bf1.yahoo.com compressed/chunked Thu Oct  1 19:25:38 UTC 2015 -->
