Saturday, 9 November 2013

John Cleese on Pair Programming

Hello Readers!

I'm feeling philosophical today, so rather than sharing with you some advice on solving a particular problem, I'm going to touch on why I think Pair programming is fantastic, and how English Comedian John Cleese helped convince me.  As you are presumably aware, Pair Programming involves one programmer who drives and one who observes, critiques and thinks ahead.  The advantages of this style of development are said to range from increased morale to increased code quality at the expense of development time.  But why?

I had always attributed the increase in code quality to the simple explanation of "two sets of eyes are better than one".  Perspective surely helps you spot mistakes and come up with more optimal solutions; a common sense anecdotal conclusion that lends itself to encouraging the use of Pair Programming.  However, after watching John Cleese - a lecture on Creativity I came to realise that the Pair Programming dynamic is in fact rooted in the fundamentals of Human Creativity, and that it is to an extent, a necessity for the development of great software.

I'd encourage you to go ahead and check out the video as I think it is an essential watch for anyone.  However the point I'd like to hone in on is Cleese's idea of the "Open" and "Closed" mental modes.  The Open mode being a state of mind in which creativity is possible and the Closed in which is it impossible.

Cleese describes the Closed state as a mode in which we are focused on a task at hand.  In this mode we are purposeful and determined but cannot be creative.  He goes on to describe the Open mode in which we are less focused, more relaxed and as a result more inclined towards curiosity, playfulness and as a result, creativity.

In his discussion he concludes that both modes are a necessity for any creative pursuit:
We need to be in the open mode when we're pondering a problem but once we come up with a solution, we must then switch to the closed mode to implement it. Because once we've made a decision, we are efficient only if we go through with it decisively, undistracted by doubts about its correctness.
The truth of Cleese's take on creativity can easily be observed in the creative pursuit of Software Engineering.

I often find myself completely zoned into a task, eyes glued to walls of code and headphones blasting my favourite Meshuggah track.  Although this state of mind is fantastic for productivity, I've often found that being so focused has allowed me to lose awareness of the big picture and how my changes propagate through a code base; sure signs of being sucked into Programmer Tunnel Vision.  In this state we can quite easily make questionable design decisions or introduce bugs that are overlooked in the shadow of a successful current task.

Thankfully at Orion Health, we're pretty strict with Code Reviews.  I've often shown a supposedly complete task to a peer only to find my relief shattered by their observation of a new edge-case to test, a scenario I didn't think to cover or the potential for a bug, leaving me wondering how in the world I even began to think that my work was complete.  Similarly, I've often found myself dishing out a grilling at code reviews, often spotting issues that seem very plainly obvious.

Going back to Cleese's mental states, we can see that the concept of a Closed mode marries quite well with the idea of Programmer Tunnel Vision.  Staring at a screen and blasting your ears with Death Metal seems to work wonders for productivity at the cost of not always asking the "what if" questions and considering the alternatives.  Being in a mindset of productivity makes it difficult to be creative.  However, casually strolling over to a colleague's desk and discussing their latest code commit seems to fill you with a million constructive questions and thoughts about what their solution may lack.  Being in a relaxed mindset free from pressure allows creativity to flow.

It seems the ideal Super-programmer would be able to zone in to a problem and zone out to the big picture at will, switching between the Closed and Open mental states to facilitate the optimal balance between unadulterated focus and playful creativity.

From here, we finally arrive at the point.  Pair Programming facilitates exactly this by separating the zone in from the zone out using two developers.  The Driver is afforded the freedom to focus on the implementation of a problem, while the Observer is afforded the freedom to consider the big picture.

As a driver I've found silly mistakes and misunderstandings cleared rapidly with a second pair of eyes looking over my shoulder.  I've found the observer realising issues with my designs that result in complete changes in direction.  As an observer I've found myself constantly considering how the driver's changes propagate and what alternatives to consider.  Where the driver focuses on the implementation of the solution, the observer can sit back and let their curiosity do its work.

Pair Programming allows for the creative pursuit of Software Development to occur simultaneously in the Open and Closed mental states.

In addition to now having a deeper understanding of my many creative pursuits, watching John Cleese's presentation has solidified my advocacy for Pair Programming.  I cannot speak for the exact situations in which it is practical and which pairs of colleagues would make great Pair Programming teams.  Perhaps that's a discussion I'll return to in a future blog post.  However, understanding its effectiveness in terms of the fundamentals of Human Creativity makes me think it should be exercised whenever possible.  At the very least, Code Reviews should be mandatory.  Although they may not be as thorough, Code Reviews do allow for the same relaxed mode of thinking for an onlooker.

That's it from me today!  Be sure to check out  John Cleese - a lecture on Creativity in full for more invaluable perspective on creative and professional environments,

Cheers,

Shrek

Wednesday, 10 April 2013

Notes on Remote Debugging in Java

Hello Readers,

Been a while!  This post will cover how to enable remote debugging in a java application and hook Eclipse's debugger onto it.  It'll also cover the explanations of all those little details that can really bite you if you don't understand them.  If you're looking to debug issues in a testing or production environment and are feeling blind without being able to snoop through your code then you've hopefully come to the right place!

Enable Remote Debugging


Remote debugging of a Java application isn't enabled by default.  You need to run the application (or Target Java VM) with certain Java properties that enable and expose the debugging functionality.  There are many properties we can use to configure Java debugging on the VM's end but for this post, we'll stick to one standard set of properties that suffice for allowing the Eclipse debugger to connect.  When running the Target VM, these properties look like:

java myApplication -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9000,server=y,suspend=n

What these properties mean (found from around the web) are as follows:
  • -Xdebug : Enables debugging support in the Java VM
  • -Xnoagent: Disables oldjdb, a legacy Java debugger that has now been deprecated
  • -Xrunjdwp: loads libraries required for Java debugging
    • transport: specifies the manner in which the VM and debuggers will communicate.  For instance, setting transport=dt_socket means that the debugger and the VM will communicate socket to socket via a TCP/IP connection.
    • server: specifies whether or not the Java VM will act as a 'server'.  If server=y, the VM will expose a port for debuggers to attach onto.  If server=n, the VM will instead attach onto a specific debugger application.
    • address: If server=y, this is the address that the VM exposes to debuggers.  If server=n, this is the address of the specific debugger that the VM attaches to.
    • suspend: specifies whether or not the VM should wait for a debugger to attach before starting
Thus, in our example:

java myApplication -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9000,server=y,suspend=n

What we have done is:
  • enabled debugging for the Target Java VM
  • exposed it as a server at port 9000, so that any debugger can attach to the VM at this port
  • ensured that the VM will not suspend while waiting for a debugger to attach

Ensure that the Classes of Interest in the Target VM have Source Attached


Java debugging seems to work on a file line or method signature basis.  If the environment you are running happens to be in a production or testing environment with Obfuscated source, then it will be near impossible for your debugging application to break when you want it to break.  The approach I've seen used at work has been to:
  • Stop the target VM
  • Replace any obfuscated classes (in the form of a .jar library), with non-obfuscated classes
  • Start the target VM
This way the source for your class files in Eclipse will match those in your Target VM.

Hook the Eclipse Debugger onto Target VM


To use Eclipse as our debugger:
  • In Eclipse, open 'Debug Configurations' (found in the drop down menu next to the bug icon)
  • Create a new 'Remote Java Application' configuration
  • Set the 'Project' to the Eclipse project that contains the classes you want to debug.  I believe this project determines which classpath the debugger will be looking through.  Thus, classes from projects referenced by this project should also be able to be found.
  • Set Connection Type to 'Standard (Socket Attach)'.  This matches our dt_socket option set on the Target VM.
  • Set the Connection Properties:
    • Host: the host of the Target VM (e.g. localhost).
    • Port: the port that the Target VM has exposed for debugging.  This should match the address option we set for the Target VM earlier.
  • Hit 'Debug'

Set Breakpoints on Lines... not on Method Signatures!


Setting breakpoints on Method Signatures then attaching the debugger seems to cause the Target VM to slow to a crippled pace, pretty much killing any chance you have of investigating your issue.  Apparently this happens because Method Breakpoints are "expensive to evaluate" (http://devnet.jetbrains.com/docs/DOC-23).  Avoiding Method Signature breakpoints can save you a lot of pain :).

References


Check out the following sites if you want to learn more details:

Monday, 17 September 2012

Ant Contrib Try/Catch magic! How to Print Exception Messages in a Catch Block

Hello Readers!

This post will cover how to print exception messages in ant using means provided by ant-contrib.  Apologies for the terrible code formatting..  Will get around to fixing it!


The following examples assume you have antcontrib imported into your build file etc.  Here's a silly example of where you might want to use a try catch block; you're zipping up a folder and want to handle any problems that might occur in doing so:

<target name="try.catch.test" >
    <sequential> 
        <antc:trycatch>
            <try>
                <zip destfile="testzip.zip" basedir="testzipdir"/>
            </try>
            <catch> </catch>
        </antc:trycatch>
    </sequential>
</target>
If say, the "testzipdir" folder does not exist, the code above will swallow the exception and allow the build file to continue execution.  Perhaps we want to print this exception out instead.  To do this we need to specify the ant object that the exception will be stored in, then reference this exception and print it out in the catch block.  To specify the exception object we can add the "reference" attribute to the trycatch element e.g.
<antc:trycatch reference="exception">.
In the catch block, we can create a property that references this exception object and echo that out, e.g.
<catch>
    <property name="exceptionprop" refid="exception" />
    <echo>Exception: ${exceptionprop}</echo>
</catch>




as the antcontrib trycatch documentation seems to suggest.  However using a property to store exceptions is pretty inflexible.  What if your try/catch block is inside a for loop?  Once a property is set, it can't be set again, so if more than one exception occurs the exception message becomes useless.

Luckily, you can pull out the String value of objects referenced in ant using the ${toString:} syntax.  In our case, "${toString:exception}" would call the toString method of whatever object is referenced by "exception".  Our catch block becomes:

<catch>
    <echo>Exception: ${toString:exception}</echo>
</catch>
Putting this all together, the following example loops through all directories specified by the "dir.list" property, and attempts to zip them up.  If any of the listed directories do not exist, the zipping fails and an exception is echoed out.




<target name="try.catch.test"> 
  <sequential>
   <antc:for list="${dir.list}" param="dir">
    <sequential>
     <antc:trycatch reference="exception">
      <try>
       <zip basedir="@{dir}" destfile="@{dir}.zip">
      </zip></try>
      <catch>
       <echo>Exception: ${toString:exception}</echo>
      </catch>
     </antc:trycatch>
    </sequential>
   </antc:for>
  </sequential>
 </target>






Calling this target using ' ant try.catch.test -Ddir.list="bleh,build,Test" ' where directories "build" and "Test" exist but "bleh" does not, will result in the following output:





try.catch.test:
[echo] Exception: C:\Work\build.xml:118: C:\Work\bleh not found.
[zip] Building zip: C:\Work\build.zip 
[zip] Building zip: C:\Work\Test.zip




Hope you've found this useful!

Sunday, 5 August 2012

Handy use of Oracle Metadata

Need to run an sql statement on multiple tables in your database?  Nauseous about having to copy/modify/paste/run again and again?  Using an Oracle database?!  Well perhaps the following will help to significantly mitigate your woes.

The idea is to use Oracle Metadata to select the tables of interest inside a string containing the SQL you wish to run.  The output of this query will be the list of SQL statements that you otherwise would have had to painstakingly construct by means of copy/pasting.  You can then copy this output, paste it back into sqldeveloper, hit run and kick back.

Consider the following example.  I wish to grant Select permissions on every table under my user name to another user:

  1. Run the following:
    • SELECT 'GRANT SELECT ON ' || TABLE_NAME || ' TO Other_User;' FROM USER_TABLES;
    • "Other_User" is the name of the database you wish to grant select permissions to.
  2. Copy the output of the above run into SQLDeveloper and hit run again.
Simple and useful.  Cheers to Renae Carr for the example.

Sunday, 24 June 2012

Jasper Report Server - Hyperlinks to Subreports!

Dearest potentially non-existent readers,

My first post here will be a small note on how to configure Jasper Reports running on Jasper Report Server to contain hyperlinks to subreports.  This may seem simple and intuitive but it really isn't.  I've witnessed a lot of confusion and red-herring chasing on the net about this so I figured it's worth writing a rough set of instructions for how to do this.  Here it is:

Sub Report

  1. In Jasper Reports Server, Create a separate Jasper Report for the subreport of choice.
  2. Create an Input Control that matches every parameter you expect to be passed to the subreport through the hyperlink.

Parent Report

  1. Right click on a text field of choice and select 'Hyperlink'.
  2. Set 'Hyperlink target' to "Self".
  3. Set 'Hyperlink type' to "ReportExecution".
  4. Click on 'Link parameters'. 
    1. Create a report parameter called '_report'. 
    2. Set its expression to a repository location using the "repo:" syntax.  This part is strange.. it seems the url you provide here should be relative to two parent directories above the current report... e.g. for parent report  at "/organizations/organization1/reports/parent", subreport at "/organizations/organization1/reports/subreport", set '_report' parameter to "repo:/reports/subreport" (with quotes).
  5. Set all the report parameters required.  Ensure that the names of these parameters match the parameter names of the Input Controls defined for the sub report.
  6. Upload the report to Jasper Server
The way I trial and error'd my way through figuring out what to set for the '_report' parameter was to view the hyperlink created in the parent report (using firebug) and copy its value into a text file, then open the subreport by itself and copy its url into a text file.  Observing the &reportUnit parameter:



 URL:  
  &reportUnit=%2Forganizations%2Forganization1%2Freports%2Fsubreport  
 Hyperlink:  
  &reportUnit=repo%3A%2Forganizations%2Forganization1%2Freports%2Fsubreport  

.. it became clear that tweaking the "_report" parameter until the 'reportUnit' parameters were identical (save for the "repo:" prefix in the hyperlink) made for a working hyperlink.
For your reference, the error you get when clicking on a hyperlink that isn't correctly set is the following:
 java.lang.NullPointerException at   
 com.jaspersoft.jasperserver.war.action.ResourceTypeMappingAction.doPreExecute(ResourceTypeMappingAction  
 .java:53) at org.springframework.webflow.action.AbstractAction.execute(AbstractAction.java:186) at   
 org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:51) at   
 org.springframework.webflow.action.EvaluateAction.doExecute(EvaluateAction.java:79) at   
 org.springframework.webflow.action.AbstractAction.execute(AbstractAction.java:188) at   
 org.springframework.webflow.execution.AnnotatedAction.execute(AnnotatedAction.java:145) at   
 org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:51) at   
 org.springframework.webflow.engine.ActionState.doEnter(ActionState.java:101) at   
 org.springframework.webflow.engine.State.enter(State.java:194) at   
 org.springframework.webflow.engine.Flow.start(Flow.java:535) at   
 org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:364) at   
 org.springframework.webflow.engine.impl.RequestControlContextImpl.start(RequestControlContextImpl.java:234)   
 at org.springframework.webflow.engine.SubflowState.doEnter(SubflowState.java:101) at   
 org.springframework.webflow.engine.State.enter(State.java:194) at   


Also, it's worth noting that it isn't possible to pass parameters of any type other than those defined by the Input Controls in the subreport :(.  Perhaps there's a way around this?  I dunno...


Hope this helps someone!