Stop cramping my style, boss
We've all been there. The boss is demanding we follow a rigid software process and all we want to do is prototype a solution that demonstrates a more profound understanding of the problem then another proposed solution.
Younger software engineers who show a great deal of aptitude often fall victim to this type of thinking, because for tasks that are beneath the scope of a few weeks of work, they are completely correct.
If your task granularity and project load is incredibly low, say limited to homework programming assignments, you can absolutely attack the problems with an unstructured process such as rapid prototyping or just hack away.
However, I think it is actually beneficial for students, particularly for those seeking to join an embedded development community, to understand the kind of software process used by real hardcore engineering shops that deliver world-acclaimed products that save lives.
Not only are these people on a mission to fix world problems, they are also keenly aware that they could be held responsible for deficiencies in the software.
This article addresses C++, C or similar language-based embedded development in an integrated posix programming environment that employs agile methodologies and pair programming. It is the author's belief that this does not apply to softer sciences such as web services or script-based programming, even if that programming is compiled to actual instructions or if C and C++ code can be virtualized.
No matter how execution of your code is performed, you must be able to fully model it and demonstrate it completely to the extent that would be satisfiable by a forensic investigation.
What goes wrong?
All software design involves risk. The key is to disambiguate risk vs management dysfunction vs programmer dysfunction. Usually, if something goes wrong, it is the result of a product of these factors.
When a software shop becomes dysfunctional, it is usually due to an abridgement or abortive use of this process in favor of fire fighting, rapid development, or vague and poorly understood alternative software processes, often in order to save the engineering team's reputation from the viewpoint of a hostile non-technical manager in sales, or to beat a competitor to the delivery of a feature in competing software.
It used to be the case that this process was at odds with a process often referred to as the "waterfall model." It is my belief that this "waterfall model" can be shown to be out of date even for complex engineering tasks like medical ventilators or motor vehicle control systems.
What is the new alternative? TDD specified design combined with integrated task tracking and source control.
A fully integrated software development environment should include a task management system such as Jira, a source control versioning system, as well as a fully articulated release and quality assurance cycle.
Without these crucial elements, any agile environment will quickly descend into chaos, even if it is populated by very talented research and development engineers with doctoral degrees.
The biggest mistake I have seen in software shops is when teams get too adversarial with each other and do not interoperate with a sufficiently unified goal. This is not always due to the executive or manager's poor decisions, but can also occur because of:
- Geographic separation of teams causing rivalries, mutual social exclusion and dislike.
- Interpersonal conflict among staff due to diverse differences in upbringing.
- A single engineer who does not work well with others and excludes them from development decisions.
- Several engineers who do not produce quality code but depend on a single quality engineer for sustained effort.
- Talented engineers who produce quality code but are dismissive of management concerns and process accountability.
- Grandfathered engineers who no longer produce quality code, but have institutional knowledge crucial to company survival which they depend on for employment
Motivated by what I saw as past failures in software process, occasional non-technical mismanagement, and observation of incredibly effective management alternatives in the biomedical devices industries, I have decided to establish my own minimalist approach to engineering management that I feel combines the wisdom of all of my previous successes, failures and experiments.
The bare necessities and no more
Here is my personal addendum to the well-composed and well-thought out agile manifesto.
- Engineering approaches should almost always be minimalist, because this usually reduces cost.
- Safety-critical engineering should be performed in pairs with task management and source control integrated directly into the software development environment.
- Creativity should never be restricted, but should always be integrated into the process. Any code produced by an engineer alone should be tracked and in source control. Coding alone when not assigned to a task should be encouraged and appreciated.
- Design acceptance criteria should be specified entirely using the unit tests. Extensive annotation and comments are unnecessary and a sign of poor code construction.
- Build release cycles, branch integration and build errors should be detected automatically by a build management system and blame assigned automatically. It may be reassigned at the appropriate management authority's prerogative.
- Commits should always occur in pairs and this process should be integrated into the version control system.
- Designers and web service engineers whose industry values expediency over code quality but whose artistic talent is seen to be valuable should be accommodated through an integration process that is as rigid as any other part of the project and conforms to basic engineering expectations and guidelines, such a testable design acceptance criteria.
- Any region of code, physical component, integrated circuit, or user interface that has a user story that is not testable by a design acceptance criteria is considered insufficient. A user story that is not testable is considered to be out of scope and non-information.
- Code analysis tools must be integrated into the build cycle and must include test coverage tools. An engineer should make his test design acceptance criteria his contract and as part of that contract be expected to show complete code coverage of all his tests. The mechanism through which this should be achieved should be agreed upon through engineering consensus of the entire administrative staff.
Brevity, clarity, with redundancy only when necessary by design.
- Do less with more. Do just enough and no more. Save on costs.
- Work in pairs. Engineers hold each other accountable. Rotate pairs often.
- Do not restrict individual creativity when it is useful, but track it and save it diligently.
- Keep unit tests minimal but sufficient, and time needed to understand them short. Break up any large test into smaller tests if it does not comply with this maxim.
- Build releases and assign blame automatically. Be flexible with humans. Assign responsibility using empirical evidence.
- Commit only in pairs and require two-level authentication of both engineers.
- Accommodate non-technical designers, but prevent them from introducing harmful code unintentionally.
- Keep designs testable or throw them out.
- Use empirical data alone to show test coverage.
Process, no matter how well designed or enforced, is no guarantee of code quality
Any belief that following a code development process rigidly guarantees an improved or even successful result is as silly as believing that prayer alone will heal a sick child and should be avoided.
Talent is necessary but not sufficient for code quality. Process is necessary but not sufficient for code quality. Both are necessary but insufficient for code quality. Code quality is a factor of effective team management, mentorship of the most talented but sometimes impetuous junior engineers by tempering it through the wisdom of older engineers, and effective guidance of the executive and involvement of the executive at all levels of engineering.
As a follow up to these posts, we will be expanding our material to cover the following topics. Please stay tuned.
Coming soon
- Specifying a C++ design entirely in unit tests
- A manager's view of integrated circuit design testability
- Design testability: It applies to engineering, too.
- Acceptable risk is *testable* risk: Disambiguating mismanagement and bad engineering from acceptable risk using test criteria
No comments:
Post a Comment