Monday, March 10, 2014

What I love about functional languages

I am very intrigued by functional programming of late but there are so many functional languages and so many descriptions of them that I wanted to document here what I believed are the main draws for me.

They are: (in no particular order)

  • First class functions:  I.e., the ability to pass functions to and from other functions, or functions as data.
  • Homoiconicity:  I.e., program code is represented as the language's fundamental data type.  Not all functional languages have this, but it makes something I love much much more than the syntax possible.  It's one of the most recognizable characteristics of languages in the LISP family.  That is the creation of DSLs easily.  You can modify almost everything about the language to suit your particular use case, emphasising particular aspects and deemphsising others to make it easier to understand.
  • Immutable data structures:  What goes in to a function won't be changed.
  • Side-effect free functions:  This means the environment won't be changed when you call a function.  
The last 2 items make writing concurrent code much easier because of the lack of need to lock.  They also for mathematical reasoning about functions as black boxes because the state of the function parameters and the functions context doesn't change in the execution.   You can easily unit test functions without as much need to do integration testing and higher abstractions tend to be less "leaky".

The first 2, in my mind, allow you to write code that clearly follows the requirements at just the right level of abstraction removing all incidental complexity and only leaving the substantive complexity of the problem domain. This brings the programmer to the holy grail of programming which is making the code as simple as possible, but not simpler. That brings it's own benefits like maintability and reusability and the potential for very few bugs, etc.

Honestly, I'm still trying to understand how to write even simple programs in LISP and I think that is the reason that seeminly great languages like Clojure haven't yet caught on in the mainstream.  They require you to relearn much of the fundamentals you know about programming and it's hard and takes time.

Monday, February 17, 2014

My Mom Helped Me Be a Better Engineer

When I was young, my mom often told my siblings and I that if we lost something the best way to find it was to clean up as we looked. Although I don't remember, I can see myself being dubious about her motives, thinking she wanted me to clean more than find what I was looking for, but since then I have seen the wisdom in assertion, proving it over and over when I needed to find something.

Most of us, I believe find out our parents were wiser than we first thought as teenagers, but as a professional, I have found a surprising software engineering application to my mother's assertion.

It is this, when you have a bug to fix and don't know where to find it, one good technique to fix it is to fix all obvious bugs you find as you look for it. Software is so interdependent that the relationships between components are not always obvious. If you don't know where the cause of the bug you are looking for is you may also not know if the obvious bug in front of you is the root cause of the bug you are looking for. I recommend you try it, it has been very useful to me. Even if the bugs you fix along your search for the elusive bug aren't the cause you were looking for, you probably eliminated the need for a few future bug searches a long the way.

So Mom, thank you! I'm now confident I'll find more of your wisdom the older I get.

PS, I'm not recommending doing some endless refactoring job every time you need to fix a bug.  I don't think my mom would advocate replacing the carpet when looking for a safety pin in the carpet either.

Tuesday, August 28, 2012

Good Code


In an interview I was once asked the following question:

    In your opinion, what qualities make code "good"? What qualities make it "bad"?

I thought awhile about it and gave an answer similar to this.  I wanted to save and share it here because it is pretty well defines my current thoughts on what good code is.

To me, good code is code that meets the needs of the consumer of the code and the authors/maintainers of the code.

So, for the consumer it must: 

- execute and perform the functions needed by the consumer within the parameters the consumer needs (execution speed, accuracy of outputs, ease of use, development time, etc) and not do things that the customer doesn't need or want like open up security holes.  

For the authors/maintainers of the code it must be:

clear to read (by conforming to some coding standard and be documented to the point where those who did not write it but are familiar with the language/framework can learn what is does and hopefully why, without undue hurdles).
consistent by using some type of paradigm throughout that unifies it (a domain model) that can be understood by the consumer (domain expert) and the developers alike (i.e., a shared domain language).  This makes it easier to modify and more useful and understandable to the consumer.
verifiable by some type of automatic and documented means (usually tests).  This also makes modifications easier due to the assurances that the documented functionality in the tests, if they still pass after modifications, has not regressed.  Static typing and compile time errors help with this in my opinion.
have little magic.  It's harder to find and fix problems if it is not clear what something does and how it does it.  Code that is debuggable is much easier in which to find and fix problems.
structured appropriately for the situation.  It is possible and I have seen cases where code has had too many layers and not enough layers.  Blindly following best practices without knowing how they apply in a particular situation may just add unnecessary complexity and cost, but writing code without thought for structure and best practices quickly becomes unmaintainable.  So, a balance is needed here.
To me, code is bad to the degree that it lacks one or more of those elements.


What do you think?

Monday, July 30, 2012

Keystone

For small python web projects I'm really liking keystone.

http://late.am/post/2011/11/27/keystone-a-simple-python-web-framework 

Almost all essence and no ceremony.

Friday, June 17, 2011

How to fix the permGen memory error in Intellij 10.5

If you were like me, you were working on a large web-based java project and had intellij configured to start jetty for you.

All was well until you tried to start jetty using the Intellij Run or Debug functionality and it errors out every time due to a permgen memory error.

Google showed quickly that the problem was a memory configuration of the JVM, but how to change that configuration was not quickly apparent to me.

So this is how you do it.

  • Find the JVM memory values you want to change from the stackoverflow.com link above.  I used -XX:MaxPermSize=256M which worked in my case, YMMV.
  • Enter that configuration into the Run/Debug Configurations page in the VM parameters field.
VoilĂ !

Wednesday, September 16, 2009

Merging a branch with git-svn and still retaining the association with the previous svn path

git-svn uses commit messages to tie the commits in a particular local branch to its corresponding SVN path, which works great most of the time.

It causes a problem though when you want to merge branches in git and have the merged results be put back into svn.  I wanted to do this because the git merge functionality is much easier to use, IMHO, than subversion's merge command.

The problem is that when you do a git merge of two remote svn folders in a local git branch the commit message path changes from the previous path to the path of the source of the merge.

So, for instance, if you want your trunk in svn to match a branch (let's say branch 1.1.1), you could do the following in a git-svn checked out repo (Assuming you have already done git svn clone -s...)

git checkout trunk
git checkout -b localtrunk
You are now in the local git branch 'localtrunk' which is a copy of the trunk path of your svn repository.
Now, let's say you want to merge changes from branch 1.1.1 into trunk, you could do this...
git merge 1.1.1
If the merge is successful there is still a problem. The problem is that now if you do a git svn dcommit to push the merged changes into trunk they will not go into trunk. They will go into the 1.1.1 branch! Bummer. If you read the man page for git-merge you might say, "Hey, there is a --no-commit option to git-merge! That could fix the problem." In theory you would be right and I thought the same thing, but after many attempts (on Ubuntu 9.04) it would always commit after merging. Bummer! --no-log didn't work either. So, after a lot of searching, I found a way to do this, but it only works if you don't have a lot of commits to replicate.
Instead of running git merge as above do this. For each commit do...
git cherry-pick -e (SHA1 hash of the commit to merge from branch 1.1.1)
You can get those hashes from git log, after doing git checkout 1.1.1 in another terminal.

Each time you do it delete the line in the commit message that starts with git-svn-id: (and the line after it, but I don't think deleting that 2nd line is technically necessary)

Now do...
git svn dcommit (to send the merged changes to svn while keeping your local git branch pointing to trunk!)
git svn fetch
git svn rebase

Check that your localbranch branch and your 1.1.1 branch are the same with...
git diff 1.1.1

If there is no output they are identical.

Check that your localbranch branch is still pointing to trunk by doing...
git log

and verifying the git-svn-id: lines for the last commits (the ones at the top) still point to trunk@(svn commit number)

All done!

Tuesday, June 30, 2009

How to easily fork python code into separate processes via a decorator

Do you have a bit of python code that is taking a long time, and you don't want to wait for it to finish?

The blogger here made an excellent way of forking pieces of your code into separate processes using a decorator.

http://buffis.com/2008/01/09/easy-forking-of-processes-in-python-using-generators/

It doesn't get easier than this.