

If the entity has a parent, return the sum of the parent `obj` should have `position` and `parent` methods. If templates are a possibility (we have the necessary compile-time info in advance which is not lost by the time we get hold of an object, i.e.), then we can simply do this: // Returns the absolute position of an entity as the sum
Interface segregation principle software#
The runtime part can be important in, say, a setting with a software development kit where the functions will not have the compile-time information of plugins in advance that implement these interfaces. It allows you to design interfaces with very singular responsibilities (sometimes just one member function inside) that you can mix and match all you like without worrying about ISP, and getting the flexibility of pseudo-duck typing at runtime in C++ (though of course with the trade-off of runtime penalties to query objects to see if they support a particular interface). With this, the temptation to design overlapping interfaces is often mitigated to the absolute minimum. of course hopefully with type-safe wrappers and all that you can build centrally to get something safer than raw pointers. Return xy + abs_position(parenting->parent()) return the sum of the parent position and the entity's If the entity implements IParenting and has a parent, If (parenting & parenting->parent()->query_interface()) IParenting* parenting = obj->query_interface() IPosition* position = obj->query_interface() Īssert(position & "obj does not implement IPosition!") inherited by all entities using this interface query system. `Object::query_interface` returns nullptr if the interface is `obj` should implement `IPosition` and optionally `IParenting`. When designing interfaces with a totally distilled, ultra-singular responsibility, the temptation will often be to either accept some downcasting or consolidate interfaces to fulfill multiple responsibilities (and therefore tread on both ISP and SRP).īy using a COM-style approach (just the QueryInterface part), we play to the downcasting approach but consolidate the casting to one central place in the codebase, and can do something more like this: // Returns the absolute position of an entity as the sum So we end up often wanting to design a more diluted interface which consolidates the concerns of IParenting and IPosition in one place, like IGuiElement or something like that which then becomes susceptible to overlapping with the concerns of orthogonal interfaces which will likewise be tempted to have more member functions for the same "self-sufficiency" reason.
Interface segregation principle code#
as well as quite ugly/dangerous, given that we're leaking the responsibility to do error-prone casting to the client code using these interfaces and/or passing the same object as an argument multiple times to multiple parameters of the same function. Return xy + abs_position(dynamic_cast(parent), parent position and the entity's local position. If the entity has a parent, return the sum of the Vec2i abs_position(IPosition* position, IParenting* parenting) `position` and `parenting` parameters should point to the of its own position and the position of its ancestors.

This is almost certainly going to be a complete tangent to the cited book's approach, but one way to conform better to ISP is to embrace a casting mindset at one central area of your codebase using a QueryInterface COM-style approach.Ī lot of the temptations to design overlapping interfaces in a pure interface context often comes from the desire to make interfaces "self-sufficient" more than performing one precise, sniper-like responsibility.įor example, it might seem odd to design client functions like this: // Returns the absolute position of an entity as the sum
