Jump to content
Daniel-Lopes

Quando devo usar códigos repetidos em classes diferentes (Divisão de tarefas em Orientação a objetos - PHP)

Recommended Posts

Estou com dificuldades em entender quando um determinado trecho de código deve ser repetido em mais de uma classe afim de manter a independência da mesma, pois segundo artigos que leio sobre orientação a objetos - Um Objeto (classe) deve ser independente o suficiente para ser utilizada sem dependências. - Ter apenas uma funcionalidade, desempenhando apenas o seu papel (coesão).

Meu sistema é foi criado para vendas de comerciais, onde cada bloco/horário tem um preço diferente, calculado com base no preço médio + acréscimos - descontos.

O objetivo (funcionalidade ou papel) da classe VendasController é retornar para View Orcamentos, informações sobre produtos e valores para realização de um orçamento e posteriormente um contrato. Para retornar essas informações eu obtenho o preço médio de cada bloco e adiciono os acréscimos em alguns métodos dentro desta classe, ela tem o funcionamento independente.

Agora estou desenvolvendo outra classe que se chama DistribuicoesController, onde a sua funcionalidade é distribuir uma quantidade X de comerciais no blocos/horários disponiveis, e uma de suas opções seriam distribuir no blocos com menor custo médio.

Portanto a questão aqui é:

Tanto na Classe VendasController como na classe DistribuicoesController eu faço uso de preço médio dos blocos.

Qual seria o mais correto: eu repetir o código nas duas classes, fazer tudo dentro de uma unica classe, criar uma "super classe" e usa-la estendida dentro das classes VendasController e DistribuicoesController.

Share this post


Link to post
Share on other sites
1 hora atrás, Daniel-Lopes disse:

[...]Um Objeto (classe) deve ser independente o suficiente para ser utilizada sem dependências.[...]

 

Essa definição está errada e não condiz com o paradigma orientado à objetos. Ou pode apenas estar fora de contexto. Objetos podem ser independentes, entretanto, não é ruim ter dependência. Apenas, a dependência deve ser bem construída.

 

Por outro lado, esta, está correta:

1 hora atrás, Daniel-Lopes disse:

[...]Ter apenas uma funcionalidade, desempenhando apenas o seu papel (coesão)[...]

 

 

O princípio da orientação a objetos, no seu estado mais bruto, é trazer a programação o mais próximo possível do mundo real.

 

Pelo que você descreveu sobre o objeto VendaController, ele já está fazendo muito mais do que é de sua responsabilidade. Um controller, por definição, deve apenas receber uma requisição, acionar um model (caso necessário) e enviar os dados para uma view. Um controler sempre estará linkado a uma view, mas, pode nao estar linkado a um model.

 

1 hora atrás, Daniel-Lopes disse:

Qual seria o mais correto: eu repetir o código nas duas classes, fazer tudo dentro de uma unica classe, criar uma "super classe" e usa-la estendida dentro das classes VendasController e DistribuicoesController.

 

O correto é nunca repetir. Se repetir, há possibilidade de refatoração e a criação em uma classe separada.

 

Crie um objeto que seja responsável por aquilo que você está trabalhando. Se você está exibindo dados de um orçamento, provavelmente você terá alguns integrantes, como: Orçamento; Itens do Orçamento (seja produto e/ou serviços).

 

O Orçamento e Itens do Orçamento, podem estar associados a outros itens, como o produto/serviço em si, clientes, etc...

 

Quando você separa desta forma, você isola as responsabilidades e entenderá que cada objeto tem o seu papel. No seu caso, se o cálculo de preço médio dos blocos é realizado para o produto apenas quando ele está em um orçamento, bem, isso é de responsabilidade do Item do Orçamento. Por outro lado, se o preço médio do bloco deve ser calculado considerando o orçamento, o cálculo é de responsabilidade do Orçamento.

Share this post


Link to post
Share on other sites

 

Citar

Pelo que você descreveu sobre o objeto VendaController, ele já está fazendo muito mais do que é de sua responsabilidade. Um controller, por definição, deve apenas receber uma requisição, acionar um model (caso necessário) e enviar os dados para uma view. Um controler sempre estará linkado a uma view, mas, pode nao estar linkado a um model.

 

Entendi, no caso o Controller serve apenas para receber e enviar (a grosso modo), então neste caso as demais funcionalidades, como está de aplicar acréscimos, montar os preços para serem retornadas pelo controller para a view é feita onde em um padrão MVC ?

 

Citar

O correto é nunca repetir. Se repetir, há possibilidade de refatoração e a criação em uma classe separada.

Então é isso que está me deixando preocupado com minhas classes...

Por exemplo, eu tenho a classe Clientes, onde no momento do Orçamento eu necessito retornar para View uma listagem de clientes, dentro do controller Orcamentos eu chamo o Model Clientes para retornar essa listagem (ja que para realizar um orçamento necessita de escolher um cliente), está correto esta prática ?

 

 

Citar

Crie um objeto que seja responsável por aquilo que você está trabalhando. Se você está exibindo dados de um orçamento, provavelmente você terá alguns integrantes, como: Orçamento; Itens do Orçamento (seja produto e/ou serviços).

Tenho uma situação distinta onde uso os valores médios dos produtos em cada bloco/horario (exemplo: spot 30", testemunhal, spot 15",  no bloco das 15:00) em dois locais, que não tem ligação em si.

 

Neste caso teria que criar um objeto responsável por retornar esta tabela de preços e utiliza-la nos outros dois objetos (Controllers) distintos para serem retornados ?

Share this post


Link to post
Share on other sites
4 minutos atrás, Daniel-Lopes disse:

Entendi, no caso o Controller serve apenas para receber e enviar (a grosso modo), então neste caso as demais funcionalidades, como está de aplicar acréscimos, montar os preços para serem retornadas pelo controller para a view é feita onde em um padrão MVC ?

 

O padrão MVC em si define apenas que, regras de negócio devem ser tratadas na camada (layer) Model . Ou seja, esse cálculo deve estar no model. 

 

O model, por sua vez, pode ser compreendido como N camadas. Essas camadas podem ser:

  • Entidades (Entities), ex.: Orçamento, Cliente, Produto;
  • Controle de dados, ex.: DAO (Data Access Object), DataMapper, FileSystem;
  • Operacional, ex.: contábil, estoque, financeiro, etc...

Deve-se entender que o Model é um ecossistema que podem ser diversas camadas. Essas camadas não são definidas pelo MVC e sim por outros padrões. Eu costumo criar sempre as seguintes "camadas" no Model:

  • Model: os objetos que são acessados diretamente pelo controller;
  • DataMapper: conjunto de objetos específicos para o mapeamento de dados de uma base de dados para entidades;
  • Entities: entidades do sistema, são as entidades que são persistidas na base de dados;
  • Entidades de negócio: São entidades que não são persistidas, mas estão intrinsincamente ligadas as entidades e possuem regras complexas de negócio, como contabilidade, financeiro, estoque, etc..

A forma que você irá separar, vai depender do quão complexo é o seu sistema. Há também o DDD (Domain-Driven Design) que prove uma excelente abordagem para a arquitetura.

 

4 minutos atrás, Daniel-Lopes disse:

Então é isso que está me deixando preocupado com minhas classes...

Por exemplo, eu tenho a classe Clientes, onde no momento do Orçamento eu necessito retornar para View uma listagem de clientes, dentro do controller Orcamentos eu chamo o Model Clientes para retornar essa listagem (ja que para realizar um orçamento necessita de escolher um cliente), está correto esta prática ?

 

Sim, a prática está ok. Você pode verificar os seguintes tópicos sobre o assunto:

https://pt.stackoverflow.com/a/197651/5007

 

4 minutos atrás, Daniel-Lopes disse:

Tenho uma situação distinta onde uso os valores médios dos produtos em cada bloco/horario (exemplo: spot 30", testemunhal, spot 15",  no bloco das 15:00) em dois locais, que não tem ligação em si.

 

Neste caso teria que criar um objeto responsável por retornar esta tabela de preços e utiliza-la nos outros dois objetos (Controllers) distintos para serem retornados ?

 

Existe uma abordagem chamda de Anemic Model, ela define que entidades devem ter nada ou o mínimo de regras de negócio possível e que outros objetos seriam responsávels por essa regra de negócio. Essa abordagem é muito criticada e, normalmente, o recomendado é inserir a regra de negócio, especifica de uma entidade, na entidade.

 

Caso uma regra de negócio seja compartilhada, essa regra deve ser separada em outro objeto (vide a minha camada de Entidades de negócio).

 

Mas isso fica a sua escolha, ambas as abordagens existem, só Anemic Model não é recomendada.

  • Obrigado! 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By Giovanird
      Olá a todos!

      Abaixo lista minha estrutura em Json. Há grupos que faltam um objeto (TIPO) e ao listar recebo o erro  por não encontrá-lo.
      Existe alguma maneira de verificar se este objeto existe e caso não, ignorar?

      Desde já agradeço a atenção.

       
      ESTUTURA JSON: [ { “titulo”: “JSON”, “data”: “20/10/2020”, “ano”: 2020, “tipo”: novo }, { “titulo”: “HTML”, “data”: “20/10/2020”, “ano”: 2020, “tipo”: usado }, { “titulo”: “PHP”, “data”: “20/10/2020”, “ano”: 2020 } ] CAPTURANDO OS DADOS: $titulo = $decode->titulo; $data = $decode->data; $ano = $decode->ano; $tipo = $decode->tipo;  
       
    • By maurohpg
      Estou fazendo uma gravação dos dados no banco e ao mesmo tempo eu faço upload de um arquivo pdf. 

      Acontece que a gravação do dados está ok, grava o nome do arquivo pdf no banco, mas não grava o arquivo pdf na pasta, e não me retorna nenhum erro, segue no script ou no log.
       
      Alguém pode dar uma luz no que estou fazendo errado? É bem simples, nas não encontro o erro.
       
      <?php include("../config.php"); include("verifica.php"); include("../tags.php"); $acao = strip_tags( $_GET['acao'] ); /* Informa o nível dos erros que serao exibidos */ error_reporting(E_ALL); /* Habilita a exibiçao de erros */ ini_set("display_errors", 1); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <?php echo "<?xml version=\"1.0\" encoding=\"iso-8859-2\"?".">"; ?> <title><?php echo $nomeL ?></title> <link href="css/css.css" rel="stylesheet" type="text/css" /> <!-- desenvolvido por Mauro Garcia --> <script type="text/javascript" src="../js/funcoes.js"></script> <script src="ckeditor/ckeditor.js"></script> </head> <body> <?php include("topo.php"); ?> <div id="content_interno"> <?php include("menu.php"); ?> <div id="admin"> <table width="774" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="82%"><p>INSERIR REGISTRO</p></td> <td width="18%"><a href="privacidade_add.php"><br /> </a></td> </tr> </table> <br /> <br /> <?php if( empty( $acao ) ) { ?> <form name="add" action="privacidade_add.php?acao=add" method="post" enctype="multipart/form-data"> <div class="form_add"> <table width="650" border="0" align="left" cellpadding="5" cellspacing="5"> <tr> <td colspan="4"><strong>Mostrar no site</strong></td> </tr> <tr> <td colspan="4"><select name="ativo"> <option value="1">Sim</option> <option value="0">N&atilde;o</option> </select></td> </tr> <tr> <td height="5" colspan="4"><img src="img/spacer.gif" width="5" height="5" /></td> </tr> <tr> <td colspan="4"><strong>C&oacute;digo, se n&atilde;o houver deixe em branco</strong></td> </tr> <tr> <td colspan="4"><input name="codigo" type="text" id="codigo" onfocus="dentro(this, 'Código')" onblur="fora(this, 'Código')" value="Código" size="20" maxlength="10"/></td> </tr> <tr> <td colspan="4"><img src="img/spacer.gif" width="5" height="5" /></td> </tr> <tr> <td colspan="4"><input name="hora" type="text" id="hora" onfocus="dentro(this, 'Data')" onblur="fora(this, 'Data')" value="Data" size="20" maxlength="10"/> dd/mm/aaaa</td> </tr> <tr> <td colspan="4"><img src="img/spacer.gif" width="5" height="5" /></td> </tr> <tr> <td colspan="4"><strong>T&iacute;tulo (At&eacute; 200 caracteres): </strong></td> </tr> <tr> <td colspan="4"><input name="nome_imovel" type="text" id="nome_imovel" onfocus="dentro(this, 'Título')" onblur="fora(this, 'Título')" value="T&iacute;tulo" size="80" maxlength="200"/></td> </tr> <tr> <td colspan="4"><img src="img/spacer.gif" alt="" width="5" height="5" /></td> </tr> <tr> <td colspan="4"><strong><font color="#FF0000">N</font><font color="#FF0000">&atilde;o esquecer de selecionar</font></strong></td> </tr> <tr> <td width="174"><select name="id_negocio_tipo"> <option value="">Categoria</option> <?php $sql = mysql_query("SELECT id, tipo FROM negocio_tipo ORDER BY tipo ASC"); while( $linha = mysql_fetch_array( $sql ) ){ echo '<option value="' . $linha['id'] . '"> ' . $linha['tipo'] . '</option>'; } ?> </select></td> <td width="192">&nbsp;</td> <td width="184">&nbsp;</td> <td width="184">&nbsp;</td> </tr> <tr> <td colspan="4"><img src="img/spacer.gif" alt="" width="5" height="5" /></td> </tr> <tr> <td colspan="4"><strong>Resumo</strong></td> </tr> <tr> <td colspan="4"><textarea name="msg" id="msg" cols="60" rows="5" onfocus="dentro(this, 'Texto')" onblur="fora(this, 'Texto')"></textarea></td> </tr> <tr> <td colspan="4"><img src="img/spacer.gif" alt="" width="5" height="5" /></td> </tr> <tr> <td colspan="4"><strong>PDF</strong></td> </tr> <tr> <td colspan="4"><input id="fakeupload" name="fakeupload" class="fakeupload" type="text" /> <input id="arquivo" name="arquivo" class="foto" type="file" onchange="this.form.fakeupload.value = this.value;" /></td> </tr> <tr> <td><a href="javascript:document.add.submit();"><img src="img/bt_gravar.png" width="74" height="26" /></a></td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </table> </div> </form> <?php } // fim da açao EMPTY if( $acao == 'add') { extract( $_POST, EXTR_OVERWRITE); // extrai os dados do POST, transformando os indices em nomes. Sobrescreve as variaveis existentes, se houver $sql1 = mysql_query("SELECT id FROM privacidade WHERE codigo='$codigo'"); $ttlCodigo = mysql_num_rows($sql1); if( !empty( $codigo ) && $ttlCodigo > 0){ echo "<script language='JavaScript'> alert('Código duplicado, informe outro código'); window.location.href='javascript:history.go(-1)' </script>"; exit; } ///////////////// TRATA if( !empty( $arquivo['name'] ) ) { if(preg_match( '/\.(pdf)+$/', $arquivo["type"])){ echo "<script language='JavaScript'> alert('Arquivo em formato inválido! Formato aceito: PDF'); window.location.href='javascript:history.go(-1)' </script>"; exit; } // Verifica tamanho do arquivo if($arquivo["size"] > 200000000) { echo "<script language='JavaScript'> alert('A imagem deve ser de no máximo 2020680 bytes'); window.location.href='javascript:history.go(-1)' </script>"; exit; } preg_match("/\.(pdf)+$/", $arquivo["name"], $ext); $imagem_nome = md5(uniqid(time())) . "." . $ext[1]; $imagem_dir = "../uploads/pdf/" . $imagem_nome; }else{ // se nao for informado nenhum arquivo echo "<script language='JavaScript'> alert('A imagem da notícia esta faltando'); window.location.href='javascript:history.go(-1)' </script>"; exit; // Repassa a variável do upload $arquivo = isset($_FILES["arquivo"]) ? $_FILES["arquivo"] : FALSE; // Caso a variável $arquivo contenha o valor FALSE, esse script foi acessado // diretamente, então mostra um alerta para o usuário if(!$arquivo) { echo "Não acesse esse arquivo diretamente!"; } // Imagem foi enviada, então a move para o diretório desejado else { // Diretório para onde o arquivo será movido $imagem_dir = "../uploads/pdf/"; // Move o arquivo // Lembrando que se $arquivo não fosse declarado no começo do script, // você estaria usando $_FILES["arquivo"]["tmp_name"] e $_FILES["arquivo"]["name"] if (move_uploaded_file($arquivo["tmp_name"], $imagem_dir . $arquivo["name"])) { echo "Arquivo Enviado com sucesso!"; } else { echo "Erro ao enviar seu arquivo!"; } } } $sql = mysql_query("INSERT INTO privacidade (id_negocio_tipo, codigo, foto_exibicao, msg, ativo, nome_imovel, hora) VALUES ('$id_negocio_tipo','$codigo','$imagem_nome','$msg','$ativo','$nome_imovel','$hora')") or print(mysql_error()); $ultimo_id = mysql_insert_id(); echo '<div id="sucesso"><font color="#5a5a5a" size="3" face="Arial, Helvetica, sans-serif"><font color="#009900" size="4"><b>Registro inserido com sucesso</b></font><br /><br /> <a href="privacidade_add.php">CADASTRAR OUTRO</a><br><br> <a href=privacidade.php>clique aqui para voltar</a> </font></div>'; } ?> </div> </div> <script> // This call can be placed at any point after the // <textarea>, or inside a <head><script> in a // window.onload event handler. // Replace the <textarea id="editor"> with an CKEditor // instance, using default configurations. CKEDITOR.replace( 'msg' ); </script> <?php include("rodape.php"); ?> </body> </html>  
    • By anabeatrizzz
      2. Por que PHP é a mais utilizada em projetos? Explique.
       
      3. São 24 anos de desenvolvimento em PHP, o que faz ele durar tanto na área da programação? Explique.
       
      4. Você acredita que o PHP vai morrer ou não? Explique.
       
      5. Explique o que seria esta HHVM que as empresas utilizam.
       
      6. PHP tem a facilidade de criar APIs, quais seriam as vantagens na hora de desenvolver aplicativos para celular? Explique.
       
      7. Explique um pouco sobre o Laravel, Zend Framework, Sympony, lumen, codelgniter que foram surgindo ao decorrer dos anos.
       
      8. “O PHP veio da WEB e da WEB ele permanecerá”. O que essa frase significaria para você? Explique.
       
      9. Como funcionariam as comunidades em PHP? Por que existem tantas pessoas ainda usando a linguagem? Explique.
       
      10. O PHP vem se modernizando durante anos, quais seriam estas evoluções dele? Explique.
    • By fideles
      Mais uma vez venho aqui pedir ajuda a vocês.
       
      Tenho um formulario que criei aqui na empresa algo bem simples, somente para sair das planilhas de excel, que seria cadastro de funcionarios.
       
      Tem os campos, matricula, nome completo, unidade de trabalho, endereço e telefone de emergencia.
       
      A parte do formulario funciona, a gravação no BD tbm, listar as informações também, ai me perguntaram se era possível um auto preenchimento dos campos colocando somente a matricula do funcionario e respondi que eu não sei porque realmente não sei.
       
      A ajuda que eu preciso de vocês seria, é possível fazer isso ? Colocar a matricula e vir do banco e preencher os outros inputs? Se sim, é possível me derem um exemplo de como funciona e eu estudar o codigo e colocar nos outros inputs.
       
      Obrigado antecipadamente. 
       
    • By tetsuo
      Boas galera?
      Às vezes subo um projeto que, despercebidamente passa um arquivo com letra maiúscula/minúscula
      E dá trabalho pra descobrir que era somente e apenas isso.
       
      Como posso resolver isso?
      Uso rWindows 10.
      Mas a hospedagem é em linux.
       
      O Docker serviria pra me ajudar com essa questão?
       
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.