Is the whole idea of restricting access to a class's public functions in different ways for other different classes just silly altogether?
Sì e no. Portami con me.
Limitare l'accesso a una classe specifica è sciocco. Mentre è importante separare una classe dall'implementazione delle sue dipendenze, è probabilmente più importante separare una classe dai dettagli della classe che dipende da essa.
Per questo motivo, è anche sciocco chiamare le tue interfacce come se fossero un collegamento tra le due classi. Non lo sono.
Alla classe chiamante, come sottolinea Euforic, l'interfaccia è "Devo essere in grado di farlo ... Non mi interessa come è fatto". Il nome dovrebbe riflettere questo. vale a dire. Piuttosto che un'interfaccia tra ProductService e SqlProductRepository denominata SqlProductRepositoryForProductService, dovrebbe esserci un'interfaccia nota al ProductService denominato ProductRepository ("Devo essere in grado di salvare un prodotto e non mi interessa come"), che è implementato da SqlRepository.
Ma SqlRepository potrebbe anche essere in grado di memorizzare ordini. E in questo senso, ha senso limitare l'accesso FROM ProductService a SqlRepository in modo che possa solo memorizzare i Prodotti. OrderService può accedere a SqlRepository tramite una nuova interfaccia denominata OrderRepository.
Perché preoccuparsi, chiedi? Perché non accedere semplicemente alla classe o un'interfaccia che ti dà accesso all'intera classe?
Perché potrebbe essere che, una volta che SqlRepository è cresciuto oltre il proprio controllo, si desidera suddividerlo. Forse in un SqlMembershipRepository (che potrebbe gestire utenti, gruppi, ruoli, ecc.) E un SqlManufacturingRepository (che potrebbe gestire prodotti, componenti, ecc.) E un SqlSalesRepository (che potrebbe gestire ordini, clienti, ecc.). Se hai consentito a tutti gli accessi a tutto lo SqlRepository, potresti trovare che questo è un compito molto più impegnativo che semplicemente spezzare la classe in tre e implementare le stesse interfacce che i Servizi richiedevano sempre. Soprattutto se hai diverse classi che devono salvare un prodotto.
Oppure, e questo potrebbe essere il punto più importante, potresti voler cambiare il modo in cui gestisci solo le vendite. Per qualche motivo, potresti decidere di memorizzarlo in un file o in un database NoSql.
Se hai tenuto segregate le tue interfacce, devi solo implementare l'interfaccia ProductRepository sul nuovo NoSqlRepository. Se lo hai tenuto come un'unica interfaccia, dovresti implementare SaveOrder nel NoSqlRepository (anche se era un metodo vuoto, perché non è mai stato utilizzato) e lasciare l'implementazione di SaveProduct su SqlRepository.
All'improvviso la tua intera astrazione tra servizi e repository non avrebbe senso. Un altro sviluppatore può venire e scrivere un codice che memorizzerà un ordine. C'è una buona possibilità che chiamino accidentalmente il metodo SaveOrder vuoto sul NoSqlRepository, invece del metodo SaveOrder su SqlRepository. E potrebbero essere molto confusi quando ciò non funziona.