Less Code More Better

Use Null Contracts

JSR 305 org.eclipse.jdt.annotations

import org.eclipse.jdt.annotations.*;

@NonNullByDefault
public class MyClass
{
...
}

Bad

Good or Better

Object myMethod( Collection parameter )
{
    if ( ( parameter != null )
        || ( parameter.size() != 0 ) )
    { return 
        doSomethingThatMayReturnNull(
            parameter );
    } else { return null; }
}
@NonNull Optional<TypedResult>
 myMethod( @Nullable final
    Iterable parameter )
{
    if ( parameter == null )
        return Optional.absent();

    return Optional.fromNullable(
        doSomethingThatMayReturnNull(
            parameter.first() ) );
}

@NonNull Optional<TypedResult>
 myBetterMethod( 
    @NonNull final Optional<TypedParameter>
        parameterIfAny )
{
    if ( ! parameterIfAny.isPresent() )
        return Optional.absent();

    return doSomethingOptionalResult(
        parameterIfAny.get() ) );
}

Best
(in Jdk7)

import org.eclipse.jdt.annotations.NonNullByDefault;
import org.eclipse.jdt.annotations.Nullable;

@NonNullByDefault
public class MyClass
{
  Optional<TypedResult>
    myMethod( @Nullable final parameter )
  {
    if ( Strings
        .isEmptyOrNull( parameter ) )
            return Optional.absent();

    return Optional.fromNullable(
        doSomethingThatMayReturnNull(
            parameter ) );
  }

  Optional<TypedResult>
   myBetterMethod( 
    final Optional<TypedParameter>
        parameterIfAny )
  {
    if ( ! parameterIfAny.isPresent() )
        return Optional.absent();

    return doSomethingOptionalResult(
        parameterIfAny.get() ) );
  }
}

Use Guava Optional

Bad

Good

if ( parameter != null )
  return 
  ( parameter.size() > 0 )
   ? parameter.get(0)
    : null
local = Optional.fromNullable( parameter );

return local;

More Optionals

// When you have to return something non-null
// but a proper result isn't available
return Optional.absent();

// When you need to ask and use something that
// might be null and a good default is available
Optional<SomeType> result = Optional.fromNullable(
    getSomeInstance( arguments ) );

return result.or( aGoodDefault );

// When you need to return an iterable collection
// that might be empty because something wasn't
// available
return FluentIterable.from(
    something.isPresent()
        ? ImmutableList.of( something.get() )
            : new ImmutableList.Builder<SomeType>()
                .build();

Offer Fluent Builders

Awkward

Adaptable

final MyWidget myWidget =
    new MyWidget( argA,
        argB, ... argZ );

final MySprocket mySprocket =
    new MySprocket();

    mySprocket.setA( argA );
    mySprocket.setB( argB );

    ...

    mySprocket.setZ( argZ );
// flexible subset and order
final MyWidget myWidget =
    Widget.Builder()
        .setA( argA )
        .setM( argM )
        .setB( argB )
    .build();

// fluent narrative
final MyWidget aWidget =
    Widget.Builder()
        .from( materials )
            .in( store )
                .assemble( parts )
    .build();

aWidget.useIt();

Duck Typing and
Default Quacking

Interfaces

Offer Interfaces that state the methods of a service object that are accessible regardless of the particular compiler-time class type or run-time instance type.

 

Interfaces specify the API contract: name, arguments, returns, exceptions, and nullness

Abstracts

Offer Abstract Classes which implement the Interface that provide harmless or noop behavior for the interface methods.

 

When a method requires instance properties, don't implement a default method.

 

Keep the Abstract Class free of instance state.

@NonNullByDefault
public interface Ducky
{
    public Ducky quack( final DuckEdible food );
    public Ducky fly( final Direction away );
    ...
}

@NonNullByDefault
public abstract class DuckDefault implements Ducky
{
    @Override
    public Ducky quack( final DuckEdible food )
    {
        return this;
    }

    @Override
    public Ducky fly( final Direction away )
    {
        return this;
    }
}

@NonNullByDefault
public class CatDuck extends DuckDefault
{
    @Override Ducky quack( final DuckEdible food )
    {
        meow();

        return this;
    }
}

final Ducky someDuck = DuckFactory.species()
    .with( catNature )
    .with( duckNature )
    .build();

someDuck.quack( someFood ); // yields meow()

Use FluentIterables and ImmutableLists

Caveat Coder

Neither Iterables nor FluentIterables are Collections.
 

They specify a deferred-execution transformation pipeline.
 

The filters and transforms are performed when client-code calls the next() (e.g. *.first().get()) method.
 

They do nothing to the underlying collection when specified in the program logic.
 

Force the filtering and transforming by serializing the iterator (e.g. iterator.toList())

Complicated

Curried Fluent

SomeResult result =
    methodWithNumerousArgs(
        argA,
        new ArgB(),
        argC.getC()
        ...
        argZ );
SomeResult result =
    oneInOneOut( argA )
        .noSideEffect( argB )
            .easilyUnderstood( argC )
            ...
                .simple( argZ );
final FluentIterable<TypeA> Ainstances = 
    FluentIterable.from( providerOfAs );

final FluentIterable<TypeC> Cinstances =
    Ainstances
        .filter( unwantedAs() )
        .filter( wantedAs() )
            .transform( fromAsToBs() )
                .filter( unwantedBs() )
            .transform( fromBsToCs() )
                .filter( wantedCs() )

// perform the first get from the providerOfAs
// and transform that A into a B then into a C
final TypeC someC = Cinstances.first().get();

less code more better

By Lonnie VanZandt

less code more better

  • 788