Currently, I'm in Columbus working for a company called SubmitOrder. I work on a somewhat large system as a programmer. The original system when I started was about 100,000 lines of PL/SQL (Oracle's procedural language) and took 30 person-years to implement. (Of course, this was 30 people x 1 year.) Performance and support were both terrible, so I re-designed the system. Our new version is nearing completion. It is about 15,000 lines of Java, much more flexible, and performs at 25 times the throughput with 1% of the latency of the previous system. It will have been completely implemented in 1.5 person-years (5 people x 4 months).
After reading the above paragraph again, it sounds quite boastful, but it is not intended to be. The new system is nothing earth-shattering, it just follows the basic design principles that were taught in the Resolve sequence. After spending a few years in industry, I am completely surprised at how under-used these concepts are.
The biggest thing that impresses people with our new software is the separation of interface from implementation. Almost every component implements an abstract interface, even if there is only one implementation. Time and time again, we have realized later that there are several different implementations that fit the same interface. This has also allowed us to build a highly flexible message passing system that can use about 10 different transports and 5 different database objects. The Resolve sequence has really done a great job of showing that a well defined interface helps in prototyping as well as in the software life-cycle. I can't tell you how many times my co-workers have been amazed as we completely re-write a module with no changes (other than performance improvements) to the system.
The second thing that has really helped the design and development cycle is layering. The concept of using many small objects to implement larger objects has increased the pace of development. The people I work with are starting to see that reuse through aggregation and layering often is much simpler than reuse through subclassing (the more traditional object-oriented approach to reuse). People are shocked at how few inheritance hierarchies we have, yet we still can create large objects. The difference is in the abstraction, because we can swap out one implementation for another without affecting the objects that use the smaller objects.
Finally, documentation on what each operation does is important. While our documentation is not predicate calculus, simple notes about parameters that are modified as well as information on what is consumed, produced and used has been invaluable. Our system passes messages that contain meta-data. Many components require certain meta-data to function, and by making this information available programatically, we can build a dynamic system in which modules can be rearranged, inserted and deleted at will -- and that we are positive will function. This programatic dependency checking has been a life saver. (I don't think I ever realized how much I would miss the produces, consumes ... clauses on parameters.)
I'm sure there are more things that I learned in 221, 222 and 321 that
I put to use on a daily basis. However, those were the three that
made the biggest impact on me. I can't thank you and the rest of
RSRG enough for the time and effort you put into developing the curriculum.
I know a lot of people don't quite understand the reasons for everything
that is done. However, I can assure them that what you are doing
is extremely useful and will help them in the future.