Monday, 09. October 2006

clipboard considered harmful - a funny look at developers 'laziness'

software developers are lazy ... by nature.
well, not all of them are lazy. but most of us are tempted to avoid unnecessary efforts (this seems to be a good attitude, normally). for example, we all don't want to write boilerplate code - just stuff, no fluff ...

one of the most dangerous challenges in this regard (because of its easy adoption and therefore such attractive) is the usage of the clipboard. clipboard enables us to comply to our laziness in a 'wrong' way. it's easy to duplicate code via copy n paste, to often only to alter the copied code marginally afterwarts in order to adapt it's behaviour to the new specific area.

for what reasons?
is it because we don't have enough confidence in the existing code so we don't dare refactoring? don't we have a sufficient test base so we dont dare refactoring? do we have to little knowledge about the domain in order to be able to abstract and therefore don't dare refactoring? beside of the violation of DRY you should ask yourself if it could be because of what we may call a smell of uncertainty (that would be an issue for a post of its own).

back to the clipboard. maybe we should deactivate clipboard in our IDE generally? ... don't offer clipboard to a developer in principle, never ... ever.
if we could'nt fall back to the clipboard, we would be forced to ... copy the code by hand (of course we have no alternative to duplicate code, have we? time is short and who cares about DRY anyway ... ;o)).
but now we are in a situation, where it will come to a natural selection:

the evil developer maybe would in fact copy the code by hand! this developer would take an unreasonable amount of time completing his task and therefore have to live with a higher risk to get the push (this very seldom occuring scenario would also be worth another post). a special kind of darwin award, developers only.

the good developer would be (hopefully) again to lazy to copy manually and maybe would start to reflect how to avoid this boring activity to type the code by hand. that is our chance to eliminate code duplication and instead searching for alternatives. maybe we could factor out the needed code and reuse it in different areas. maybe we have to abstract from one conrete context and look behind the curtains to recognize the core intention - object orientation offers some options, such as template method, strategy, polymorphism, ...
perhaps we have to deal with foreign code or - even worse - with some concepts of the domain. don't worry ... this is a chance to get over the smell of uncertainty (otherwise it's maybe someone other who smells ... ;o))!

now lets get philosophical. lets ask why everyone of us has used clipboard in the past (me too, i have to admit - what's about you?) but maybe we should better ask instead why we sometimes consciously violate DRY?

apart from the harmless cases where we slothfully use the clipboard to virtually transport data from one place to another, what's about the real risky cases where we are temped to copy and vary methods or whole classes?
it seems that most of us are anthropological influenced. we like to keep control over situations (in the good old subject-object-relationship, we want to be the subject), more than ever when we act in an uncertainty context.

whenever we act in such an partly unfamiliar context, it seems that control slips away, because we don't know all influencing factors (now subject - object - relationship has turned. it looks like the context is driving us and thats a situation we are a little concerned of). if we have not captured the whole situation mentally, we tend to reinvent the wheel again. starting over from scratch lets us keep control because it seems that we know how things work from ground up. building my own class bottom up reduces the risk to destroy the behaviour of these other class which seems to be pretty similar ... lets simply copy most of'em and adapt to my own needs. hello broken window ...

so how to escape from this state of fear?
simply dismissing clipboard is probably not the best pill in this case.
most of time the root of all evil is very clear: immoderate code complexity, as Eric Evans (domain driven design) says: 'when complexity goes out of hand, developers can no longer understand the software well enough to change or extend it easily and safely. there comes most of the uncertainty. if you don't understand it, you don't want to touch it ... and once again: don't be lazy - but this time on a different level: try to understand the domain you are designing for and write expressive code that reflects the core of the business domain. if you're in the code - you're in the business ...
key to refactoring is trusting your code. trusting your code is recognizing the functionality in your code. recognizing the right functionality is knowing the business. knowledge of the business is best expressed in code itself and tests that checks the code.

modeling the code as a rich source of business knowledge brings other advantages. because developers like best to deal with code rather than external documentation, this kind of laziness is no problem since the code documents the domain in a clear, significant way. it's also easier to share common concepts and design decisions when the code represents this one to one. you can transfer the meaning of new code in a really plain way ... but please not via clipboard ;o)




Posted by mario.gleichmann at 20:32:36 | Permanent Link | Comments (1) |

Saturday, 07. October 2006

flexible closures in java with generics

with the upcoming of the new dynamic languages like groovy or ruby, functional programming seems to flow into developer minds of many. one key to it's success is it's mighty expressivenes when using closures. even in java world, closures are highly discussed now for future versions of the language.

by now we can use anonymous classes to simulate the behaviour of closures in a similar way, even not so powerfull as with the true lambda calculus behind the idea of closures. first of all, we have an interface named Closure, which ought to represent our code block:

public interface Closure{
  public Object exec( Object arg );

}

now if we have some classes which supports our closure ...

public class BooksCollection{
  private Book[] books;
  public Collection filter( Closure closure ){
    Collection filteredBooks = new ArrayList();
    for( Book book : books ){
      if( (Boolean) closure.exec( book ) ){
        filteredBooks.add( book );
      }
    }
    return filteredBooks;
  }
}

... we can simply define an ad hoc closure to filter some desired books:

Collection booksByGoethe = classcialBookCollection.filter(
  new Closure(){ public Object exec( Object book ){
    return ((Book) book).getAuthor().equals( "Goethe" ); } } );

this solution has some serious drawbacks: one of the strength of closures is it's unbound and dynamic behavior to any kind of datatypes. you can pass a closure to any datatype who supports closures, where the closure is not restricted to a specific type of it's arguments nor it's return type. where you once pass an instance of type Book, you are free to use a closure to some other times, where you will pass instances of another type, let's say Report. as you have seen in our simple example, in a half typed language like java you can achive a similar freedom by limiting the argument and return types to type Object. but this comes with a risky tradeoff.

1. loss of type safety
the compiler can't check if your closure really returns an instance of type Boolean back to the BookCollection.
(the compiler can't also check if the class BookCollection really passes only instances of type Book to the closure)

2. bothersome typecasting
in order to evaluate the passed Book and retrieve some of its properties inside of our closure, we have to cast from Object to Book.
same is true for BookCollection. we have to cast to Boolean in order to decide whether to adopt the current book to the filteredBooks or not.

well this was a somewhat humble solution ... before generics.

generics to the rescue

with generics we can now define more flexible closures which exempt us from the bothersome work of typecasting and giving the compiler a chance to check the proper usage.

How do our interface Closure looks like with a generic touch?

public interface Closure<R,A> {
    public R exec( A arg );
}

as you can see, we define two generic types. one for the return type (R) and a second for the type of the argument (A). now this is still straightforward.

whats about our supporting classes? they now have the chance to define, which type of closures they will accept.
in order to make things more interesting, we will now extend the example and introduce a class CollectionUtils, which offers a couple of collection related functions, like filtering, converting or applying some processing to all elements of a collection:

public class CollectionUtils {

    public static <T> Collection<T> filter( Collection<T> source, Closure<Boolean,T> filter ){
        Collection<T> filteredElements = new ArrayList<T>();
        for( T item : source ){
            if( filter.exec( item ) ){
                filteredElements.add( item );
            }
        }
        return filteredElements;
    }
   
    public static <T,S> Collection<T> convert( Collection<S> source, Closure<T,S> converter ){
        Collection<T> convertedElements = new ArrayList<T>();
        for( S item : source ){
            convertedElements.add( converter.exec( item ) );
        }
        return convertedElements;
    }
   
    public static <T> void each( Collection<T> source, Closure<?,T> visitor ){
        for( T item : source ){
            visitor.exec( item );
        }
    }
}

lets take a closer look at the individual methods.
the filter() method will create a new collection for the books to filter which it will return after processing the source collection. the type of the filtered elements in this collection is of the same type of the elements in the source collection. it's also the type of the argument, which the closure have to provide. further on, we demand from our closure to return an instance of type Boolean.

what do we have achieved?
first of all, we can use closures in a typesafe way, independent of any concrete type. regardless of filtering books, reports or shop items, you only have to provide a proper closure with the adequate type parameters. let's look on how to filter books with our new closure:

public class CollectionUtilsTest {

    private Collection<Book> books;
   
    @Before
    public void setUpBooks(){
        books = Arrays.asList( 
                new Book[]{
                    new Book( "A Simple One", "Cole", 29.99f ),
                    new Book( "New and fresh", "Simmons", 59.99f ),
                    new Book( "The Big One", "Cole", 19.99f ),
                    new Book( "Foos and Bars", "Adams", 24.99f ),
                    new Book( "The Answer", "Iverson", 24.99f )
                } );
    }
   
    @Test
    public void testFiltering() throws Exception{
       
        Collection<Book> filtered =
            CollectionUtils.filter( books , new Closure<Boolean, Book>(){
                public Boolean exec(Book book) {
                    return book.author.equals( "Cole" );
                }} );
       
        assertEquals( 2, filtered.size() );
    }

as you can see, we've achieved even more: By instantiating a closure with the appropriate type parameters, there is no need to cast the argument. we can directly refer to the correct argument type Book.
(just as well we do not have to cast to Boolean in the method filter() , since it demands a return type Boolean from our closure). now the compiler is also able to check against the correct type parameters, so we have type safety at compile time.

our next method convert() is written in the same manner. this time we allow the closure to determine his return type by himself as he is responsible for the type of the converted elements. thereby the closure also determines the type of the returned collection for the converted elements of the method convert(). further on we link the type of the closure's argument to the corresponding type of the elements of the source collection, so we are typesafe when we pass the elements to the closure. let's look at the example, where we want to extract the titles of the books:

    @Test
    public void testConversion() throws Exception{
       
        Collection<String> titles =
            CollectionUtils.convert( books , new Closure<String, Book>(){
                public String exec(Book book) {
                    return book.title;
                }} );
       
        assertEquals( 5, titles.size() );
        assertTrue( titles.contains( "A Simple One" ) );
        assertTrue( titles.contains( "New and fresh" ) );
        assertTrue( titles.contains( "The Big One" ) );
        assertTrue( titles.contains( "Foos and Bars" ) );
        assertTrue( titles.contains( "The Answer" ) );
    }    

our last method each() offers no spectacular new insights. the only thing to mention is the fact, that it does'nt depend on any return type of the closure. therefore the method does'nt mind about it and express this freely.

summary

as we have seen, generics offer a new dimension to define typesafe closure-like constructs in java without the need of cumbersome and code blowing typecasts.
of course we can't obtain the same power as with true closures in languages with built-in support for functional programming. but used in moderate doses, there is potential to improve the expressiveness of our code markedly!
Posted by mario.gleichmann at 21:36:45 | Permanent Link | Comments (5) |

my favorite eclipse shortcuts for code browsing

'you have to have a set of tools, which you should use without any breakdowns' i once read a sentence in the manner of the above in 'The Pragmatic Programmer'.

for most developers eclipse is such a tool, so for me. here are some of my favorite shortcuts which helped me to keep my fingers on the keyboard when browsing through the code ...

ctrl + shift + t
search for (java) types
you can enter only the uppercase letters of your wanted class or interface. eclipse will bring only such types to the top which contains these uppercase letters inside their names.
i.e. entering BAD finds BankAccountDAO or BaseAssertionDummy

ctrl + shift + r
searches for any resources .
the same is true for search with uppercase letters as mentioned above. beside types, eclipse will list any other resources, i.e. jsp, xml, properties, ...

ctr + o
searches for a method inside a type. let you jump quickly to the beginning of a method.

F3
opens the declaration of a type. let you jump quickly from a type to another type. just place the cursor to the declared type you want to jump to and hit F3. you can alternatively push ctrl and click onto the type you want to open.

alt + arrow left / rigth
lets you jump right back (and forth) to the location (i.e. type declaration) you came from.

ctrl + t
shows the type hierarchy of a type. just place the cursor to the declared type with the wanted hierarchy and hit ctrl + t. now you can scroll through the hierarchy (arrow up / down) and open the desired supertype or subtype (by hitting enter).

ctrl + shift + g
searches for all references  of a type or method. just place the cursor the the  declaration of the type or method and hit ctrl + shift + g. now you have an overview of all types in workspace which references your class / method.

Posted by mario.gleichmann at 18:25:22 | Permanent Link | Comments (3) |

search and replace with regular expressions in eclipse

eclipse supports regular expressions within his dialog 'search and replace' (ctrl-f). you only have to activate the corresponding checkbox 'Regular Expressions' in the options pane.

let's see eclipse in action by a simple example. suppose you want to surround a couple of numbers with some text:

100 should be replaced by
INSERT INTO kredit( pk_id, fk_sicherheit ) VALUES ( 1, 100 );
200
should be replaced by
INSERT INTO kredit( pk_id, fk_sicherheit ) VALUES ( 1, 200 );

300
should be replaced by
INSERT INTO kredit( pk_id, fk_sicherheit ) VALUES ( 1, 300 );
and so on ...

in most regular expression dialects you can refer to a piece of chars which are surrounded by parenthesis with the $-operator. this is also true in eclipse. with this in mind, the task is easy. now you can search for the numbers using

^([0-9]+)$

see the parenthesis around the number expression? now we can refer to the matching in the replacement:

INSERT INTO kredit( pk_id, fk_sicherheit ) VALUES ( 1, $1 );

of course you could reference some more subexpressions (also surrounded by parenthesis) by incrementing the reference counter (as you know, the order of the starting parenthesis within the expression is relevant to the reference counter - $1, $2, $3 and so on ).

Posted by mario.gleichmann at 16:50:27 | Permanent Link | Comments (0) |

welcome to the jungle

are you developing software? don't you sometimes feel like living in a jungle? almost every day an announcement of a new framework, method or a new release of whatever improves your productivity.
but what's really essential? what's the real core of developing software that keeps you on the right track through all this groovy coppice?

when i first read the inspiring book 'The Pragmatic Programmer' by Andrew Hunt and David Thomas, there was especially one section i was deeply impressed about. In short terms: stay curious, invest in your skills and reflect about your everyday work in order to evolve.
this gave me a kick - i took (and still take) this as an encouraging invitation to investigate ...
the big thing i have learned is that you should let your reservations behind and have fun to face new challenges. you can't lose but earn new experience and as an extra gift - receive more and more a clearer view for what's really helpful and essential in developing good software.

it's worth to investigate - even if it's done step by little step (remember 'Kaizen'?). In this blog i will record some of my toughts and insights that may come with these little steps ...

i would be glad, if you like to accompany me on this way and give me some critical comments or some other feedback - keep the knifes sharp ...
Posted by mario.gleichmann at 15:05:18 | Permanent Link | Comments (0) |
1 2