The field of software engineering is slowly maturing. Methods are developed that, when used, provide software that can last for many years without falling apart. Methods like the “open-closed principle” convey wisdom that people have developed over time.
There is just one problem: Your software is worthless after the migration
What you have to realize is that the value of the migration software is not identical to normal software. Roughly speaking the value of the migration software is close to zero once you have done the migration effort. No one will ever open your code and read it to try and change it to conform to new requirements.
This has profound implications on the way you should design your software. The lessons other people learned have little value in the scenario you are facing. You absolutely have to reflect on the consequences of that, when designing and building your solution.
You can compare migration projects with one-off queries against your database. You just need to get the result and then the code will be forever forgotten. If you were a coder during the DotCom bubble you can probably remember the sentiment. Whatever you were coding was obsolete within a month of being online, so the practices of good software development went out the window. Nobody cared if your code was a mess since version-next of the webpage started over from a blank slate.
I am NOT saying that you should code poorly or that you can put any script kiddie to work doing migration software. I am arguing that using the same practices and the coding style that you use doing normal client-server software will be bad. You should adapt you coding style to fit the problem at hand.
I love the book “Code Complete 2” by Steve McConnell. He has a chapter about the characteristics of software. I have borrowed his terminology in the following section. Lets go through each characteristic to see what they are and which characteristic matters the most when doing migration projects.
The observable external characteristics are:
- Correctness The degree to which a system is free from faults in its specification, design, and implementation.
- Usability The ease with which users can learn and use a system.
- Efficiency Minimal use of system resources, including memory and execution time
- Reliability The ability of a system to perform its required functions under stated conditions whenever required—having a long mean time between failures.
- Integrity The degree to which a system prevents unauthorized or improper access to its programs and its data. The idea of integrity includes restricting unauthorized user accesses as well as ensuring that data is accessed properly— that is, that tables with parallel data are modified in parallel, that date fields contain only valid dates, and so on.
- Adaptability The extent to which a system can be used, without modification, in applications or environments other than those for which it was specifically designed.
- Accuracy The degree to which a system, as built, is free from error, especially with respect to quantitative outputs. Accuracy differs from correctness; it is a determination of how well a system does the job it’s built for rather than whether it was built correctly.
- Robustness The degree to which a system continues to function in the presence of invalid inputs or stressful environmental conditions.
The internal (only observable by a programmer) are:
- Maintainability The ease with which you can modify a software system to change or add capabilities, improve performance, or correct defects.
- Flexibility The extent to which you can modify a system for uses or environments other than those for which it was specifically designed.
- Portability The ease with which you can modify a system to operate in an environment different from that for which it was specifically designed.
- Reusability The extent to which and the ease with which you can use parts of a system in other systems.
- Readability The ease with which you can read and understand the source code of a system, especially at the detailed-statement level.
- Testability The degree to which you can unit-test and system-test a system; the degree to which you can verify that the system meets its requirements.
- Understandability The ease with which you can comprehend a system at both the system-organizational and detailed-statement levels. Understandability has to do with the coherence of the system at a more general level than readability does.
Correctness | This also holds true for migration software. That being said, the real problem of migration is not to code what is specified, but specify what solves the problem. This means that the property Accuracy is what you should aim for. |
Usability | It does not matter. Only you and a few other people are ever going to use this software. No need to go overboard trying to create a fancy GUI |
Efficiency | You need to be able to run the migration in 12 hours. Perhaps this will make this characteristic a focus point, perhaps not. It depends upon the amount of data and the complexity of the migration. |
Reliability | You will definitely need your migration software to be reliable and deterministic. Having defects that only shows up sometimes is a nightmare scenario. |
Integrity | This also holds true for migration software, but rarely has an effect on the project. Migration projects should aim for a simple security and access model |
Adaptability | Your migrations application will be needed mostly to migrate the data, but since you will want to be able to prioritize testability the application needs to have high flexibility to support various test scenarios. |
Accuracy | Probably the most important characteristic. The program needs to get the job done. When validating your migration always have in mind that the job is not to verify that the code works as specified, but to expose where the specification is wrong. |
Robustness | This characteristic is in some cases actually harmful for the software. You will want to embrace a culture of “fail hard if anything looks suspicious” culture. With regards to environments, you have full control, so planning and coding to support what-if scenarios is a waste of time. |
Maintainability | You may never need to maintain the application after it has been running, but there is a fairly long period of time before the migration occurs when you have to change the code rapidly. So while it may seem counter intuitive it is actually important that you are able to make changes in the code without fear of breaking something else in the code. Very late in the project, you can begin to make shortcuts and do copy-paste programming, but start too soon and you will find it a nightmare to implement the changes that are needed before launch. |
Flexibility | No, don’t bother. You have complete control of the environment, so you will be able to fit the environment to the software not the other way around. |
Portability | No, don’t bother. |
Reusability | It is very unlikely that you can make a generic component that you can use in other projects. Only if you know you have a series of migrations coming up will this be relevant. |
Readability | Nobody will need to look at your code 10 years from now, so readability (and documentation) might not seem paramount. That being said the characteristic is linked to maintainability which is highly desired, so by implication you should strive to write a program that you will understand 3-5 month down the road without spending undue amounts of time. Another reason to write readable code is that a typical statement in migration software is altered more often that in normal programs. This is due to the volatile requirements that cascade down to the code level to create volatile code. All things considered, this makes readability one of the most important factors to consider when coding. |
Testability | Perhaps the most important characteristic in migration software. Your chief aim should be to make the migration as open and transparent as possible. Testing migration software is very technical in nature and requires a high skillset from the testers. You as a developer will be heavily involved in that test assisting the test manager with his effort to prove that the software works. |
Understandability | You will probably not need to onboard many developers on this project, so having a complex design will not greatly affect the project.
Small projects with a single developer might not have the same luxury of ignoring this property since you will need to guard against the risk of him/her leaving before completion. Again understandability is linked to maintainability, so you will probably do fine in this metric if you keep focus on maintainability. |