Monday, August 31, 2009

Design, Don't do it

Are you designing a thread-safe front to a single-threaded resource? Relax.

The wrong way

Write layers and layers of complexly interacting abstraction over an object pool, letting the object pool (hopefully) protect you from threading concerns.

The right way

Use the JDK:

public class FooService {
    private final UnsafeResource resource;
    private final ExecutorService service;

    public FooService(final UnsafeResource resource) {
        this.resource = resource;
        service = createPoolFor(resource);
    }

    public <T, E extends Exception> Future<T> submit(
            final Work<T, E> work) {
        return service.submit(new Callable<T>() {
            T call() throws E {
                return work.use(resource);
            }
        });
    }

    public interface Work<T, E extends Exception> {
        T use(final UnsafeResource resource) throws E;
    }

    // Good place for an extension point depending on your needs
    private static ExecutorService createPoolFor(final UnsafeResource resource) {
        return newSingleThreadExecutor(new ThreadFactory() {
            public Thread newThread(final Runnable r) {
                return new Thread(r,
                        FooService.class.getSimpleName() + ": " + resource);
            }
        });
    }
}

Wednesday, August 26, 2009

Comments on Hipp's A Lesson In Low-Defect Software

Thanks to Alecco Locco for useful comments on Hipp's A Lesson In Low-Defect Software. the full title:

A Lesson In Low-Defect Software
-or-
A Journey From A Quick Hack
To A High-Reliability Database Engine

and how you can use the same techniques to reduce
the number of bugs in your own software projects

Those comments got me to read the paper.

Tuesday, August 25, 2009

A favorite functional idiom in Java

Ok, two favorite functional idioms in Java:

public abstract class Option<T>
        extends Cursorable<T> {
    public static <T> Option<T> some(final T value) {
        return new Option<T>() {
            @Override
            public int size() {
                return 1;
            }

            @Override
            public T get() {
                return value;
            }
        };
    }

    public static <T> Option<T> none() {
        return new Option<T>() {
            @Override
            public int size() {
                return 0;
            }

            @Override
            public T get() {
                throw new IllegalStateException();
            }
        };
    }

    public abstract int size();

    public abstract T get();

    public final boolean isEmpty() {
        return 0 == size();
    }

    @Override
    public final Iterator<T> iterator() {
        return new Iterator<T>() {
            private boolean empty = isEmpty();

            @Override
            public boolean hasNext() {
                return !empty;
            }

            @Override
            public T next() {
                if (empty)
                    throw new NoSuchElementException();
                empty = true;
                return get();
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
}

public abstract class Cursorable<T>
        implements Iterable<T> {
    public static <T> Cursorable<T> over(
            final Iterable<T> it) {
        return new Cursorable<T>() {
            @Override
            public Iterator<T> iterator() {
                return it.iterator();
            }
        };
    }

    public final Cursorable<T> select(
            final Select<T> select) {
        return new Cursorable<T>() {
            @Override
            public Iterator<T> iterator() {
                return new Iterator<T>() {
                    private final Iterator<T> it
                            = Cursorable.this.iterator();

                    private Option<T> current = none();

                    @Override
                    public boolean hasNext() {
                        while (it.hasNext()) {
                            final T next = it.next();
                            if (!select.accept(next))
                                continue;
                            current = some(next);
                            return true;
                        }
                        current = none();
                        return false;
                    }

                    @Override
                    public T next() {
                        if (current.isEmpty())
                            throw new NoSuchElementException();
                        return current.get();
                    }

                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

    public final <U> Cursorable<U> project(
            final Project<T, U> project) {
        return new Cursorable<U>() {
            @Override
            public Iterator<U> iterator() {
                return new Iterator<U>() {
                    private final Iterator<T> it
                            = Cursorable.this.iterator();

                    @Override
                    public boolean hasNext() {
                        return it.hasNext();
                    }

                    @Override
                    public U next() {
                        return project.on(it.next());
                    }

                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

    public interface Select<T> {
        boolean accept(final T input);
    }

    public interface Project<T, U> {
        U on(final T input);
    }
}

And a demo:

public class SelectAndProjectMain {
    public static void main(final String... args) {
        for (final Integer number : over(asList(1, 2, 3, 4))
                .select(new Cursorable.Select() {
                    @Override
                    public boolean accept(final Integer input) {
                        return 0 == input % 2;
                    }
                })) {
            System.out.println("Even: " + number);
        }

        for (final String number : over(asList(1, 2, 3, 4))
                .project(new Cursorable.Project() {
                    @Override
                    public String on(final Integer input) {
                        return Integer.toBinaryString(input);
                    }
                })) {
            System.out.println("Binary: " + number);
        }
    }
}

Produces:

Even: 2
Even: 4
Binary: 1
Binary: 10
Binary: 11
Binary: 100

Although I am afraid to add this to my project at work. I worry for the maintainer after me.

UPDATE: A coworker called me to the mat for extreme terseness. Demonstrating a more fluent style, I refactored the demo code:

public class SelectAndProjectMain {
    public static void main(final String... args) {
        final List<Integer> numbers = asList(1, 2, 3, 4);

        for (final Integer number : over(numbers).select(evens()))
            System.out.println("Even: " + number);

        for (final String number : over(numbers).project(binaries()))
            System.out.println("Binary: " + number);
    }

    static class Evens
            implements Cursorable.Select<Integer> {
        static Evens evens() {
            return new Evens();
        }

        @Override
        public boolean accept(final Integer input) {
            return 0 == input % 2;
        }
    }

    static class Binaries
            implements Cursorable.Project<Integer, String> {
        static Binaries binaries() {
            return new Binaries();
        }

        @Override
        public String on(final Integer input) {
            return Integer.toBinaryString(input);
        }
    }
}

UPDATE: And lastly, more on Option from the land of Scala.