PHP: kapan harus menggunakan array, dan kapan harus menggunakan objek untuk sebagian besar konstruk kode penyimpanan data?

37

PHP adalah bahasa paradigma campuran, memungkinkan untuk menggunakan dan mengembalikan tipe data non-objek, seperti array. Saya mengajukan pertanyaan untuk mencoba memperjelas beberapa pedoman untuk pemilihan array vs objek ketika memutuskan apa yang membangun pemrograman untuk digunakan dalam situasi tertentu.

Ini benar-benar sebuah pertanyaan tentang cara untuk menyandikan data menggunakan konstruksi bahasa PHP dan ketika satu cara lebih mungkin diambil alih yang lain untuk keperluan penyampaian data (yaitu Arsitektur Berorientasi Layanan atau layanan web).

Contoh

Misalkan Anda memiliki jenis item yang terdiri dari {biaya, nama, part_number, item_count}. Program Anda meminta tampilan beberapa jenis item, ke tempat Anda memutuskan untuk menggunakan array sebagai wadah luar untuk menampung masing-masing jenis item. [Anda juga dapat menggunakan PHP adalah ArrayObjectuntuk paradigma OO, tapi pertanyaan saya bukan tentang itu (luar) array yang]. Pertanyaan saya adalah tentang bagaimana menyandikan data jenis item, dan tentang paradigma mana yang digunakan. PHP memungkinkan Anda untuk menggunakan PHP Native Arraysatau PHP Objects.

Saya dapat menyandikan data seperti itu, dengan dua cara di sini, seperti:

//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) {..}
}

Apa yang saya pikirkan

Pengkodean array ringan, dan lebih siap JSON, tetapi bisa lebih mudah kacau. Salah mengeja salah satu kunci array asosiatif dan Anda mungkin memiliki kesalahan yang lebih sulit ditangkap. Tetapi juga lebih mudah untuk berubah pada kemauan. Katakanlah saya tidak ingin menyimpan item_countlagi, saya dapat menggunakan perangkat lunak pengolah teks untuk dengan mudah menghapus semua item_countinstance dalam array dan kemudian memperbarui fungsi-fungsi lain yang menggunakannya sesuai. Ini mungkin proses yang lebih membosankan, tetapi sederhana.

Pengkodean berorientasi objek memanggil fasilitas-fasilitas bahasa IDE dan PHP dan membuatnya lebih mudah untuk menangkap kesalahan sebelumnya, tetapi lebih sulit untuk memprogram dan membuat kode di tempat pertama. Saya katakan lebih keras, karena Anda harus berpikir sedikit tentang objek Anda, berpikir ke depan, dan OO coding membutuhkan beban kognitif yang sedikit lebih tinggi daripada mengetik struktur array. Yang mengatakan, setelah dikodekan, beberapa perubahan mungkin lebih mudah untuk diterapkan, dalam arti, bahwa menghapus item_count, misalnya, akan membutuhkan lebih sedikit mengubah baris kode. Tetapi perubahan itu sendiri mungkin masih memerlukan muatan kognitif yang lebih tinggi dibandingkan dengan metode array, karena fasilitas OO tingkat tinggi terlibat.

Pertanyaan

Dalam beberapa kasus jelas, seperti kasus di mana saya perlu melakukan manipulasi pada data. Tetapi dalam beberapa kasus, di mana saya hanya perlu menyimpan beberapa baris data "Jenis Item", saya tidak memiliki pedoman atau pertimbangan yang jelas untuk bersandar ketika mencoba memutuskan apakah akan menggunakan array atau apakah akan membangun objek. Sepertinya saya bisa melempar koin dan mengambil satu. Apakah itu yang terjadi di sini?

Dennis
sumber
2
Catatan Anda bisa mendapatkan objek ringan dengan cara casting sebuah array ke objek: (object)['foo'=>'bar']. Nilai yang dihasilkan memiliki kelas StdClass, akan dikodekan JSON secara keseluruhan oleh json_encode()dan properti dapat diubah namanya semudah indeks array (yang tidak selalu begitu mudah, ketika itu diakses secara tidak langsung melalui variabel). Namun, ada operasi yang berbeda pada nilai-nilai tersebut; misalnya, Anda tidak memiliki serikat objek karena Anda memiliki serikat array, dan Anda tidak dapat langsung menggunakan array_*()fungsi.
outis
3
Anda memiliki 3 pilihan: 1: array , 2: User-defined Class , 3: stdClass . Kinerja dalam hal kecepatan hampir sama ketika membandingkan arraydan User-defined class(seperti Anda ItemType), tetapi classbiasanya cenderung menggunakan lebih sedikit memori daripada menggunakan arrays. stdClassdi sisi lain adalah yang paling lambat dari tiga opsi dan juga menggunakan sebagian besar memori.
Andy

Jawaban:

33

Cara saya melihat ini, itu tergantung pada apa yang ingin Anda lakukan dengan data setelahnya. Berdasarkan beberapa pemeriksaan sederhana, Anda dapat menentukan mana dari dua struktur data yang lebih baik untuk Anda:

  1. Apakah data ini memiliki logika yang terkait dengannya?

    Misalnya, apakah $pricedisimpan sebagai bilangan bulat sen, sehingga produk dengan harga $ 9,99 akan memilikinya price = 999dan tidak price = 9.99? (Mungkin, ya) Atau partNumberperlu mencocokkan regex tertentu? Atau, apakah Anda harus dapat dengan mudah memeriksa apakah itemCounttersedia di inventaris Anda? Apakah Anda perlu melakukan fungsi-fungsi ini di masa depan? Jika demikian, maka taruhan terbaik Anda adalah membuat kelas sekarang. Ini berarti bahwa Anda dapat mendefinisikan kendala dan logika yang dibangun ke dalam struktur data: private $myPricediatur ke 999tetapi $item->getPriceString()kembali $9.99dan $item->inStock()tersedia untuk dipanggil dalam aplikasi Anda.

  2. Apakah Anda akan meneruskan data ini ke beberapa fungsi PHP?

    Jika demikian, maka gunakan kelas. Jika Anda menghasilkan data ini sekali untuk melakukan beberapa transformasi di atasnya, atau hanya mengirim sebagai data JSON ke aplikasi lain (JavaScript atau lainnya) maka sebuah array adalah pilihan yang lebih mudah. Tetapi jika Anda memiliki lebih dari dua fungsi PHP yang menerima data ini sebagai parameter, gunakan kelas. Jika tidak ada yang lain, itu memungkinkan Anda menentukan someFunction(MyProductClass $product) {dan sangat jelas apa fungsi yang Anda harapkan sebagai input. Saat Anda memperbesar kode dan memiliki lebih banyak fungsi, akan lebih mudah untuk mengetahui tipe data apa yang diterima setiap fungsi. Melihatnya someFunction($someArrayData) {hampir tidak jelas. Juga, ini tidak menegakkan konsistensi jenis dan berarti bahwa (seperti yang Anda katakan) struktur fleksibel array dapat menyebabkan rasa sakit pada pengembangan di kemudian hari.

  3. Apakah Anda sedang membangun perpustakaan atau basis kode bersama?

    Jika demikian, gunakan kelas! Pikirkan beberapa pengembang baru yang menggunakan perpustakaan Anda, atau pengembang lain di tempat lain di perusahaan yang belum pernah menggunakan kode Anda sebelumnya. Akan jauh lebih mudah bagi mereka untuk melihat definisi kelas dan memahami apa yang kelas itu lakukan, atau melihat sejumlah fungsi di perpustakaan Anda yang menerima objek dari kelas tertentu, daripada mencoba dan menebak struktur apa yang mereka butuhkan untuk menghasilkan dalam suatu jumlah array. Juga, ini menyentuh masalah konsistensi data dengan # 1: jika Anda mengembangkan pustaka atau basis kode bersama, bersikap baik kepada pengguna Anda: beri mereka kelas yang menegakkan konsistensi data dan melindunginya dari membuat kesalahan dengan desain data Anda .

  4. Apakah ini bagian kecil dari aplikasi atau hanya transformasi data? Apakah Anda tidak cocok dengan yang di atas?

    Kelas mungkin terlalu banyak; gunakan array jika cocok untuk Anda dan Anda merasa lebih mudah. Seperti disebutkan di atas, jika Anda hanya menghasilkan data terstruktur untuk dikirim sebagai JSON atau YAML atau XML atau apa pun, jangan repot-repot dengan kelas kecuali ada kebutuhan untuk itu. Jika Anda menulis modul kecil di aplikasi yang lebih besar, dan tidak ada modul / tim lain yang perlu berinteraksi dengan kode Anda, mungkin array sudah cukup.

Pada akhirnya, pertimbangkan kebutuhan penskalaan kode Anda dan pertimbangkan daripada array terstruktur mungkin perbaikan cepat, tetapi kelas adalah solusi yang jauh lebih tangguh dan terukur.

Juga, pertimbangkan hal berikut ini: jika Anda memiliki kelas, dan Anda ingin menampilkan ke JSON, tidak ada alasan Anda tidak dapat menentukan json_data()metode kelas Anda yang mengembalikan array data JSON-ifiable dari data di kelas. Inilah yang saya lakukan dalam aplikasi PHP saya di mana saya perlu mengirim data kelas sebagai JSON. Sebagai contoh:

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());
Josh
sumber
Anda tidak mengubah elemen my_lineitems, jadi mendapatkannya dengan referensi tidak perlu, terutama karena variabel hanya menyimpan pengidentifikasi ke objek, bukan objek itu sendiri. php.net/manual/en/language.oop5.references.php
Chinoto Vokro
Sepakat. Saya pikir itu adalah cuplikan dari aplikasi yang jauh lebih besar yang membutuhkan referensi karena suatu alasan, atau sesuatu ...
Josh
2

Anda dapat mengimplementasikan struktur json menggunakan antarmuka JsonSerializable dan menggunakan nested array / class dengan cara apa pun. Kelas lebih cepat dalam operasi get / set dan lebih mudah untuk debug. Dengan Array Anda tidak perlu deklarasi.

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'
}
*/
El '
sumber
Apa yang ditambahkan pertanyaan ini dari jawaban yang ada yang diterima?
esoterik
@esoterik bersarang. json_encode(['order'=>$o]);di existsing jawaban yang diterima kosong: {"order":{}}. Tentu Anda dapat menggunakan: $o->forJSON()setiap kali pada setiap objek di setiap level, tetapi desainnya tidak terlalu bagus. Karena sepanjang waktu Anda perlu menulis sesuatu seperti: $items_json = array(); foreach($this->my_lineitems as $item) $items_json[] = $item->forJSON();
El '