Limit the number of explicit, static, interfaces; define large grained interfaces
Limit the number of explicit, static, interfaces. Define large grained interfaces that allow developers to code against interfaces defined early, but which do not overly constrain functionality.
To some large extent this approach is driven by the fear of change, something the modern agile methods have addressed. When interfaces are defining boundaries of functionality partitioned and split between two teams, then change to the interface will be more costly than to internal interfaces. At the time of partitioning, a broad, shallow idea of the requirements that define the interface will be available; these requirements will be fleshed out as more is known about the system. Where change to an interface is problematic, define the interface in terms of these broad, shallow requirements, using LooseInterfaces such as callbacks, ParserBuilder and HierarchyOfFactories that allow detail to vary behind a comparatively stable interface.