[SalesForce] Delete triggers don’t cascade master to detail, so why not hand-cascade on the master

I understand from experience that Master-Detail deletion triggers do not cascade. For example if I delete my Account the Contact deletion triggers don't fire.

Having devoured the first and second editions of the outstanding book Advanced Apex by Dan Appleman, there's one point in the chapter on triggers I'm looking to clarify:

Delete triggers typically do not fire on cascade deletes. If you need to detect deletion of the child objects, you must create a before-delete trigger on the parent object and perform your desired operation on the child objects at that time (be sure to design this carefully – there may be a large number of child objects).

So if I had a trigger like this on Contact:

trigger ContactBeforeDelete on Contact (before delete) {
    ContactNotifier.alertDeletedContacts(Trigger.old);
}

The book encourages creating one likewise on Account:

trigger AccountBeforeDelete on Account (before delete) {
    List<Contact> contacts = [SELECT Id FROM Contact WHERE AccountId = :id];
    ContactNotifier.alertDeletedContacts(contacts);
}

But to me, the obvious solution would be to cascade the deletion, not the business logic:

trigger AccountBeforeDelete on Account (before delete) {
    List<Contact> contacts = [SELECT Id FROM Contact WHERE AccountId = :id];
    delete contacts;
}

The child triggers will take care of the logic. Copying the invocation around isn't DRY. So why 'perform the desired operation on the child objects' instead of just cascading the delete? Is there some catch?

Best Answer

One of the issues with an explicitly delete of all the child records is that there may simply be too many of them. I've seen instances where a master object has more than 10,000 detail records, and if you're doing a mass delete of parents with high numbers of children that would eat through your DML rows limit very quickly.

While it's conceptually simpler to cascade the deletion I'd think carefully about expected volumes before doing so. Dan's pattern only cascades side effects of the deletion as needed.

It boils down to developer productivity vs efficient code, and every environment has different factors impacting which way that decision should go.

Edit: You'd also have to be wary of any developers taking advantage of the fact that cascade deletion doesn't invoke delete triggers and assuming that all delete operations on child records are explicit in their triggers. In a complex org that's a headache to check for.