Almost everyone wants to do architecture and almost everyone wants to do the UI. It means that every programmer has an opinion about the architecture and infrastructures in use. When you export an API for your system you get more opinions and when your product is an infrastructure (ex. Microsoft) you have too many opinions about the architecture.
People's architecture is usually tilted towards what they are experienced with. The architecture is based on a paradigm and people usually continue from there. A most prominent paradigm 20 years ago was Procedural Programming. Today Object Oriented Programming is the dominant one. This means that people start they system design with OOD and then ask "what's next?". In attempt to pull people from automatically using OOD I had a post called Flaws of Object Oriented Modeling, and a followup called Flaws of Object Oriented Modeling Continue.
The truth is usually in between A and B. In this case the truth is 'all of the above'. There are many programming paradigms to employ in a single application. Failing to do so will damage: Code manageability, Response to changes in requirements, Flow management, Ability to integrate a new UI, and more. There is a long argument between OOP supporters and Procedural Programming supporters. Once in every some while someone would step in and say that you should use more esoteric things such as MVC, Aspect Oriented Programming, Pipeline, etc. Too often you would hear people suggesting what they just read about or learned about during a single session in an event. People will always want to try new things and show you that they know something special. There are other cases of course in which people are really experienced with several paradigms or are experienced with a specific paradigm and can immediately spot where it best applies. This is what you should be paying attention to.
What I am really looking for is a collection of Paradigm Patterns. Just as you would use a Design Pattern as a programming technique, I suggest that you also employ a Paradigm Pattern as a design technique. So where do we find these patterns? Google doesn't know...
There is a list of paradigms in Wikipedia (see Programming Paradigms) but it is only a list and not a pattern. A pattern should have a clear definition of how you identify where it applies, and a clear definition of how to use it. Either I am starting a new collection or someone reading these lines would comment with a reference, I will now try to create a rough list based on my own personal experience.
The items below are short and simple so that we don't need a full definition of the paradigm in order to understand the pattern. Obviously I will start with OOP and Procedural Programming and we'll build it from there.
First of all let's start with the definition of a paradigm: Programming Paradigm defines the boundaries of programming and design. From this paradigm we derive the definition of software Components, Interfaces, Programming Rules, and others. For example: there is a difference between how C# code is divided into DLL files than the way a C++ code is divided into DLL files. A C# DLL has a class as an Interface and a C++ DLL prefers global functions as an Interface. The decision when to use a goto in your C++ code is derived from the programming paradigm.
Object Oriented Programming
OOP is very commonly used because it allows developers to work on the same project without any interactions between them.
Use: When you have multiple programmers who can't understand each other, for example one is managing an SQL database and another is doing audio processing. OOD works great for Top Level Design.
Don't: When you have several developers who need to share implementation specifics, for example if you need to write a keyboard driver don't break it into fragments which hide implementation specifics from a developer working on the driver.
This paradigm is used for dividing a process into procedures. For example your day is a process. What you do from the time you park the car until you start reading emails is a procedure.
Use: When there is a complex operation which includes dependencies between operations and a need for clear visibility of different application states ('SQL loading', 'SQL loaded', 'Network online', 'No audio hardware', etc). This is usually appropriate for application startup and shutdown.
Don't: When there are many simple independent tasks to perform. Also don't use to manage UI.
Model View Controller
This paradigm is used often by developers who don't even know it exists. The idea behind it is the clear division between View: the data representation to the user; Model: the data / document / storage / a virtual representation of a storage (using business logic); and the [Controller] which is the user's interaction with the system. All this basically means that there is separation between how the data is represented to the user, from what the user can do with the data, from what the data really looks like. An example is Microsoft Word: The view is a text document, the controller allows printing, and the storage can be an rtf file, a doc file, or an XML based docx file.
Use: Almost anytime you provide UI. Employing this paradigm allows very rapid integration of a completely new UI and fast responses to changes in UI requirements.
Don't: If there is no UI, or when there is very close coupling between what the UI can do and the business logic (usually when creating a UI engine).
You don't really need to use servers to have a distributed model. This paradigm states that there is no dependency between components just as with OOP, but with addition that there is also no dependency of infrastructure and object-to-object interaction should be kept to minimum.
Use: Whenever different platforms or infrastructures are used and when components are completely independent of each other. For example the interaction between User Mode and Kernel Mode is usually Distributed.
Don't: When data sharing has huge overhead, for interconnected modules, and between UI and Business Logic.
A Pipeline is usually made of several software components which are completely independent from each other. In this model there is usually a single data object sent from one component to the next. Most pipelines can operate completely asynchronously which makes it best for audio and video playback. Arranging components from left to right, too often a Pipeline has more than one component on a segment. For example decoding MPEG Audio frame and MPEG Video frame are two separate tasks which are independent of each other so they are both performed on the same timeslot of the Pipeline.
Use: When little or no UI interaction takes place, with Audio and Video playback and encoding, and when you have a chain of operations each dealing with a different technology. For example: Read XML file, Search items, Create Records, Save to SQL server.
Don't: When having multiple input types or events because there should be a different Pipeline for every type of input. Also when there is no clear correlation between Event and Response.
This paradigm divides the system into components just like OOP, with a huge difference - the system is divided into coherent layers. Each layer may employ OOP or Procedural internally but between layers there is a clear and simple interface. The ground rule is that requests only go from top to bottom, so a component within a lower layer cannot call a component within a higher layer. The only way to be serviced by a higher layer is by starting a new process / request. Usually the layers behave as a Distributed Pipeline.
Use: When OOP can be divided into Layers, when creating a system that has UI and hardware interaction, and in very large scale systems. Example: Windows NT (and Windows 8) Kernel.
Don't: Inside a Pipeline, in a small application or component, and don't create a Layer Engine inside a Layer.
Sounds like enough for now. You are welcome to comment with any thought.