Ho una classe IItemProcessor
che preleva ogni elemento da un elenco e lo invia a un'API Web ( IApiService
). L'elaborazione viene eseguita in modo asincrono su un altro thread.
Se l'API web risponde con "utente non autorizzato", l'app deve uscire. Per questo, ho un IApp
che ha il metodo LogoutUser()
.
Attualmente l'implementazione ItemProcessor
rileva errori generati da IApiService
e se l'errore è "non autorizzato", chiama IApp:LogoutUser
.
Il problema è nell'implementazione di IApp:LogoutUser
Devo chiamare IItemProcessor:Stop
per interrompere l'elaborazione. Il che significa che esiste una dipendenza circolare tra App
e 'ItemProcessor.
Sto usando Dependency Injection nel c-tor e questo mi dà una costruzione ricorsiva infinita degli oggetti concreti:
public class App : IApp
{
public App(IItemProcessor itemProcessor)
{
...
}
public void Logout()
{
_itemProcessor.Stop();
}
}
public class ItemProcessor : IItemProcessor
{
public ItemProcessor (IApp app)
{
...
}
public void Stop() {
...
}
void Run()
{
... for each item in list ..
try
{
... try send item ....
}
catch(UserNotAuthorizedException)
{
_app.Logout();
}
}
}
Come posso risolvere questo problema?
IApp
deve sapere su IItemProcessor
per avviarlo e interromperlo su login utente e logout. Ma mi sento come se IItemProcessor
interrompesse SRP, in realtà non dovrebbe chiamare Logout
, ma piuttosto in qualche modo informare "qualcuno" dell'errore, e che "qualcuno" ha a sua volta la responsabilità di chiamare IApp:LogoutUser
. Ma cosa dovrebbe essere questo "qualcuno"? Dovrebbe essere un ascoltatore per gli errori del processore dell'articolo?
Ho difficoltà a capire come dividere le responsabilità.
Ho provato a utilizzare lo schema di comando avendo LogoutCommand
public class LogoutCommand
{
readonly IApp _app;
public LogoutCommand(IApp app)
{
_app = app;
}
public void Execute()
{
_app.UserLogout();
}
}
l'implementazione ItemProcessor
potrebbe chiamare logoutCommand.Execute()
.
Ciò disaccoppia il ItemProcessor
dalla conoscenza di App
, ma ho lo stesso problema perché quando App
c-tor chiama ItemProcessor
c-tor che chiama LogoutCommand
che chiama App
c-tor.
Un'altra (cattiva) idea: pensavo che una fabbrica potesse alleviare questo problema. Ho pensato di avere un ILogoutCommandFactory
factory che crea LogoutCommand
. Finché non ho creato LogoutCommand
nel c-tor di ItemProcessor
, ho pensato che potesse funzionare. Ma il fatto che io non possa farlo, mi sembra l'odore del codice.
A me DI in c-tor sembra iniziare come un problema.