Pertanyaan Global atau Singleton untuk koneksi database?


Apa manfaat menggunakan singleton bukan global untuk koneksi database di PHP? Saya merasa menggunakan tunggal daripada global membuat kode tidak perlu rumit.

Kode dengan Global

$conn = new PDO(...);

function getSomething()
{
    global $conn;
    .
    .
    .
}

Kode dengan Singleton

class DB_Instance
{
    private static $db;

    public static function getDBO()
    {
        if (!self::$db)
            self::$db = new PDO(...);

        return self::$db;
    }
}

function getSomething()
{
    $conn = DB_Instance::getDBO();
    .
    .
    .
}

Jika ada cara yang lebih baik untuk menginisialisasi koneksi database selain global atau tunggal, tolong sebutkan dan deskripsikan keuntungannya secara global atau tunggal.


75
2017-09-25 00:56


asal


Jawaban:


Saya tahu ini sudah tua, tetapi jawabannya adalah Dr8k hampir sana.

Ketika Anda mempertimbangkan untuk menulis sepotong kode, asumsikan itu akan berubah. Itu tidak berarti bahwa Anda mengasumsikan jenis-jenis perubahan yang akan dihidupkannya di beberapa titik di masa depan, tetapi lebih bahwa beberapa bentuk perubahan akan dibuat.

Buatlah gol meredakan rasa sakit karena membuat perubahan di masa depan: global berbahaya karena sulit dikelola di satu tempat. Bagaimana jika saya ingin membuat konteks koneksi basis data itu sadar di masa depan? Bagaimana jika saya ingin menutup dan membuka kembali sendiri setiap 5 kali digunakan. Bagaimana jika saya memutuskan bahwa untuk kepentingan penskalaan aplikasi saya, saya ingin menggunakan kumpulan 10 koneksi? Atau jumlah koneksi yang dapat dikonfigurasi?

SEBUAH pabrik tunggal memberi Anda fleksibilitas itu. Saya mengaturnya dengan sangat sedikit kerumitan ekstra dan mendapatkan lebih dari sekadar akses ke koneksi yang sama; Saya mendapatkan kemampuan untuk mengubah bagaimana koneksi itu diteruskan kepada saya nanti dengan cara yang sederhana.

Perhatikan yang saya katakan pabrik tunggal dibandingkan dengan sederhana tunggal. Ada sedikit perbedaan berharga antara orang tunggal dan global, benar. Dan karena itu, tidak ada alasan untuk memiliki koneksi tunggal: mengapa Anda menghabiskan waktu untuk mengaturnya ketika Anda dapat membuat global biasa?

Apa yang membuat pabrik Anda adalah mengapa untuk mendapatkan koneksi, dan tempat terpisah untuk memutuskan koneksi apa (atau koneksi) yang akan Anda dapatkan.

Contoh

class ConnectionFactory
{
    private static $factory;
    private $db;

    public static function getFactory()
    {
        if (!self::$factory)
            self::$factory = new ConnectionFactory(...);
        return self::$factory;
    }

    public function getConnection() {
        if (!$this->db)
            $this->db = new PDO(...);
        return $this->db;
    }
}

function getSomething()
{
    $conn = ConnectionFactory::getFactory()->getConnection();
    .
    .
    .
}

Kemudian, dalam 6 bulan ketika aplikasi Anda sangat terkenal dan semakin populer dan Anda memutuskan bahwa Anda membutuhkan lebih dari satu koneksi, yang harus Anda lakukan adalah menerapkan beberapa pengumpulan dalam metode getConnection (). Atau jika Anda memutuskan bahwa Anda menginginkan pembungkus yang mengimplementasikan pencatatan log SQL, Anda dapat meneruskan subkelas PDO. Atau jika Anda memutuskan Anda menginginkan koneksi baru pada setiap permintaan, Anda dapat melakukannya. Ini fleksibel, bukannya kaku.

16 baris kode, termasuk kawat gigi, yang akan menghemat jam dan jam dan jam refactoring untuk sesuatu yang menakutkan serupa di telepon.

Perhatikan bahwa saya tidak menganggap ini "Fitur Creep" karena saya tidak melakukan implementasi fitur apa pun di babak ronde pertama. Ini garis perbatasan "Masa Depan Creep", tetapi pada titik tertentu, gagasan bahwa "coding untuk besok hari ini" adalah selalu hal yang buruk tidak cocok untukku.


104
2017-10-20 19:37



Saya tidak yakin saya dapat menjawab pertanyaan spesifik Anda, tetapi ingin menyarankan bahwa objek koneksi global / tunggal mungkin bukan ide terbaik jika ini jika untuk sistem berbasis web. DBMSs umumnya dirancang untuk mengelola sejumlah besar koneksi unik dengan cara yang efisien. Jika Anda menggunakan objek koneksi global, maka Anda melakukan beberapa hal:

  1. Memaksa Anda halaman untuk melakukan semua basis data koneksi secara berurutan dan membunuh setiap upaya pada halaman asyncronous beban.

  2. Berpotensi memegang kunci terbuka elemen database lebih lama dari diperlukan, memperlambat keseluruhan kinerja basis data.

  3. Maksimalkan jumlah total koneksi simultan Anda database dapat mendukung dan memblokir pengguna baru dari mengakses sumber daya.

Saya yakin ada konsekuensi potensial lainnya juga. Ingat, metode ini akan mencoba mempertahankan sambungan basis data untuk setiap pengguna yang mengakses situs. Jika Anda hanya memiliki satu atau dua pengguna, tidak masalah. Jika ini adalah situs web publik dan Anda ingin lalu lintas maka skalabilitas akan menjadi masalah.

[EDIT]

Dalam situasi berskala lebih besar, membuat koneksi baru setiap kali Anda memukul datanya dapat menjadi buruk. Namun, jawabannya bukan untuk menciptakan koneksi global dan menggunakannya kembali untuk semuanya. Jawabannya adalah penggabungan koneksi.

Dengan penggabungan koneksi, sejumlah koneksi berbeda dipertahankan. Ketika koneksi diperlukan oleh aplikasi, koneksi pertama yang tersedia dari pool akan diambil dan kemudian dikembalikan ke pool setelah pekerjaannya selesai. Jika koneksi diminta dan tidak ada satu pun dari dua hal yang akan terjadi: a) jika jumlah maksimum koneksi yang diizinkan tidak tercapai, koneksi baru dibuka, atau b) aplikasi dipaksa menunggu koneksi untuk menjadi tersedia .

catatan: Dalam bahasa .Net, penyatuan koneksi ditangani oleh objek ADO.Net secara default (string koneksi mengatur semua informasi yang diperlukan).

Terima kasih kepada Crad untuk mengomentari ini.


15
2017-09-25 01:05



Metode tunggal dibuat untuk memastikan hanya ada satu contoh dari setiap kelas. Tapi, karena orang menggunakannya sebagai cara untuk menggoyangkan globalisasi, itu menjadi dikenal sebagai pemrograman malas dan / atau buruk.

Oleh karena itu, saya akan mengabaikan global dan Singleton karena keduanya tidak benar-benar OOP.

Apa yang Anda cari adalah injeksi ketergantungan.

Anda dapat memeriksa mudah untuk membaca informasi berbasis PHP yang terkait dengan injeksi ketergantungan (dengan contoh) di http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection


7
2017-12-13 00:35



Kedua pola mencapai efek bersih yang sama, menyediakan satu titik akses tunggal untuk panggilan basis data Anda.

Dalam hal implementasi spesifik, singleton memiliki keuntungan kecil untuk tidak memulai koneksi database sampai setidaknya salah satu dari metode lain Anda memintanya. Dalam praktik di sebagian besar aplikasi yang saya tulis, ini tidak membuat banyak perbedaan, tetapi itu adalah keuntungan potensial jika Anda memiliki beberapa halaman / jalur eksekusi yang tidak membuat panggilan basis data sama sekali, karena halaman tersebut tidak akan pernah meminta koneksi ke database.

Satu perbedaan kecil lainnya adalah bahwa implementasi global dapat menginjak-injak nama variabel lain dalam aplikasi secara tidak sengaja. Tidak mungkin Anda tidak akan pernah secara tidak sengaja menyatakan referensi db $ global lainnya, meskipun mungkin Anda dapat menimpanya secara tidak sengaja (misalnya, Anda menulis jika ($ db = null) ketika Anda bermaksud menulis jika ($ db == null). Objek tunggal mencegah itu.


3
2017-09-25 02:44



Jika Anda tidak akan menggunakan koneksi yang terus-menerus, dan ada beberapa kasus untuk tidak melakukan itu, saya menemukan seorang yang tunggal untuk secara konseptual lebih cocok daripada desain global dalam OO.

Dalam arsitektur OO yang sebenarnya, seorang tunggal lebih efektif daripada membuat objek contoh baru setiap kali.


2
2017-09-25 01:03



Pada contoh yang diberikan, saya tidak melihat alasan untuk menggunakan lajang. Sebagai aturan praktis jika satu-satunya kekhawatiran saya adalah mengizinkan satu objek tunggal, jika bahasa memungkinkannya, saya lebih suka menggunakan global


2
2017-09-25 01:06



Secara umum saya akan menggunakan tunggal untuk koneksi database ... Anda tidak ingin membuat koneksi baru setiap kali Anda perlu berinteraksi ke database ... Ini mungkin melukai kinerja dan bandwidth jaringan Anda ... Mengapa membuat yang baru, ketika ada yang tersedia ... Hanya 2 sen ...

RWendi


1
2017-09-25 01:14



Ini cukup sederhana. Jangan gunakan global ATAU Singleton.


0
2017-09-25 00:59



Sebagai saran keduanya tunggal dan global valid dan dapat digabung dalam yang sama sistem, proyek, plugin, produk, dll ... Dalam kasus saya, saya membuat produk digital untuk web (plugin).

Saya hanya menggunakan tunggal di kelas utama dan saya menggunakannya dengan prinsip. Saya hampir tidak menggunakannya karena saya tahu bahwa kelas utama tidak akan memberi contoh lagi

<?php // file0.php

final class Main_Class
{
    private static $instance;
    private $time;

    private final function __construct()
    {
        $this->time = 0;
    }
    public final static function getInstance() : self
    {
        if (self::$instance instanceof self) {
            return self::$instance;
        }

        return self::$instance = new self();
    }
    public final function __clone()
    {
        throw new LogicException("Cloning timer is prohibited");
    }
    public final function __sleep()
    {
        throw new LogicException("Serializing timer is prohibited");
    }
    public final function __wakeup()
    {
        throw new LogicException("UnSerializing timer is prohibited");
    }
}

Global digunakan untuk hampir semua kelas menengah, contoh:

<?php // file1.php
global $YUZO;
$YUZO = new YUZO; // YUZO is name class

sementara saat runtime bisa saya gunakan Global untuk memanggil metode dan atribut mereka dalam contoh yang sama karena saya tidak memerlukan contoh lain dari kelas produk utama saya.

<?php // file2.php
global $YUZO;
$YUZO->method1()->run();
$YUZO->method2( 'parameter' )->html()->print();

Saya mendapatkan dengan global adalah menggunakan contoh yang sama untuk dapat membuat produk bekerja karena saya tidak memerlukan pabrik untuk contoh kelas yang sama, biasanya pabrik contoh adalah untuk sistem besar atau untuk tujuan yang sangat langka.

In conclusion:, Anda harus jika Anda sudah memahami dengan baik bahwa itu adalah anti-pola Singleton dan mengerti Global, Anda dapat menggunakan salah satu dari 2 opsi atau mencampurnya tetapi jika saya menyarankan untuk tidak menyalahgunakan karena ada banyak programmer yang sangat pengecualian dan setia pada pemrograman OOP, gunakan untuk kelas utama dan sekunder yang Anda gunakan banyak dalam eksekusi waktu. (Ini menghemat banyak CPU).


0
2018-05-27 18:36