What is the best approach to dealing with loosely coupled code?

Asked

Viewed 42 times

0

What would be the correct way to structure the code below? For example, is it appropriate to pass an instance of Connectorwmi as a parameter and use it to execute an instruction? Or would you have a more appropriate approach?

Connector:

abstract class Conector
{
    /**
     * Recurso de conexão externa
     * 
     * @var object
     */
    protected $conexao;

    /**
     * Mensagem de erro
     * 
     * @var string
     */
    protected $mensagemErro;

    /**
     * Realiza conexão com o host alvo
     * 
     * @param   string  $host
     * @param   string  $usuario
     * @param   string  $senha
     * @param   int     $porta
     * @param   int     $timeout
     * @return  void
     */
    abstract public function conectar($host, $usuario = null, $senha = null, $porta = 135, $timeout = 10);

    /**
     * Consulta o status da conexão
     * 
     * @return bool
     */
    public function status()
    {
        return ($this->conexao !== NULL) ? TRUE : FALSE;
    }

    /**
     * Retorna mensagem de erro gerada durante a tentativa de conexão 
     * ou erro gerado na chamada do método "executar"
     * 
     * @return string
     */
    public function mensagemErro()
    {
        return $this->mensagemErro;
    }

    /**
     * Executa a instrução remotamente
     * 
     * @param   string $instrucao
     * @return  object
     */
    abstract public function executar($instrucao);
}

Connectorwmi:

class ConectorWmi extends Conector
{    
    /**
     * Estabelece conexão com máquinas Windows via chamada COM
     * 
     * @param   string  $host
     * @param   string  $usuario
     * @param   string  $senha
     * @param   int     $porta
     * @param   int     $timeout
     * @return  void
     */
    public function conectar($host, $usuario = null, $senha = null, $porta = 135, $timeout = 10)
    { 
        try
        {
            /**
             * Testa conectividade com host alvo
             * 
             * @param string $host
             * @param string $porta
             * @param int    $errno   valor de sistema
             * @param string $errstr  mensagem de sistema
             * @param int    $timeout tempo máximo a esperar
             */    
            if (!$socket = @fsockopen($host, $porta, $errno, $errstr, $timeout))
            {
                // @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
                $dic = [
                            10056 => "Já existe uma conexão socket aberta para o host <b>{$host}</b>!",
                            10057 => "Não foi possível conectar ao socket na chamada do host <b>{$host}</b>!",
                            10060 => "Time Out na chamada do host <b>{$host}</b>!",
                            10061 => "O host <b>{$host}</b> recusou a conexão!",
                        ];

                $mensagem = (array_key_exists($errno, $dic)) ? strtr($errno, $dic) : $errstr;          

                throw new RuntimeException("Erro ({$errno}): {$mensagem}");
            }

            fclose($socket); // Fecha o socket aberto anteriormente

            $WbemLocator = new COM("WbemScripting.SWbemLocator");
            // @see https://msdn.microsoft.com/en-us/library/aa393720(v=vs.85).aspx
            $this->conexao = $WbemLocator->ConnectServer($host, 'root\cimv2', $usuario, $senha, 'MS_416');
            $this->conexao->Security_->ImpersonationLevel = 3;
        }
        catch (com_exception $e) {
            $this->mensagemErro = utf8_encode($e->getMessage());
        }
        catch (RuntimeException $e) {
            $this->mensagemErro = $e->getMessage();
        }
        catch (Exception $e) {
            $this->mensagemErro =  $e->getMessage();
        }
    }

    /**
     * Executa a instrução remotamente
     * 
     * @param   string $instrucao
     * @return  object|string em caso de erro retorna uma string
     */
    public function executar($instrucao)
    {
        try
        {
            if (!$this->conexao)
            {
                throw new RuntimeException("Antes de executar uma instrução é necessário instanciar uma conexão!");
            }

            // @see http://php.net/manual/en/ref.com.php
            if(!$retorno = $this->conexao->ExecQuery($instrucao))
            {
                throw new RuntimeException("O host remoto não retornou dados!");
            }

            return $retorno;
        }
        catch (RuntimeException $e) {
            return $e->getMessage();
        }
    }
}

CPU:

class Cpu
{
    /**
     * Armazena uma instância de Win32_Processor
     *
     * @access private
     * @var object
     */
    private $cpu;

    /**
     * Captura as informações referentes a CPU
     * 
     * @access public
     */
    function __construct(ConectorWmi $wmi)
    {
        $this->cpu = $wmi->executar("SELECT
                                            Caption,
                                            DeviceID,
                                            LoadPercentage,
                                            CurrentClockSpeed,
                                            Name,
                                            NumberOfCores,
                                            DataWidth,
                                            NumberOfLogicalProcessors
                                        FROM Win32_Processor");
    }

    /**
     * Retorna informações referentes a CPU
     * 
     * @access public
     * @return array
     */
    public function cpuDetalhes()
    {
        foreach ($this->cpu as $c)
        {
            $cpu[$c->DeviceID] = array('nome' => $c->Name,
                                       'arquitetura' => $c->DataWidth,
                                       'mhz' => $c->CurrentClockSpeed,
                                       'nucleos' => $c->NumberOfCores,
                                       'processadoresLogicos' => $c->NumberOfLogicalProcessors,
                                       'cargaDoProcessador' => $c->LoadPercentage);
        }

        return $cpu;
    }
}

Test consulting the CPU:

$wmi = new ConectorWmi;
$wmi->conectar('192.168.54.101', 'Administrador', '1QAZxsw2');

if($wmi->status())
{
    $obj = new Cpu($wmi);

    echo "<pre>";
    print_r($obj->cpuDetalhes());
    echo "</pre>";
}
else
{
    echo $wmi->mensagemErro();
}
  • Why did you delete the old question and remake it again? ... Even though I switched from Static to "object," I still believe that the comment I wrote earlier applies to this situation as well, in addition to container coupling, the problem is simply getting out using it because they taught it that way, because I said it was good, the techniques are created to solve problems, so if the class can be simple make it simple, unless you have the vision of a large project where the class will be used, instantiated, inherited, which does not seem to me the case.

  • The previous question was confused, just as I changed the code and changed the context of the question. Now the question is, what is the best approach to the code published in this question.

  • 3

    The best approach is to stop reading blogs or tutorials that teach "good practice", simplify the code and use certain things if necessary :)

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.