Solution Sprawl: Move Creation Knowledge to Factory

Continuiamo con lo smell: Solution Sprawl 
 

Problema:

La creazione di un oggetto avviene recuperando dati e codice in giro per il nostro progetto.

 

Motivazione:

Quando la creazione di un oggetto avviene tramite il passaggio di più classi si ha uno smell di tipo creation sprawl (Code Smells), questo tipo di smell nasce da un design dell’applicazione nato troppo presto (questo capita quando siamo convinti che l’analisi del sistema possa essere completa e corretta al 100%).

 

Un esempio di logica errata:
Il client ha bisogno di un oggetto Button che deve essere disegnato a seconda del sistema operativo.
L’oggetto Button per essere disegnato deve chiamare il metodo toPaint
e passarne il tipo (se bottone di tipo Windows o Linux) ed eventuali settaggi che variano a seconda dell’OS.

Il metodo toPaint chiamera il FindOS della classe OS dopo averla istanziata e configurata con i dati passati sopra.

La classe OS istanziera un nuovo oggetto OSType tramite il metodo createOS e quest’ultima classe tornerà il tipo a noi necessario, cioè un Button per il nostro sistema operativo.

Questo esempio potrebbe sembrare assurdo ma capita spesso, sopratutto quando si parla di creazioni di Query SQL.

Soluzione:

Il pattern Factory, in questo contesto, ci viene in aiuto.
Tramite questo pattern riusciamo a rinchiudere, in una classe, la logica di creazione dell’oggetto e le configurazioni richieste dal client.

Se le opzioni di creazione dell’oggetto diventano troppe allora si potrà passare al pattern Abstract Factory.

Siamo liberi di decidere se la loro implementazione dovrà seguire delle interfacce (in modo tale da lasciar liberi gli altri utenti dal conoscere la nostra classe) e se il client deve occuparsi di chiamare un ConcreteFactory method per creare l’oggetto o farlo fare a runtime.

Per Joshua Kerievsky un pattern Factory è un qualsiasi oggetto che implementa uno o più Creation Methods. E noi terremo per buona questa definizione

 

Ecco alcuni esempi:

 

Benefici e non
+ Consolida la logica della creazione e della configuraizone.
+ Disaccoppia la logica della creazione.
- Complica il design se mal utilizzato.

Il codice seguente è preso dall’esempio di Wikipedia.
Di esempi se ne potrebbero fare molteplici, ma quello di Wikipedia (IMVHO) è il più esplicativo.

using System;

namespace Abstract
{
    class MainApp
    {
        public static void Main()
        {
            string os = "WINDOWS";

            IGUIFactory gui;
            IButton button;

            switch (os)
            {
                case "LINUX":
                    gui = new LinuxFactory();
                    button = gui.CreateButton();
                    break;

                case "WINDOWS":
                default:
                    gui = new WindowsFactory();
                    button = gui.CreateButton();
                    break;
            }

            button.Paint();

            Console.ReadKey();
        }
    }

    interface IButton
    {
        void Paint();
    }

    interface IGUIFactory
    {
        IButton CreateButton();
    }

    class WindowsButton : IButton
    {

        #region IButton Members

        public void Paint()
        {
            Console.WriteLine("Io disegno il pulsante di Zio Bill");
        }

        #endregion
    }

    class WindowsFactory : IGUIFactory
    {
        #region IGUIFactory Members

        public IButton CreateButton()
        {
            return new WindowsButton();
        }

        #endregion
    }

    class LinuxButton : IButton
    {
        #region IButton Members

        public void Paint()
        {
            Console.WriteLine("Io disegno il pulsante di Linus Torvalds");
        }

        #endregion
    }

    class LinuxFactory : IGUIFactory
    {
        #region IGUIFactory Members

        public IButton CreateButton()
        {
            return new LinuxButton();
        }

        #endregion
    }
}
 

abstract_factory_class_diagram

Credo che la semplicità di questo codice rapportata all’esempio di come si potrebbe scrivere con una logica errata o, per meglio dire, con un’altra logica è lapalissiana.

Pensata come sarebbe facile tornare su questo codice ed aggiungere la gestione per Button per un’altro sistema operativo; basterebbe aggiungere un SistemaOperativoNuovoFactory e un SistemaOperativoNuovoButton.

E non prendete come scusa: “il mio sistema ormai è troppo evoluto per poterne apportare queste migliorie. E’ troppo tardi.”

Se fosse realmente così non esisterebbe il Refactoring :)

Per questi post sto prendendo, molto, spunto da libro Refactoring To Patterns di Joshua Kerievsky.

Error: The language-neutral solution package was not found

Altro giro altro errore sul deploy di un progetto WebPart:

Error: The language-neutral solution package was not found

La solutione l'ho trovata quì:
http://www.mindsharpblogs.com/aaron/archive/2007/08/23/2603.aspx

In pratica nel file solution.xml il nome del progetto da deployare è diverso da quello che avete nella solution.

  1. Chiudete Visual Studio
  2. Modificate il file solution.xml
  3. Riaprite il progetto e deployate

 

VSeWSS Service Error: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

Sto utilizzando Visual Studio 2008 extensions for Windows SharePoint Services 3.0, v1.3 - Mar 2009 CTP per deployare una WebPart come Provider.

Questa ha la sua interfaccia in un'altro progetto (Class Library).

Quando deployio ricevo il seguente errore:

VSeWSS Service Error: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

Togliendo l'implementazione dell'interfaccia, tutto ricominciare a funzionare...

Soluzione 0.5 beta:

Linkare la dll non il progetto (pessima soluzione)

Sembra che, settata correttamente la dll nel file solution.xml, rimuovendo la vecchia dalla GAC e rideployando, insernedo questa volta il progetto nelle reference, il deploy funzioni.

Soluzione 1.0 beta:

Questa soluzione sembra funzionare:

http://oidatsmyleg.wordpress.com/2009/01/28/problems-with-vsewss/

 

Symptoms include constantly encountering this error:

Unable to load one or more of the requested types.
Retrieve the LoaderExceptions property for more information.

I’m using the CTP release of VSeWSS 1.3 for Visual Studio 2008 although the error was also evident using version 1.2.

Update: I’ve found that adding the referenced assemblies to the GAC, resetting IIS then Clean the project in Visual Studio fixes this issue.
I can’t reclaim the hours lost but perhaps this information will help someone else.