Friday, July 18, 2014

How the IRS in the Netherlands effectivily prevents the funding of startup companies

A software engineer one day has a brilliant idea for a new product. As she has some savings in the bank, she can afford to take a year off and work on the brilliant new product. After about six months, she publishes the app, and she decides that she needs more people to complete the whole set of software, web site and apps. Fortunately, she finds a VC fund that is willing to invest €3 million. Now she can incorporate the company, hire a couple of programmers, a sales person, and set up a proper set of servers in the cloud.

Two months after the closing of the investment deal, she receives a letter from the IRS. The letter states that as the VC fund invested €3 million for a stake of 30% in the company, our software engineer entrepreneur created a value of €7 million with her own shares at incorporation of the company. She now needs to pay income tax over €7 million. Of course, she does not have that money. Six months later she's declared bankrupt, she needs to leave the company, and the company without her is liquidated, at a substantial loss for all involved except the IRS. It takes her three years to get out of bankruptcy, as that's the legal term on which a personal bankruptcy should end with a clean slate.

Another software engineer, a close friend of our unfortunate first entrepreneur, decides to follow another path. He takes a year off, and on the first day incorporates a company to hold the intellectual property rights of the software he will be creating. That way, no value is "created" at the point where a VC fund invests.

After two months, our friend receives a letter from the IRS. As he's working as the sole proprietor of his corporation, in which he is creating value for the company, and as he has no other jobs, the company is required by law to pay him a salary of € 40,000 per year. Of course, the company doesn't actually need to do this, as long as it pays taxes as if it did. The entrepreneur needs to pay income tax for a fictional income of € 40k per year. This is not how our friend wants to spend his savings, so he calls the company he used to work for and gets his job back. He still has to pay two months of income tax from his savings.

Another friend, having seen all this, thinks she's smarter. She writes a letter to the IRS asking them how to go about if you start a tech company, you work 12 months for free, living off your savings, and how to avoid being taxed before the company makes revenues and the entrepreneur gets an income from the company. It takes two months for the IRS to reply: "we are not a consulting agency, we are the IRS. We tax companies and people, but we don't advise you on how to arrange your administration. We refer you to your tax consultant". After conversations with four different fiscal consultants, having received four different opinions on how the IRS will act, the entrepreneur gives up and tells her boss to please not pay attention to her resignation letter.

But there's a happy ending,
The fourth entrepreneur in this little group of friends now knows how to do it. He spends a year developing a prototype product, he incorporates his company with the help of a well known VC fund, he hires a sales person and five programmers, and he's very very happy. By the way, he lives in San Francisco now, where he moved when he left her job and started working for his own company.

Saturday, July 05, 2014

Android programming: injecting a context using Robolectric and Roboguice

I have an Android project where I retrieve instances from a database. These classes are not under control of Roboguice, so I have no injection. If I use Roboguice.getInjector(..) I need a context, that I can supply from a static referenced context that I define elsewhere. However, I want to test the same classes in Robolectric, I need a different context.

I decided to do the following.
I create a ContextProvider like so:
public class ContextProvider {

    protected static Context context;

    public static Context getContext() {
        return context;
    }
}

I make a static reference to this in my app as
ContextProvider.getContext()
The implementation in my app is
public class ContextProviderImpl extends ContextProvider {

    @Inject
    public ContextProviderImpl(Context ctx) {
        context = ctx;
    }
}
and in my Robobuice modules file I have
    bind(ContextProvider.class).to(ContextProviderImpl.class);

In my Robolectric test project, the implementation is
public class TestContextProvider extends ContextProvider {

    public TestContextProvider() {
        context = Robolectric.application.getApplicationContext();
    }
}
and the modules file in the test project has
    bind(ContextProvider.class).to(TestContextProvider.class);
What happens is this:
In Roboguice you can implement a class (not interface) with another class that extends the first. The parent class provides the getter for the context instance, so it's the same in the project and the test project. The implementation sets the context field, in different ways in the project and the test project. I think this is an elegant way to have Roboguice injection in classes that can't have injection in the "normal" way.

There is another way of achieving this: you can use Guice AssistedInject to re-create the instance after you retrieve it from a database. That works, but it's more code and less elegant than this.

Tuesday, July 01, 2014

The art of not so good design

I have a waste basket, with a lid. Cost three euro's, so what can you say. Still, someone has spent some time to design the thing, and, hopefully, test the prototypes. Or not. The lid hangs from the middle, it's bent so its center of gravity is below the hinges and it automatically shuts. Unless you throw something in, then the lid goes past its balance point and stays open.

Dear waste basked designer, how hard is it to test a prototype of your waste basked by throwing in a piece of paper? How hard is it to keep looking at the lid until you notice it doesn't close by itself? How hard is it to change the shape by just half an inch to make sure it always closes?
You may say "how hard is it to bend over and close the lid yourself?". But it's not about that. Every morning I bend over and close the lid. The issue is that you designed it so I wouldn't have to close it myself, and you failed.

Rooting a Nexus 5 (2)

I had rooted my Nexus 5, but the Android update before last made it lose root. I tried to reroot, but I ran into trouble because fastboot didn't recognize my device and the sdcard was not readable when trying to install from that.

I tried again today, this site (as before) proved very helpful.
I installed clockwordmod recovery again, then installed Clockworkmod SU via adb sideload (recovery said sdcard could not be accessed so I couldn't install from there). I used "adb sideload" rather than push the zip to the sdcard. Now the device has root again. In the mean time the device had upgraded to Android 4.4.4 but I don't think that mattered....

Btw, it turns out you can root a device even if it's encrypted. Or, that's what I did.

Thursday, January 23, 2014

UI design

I have an interesting UI design issue. In a project in which we develop an Android app, we were discussing the behavior of the back button.

The app has tabs in the actionbar. The behavior of the back button currently is to leave the app, independent of the tab you have pressed. My idea on the back button is that it should take you back to the home tab, then when you press it again, you leave the app. If in one of the tabs you have pressed a button or a list item which brings you deeper into the app, the back behavior should be as follows: first press brings you to the default page of the tab you have selected, next press brings you to the default page in the home tab (or whichever tab is selected when you enter the app), third press makes you leave the app.

In another project, we had to different landing pages, depending on the preferences of the user. I made it so that the back button brings you back to the landing page that is in your preferences, or the landing page that you have selected when you entered the app. I feel that this is the most intuitive behavior of the back button, even if, as a developer said, the button is not stricly bringing you "back".

Wednesday, January 22, 2014

Rooting an encrypted Android device

I wanted to root my Nexus 7, so I installed the right image and zip. But then the device didn't work any more. I think it's because the device was encrypted, and somehow after rebooting, the thing got stuck. I managed to get the right factory images from Google (I didn't backup the system, which you should always do), my defice is "flo" which is "razor". After I got the device back to a factory installation, rooting the device with clockworkmod was easy. Now I'll encrypt it again.

Wednesday, December 18, 2013

How to make ormlite and robolectric work together.
I use Roboguice also, this is my RoboInjectedTestRunner:

public class RoboInjectedTestRunner extends RobolectricTestRunner {

 public RoboInjectedTestRunner(Class testClass)
   throws InitializationError {
  super(testClass);
 }

 @Override
 protected Class getTestLifecycleClass() {
  return TestLifeCycleWithInjection.class;
 }

 public static class TestLifeCycleWithInjection extends DefaultTestLifecycle {

  @Override
  public void prepareTest(Object test) {
   Application application = Robolectric.application;

   AbstractModule eftelingModule = new EftelingModule();
   AbstractModule testModule = new TestModule();

   RoboGuice.setBaseApplicationInjector(application,
     RoboGuice.DEFAULT_STAGE,
     RoboGuice.newDefaultRoboModule(application), eftelingModule, testModule);

   RoboGuice.getInjector(application).injectMembers(test);
  }

 }
}


If you don't use Roboguice, you can use the default RobolectricTestRunner instead.
This is the annotations I have for my test classes:
@RunWith(RobolectricTestRunner.class)
@Config( shadows = {ShadowCaseSensitiveSQLiteCursor.class})
@UsingDatabaseMap(SQLiteMap.class)
public class APITest {
...
}

This is the ShadowCaseSensitiveSQLiteCursor: (it's from here:http://stackoverflow.com/questions/11833150/robolectric-testing-with-ormlite so please give that post a credit)
/**
 * Simulates an Android Cursor object, by wrapping a JDBC ResultSet.
 */
@Implements(value = SQLiteCursor.class, inheritImplementationMethods = true)
public class ShadowCaseSensitiveSQLiteCursor extends ShadowSQLiteCursor {
  private ResultSet resultSet;

  public void __constructor__(SQLiteCursorDriver driver, String editTable, SQLiteQuery query) {
  }

  /**
   * Stores the column names so they are retrievable after the resultSet has closed
   */
  private void cacheColumnNames(ResultSet rs) {
    try {
      ResultSetMetaData metaData = rs.getMetaData();
      int columnCount = metaData.getColumnCount();
      columnNameArray = new String[columnCount];
      for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
        String cName = metaData.getColumnName(columnIndex);
        this.columnNames.put(cName, columnIndex - 1);
        this.columnNameArray[columnIndex - 1] = cName;
      }
    } catch (SQLException e) {
      throw new RuntimeException("SQL exception in cacheColumnNames", e);
    }
  }

  private Integer getColIndex(String columnName) {
    if (columnName == null) {
      return -1;
    }

    Integer i = this.columnNames.get(columnName.toLowerCase());
    if (i == null) return -1;
    return i;
  }

  @Implementation
  public int getColumnIndex(String columnName) {
    return getColIndex(columnName);
  }

  @Implementation
  public int getColumnIndexOrThrow(String columnName) {
    Integer columnIndex = getColIndex(columnName);
    if (columnIndex == -1) {
      throw new IllegalArgumentException("Column index does not exist");
    }
    return columnIndex;
  }

  public void checkPosition() {
    if (-1 == currentRowNumber || getCount() == currentRowNumber) {
      throw new IndexOutOfBoundsException(currentRowNumber + " " + getCount());
    }
  }

  @Implementation
  public void close() {
    if (resultSet == null) {
      return;
    }

    try {
      resultSet.close();
      resultSet = null;
      rows = null;
      currentRow = null;
    } catch (SQLException e) {
      throw new RuntimeException("SQL exception in close", e);
    }
  }

  @Implementation
  public boolean isClosed() {
    return (resultSet == null);
  }

  private Map fillRowValues(ResultSet rs) throws SQLException {
    Map row = new HashMap();
    for (String s : getColumnNames()) {
      row.put(s, rs.getObject(s));
    }
    return row;
  }

  private void fillRows(String sql, Connection connection) throws SQLException {
    //ResultSets in SQLite\Android are only TYPE_FORWARD_ONLY. Android caches results in the WindowedCursor to allow moveToPrevious() to function.
    //Robolectric will have to cache the results too. In the rows map.
    Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    ResultSet rs = statement.executeQuery(sql);
    int count = 0;
    if (rs.next()) {
      do {
        Map row = fillRowValues(rs);
        rows.put(count, row);
        count++;
      } while (rs.next());
    } else {
      rs.close();
    }

    rowCount = count;

  }

  public void setResultSet(ResultSet result, String sql) {
    this.resultSet = result;
    rowCount = 0;

    //Cache all rows.  Caching rows should be thought of as a simple replacement for ShadowCursorWindow
    if (resultSet != null) {
      cacheColumnNames(resultSet);
      try {
        fillRows(sql, result.getStatement().getConnection());
      } catch (SQLException e) {
        throw new RuntimeException("SQL exception in setResultSet", e);
      }
    }
  }
}

Sunday, December 08, 2013

My dad moved from Windows XP to Windows 8. Disaster. One thing Windows 8 doesn't seem to support is getting your old email (Outlook Express, from POP3) into your new mail program. Apparently, Windows users don't keep their email?

What I did to transfer his mail is the following.
I made a copy of the OutlookExpress mail file and put it on my computer. Evolution allows me to import it into a new mail box. Then I created an account on my dad's IMAP mail, and copied the mail from the import mailbox to his Inbox. Simple as that. Why can't Microsoft think of a way to keep your old email?

Saturday, November 02, 2013

The art of bad design

In the course of my life, I have used some ten different vacuum cleaners, if not more. We all use vacuum cleaners, and we all know what the common issues with vacuum cleaners are.
  1. The power cord.
    The cord of a vacuum cleaner tends to get tangled when you use it, and because it's longish, it gets tangled when you store the machine in a closet. That's why modern vacuum cleaners have a system that retracts the cord when you push a button or when you jerk the cord. This works fine on all vacuum cleaners. That is, it works fine when it's new. But lets consider your average three year old vacuum cleaner. My Dyson currently is two years old, and when I store it, the cord sticks out by about a foot. And this is ok, because in all other cleaners, it was worse. The cord retraction was tested with new cleaners. Apparently they don't test older machines.
  2. The wheels.
    A vacuum cleaner has two big wheels, and a small caster. This causes the device to follow your movements and not topple. The caster hops over the cord most of the time, it doesn't get stuck. As long as it's new. After a few years, or even after six months, the caster wears out, and it does get stuck when it hits the power cord. I've had a vacuum cleaner with a fine looking caster, made out of plastic, it looked like a half sphere with a little wheel sticking out. It stopped moving after half a year, and when I took it apart, every idiot could see that it couldn't have lasted long. It was badly designed and badly made. I replaced it with the cheapest and simplest caster from the hardware store, which outlasted the rest of the vacuum cleaner. Why didn't the manufacturer put in that caster? Is it because it would have added one euro to the price?
  3. The hose.
    When you walk around pulling the vacuum cleaner, you know that the device has a tendency of falling backwards when you pull it in the wrong direction. Which you do because you don't pay attention. Manufacturers come up with all kinds of solutions for this, and when you test your new vacuum cleaner, you're happy because it works perfectly well. But the connections between the hose and the device wear out quickly, or they get stuck because dust is collecting inside, so my two year old Dyson does topple when I make a wrong move. Which is stupid because if Mr Dyson would have spent an hour a week using an old vacuum cleaner, he'd know what the issues are and he could have started looking for proper solutions.
  4. The brush.
    I have cats. Cats drop mountains of hair in your home. Which you have to vacuum out. My vacuum cleaner, like all of them, has a brush with hairs on the edge and a whole that sucks in the middle. The cat hair gets sucked towards the brush, and it gets stuck between the floor and the brush, outside the brush, so it can't be sucked up into the machine. Every two minutes, I have to pause and remove the cat's hair from the brush. Mr Dyson apparently doesn't have cats. Or he would have made the brush inside out: it would have brushes that it rests on in the middle, and it would be sucking at the edges.
If I can think of that, why can't the average designer of vacuum cleaners? One thing I know. Vacuum cleaner designers don't do the vacuum cleaning at their place.

The art of bad design

I have a wastebin in my kitchen. It's a simple bin, mostly thin sheet metal, plastic inner bucket. The lid opens by a pedal at the bottom, so you don't have to touch it with your hands. It was rather cheap, though one of the most expensive ones the store had on display.
Now, someone has spent a couple of days designing the thing. They created a few prototypes, tested them, created some production models, tested them, then set off to mass produce them. Also, the designer probably designed wastebins of similar type before, and they obviously use one on a daily basis. You'd expect the bin to be perfect. But it's not.

First, the hinge that holds the lid protrudes a millimeter. When you lift the inner bucket from the bin, that millimeter is enough to make the bucket get stuck, you can't lift it out without wiggling and jerking it. Which, if the bin is full, causes content to fall out. There's no reason for the hinge to protrude. At the same cost, it could have been made so that it doesn't stick out. But they didn't.
The second issue is when you want to get the plastic bag out of the bucket. Most people use plastic bags in the wastebin, so they don't have to thoroughly clean the bin every time they empty it. The handle that you use to lift the bucket, is one millimeter smaller than the bucket itself. It sticks out to the inside. Which means that when you lift the bag out, the handle gets pulled up and you can't lift the bag. Again you have to use both hands and wiggle and jerk, causing garbage to spread over your kitchen floor. There's no reason why this handle should stick out to the inside. It's just a designer being thoughtless.

I'm surprised how a person who has experience designing wastebins and who uses one, and has used many in their life, can make such stupid and unnecessary mistakes. My theory is that they are not the person who does the kitchen work too often in their household, or they wouldn't have made these mistakes.

Thursday, September 19, 2013

The art of terrible design

I am not a chef. Not by profession, not by hobby. I don't like to cook, but I do like good food, so every day I make a proper dinner from fresh ingredients. I guess I am a "gourmet cook".

I have always used a natural gas stove, with four burners. That's the best, the gas has the right high temperature and it's easy and fast to adjust. Like, when you make hot chocolate, you heat the milk quickly, then you have half a second to switch if of when it boils.

After my last move, I got a Bosch electric plate. It's induction based, so it's hot, and it's quick to adjust. It has four stations, which most of the days is just enough for me. However, it has one major flaw.
The designer decided that the plate should be easy to clean, hence it has no protruding knobs, it has touch keys. Or rather, you don't just touch them, you have to press them, "+" for higher, "-" for lower. The buttons go from 0 to 9 in half steps, you push it 17 times for full heat. The designer also thought that a chef wants as little knobs or pushbuttons on the plate as possible. So, instead of having a plus and a minus button for each station, it has one plus and one minus, and a selection button with a light that indicates which station is currently "active". Now, imagine the little pan with milk for my hot chocolate. I put it on 9, I wait for it to boil. When it does, I push the station selector twice to select the milk pan, then I push the minus button 17 times to switch it off. Then I pour new milk in the pan and I clean the plate, because the boiling milk went all over the plate. Of course, after a while you find out there are shortcuts, instead of pressing 17 times, there's a way to switch it of in just a few steps. But including the selector, it's always five or six. And you shouldn't accidentally push the wrong button, or one button once too many, because that increases the total nummber of actions, and you do press the wrong button because you want to stop the milk from boiling over and the buttons are barely visible on the plate. The fastest way to switch off the milk pan is to switch off the plate alltogether. Then you have to switch it back on and switch back on the other stations.

My question is: why does a very expensive stove have such a lousy user interface? Why can't it just have four turning knobs? The answer is simple. The engineers and designers of the stove are not chefs. Or if they are, they have never used this stove, because if they had, they would have changed the user interface.
I propose the following add-on to my stove: a remote control with four turning knobs that let you adjust the stations fast, while maintaining the option of easy cleaning of the plate.

Tuesday, July 23, 2013

I was at a Demo conference in 2001, in Phoenix, AZ. Demo2001. I was selected to maybe do a pitch, which they called "the hot seat". Some fifty startup entrepreneurs were located in the front of the room, and every half hour they'd call two names, and when your name came up, spotlights were pointed at you, people with huge cameras would rush towards you and film you from two feet distance, just to make it scary, and while your face was on a big screen in the front, you got two minutes for a pitch. Now, you weren't sure your name would come up. The people who weren't called, were nervous throughout the conference, because they didn't announce when they'd call someone, it just came up suddenly. Nerve wracking, because the room was full with investors and other important people, I guess there were 1000 people in the room.
My name came up second, right after the key note. I got to relax and listen to the presentations, while most of my fellow hot seat entrepreneurs were still waiting for their name. It's always good to have your pitch or presentation right at the start. I was second, which is even better than first.
On the last day of the conference, I was ill. High fever, maybe because of the heat, I stayed in bed. At the end of the day I talked to one of the programmers who'd manned our booth, and he said "there was a lady asking for you today". I asked if he caught the name, and he said "yeah, her name was Ann Winblad". I never shout at people, but this time I did. "then why didn't you call for me? Why didn't you run to my room, bang on the door, and get me down there in the booth?" and some words I won't repeat here. The poor guy didn't know who Ann Winblad is. I sent her an email, called her office, to no avail.

The company didn't make it, in the end. Me talking to Ms Winblad might have made the difference.

Monday, July 08, 2013

off line?

My web site has been off line for a few days, due to a misconfiguration of the firewall that went unnoticed.

Saturday, June 15, 2013

Wednesday, November 07, 2012

DroidCon

On November 22nd, I will speak at DroidCon NL. The subject will be RoboGuice and Android development.

Wednesday, October 31, 2012

Friday, September 28, 2012