What has been your experience fully specifying multiple packages before implementing the bodies, either in full Ada or with SPARK?
I’m thinking of giving it a try for my current project if it gives good results.
What has been your experience fully specifying multiple packages before implementing the bodies, either in full Ada or with SPARK?
I’m thinking of giving it a try for my current project if it gives good results.
I’ve found it useful to have multiple package specs defined first and write example programs that utilize some of them. This usually helps to identify details or interactions I didn’t realize at first which lead me to make adjustments. This is why I really like Ada’s emphasis on separation of specification and implementation, which helps to discourage the author from getting too caught up in implementation details too early only to find out in the middle that something has to be reworked.
I am personally a big fan of “top-down design” which is pretty close to what you are suggesting. There might be a bit less re-use using a top-down development process, though that can typically be ameliorated a bit during the lower-level implementation phase. In my experience, the net result of a top-down design is a significantly better overall architecture, and in some cases, that results in more reusable components when you are done.
I would definitely agree with writing as many example programs as you can before locking down an API, because that is really the best way to validate the architecture and usefulness of the set of package specs.
I have found it really useful in multiple projects. I did find myself struggling with how to do it when I first started and I would often fall into habits of trying to implement things too early, but once I got used to it, I really liked how the design stage felt, and I felt my designs had much better architecture and were easier to document. I’m saying it is the silver bullet for everyone, but for me it feels really good.
From my own experience I just found it to be a different type of reuse. Going top down on my designs allowed me reuse entire systems, only changing a few implementations at the low level while the rest of the code just worked. For the projects doing bottom up, I ended up with components that I could reuse in multiple different types of projects but I had to design the business logic from scratch in most cases.
This is pretty much the only way to engineer software. I generally use an edges-in approach, which results in both low-level reusable packages (for hardware interfacing, for example) and high-level package specifications representing problem-space entities. One then repeats the process to implement the bodies of those high-level packages, and the bodies of the packages resulting from implementing those bodies, and so on, until things get low-level enough to be easily implemented correctly.