⌚️ Project Timeline
Execution is more important than the idea.
This note is about software development projects: what are the basic steps, what should be planned, how projects usually advance etc.
Before you can start the project, you usually need a team. Get developers involved in the project early on. They should be able to start thinking ways to start solving the problem.
Project time-line:
- Problem-definition
- Requirements
- Planning the Architecture
- Planning the Design
- Construction
- (Quality Assurance)
- (Maintenance)
Parts 1, 2 and 3 should take about 25% of project time and resources.
1. Problem-definition
People always want more choices but are always happier with less.
Solutions are for fixing problems. Problem-definition is for making sure that the software being planned is a valid solution for the problem. If a problem is not completely understood, it is best to provide no solution at all.
List all problems that you need to solve. What customers want is different what they need. When user specifies highly complex problems, ask a lot of whys to get the real problems you should be solving.
You want a bridge? That is a solution, not a need. You need to cross the bridge? Good, that is a need we can work on. How many people are crossing, one, two or hundred? How frequently are those people going to cross it, daily or once a year? Rowboat can be better solution.
Everyone can recognize and reject bad ideas. They are the "good ideas" that slip through, causing additional complexity and wasted effort for something close to useless. Ask yourself, do we really need this feature?
Research who will be the end users. You should have three groups of users: primary, secondary and other. Primary users must have all of their need filled. Secondary users will have a portion of their needs filled. Other users are ignore on purpose.
Problems should be defined from user's point of view. You should speak in user's language. This way the problems can be discussed with the user.
2. Requirements
Working on the wrong thing for a month is equivalent to not showing up to work for a month.
Requirements describe what the software is supposed to do. Requirements also state directly or indirectly what the software is not supposed to do so you do not end up creating unnecessarily complex system.
Requirements help developers to do their job. Even individual developers should think about the business value of the solution while building the software.
Requirements should not change during development. Make sure everyone understands that changing requirements wastes time and money.
Boss gives you feature X1. You start developing feature X1. Later it gets changed to X2 for legal reasons. Later it gets changed to X3 because customer asks so.
Requirements should be written. Written requirements help keeping the project scope focused. Requirements can contain input data, output formats, required external hardware, software interfaces, communication protocols, expected response time, level of security, when must it be ready and all tasks user wants to perform are specified in some detail.
3. Planning the Architecture
Architecture comes after the formal requirements. Now you know what goes in and what comes out of the system.
You must go through all major architectural decisions and give at least few statements about each of the following points:
- Programming Languages: you should use the highest level mature programming language that makes it possible to fulfill the requirements. Go to lower level only if you need optimization. E.g. use Ruby, PHP, Clojure and Python over C++.
- Logical Organization: define what major parts of the program will do e.g. class structure overview in object-oriented programming. How are responsibilities being divided so that the system stays robust? Should allow breaking the software down to so small pieces that it is easy to replace.
- Business Rules: define how all core business rules are being implemented and define who to create basic business logic layer that can easily be extended e.g. "customer info cannot be older than 30 seconds".
- Data Design: what data is saved, where and in what format e.g. dates and time are always transferred in ISO 8601 and saved in database as native timestamps.
- User Interface Design: sketches of major elements of software layout.
- Testing Culture: decide what parts of the system should be tested. You should extend testing starting as close from the data as you can, meaning you should first implement unit testing, then integration testing. I suggest at least using unit tests.
You should go through some minor architectural decisions and at least think how you will handle the following points:
- Resource Management: available database connections, threads and handles.
- Security: design-level and code-level guidelines how to handle security.
- Performance: architects opinion how to reach performance goals. Usually best is to ignore performance totally when constructing and optimize only when there is a need for it.
- Scalability: how many users can system support in short time range.
- Interoperability: is the system supposed to share data or resources with other systems.
- Localization: is localization planned and how will it be done.
- Error Processing: how are errors being handled? Should code throw exceptions at what point? Should exceptions be fixed when caught?
You must go through all architecture related construction details so software developers can maximize their potential:
- Code Organization: How will the files be organized? There must be consistency so developers can effectively work with the code.
- Coding Guidelines: Define guidelines how to write code e.g. how should variables and functions be named?
- Buy-vs-Build Decisions: Are developers allowed to use third-party libraries or should they build their own? Is there any budget for buying libraries?
- Over Engineering: Specify over engineering scope. Usually best is to state that if no changes are being planned, construct everything in the most simple way.
- Reuse Plan: reuse what parts of your existing code?
4. Planning the Design
Software design is splitting the system to smaller pieces. Separate program to modules e.g. business rules, hardware, input, output, language, database connection, testing.
Prefer consistency. All parts of the system should have a familiar feeling.
Design documentation should be available to all developers. Design documents should not contains any implementation details.
Prefer composite classes over multi-inheritance for grouping behaviour. Use inheritance if you really have multiple versions of same behavior that should be kept separate. But you should go through all common design patterns that are available.
One person can do the major design. But there are few situations where design should be at least reviewed by other person e.g. inexperienced person in this problem domain, mission-critical part or security-critical part.
5. Construction
You should start each software project by creating following
- Implement debug mode Can be enabled even on runtime and should be disabled on production by default.
- Implement debug printing Works only in debug mode. This is valuable for creating the software.
- Implement logging. This is valuable for fixing errors that happen in production.
- Setup testing framework and test these few functions. The sooner you start writing testing code, the better.