Plan partitions around packages, processes, and machines:
In the absence of other constraints we partition code logically, trying to keep each part simple and focused on a single activity.
But, often other factors enter into those decisions. Performance often dictates other structures.
The time required to make a function call varies greatly with the degree of locality of the call, e.g., within a process
defined by an Executable and possibly Dynamic Link Libraries (DLLs), between
processes, between machines, and between networks. Each of these locality boundaries increases call time by about an order of magnitude.
Ideally when you have a lot of calls to make you try to do that as locally as you can.
When lots of data has to be marshalled you try to do that as locally as you can. Marshalling occurs when data has to
be serialized into a transmission format then deserialized when it arrives at its destination. This usually happens when data is transferred
between two different technologies, e.g., COM and native code or managed code and native code, between two different processes, or between
machines in a network or across the internet.
Sometimes we will partition based on software reuse. The existing code lies in its original set of packages and new code is added to use
This means that partitioning is not always simply a logical matter of creating cohesive packages. We often have to take into account physical
boundaries as well.
Conclusions for Package, Process, and Machine Partitions:
Partition based on both logical cohesiveness and physical boundaries.
If one entity has to make a lot of calls to another, try to place them as locally as possible.
Ideally they will be in the same package.
Do the same when one entity has to send another a lot of data.