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.

Friday, June 19, 2009

How to get the firefox java plugin working in Ubuntu 8.10 64bit

The default java plugin for Firefox on Ubuntu 8.10 is not fully functional on 64 bit machines.  It works for some applets, but not all.

This blogger took the time to figure out how to replace it with Sun's plugin. Thank you for sharing!

http://tp0x45.blogspot.com/2009/03/openjdk-issue-in-ubuntu-810-64-bit.html

Friday, April 17, 2009

Use Python for Microsoft Windows Login and Group Policy Scripts

Background

Microsoft's Active Directory provides a way to distribute msi files and execute scripts on login, logout, shutdown etc. This makes it very easy to distribute a script to be run on login for a group of machines registered to Active Directory.

The type of scripts that can be run are .bat files, JScript or VBScript files via Windows Script Host (WSH. It's executables are wscript.exe (windows version) and cscript.exe (command-line version)), or windows executables (exe files). While those options are not too bad, I much prefer python for programming so here we are going to outline how to use python for these scripts.

Tim Golden has written some excellent wrapper code for python to make programming for Active Directory, WMI, shell work (like creating shortcuts) amoung other windows-specific things a pleasure.

Instructions
  • Get the Python MSI from Active State. We could have used the msi from python.org but we would have had installed the windows specific stuff that Mark Hammond wrote (pywin32 Windows Python Extensions) separately. And since I want to distribute this with Actirve Directory I would have had to convert the pywin32 package to an MSI as it is distributed as an exe. I tried compiling the source distribution to an msi with distutils (i.e.,
    python setup.py bdist_msi
    ) but the build failed because I did not have Visual Studio 2003 installed (I was building python 2.5). I do not want to buy or install Visual Studio (especially the old 2003 version) so I was happy that Active State packaged it all up in an msi already and distributed it for free! Thank you Active State!
  • If you would like to install Tim Golden's wrapper code via Active Directory as well (highly recommended) it is easy since he provided the setup.py distutils scripts for each package. Just download the zip files you want from his site and then for each one run
    python setup.py bdist_msi
    and an msi will be created for you. Thank you Tim!
  • You can distribute any python code that you want via Active Directory this way. Just make an msi of your code by writing a setup.py script and then running
    python setup.py bdist_msi
    . Distutils makes it easy!
  • Then, distribute those msi files with Active Directory Group Policy. I'll leave that to an exercise for the reader, but here is a good starting point. For some reason, I had to reboot a couple of times on some workstations for them to get the msi files installed.
  • Now your setup work is done and your workstations (or servers) have python installed along with pywin32 and optionally some nice wrapper code. From here you can write python scripts for those hosts that will be able to interact with active directory, WMI, COM, etc.
  • Now write your python login scripts.
  • To setup your login scripts to run at login you have a choice. First, you could compile your python code into exe files. You can do that without a lot of effort using py2exe (a distutils extension). This route adds a separate step (conversion to exe file) and every time you make a new exe it copies the whole python interpreter and other code with it so the exe files are large. This is a good option if you don't want to install python on the hosts though.
  • Windows Script Host (WSH) integration is another good option (I won't go into calling the python intepreter on your scripts via a bat file, but that is also an option). This way cscript.exe or wscript.exe runs the python intepreter which runs your script. Here's what you need to do to set this up.
    • First, run C:\Python25\Lib\site-packages\win32comext\axscript\client\pyscript.py (adjust for your installed version of python) on each host. This registers python as a language that Windows Script Host can run (called pyscript). Once this is done your python files (saved with the .pys extension can be used as Windows login scripts! You could put this command in a MSI file and distribute it with python so that when your login script runs it will already have been done.

    • There is one registry entry that needs to be added I have found in experimenting and below is some jscript code that does it (put it in a file in with a .js extension that you can publish it via a Group Policy in the Computer section of the policy to run on startup of the machine (best not done on logon to make sure it get's done before your python scripts run))


      var objShell = WScript.CreateObject("WScript.Shell");
      objShell.RegWrite("HKEY_CLASSES_ROOT\\pysFile\\shell\\open\\command\\", "\"C:\\WINDOWS\\system32\\wscript.exe\" \"%1\"", "REG_SZ");



    • Lastly setup your new shiny .pys script to run at login user the User side of the Active Directory Group Policy Object. Here is a site that shows you how.

    • This site has a lot of good information as well, but I have found that you don't need to do all the steps it outlines because the msi files above do most of it. The steps above worked for me.