Como sei quando refatorar as chamadas de consulta de banco de dados global e quando deixá-las em paz?

5

Eu tenho as seguintes chamadas de instruções globais espalhadas em toda a minha base de código legado do PHP:

$jobnumber = db_quick($sql);
db_query($sql);

Ou seja, essas chamadas de função foram inicializadas no escopo global e elas mesmas chamam um objeto global do MySQL anteriormente inicializado, ou seja:

//initializes MySQL connection object in the global scope
$dblink = MySqlConnector::getMySql();

function db_query($sql)
{
    //previously initialized MySQL connection object
    global $dblink;  

    //native MySQL API call:
    return mysqli_query($dblink, $sql);
}

Pergunta

Há algum benefício em refatorar essas declarações globais, além de apenas dizer "Eu as removi agora do escopo global"?

O espírito da minha pergunta é ... esses já estão na base de código e funcionam. Eu devo mexer com eles? Até agora [3 anos trabalhando com o código] não houve nenhum dano aparente. Mesmo com a transição do mysql obsoleto para o mysqli, foi uma transição indolor. Será que mantê-los como globais causará algum dano mensurável mais tarde? São bons o suficiente para ficarem como estão?

E se eu refatorar?

A propósito, se eu refatorar estou pensando em usar um padrão Singleton para instanciação de link de banco de dados e, em seguida, chamá-lo através de uma classe instanciada, que chama o Singleton. Assim:

//in a calling class:
$repository = new GenericRepository();
$repository->getMySql()->persist($sql);
$value = $repository->getMySql()->paramQuery($sql, $param);

//GenericRepository makes a static call to the actual connector
class GenericRepository 
{
    final public function getMySql()
    {
        if ($this->link === null)
            $this->link = MySqlConnector::getMySql();

            return $this->link;
    }
}

//Connector calls MySQL API
class MySqlConnector
{

    public static function getMySql()
    {
        if (null === static::$instance)
        {
            include 'include/config.php';

            //class MySql extends mysqli library
            static::$instance = new MySql(DBHOST, DBUSER, DBPASS);
        }

        return static::$instance;
    }
}

Portanto, em essência, refatorando, removerei os métodos de banco de dados globais e os substituirei por chamadas instanciadas para o padrão Singleton. A alteração do código será bastante extensa, já que existem algumas milhares de chamadas globais de banco de dados.

Efeitos da Refatoração acima

Atualmente, posso chamar os métodos "de qualquer lugar" - eles são globais.

db_query($sql);    

Após a refatoração, ainda serei capaz de chamá-los "de qualquer lugar", mas usando uma string de conexão mais longa.

(new \Namespace\GenericRepository())->getMySql()->persist($sql);

Isso soa um pouco como um prejuízo - uma string mais longa, mais para digitar, mais para copiar & colar. Existem realmente alguns benefícios para isso?

    
por Dennis 27.12.2016 / 17:51
fonte

2 respostas

2

Há uma razão pela qual db_query está no escopo global, e isso é porque você precisa estar visível em todos os lugares para poder chamá-lo de qualquer lugar. Quando você usa jQuery, $ está no escopo global e é por isso.

Antes de passar por uma refatoração complexa apenas para remover uma função do escopo global, considere as razões pelas quais o escopo global é problemático. Acho que você descobrirá que não é um escopo global que é ruim, mas sim variáveis globais. a>

Além disso, observe que as variáveis globais nem sempre são ruins. Se você estiver usando um para não precisar repetir uma string de conexão indefinidamente em todo o programa, isso é bom.

    
por 27.12.2016 / 18:03
fonte
2
Refatoração não é um fim em si mesmo, é um meio para um fim. E o objetivo é tornar o código mais testável, sustentável e evolutivo.

No seu caso, usar a mesma função global $db_query que acessa o mesmo objeto global $dblink durante toda a base de código evita que você use facilmente essa função com duas conexões de banco de dados diferentes durante uma execução de execução. A restrição "uma e apenas uma conexão de banco de dados por instância de aplicativo" é manifestada na arquitetura. Qualquer código criado com base no seu $dbquery terá que conviver com essa suposição e não poderá ser facilmente reutilizado em um contexto diferente em que o ambiente do banco de dados será diferente ou colocado em um contexto de teste sem banco de dados.

Isso pode ser perfeitamente aceitável . Para muitas aplicações, a arquitetura "one db connection at a time" é tudo o que eles precisam durante toda a sua vida útil. Se o seu aplicativo for desse tipo e você não notar nenhum inconveniente real dessa restrição, nem mesmo para testes, deixe-o como está.

No entanto, se essa arquitetura começar a atrapalhar a implementação de novos recursos ou testes, um tipo de refatoração será uma refatoração em que o $dblink será fornecido de maneira dependente de contexto ou o banco de dados por trás de $dbquery pode ser facilmente ridicularizado. Isso mostra por que sua refatoração Singleton é provavelmente a abordagem errada, porque não resolve as restrições principais de sua arquitetura.

    
por 28.12.2016 / 10:14
fonte