Software design in scientific computing
Posted: 10 May 2016 | 00:07
Useful software design
Prompted by a recent discussion of a blog post discussing applying commercial development techniques to academic software development, I've been trying to formalise the software design process I'd recommend to academic software developers.
Just the term, software design, puts a lot of people off. It sounds like a long, elaborate process, full of requirements capture and storyboards, but it really doesn't have to be. I think anyone who is writing programs will be doing some form of software design, even if that design is just following the process they've always used, but are just not formalising it. However, formalising your software design could bring important benefits.
For me minimal software design should involve writing a very short document that contains the following:
- What is the purpose of the program?
- What data will it consume and produce?
- How can you validate correctness?
- Who do you expect the users to be?
- What parts of the program could you imagine replacing in the future (ie for performance or functionality reasons, for instance moving from 2D to 3D simulations, using a different solver, etc...)?
- Are you going to use existing code or libraries to implement all or part of the program (what are your dependencies)?
It could just be a sentence for each of the above, especially if you are writing a very small program, but you could also expand on these and write a page or two, with some pictures to help out if needed.
As with any tool to improve software development, the key to using something like this is tailoring; using the parts that are useful, adding to it as required, and ignoring the bits that don't apply. The purpose of the questions above are simply to encourage thought before coding starts, hopefully prompting sensible decisions on how the program is written based on the answers. They can also be used to evaluate the program later on, in code reviews or when releases happen; you'll have a document to reference that outlines key information about the program.
One of the key design areas for software, which often is not properly considered and can have a big impact on applications later in the development process, is the changeability of a program. If there are areas in the program that it is likely you will want to change in the future, for performance or functionality reasons, then if you can cleanly encapsulate them in the program it will enable easy changes in the future (thinking data layout or solvers).
Likewise, understanding the likely user base, and I/O, of the program will let you take sensible decisions on how to structure your program and the level of testing needed (will you need GUIs, do you need multiple data formats for input and output, are you going to need documentation and error checking of inputs, etc...).
Finally, understanding and documenting your validation cases/information (how you can confirm correctness once you have a working program) will help anyone else developing the program in the future; and thinking about what parts of the program can be implemented using code you've developed before, or that's already available, will give you chance to have a look around for code you can re-use, potentially saving time in your development.
Really there's also a seventh question along the lines of "What design pattern will this program follow?". But I've not included it as I know this would be a software engineering step too far for a lot of developers. I instinctively don't like design patterns as it always feels like trying to shoehorn a program into a specific model rather than allowing programming freedom. However, in reality we all follow design patterns, even if it's just the same pattern you always use (functional decomposition, for example).
The only reason to include such a question would be to get people thinking about how they structure programs, and whether this program will be similar to programs they have written before or will require a new approach (and therefore probably more testing, comments, documentation,etc...). If you use this type of design approach for all the programs you write then it will not take long to build up your own set of design patterns which you can utilise in future designs.
Lastly, the real strength of adding a small amount of software design to your development process is not just in helping to ensure that the program is sensibly structured from the start, allowing easy modification and maintenance where most required, but also it allows evaluation of your programs once development has progressed. The software design gives an initial set of specifications that the program can be evaluated against, it can be used in code reviews and other assessment processes, to work out whether the approach taken to writing the program worked and was (relatively) efficient.
It allows evaluation of the program over time so that maintenance and continued development costs can be assessed against the development module or design pattern used, and can let you learn from the good and bad points of the program for future development work.
I can imagine that, again, this is a step too far for many developers who aren't even undertaking regular code reviews, let alone evaluating software against a design over time. However, if you are to learn from your mistakes and improve your development skills over time some form of evaluation of the code you write is essential, and if you have an initial design this can be very useful in the evaluation.
I'm not claiming that the process I've outlined is perfect and I've probably left some important stuff out, but it's a process I try to follow when developing. If you have any suggestions for improvements/changes do get in touch because I'd be keen for some feedback. Would this work for you? Would you use it? Or can you not see the benefits?
You can also read this post on our Medium account.