While more established engineering disciplines, such and civil and electrical/electronic engineering, has had a couple of centuries to grow, fail, improve and stabilize – software engineering has only been around for a number of decades. It’s akin to an adolescent teenager going through some dramatic growth spurts.
Software engineering, as a discipline, is expanding at a tremendous rate. Unfortunately there is still much chaos with regards to standards, interoperability , and quality. Part of what is fueling this chaos is the equally (or even more) dramatic growth of computing hardware [Check out Moore's Law regarding the doubling of transistor capacity on integrated circuits every two years]. It’s too easy these days to adopt the “throw-hardware-at-it” approach to solving software issues, instead of investing time to make the software engineering part of the solution more efficient, standardized and qualified.
I believe that two key elements that will help to save the software industry from inevitable [yes, I can predict the future] implosion are the API and the Unit Test. Wikipedia [I know it is not an "official" source, but it will do for this purpose] offers this introductory definition of API:
An application programming interface (API) is an interface implemented by a software program to enable interaction with other software, much in the same way that a user interface facilitates interaction between humans and computers.
I would extend that by saying that an API also establishes a contract [and yes, I wish it were a legal contract, accompanied by certifications, penalties and expulsion - but I digress] between the consumer and software component that defines and enforces the following:
- Purpose – A statement of intent for the software component, including a listing of contracted actions.
- Inputs – The definition (including type and value constraints) of the information/data needed by the software component to perform the contracted action(s).
- Outputs – The definition (including type and variability/tolerances) of the information/data produced by the software component as a result of performing the contracted action(s). This includes any notifications (events, warnings, errors, etc.) that may occur during the process.
- Changes – This can also be classified as output, but specifically defines the expected changes to the state of the software component and its environment (context) as a result of performing the contracted action(s).
I would describe a software component as a packaged (however crude that ma y be) set of software elements that is delivered (or sold) to a consumer.
With the establishment of a well-defined API as a “necessary and required” part of all software components, software engineering can begin to take its place among the other stabilized and mature engineering disciplines. Consumers, whether they be end-users or other software engineers, will begin to better predict software behavior and have increased capability with integrating software components to meet their needs.
But wait… How can software engineers gain the confidence needed to guarantee their software components’ API contracts? Well, testing is the answer – specifically unit testing. Not to take away from the other types of testing (e.g. system, performance, security, etc.), but it all starts with a deliberate and specific unit test. There are quite a few testing approaches in the industry to choose from to adopt (e.g. TDD – Test Driven Development), but it all comes down to ensuring quality and verifying expected results of software, as defined by the API. In the case of unit testing, quality is verified from the bottom up.
So, today, what we can all do to advance software engineering in the right direction is to start with a well-defined API, and then build and Unit Test our software components to meet that API. You never know – one day you may have to cough up some dough if you breach that contract.