2009-01-06 8 views
3

Donc, je suis en train de refactoriser une base de code héritée dont j'ai hérité, et dans le processus j'ai trouvé une classe statique qui encapsule la logique de lancement des applications tierces. Il semble essentiellement comme ceci (raccourci par souci de concision seulement montrer une application):.NET Class Refactoring Dilemma

using System.IO; 
using System.Configuration; 
public static class ExternalApplications 
{ 

    public string App1Path 
    { 
     get 
     { 
     if(null == thisApp1Path) 
      thisApp1Path = Configuration.AppSettings.Get("App1Path"); 
     return thisApp1Path; 
     } 
    } 
    private string thisApp1Path = null; 

    public bool App1Exists() 
    { 
     if(string.IsNullOrEmpty(App1Path)) 
     throw new ConfigurationException("App1Path not specified."); 
     return File.Exists(App1Path); 
    } 

    public void ExecuteApp1(string args) 
    { 
     // Code to launch the application. 
    } 

} 

C'est une tentative bien de séparer les applications externes du reste du code, mais il me semble que cela aurait pu être refondus plus loin. Ce que je pense à quelque chose comme ceci:

using System.IO; 
public abstract class ExternalApplicationBase 
{ 

    protected ExternalApplicationBase() 
    { 
     InitializeFromConfiguration(); 
    } 

    public string Path { get; protected set; } 

    public bool Exists() 
    { 
     if(string.IsNullOrEmpty(this.Path)) 
     throw new ConfigurationException("Path not specified."); 
     return File.Exists(this.Path); 
    } 

    public virtual void Execute(string args) 
    { 
     // Implementation to launch the application 
    } 

    protected abstract InitializeFromConfiguration(); 

} 

public class App1 : ExternalApplicationBase 
{ 

    protected virtual void InitializeFromConfiguration() 
    { 
     // Implementation to initialize this application from 
     // the application's configuration file. 
    } 

} 

public class App2 : ExternalApplicationBase 
{ 

    protected virtual void InitializeFromConfiguration() 
    { 
     // Implementation to initialize this application from 
     // the application's configuration file. 
    } 

} 

Mes préoccupations sont les suivantes:

  1. Une classe, une interface ou une autre construction peut déjà exister qui fait cela, et je viens havre de paix » J'ai trébuché dessus.

  2. Il peut être exagéré pour ce que je veux faire. Notez, cependant, que l'application utilise au moins trois applications tierces distinctes que j'ai identifiées jusqu'à présent (et d'autres sont presque certaines à apparaître). Je ne suis pas tout à fait à l'aise avec le nom de la classe de base.

  3. Cela semble flou, et pas très instructif (mais je ne pourrais pas penser beaucoup mieux, étant donné que l'Application est déjà bien définie, réservée par le Cadre, et créerait un niveau de confusion grossier si je l'utilisais). L'idée est que je veux pouvoir conserver les données de configuration de l'application (son chemin et son nom) dans le fichier App.Config et vérifier son existence au démarrage de l'application; Lorsque mon logiciel a besoin de lancer le logiciel, je veux le faire via un seul appel de méthode, et ne pas avoir de lignes de commande de construction de code et essayer de lancer le logiciel manuellement (comme c'est le cas actuellement).

Je vous envoie donc une demande d'aide, de conseils et de suggestions. Tout ce que vous pouvez proférer est grandement apprécié.

P.S. Je pose cette question ici parce que je travaille, comme je le fais souvent, en tant que développeur unique dans mon entreprise; Je n'ai personne d'autre pour faire rebondir ces idées. Vous avez beaucoup d'expérience avec ce genre de choses, et il serait stupide de ma part de ne pas demander vos conseils, alors j'espère que vous me supporterez tous. Merci d'avance!

Répondre

2

Voici une autre façon de refactorisation ceci:

using System.IO; 
public class ExternalApplication 
{ 
    public ExternalApplication(string path) 
    { 
     this.Path = path; 
    } 

    public string Path { get; protected set; } 

    public bool Exists() 
    { 
     if(string.IsNullOrEmpty(this.Path)) 
     throw new ConfigurationException("Path not specified."); 
     return File.Exists(this.Path); 
    } 

    public void Execute(string args) 
    { 
     // Implementation to launch the application 
    } 
} 

public class AppFactory 
{ 
    public ExternalApplication App1() 
    { 
     // Implementation to initialize this application from 
     // the application's configuration file. 
    } 

    public ExternalApplication App2() 
    { 
     // Implementation to initialize this application from 
     // the application's configuration file. 
    } 

    public ExternalApplication AppFromKey(string key) 
    { 
     // get from somewhere 
    } 
} 

Dans ce cas, vous avez un seul type ExternalApplication et une usine qui a des méthodes le retour une application correctement configurée pour vous.

+0

J'avais prévu d'utiliser une usine de toute façon; mais cela élimine assez bien les types dérivés inutiles. J'ai juste besoin d'ajouter une propriété supplémentaire pour gérer si elle doit ou non fonctionner de manière asynchrone, et une propriété pour son nom. Merci! –

+0

Je pourrais vouloir déplacer où l'exception ConfigurationException est lancée, bien que ... –

0

Cela me semble raisonnable.

J'ai fait quelque chose de similaire dans le passé, mais je n'avais pas de classe de base abstraite. Au lieu de cela j'ai passé dans le chemin d'application dans le constructeur.

+0

J'ai pensé à faire cela, mais certaines des applications que nous voulons exécuter de manière synchrone, et d'autres de manière asynchrone. D'où la nécessité de surcharger Execute. –

+0

Si je n'avais pas prévu de surcharger Execute de cette façon, je pourrais sortir avec une seule classe, et simplement passer l'information lors d'un événement d'initialisation de configuration. Mais de cette façon, j'obtiens une sorte d'objet d'application Excel ou PKZip sécurisé. –

0

Je suis d'accord avec @Grauenwolf que cela semble raisonnable. En fonction des points communs, vous pouvez fournir un mécanisme pour encapsuler la récupération de configuration (un moyen de sortir/définir des arguments de ligne de commande) ou comment exécuter l'application (Sync ou ASync).

  1. Si vous en trouvez un qui existe déjà, essayez de l'entourer et continuez.
  2. Il n'y a pas trop d'efforts dans l'ajout de cette couche supplémentaire et contribue à améliorer les problèmes d'application distincts. Je pense que c'est bon et peut aider améliorer testabilité par le biais de moqueurs.
  3. AppLauncherBase ou AppExecutorBase? Il n'y a aucune raison pourquoi l'application doit être externe. Pas les meilleurs noms jamais inventés mais j'essayerais d'encapsuler le but de la classe, lancer/exécuter des applications.
  4. Vous pouvez envisager d'utiliser une convention pour définir les données de configuration/informations sur le chemin d'application dans App.Config, puis implémenter la logique de récupération dans la classe de base par défaut.

Bonne chance et j'espère que cela aide.