IoC, Functional Programming, and DSLs

The Inversion of Control (IoC) design pattern, functional programming, and Domain Specific Languages are all different faces of the same underlying concept and can be used interchangeably.  Recognizing this should make it easier to understand each one and when they should be used within your own code.

IoC simply refers to a library passing control to it’s caller.  A typical object-oriented implementation would be a function which takes an object that implements ISomething where ISomething has a single method that the function then calls.  Those familiar with the visitor pattern should recognize that the visitor pattern is just a specialization of IoC where the callers code is applied to each object in a collection (actually any structure, it doesn’t *have* to be a collection).

I think the tie between IoC and functional programming should be pretty obvious at this point.  If your language supports first class functions and closures, then creating an interface with a single method is just extra work when you can simply pass a function as a parameter.   In fact, since a closure will close over lexical variables to maintain their “state”, both types of IoC implementation (Interfaces and Functions) are exactly equivelant in terms of power.  I believe that using a simple function is more readable though, and it’s certainly more convienent for the caller to not have to create a class that implements ISomething.

The tie between DSLs and IoC is more abstract and requires exploration into the problems being solved.  IoC is a useful design when the problem is not completely specified.  If you are writing a library and the only thing that will vary in how it’s used is the inputs, IoC is just extra typing with no real benefit.  If your problem is only partially specified on the other hand, then IoC allows you to implement the bits of the solution that you can infer from the specs, and leave the rest up to the caller.  This is why very generic libraries tend to use IoC a lot.  A DSL typically provides the users with a base set of combinators (functions that create functions out of other functions) to build up functions that perform a specific type of task in a very high level manner.  A DSL for writing parsers should look very close to BNF so that a grammar can be encoded in the host language with as few implementation specific details as possible.  How to do this with combinators is an interesting topic itself that deserves it’s own post and maybe I will get motivated and write one some day.  A more intuitive example is configuration files, any time you have a configuration file that can change the flow of a program you are creating a mini-language and you are passing control to the end-user (ie.. IoC).

So great, they are the same thing conceptually, what do we gain from this?  Well we can transfer the knowledge we have from one paradigm (like OO) to another (like functional) and vice versa.  More concretely, by recognizing that they are all ways to partially specify a solution, we now have a good solid concrete criteria for deciding when one of these types of implementation are necessary.

On a side note, this should help highlight the difference between a pattern and an implementation.  Interfaces/Functions/Monads are ways to implement the IoC pattern.  Creating a library to “handle IoC” is confusing the two, and if you find yourself writing or consuming one of these libraries, then some reflection on how your handling the task at hand would probably do some good.

5 reasons to use Git instead of Subversion

Git is a new version control system originally written and designed by Linus Torvalds for managing the development of the Linux kernel.  Due to the chaotic nature and massive amout of contributers to Linux kernel development, Linus is quite arguably the most qualified person in the world to design a good VCS.  Git is quite a bit different than a traditional VCS such as Subversion and it doesn’t have the mathematical theory that darcs has behind it, but it is by far the most practical VCS I have used to date.  So anyways, here are my 5 favorite reasons to git.

  1. You always have a full copy of the repository with all the meta-data, online or off
  2. You can merge with anybody’s repository, not only a single central server
  3. Even with the full history, git repositories take less space than a SVN checkout
    brandon@Brandon:~/localtmp/clone$ du -sh *
    1.6G    cohiba.git
    2.6G    cohiba.svn
  4. Modifying the history is easy, using git rebase -i <some_revision> will bring up a list of patches in your favorite editor and allow you to merge/reorder/delete them, then it will apply them as you’ve specified, re-committing with each one
    pick e4eb2ca Added -d option to only look at 1 date
    pick 881ef7f Fixed bug that caused an Prelude.head: empty list exception if no work orders were pushed
    pick 3595183 Added line itemized reports on pushed work orders
    pick 1b6ff52 Fixed the parser so that it doesn't break if there is a [] in the stack trace It was using a bit of a hack, but i've cleaned up the parser so there should be no more suprises, no matter what we throw at it
    pick 12b7023 Changed slurp_until to fail on eof
    pick e511b15 New log file for tests
    
    # Rebase 378dd8b..e511b15 onto 378dd8b
    #
    # Commands:
    #  p, pick = use commit
    #  e, edit = use commit, but stop for amending
    #  s, squash = use commit, but meld into previous commit
    #
    # If you remove a line here THAT COMMIT WILL BE LOST.
    # However, if you remove everything, the rebase will be aborted.
  5. You don’t need a centralized server with a single ‘master’ copy of the codebase with git, but that is  still how most software shops will operate.  Any mucking with this master copy would be noticed by all because git revision id’s are hash sums of the entire history up to that point.