Design Logic
When generating circuitry, you are designing a logical solution to a problem. You can therefore assume an infinitely parallel, shared memory processor - all methods will (logically) run in parallel when their events are ready. As such there is no need to think 'parallel', instead think 'what are the requirements for this method'. Physical parallelism will depend on the available hardware.
Granularity
When designing circuits think, logical units (Eg. Input, Output, Recording, Display, Control, Detection, Tracking etc.). Keep all of the processing required to perform this logical unit together in a circuit or sub-circuit.
Dont make circuits too small. How small is too small? Unfortunately their is no Golden Rule. Although a stand-alone method is probably too small, it may encapsulate all of the required logic (eg. to detect something). A future revisit, may decide to add more processing within the defined logic (eg. change the detection algorithm from "Do i see it? yes/no" to a complex "yes/no - if not sure have another look"). If no circuit interface changes are required (its contained within the original logic) then no changes to other circuits are required. The original choice of a single method circuit would now seem to have been an inspired choice.
Client/Server
Each circuit should have a Client/Server relationship with other circuits, where a Server provides a service to any Client that requests it. Thus a Server has no design knowledge of its Clients, whereas a Client requires intimate knowledge of its Servers, and cannot execute without them.
Circuits designed with Client/Servers that do not form loops (A client of B, B client of C, C client of A), simplifies the general development and testing process. As the system can be built and tested in stages, adding new clients each time. Laying out containers/parent circuits with Servers on the left, Clients to their right, helps to highlight any potential loops. Left-most Servers are Master Servers, they are clients of no-body. Similarly right-most Clients are Dumb Clients, they serve no-body.
NB The Client/Server relationship depends on which objects do the connecting. Clients 'connect to' Servers. It has nothing to do with data flow, Clients can 'connect to' and write data to a Server, once received the Server holds the definitive copy of the data for other Clients to 'connect to' and read.
Degradation/Game Over
Game Over is the condition where something has gone so badly wrong that it is not worth continuing, the system should be shut down and restarted.
By identifying what constitutes Game Over, circuits can be designed to reduce the likelihood of it ever happening. Ignoring the issue, or simply stating that it mustn't happen are good ways of generating non-maintainable spaghetti code and ensuring it will happen.
In practice, Game Over invariably occurs when the definitive control data is lost (or corrupted), anything else just generates a temporary glitch in the output. By creating Client/Server circuits and putting critical data/processing in the Master Server circuits and putting non-critical functions in Dumb Client circuits, means that should a circuit fail it will only affect Clients to their right, degrading the system, but not Game Over (unless the Master Server circuit fails). Isolating this critical circuit infrastructure means we can concentrate our protection efforts, by isolating them in this way we are implicitly protecting them, reducing the chances of Game Over events ever occuring.
Defining Client/Server circuits in this way, explicitly highlights what functionality can degrade, and what circuits are affected when it does. Policies can now be put in place as to 'when and where' to trap potential failures and what to do about them.
Eg
Raw Input data is distributed to the two clients, Recorder and Processing. Processed data is sent to the GUI for display.
Master Server - Input
Clients - Recorder, Processing
Dumb Client - GUI (we dont want any failures in the GUI to stop the Processing/Recording/Input)
Corrupt Input data should always be sent to the Recorder, but should not be processed nor sent to the GUI for display.
The first method in the Processing client must check for validity and abort the processing chain if corrupt, else process it and pass it on to the GUI.
Neither subsequent Processing nor the GUI need to check for validity.
Processing and GUI clients need to be able to handle jumps in the data.
The Recorder must not check for validity or jumps, just record it.