richiejp logo

Three ways to help your project fail

Intro

It’s said that failures provide more information than successes. If you know what doesn’t work then you can focus on what might work. If something succeeds, maybe you got lucky; perhaps you didn’t test the limits.

When something does fail, it is sometimes clear why. Especially when you spot a potential failure and structure things as an experiment. It’s fine and necessary to fail. What isn’t, is to fail in a costly manner. Where you test things in the wrong order or don’t know what to blame. Where you spend a long time building supporting structures for a baseless undertaking.

So here is a list of ways in which I have ruined projects. Not just ruined them in the sense that they ultimately failed, but also in that I made them costly. I did learn from them, a lot, however the time expenditure to payoff ratio is not as good as it could be.

Doing the things listed here will take you away from fulfilling the basic premise of a project. Indeed it will set testing the project’s core assumptions further down the road. Also when the project eventually fails, it will be difficult to untangle the root causes.

Additionally I have suggested some mitigations or what to do instead. These I am less confident about than what not to do. It has to be said that knowing what to do in the abstract is only 1% of the battle.

For example, it’s all very well and good to know that presenting your work at a conference is a good way to get users or feedback. In fact you don’t even need to know its a good idea. The cost of trying it is relatively small, so you can merely try it… right?

Usually the things you should be trying or avoiding are obvious. The problem is making yourself do them or not. The true battle is “selfovercoming” as Nietzsche put it. That said, it sometimes helps to have a map of the terrain, even if some important details are missing. Also there is maybe, just maybe, the possibility someone will find this article entertaining and share it. Thus bringing more traffic to my website.

It amuses me quite a lot that web3 and block-chain fall foul of all of these if you discount gamblers as real end users. If you look at Ethereum; they invented their own language and VM (Solana did better here, but only slightly). The underlying technology is new to begin with. They don’t ask the little people if they want their private details storing on a block chain forever, where they have to pay to add to them. As for whether block-chain is an over abstracted, over generalised, utopian vision that is essentially quixotical. Well, time will tell.

Of course a block-chain or an element of block-chain could still be successful. Often the biggest discoveries are made when someone breaks the rules. Does all the things that shouldn’t work and still succeeds. These make interesting and heroic stories. However one has to look past these and look at how similar attempts faired.

Neomania

1. Combine multiple new things at once

Implement a novel idea in a new language, with a new database, using new protocols and methodologies (for example). Combine things that have never been used together before. Doing all the work yourself to fix any issues that arise.

Ignore the lack of a track record by the creators of multiple components you rely on. Ignore the lack of scrutiny these technologies have come under or the fact most of the users are enthusiasts and True Believers.

Try to sell a new language and ecosystem to existing associates. In addition to selling them on the basic premise of your project. Which is also a new concept for them to digest.

Mitigations

At the outset, if possible, use tried and tested components that are known to work together. If there is a strong reason to use something new, try to make it a single component. Then experiment with new tech by swapping out components one at a time. Keeping most of the things the same.

Sometimes new components come as a package and work better together. If this is the case then try to stick to what the largest number of other people are doing. Usually this is not the case though, new projects try to be compatible with the largest existing code bases. As you should.

The cost of not using something new can also be very high in theory. It’s just hidden until years down the line. So while it is an option to ignore new stuff, you probably don’t want to do that either. It’s often less costly to spend time trying things both ways and comparing.

However if something is constantly changing in a way that breaks backwards compatibility. Then a comparison at a single point in time may not be a fair one. If a component introduces breaking changes on a regular basis, this may outweigh the advantages of using it.

I suspect that it is perhaps easier to find new associates than to convince old ones to learn new things. It makes sense to find people for whom only one or two aspects of your project are new to them.

Antisocial

2. Avoid talking to people

Focus on documentation and 1-to-n communication. Don’t partake in general discussions in whatever communities your project is related to. Don’t ask other people for advice on the best way to do something. Remain aloof and unapproachable. Avoid any display of weakness or ignorance.

If you do ask for feedback, then make it very specific. If people comment on things outside the scope of what you requested. Then ignore it and say you are not interested in that.

Meanwhile consume large amounts of 1-to-n communication yourself. Don’t engage with the authors directly and risk exposing a treasured opinion to public scrutiny.

Mitigations

Before writing any code, ask around if anyone would be interested. Whether someone is already working on it. Whether there is a way to cut out the problem entirely without writing code. If you think you know the answer already, put it out there for people to refute.

Ask for advice on what components and methods to use. People love to be asked for advice. They don’t like being asked to do actual work. However people enjoy giving advice so much that it often comes unsolicited.

Find some communities related to your project and take part in the general discussion. Avoid reading articles and discussions you’re not likely to respond to. Most of what is discussed is noise when viewed passively. Only as an active participant does it become a medium for building lasting bonds.

Only write minimal documentation and instead make yourself available for discussion. You don’t want to spend time writing and maintaining documentation no one reads or understands. Your idea of how to explain things may be way off. It’s obvious in an interactive discussion if people don’t get what you are trying to say. Not so, if someone reads some documentation then disappears into the ether.

Quixotic

3. Future-proof, abstract and generalise

Spend time and effort designing and writing code for a future that may never come. Try to generalise, decouple and abstract every little detail. Split up and compartmentalise all of the functionality, before you have implemented most of it.

Pick an abstract utopian model of how an application should look and try to stick to it. Regardless of if it makes the initial implementation far more difficult. Stick to your ideals at all costs. Especially if those ideals are lifted from a handful of unusual projects or companies. Top marks if you read about them in a blog or by a non-founding employee. Bonus points if they are more of a journalist than a software developer.

Design for your application to scale in all directions. To scale in users, to scale in complexity, to scale in contributors, to scale in robustness. You especially want it to be decentralised across multiple dimensions.

Mitigations

Do the simplest thing that works first and by “works”, I mean works in enough of a capacity to prove the concept. Satisfying the underlying purpose of the software is of primary importance.

I’ve never seen a project fail because it didn’t use a distributed thingy that can scale to infinity from the outset. Not even using Perl and a single DB instance seems to result in failure. Scaling issues can be solved by profiling and fixing shoddy code for the most part.

Often it’s only really one aspect of an application which needs to scale into the realm where structural changes are required. So a distributed thingy or a bit of code written in C (or equivalent) can be brought in to deal with that. If one constantly simplifies their application and rewrites shoddy code, farming bits out is not all that difficult.

Of course things are not constantly simplified, so this is often a very painful process. Where code has to be disentangled and pulled out at the same time as being cleaned up. However this still doesn’t cause projects to fail if their basis is sound and alternatives are not obvious. That’s why there is so much “bad” code around.

Ironically, the easiest thing to change later is usually the simplest. Often introducing abstractions and decoupling things, introduces complications. Abstractions are rarely free (even if there is no runtime cost), so you have to be conscious of the cost to benefit ratio.

Sometimes abstractions and fancy scalable solutions are as easy to use as anything else. They are default way of doing things. In this case you should obviously use them, why not? However when in doubt I think it’s best to assume they aren’t.

Sometimes an abstraction or generalisation actually helps to understand the core problem. I often find this better to do on paper however and still only write code for a specific case. It’s easy to change a model. Code on the other hand has to compile and run correctly.