Write complex access control in a reusable way We deal with nodes representing humans with two important properties: mother and father.

Your parents as well as your aunts and uncles should get extra permissions, like to see you in a certain view mode, or to see your private images.

Where should I place this complex access control in a way that I can easily call it in several controllers and hooks?

Is there a name for the kind of feature I'm going to program?

If there's no better idea, I would go with a validation. We could put the access control in a validator that we use like this:

$errors = $family_access_validator-&gt;validate($node);
if (count($errors) &gt; 0) {
    throw new AccessDeniedHttpException();
}



However, I'm not sure whether this is the correct approach. When we use validation, we are always interested in the message why the data is rejected. Here, we are only interested in OK or not OK.
For access control on routes, you can write a service which implements AccessInterface.  At its simplest, this is just a class placed in a module's src/Access folder with a single method public function access(AccountInterface $account), returning a flavour of AccessResult.  Then you simply register your class in the module's services.yml, annotate the route to use that access checker and Drupal will do the rest.  Relevant documentation  

The documentation suggests that if the route being access-checked has an upcasted parameter like {node}, then you can add $node to function's arguments - i.e. public function access(AccountInterface $account, Node $node) and it will be automatically supplied.  I haven't actually tried that part myself though.  Assuming it works, you can then access the node's fields as normal in order to compare the entity ids of the mother/father fields with the user to which the $account belongs.  

I'm not sure if there are similar ways to automatically invoke this same access check for displaying entities with different view modes, but at the end of the day it is just a service like any other, so you could always request it from the container or inject it into whatever other controllers / services / hooks you need.  In these contexts you will of course have to 'manually' supply the current user $account and relevant $node to check.