Quale schema di progettazione corrisponde a questo problema il più vicino?

1

Ho due oggetti, uno è un oggetto Utente e l'altro è un oggetto Contenuto. L'oggetto Utente ha proprietà come "reads_articles" o "reads_books". L'oggetto Contenuto ha proprietà come "is_article" o "is_book". Se le due proprietà coincidono (vale a dire l'utente reads_articles e il contenuto è_article), l'utente può vedere il contenuto. Fondamentalmente, sto cercando la migliore soluzione per avvicinarmi a questo senza usare un'istruzione switch ().

Mi sto anche chiedendo se forse sto rendendo questo troppo difficile e / o un modello di design è eccessivo qui. La ricerca preliminare ha suggerito che il modello di strategia potrebbe essere il più appropriato, ma mi trovo in difficoltà a modellare questo problema su tale modello. Non voglio eseguire il codice in modo rigido per i test: mi piacerebbe davvero trovare una soluzione generale che esamina le proprietà di entrambe le classi e determina se il Contenuto può essere visualizzato da quell'utente.

Chiarimento: il mio obiettivo finale è un algoritmo che esaminerà le proprietà dell'utente e le proprietà del contenuto e verificherà se corrispondono. Fondamentalmente, voglio vedere se i due oggetti hanno proprietà corrispondenti (senza codificare le proprietà stesse nell'algoritmo) e fare alcune azioni.

Non sono sicuro che quello che voglio sia un sogno irrealizzabile, quindi ho pensato di chiederlo. Grazie per l'aiuto!

    
posta JRizz 23.12.2013 - 22:50
fonte

2 risposte

1

Basically, I want to see if the two objects have matching properties (without hardcoding the properties themselves into the algorithm) and do some actions.

Sì, questo aiuta. La risposta basata sull'ipotesi che ho iniziato non sarebbe stata sufficiente. Ma KISS - mantenerlo semplicemente stupido - si applica ancora qui, IMO. Tenerlo breve e al punto, non è necessario forzarlo in un modello di progettazione se non si adatta naturalmente.

Consente di utilizzare una funzione di linguaggio speciale a nostro vantaggio. PHP consente di chiamare l'accesso dinamico agli attributi, con i nomi memorizzati come stringhe nelle variabili. Spesso è disapprovato in PHP, ma a volte è anche la soluzione più semplice. Ad esempio, in questo pseudocodice:

$attribs = array(
   array('User' => 'reads_articles', 'Content' => 'is_article'),
   array('User' => 'reads_books', 'Content' => 'is_book'),
);

class User {
   function can_access(Content) {
      foreach ($attribs as $reqs) {
         if (!property_exists(self, $reqs['User'])) {
            throw Exception("User is missing {$reqs['User']}");
         }
         if (!property_exists(Content, $reqs['Content'])) {
            throw Exception("Content is missing {$reqs['Content']}");
         }
         if (self->{$reqs['User']} && Content->{$reqs['Content']}) {
            return true;
         }
      }
      return false;
   }

   reads_articles = true;
   reads_books = true;
}

(Attenzione: non verificato, e so di avere una parte della sintassi errata (come ad esempio non nominare l'argomento Content, e dubito che lo scope sia giusto)).

Ci sono 3 possibili fonti per $attribs a cui posso pensare. Ecco alcuni ulteriori pensieri su ciascuno:

  • Hardcoded nella sorgente, come sopra
    • Vantaggi: è proprio lì . Per la manutenzione, è molto facile vedere da dove proviene. Anche in un altro file, non devi cambiare mentalmente il contesto per ottenerlo.
    • Svantaggi: è statico. Tutte le classi User e Content devono definire ogni singolo, a meno che can_access non venga modificato per accettare che "mancante" significhi "falso".
  • Caricato da una tabella di database
    • Vantaggi: In parole semplici, è molto più flessibile e più facile da estendere in futuro poiché l'interfaccia per utilizzare il database è già presente.
    • Svantaggi: leggendo il codice, ora devi anche guardare il database per capire quali attributi saranno usati insieme. È anche più facile trascurarlo quando ne aggiungi uno nuovo.
  • Derivato dal riflesso, esaminando le classi
    • Vantaggi: i nuovi attributi sono inclusi automaticamente e le "regole" per determinare quali vanno insieme sono piuttosto semplici.
    • Svantaggi: le regole per l'associazione degli attributi potrebbero essere skin-deep ( is_letter / sends_letters non si adatta, per esempio), e c'è la possibilità che possano eguagliare qualcosa che non dovrebbero comunque. La programmazione "Meta" come questa è anche meno ovvia delle altre due, dal momento che tende ad essere usata meno spesso, quindi dovrebbe essere documentata abbastanza bene.

Gli svantaggi dell'utilizzo di un database sono così limitati che è così che andrei con esso, a meno che non fossi molto sicuro che questo insieme di attributi fosse improbabile che cambiasse o che il progetto non avesse già un database - quindi potrei vai con la prima opzione, hardcoding da qualche parte. Almeno con esso già in una forma semi-tabulata del genere, sarebbe semplice convertire in una tabella di database, se necessario.

Il fatto di dedurlo attraverso il pattern matching deve essere molto ben definito, quindi lo eviterei il più possibile. IMO rientra nella categoria "trucco ordinario" che raramente è più utile di altri metodi, fa alla possibilità di falsi positivi e probabilmente richiede documentazione aggiuntiva.

Ora, c'è un'opzione a metà strada che penso dovrebbe essere usata al posto degli attributi direttamente sulla classe:

class User {
   $permissions = array(
      'reads_articles' => true,
      'reads_books' => true,
   );
}

In questo modo, non c'è sovrapposizione con i normali attributi utente, ed è ovvio quali sono importanti. Le avvertenze su come per accoppiarle con quelle sul contenuto sono ancora valide, quindi uno dei precedenti 3 metodi sarebbe ancora necessario. Tuttavia, dalla domanda, non sono sicuro se ciò funzionerebbe per quello che hai in mente.

(Nota a margine, poiché potrebbe non essere ovvio - sto cercando di mantenere questo aspetto leggermente generico, dal momento che non sono sicuro che le autorizzazioni di cui parli siano a livello di classe o di istanza. di quanto sopra può essere fatto in entrambi i modi.)

    
risposta data 23.12.2013 - 23:54
fonte
1

Puoi verificare se un elemento è membro di un set utilizzando in_array .

Quindi, ad esempio, se il tuo utente legge articoli e libri, la matrice "legge queste cose" dell'oggetto utente conterrà "articoli" e "libri" (o il loro equivalente numerico codificato), e puoi avere un metodo sul user oggetto chiamato ReadsContent() che accetta un tipo di contenuto come parametro e restituisce vero o falso in base al fatto che quel tipo di contenuto sia in_array .

    
risposta data 23.12.2013 - 22:59
fonte

Leggi altre domande sui tag