La tua domanda equivale a scegliere il giusto livello di astrazione per l'interfaccia del tuo servizio. Ogni sistema del mondo reale ha requisiti diversi, ma come regola generale preferisco strongmente le interfacce di servizio con una vista di alto livello. Cioè, il secondo approccio che descrivi, non il primo.
Tuttavia, questa è solo una linea guida e per fare una scelta corretta dovrai essere in grado di giustificarlo con più di "qualcuno ha detto che era meglio così" o "è il solito approccio".
Quindi analizziamo qui i problemi rilevanti.
Accoppiamento
Il tuo design dovrebbe consentire l'implementazione del servizio e i suoi clienti in modo flessibile. Il cliente non dovrebbe aver bisogno di sapere come è implementato il servizio, o come memorizza (spesso, anche come rappresenta) i suoi dati. Dovrebbe essere possibile (molto) modificare l'implementazione del servizio senza dover ricostruire o modificare i client. L'uso della parola "Entità" nella descrizione sembra implicare che gli oggetti esposti tramite l'interfaccia di servizio corrispondano esattamente alle entità in cui i dati dell'applicazione sono stati scomposti. In tal caso, ciò potrebbe indicare che esiste un accoppiamento stretto tra l'interfaccia client e l'implementazione del servizio. A volte questo è comunque consentito, laddove il servizio stesso utilizza definizioni di dati definite nella propria interfaccia (questo può aiutare con la decomposizione, che menzionerò più avanti).
Pensa a come implementare una modifica alle strutture dati utilizzate nell'interfaccia; cioè, se le strutture di dati trasportate attraverso l'interfaccia del servizio devono cambiare, devi eseguire un cambiamento radicale (scomodo!) o il tuo servizio di progettazione può accogliere clienti che si aspettano la nuova rappresentazione e alcuni vecchi? (il controllo delle versioni dell'interfaccia è un modo comune per consentire ciò)
decomposizione
La progettazione dell'interfaccia del servizio dovrebbe generalmente consentire una flessibilità tale da consentire la suddivisione dell'implementazione del servizio, al fine di consentire a parte dell'implementazione del servizio di migrare verso un design diverso. Ad esempio, dovrebbe essere possibile mantenere gli attributi delle persone spostati fuori dalla vecchia implementazione del servizio e in un database LDAP. Mentre suppongo che questo sia sempre possibile, voglio dire che il design dovrebbe funzionare in modo tale che i client non necessariamente debbano preoccuparsi che ciò sia successo, e che il l'implementazione di solo una quantità ragionevole delle interfacce del servizio dovrebbe essere modificata per consentire ciò. Ad esempio, in questo caso, questo tipo di refactoring non dovrebbe richiedere modifiche da apportare a parti non correlate dell'implementazione del servizio.
Indirection
Il livello di astrazione del tuo servizio dovrebbe essere scelto in modo tale che interagisca in un modo facile da spiegare con i sistemi a strati. Ad esempio, dovrebbe essere semplice creare un servizio di caching che front-end questo servizio e memorizza nella cache i dati per ridurre il carico sul back-end. Allo stesso modo con modifiche allo schema di autorizzazione. Allo stesso modo, dovrebbe essere ragionevolmente semplice creare un finto back-end (spesso offrendo solo un sottoinsieme di interfacce) per facilitare la verifica dei client. Allo stesso modo, i client artificiali per il test del carico.
Altri problemi
Ci sono altri problemi da tenere a mente per alcuni sistemi che non sono sempre importanti, ma possono rendere la vita molto difficile se non li si pensa prima del tempo. Un grande qui è la questione di come tagliare il servizio. Ossia, dividere il sistema esistente in più parti, ciascuna delle quali tratta alcuni degli oggetti dati nel sistema. Ad esempio se il tuo sistema accetta la posta elettronica, potrebbe essere necessario suddividerlo in più backend, ciascuno accettando la posta elettronica per un sottoinsieme di utenti (ad esempio "a" - "f" su shard 1, "g" - "p" su shard 2, "q" - "t" su shard 3, "u" - "z" su shard 4, "Â" - "Ͱ" su shard 5, e così via). Al fine di consentire ai client di rimanere invariati, questo tipo di cambiamento verrebbe di solito accompagnato dall'introduzione di un livello proxy, il cui unico compito è quello di inoltrare le richieste al back-end pertinente (dovrebbe essere possibile distribuire quanti più proxy ci sono necessario per far fronte al carico, il loro compito non è computazionalmente difficile e non dovrebbe richiedere di colpire un disco per identificare il back-end giusto.