First steps with Ethereum Private Networks and Smart Contracts on Ubuntu 16.04

Ethereum is still in that “move fast and break things” phase. The docs for contracts[1] are very out of date, even the docs for mining have some out of date content in[2].

I wanted a very simple guide to setting up a small private network for testing smart contracts. I couldn’t find a simple one that worked. After much trial and error and digging around on Stackexchange, see below the steps I eventually settled on to get things working with a minimum of copy/paste. Hope it will prove useful for other noobs out there and that more experienced people might help clear things up that I have misunderstood.

I’ll do 3 things:

  1. Set up my first node and do some mining on it
  2. Add a very simple contract
  3. Add a second node to the network

First make sure you have installed ethereum (geth) and solc, for example with:

sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum solc

Set up first node and do some mining on it

Create a genesis file – the below is about as simple as I could find. Save it as genesis.json in your working directory.

  "config": {
    "chainId": 1907,
    "homesteadBlock": 0,
    "eip155Block": 0,
    "eip158Block": 0
  "difficulty": "40",
  "gasLimit": "2100000",
  "alloc": {}

Make a new data directory for the first node and set up two accounts to be used by that node. (Obviously your addresses will differ to the examples you see below).

ethuser@host01:~$ mkdir node1
ethuser@host01:~$ geth --datadir node1 account new
WARN [07-19|14:16:22] No etherbase set and no accounts found as default 
Your new account is locked with a password. Please give a password. Do not forget this password.
Repeat passphrase: 
Address: {f74afb1facd5eb2dd69feb589213c12be9b38177}
ethuser@host01:~$ geth --datadir node1 account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Repeat passphrase: 
Address: {f0a3cf66cc2806a1e9626e11e5324360ee97f968}

Choose a networkid for your private network and initiate the first node:

ethuser@host01:~$ geth --datadir node1 --networkid 98765 init genesis.json
INFO [07-19|14:21:44] Allocated cache and file handles         database=/home/ethuser/node1/geth/chaindata cache=16 handles=16
INFO [07-19|14:21:44] Successfully wrote genesis state         database=lightchaindata                          hash=dd3f8d…707d0d

Now launch a geth console

ethuser@host01:~$ geth --datadir node1 --networkid 98765 console
INFO [07-19|14:22:42] Starting peer-to-peer node               instance=Geth/v1.6.7-stable-ab5646c5/linux-amd64/go1.8.1
 datadir: /home/ethuser/node1
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0


The first account you created is set as eth.coinbase. This will earn ether through mining. It does not have any ether yet[3], so we need to mine some blocks:

> eth.coinbase
> eth.getBalance(eth.coinbase)
> miner.start(1)

First time you run this it will create the DAG. This will take some time. Once the DAG is completed, leave the miner running for a while until it mines a few blocks. When you are ready to stop it, stop it with miner.stop().

INFO [07-19|14:40:03] 🔨 mined potential block                  number=13 hash=188f37…47ef07
INFO [07-19|14:40:03] Commit new mining work                   number=14 txs=0 uncles=0 elapsed=196.079µs
> miner.stop()
> eth.getBalance(eth.coinbase)
> eth.getBalance(eth.accounts[0])

The first account in the account list is the one that has been earning the ether for its mining, so all we prove above is that eth.coinbase == eth.accounts[0]. Now we’ve got some ether in the first account, let’s send it to the 2nd account we created. The source account has to be unlocked before it can send a transaction.

> eth.getBalance(eth.accounts[1])
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xf74afb1facd5eb2dd69feb589213c12be9b38177
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(3,"ether")})
INFO [07-19|14:49:12] Submitted transaction                    fullhash=0xa69d3fdf5672d2a33b18af0a16e0b56da3cbff5197898ad8c37ced9d5506d8a8 recipient=0xf0a3cf66cc2806a1e9626e11e5324360ee97f968

For this transaction to register it has to be mined into a block, so let’s mine one more block:

> miner.start(1)
INFO [07-19|14:50:14] Updated mining threads                   threads=1
INFO [07-19|14:50:14] Transaction pool price threshold updated price=18000000000
> INFO [07-19|14:50:14] Starting mining operation 
INFO [07-19|14:50:14] Commit new mining work                   number=14 txs=1 uncles=0 elapsed=507.975µs
INFO [07-19|14:51:39] Successfully sealed new block            number=14 hash=f77345…f484c9
INFO [07-19|14:51:39] 🔗 block reached canonical chain          number=9  hash=2e7186…5fbd96
INFO [07-19|14:51:39] 🔨 mined potential block                  number=14 hash=f77345…f484c9

> miner.stop()
> eth.getBalance(eth.accounts[1])

One small point: the docs talk about miner.hashrate. This no longer exists, you have to use eth.hashrate if you want to see mining speed.

Add a very simple contract

The example contract is based on an example in the Solidity docs. There is no straightforward way to compile a contract into geth. Browser-solidity is a good online resource but I want to stick to the local server as much as possible for this posting. Save the following contract into a text file called simple.sol

pragma solidity ^0.4.13;

contract Simple {
  function arithmetics(uint _a, uint _b) returns (uint o_sum, uint o_product) {
    o_sum = _a + _b;
    o_product = _a * _b;

  function multiply(uint _a, uint _b) returns (uint) {
    return _a * _b;

And compile it as below:

ethuser@host01:~/contract$ solc -o . --bin --abi simple.sol
ethuser@host01:~/contract$ ls
Simple.abi  Simple.bin  simple.sol

The .abi file holds the contract interface and the .bin file holds the compiled code. There is apparently no neat way to load these files into geth so we will need to edit those files into scripts that can be loaded. Edit the files so they look like the below:

ethuser@host01:~/contract$ cat Simple.abi
var simpleContract = eth.contract([{"constant":false,"inputs":[{"name":"_a","type":"uint256"},{"name":"_b","type":"uint256"}],"name":"multiply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_a","type":"uint256"},{"name":"_b","type":"uint256"}],"name":"arithmetics","outputs":[{"name":"o_sum","type":"uint256"},{"name":"o_product","type":"uint256"}],"payable":false,"type":"function"}])


ethuser@host01:~/contract$ cat Simple.bin

var simple =
{ from: eth.accounts[0],
data: "0x6060604052341561000f57600080fd5b5b6101178061001f6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063165c4a161460475780638c12d8f0146084575b600080fd5b3415605157600080fd5b606e600480803590602001909190803590602001909190505060c8565b6040518082815260200191505060405180910390f35b3415608e57600080fd5b60ab600480803590602001909190803590602001909190505060d6565b604051808381526020018281526020019250505060405180910390f35b600081830290505b92915050565b600080828401915082840290505b92509290505600a165627a7a72305820389009d0e8aec0e9007e8551ca12061194d624aaaf623e9e7e981da7e69b2e090029",
gas: 500000

Two things in particular to notice:

  1. In the .bin file you need to ensure that the from account is unlocked
  2. The code needs to be enclosed in quotes and begin with 0x

Launch geth as before, load the contract scripts, mine them into a block and then interact with the contract. We won’t be able to do anything useful with the contract until it’s mined, as you can see below.

ethuser@host01:~$ geth --datadir node1 --networkid 98765 console
INFO [07-19|16:33:02] Starting peer-to-peer node instance=Geth/v1.6.7-stable-ab5646c5/linux-amd64/go1.8.1
> loadScript("contract/Simple.abi")
> loadScript("contract/Simple.bin")
Unlock account 0xf74afb1facd5eb2dd69feb589213c12be9b38177
INFO [07-19|16:34:16] Submitted contract creation              fullhash=0x318caec477b1b5af4e36b277fe9a9b054d86744f2ee12e22c12a7d5e16f9a022 contract=0x2994da3a52a6744aafb5be2adb4ab3246a0517b2
> simple
  address: undefined,
  transactionHash: "0x318caec477b1b5af4e36b277fe9a9b054d86744f2ee12e22c12a7d5e16f9a022"
> simple.multiply
> miner.start(1)
INFO [07-19|16:36:07] Updated mining threads                   threads=1
INFO [07-19|16:36:21] 🔨 mined potential block                  number=15 hash=ac3991…83b9ac
> miner.stop()
> simple.multiply
[17, 72]

Set up a second node in the network

I’ll run the second node on the same virtual machine to keep things simple. The steps to take are:

  1. Make sure the existing geth node is running
  2. Create an empty data directory for the second node
  3. Add accounts for the second geth node as before
  4. Initialise the second geth node using the same genesis block as before
  5. Launch the second geth node setting bootnodes to point to the existing node

The second geth node will need to run on a non-default port.

Find the enode details from the existing geth node:

> admin.nodeInfo
{  enode: "enode://08993401988acce4cd85ef46a8af10d1cacad39652c98a9df4d5785248d1910e51d7f3d330f0a96053001264700c7e94c4ac39d30ed5a5f79758774208adaa1f@[::]:30303", 

We will need to substitute [::] with the IP address of the host, in this case

To set up the second node:

ethuser@host01:~$ mkdir node2
ethuser@host01:~$ geth --datadir node2 account new
WARN [07-19|16:55:52] No etherbase set and no accounts found as default 
Your new account is locked with a password. Please give a password. Do not forget this password.
Repeat passphrase: 
Address: {00163ea9bd7c371f92ecc3020cfdc69a32f70250}
ethuser@host01:~$ geth --datadir node2 --networkid 98765 init genesis.json
INFO [07-19|16:56:14] Allocated cache and file handles         database=/home/ethuser/node2/geth/chaindata cache=16 handles=16
INFO [07-19|16:56:14] Writing custom genesis block 
INFO [07-19|16:56:14] Successfully wrote genesis state         database=lightchaindata                          hash=dd3f8d…707d0d
ethuser@host01:~$ geth --datadir node2 --networkid 98765 --port 30304 --bootnodes "enode://08993401988acce4cd85ef46a8af10d1cacad39652c98a9df4d5785248d1910e51d7f3d330f0a96053001264700c7e94c4ac39d30ed5a5f79758774208adaa1f@" console

Wait a little and you will see block synchronisation taking place

> INFO [07-19|16:59:36] Block synchronisation started 
INFO [07-19|16:59:36] Imported new state entries               count=1 flushed=0 elapsed=118.503µs processed=1 pending=4 retry=0 duplicate=0 unexpected=0
INFO [07-19|16:59:36] Imported new state entries               count=3 flushed=2 elapsed=339.353µs processed=4 pending=3 retry=0 duplicate=0 unexpected=0

To check that things have fully synced, run eth.getBlock('latest') on each of the nodes. If things aren’t looking right then use admin.peers on each node to make sure that each node has peered with the other node.

Now you can run the miner on one node and run transactions on the other node.



Compiling via RPC has been removed in #3740 (see ethereum/EIPs#209 for why). We will bring it back under a different method name if there is sufficient user demand. You’re the second person to complain about it within 2 days, so it looks like there is demand.

[2] The official guide to Contracts is out of date. I spotted some out of date material on Mining and submitted an issue but updating the official docs doesn’t seem much of a priority so I figured I would collect my learnings here for now.
[3] You can pre-allocate ether in the genesis.json if you prefer, but that would mean a little more cut and paste which I am doing my best to minimise here.

Learning Haskell gave me a whole new outlook on programming

A while back I decided to learn Haskell as a counterpoint to Ruby/Java etc that I was more familiar with previously. I am very grateful for the new perspective that learning Haskell has given me. In particular:

  • I always used to start with database tables and a user interface. Haskell forces you to think about the functions and how they work on data structures. Not having to think about data storage is strangely liberating as it is much easier to change your data structures if there is no UI or database to worry about.
  • It might need a lot more thinking to write a piece of code, but by the time you’ve finished it invariably feels very elegant.
  • Writing pure code and then wrapping IO around it later really forces you to write code that is simpler and more testable.
  • I have an appreciation of how intimidating jargon can confuse and put people off, unnecessarily. For example, Haskell purists might want you to grok Category Theory even if it’s not that relevant to writing Haskell apps.

The learning curve has been ridiculous. Have a look at Tymon Tobolski’s comparison of using Ruby vs Haskell in a small Redis application. The Haskell version is terse to the point of being incomprehensible at the outset. As a Haskell learner I couldn’t find something that packed a similar “wow” to “A blog in 15 minutes with Ruby on Rails”

Here’s a small Scotty/Warp Haskell app I put together recently. (Scotty is Haskell’s answer to Sinatra for you Rubyists).

Impress your CTO – Track Everything

The day after your new feature goes live, someone will want to know how well it’s working (or not). They don’t just mean “are there any exceptions in the logs”. They mean “how are people using it, if at all?”

Hopefully, you had thought about unspecified requirements and so you already implemented something that they can see. It doesn’t even have to be super heavyweight. I’ve seen good stuff done using something sophisticated like Heap Analytics, and also seen people be able to get actionable insights from something as simple as Google Analytics.

Whatever you choose to do, make sure that there is an easy way for a non-developer to dig around the stats, and ideally download some raw data to play around with offline.

Just be sure to track everything.


Trying to make some sense of it all

I’m still trying to get to grips with the course of events in the UK recently. Since the Brexit referendum, of course, but increasingly over the past few days. I’m getting a bit tired of the Facebook echo-chamber and so given that I have a blog I figured I’d take a momentary break from talking about tech to think through these issues. But here’s a tweet to give some Tech Business angle to this post.

OK with that out of the way let’s get on with things.

The Conservatives apparently want to shame British firms into hiring more British workers by making them publish how many non-British workers they employ. And most Brits apparently support that position.

Similarly, they, apparently all of a sudden, want schools to list how many foreign-born students they each have. And there are also the reports about the Foreign Office not wanting to use foreigners in some advisory work to do with leaving the EU.

Meanwhile, the de facto opposition party (UKIP) has experienced thuggish behaviour and somehow this is considered acceptable by the UK electorate. And in a surprising twist, a UKIP representative has spoken out against these Conservative ideas.

I’m a member of the liberal, cosmopolitan elite. In the referendum I supported Remain. My sympathies were to Leave based on the mess that the EU has made of Greece. But the absence of any realistic vision for how Leave could work meant that, for me, the whole thing was flawed. I suspect that most (all?) other voters also have their own reasons that defy stereotyping. I certainly didn’t enjoy the Remain scare-mongering. For what it’s worth I also have a healthy scepticism of experts – they crop up all over the place and I’m not always convinced of their insight. However I do have to admit that some of the worst scare-mongering (I seem to remember £1 being predicted to fall as far as $1.28) has now come true so I do wonder what else will be coming over the horizon.

Anyway, back to the plot. The public was asked a question and in a close result the public answered it. Brexit was about leaving the EU. I hope that however Brexit gets implemented it is not a simple Tyranny of the 51%. But that’s not what worries me most. What worries me most is that, based on the noises that we are hearing, Brexit is increasingly becoming about xenophobia, not about the EU.

Since the referendum result racist incidents have increased. Over the past week we’ve seen these latest nationality-related proposals. Obviously I’ve never met any of these people and don’t know what their motives are, to what degree they believe what they are reported as saying, to what degree they are grandstanding or just doing their job or whatever. But something is very concerning indeed about the content of this debate.

Let’s come back to the Name And Shame Businesses Who Employ Foreigners idea. The Party may now be back-pedalling on it but remember that, firstly, it was seriously considered, and secondly, the reality is that apparently most UK people support it. I do expect it to come back in another guise sooner or later (consider the example about profiling non-Brits in British schools). So let’s imagine that, in order to try to improve standards of living, British companies are somehow encouraged to hire native Brits rather than foreigners. It’s easy to see where this will end: They will hire based on nationality rather than ability; so they will perform less well; standards of living won’t increase as expected; immigrants will get scapegoated even more; and the cycle will repeat itself.

Whether in our out of the EU, this country depends on immigrants and will always depend on immigrants. Immigrants disproportionately contribute to the UK, despite the views evident in the YouGov poll. How to reconcile these contradictory facts is something I would hope our leadership manages to lead on, rather than just scapegoating immigration as they seem to be doing. I do have a general faith in common sense, decency and democracy so I remain optimistic, but it ain’t easy. Maybe I’ll have to stay up to watch the US Presidential Debate tonight to remind myself that it could always be worse.

Update 31st December 2016:

One thing that has been playing on my mind is the clear strength of feeling on the subject. There was a James O’Brien LBC clip doing the rounds a while back in which a Leave voter was finding it hard to articulate why he wanted to Leave (probably something to do with immigration). Getting out-talked by a talk show host isn’t the interesting thing here. The interesting thing here is that towards the end of the call the caller says he is willing to suffer 5 years of financial/economic hardship in order to get to a better future. That level of self-sacrifice is pretty incredible.

That’s not a business, it’s a hustle

“That’s not a business, it’s a hustle.”

I’m paraphrasing Dan Lyons speaking at a recent Chew The Fat event. He was talking about his time at HubSpot and wondering how a loss-making company could grow so fast, list, and make a lot of investors a lot of money. In his view its business model is fundamentally flawed: he describes it as buying dollar bills at face value and selling them at 75 cents each. That sort of model may well get you hyper-growth but it’s a hustle, not a business.

The image of the hustling, zillionaire tech entrepreneur who has never made worried about profits has become dangerously deeply ingrained. I recently got talking to a graduate – evidently a bright individual – who ran a business idea past me. It was to do with optimising a retail shopping experience. Quite a neat idea so I asked the obvious question: where would the revenue come from? The consumers or the retailers?

He didn’t have an answer.

He assumed that all he’d have to do is somehow get some VC money, spend it on scaling a platform with loads of users, then sell out and walk off into the distance with $50 million in his pocket. Now that’s a hustle, not a business. There are cases where this has happened. But there are also plenty of cases of people winning the lottery and I suspect that on a risk-weighted basis, winning the lottery is more likely than being a part of the next Whatsapp.

Please, if you want to become an entrepreneur, bear these two things in mind:

  1. You stand a better chance of making a successful business if you have intimate knowledge of the problem you are trying to solve. If you’re targeting students then, fine, as a recent student you might have more than enough knowledge to build a viable business. But if you’re not then probably you would need to work somewhere for a few years to get that deep understanding first (“domain knowledge”, in the jargon)
  2. You will stand a better chance of success if you can create something that makes revenue, profit and cash. All those things are different so make sure you have a clear idea of how they will interplay in your business. In fact, you might even end up with more money in your pocket if you build a niche, profitable, growing business than if you go chasing unicorns.

This doesn’t mean you need a detailed business plan. You just need to be articulate those two points in as straightforward a fashion as possible. Here’s a classic DHH talk to hopefully get you thinking along the right lines . Incredibly it is still as valid today as it was in 2008.

Startup Lessons from the English East India Company


The Company of Merchants of London trading into the East Indies was founded in 1600 as a scrappy startup trying to disrupt a spice trade dominated by the Dutch. Over the next two centuries it evolved into a solid financial performer, a regulated monopoly and then into a branch of government.

Please put aside for the rest of this post any concerns about the various and many reprehensible things done by, or in the name of, this company. Just look at it from the perspective of what it can tell us about growing and evolving a business.

Turns out that plus ca change. Much of what we obsess about in the world of startups today would be very recognisable to an observer in the 1600’s. In the 21st Century how companies get created and develop is not all that different to 400+ years ago. Shouldn’t be surprising as ultimately we are still people and people haven’t changed all that much over the centuries.

The quotes below are from John Keay’s The Honourable Company.

On being an early stage investor

The first voyage didn’t live up to founder or investor expectations but it was a pretty impressive feat nonetheless. Now there’s a sentence that could easily apply to every MVP I’ve seen. It set out in 1601 in search of the spice islands and their cloves. Didn’t quite make it but managed to return in 1603 with plenty of pepper.

[T]he 218 petitioners who in 1600 had become the Company of Merchants of London trading into the East Indies had subscribed for only one voyage. The majority now wanted their money back; they were not amused when instead they were told that for every £250 they had subscribed, £200 must be reinvested in a second voyage. (p25)

Same lesson applies today to any early seed investor. Make sure you’ve kept enough money aside for a top-up later on. Whatever you put in now won’t be enough.

On the importance of dog-fooding

England had one huge commodity at the time: wool. The Company was desperate to find a market for wool and thought that Japan might be a good bet. Unfortunately not so. Keay quotes John Saris, leader of this expedition who in 1613 wrote that:

The natives were now more backward to buy than before because they saw that we ourselves were no forwarder in wearing the thing that we recommended to them. ‘For’, said they, ‘you commend your cloth [wool] unto us but you yourselves wear least thereof, the better sort of you wearing silken garments, the meaner fustians [made from cotton] (p58).

Product Managers take note: use your product and be seen to use it 🙂

On the roller-coaster of investing in a growth stock

“£100 of stock purchased … in 1657 had slumped to £70 by 1665 but thereafter appreciated dramatically. By 1677 it was valued at £245 and by 1683 was selling at anything between £360 and £500.” (p170)

Now look at the stock price chart of Facebook 2013 vs Facebook 2016.

On becoming a solid financial performer

If the 17th Century was about a scrappy startup trying to figure out its business model, in the 18th Century the bean counters took over.

By 1710 it was regularly sending to the East ten to fifteen ships a year, each of around 300 tons… Thirty years later the number of sailings had risen steadily … to around twenty, each ship being usually of 490 tons. (Over 500 tons and the ship’s company had to include a chaplain.) … Naturally prices and profits fluctuated but there was none of the erratic boom and bust so typical of the previous century. Shareholders came to expect their annual 8 percent dividend and when in 1732 it was proposed to reduce it to 6 per cent there was such an outcry that the directors had to think again. India stock had become the eighteenth-century equivalent of a gilt-edged security, much sought after by trustees, charities and foreign investors. (p220)

Interesting to see the emphasis move from capital appreciation to income generation.

On dealing with the haters

Naturally success breeds detractors and the Company had plenty of those. From a 21st Century perspective it’s really interesting to see 17th Century people struggling with trying to make sense of international trade. When the first voyage returned in 1603 it faced some hostility back home: “Already there were those who failed to see how exchanging precious bullion for an inessential condiment like pepper could possibly be in the national interest.”(p24).

One recurrent criticism … was that the Company must be impoverishing the nation since it exported treasures and imported only luxury items. In the case of Indian cottons these were manufactured goods which must be killing off English manufactures… But in 1620 Thomas Mun, a director of the Company, met … objections in his Discourse of Trade unto the East Indies. Mun argued convincingly that there was nothing inherently wrong with exporting precious metals provided that values of such exports was less than the value of the imported goods. ‘For let noe man doubt that money doth attend merchandise, for money is the price of wares and wares are the proper use of money, so that coherence is inseperable.’ (p119)

We may not be so worried about exporting gold any more. But there are plenty of similar debates about trade vs. protectionism still going on.

On the role of telling a good story to the financial markets (and of investing in yourself)

Robert Clive, already a powerful presence in the Company, was sent from England to run their interests in India in 1764. He was so excited at the opportunities he found that he “gave instructions for ‘whatever money I may have in public funds or anywhere else and as much as can be borrowed in my name’ to be invested in Company stock.” (p376)

Clive was massively over-optimistic about what he could deliver. The huge annual surplus he foresaw was “sweet music to the ears of the directors” and when news of these predictions reached London in 1766 they had a profound effect on Company stock.

[T]he Company’s stock, a normally unexciting performer on the financial markets, suddenly began to climb. It added …. about five percent in a single day and it went on climbing, nearly doubling its value over the next eight months. Clive’s friends …. bought heavily; but as word of his optimistic calculations … leaked out, outside investors also leapt on the bandwagon. On the Amsterdam and Paris markets the bubble went on growing and as the wilder speculators moved in, the greater became the pressure to keep the bubble from bursting.

An obvious way of preventing such a catastrophe was by boosting confidence still further with a hefty increase in the annual dividend … Accordingly, in September 1766, the General Court of Proprietors moved from an increase from six to ten percent… As a result, stock values continued to climb. (p378)

Turns out he had been massively over-confident and the stock price crashed later on. But just goes to show much people have always been driven by story telling and their animal spirits.

And finally, on how to eventually turn philanthropist

Of those who remained in the Company’s service the American-born Yale brothers proved the shrewdest operators. In the late 1680s Thomas Yale handled their affairs in Siam while Elihu Yale maximised their profits as Governor of Madras. Eventually both attracted the Company’s censure and were dismissed for abusing their positions. Elihu was not, however, disgraced and … he was able to retain his Indian fortune. Part was donated to his old school, then known as His Majesty’s College of Connecticut. In 1718 the grateful trustees renamed it ‘Yale College’ in his honour. (pp199-200)


Impress your CTO – avoid these boring complaints

Here are some of the most boring complaints I hear.

  • No-one knows how it works
  • You can’t measure the quality of what I’m doing
  • It’s because of all of our technical debt
  • We need to re-write this from scratch

They each contain an element of truth but at the same time they manage to completely miss the point. Hence boring.

No-one knows how it works

This really means “I don’t know how it works and nor does the person I usually work closest with”. I once saw a developer spend a huge amount of time trying to recreate, by reading the friendly source, the possible state transitions for a particularly key entity. Because “no-one understood it”. This had two problems:

  1. He may have missed something
  2. By reverse engineering requirements from the working code, what he ended up describing might have included bugs rather than how the feature was supposed to work.

And in this particular instance I could have pointed the developer to one person still in the business and one person who had left but would still be helpful. Next time you’re tempted to assert “no-one understands these state transitions” just change it to a question: “Is there anyone either on the team here, or who has left but is still friendly, who can help me understand how these state transitions are supposed to work?”

You can’t measure the quality of what I’m doing

This is invariably an attempt to hide something. I once worked with a team who didn’t report their test coverage because the lead developer felt that software is too complicated for a metric as simple as test coverage to be meaningful. We debated the subject and eventually agreed that although 100% coverage is probably not that meaningful, it is worth at least knowing where you are. Where were they when they measured code coverage? About 15%. I was amazed. Here we were debating the costs and benefits of 90% or 100% code coverage and all the time we were staring 15% in the face. I cannot think of anyone who would seriously argue that code coverage of 15% is in any way acceptable. For sure, you can’t measure everything, but the skill of a good developer is in helping finding a useful metric to use. For example on a recent project we agreed on a simple metric that if RubyCritic gives us an  A or a B grade then that’s good, if it’s any worse then we need to know why. It’s not perfect but it’s a lot better than hiding behind “you can’t measure what I’m doing”.

It’s because of all of our technical debt

As an experiment, I once agreed with a team to spend one month just doing technical debt cleanup. The results? Nothing noticeably better or faster for the users, nothing notably better quality as far as the QA people were concerned, no metric to show anything had improved, and I was still getting the same developers 3 months later making the same complaints about technical debt. The reality is that there will always be technical debt of some shape or form. Just like real world debt, some technical debt can be good if it helps you achieve other ends that you couldn’t otherwise achieve. Better developers would have a plan that says, for example, “Technical debt in module X is causing us problems, in order to fix those we will need to do Y”. This is better because it is specific and measurable and, if defined well enough, deliverable.

We need to re-write this from scratch

Stop thinking that. It’s a dreadful idea. Whenever you think of re-writing you are thinking of the 20% of the system that is a PITA to maintain. You’re not thinking of the 80% of the system that you will also need to re-write. I remember one project where a 5-month re-write was still going on 18 months later, still with no end in sight. And another where a re-architected system was being built in parallel but wasn’t able to keep up with the new features being added to the “legacy” platform. In shoert I’ve never seen a complete re-write that people were glad to have done. If you do need to make dramatic changes then you will need to find some way to change very specific parts of the application one by one. It will take a very long time: make sure you do your homework before advocating this.