I have to preface this with the note that I'm not a mechanical engineer. I know a little about the subject, but not a whole lot. If you are a real mechanical engineer, please leave comments on what I have wrong. Otherwise take my illustration with a grain of salt.
Figuring out what seams to test at is hard on a complex project. Testing the completed project is too expensive, but if you test less than the full product you risk that your tests don't reflect how the parts actually work together. Can we look to other fields for help? To answer this question I looked a little a mechanical engineering to see what they do.
Probably the best description for building complex mechanical systems is from Richard Feynman's appendex to the Challenger disaster
The usual way that such engines are designed (for military or civilian aircraft) may be called the component system, or bottom-up design. First it is necessary to thoroughly understand the properties and limitations of the materials to be used (for turbine blades, for example), and tests are begun in experimental rigs to determine those. With this knowledge larger component parts (such as bearings) are designed and tested individually. As deficiencies and design errors are noted they are corrected and verified with further testing. Since one tests only parts at a time these tests and modifications are not overly expensive. Finally one works up to the final design of the entire engine, to the necessary specifications. There is a good chance, by this time that the engine will generally succeed, or that any failures are easily isolated and analyzed because the failure modes, limitations of materials, etc., are so well understood. There is a very good chance that the modifications to the engine to get around the final difficulties are not very hard to make, for most of the serious problems have already been discovered and dealt with in the earlier, less expensive, stages of the process.
Probably the best description for building complex mechanical systems is from Richard Feynman's appendex to the Challenger disaster
The usual way that such engines are designed (for military or civilian aircraft) may be called the component system, or bottom-up design. First it is necessary to thoroughly understand the properties and limitations of the materials to be used (for turbine blades, for example), and tests are begun in experimental rigs to determine those. With this knowledge larger component parts (such as bearings) are designed and tested individually. As deficiencies and design errors are noted they are corrected and verified with further testing. Since one tests only parts at a time these tests and modifications are not overly expensive. Finally one works up to the final design of the entire engine, to the necessary specifications. There is a good chance, by this time that the engine will generally succeed, or that any failures are easily isolated and analyzed because the failure modes, limitations of materials, etc., are so well understood. There is a very good chance that the modifications to the engine to get around the final difficulties are not very hard to make, for most of the serious problems have already been discovered and dealt with in the earlier, less expensive, stages of the process.
There is of course more to design than can be expressed in one paragraph, but that gives us something to work with.
The first test mechanical engineering does is the properties of the material in question. In programming we start with standard libraries and algorithms and test them in isolation. We often test situations that cannot happen in the real world. We document the limitations. Unit tests do this very well. If you switch a turbine blade from zinc to aluminum, for the most part your same tests will pass, but some edge cases (max RPM before it explodes) will change, and we can predict with reasonable reliability what those changes are. Likewise when you switch from bubble sort to merge sort most things will work, but some edge cases (is the sort stable) will change.
One digression needs to be made here: mechanical engineering has margin factors. Material tests is generally for an ideal case of the material as formed in a laboratory. In the real world of manufacturing the same quality might not be obtainable - for example there might be "bubbles" or "cracks" in the real part. (for materials prone to this, that is part of the list of properties). Some of this is solved by inspecting parts in manufacturing, but some of it is solved by specifying parts that in theory can handle more stress than they will actually see. This margin is adjusted depending on needs, large expensive parts will in general have minimal factors, while parts that could kill someone will often be three times "stronger" than required just in case. I don't know of an analog for programing.
From there they create larger components, and assemble those components into larger and larger components. Programs are also made of components, which are then put together into larger and larger parts. In both cases you eventually arrive at a whole. So long as only minor changes are required there is no problem, as long as the parts fit together you can change the pieces inside without problem, just test that part and all the parts higher up.
The most important lesson is if your change to one part changes the way it connects with the next component, you also need to re-design that component to fit, which means a lot of parts need to be retested. Mechanical engineers have a concept of interchangeable parts. I upgraded the clutch on my car with one from a model 4 years older for a different engine: the upgrade just bolted right to my engine and transmission and so the change was fairly simple even through large parts of my car had been re-designed.
In programming we have figured out how to substitute simple algorithms like sort and a few containers. However we don't yet have a concept of how to substitute larger pieces in general. There are plug in architectures, but they are plug in only at a few levels. You can run many different programs, but the programs themselves are generally either monolithic, or only allow a few areas of change. We can trade out device drivers, and a few other areas, but those tend to be places where our program touches something external. What is your "clutch" that is a part of your program, yet can be traded out? I'm not sure if this is actually a valid question though: my son's toys generally have one changeable part: the battery. Maybe most software only has a few plug ins because changing plug-ins is not useful for most software.
Lets go back to Richard Feynman's description. I have a problem with his approach. He says you start with a turbine blade, but why are we using a turbine in the first place? Those model rockets I made as a kid didn't have one. Of course my model rocket used a different fuel source, but that is the point, before you can decide you need turbine at all you need to know what fuel you will use, and that is top down design not bottom up. You need to know a lot of your design before hand: a turbine that won't fit is a design disaster even if it works well in isolation. This is exactly the same problem I'm facing in programing: eventually in a large system you will design two components that don't quite fit together right, and fixing it means you have to do major work to one or both parts.
The most important lesson is if your change to one part changes the way it connects with the next component, you also need to re-design that component to fit, which means a lot of parts need to be retested. Mechanical engineers have a concept of interchangeable parts. I upgraded the clutch on my car with one from a model 4 years older for a different engine: the upgrade just bolted right to my engine and transmission and so the change was fairly simple even through large parts of my car had been re-designed.
In programming we have figured out how to substitute simple algorithms like sort and a few containers. However we don't yet have a concept of how to substitute larger pieces in general. There are plug in architectures, but they are plug in only at a few levels. You can run many different programs, but the programs themselves are generally either monolithic, or only allow a few areas of change. We can trade out device drivers, and a few other areas, but those tend to be places where our program touches something external. What is your "clutch" that is a part of your program, yet can be traded out? I'm not sure if this is actually a valid question though: my son's toys generally have one changeable part: the battery. Maybe most software only has a few plug ins because changing plug-ins is not useful for most software.
Lets go back to Richard Feynman's description. I have a problem with his approach. He says you start with a turbine blade, but why are we using a turbine in the first place? Those model rockets I made as a kid didn't have one. Of course my model rocket used a different fuel source, but that is the point, before you can decide you need turbine at all you need to know what fuel you will use, and that is top down design not bottom up. You need to know a lot of your design before hand: a turbine that won't fit is a design disaster even if it works well in isolation. This is exactly the same problem I'm facing in programing: eventually in a large system you will design two components that don't quite fit together right, and fixing it means you have to do major work to one or both parts.
No comments:
Post a Comment