Design Strategy We are still bad at writing large software. Many companies (particularly large ones), try to solve the problem by adding lots of design, documentation, and oversight controls and processes; particularly up-front. This seems like a good idea as it is analogous to building a house with o an architect (software architect) o a general contractor (manager) o lots of construction workers (coders) People can specialize and you can pay people according to their "level". The only problem is that building a house is very poor analogy to building a program. Why? Imagine constructing a house as if it were more like building software: o every time you pound in a nail downstairs, the upstairs toilet flushes == dependence between objects. o the architect had no idea a priori how much weight the dirt/sand underneath the house could actually take == don't know how fast disk access will be. o the architect couldn't foresee that the cost of pine wood would rise dramatically due to supply problems; they have to alter the design to use wood with a different load-bearing strength == no idea that users would behave in a weird way, making a previously small array a HUGE array that won't fit in memory. o the architect designed the house as a two-story house per customer request, but the customer decides 2 months into construction that they are afraid of heights and want a single-story house instead == marketing wants radical changes. o there are numerous small changes to the dimensions of everything from pipe diameters to room widths to suit the tastes of individual workers or unforeseen problems. All of a sudden one pipe doesn't match up with another == individual coders make lots of seemingly-innocuous decisions that can affect other programmers. o the architect designs the house using idealized components. In reality some components are unavailable or too costly or simply expand too much in hot weather == an algorithm of cost O(n) has such high implementation constant on front as to be impractical. Sun-Tzu: "no plan has ever survived contact with the enemy." Better to plan on being agile, reacting intelligently rather than stubbonly and rigidly sticking to your original plan even though it doesn't fit the current circumstances. Confidence in yourself or your coders may influence design strategies. You have to be confident that you can react intelligently and swiftly to the rapidly and constantly changing currents of software development. You should assume you will make mistakes and have to back up, throwing out some software. Your software is always in a state of decay anyway, so you should be used to refactoring your code; it must be groomed continuously lest it become fragile and inflexible. Tom Burns, CEO of jGuru.com, suggests that some of these "do all design work upfront" strategies are legacies of the day when edit-compile-test cycles were insanely slow (perhaps even using punch cards). You couldn't really "send out scout parties" to test ideas. Per the above about the toilet, one of your goals should be to make each object as encapsulated and independent as possible. #### Process Design goals: get a list of operations, entities/actors start with general features then iteratively refine them until you can clearly see the operations like "show email msg". With web apps you can start to lay out the pages as a tool to help you think about the system and get more specific. Same with gui apps. Once you have actors and functionality, try to group functionality into services or modules. Do a data flow diagram to show what actors or entities you have like mail msg, user, address, ... Usually reveals a general architecture; draw lines where different machines exist. You can begin to formalize everything by making classes for services and actors and then filling in operations names as methods (no implementation yet!). This helps you define the interface between objects. Try to isolate funtionality that will change by abstracting the operation such as the persistence layer.