Kai Witte's Blog http://witte-consulting.com/blog Brief articles by Kai Witte Thu, 01 May 2014 16:03:04 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.7 Avoid destructive updates http://witte-consulting.com/blog/avoid-destructive-updates/ http://witte-consulting.com/blog/avoid-destructive-updates/#respond Thu, 01 May 2014 15:32:20 +0000 http://witte-consulting.com/blog/?p=372 This is an excerpt from a document I’ve been working on for some time now.

A destructive update to a variable or field means assigning a new value to it even though it already has a value assigned. Let’s have a look at the anamnesis of a small piece of code which I found in the VCS history.

ValueType x = null;if (yType.isSetType()) {
    x = yType.getValue();
} else {
    x = yType.addNewValue();
}
x.doSomething();

x is first null, then something else is assigned depending on some condition. The next programmer introduced this:

ValueType x = null;
if (yType.isSetType()) {
    x = yType.getValue();
} else {
    if (unsetFlag) {        yType.unsetValue();
        x = yType.addNewValue();
    }
}
x.doSomething();

Now it still compiles, but a NullPointerException will occur at runtime – sometimes. That’s bad. The principle “Fail early, fail hard” is best applied by failing at compile time with a compile time error. The unnecessary destructive update prevented that. Better start with:

final ValueType x;if (yType.isSetType()) {
    x = yType.getValue();
} else {
    x = yType.addNewValue();
}
x.doSomething();

Then after

final ValueType x;
if (yType.isSetType()) {
    x = yType.getValue();
} else {
    if (unsetFlag) {
        yType.unsetValue();
        x = yType.addNewValue();
    }
}
x.doSomething();

it doesn’t compile anymore (can you see why?). The compiler caught the problem before it was too late.

The programmer is forced to take action and will change to what he really needed instead:

final ValueType x;
if (yType.isSetType()) {
    x = yType.getValue();
} else {
    if (unsetFlag) {
        yType.unsetValue();
    }
    x = yType.addNewValue();
}
x.doSomething();

By the way, Eclipse doesn’t even show a warning for the code that causes the NPE. Especially when working with bad code, the inspection features of Intellij Idea are mandatory. When working with professionals, an editor and a compiler will do.

Another example:

int x = 7;
if (b) x = 8;
if (c) x = 9;

if without else is usually bad, and destructive updates are used in this example as well. It’s not an example from the real world like the one above that caused a concrete problem, but still should be rewritten to this:

final int x;
if (b) x = 8;
else if (c) x = 9;
else x = 7;

Destructive updates are one of the biggest problems in old software monoliths. Just by declaring everything final, one will automatically move towards a functional programming style and avoid many problems. “Everything” means everything: parameters, Exceptions in catch blocks, fields, local variables. I noticed something interesting: Programmers who avoid destructive updates themselves are much, much better at detecting problems related to destructive updates in other people’s code. Destructive updates are not something that bad programmers recognise as a phenomenon, they just do it without being aware of the consequences.

Now a dispute between communities that recognise this principle is whether it should be followed absolutely in languages like Java or not. There are many situations in which it would be clumsy and inconvenient to absolutely avoid destructive updates in Java due to language limitations. Some programmers compromise in that case, others don’t.

]]>
http://witte-consulting.com/blog/avoid-destructive-updates/feed/ 0
List mapping in Java 8 http://witte-consulting.com/blog/list-mapping-in-java-8/ http://witte-consulting.com/blog/list-mapping-in-java-8/#respond Wed, 23 Apr 2014 19:36:31 +0000 http://witte-consulting.com/blog/?p=357 For Java 5 – 7, see List type mapping in Java.

A common problem is to convert a List of type X to a List of type Y, given a well-defined function from X to Y. For example, we have a List<Double> and want a List<Long> containing those numbers rounded. In Java 8, there is a quick solution for this:

final List<Double> l = Arrays.asList(1.1, 2.9, 3.3, 4.6, 5.5);
final List<Long> solution1 = l.stream().map(Math::round).collect(Collectors.toList());
System.out.println(solution1); // [1, 3, 3, 5, 6]

Short enough, but not lazy: We may not always need to access every member of the List, and thus we don’t need to allocate memory for the whole result and calculate it all at once. In those situations, I use this utility method:

/**
 * Maps a List of one type to a List of another type.
 *
 * @param f    the function used to convert from type E to type F
 * @param list the List to be mapped
 * @param <E>  the domain
 * @param <F>  the codomain
 * @return a new List with the elements mapped
 * @throws NullPointerException iff any argument is <code>null</code>
 */
public static <E, F> List<F> map(final List<E> list, final Function<E, F> f) {
  Objects.requireNonNull(list);
  Objects.requireNonNull(f);
 
  return new AbstractList<F>() {
    @Override
    public F get(final int index) {
      return f.apply(list.get(index));
    }
 
    @Override
    public int size() {
      return list.size();
    }
  };
}

Usage example:

final List<Double> l = Arrays.asList(1.1, 2.9, 3.3, 4.6, 5.5);
final List<Long> solution2 = map(l, Math::round);
System.out.println(solution2); // [1, 3, 3, 5, 6]

As you can see, line 2 is much simpler now (once map is available as a global utility method). It allocates very little memory, which does not depend on the size of the source List, and doesn’t run Math::round yet. However, when the same number is accessed more than once, it has to calculate it again. So it’s not always the best solution.

]]>
http://witte-consulting.com/blog/list-mapping-in-java-8/feed/ 0
Chess puzzle: Win even more http://witte-consulting.com/blog/chess-puzzle-win-even-more/ http://witte-consulting.com/blog/chess-puzzle-win-even-more/#respond Sat, 01 Feb 2014 13:13:28 +0000 http://witte-consulting.com/blog/?p=354
Chess puzzle: Win even more

Obviously a bad move for white. But how can black take the best advantage of it?

Hint: show

Solution: show

]]>
http://witte-consulting.com/blog/chess-puzzle-win-even-more/feed/ 0
Chess puzzle: Missing a chance http://witte-consulting.com/blog/chess-puzzle-missing-a-chance/ http://witte-consulting.com/blog/chess-puzzle-missing-a-chance/#respond Tue, 28 Jan 2014 11:11:40 +0000 http://witte-consulting.com/blog/?p=349

black to move and win material

Solution: show

]]>
http://witte-consulting.com/blog/chess-puzzle-missing-a-chance/feed/ 0
Chess puzzle: Blunder in the opening (medium) http://witte-consulting.com/blog/chess-puzzle-blunder-in-the-opening-medium/ http://witte-consulting.com/blog/chess-puzzle-blunder-in-the-opening-medium/#respond Sun, 26 Jan 2014 12:20:58 +0000 http://witte-consulting.com/blog/?p=345
Chess puzzle: Blunder in the opening

White to move and win material

So I chased his knight around for a bit, until he decided to interrupt the chase with a tempo.

Solution: show

]]>
http://witte-consulting.com/blog/chess-puzzle-blunder-in-the-opening-medium/feed/ 0
Chess puzzle: Pin vs. tempo http://witte-consulting.com/blog/chess-puzzle-pin-vs-tempo/ http://witte-consulting.com/blog/chess-puzzle-pin-vs-tempo/#respond Sun, 12 Jan 2014 22:14:25 +0000 http://witte-consulting.com/blog/?p=330
Chess puzzle: Pin vs. tempo

White to move and win material


Hint: show

]]>
http://witte-consulting.com/blog/chess-puzzle-pin-vs-tempo/feed/ 0
Chess puzzle: not a simple trade after all … (easy) http://witte-consulting.com/blog/chess-puzzle-not-a-simple-trade-after-all/ http://witte-consulting.com/blog/chess-puzzle-not-a-simple-trade-after-all/#respond Tue, 07 Jan 2014 13:02:02 +0000 http://witte-consulting.com/blog/?p=324
chess puzzle: not a simple trade after all ...

My opponent and me missed something here ... white to move and win material.

]]>
http://witte-consulting.com/blog/chess-puzzle-not-a-simple-trade-after-all/feed/ 0
Chess puzzle: Who cares about pins? (hard) http://witte-consulting.com/blog/chess-puzzle-who-cares-about-pins-hard/ http://witte-consulting.com/blog/chess-puzzle-who-cares-about-pins-hard/#respond Sun, 05 Jan 2014 21:33:59 +0000 http://witte-consulting.com/blog/?p=315
Chess puzzle: Who cares about pins?

White to move and win material.

Hint: show

Solution: show

]]>
http://witte-consulting.com/blog/chess-puzzle-who-cares-about-pins-hard/feed/ 0
List type mapping in Java http://witte-consulting.com/blog/list-type-mapping-in-java/ http://witte-consulting.com/blog/list-type-mapping-in-java/#respond Sun, 28 Nov 2010 01:23:03 +0000 http://witte-consulting.com/blog/?p=292 Update for Java 8: List mapping in Java 8

Recently someone asked me how to convert a List of type X to a List of type Y, given a well-defined function from X to Y. I’ve seen some horrible “solutions” for that in real world programs, and I hope that some people will benefit from my way of doing this:

/**
 * Defines a Function from E to F.
 * @param <E> the domain
 * @param <F> the codomain
 */
public interface Converter<E,F> {
    F convert(E f);
}
/**
 * Maps a List of one type to a List of another type.
 * @param c the function used to convert from type E to type F
 * @param list the List to be mapped
 * @param <E> the domain
 * @param <F> the codomain
 * @return a new List with the elements mapped
 * @throws NullPointerException iff any argument is <code>null</code>
 */
public static <E,F> List<F> map(final Converter<E,F> c, final List<E> list) {
    if (c == null || list == null) {
        // fail early; particularly important when using lazy evaluation
        throw new NullPointerException();
    }
    return new AbstractList<F>() {
        @Override
        public F get(final int index) {
            return c.convert(list.get(index));
        }
 
        @Override
        public int size() {
            return list.size();
        }
    };
}

This is some pretty generic code that can be used in many situations. For example in web applications it’s often necessary to map a certain entity to a String representation to display on the page.

Here is a usage example:

final List<JFrame> frames = Arrays.asList(new JFrame("hello"), new JFrame("world"));
 
final List<String> titles = map(
        new Converter<JFrame, String>() {
            @Override
            public String convert(final JFrame f) {
                return f.getTitle();
            }
        },
        frames
);
 
System.out.println(titles); // prints: [hello, world]
 
final List<Integer> nums = Arrays.asList(1,2,3);
final List<Integer> inc = map(
        new Converter<Integer, Integer>() {
            @Override
            public Integer convert(final Integer f) {
                return f + 1;
            }
        },
        nums
);
 
System.out.println(inc); // prints: [2, 3, 4]

Not as sweet as it would look like in a functional programming language like Haskell or Scala, but as good as it gets in Java.

See also:

  • Functional Java provides a more pure approach, using its own List implementation rather than java.util.List
  • Jushua Bloch. Effective Java, 2nd Edition. Chapter 4, Item 18 provides a similar application of AbstractList
]]>
http://witte-consulting.com/blog/list-type-mapping-in-java/feed/ 0
The history of JTiger http://witte-consulting.com/blog/the-history-of-jtiger/ http://witte-consulting.com/blog/the-history-of-jtiger/#respond Sat, 22 May 2010 11:20:00 +0000 http://witte-consulting.com/blog/?p=222 JTiger is a test framework, developed by Tony Morris in 2004 and published March 23, 2005.

Defining attributes

JTiger had a rich set of features and predefined assertions:

an integrated test assertion for serializability

an integrated test assertion for serializability


check for expected Exception

check for expected Exception


check for equals/hashCode contract

check for equals/hashCode contract


It was easy to run tests programmatically or from an Apache Ant task.

History

Tony Morris developed Assertion Extensions for JUnit (at that time known as JUnitX; not to be confused with other frameworks sharing the same name) a while ago. It contained advanced assertions to be used with plain old JUnit. When Java SE 5 was in beta, he started with the development of JTiger. Because of his contract as an employee of IBM, he needed permission by IBM to publish it as Open Source, even though he developed it in his free time. That process took several months. JTiger even crossed the desk of Erich Gamma, who commented on it in a private email to Tony Morris.

While JTiger was in this approval process, TestNG has been released. At that time it had less fancy assertions (see examples above), but the concept was just as good and additional assertions have been introduced later. Also there were IDE-Plugins for Intellij Idea and Eclipse.

After JTiger has been approved by IBM and released, it gained a fair amount of community acceptance. Independent comparisons with JUnit and TestNG were rather positive, such as Justin Lee’s Test Framework Comparison.

In December 2005 I officially took charge of the project and Tony Morris retired from it. I never changed much except for the documentation and website, though.

Early in 2010 the transfer of the domain ownership for jtiger.org to me failed. I don’t know what went wrong. I got the correct release code from Tony Morris and gave it to my registrar. A few days later my registrar informed me that either the current registrar or the owner (Tony Morris) did not approve the transfer. That was the end of the website.

What now?

In 2008, Tony Morris released Reductio. Similar to QuickCheck, it uses Automated Specification-based Testing. Reductio has become part of the Functional Java API.

And of course you can still use JTiger:


JTiger tar.gz

jtiger-2.1.0376.tar.gz

JTiger MD5 tar.gz

jtiger-2.1.0376.tar.gz.MD5


JTiger zip

jtiger-2.1.0376.zip


JTiger MD5 zip

jtiger-2.1.0376.zip.MD5

]]>
http://witte-consulting.com/blog/the-history-of-jtiger/feed/ 0