Book Review: Effective Java by Joshua Bloch

This is not your ordinary book review. You have been warned!

So, you’re working with Java, right?
Go, read this book!

You’ve learned Java at the university, or in a boot camp, perhaps as a self-thought programmer?
Go, read this book!

Maybe you’re thinking about becoming a Java developer, hm?
Well, learn the basics, and then read this book!

I think you get the point.

My shortest book review ever


Cover - Effective Java Book Review

It’s a very pragmatic book in nature. It contains 90 items divided into 12 sections each centered around different topics like lambdas, exceptions, serialization, etc. Writing Java code which works is one thing. This book will help you to write code which is effective, clear and easy to maintain.

Every Java developer should read this book. Period.

Take Action

Knowledge without action is worthless, especially when we take this book. After every item in this book I stopped reading and started thinking: is this something I can apply to the project I’m working on?

Then a searched. I found some issues. And I fixed them.

More often than not the code I had to patch was mine. But that’s OK. That is called progress. None of us writes perfect code, but this book helps us to get better at it. If you read this book as a junior developer, it might prevent you from making a lot of mistakes in the first place!

As the Java language evolves, so does this book. The current one is the 3rd edition. I’ll make sure to read the next one when it comes out to see if there are any new best practices. If there will be only one Java book you read this year, let it be this one. And of course, don’t forget to take action on it!

Before you go

In case you’ve already read this book, feel free to share your experience in the comments below. The most eye-opening items for me were: static factory methods, enum sets, and the cost of reflection. Which ones were yours?

Buy on Amazon: Effective Java, 3rd Edition, Joshua Bloch
Read another one of my book reviews: Console Wars, Blake J. Harris.

What’s Missing from Mastering Spring 5.0

Mastering Spring 5.0 book cover
Mastering Spring 5.0 book cover from Amazon.com

Chapter Dependency Injection

Now that Java 9 and Spring Framework 5.0 have been released and end-of-year is just around the corner I thought I’ll keep my knowledge up-to-date and read Mastering Spring 5.0 from Packt Publishing. Based on the first two chapters it seems to be giving a good overview of the framework in an easy to follow fashion. However, after reading the 2nd chapter I could not resist writing a post about what I believe is missing from it. Despite the book targeting experienced developers when it discusses IoC – Inversion of Control, it fails to mention two advanced but very important features I’ll now share with you.

Defining beans within configuration classes

When the book compares XML configuration with annotations it states that “Classes using annotations are no longer simple POJOs because they are using framework-specific annotations.” Example:

@Service
public class UserService {
  @Autowired
  private UserRepository repository;
...
}

This is why my preferred way of wiring components together is by configuration classes.

@Configuration
public ServiceConfiguration {
  @Autowired
  private UserRepository repository;
  @Bean
  public UserService userService() {
    return new UserVervice(repository);
  }
...
}

By doing so the @Service tag becomes unnecessary, plus I can keep all Spring specific annotations in one place: in the configuration classes. This is how I keep my repositories and services as clean POJOs.

The other topic I was missing from the 2nd chapter was how XML and annotation based configurations can work hand in hand.

Mixing XML and Java based configuration

When working on a “legacy” project which is still using XML based context configuration you can find yourself in a situation where you need to add some new configuration. And because it’s not 2009 you would like to use annotations. What can you do? Rewriting the whole configuration might require a significant amount of time and can be error-prone. Even if you aspire to do so in the long term, the best you can do is to start with incremental improvements. The Spring Framework provides a way to import Java configuration files into the XML context configuration.

First, you write your Java configuration like this:

@Configuration
class NewConfig {
  @Bean
  public DataRepostory dataRepository() {
  ....
  }
}

… and then import it into your XML config:

<bean class="org.randomdeveloper.spring5.config.NewConfig" />

By doing so you will have the ability to reference your new beans in the XML configuration – if required.

I hope you find my tips useful. Despite these shortcomings, I still think that Mastering Spring 5.0 is a very well written book. I suspect chapters about Spring Cloud will contain a lot of stuff that is new for me 😉

Console Wars by Blake J. Harris

There was a time when Sony and Microsoft didn’t know the first thing about gaming. A time when the term home video game console was equivalent to the Nintendo Entertainment System (NES). This was the time when Sega, one of the rivals, decided to break the status quo. If they had managed to keep their momentum perhaps the videogame industry would look very different to what it is today.

Console Wars: Sega, Nintendo and the Battle that Defined a Generation
Console Wars: Sega, Nintendo and the Battle that Defined a Generation book cover

The book from Blake J. Harris, Console Wars: Sega, Nintendo and the Battle that Defined a Generation, is based not just on publicly available materials like conference presentations, newspaper articles but also on more than 200 hundred personal interviews with key figures from the industry at the time. Such a key figure was Tom Kalinske who was recruited to be president and CEO of Sega of America in 1990. The book centers around his figure and his team’s efforts to overthrow Nintendo.

To be in the gaming industry in the early 90’s must have been a crazy rollercoaster ride. The market was growing at an ever faster speed and the user base exploded astronomically. For Sega, the key question was how to combine technology with clever marketing to fight from the underdog position. To better understand the differences just have a look at their mascots. Nintendo’s best-known character Luigi is a nice, jovial guy who is jumping around the Mushroom Kingdom to save Princess Peach. In contrast, Sonic the Hedgehog rushes through levels at a breathtaking speed and with an edgy attitude.

Sonic the Hedgehog
Sonic the Hedgehog

If it was only about the characters and the gaming experience these two companies had to offer the story wouldn’t be so interesting. But if you add into the mix the cultural differences between the Amercian and Japan parties on both sides. The problems of distribution, fighting for the shelves space at major retailers. Deciding which R&D project to support and which one to kill. Answering the question whether having the superior technology is enough to win the battle? As you can see there’s a lot of room for clever thinking – and a lot of chance for things to go south. How about pricing? Does printing brand new catalogs overnight just to announce a price drop a few hours earlier than Nintendo to steal their thunder sounds crazy? At Sega, this level of dedication was rather a rule than an exception.

The author of the book did a remarkable job of describing an era by telling the stories of the individuals who lived through it. Their happy, sad and sometimes bitter sweet moments, their professional victories and individual losses make the book very personal. What I really liked about their story is that no matter how many challenges they had to face still they managed to have fun in growing this niche market into a multi billion dollar industry while also shaping an entire generation.

Sega Genesis
Genesis a.k.a. Mega Drive: 16-bit home video game console from Sega

Nevertheless, Sega has faded away and today Nintendo is only the 3rd by market share on the console market. How did it happen? Well, it has a lot to do with the PlayStation and Steve Race’s “299$” speech. But did you know that Sony has originally planned to release a console with Sega? For more on that and for other interesting anecdotes I suggest to get hold of the book. Have I mentioned it’s more than 500 pages? Long but worth every page 🙂

Composing Objects – Java Concurrency in Practice

Hi, Java dudes! In my previous post, Sharing Objects – Java Concurrency in Practice, I reviewed how objects can be published and accessed from multiple threads in a safe manner. Today’s topic is how thread-safe components can be combined and enriched with new functionality.

While it is possible to write a thread-safe application that stores all its state in public static fields, but it is much easier if we do it by combining thread-safe components. By doing so we can delegate every thread-safety issue to the right application tier where it needs to be handled. Let the thread-safe class deal with how access to its inner state has to be synchronized. While on a higher level, we can think about how these thread-safe components can be used to represent the application state properly.

In order to prevent concurrency issues, we have to think about state ownership. This is something that is not part of the language itself but it is defined by class design. Therefore programmers have a great autonomy to make the right choices – and the bad ones too. A class usually does not own the objects passed to its methods. In many cases, ownership and encapsulation go together – the object encapsulates the state it owns and owns the state it encapsulates. Collections often share ownership of the contained objects with the client code that inserted them into the collection.

The Java monitor pattern is an example for ownership by encapsulation.

An object following the Java monitor pattern encapsulates all its mutable state and guards it with the object’s own intrinsic lock [JCiP]

Synchronized collections offered by the standard JDK follow the Java monitor pattern. Synchronization is implemented as a wrapper layer that controls all access to the underlying collection. A synchronized list of Strings can be created like this:

import java.util.Collections;
...
List syncStrings = Collections.synchronizedList(new ArrayList());

It is critical that the reference to the backing collection must not escape otherwise it can undermine thread-safety. Operations over a synchronized collection are mutually exclusive – only one thread at a time can work with the collection. In most cases, this is too restrictive and result in poor application performance. There are other alternatives but more on that later.

Now let’s suppose we have a class that is already thread-safe but misses an operation that we need. What can we do in such a situation? We have multiple options, but not all of them are correct:

  • put new synchronized code in a helper class, ☠
  • extend the original class, ☠
  • modify the original class to support the desired operation, or
  • add new functionality in a class encapsulating the original one.

Using a synchronized method of a helper class is probably the worst possible approach. Whatever lock the parameter object uses it definitely won’t be the intrinsic lock of the helper method. It only gives us the illusion of safety while other threads can still modify the state of the passed in object.

Extending the original class – if possible – could work, but it’s fragile because the underlying class might silently change its synchronization policy and jeopardize thread-safety of the extending class. Another problem is that not all classes expose enough of their state to make this approach possible (private lock).

The safest way to add a new atomic operation is to modify the original class consistently with its original design. In this case, all code that implements the synchronization policy is contained in a single source file – easier to understand and maintain.

If changing the existing class is not an option then using composition is the best alternative. This is how standard synchronized collections are implemented. And just as with synchronized collections, it’s crucial that all access to the underlying object must go through the wrapper class.

Don’t force clients or other developers to make risky guesses about the thread-safety of your code.

Document a class’s thread safety guarantees for its clients; document its synchronization policy for its maintainers. [JCiP]

Did you know that java.text.SimpleDateFormat is not thread-safe? Okay, maybe you did, but did you know that it wasn’t explicitly documented until JDK 1.4? And this is the worst that can happen: you assume that something is thread-safe that is not. This is why you should always document your code.

...
@ThreadSafe
public class ImprovedList<T> {

    @GuardedBy("this")
    private final List<T> innerList;

    public ImprovedList(List<T> list) {
        this.innerList = list;
    }

    public synchronized void putIfAbsent(T elem) {
        if (!innerList.contains(elem)) {
            innerList.add(elem);
        }
    }
}

Annotations @ThreadSafe and @GuardedBy are not part of the standard JDK.

That was all for now. Next week we are going to look at what building blocks Java provides that we can use as Lego™ pieces to build our application. Best wishes until we meet again here 😉

P.S.: instead of java.text.SimpleDateFormat use its thread-safe Java 8 alternative the java.time.format.DateTimeFormatter – where applicable.

Resource
[JCiP] Java Concurrency in Practice by Brian Goetz, ISBN-10: 0321349601

Sharing Objects – Java Concurrency in Practice

Welcome, Java enthusiast! Today I’m going to deal with issues around sharing objects in a multi-threaded environment. In last week’s post, Java Concurrency in Practice – Thread Safety, I was focusing on preventing multiple threads from accessing a shared state at the same time. In this post, I’m going to deal with a more subtle aspect of synchronization: visibility. How to publish changes by one thread so they can be safely read by other threads.

public class NotVisible {

  private static class WorkerThread extends Thread {
    public int value = 1;
    public boolean finished = false;
    public void run() {
      while (!finished)
        Thread.yield();
      System.out.println(value);
    }
  }
  
  public static void main(String[] args) {
    WorkerThread t = new WorkerThread();
    t.start();
    t.value = 2;
    t.finished = true;
  }

}

The class NotVisible demonstrates what can go wrong without proper synchronization. While it seems reasonable to assume that the code above will print 2. Actually, it can loop forever because there is no guarantee that the values set by the main thread will be visible in the “worker” thread. Nor, that they will become visible in the same order. Therefore it can happen that it will finish, but print 1 instead of 2.

“in the absence of synchronization, the Java Memory Model permits the compiler to reorder operations and cache values in registers, and permits CPUs to reorder operations and cache values in processor-specific caches.” [JCiP]

Therefore:

“Attempts to reason about the order in which memory actions ‘must’ happen in insufficiently synchronized multithreaded programs will almost certainly be incorrect.” [JCiP]

In insufficiently synchronized programs reader threads can see out-of-date values. Stale data can cause serious issues and failures like unexpected exceptions, broken computations, corrupted data, or infinite loops.

Intrinsic locking is one of the mechanisms that can guarantee that changes made by one thread will be visible to other threads in a predictable manner.

“Locking is not just about mutual exclusion; it is also about memory visibility. To ensure that all threads see the most up-to-date values of shared mutable variables, the reading and writing threads must synchronize on a common lock.” [JCiP]

Meaning that:

“When thread A executes a synchronized block, and subsequently thread B enters a synchronized block guarded by the same lock, the values of variables that were visible to A prior to releasing the lock are guaranteed to be visible to B upon acquiring the lock.” [JCiP]

There is an alternative way to propagate changes predictably: using volatile variables. When a field is declared volatile the compiler and the JVM is put on notice that this variable is shared and should not be cached nor should be access to it re-ordered with other memory operations. Volatile variables provide visibility but not atomicity. Therefore we cannot use them when a write to the variable depends on its current value.

“Locking can guarantee both visibility and atomicity; volatile variables can only guarantee visibility.” [JCiP]

Publishing an object means to make it available outside of its current scope. Using good OOP practices like encapsulation is not necessary for writing safe concurrent programs. However, it certainly makes easier to reason about correctness. Publishing internal state variables can compromise not just encapsulation but the thread-safety of your application. Other classes or threads can intentionally or carelessly misuse the published state and break your design. Sometimes, publishing is obvious e.g. storing a reference in a public static field. In other cases, it can be more subtle like passing an object to an overrideable – neither private or final – method.

An object is in a predictable, consistent state only after its constructor returns. This is why:

“Do not allow the this reference to escape during construction.” [JCiP]

We can let the this reference escape during construction either explicitly (by passing it) or implicitly by instantiating an inner class of the owning object.

No synchronization is needed if the data is accessed only from a single thread. What an ingenious idea! Actually, it is so important it has its own name: thread-confinement. For example JDBC connection pools use thread confinement to ensure correct program behaviour. The Connection object itself is not thread-safe but the pool won’t dispense the same connection to another thread until it is returned from the owning thread – which acquired the connection in a thread-safe manner from the pool.

ThreadLocal class allows us to maintain a separate copy of a value on a per-thread basis. It provides getter and setter methods to return or set the value for the currently executing thread respectively. When a thread calls get for the first time the initialValue() method is executed to construct the new value.

Stack confinement is a special form of thread confinement. Because local variables only live on the executing thread’s stack. If the data is only reachable through local variables thread-safety is not an issue.

An immutable object is one whose state is cannot be changed after construction.

“Immutable objects are always thread-safe.” [JCiP]

It’s technically possible to have an immutable object without all fields being final. The String class lazily computes the hash code the first time it is actually needed but because this is derived deterministically from an immutable state String is still considered immutable.

So far, we have been focusing how not to share objects among multiple threads. Of course, sometimes we simply have to and then we have t do it safely. If the object we would like to share is not immutable we have to follow the safe publication idioms listed below.

To publish an object safely, both the reference to the object and the object’s state must be made visible to other threads at the same time. A properly constructed object can be safely published by:

  • Initializing an object reference from a static initializer
  • Storing a reference to it into a volatile field or AtomicReference
  • Storing a reference to it into a final field of a properly constructed object
  • Storing a reference to it into a field that is properly guarded by a lock
[JCiP]

The Java Memory Model model offers a special guarantee for immutable objects: they don’t have to be published safely. But, they have to be constructed properly: all fields have to be final and their state must not change. This guarantee does not hold for effectively immutable objects. They have to be published safely but can be later accessed without any further synchronization.

Whoa, this was a lot of information. I’m so glad that I decided to write my own study notes because it helps me a lot to better understand what I’ve read. I also hope that I can help others as well. I recommend to read the book and use my notes to recapitulate 😉

Resource
[JCiP] Java Concurrency in Practice by Brian Goetz, ISBN-10: 0321349601

Java Concurrency in Practice – Thread Safety

In my last post, Java Concurrency in Practice: Study Notes, I finished my writing with a statement that all code paths accessing a shared state must be thread safe. But, what is thread-safety? A piece of code is said to be thread-safe when it continues to behave correctly when accessed from multiple threads. To put it in a slightly more formal way:

“A class is thread-safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code” [JCiP].

At the heart of the definition, there is something we call: correctness. As we programmers often don’t get precise specifications we have to define correctness as something we recognize when we see it – the code works. Since a single-threaded environment is just an edge case of a multi-threaded environment. A program, class, or any piece of code “cannot be thread-safe if it is not even correct in a single-threaded environment” [JCiP].

Let’s continue with an another definition:

“stateless objects are always thread-safe” [JCiP].

But, what do we mean by the state of the object? An object’s state includes any data that can affect its externally visible behavior.

“An object’s state is its data, stored in state variables such as instance or static fields. An object’s state may include fields from other, dependent objects” [JCiP].

For example, a HashMaps state is defined not just by its fields but also by the state of the key value pairs it contains. Now, let’s suppose that we have an object with a state accessible from multiple threads. We often define a set of actions over the object with pre- and post-conditions, invariants, that must hold true before or after any action. These invariants rule out part of the objects state space as invalid. If an object is correctly implemented, no sequence of operations can get the object into an invalid state.

Change of state might be tricky. Often, what seems like a single action operation, it might not be atomic, which means that it does not execute as a single, indivisible operation.

“Operations A and B are atomic with respect to each other if, from the perspective of a thread executing A, when another thread executes B, either all of B has executed or none of it has” [JCiP].

In the CarFactory example below the state of the factory instance is represented by the member variable nextId. The code below looks totally innocent until we realize that incrementing variable nextId is not an atomic operation. It consists of three separate actions: fetch the current value, add one to it, and write the new value back. If multiple threads can access the CarFactory instance with some unlucky timing two cars can get the same id. Depending on the application this can have fatal consequences.

...
@NotThreadSafe
class CarFactory {

  private long nextId = 1;
 
  public Car createCar() {
    Car c = new Sedan();
    c.setId(nextId++);
    return c;
  }
  ...
}

The possibility of getting incorrect results by unlucky timing is so important in concurrent programming that it has a name: a race condition.

“A race condition occurs when the correctness of a computation depends on the relative timing or interleaving of multiple threads by the runtime” [JCiP].

To avoid race conditions, there are multiple ways to prevent other threads from using a variable while we’re in the middle of modifying it. Our aim is to ensure that other threads can observe or modify the state only before we start or after we finish, but not in the middle. One way to make our CarFactory thread safe is to use the AtomicLong library class. Because method getAndIncrement ensures atomicity now we don’t have to worry about unlucky timing. Annotations @NotThreadSafe and @ThreadSafe are not part of the standard jdk. They are used throughout this article and in the book to differentiate between safe and unsafe patterns.

...
import java.util.concurrent.atomic.AtomicLong;

@ThreadSafe
class CarFactory {

  private AtomicLong nextId = new AtomicLong(1);
 
  public Car createCar() {
    Car c = new Sedan();
    c.setId(nextId.getAndIncrement());
    return c;
  }
  ...
}

But what happens if the state of the object is shared among multiple variables? Is it enough to replace all member variables with their atomic version? Of course, not.

To preserve state consistency, update related state variables in a single atomic operation” [JCiP].

Locking helps us to preserve state consistency be ensuring that a critical section can only be executed by a single thread at a time. Java provides the synchronized block as a built-in locking mechanism.

synchronized (lock) {
   // Access or modify shared state guarded by lock
}

Every java object has an intrinsic lock that can be used for synchronization purposes. This internal lock is automatically acquired when entering a synchronized block and automatically released when leaving the synchronized block – even if it is by throwing an exception. A special case of a synchronized block is when we make a whole method synchronized. By doing so, we synchronize on the objects intrinsic lock or in case of a static method the Class< ? > object is used.

Intrinsic locks are reentrant. If a thread tries to acquire a lock that it already holds, the request succeeds. Reentrancy means that locks are acquired on a per-thread rather than per-invocation basis. Reentrancy is implemented by associating with each lock an acquisition count and remembering the owning thread.

From a performance point of view, locking has its own challenges. We will discuss them in detail in a later chapter. For now, just remember one simple rule:

“Avoid holding locks during lengthy computations or operations at risk of not completing quickly such as network or console I/O” [JCiP].

In the next post, I’m going to deal with sharing objects: memory visibility, immutability, what is safe and unsafe publication. Stay tuned!

Resource
[JCiP] Java Concurrency in Practice by Brian Goetz, ISBN-10: 0321349601

Java Concurrency in Practice: Study Notes

A Personal Standpoint

Not long ago a guy from the HR department of the company I work asked if I have interest interviewing candidates for open positions. And I said something like: “Sure, why not”. On the first couple of occasions, I was only an observant. I asked a question or two, but the interview itself was conducted by a more experienced colleague. Then I started doing interviews on my own over the phone and started taking up the leading role in face-to-face interviews. Of course, every interview is different and each interviewer has a favorite set of questions but more or less all interviews are conducted based on a script prescribing which specific topics should be visited. As I started taking more and more responsibility for interviews I noticed that there was a topic that made me very uncomfortable. Often I just asked a couple of basic questions or sometimes even skipped it “because of a time constraint”. You have probably guessed by now, it was: concurrency. Of course, I had a basic concept of what concurrency is and what are the main pitfalls. However, I only had limited knowledge and experience with writing concurrent Java programs. I thought to myself, it would a good time to study the topic of concurrency in Java until, from being a weakness, it becomes one of my strongest points.

Study. Ok, but from What?

One can learn a lot about concurrency in Java only by reading the documentation of concurrency related Java classes like java.lang.Thread. However, to get a broader picture and a detailed explanation I was looking for a good book to learn from. After a little bit of googling, I’ve noticed that most of the sources point to a single book: Java Concurrency in Practice by Brian Goetz [JCiP].

Java Concurrency in Practice book cover
Java Concurrency in Practice by Brian Goetz

After reading the book I can say that it wasn’t a coincidence. It’s a wonderful book: it’s deep but also written in a way that is easy to understand, and most common problems and their solutions are illustrated with code snippets. To put it simply: it’s a must read for every Java developer.

Study Notes

The best way of acquiring new knowledge is not just to read books, but also to take notes. By doing so our brain is “forced” to process the new information once more. This is one of the reasons why I did other books on this as well – check posts in the Bookshelf Category. Another reason is that I hope others can benefit from my notes too. If you don’t have the time to read the full book, or you are not sure if it worths the time: just check my notes. In this case, I decided to go chapter-by-chapter because there is so much to process. I’ll present my notes from each chapter on a weekly basis. It won’t take more than 5-10 minutes to read them and at the end, I’ll share some extra content too. Without any further due, here comes the first chapter.

Chapter 1: Introduction

Writing concurrent programs is hard, to maintain them is arguably even harder: So, why bother with concurrency in the first place? In a nutshell: it is the easiest way to tap the computing power of multiprocessor systems, and often it is easier to write a complicated asynchronous program by writing multiple pieces of code that run concurrently but each doing only a single well-defined task.

The main motivating factors behind the development of operating systems that allowed multiple programs to execute simultaneously were:

  • Resource utilization – programs sometimes have to wait for external events that are out of they control. For example, an I/O operation to finish. While waiting for other programs might do some useful work.
  • Fairness – multiple users and programs may have equal claims on the computer’s resources. In a multi-user or multi-process environment, it’s more desirable for each program to get a chance to do some work than to wait for one program to run to finish and then start another.
  • Convenience – “It is often easier or more desirable to write several programs that each perform a single task and have them coordinate with each other as necessary than to write a single program that performs all the tasks” [JCiP].

Individual programs run in isolated processes: resources such as memory, file handles, and security credentials are allocated by the operating system separately. If they needed to, processes could communicate through means of inter-process communication: sockets, signal-handlers, shared memory, and files. “The same concerns (resource utilization, fairness, and convenience) that motivated the development of processes also motivated the development of threads. Threads allow multiple streams of program control flow to coexist within a process. They share process-wide resources such as memory and file handles, but each thread has its own program counter, stack, and local variables.” [JCiP]

In most modern operating system the basic unit of scheduling is the thread – not the process. All threads within a process have access to the heap that allows fine grained inter-process communication. However, uncoordinated access from multiple threads can leave shared data in an inconsistent state, resulting in undefined program behavior.

Java’s built-in support for threads is a double-edged sword. On one hand, it simplifies the development of concurrent applications. On the other hand, developers need to be aware of thread-safety issues. “Thread safety can be unexpectedly subtle because, in the absence of sufficient synchronization, the ordering of operations in multiple threads is unpredictable and sometimes surprising” [JCiP]. Fortunately, Java provides a number of synchronization mechanisms to coordinate shared access. But, in the absence of such synchronization, “the compiler, hardware, and runtime are allowed to take substantial liberties with the timing and ordering of actions, such as caching variables in registers or processor-local caches where they are temporarily (or even permanently) invisible to other threads” [JCiP].

When writing concurrent applications one must never compromise on safety, we must ensure that “nothing bad ever happens”. Although, that is desirable we also want to make sure that “something good eventually happens”, meaning that the program should not get into a state where it is permanently unable to make progress. On top of that, we often want “good things to happen quickly”. It really would be a waste of effort to rewrite an application to use multiple threads and end up with a program with a worse performance than the single-threaded version.

Threads are really everywhere. “When the JVM starts, it creates threads for JVM housekeeping tasks (garbage collection, finalization) and the main thread for running the main method” [JCiP]. Sometimes concurrency is introduced by using frameworks. The developer writes the business logic which seems to be a simple sequential order of steps (see. convenience as a reason for concurrency) but when it is plugged into the framework it might execute in parallel with other tasks, thus requiring that all code paths accessing shared state be thread-safe.

Crossing the Chasm by Geoffrey A. Moore

“First, there is a mountain, Then there is no mountain, Then there is.”

Is this some kind of magic trick? Nope, this is how business to business marketing works in the high tech industry. And this what Crossing the Chasm book is about: marketing and selling technology products to mainstream customers.

Before you stop reading because “marketing is not for me”, I promise it’s going to be interesting just bear with me for a little longer. In fact, I think every developer should read that book to get a wider perspective on what happens with the code we write. How it becomes a real product and how marketing decisions can drive a product with superior technology into the ground while a seemingly inferior product triumphs.

Crossing the Chasm book cover
Crossing the Chasm book cover

Disruptive Innovation

First, we have to understand the distinction between continuous and discontinuous or disruptive innovation. BMW offering a faster, more dynamic gasoline car with a slightly better design is an example of continuous innovation. In contrast, all electric cars from Tesla represent a discontinuous innovation. Because they demand significant changes not only by the customer but also by the supporting infrastructure. We cannot just stop, fill up our electric car and be on our way in a matter of minutes – or at least not for now. We need to stop for like 30 minutes maybe have a bite while our car gets charged. In exchange, we get a cleaner, more sustainable and more efficient form of transportation.

The Technology Adoption Life Cycle

“The Technology Adoption Life Cycle model describes the market penetration of any new technology product in terms of a progression in the types of consumers it attracts throughout its useful life. The groups are distinguished from each other in terms of how they react to disruptive innovation.”

Innovators or technology enthusiasts pursue technology products simply for the pleasure of exploring the new capabilities they provide. Early adopters or visionaries appreciate the benefits of a new technology. They typically have a greater vision and they see how a new technology product could support their goals. The early majority shares the early adopter’s ability to relate to technology, but they are driven by practicality. They want to see how other people making out before they invest substantially. The late majority is even more conservative they wait until the new technology becomes a standard. Laggards are people who only buy the technology when it becomes a necessity or when it’s so deeply integrated with something existing that they don’t even know they bought it. Each group has a unique psychographic profile – price sensitivity, expectations, and priorities. Therefore selling products to customers in each group requires fundamentally different approach and marketing communication.

Discovering the Chasm

As we work ourselves through the technology adoption lifecycle we discover that the psychographic groups are divided from each other by gaps. “This symbolizes … the difficulty any group will have in accepting a new product if it is presented in the same way as it was to the group to its immediate left”. The biggest disconnect is between the innovators and the early majority – this is the chasm that many start-up ventures have fallen into. And because there are so many business customers on the right side of it crossing the chasm is fundamental to making any significant profits.

Visionaries or innovators expect a radical discontinuity between the old ways and the new, and they are prepared to fight the resistance. They are prepared to bear with the inevitable bugs and glitches of the new product. By contrast, what early majority wants is a productivity improvement for existing operations. They do not want to debug someone else’s product. They are looking for a solution integrated with current systems. Because of these incompatibilities, visionaries do not make good references for early majority. The only suitable reference, it turns out, is another member of the same group. This leads us to a catch-22 situation which needs to be solved because references play an utmost role in buying decisions of early majority customers.

Crossing the Chasm

To cross the chasm high technology companies need to launch a D-day type of invasion where they first focus on a single niche market segment to secure the beachhead. All development and marketing efforts should be focused on a single target. This is the only way to cross the channel … sorry, the chasm. Once the beachhead is secured you can advance to adjacent market segments until you become the market leader. But how to choose which beachhead to attack? You will need to select a market segment with an acute problem and provide a solution that current mainstream products cannot provide. They neglect a particular segment perhaps because they can make a tremendous amount of profit with a more general product.

Let me illustrate this with an example from the book. When farmaceutical companies introduce a new drug they deal with a very complicated documentation process. They were often delays just because the tracking and versioning of the documentation was a nightmare. Then came a company called Documentum that solved this literally million dollars a day problem. Guess what, effective document handling is also important in a number of other niches like finance, human resources etc. The trick is once you dominate a segment with customers of the early majority they serve as a very good reference for the same type of customers in adjacent segments.

Creating the Competition

When choosing the point of attack try to select a small pond where you can be the big fish. Of course, the pond should be big enough to keep you alive. And in any big enough pond there will be a competition. But competition is good, in fact, pragmatists resist to buy until they can compare. You will need two companies to put your product on the map like GPS satellites tell your position on the globe. One of them is the market alternative with established customer base you are after. This could be for example Microsoft SharePoint in document sharing. The other is the product alternative also harnessing the same disruptive innovation as your solution. This could be something like Dropbox with its ease of use and polished user experience. By pointing out that there is a product alternative you also weaken the position of the market alternative company. This is done by giving customers the notion that there is an undergoing paradigm shift in the marketplace. Your intent should be to acknowledge this new technology but to differentiate from the product alternative by virtue or your own segment focus.

Leaving the Chasm Behind

There is a sad revelation to make once you have successfully crossed the chasm. People who made this breakthrough possible most probably won’t carry you forward. Rockstar developers will want to work on the “next big thing” and salespeople who are able to sell to visionaries might not be as successful with conservatives. This transition won’t happen overnight but it will happen almost inevitably.

Personal Notes

I found two things very interesting in the book: subsequent editions after the first one haven’t been written because market dynamics have changed significantly. They work nearly the same way today as they were in 1991 when the book was first released. The reason for new editions was that companies come and go and the examples in the book had to be updated. Who heard of Lotus or Silicon Graphix? Will Facebook be still known in 10, 20 or 25 years time? Maybe, maybe not. It always fascinates me how fast paced our industry is.

The second thing is: the D-day type strategy might work withing a single enterprise just as well as in the wider market. I see a fractal pattern where departments inside a firm behave as adjacent market segments at a smaller scale. Departments working with less business critical applications will adopt any new technology first. Once it’s established at least in one department it will be easier to sell the technology to other department heads.

As a closure, I would like to recommend this book to developers and owners of small technology companies. A strategy that proved itself many times with big companies can be applied on a smaller scale as well. It might not be the same league but it surely is the same game!

7 Habits of Highly Effective People by Stephen R. Covey

I’ve read this magnificent book recently and I would like to share some of my findings with you. It’s going to be less of a formal review but rather an ad-hoc collection of subjective thoughts about the ideas presented in the book. You may say: “this is just one those worthless self-help books” or “This is just another scam”. But I can assure you nothing is further from the truth. This book can really help those who seek ways to improve their personal and business relationships, or simply just want to better understand themselves and their place in the world.

The 7 Habits of Highly Effective People book cover
The 7 Habits of Highly Effective People by Stephen R. Covey

The core of the book 7 Habits of Highly Effective People consists of two parts: private and public victories. This division catches the essence of the revelation that in order to be successful in our interpersonal relationships we first need to build our own character. You cannot win by hacking at the leaves without taking care of the problems at the root. Now let’s have a look at the 7 habits of highly effective people.

Habit 1: Be Proactive

Act and not be acted upon. So simple, but so powerful. Arguably one of the greatest sources of frustration is that we feel like we are not in control of our own life. The book says: “we find two ways to put ourselves in control of our lives immediately. We can make a promise – and keep it. Or we can set a goal – and work to achieve it“. By doing so, we build a character that will serve as a strong foundation we can build upon.

Habit 2: Start with the End in Mind

How would like to be remembered after you are gone? What kind of husband, wife father, mother, colleague or friend were you? Did my yesterday behavior bring me closer to what I’ve just imagined who I want to be? If you start with the end in mind you will find yourself working towards your life goals and not wandering on side roads. “People may spend their whole lives climbing the ladder of success only to find, once they reach the top, that the ladder is leaning against the wrong wall.

Habit 3: Put First Things First

For the many of us, and I’m no exception, there is a deep chasm between what we say are important things to us, and how we actually allocate our time. That’s not always as evident as choosing between going to a gym or watch another episode of our favorite TV show. Sometimes we think: oh, it would be very important to read that book or take that course, but I’ll do these million little things first.
To say yes to important priorities, you have to learn to say no to other activities, sometimes apparently urgent thigs.” And it’s tricky because finishing up little tasks gives us the feel of progress while we are neglecting other things that would contribute to our long-term growth. Put first things first is the last one of private victories.

The first 3 habits are concluded with an analogy to which IT people can easily relate too. We need to realize that we are the “programmers” of our own life (habit 1). We need to “write” the program with the desired end result in mind (habit 2). Then we need to “execute” (habit 3). Each step builds upon the previous one, just like developing personal victories serves as a foundation for public victories.

Habit 4: Think Win-Win

Who is winning in your marriage? is a ridiculous question. If both people aren’t winning, both are losing.” Life, in most cases, is not a zero sum game. For you to win another person does not necessarily have to lose. Most people are scripted in scarcity mentality – there is only one pie out there, and if someone were to get a piece, it would mean less for everybody else. This is how mediocre people see the world. On the other hand, people with abundance mentality realize how sharing of prestige, recognition, and profit springs new possibilities for even greater successes. Having abundance mentality is essential to be able to think win-win.

Habit 5: Seek First to Understand Then to be Understood

Since our childhood, we put tremendous efforts into improving our communication skills both written and verbal. But what about listening? “Most people do not listen with the intent to understand; they listen with the intent to reply”. To try to help somebody without seeing things from the other person perspective first is like prescribing medicine without examination. Our ability to think win-win is greatly affected by how carefully we intend to listen. It happened to me in the past, probably more than once, that a UI developer came to me complaining about the API I wrote as a backend developer. It didn’t make any sense to me. I was thinking: “It suits the requirements why can’t he just use it!” Now I know, I couldn’t understand him because I didn’t intent to listen.

Habit 6: Synergize

What is synergy? Simply defined, it means that the whole is greater than the sum of its parts. It means that the relationship which the parts have to each other is a part in and of itself.” By exercising habits 4 and 5 we often reach a synergistic solution that is better than either of the originally proposed ones. “The essence of synergy is to value the differences. Sameness is not oneness; uniformity is not unity.” Probably the aforementioned API would have turned out to be much better if a synergistic solution had been reached.

Habit 7: Sharpen The Saw

If you take a little time to sharpen the saw you will be able to cut down a tree much faster. It’s a very simple principle, but still, people often fail to recognize it in their own life. “Going to the gym takes to much time”. Well, how much time will you spend at doctors if you ruin your health? Sharpen the saw is basically improving our production capability today. Because for the great struggles of the future, you have to prepare today.

These are the 7 habits of highly effective people by Stephen Cover. Of course, the book goes into greater lengths and explains each topic in much more detail. The book is enriched with real life stories about the author’s family. Reading these stories was full of aha moments when I realized that something similar has happened to me in the past and now I can understand why things played out as they did. The cool thing about these stories is that the author does not try to hide his own mistakes. We learn that sometimes he failed to respond to a given situation in harmony with the seven habits. However, sincerely admitting our mistakes is not a weakness but quite the contrary a manifestation of great strength. Remember: success lies on the far side of failure.

Remotely Rich by Matt Vogel

“Do you want to make $450,000 a year as a Web developer?”

What a rhetorical question to start a book with. I started thinking right away: is that achievable by a combination of web development and affiliate marketing, or perhaps by developing your own product and selling it to big businesses? Actually, none of that turned out to be the case.


Book Cover - Remotely Rich

In his book Remotely Rich, Matt Vogel is sharing his practices and experiences of being a freelancer web developer working from home. But how can he make almost half a million dollars a year? The secret turns out to be more prosaic than you might think. Matt is saying that by managing his time properly and by cutting out all the disruption that is present in an office environment he is able to work three full-time jobs. And because freelancers tend to be paid more than regular workers the numbers add up. I’m pretty sure that anyone who ever worked in an office can testify that a significant portion of the day is spent in a breakout area – drinking coffee, tea or some other source of caffeine and sugar while discussing last weekend and planning the next one.

In contrast, Matt focuses on maximizing effectiveness. It’s not easy and he is painting a very realistic picture of what it takes to be a freelancer. Matt admits it can be difficult sometimes and occasionally it involves working crazy hours to meet a deadline. However, I could not help myself but think that, in one form or another, most of the challenges of being a freelancer is present at regular jobs too. Working on the weekend? Check. Do managers have unrealistic expectations or imperfect knowledge about the state of the project? Most of the time. I’m not saying that working in a nine-to-five job and being a freelancer are the same things, but there are similarities for sure. Probably handling clients is the biggest challenge that you don’t have to bother with when you are working for a company. I see that not every programmer would be willing to do that. However, maybe it would worth to git it a try given how financially rewarding freelancer life could be. There are some valuable tips and techniques in the book regarding how clients should be handled.

Matt in his book is being very practical and tells us about a lot of things from choosing office space down to personal hygiene (really). There is a section dedicated to advises on tax and financials. Because he is living in the US this section is less helpful for us who work outside the States. Although every developer should think about what to do with the money earned. Invest in stocks, bonds or index funds? Buying a real estate is an option too. Developers who are not confident with financials should seek professional advice.

Remotely Rich is not a long book to read. It’s very practical and down-to-earth. This book is more about core soft skills than programming techniques. I definitely recommend it to anyone who is thinking about starting a career as a freelancer web developer.


Amazon: Remotely Rich – How to Multiply Your Income As a Web Developer