Tuesday, June 23, 2015

Q&A on Test Driven Development and Code Smells with James Grenning

The whole Q&A is good but here is my favorite question and answer from the interview.
InfoQ: In your opinion what are the causes why are people not doing technical practices like TDD or refactoring sufficiently or well enough?
Grenning: Even though the technical practice of TDD and Refactoring have been around visibly since 1999 (with the publication of Extreme Programming Explained), most people in software development have no idea what they are.  I recall being a young engineer, having large demands on my time from my employer and family.  There was not a lot of time to devote to learning what the best ideas and techniques are. There are many ideas out there on how to build software.  Not all of them so helpful. So its hard to know where to put your energy.  As a young engineer in a new field, I thought I knew everything too.
With experience came the humbling realization that I did not know everything.  There is a lot to know in this broad and deep field.  We each learned how to program in a very unique way.  For me, a professor showed some examples of C programming constructs and then gave us an assignment to write an operating system.  Go figure it out! And we each did figure out how to program in our own unique way.  It seems that no one was taught how to program. If you think you are already a master of your craft, what motivation if there to learn more?
I give a survey to people that are about to attend my training.  You can see the questions and answers here: Training preparations replies.  You can see the techniques for writing and testing software are all over the map.  Most report using the techniques we used at the university in the 70s, and in industry in the 80s and 90s: print statements, break pointing and single stepping the debugger. Congratulations, it is 2015 and you are using state of the art debugging techniques from the 1970s!  How about trying 1999 state of the art defect prevention with TDD!?
After seeing TDD, engineers tell me they do not have time to write tests.  They do not have time to proactively prevent defects but they do have time to react to those defects.  Engineers also tell me that their boss won’t let them write unit tests.  It should be equivalent to me not not following my doctor's prescription because I’m in a hurry.
The long feedback loops that most developers live with are part of the problem.  Let’s say I provide an estimate of three months to my boss.  After two and a half, I go and deliver the bad news that I need another month.  This repeats.  Finally a subset of the promised functionality is delivered after six months.  It only looked like the engineer was really working when the deadlines were close.  What does this do to the engineer’s credibility?  Not much.
Working in iterations, with slim vertical slices of functionality, delivered every couple weeks, does a lot for a programmers credibility and confidence.  Having the test safety net catches unwanted changes in behavior.  The programmer gets all that for free once they master TDD as it takes about the same amount of time to get the code working in the first place with TDD as it does the 1970s way, Debug Later Programming (see the physics of test driven development).

Tuesday, June 16, 2015

Alfresco SDK 2.1

Just watched this tech talk on the latest version of the Alfresco SDK.



This sums up how you should setup a development environment and develop on top of Alfresco.

Here is a link to the current documentation.




Friday, June 12, 2015

Agile Software Development Videos from Bob Martin

Here are some really good videos about agile development.   Bob Martin is a great presenter. 

These are all pretty long but they are all worth watching.   The first 3 in the list below are my favorites.

Professional Software Development

Craftsmanship and Ethics

Demanding Professionalism


Clean Architecture and Design

The Single Responsibility Principle


The SOLID Principles of OO and Agile Design

Saturday, May 31, 2014

Moving from traditional filesystem storage to ATMOS for Alfresco

I recently had the opportunity to configure Alfresco with ATMOS using the Alfresco S3 connector.

The company I work for has an ATMOS cloud setup across multiple data centers.  

ATMOS is an object-based cloud storage platform to store, archive and access unstructured content at scale.  

We had an existing instance of Alfresco leveraging NetApp storage that I had to migrate to ATMOS.

In order to do this I needed to download and install 2 tools.

The steps to make the move to ATMOS are fairly simple…

    1.  Stop your Alfresco and Solr servers

    2.  Create your S3 bucket with ATMOS FOX. 
    3.  After you create the bucket you must add a non listable meta tag (bucket-mapping-type=one_to_one) to the bucket folder. 

     4.  Copy your files in your contentstore and contentstore.deleted to Atmos using AtmosSync.jar. 

     5.  Update your alfresco-global.properties with your S3 configuration.
          ### S3 Config ###
          s3.accessKey=xxxxxxxxxxxx/xxxx
          s3.secretKey=xxxxxxxxs3.bucketName=bucketNAME

             #s3.bucketLocation=US
             s3.flatRoot=falses3service.https-only=false
             s3service.s3-endpoint=ATMOSHOST
             s3service.s3-endpoint-http-port=8080#
             s3service.disable-dns-buckets=false
             dir.contentstore=contentstore
             dir.contentstore.deleted=contentstore.deleted
          #Maximum disk usage for the cache in MB 

             system.content.caching.maxUsageMB=51200
             #Maximum size of files which can be stored in the cache in MB (zero implies no limit)              
             system.content.caching.maxFileSizeMB=0 

      6.  Back up your DB if you haven’t already

      7.  Update all records in the ALF_CONTENT_URL table (store:// to s3://)
               UPDATE alf_content_url SET content_url = replace(content_url, 'store:', 's3:’)

 
     8.   Startup Alfresco and Solr servers and you should be good to go.   


Once you have verified that Alfresco is functioning properly you can repurpose the filesystem storage.

Wednesday, January 8, 2014

Duplicate entries put into HashSet Java issue

I have recently run into an issue using HashSet.addAll(Object) where duplicates are added to my Set.

I even made sure that the Object I was using Overrode hashCode().

Apparently the addAll() implementation for HashSet doesn't check for duplicates.  This is bad because a reason for using a Set over a List is to avoid duplicate values.

If you loop through all of the values in the collection you are adding to the Set it works as expected not adding the duplicates.  This is the approach I took to get around this issue.

for (item in myCollection){
    set.add(item)
}

vs what I was trying to do which didn't work:

set.addAll(myCollection)

Another approach could be extend the HashSet and override the addAll() with the logic I used.


Saturday, June 22, 2013

JUnit TemporaryFolder Rule


If you need a temporary directory or file for testing and you are using jUnit, @Rule together with TemporaryFolder solves your problem. 
The TemporaryFolder Rule allows creation of files and folders that are guaranteed to be deleted when the test method finishes (whether it passes or fails) 
@Rule

public TemporaryFolder tempFolder = new TemporaryFolder();
...

@Test
public void testFileCreation (){
        File myFolder = tempFolder.newFile("test.);
        fileGenerator.createFiles(2, myFolder);
        myFolder.listFiles().length == 2;
}
The files that were generated will be deleted once the test finishes executing.

Wednesday, May 15, 2013

Using Groovy Closures To Simplify Working With Alfresco Transactions

If you are familiar with Alfresco transactions than you will be familiar with the following:
  
Boolean result = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Boolean>() {
            public Boolean execute() throws Throwable {
                //Your code
                return true;
            }
}, false, true);
This is quite a bit of code and gets ugly if you start embedding a bunch of code inside this block. It is also not very testable with out some crazy mocking.


Groovy Closures to the rescue. http://groovy.codehaus.org/Closures
I created a simple TransactionHelper Groovy class with a method that takes a closure and wraps the closure inside of the above code required for a transaction and wired it as a Spring Bean.

import org.alfresco.repo.transaction.RetryingTransactionHelper
import org.alfresco.service.transaction.TransactionService
class TransactionHelper {
    private TransactionService transactionService
    def executeInSperarateTransaction(closure) {
        Boolean result = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Boolean>() {
            public Boolean execute() throws Throwable {
                closure()
                return true
            }
        }, false, true)
    }
    void setTransactionService(TransactionService transactionService) {
        this.transactionService = transactionService
    }
}

Now if I need to execute a transaction I can simply do the following.
transactionHelper.executeInSperarateTransaction({ nodeService.addAspect(nodeRef, MyModel.THUMBNAIL_ASPECT, new HashMap<QName, Serializable>())})


You can simply pass a closure statement like above or pass in a closure like the following.

def closure() {
  def localVariable = new java.util.Date()
  return { println localVariable }
}
transactionHelper.executeInSeperateTransaction(closure)
 
For more information on Groovy and Closures see http://groovy.codehaus.org/Closures