In the earliest days of programming, each programmer not only had to have a bootstrap program that would read his/her application from the card reader, but write drivers for any hardware that was used by their application.
An operating system provided an API so that a programmer could concentrate on an application rather than building a system for each application. SPUDS was not only an operating system, it was a developers environment that could be used to debug a real-time embedded system. It not only allowed for setting break points and tracing application code, but it allowed setting break points and tracing the real-time operating system as well.
As I became proficient with SPUDS, many of the engineers asked for my help to debug their modules in the system. This put me in a great position to work with the entire system, and learn how a real-time system is built.
Because I had an overall knowledge of the entire system, thanks to the knowledge I gained from the team members, I was selected to go on sea trials for the ship. Even though the ships captain, did not care for "ships riders", it was enjoyable, and the captain eventually accepted my presence.
Even though the leaders of the project had a good engineering process in place, they were on the look-out for improvement. At the time, many papers were being written about structured analysis and design, so they decided to run an experiment. Two teams were selected, and one team would be involved from requirements definition through the end, while the second team would become involved after the high level design was completed. The objective would be to determine which team finished first, and document how and why.
The archive tape was a log of messages that were important for our customer to track. It contained logical files and logical records that overlapped physical files and physical records. On a disk storage system, there would not have been any problem, but tapes were not made for random access, and the tapes became stretched over the years, and became apparently unusable. I was given an emergency assignment to write a low level application that could retrieve the data.
I was given an assignment to write a data reduction program for sea trials. The test engineers were trying to decide what data to report, and I knew that once they decided which data I was to report, it would be very close to the sea trial date. I decided that what I had to do, was to develop the requirements for a program that could report any data they decided on without hard coding it. To support my plan, I developed the requirements for a data reduction language that could read the symbol table and load map to select any data and report it in any format. When the test engineers settled on the data they needed, I used the user manual I wrote to teach them how to write "reduction packets" (I avoided calling them programs). It was an instant success since they could add or delete data without rewriting the reduction program as had to be done in the past.
I didn't realize it at the time, but when I wrote the modules to process the reduction packets, I was writing a lexer and parser. I later worked with lex and yacc (flex, bison), and found them more cumbersome than the simple lexer and parser for this particular application.
ATEP/MAX is a real-time operating system, originally developed for larger computers on shipboard systems. It was written using a mix of assembly language and a high-order language. It used a dual priority algorithm for scheduling tasks. ATEP/MAX was chosen for the system we were building, and I was assigned maintenance duties as part of my assignment. The real benefit of having the source code for the operating system became apparent when I had to add new functionality to it. Instead of having to write a problem report or change request, I simply wrote the requirements for the changes, got them approved, designed the changes into the operating system, and implemented them, all in a relatively short time.
I was assigned the responsibility of adding a hardware driver and protocol into a commercial operating system. Although we didn't have the source code for the operating system, we had the specifications for adding drivers and modules to the operating system. I found it cumbersome to work from incomplete specifications, but was successful implementing the driver and protocol layers.
I learned the importance of team building by being assigned as a mentor. Being a mentor for an junior engineer, and watching them progress gives me the pride and satisfaction that is only exceeded by the pride and satisfaction I take in helping develop my own children. I have a sense of satisfaction when my team members thank me for sharing my knowledge by documenting my contributions to our systems.
There is nothing that can stress the importance of adhering to a software development process than to attempt to run a project without it. Without a defined and enforced development process, there is only chaos and failure.
Although I have found that the best engineers I have worked with over the years adhere to a process for software development and are constantly seeking ways to improve the process, some engineers and / programmers do not see the need for such a dicipline. By implementing a process at the management level, a project is assured that the process is implemented uniformly.
As new hardware was added, I was able to develop my device driver skills for multiple operating systems.
I learned that companies have personalities (or cultures), and projects within the companies develop complimentary personalities. The process of building a company or project personality takes place on a sub-conscious level.
There are many ways to keep good engineers, including recognizing their accomplishments, not only with praise, but with monetary rewards as well. An engineer who receives a bonus for exceptional performance will be more likely to remain at the company, and will continue to perform well. Mentor engineers who are not performing as well in an effort to improve their capabilities. Sometimes an engineer might be given an assignment that they are not prepared for. Try a different assignment, it might work out better. Encourage team work so that the engineers will share their expertise and mentor each other.
I hear the term "best engineering practices", but have never seen any "best". Instead, there are recognized "good engineering practices" that can be implemented. Good engineering practices include defining a process that all engineers will follow. As part of the process, identify what requirements are and are not, as well as who is responsible for them.