Domanda

Sto creando un oggetto per cercare gli ordini nel mio database. Ci sono un sacco di possibili parametri che l'utente può impostare e ne possono impostare quanti ne vogliono per ogni ricerca. Ho creato metodi setter per raccogliere tutti i parametri necessari per la ricerca.

La mia domanda è questa. Quali sarebbero le "migliori pratiche"

  1. Memorizzazione dei parametri e creazione della clausola WHERE quando viene chiamato il metodo doSearch
  2. Creazione della clausola WHERE come parametri impostati

Mi piacerebbe capire il motivo dietro ogni raccomandazione.

Si noti che l'oggetto è istativato per ogni ricerca, quindi non devo preoccuparmi di una seconda ricerca con parametri diversi.

È stato utile?

Soluzione

È necessario separare il codice per la ricerca dell'ordine dal codice che genera l'SQL. L'SQL dovrebbe essere costruito in una derivata (o Strategia derivata) del OrderSearch classe. Una volta effettuata questa separazione, non importa in realtà quando si crea l'SQL.

Per renderlo un po 'più semplice. Data una classe chiamata OrderSearch che ha un sacco di metodi setter per i criteri di ricerca, ti piacerebbe avere una sottoclasse denominata OrderSearchSQLBuilder . Notare che la sottoclasse dipende dalla classe base e che la classe base è indipendente dalla sottoclasse. Questo è molto importante. Questa indipendenza consente di ignorare se l'SQL è incorporato nei metodi setter o nel metodo di ricerca. Vedi The Dependency Inversion Principle (DIP) .

Una volta ottenuto questo tipo di separazione, è possibile sostituire il derivato con altre strategie. Ad esempio, se si desidera testare l'applicazione senza collegarla al database SQL, è possibile creare un database fittizio in-ram e creare una derivata di OrderSearch che si occupi di quel database fittizio. Il resto dell'applicazione sarebbe beatamente inconsapevole e i tuoi test sarebbero quindi indipendenti dagli orrori delle connessioni al database, dati preesistenti, ecc.

Altri suggerimenti

Nel tuo metodo, usa semplicemente i parametri nel tuo SQL dinamico che esegue la ricerca. In questo modo la clausola where viene creata appena prima che SQL venga eseguito. Passerai semplicemente i parametri di ricerca nel tuo metodo come argomenti.

Qualcosa del genere ...

<cffunction name="getByAttributesQuery" access="public" output="false" returntype="query">
    <cfargument name="id" type="numeric" required="false" />
    <cfargument name="userName" type="string" required="false" />
    <cfargument name="firstName" type="string" required="false" />
    <cfargument name="lastName" type="string" required="false" />
    <cfargument name="createdAt" type="date" required="false" />
    <cfargument name="updatedAt" type="date" required="false" />
    <cfargument name="orderby" type="string" required="false" />

    <cfset var qList = "" />        
    <cfquery name="qList" datasource="#variables.dsn#">
        SELECT  
            id,
            userName,
            firstName,
            lastName,
            createdAt,
            updatedAt
        FROM    users
        WHERE       0=0
    <cfif structKeyExists(arguments,"id") and len(arguments.id)>
        AND id = <cfqueryparam value="#arguments.id#" CFSQLType="cf_sql_integer" />
    </cfif>
    <cfif structKeyExists(arguments,"userName") and len(arguments.userName)>
        AND userName = <cfqueryparam value="#arguments.userName#" CFSQLType="cf_sql_varchar" />
    </cfif>
    <cfif structKeyExists(arguments,"firstName") and len(arguments.firstName)>
        AND firstName = <cfqueryparam value="#arguments.firstName#" CFSQLType="cf_sql_varchar" />
    </cfif>
    <cfif structKeyExists(arguments,"lastName") and len(arguments.lastName)>
        AND lastName = <cfqueryparam value="#arguments.lastName#" CFSQLType="cf_sql_varchar" />
    </cfif>
    <cfif structKeyExists(arguments,"createdAt") and len(arguments.createdAt)>
        AND createdAt = <cfqueryparam value="#arguments.createdAt#" CFSQLType="cf_sql_timestamp" />
    </cfif>
    <cfif structKeyExists(arguments,"updatedAt") and len(arguments.updatedAt)>
        AND updatedAt = <cfqueryparam value="#arguments.updatedAt#" CFSQLType="cf_sql_timestamp" />
    </cfif>
    <cfif structKeyExists(arguments, "orderby") and len(arguments.orderBy)>
        ORDER BY #arguments.orderby#
    </cfif>
    </cfquery>

    <cfreturn qList />
</cffunction>

Non creare la clausola where prima che sia necessaria per eseguire la ricerca. Potresti finire con un'interfaccia utente che alimenta i parametri nelle iterazioni e non sai quando hai tutto. Inoltre, potresti non eseguire mai la ricerca, quindi perché preoccuparti della clausola where.

Non penso che faccia molta differenza, ma penso che sia meglio fare pratica per creare la clausola WHERE quando fai la ricerca. Non credo che dovrebbe essere la responsabilità di un setter per un parametro da aggiungere a una stringa della clausola WHERE da qualche parte.

Su un database SQLServer è più efficiente includere tutti i parametri nella clausola where anziché crearla al volo. Quindi disporre di un indice del database che includa tutte le colonne su cui si cercherà. Ciò garantisce che l'indice venga sempre utilizzato durante l'esecuzione dell'istruzione.

Non sembra che la tua astrazione sia corretta.

La ricerca potrebbe essere migliore come metodo di un "ordine". oggetto. passa i parametri alla funzione di ricerca e crea la query manualmente come russ suggerito . Tutto ciò che è specifico degli ordini piuttosto che la ricerca può quindi essere impostato sul metodo init ordini.

È possibile che tu voglia creare un oggetto di ricerca ordini, ma ciò dovrebbe essere fatto tramite un oggetto ordini, per mantenere semplice il tuo codice front-end.

L'opzione 1 è la soluzione migliore. L'opzione 2 sembra pericolosa. Cosa succede se un parametro viene aggiornato? Come lo si sostituisce nella clausola WHERE?

Vorrei fare qualcosa del genere:

<cffunction name="doSearch" access="public" output="false" returntype="query">        
    <cfset var qList = "" />
    <cfquery name="qList" datasource="#variables.dsn#">
       SELECT
           ...
       FROM
           ...
       WHERE 0=0 
         <cfif len(getID())>
           AND id = <cfqueryparam value="#getID()#" CFSQLType="cf_sql_integer" />
         </cfif>       
         <cfif len(getUserName())>
           AND userName = <cfqueryparam value="#getUserName()#" CFSQLType="cf_sql_varchar" />
         </cfif>
    </cfquery>
    <cfreturn qList />
</cffunction>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top