"Akkor megint API break az, hogy mondjuk a konfig fájlban(!) átütöm, hogy nekem mégsem a NoopEmailValidator kell, hanem egy olyan, ami szépen végigcsinálja az RFC ellenőrzést, a DNS kéréseket stb?"
Ez egy szemantikus törés, bizony. Ugyanis a NoopValidator meg RFCBasedValidator csak formailag ugyanazt az interfészt implementálja, szemantikailag meg nem.
Mondjuk például ellentmond a Liskov substitution principle-nek.
Van egy EmailValidator interfészed, N implementációval.
Akkor bármikor, bármilyen inputra a következő kódnak mindig ugyanúgy kell viselkednie a hívó szempontjából:
emailValidator.isValid('a@b.c')
Mert ha különbözőképpen viselkednek a hívó szempontjából, akkor az azt jelenti, hogy valójában nem ugyanazt az interfészt implementálják szemantikailag, csak formailag.
Hogy egy másik, közismert példát mondjak: Javaban ha implementálod az equals-t, akkor az equals szemantikáját is be kell tartanod, nem csak a formáját. Ha nem tartod be az equals szemantikáját (rosszul implementálod), akkor például nem működhet egy Set-ed, egy List-ed, amelyek felhasználják az equals szemantikáját, és feltételezik, hogy aki implementálja az equals-t, az helyesen teszi.
Azért az eléggé ciki, amikor egy hívónak tudnia kéne, hogy akit hív, az hogyan van implementálva.
Hogy értsd: az Ariane-nál is ez volt a probléma. Tightly coupled rendszer, az IMU-nak tudnia kellett, hogy milyen környezetbe ágyazzák be, és emiatt (az IMU implementációs hiányossága miatt) nem lehetett beágyazni egy formailag (de nem szemantikailag!) ugyanazt az interfészt (hogy úgy tessék, API-t) használó rendszerbe.