Freelancing big projects - 9 key takeaways from my failure that you can learn from
I love creating. Whether it’s a nicely cooked dinner for friends or a design for my next “I’m gonna change the world” project. Fortunately, I've been given a chance by various clients to freelance as a designer and a developer, through which I've gained invaluable lessons about people, entrepreneurship and (software) development. I also have a day-job as a software engineer where I get to craft my full-stack skills.
As a freelancer, I've created over 30+ Wordpress websites/e-commerce solutions(both as a designer and developer), which should result in a good understanding of how freelancing works.
My latest and thus far, biggest project, was like a final exam of all my previous endeavours. It was a custom Mongo-Express-Vue project with a separate management system and an authentication-based web app. Something really different from what I had freelanced before.
9 months after agreeing to work on the project, the exam can be said to be failed. I wasn't able to deliver the promised solution. Thinking back about what happened, I've come up with 9 key points that I (and maybe you too) can learn from in order to become a better freelancer.
1. Excitement is great but do not let it blind you
When I first met my clients(there were 3 of them) and heard about their idea, I was excited. Not only did it seem like a product I would use myself but there were also engineering-related challenges, as it was not just a simple "design-to-code template" project.
They gave me a list of features, everything seemed doable. I took time to think, suggested to drop some features and finally we agreed on the price. The programmer in me was truly happy.
After 2 weeks of heavy coding, the management system for the project was ready. Communication with the main shareholder for it was great and I got to use component libraries on the FE side, meaning things moved fast.
Then came the other part, a public-faced web app. After some coding of the backend, I started to receive the UX designs. That's when I understood I had no idea of how complex the FE side is going to be. Also, only when things were designed, we started to have discussions on how the features should actually behave. The programmer in me wasn't that happy anymore.
2. Have a list of prerequisites that must be fulfilled before making decisions
A mistake I made was excluding the project-manager side of me and let the coder take over. I decided to completely ignore my previous experiences and just started working on the project. Things that should've been done before coding include:
- going through each feature and making sure all parties understand them the same way
- asking for the designs beforehand
- making sure the designs are checked by every stakeholder
- letting each feature have one stakeholder
- not give a fixed price before all the aforementioned prerequisites are filled
Had I controlled my excitement and checked that all the prerequisites were fulfilled, many of the future problems could've been avoided.
Then again, it's understandable big projects can't have everything planned out. The designs and features can change based on previous developments.
3. Instead of promising to deliver a huge single project, work in small meaningful chunks
All the aforementioned mistakes would've been more-or-less okay if I had not made yet another mistake. I agreed to deliver all the features in a single project.
The thing with freelancing big projects is that I nor the client are able to test everything. Also, when bugs occur and they're found during later phases of the project, fixing them becomes harder.
Instead, one could split the project into small, meaningful pieces. In my case, the back-office could've been one piece. Another piece could've been the landing page, then the signup system etc.
This approach has many benefits - testing becomes easier, the client can see the progress and also, you stay motivated because you actually deliver. Oh, and you can also bill them after each chunk.
4. Charge the client in small chunks, feature after feature.
As the development continued, we had to make changes to features, rethink some UI etc. It was a result of miscommunication and not going into details thoroughly enough.
Unfortunately(for me) we had agreed on a fixed price. Based on my previous experiences, it's a good solution if there are no unknowns. In hindsight, that wasn't the case here.
At some point, the project had taken 3-4x more time I had initially predicted. That's when I found myself telling things like "it's not just about money, it's about experience", which to some extent is true.
This situation could've been avoided by using feature-based billing. It means that after each meaningful feature development, you bill the client. This way you can make better predictions regarding the price, get awarded more often and stay more motivated.
5. You'll need more than self-motivation and “I’ll do it for the sake of learning".
James Clear, the author of Atomic Habits, has said: "You do not rise to the level of your goals. You fall to the level of your systems"
At the beginning of the project, I was motivated to deliver. The first part of the project, the back-office, was done in a couple of weeks. Mostly because the goals were clear and it was full of interesting problems(how to structure the system, how DBs schemas should look like etc).
The second part of the project, the public-facing solution, went slowly. Not only did it have a custom design, but also features that we hadn't discussed thoroughly enough. This meant constant communication and discussion of how and what to do. The "I have a clear goal" and "interesting engineering problems" were replaced with meetings and constant changes to the system. I wasn't just a developer at that point, I was also a partner, project manager and maybe even a product manager.
At some point, I lost my motivation to do things properly and let the code quality suffer.
6. Don't fix but solve problems
There are many awesome coding practices like DRY and KISS, which I try to follow(here I'd recommend The Clean Code - a must-read for developers). After losing motivation, I started to look for easier solutions. Things like "I can hack it together and later see if it's needed" started to occur.
A couple of weeks later, when I finally thought we're getting somewhere with the project, one of the clients said that some calculations don't add up. Apparently we had misunderstood each other when creating the calculations. Confident that it's an easy fix, I actually found myself swimming in the spaghetti I had created during the past weeks. After hours and hours of debugging, I wasn't able to fix the problem because of new bugs we hadn't noticed before emerged...And now I was done.
7. Communicate
There are multiple reasons why I wasn't able to deliver the project, one of the prominent ones being poor communication.
There were times I had developed a feature but didn't communicate it. There were also times I let the clients know but didn't tell them to test it. It was my assumption they did, only to find out some fundamental flaws in the end.
The solution here is processes. To keep up the communication, establish a (bi)weekly meeting, where things could be tested, discussed and improved. Use some simple project-management tool like Trello or Asana where work can be managed. This way you are constantly in contact with the shareholders and can be sure that flaws are spotted in a quick manner.
Anyways, regarding communication, I did the only thing I could...
8. Be honest, don't BS
...I gathered my ideas, emotions and told the clients that things are quite bad - the codebase is a mess, I'm not able to fix it properly without a rewrite and that my motivation is gone.
They thanked me but also requested some time to think about the situation.
9. If stuck, look for help, consult. Fresh eyes can always help.
Haunted by my feeling of failure and not knowing what the clients will decide, I took it into my hands to rewrite the backend.
Instead of diving into the code straight away, I contacted my colleagues from daily job to discuss architectural decisions.
The result - I rewrote the part I had spent 3 months on in one weekend. And it was faster, cleaner, better. I was able to reuse some parts of the older code which made things easier, but the idea persists.
The combination of now knowing what the client wanted but also discussing technical aspects with others sped up my work. Plus, I had a huge motivation boost from the need to prove my clients (and myself) that I can do it.
-
2 days later, I had a conversation with the clients. They decided it had been a great learning experience for both of us, but couldn't continue working with me. Looking from their point of view, it can be understood. It wasn't just a developer they had hoped to hire. It was also a project manager and a partner. Unfortunately, I lacked both experience and wisdom.
In the end, I had mixed feelings - disappointed, but also happy to have gained the experience. Hopefully, I'm gonna learn from this project and who knows, maybe even implement the knowledge in future projects.
Conclusion
My main message is that by freelancing, you're not only a developer. You're also an entrepreneur, project manager, partner. You are someone, who's been trusted to solve a problem. Before taking on a new project, invest some time into coming up with not only technical but also managerial solutions.