Edmund Kirwan damns the ubiquitous JUnit in JUnit's evolving structure. What's the problem? — galloping interdependencies. As a bonus, a spiffy graphical timeline of JUnit's structure.
Thursday, March 07, 2013
Wednesday, March 06, 2013
Skipping TDD
Uncle Bob, as usual, is a pleasure to read, to wit, The Pragmatics of TDD. Highlights:
- I don't write tests for getters and setters. Doing so is usually foolish. Those getters and setters will be indirectly tested by the tests of the other methods; so there's no point in testing them directly.
- I don't write tests for member variables. They too will be tested indirectly.
- I don't write tests for one line functions or functions that are obviously trivial. Again, they'll be tested indirectly.
- I don't write tests for GUIs. GUIs require fiddling. You have to nudge them into place by changing a font size here, an RGB value there, an XY position here, a field width there. Doing that test-first is silly and wasteful.
- In general I don't write tests for any code that I have to "fiddle" into place by trial and error. But I separate that "fiddling" code from code that I am surer of and can write tests for.
- A few months ago I wrote an entire 100 line program without any tests. (GASP!)
- I usually don't write tests for frameworks, databases, web-servers, or other third-party software that is supposed to work. I mock these things out, and test my code, not theirs.
Tuesday, March 05, 2013
Plugging a leaky ship
Plumbr's Nikita Salnikov-Tarnovski writes Hunting down memory leaks: a case study. Quoting:
A week ago I was asked to fix a problematic webapp suffering from memory leaks. How hard can it be, I thought – considering that I have both seen and fixed hundreds of leaks over the past two years or so.
But this one proved to be a challenge. 12 hours later I had discovered no less than five leaks in the application and had managed to fix four of them. I figured it would be an experience worth sharing. For the impatient ones – all in all I found leaks from
- MySQL drivers launching background threads
- java.sql.DriverManager not unloaded on redeploys
- BoneCP loading resources from the wrong classloaders
- Datasource registered into a JNDI tree blocking unloading
- Connection pool using finalizers tied to Google’s implementation of reference queue running in a separate thread
Of course, there's more.
Monday, February 25, 2013
TCP traceroute
Peteris Krumins posts on TCP Traceroute, a nifty trick to "see" through firewalls. His pudding:
# traceroute -T -p 80 www.microsoft.com traceroute to www.microsoft.com (65.55.57.27), 30 hops max, 60 byte packets 1 50.57.125.2 (50.57.125.2) 0.540 ms 0.629 ms 0.709 ms 2 core1-aggr701a-3.ord1.rackspace.net (184.106.126.50) 0.486 ms 0.604 ms 0.691 ms 3 corea.ord1.rackspace.net (184.106.126.128) 0.511 ms corea.ord1.rackspace.net (184.106.126.124) 0.564 ms 0.810 ms 4 bbr1.ord1.rackspace.net (184.106.126.147) 1.339 ms 1.310 ms bbr1.ord1.rackspace.net (184.106.126.145) 1.307 ms 5 chi-8075.msn.net (206.223.119.27) 3.619 ms 2.560 ms 2.528 ms 6 * 204.152.140.35 (204.152.140.35) 3.640 ms * 7 ge-7-0-0-0.co1-64c-1a.ntwk.msn.net (207.46.40.94) 52.523 ms xe-0-2-0-0.ch1-96c-2b.ntwk.msn.net (207.46.46.49) 3.825 ms xe-1-2-0-0.ch1-96c-2b.ntwk.msn.net (207.46.46.53) 3.355 ms 8 xe-0-1-0-0.co1-96c-1a.ntwk.msn.net (207.46.33.177) 61.042 ms 61.032 ms 60.457 ms 9 * * xe-5-2-0-0.co1-96c-1b.ntwk.msn.net (207.46.40.165) 100.069 ms 10 65.55.57.27 (65.55.57.27) 53.868 ms 53.038 ms 52.097 ms
Monday, February 18, 2013
Friday, February 15, 2013
On being the bearer of bad news
Elena Yatzeck writes 6 Steps To Success With Your Executive Boss, or "On being the bearer of bad news" (my title), another good post on the timeless theme, Do The Right Thing.
Thursday, February 07, 2013
The Java enum factory
This comes up in interviews with intermediate programmers (and some seniors), the "enum factory" in Java:
public final class Money {
// Infrequent that new currencies created,
// old currencies never vanish, just fade away
public enum Currency {
USD, PHP; // And many more
// Additional fields as needed, e.g., locale
public Money print(final BigDecimal amount) {
return new Money(this, amount);
}
}
private final Currency currency;
private final BigDecimal amount;
private Money(final Currency currency, final BigDecimal amount) {
this.currency = currency;
this.amount = amount;
}
// Appropriate methods
} And elsewhere with static imports:
Money pocket = asList(USD.print(ONE), PHP.print(TEN));
The key observations:
- Amounts of money are intimately attached to a particular currency
- Currency has few qualities not attached to money
- Ok to add more currencies through code
- Code reads better with factory than without
Tuesday, February 05, 2013
Mana on leadership
Mana of Geek Diva posts on leadership. Key point (emphasis mine):
When I see people who I consider good leaders, be they of any age, gender, height or ethnicity, I see one thing that they do very well. They make decisions quickly. Quickly does not mean recklessly. It just means that they make a decision knowing that if it isn't right then they can correct at a later time.
Java 8 lambdas and all that
Lovely post from Anton Arhipov at JRebel, Java 8: The First Taste of Lambdas. Kudos for javap decompilation for an "under the hood" explanation. His conclusion:
We can definitely say that lambdas and the accompanied features (defender methods, collections library improvements) will have a great impact on Java very soon. The syntax is quite nice and once developers realize that these features provide value to their productivity, we will see a lot of code that leverages these features.
It was quite interesting for me to see what lambdas are compiled to and I was very happy when I saw the total utilization of the invokedynamic instruction in action without any anonymous inner classes involved at all.
Friday, February 01, 2013
Wednesday, January 16, 2013
Superior teams
Venkatesh Krishnamurthy writes The 4 Ingredients of Building Hyper-Productive Teams. What he means are agile teams, quoting Jeff Sutherland:
We define Hyper-Productivity here at 400% higher velocity than average waterfall team velocity with correspondingly higher quality. The best Scrum teams in the world average 75% gains over the velocity of waterfall teams with much higher quality, customer satisfaction, and developer experience.
Agile for me, though worded awkwardly: how do the best scrum teams compare to the best waterfall teams?
Friday, January 11, 2013
GapList, an alternative to ArrayList and LinkedList
Thomas Mauch presents GapList, an alternative to ArrayList and LinkedList in Java, with the best performance behaviors of both: fast random reads and compact, cache-friendly storage like ArrayList, fast random updates like LinkedList.
Monday, January 07, 2013
Marz on Lambda Architecture
Nathan Marz writes on Big Data Lambda Architecture, promoting his upcoming book from Manning, Big Data. It's a comprehensible take on big data architectures. (See Chapter 1 [pdf].)
In a nutshell:
Computing arbitrary functions on an arbitrary dataset in real time is a daunting problem. There is no single tool that provides a complete solution. Instead, you have to use a variety of tools and techniques to build a complete Big Data system.
The lambda architecture solves the problem of computing arbitrary functions on arbitrary data in real time by decomposing the problem into three layers: the batch layer, the serving layer, and the speed layer.
Wednesday, December 19, 2012
Why go?
Rob Pike explains Go at Google: Language Design in the Service of Software Engineering, or, Why go?
Thursday, December 13, 2012
Passing of an era: No more i386
Thus spake Linus Torvalds:
Pull "Nuke 386-DX/SX support" from Ingo Molnar:
"This tree removes ancient-386-CPUs support and thus zaps quite a bit
of complexity:
24 files changed, 56 insertions(+), 425 deletions(-)
... which complexity has plagued us with extra work whenever we wanted
to change SMP primitives, for years.
Unfortunately there's a nostalgic cost: your old original 386 DX33
system from early 1991 won't be able to boot modern Linux kernels
anymore. Sniff."
I'm not sentimental. Good riddance.
Tuesday, December 04, 2012
Guicing your jars, part 2
In Guicing your jars I mention using Java's service loader feature to automate finding modules for Guice, along these lines:
public class MetaInfServicesModule
extends AbstractModule {
@Override
protected void configure() {
for (final Module module : ServiceLoader.load(Module.class))
install(module);
}
} What I did not mention was the secret sauce, Kohsuke's MetaInfServices annotation processor which creates the META-INF/services file for you:
@MetaInfServices(Module.class)
public class FooModule
extends AbstractModule {
@Override
protected void configure() {
// Awesome foo-ness here
}
} Now using your Maven runtime dependencies to control the classpath, Guice automatically installs your modules:
Guice.createInjector(new MetaInfServicesModule());
(Dependencies between modules is beyond the scope of this post!)
Friday, November 30, 2012
WebPageTest
Ryan Hurst posts How Facebook can avoid losing $100M in revenue when they switch to always-on SSL, an interesting discussion of web page performance when using SSL.
What I noticed: WebPageTest, a fantastic resource for tuning public web pages courtesy AOL, Google & others. WebPageTest can also be downloaded, for testing your internal web site.
Monday, November 26, 2012
See more debug data in IntelliJ
Mark Needham posts a useful IntelliJ debugging tip, IntelliJ Debug Mode: Viewing beyond 100 frames/items in an array.
Sunday, November 25, 2012
Parker on Ordesky
Andrew Parker writes on learning Scala from Ordesky through an online course. Who needs a university?
Monday, November 19, 2012
Alternative to Java 8 virtual extension methods
Tired of waiting for Java 8? Project Lombok brings a little piece to you today, virtual extension methods similar to those proposed for JDK8. The most interesting bit: Lombok works using only JDK annotation processors and no required run-time library.
JUnit testing that a call blocks
Certain that I missed an existing solution, I post this in hopes of helping anyone who also misses it. But if you know a better way, please comment.
Usage
class SomeTest {
@Test(timeout = 1000L)
public void shouldBlock() {
assertBlocks(new BlockingCall() {
@Override
public void call()
throws InterruptedException {
// My blocking code here
}
});
}
} Implementation
import javax.annotation.Nonnull;
import java.util.Timer;
import java.util.TimerTask;
import static java.lang.String.format;
import static java.lang.Thread.currentThread;
import static org.junit.Assert.fail;
/**
* {@code BlockingCall} supports blocking call assertion for JUnit tests.
*
* @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
*/
public interface BlockingCall {
/**
* Calls blocking code. The blocking code must throw {@code
* InterruptedException} when its current thread is interrupted.
*
* @throws InterruptedException if interrupted.
*/
void call()
throws InterruptedException;
/** Wrapper class for block assertion. */
public static final class Assert {
/**
* Asserts the given <var>code</var> blocks at least 100ms. Interrupts
* the blocking code after 100ms and checks {@code InterruptedException}
* was thrown. When not blocking, appends <var>block</var> to the
* failure message.
*
* @param block the blocking call, never missing
*/
public static void assertBlocks(@Nonnull final BlockingCall block) {
final Timer timer = new Timer(true);
try {
final Thread current = currentThread();
timer.schedule(new TimerTask() {
@Override
public void run() {
current.interrupt();
}
}, 100L);
block.call();
fail(format("Did not block: %s", block));
} catch (final InterruptedException ignored) {
} finally {
timer.cancel();
}
}
}
} UPDATE: Idioms like this would be far more attractive with Java 8 lambdas:
public void shouldBlock() {
assertBlocks(() -> { /* blocking code */ });
}
Friday, November 09, 2012
Python's enumerate for Java
Surprisingly I did not find Python's enumerate in Guava Iterables.
A little static import and all is well:
import com.google.common.collect.UnmodifiableIterator;
import javax.annotation.Nonnull;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Iterator;
import java.util.Map.Entry;
/**
* {@code EnumerateIterable} wraps an iterable like Python {@code enumerate}.
*
* @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
*/
public final class EnumerateIterable<T>
implements Iterable<Entry<Integer, T>> {
@Nonnull
private final Iterable<T> delegate;
public EnumerateIterable(@Nonnull final Iterable<T> delegate) {
this.delegate = delegate;
}
/**
* Creates a new enumerated iterable for the given <var>delegate</var>.
*
* @param delegate the underlying iterable, never missing
* @param <T> the underlying wrapped type
*
* @return the new enumerated iterable, never missing
*/
@Nonnull
public static <T> Iterable<Entry<Integer, T>> enumerate(@Nonnull final Iterable<T> delegate) {
return new EnumerateIterable<>(delegate);
}
@Nonnull
@Override
public Iterator<Entry<Integer, T>> iterator() {
return new EnumerateIterator<>(delegate);
}
private static final class EnumerateIterator<T>
extends UnmodifiableIterator<Entry<Integer, T>> {
@Nonnull
private final Iterator<T> it;
int i;
EnumerateIterator(@Nonnull final Iterable<T> delegate) {
it = delegate.iterator();
i = 0;
}
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
@Nonnull
public Entry<Integer, T> next() {
return new SimpleImmutableEntry<>(i++, it.next());
}
}
} UPDATE: Completeness requires a static factory method for arrays as well as iterables.
ISO8601 UTC with XStream
I need ISO8601 conversion with XStream for UTC (GMT/Zulu) time. Originally I went with ISO8601DateConverter which comes with XStream and uses Joda. However I found that it read in UTC (GMT/Zulu) time but wrote back out local time.
To fix this I wrote my own converter using JAXB in the JDK, and dropped the Joda runtime dependency from my project.
I unit tested full roundtrip with "2012-10-22T12:34:56Z". The original converter parsed correctly but serialized as "2012-10-22T07:34:56-05:00". My converter serializes as the input string.
import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
import java.util.Date;
import java.util.GregorianCalendar;
import static java.util.TimeZone.getTimeZone;
import static javax.xml.bind.DatatypeConverter.parseDateTime;
import static javax.xml.bind.DatatypeConverter.printDateTime;
/**
* {@code UTCConverter} converts {@code java.util.Date} objects in ISO8601
* format for UTC without milliseconds.
*
* @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
*/
public final class UTCConverter
extends AbstractSingleValueConverter {
@Override
public boolean canConvert(final Class type) {
return Date.class.isAssignableFrom(type);
}
@Override
public String toString(final Object obj) {
final GregorianCalendar gmt = new GregorianCalendar(getTimeZone("GMT"));
gmt.setTime(Date.class.cast(obj));
return printDateTime(gmt);
}
@Override
public Object fromString(final String str) {
return parseDateTime(str).getTime();
}
}