Many of us have been on a project where everything starts out great and the client remains happy for a few months until suddenly they change their mind and are no longer happy. This project was certainly the case.
However, there was quite a bit that we did right on the project.
The code was clean and well architected. We used a transformation layer in the code to allow the API payloads to be detached from the database. The styles and frontend code was architected in a way where we could use most of it for the website and Cordova app.
We used service classes and the repository pattern to allow for greater testability. Code was organized by component rather than by type so that it was easier and more intuitive to find a piece of code. Value Objects (sometimes called data transfer objects or DTOs) were created to allow the data to be typed. In addition, custom business logic was componentized or put into a class.
Likewise, connections with third party services were modularized so that they were more testable and easier to change at a future date. I wrote the integration with a major CRM and it was a daunting task since I had never done so before with this platform but I learned what I needed to know on the fly so that we were able to succeed.
Finally, we did a good job handling client communications and functioning as a team. We were always prompt in our replies to the client and we conversed with each other on how we might better serve them. The junior developer on the team was also given reasonable tasks to work on in addition to a one-on-one mentoring relationship.
That being said, everything wasn’t rosy. We messed up in a few areas.
First and foremost, we didn’t guide and control the client relationship as we should have. While a client should have say in what is built, as professionals it is our responsibility to advise the client and to help them maintain perspective. In this case, the client seemingly wanted to build Rome in a day. The requirements and vision would seemingly change every week.
They wanted to essentially build Facebook in a few months and on a small budget. All-in-all, this was our fault. We should have helped the client define a clear and obtainable objective that would get their product into the hands of users as soon as possible and push back if necessary to help them achieve their goals.
This is one of those cases where you realize that software development services are not completely detached from business development services - they go hand in hand. As the project lead, I can take some of the blame for this. I should have spoke up louder since I knew that essentially rewriting the code every week was not efficient nor was it going to get us to a profitable end. It was just wasting money.
Another problem was scope creep mid-sprint. While some things need to be and can be changed mid-sprint, there has to be an agreed upon limit to such changes. Developers can’t plan their coding activities based around proverbial shifting sand. They don’t need concrete requirements roadmapped ten years out but they do need to know that they can work on something for a few weeks without it changing.
But, all was not the project manager’s fault. I chose a few solutions that were too complicated early on and they ended up being discarded. For example, I used a closure table for user relations when I probably should have pushed back on the requirement and used a simpler method for the MVP.
Along with this, I decided to delay integration with Cordova and the third party CRM even though I knew better from having read the book Growing Object-Oriented Software, Guided by Tests.
So, there were definitely a few takeaways.
- Don’t try to build Rome in a day, it doesn’t work.
- Push back and raise a warning flag when requirements shift too frequently.
- YAGNI - don’t overcomplicate things prematurely.
- Integrate early and target ambiguity otherwise it will prolong a project.