2017-10-02 4 views
0

Je lis partout que si les instructions/switch sont mieux évitées dans la plupart des cas avec la POO. Mon problème est de savoir comment éviter une instruction switch lors du codage d'un login.Comment éviter les conditions pour un login?

J'ai une structure MVP et un client lors de la connexion sera redirigé vers la vue appropriée en fonction du type de client qui est défini par une énumération. Donc, si le client est de type client '0', alors ils devraient être redirigés vers la page d'accueil du client, si le type de client est '1', alors ils devraient être redirigés vers la page d'accueil de l'administrateur ect ... Ma première pensée est qu'il devrait y avoir quelques classes client-login qui sont créées quand un nom d'utilisateur valide et un mot de passe sont soumis. Ces classes pourraient chacun avoir une méthode de redirection spécifique - quelque chose comme classe client-login, classe admin-connexion etc ...

Le problème est maintenant que mon LoginPresenter est celui qui appelle les méthodes de redirection qui appartiennent au LoginView via la vue Interface.

Si mon modèle renvoyait une classe de connexion client au Presenter, comment la classe de connexion client aurait-elle accès aux méthodes de redirection LoginViews?

Il me semble que le présentateur est la seule classe capable d'appeler les méthodes de redirection, donc je suis un peu déconcerté comment je devrais procéder. J'ai besoin d'un moyen pour que la classe de connexion client indique au présentateur la méthode de redirection à appeler.

Voici le code tel qu'il est maintenant dans le présentateur ...

public class LoginPresenter : PresenterBase 
{ 

    private readonly ILoginView _view; 

    private readonly ILoginModel _model; 

    private ClientType _clientType; 

    public LoginPresenter(ILoginView view, ILoginModel model) 
    { 

     _view = view; 

     _model = model; 

     _view.LoginAttempt += OnLoginAttempt; 

    } 

    private void OnLoginAttempt(object sender, EventArgs e) 
    { 

     AttemptLogin(); 

    } 

    public void AttemptLogin() 
    { 

     string email = _view.Email; 

     string password = _view.Password; 


     bool ClientExists = _model.CheckClientExists(email, password); 
     if (ClientExists) 
     { 

      _clientType = (ClientType)_model.GetClientType(); 

      CheckClientType(); 

     } 
     else 
     { 

      _view.Message = "Login Failed"; 

     } 

    } 

    private void CheckClientType() 
    { 

     switch (_clientType) 
     { 

      case ClientType.Customer: 
       _view.RedirectToCustomerHomePage(); 
       break; 
      case ClientType.Operator: 
       _view.RedirectToOperatorHomePage(); 
       break; 
      case ClientType.Admin: 
       _view.RedirectToAdminHomePage(); 
       break; 

     } 

    } 

Bien sûr, cela fonctionne avec le boîtier de l'interrupteur, mais ce n'est pas très approche orientée objet. Avoir à demander au modèle de fournir le type de client et ensuite vérifier le type de client me fait mal quand je pourrais obtenir le modèle pour me donner un objet capable de dire au présentateur ce dont il a besoin - je sais qu'il manque quelque chose ici.

Je serais très reconnaissant pour toute l'aide ou des conseils: D

+0

Lit le modèle de stratégie. – Nkosi

+0

Merci! Est-ce que le modèle de stratégie peut gérer le problème concernant la façon d'obtenir la redirection appelée dans la vue? C'est le problème majeur pour moi - les exemples que j'ai trouvés jusqu'ici ont tous des sous-classes appelant des méthodes qui ne reposent pas nécessairement sur une classe externe comme une vue. Ceux que j'ai trouvés sont généralement pour calculer une valeur ou retourner une chaîne. Quel pourrait être le mécanisme pour déclencher la bonne redirection? – Chi

+0

Vous devrez fournir plus de code et mieux expliquer le scénario dans un [mcve] qui peut être utilisé pour représenter votre problème. – Nkosi

Répondre

1

Je vais faire une hypothèse selon laquelle un ORM est impliqué ici. Si tel est le cas, une classe abstraite simple fonctionnera. Si le type du client est une propriété dans la base de données (lire: colonne) alors nous pouvons essentiellement résumer ce type à une hiérarchie de classes.

public abstract class Client 
{ 
    public abstract void LoginRedirect(ILoginView view); 
} 

public class Customer : Client 
{ 
    public void LoginRedirect(ILoginView view) 
    { 
     view.RedirectToCustomerHomePage(); 
    } 
} 

Avec une hiérarchie comme cela, je suggère que le code de connexion pourrait être modifié en tant que tel:

public void AttemptLogin() 
{ 
    Client client = _model.GetClient(_view.Email, _view.Password); 
    if (client != null) 
    { 
     client.LoginRedirect(_view); 
    } 
    else 
    { 
     _view.Message = "Login Failed"; 
    } 
} 

Dans ce cas, la méthode getClient retournerait une instance réelle du client au lieu d'un booléen . Si null est renvoyé, vous savez que la connexion a échoué.

+0

Merci! Je vais essayer d'utiliser cette première chose demain - il ressemble à une excellente solution. Je suppose que la classe abstraite et ses implémentations doivent exister dans le même assemblage que le modèle - avec une référence à l'assembly qui contient les interfaces de vue? – Chi

+0

Je ne suis pas sûr de la façon dont votre projet est mis en place, mais cela semble fonctionner. Je ne pense pas vraiment que ce soit la meilleure solution car cela crée une dépendance de votre modèle client sur la vue, mais quelque chose comme ça pourrait être ce que vous finissez avec. –

+0

hmmm, bon point - le but principal de l'utilisation de mvp est de découpler autant que possible. Mais le modèle référençant l'interface de vue provoque-t-il un couplage étroit à la vue? J'étais sous l'impression que c'était encore considéré comme un couplage lâche si c'était seulement l'interface qui était la dépendance mais peut-être pas? Pensez-vous que l'instruction switch est en fait une solution préférable dans ce cas? – Chi