This is something I work to convince my team about and Dan Appleman has a great book out that I definitely recommend that explains trigger structure very well. If controlling the execution of Triggers is needed a software structure needs to be put in place as the .trigger files will not execute in any order. His book has a good basis for a trigger structure that allows you to control the execution of trigger flow very precisely. Here is a basic implementation that we use
public with sharing class TriggerHandler {
public static ITrigger activeFunction = null;
public static map<Id,SObject> sObjectsToUpdate = new map<Id,SObject>();
public static void TriggerHandlerEntry(TriggerState state){
if(state.TriggerObject == 'Custom_Object_1__c'){
processCustomObject1TriggerHandler(state);
}else if(state.TriggerObject == 'Account'){
processAccountTriggerHandler(state);
}else if(state.TriggerObject == 'Custom_Object_2__c'){
processCustomObject2TriggerHandler(state);
}else if(state.TriggerObject == 'Custom_Object_3__c'){
processCustomObject3TriggerHandler(state);
}
if(sObjectsToUpdate.values().size() > 0){
update sObjectsToUpdate.values();
}
}
public static void processCustomObject1TriggerHandler(TriggerState state){
if(activeFunction != null){
activeFunction.InProgressEntry(state);
}
else{
activeFunction = new OrderLineItemTriggerHandler();
activeFunction.MainEntry(state);
}
}
public static void processAccountTriggerHandler(TriggerState state){
if(activeFunction != null){
activeFunction.InProgressEntry(state);
}
else{
activeFunction = new AccountTriggerHandler();
activeFunction.MainEntry(state);
}
}
public static void processCustomObject2TriggerHandler(TriggerState state){
if(activeFunction != null){
activeFunction.InProgressEntry(state);
}
else{
activeFunction = new StampOrderTriggerHandler();
activeFunction.MainEntry(state);
}
}
public static void processCustomObject3TriggerHandler(TriggerState state){
if(activeFunction != null){
activeFunction.InProgressEntry(state);
}
else{
activeFunction = new BondTriggerHandler();
activeFunction.MainEntry(state);
}
}
public interface ITrigger{
void MainEntry(TriggerState state);
void InProgressEntry(TriggerState state);
}
}
The author passes around the "TriggerState" information with a multitude of parameters but we added the information into an object called "TriggerState"
public with sharing class TriggerState {
public String TriggerObject {get; set;}
public Boolean IsBefore {get; set;}
public Boolean IsAfter {get; set;}
public Boolean IsDelete {get; set;}
public Boolean IsExecuting {get; set;}
public Boolean IsUpdate {get; set;}
public Boolean IsInsert {get; set;}
public list<SObject> NewList {get; set;}
public list<SObject> OldList {get; set;}
public map<Id,SObject> NewMap {get; set;}
public map<Id,SObject> OldMap {get; set;}
public TriggerState(String triggerObject, Boolean isBefore, Boolean isAfter, Boolean isUpdate, Boolean isDelete,
Boolean isInsert, Boolean isExecuting, list<SObject> newList, map<ID,SObject> newMap, list<SObject> oldList, map<ID,SObject> oldMap) {
this.TriggerObject = triggerObject;
this.IsBefore = isBefore;
this.IsAfter = isAfter;
this.IsUpdate = isUpdate;
this.IsDelete = isDelete;
this.IsInsert = isInsert;
this.IsExecuting = isExecuting;
this.NewList = newList;
this.OldList = oldList;
this.NewMap = newMap;
this.OldMap = oldMap;
}
}
Now every trigger class looks like this except that you would pass in the name of the current SObject you are in and create a subsequent handler class:
trigger Account on Account (before insert, before update) {
TriggerHandler.TriggerHandlerEntry(new TriggerState('Account', trigger.isBefore, trigger.isAfter, trigger.isUpdate,
trigger.isDelete, trigger.isInsert, trigger.isExecuting, trigger.new, trigger.newMap, trigger.old, trigger.oldMap));
}
Now there are a few different things going on in this structure besides just controlling flow of trigger execution. This is also making a determination between Triggers DML calls and user generated DML statements. Each trigger handler must implement that ITriggerHandler Interface which contains a MainEntry and ActiveEntry method. The TriggerHandler keeps track of an "Active" trigger handler and unless this active function is set all subsequent triggers are routed to that handler's inProgressEntry. If you want the Trigger to execute through its own handlers main entry - simply set the activeFunction static variable to null. When the trigger handler comes in it will be routed to its particular trigger handler. This structure is also creating a centralized list of SObjects to update so that all code can finish executing and then process the update for the objects.
For your situation you may not need all the features this type of structure offers but one thing that is stressed in that book is that if you can justify just a little extra time into putting a good structure in place - it can save you alot of time in the future. Obviously it is still important to keep the scope of the project in mind when implementing something like this but I think that more often than not these systems get larger than anticipated. I have personally run into issues where a lack of a centralized trigger system in a very large application caused me a couple days of headaches.
If you do some research you will find all kinds of trigger structures out there - you may find a different one more suited for your particular case but it is an important question to have none the less.
Here is the link for the book I was mentioning.