PHP: quando utilizzare gli array e quando utilizzare gli oggetti per la maggior parte dei costrutti di codice di memorizzazione dei dati?

30

PHP è un linguaggio di paradigmi misto, che consente di utilizzare e restituire tipi di dati non oggetto, come gli array. Faccio una domanda per cercare di chiarire alcune linee guida per la selezione di array vs oggetti al momento di decidere quale costrutto di programmazione utilizzare in una particolare situazione.

Questa è davvero una domanda sui modi per codificare i dati usando i costrutti del linguaggio PHP e quando è più probabile che un modo venga scelto su un altro per scopi di trasmissione dati (ad esempio architettura orientata ai servizi o servizi web).

Esempio

Supponiamo di avere un tipo di oggetto composto da {costo, nome, numero_parte, numero_articolo}. Il tuo programma richiede la visualizzazione di diversi di questi tipi di elementi, in cui decidi di utilizzare un array come contenitore esterno per contenere ciascuno dei tipi di elementi. [Puoi usare anche ArrayObject di PHP per il paradigma OO, ma la mia domanda non riguarda quella (esterna) matrice]. La mia domanda è su come codificare i dati del tipo di oggetto e su quale paradigma utilizzare. PHP ti permette di usare PHP Native Arrays o PHP Objects .

Posso codificare questi dati, in due modi qui, in questo modo:

//PHP's associative arrays:
$ret = array(
    0 => array(
        'cost' => 10.00, 
        'name' => 'item1',
        'part_number' => 'zyz-100', 
        'item_count' => 15
        ),
    1 => array(
        'cost' => 34.00, 
        'name' => 'item2', 
        'part_number' => 'abc-230', 
        'item_count' => 42
        ),
  );

vs

//here ItemType is encapsulated into an object
$ret = array(
  0 => new ItemType(10.00, 'item1', 'zyz-100', 15),
  1 => new ItemType(34.00, 'item2', 'abc-230', 42),
);

class ItemType
{
    private $price;
    private $name;
    private $partNumber;
    private $itemCount;

    function __construct($price, $name, $partNumber, $itemCount) {..}
}

Cosa sto pensando

La codifica di array è leggera e più pronta per JSON, ma può essere più facile rovinarla. Misspell una delle chiavi di array associativo e potresti avere un errore che è più difficile da individuare. Ma è anche più facile cambiare su un capriccio. Supponiamo che non voglia più memorizzare item_count , posso utilizzare qualsiasi software di elaborazione del testo per rimuovere facilmente tutte le istanze di item_count nell'array e quindi aggiornare altre funzioni che lo utilizzano di conseguenza. Potrebbe essere un processo più noioso, ma è semplice.

La codifica orientata agli oggetti richiama le strutture del linguaggio IDE e PHP e rende più facile rilevare eventuali errori in anticipo, ma è più difficile da programmare e codificare in primo luogo. Dico più strong, perché devi pensare un po 'ai tuoi oggetti, pensare al futuro, e la codifica OO richiede un carico cognitivo un po' più alto rispetto alla tipizzazione delle strutture di array. Detto questo, una volta che è stato codificato, alcune modifiche potrebbero essere più facili da implementare, in un certo senso, che la rimozione di item_count , ad esempio, richiederà la modifica di meno righe di codice. Ma i cambiamenti stessi possono ancora richiedere un carico cognitivo più elevato rispetto al metodo dell'array, poiché sono coinvolte strutture OO di livello superiore.

Domanda

In alcuni casi è chiaro, come i casi in cui dovrò eseguire manipolazioni sui dati. Ma in alcuni casi, dove ho bisogno di archiviare solo poche righe di dati di tipo "Articolo tipo", non ho linee guida o considerazioni chiare su cui basarsi per decidere se utilizzare gli array o se costruire oggetti. Sembra che posso solo lanciare una moneta e sceglierne una. È questo il caso qui?

    
posta Dennis 08.09.2015 - 21:26
fonte

2 risposte

26

Il modo in cui vedo questo, dipende da cosa intendi fare con i dati in seguito. Basandoti su alcuni semplici controlli, puoi determinare quale delle due strutture dati è migliore per te:

  1. Questi dati hanno una logica associata?

    Ad esempio, $price è memorizzato come numero intero di centesimi, quindi un prodotto con un prezzo di $ 9,99 avrebbe price = 999 e non price = 9.99 ? (Probabilmente, sì) O partNumber deve corrispondere a un'espressione regolare specifica? Oppure, è necessario essere in grado di verificare facilmente se itemCount è disponibile nel tuo inventario? Avrai bisogno di fare queste funzioni in futuro? Se è così, allora la soluzione migliore è creare una classe ora. Ciò significa che è possibile definire vincoli e logica incorporati nella struttura dati: private $myPrice è impostato su 999 ma $item->getPriceString() restituisce $9.99 e $item->inStock() è disponibile per essere chiamato nella propria applicazione.

  2. Passerai questi dati a più funzioni PHP?

    Se è così, allora usa una classe. Se stai generando questi dati una volta per eseguire alcune trasformazioni su di esso, o semplicemente per inviare come dati JSON a un'altra applicazione (JavaScript o altro), allora un array è una scelta più semplice. Ma se hai più di due funzioni PHP che accettano questi dati come parametro, usa una classe. Se non altro, ciò ti consente di definire someFunction(MyProductClass $product) { ed è molto chiaro ciò che le tue funzioni si aspettano come input. Man mano che ridimensiona il tuo codice e disponi di più funzioni, sarà molto più facile sapere quale tipo di dati accetta ogni funzione. Vedere someFunction($someArrayData) { non è altrettanto chiaro. Inoltre, questo non impone l'uniformità del tipo e significa che (come hai detto tu) la struttura flessibile dell'array può causare dolore in seguito allo sviluppo

  3. Stai creando una libreria o un codebase condiviso?

    Se è così, usa una classe! pensa a qualche nuovo sviluppatore che sta usando la tua libreria o un altro sviluppatore da qualche altra parte della società che non ha mai usato il tuo codice prima. Sarà molto più facile per loro guardare una definizione di classe e capire cosa fa quella classe, o vedere un certo numero di funzioni nella libreria che accettano oggetti di una certa classe, piuttosto che cercare di indovinare quale struttura devono generare in una numero di array. Inoltre, questo tocca i problemi di coerenza dei dati con il n. 1: se stai sviluppando una libreria o una base di codice condivisa, sii gentile con i tuoi utenti: fornisci loro classi che rafforzano la coerenza dei dati e proteggono da errori nella progettazione dei tuoi dati .

  4. Questa è una piccola parte di un'applicazione o semplicemente una trasformazione dei dati? Non ti va bene in nessuno dei precedenti?

    Una classe potrebbe essere troppo; usa un array se ti va bene e lo trovi più facile. Come accennato in precedenza, se stai solo generando dati strutturati da inviare come JSON o YAML o XML o altro, non preoccuparti di una classe a meno che non sia necessario. Se stai scrivendo un piccolo modulo in un'applicazione più grande e nessun altro modulo / gruppo ha bisogno di interfacciarsi con il tuo codice, forse un array è sufficiente.

In definitiva, considera le esigenze di ridimensionamento del tuo codice e considera che una matrice strutturata potrebbe essere una soluzione rapida, ma una classe è una soluzione molto più resiliente e scalabile.

Inoltre, considera quanto segue: se hai una classe e vuoi eseguire l'output su JSON, non c'è ragione per cui non puoi definire un metodo json_data() della tua classe che restituisce una matrice JSON-ifiable dei dati in la classe. Questo è quello che ho fatto nelle mie applicazioni PHP in cui avevo bisogno di inviare dati di classe come JSON. Ad esempio:

class Order {
    private $my_total;
    private $my_lineitems;

    public function getItems() { return $this->my_lineitems; }
    public function addItem(Product $p) { $this->my_lineitems[] = $p; }
    public function getTotal() { return $this->my_total; }

    public function forJSON() {
        $items_json = array();
        foreach($this->my_lineitems as $item) $items_json[] = $item->forJSON();
        return array(
            'total' => $this->getTotal(),
            'items' => $items_json
        );
    }
}

$o = new Order();
// do some stuff with it
$json = json_encode($o->forJSON());
    
risposta data 12.09.2015 - 23:07
fonte
2

Puoi implementare la struttura json usando l'interfaccia JsonSerializable e usa in ogni modo array / classe nidificati. La classe è più veloce nelle operazioni get / set e più facile da eseguire il debug. Con Array non hai bisogno di dichiarazioni.

class Order implements \JsonSerializable{
    private $my_total;
    private $my_lineitems;

    public function getItems() { return $this->my_lineitems; }
    public function addItem(Product $p) { $this->my_lineitems[] = $p; }
    public function getTotal() { return $this->my_total; }

    public function jsonSerialize(){
        return [
            'total'=>$this->my_total,
            'products'=>$this->my_lineitems;
        ];
    }
}

class Product implements \JsonSerializable{
    private $name;
    private $price;

    public function jsonSerialize(){ 
        return [
            'name'=>$this->name, 
            'price'=>$this->price
        ];
    }
}

$order = new Order();
$order->addProduct(new Product('Product1', 15));
$order->addProduct(new Product('Product2', 35));
$order->addProduct(new Product('Product3', 42));
$json = json_encode(['order'=>$order, 'username'=>'Eughen']);
/*
json = {
    order: {
        total: 92, 
        products: [
            {
                name: 'Product1',
                price: 15
            }, 
            {
                name: 'Product2',
                price: 35
            },
            {
                name: 'Product3',
                price: 42
            }
        ]
    }, 
    username: 'Eughen'
}
*/
    
risposta data 04.06.2018 - 16:43
fonte

Leggi altre domande sui tag