Maintainability: if you can only just understand what you developed, no-one else will be able to

Among Software Developers there is a distinct range of abilities and level of understanding that rangesĀ from ‘ability to solve business problems’ and then on the other extreme is ‘ability to write compilers’. I’m not saying that if you are capable of writing compilers you cannot solve business problems, because if you work for a tools company that makes it’s money from developing compilers, you’re most likely in the right place.

The issue is, on the majority of software development projects, either in-house development or consulting engagements, you don’t often (if at all) find yourself solving anything technically that has the complexity of developing compilers. This is where the issue is with different developers on this ability/skill scale. For a developer who is entirely focused on solving business problems, and on a consulting project that is the reason you are there, this type of developer will have a hard time understanding why The Compiler Developer is inventing all kinds of wild and wacky technical solutions to problems involving every possible API and open source project they can find. The Compiler Developer on the otherhand has trouble understanding why The Business Problem Solver has no interest in investing time and budget in incorporating all these technical gizmos and doo-dads into the system that from The Business Problem Solver’s point of view just increase the risk to the project.

In reality I believe a project needs to have a good mix of ability to solve business problems and ability to use technology to best solve these problems, and it’s up to the management of the project to keep this balance healthy. If you swing the mix too rich in either direction I think you’ll have a hard time getting anything complete.

One of my most favorite quotes sums up the issues that can be created by leaving Compiler Developers to their own devices:

"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're
as clever as you can be when you write it, how will you ever debug it?"

 

– Brian Kernighan, the ‘K’ in ‘K&R’ (Kernighan and Ritchie), co-developer of the C programming language, fromĀ http://en.wikiquote.org/wiki/Brian_Kernighan

Kernighan makes a great point, if you have developed something that is so complicated that you have no hope of debugging it, how will anyone else be able to understand it? This is why, unfortunately from the point of view to the Compiler Developers, you need to develop code close to the lowest common denominator of technical abilities on any project, otherwise you are potentially creating a maintenance nightmare for yourself or your client with code so complex that no-one is able to understand, maintain, or fix.

Linking to other actions from a view page

Use the <g:link> tag to link to another action. For example:

To link to ‘someAction’ in the same controller being used to handle this current view page, passing an id:

<code>&lt;g:link action="someAction" id="${exampleDomainObject.id}"&gt;</code>

If the action is in a different controller, then specify the controller as well:

<code>&lt;g:link action="someAction" controller="OtherControlller" id="${exampleDomainObject.id}"&gt;</code>

Changing the default list method

the default list method in generated controllers looks like this:

<code>
    @Property list = {
        [ exampleList: Example.list( params ) ]
    }
</code>

This can be changed to return results however you need. For example, to execute an HQL statement to return the results in reverse order of id, use the following:

<code>
    @Property list = {
        [ exampleList: Example.findAll( "from Example order by id desc", params ) ]
    }
</code>

Understanding Acegi’s FilterSecurityInterceptor and URL matching

The ‘CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON’ parameter to FilterSecurityInterceptor means exactly that – URLs are converted to lower case for comparison with the patterns that you define.

If you use CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON, then make sure all the URL patterns you specify are also in lower case, otherwise you will never get a match. This seems obvious, but it took me several hours of trial and error before I spotted what was not working in my configuration.

For example, take this snippet of configuration:

<code>
    &lt;bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt;
        &lt;property name="authenticationManager"&gt;
        &lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
        &lt;property name="accessDecisionManager"&gt;
        &lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
        &lt;property name="objectDefinitionSource"&gt;
            &lt;value&gt;
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                PATTERN_TYPE_APACHE_ANT
                /acegilogin.jsp*=ROLE_ANONYMOUS, ROLE_ADMIN
                /=ROLE_ANONYMOUS, ROLE_ADMIN
                /index.jsp=ROLE_ANONYMOUS, ROLE_ADMIN

                /item/show/**=ROLE_ANONYMOUS, ROLE_ADMIN
                /item/list/**=ROLE_ANONYMOUS, ROLE_ADMIN
                /item/doSomeOtherThing=ROLE_ANONYMOUS, ROLE_ADMIN
                ...
    &lt;/bean&gt;
</code>

The URL ‘/item/doSomeOtherThing’ is never going to be matched, since the incoming URLs for comparison are converted to lowercase by the CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON instruction.