Ir para conteúdo

Placar de líderes


Conteúdo popular

Exibindo o conteúdo com as maiores reputações desde 07/15/09 em todas as áreas

  1. 6 pontos
    Vou sair um pouco do escopo do tópico, mas o exemplo que você deu sobre o ar condicionado do carro é um bom exemplo de onde NÃO usar herança. Por quê? Suponha que você tenha: abstract class Car { public function accelerate() {} public function steer() {} public function turnOnAirConditioning() {} }Você assume que todo carro possui ar condicionado. Se algum não tiver, temos que recorrer a peripécias como: class SpartanCar { public function turnOnAirConditioning() { throw new Exception('No air conditioning in this car!'); } }Na maioria das vezes, algo assim é quase um crime, que vai levar a um erro fatal no seu código quando você menos esperar. Aí você pensa: abstract class Car { public function accelerate() {} public function steer() {} public function break() {} }O problema é que agora sempre que um carro tiver um ar condicionado, vou precisar implementar um método para ligá-lo... class Ferrari extends Car { public function turnOnAirConditioning() {} } class Lamborghini extends Car { public function turnOnAirConditioning() {} }Mas isso é fácil de resolver: é só criar uma outra classe abstrata que estende a primeira e que tenha a implementação do ar-condicionado. abstract AirConditioningEnabledCar class Car { public function turnOnAirConditioning() {} }Agora eu faço: class Ferrari extends AirConditioningEnabledCar {} Problema resolvido! Só que não, jovem Padawan... Essa solução funciona bem se a única modificação possível for o ar condicionado. Suponha agora que você também pode adicionar freios ABS no seu carro. Como fazer? abstract AbsEnabledCar class Car { public function break() {} // changes implementation }E se o seu carro tiver ambos freios ABS e ar condicionado? Você vai querer perpetrar o horror que é: abstract AbsAndAirConditioningEnabledCar class Car {} Mesmo que você ache que está tudo bem agora, o que acontece se você puder adicionar air bags também e sabendo que qualquer carro pode ter qualquer combinação desses 3 opcionais? Você está com um problema exponencial em mãos! Você está em meio a um mar de DRY e KISS. Design Pattern: Decorator Objetivo Adicionar responsabilidades a e/ou modificar o comportamento de um objeto dinamicamente.Problema Você precisa modificar o comportamento de objetos individuais em tempo de execução. Usar herança não é plausível porque ela é estática e se aplica à classe como um todo, não a objetos. Discussão A solução mais comum para essa classe de problemas envolve encapsular o objeto original em uma interface. São criados também classes modificadoras desse objeto original ("decoradores"), que alteram uma ou mais funcionalidades e também implementam aquela interface. Para poder modificar o comportamento do objeto original, esses decoradores mantêm uma referência para o objeto original ou para uma composição entre outros decoradores e o objeto original. Estrutura Descrever padrões verbalmente é sempre complicado, por isso, costumamos utilizar diagramas de classe para facilitar seu entendimento: Exemplo Voltando ao seu exemplo, teríamos algo assim: interface ICar { //NOT from Apple!!! public function accelerate(); public function break(); public function steer(); public function turnOnVentilation(); // regular ventilation all cars have public function turnOffVentilation(); // regular ventilation all cars have } abstract class AbstractCar implements ICar { public function accelerate() {} public function break(){ } public function steer(){ } public function turnOnVentilation(){ } public function turnOffVentilation(){ } } class Mustang extends AbstractCar { } Até aí nada de muito diferente. Vamos agora aos nossos decoradores: abstract class AbstractCarDecorator implements ICar { private $origCar; public function __construct(ICar $origCar) { $this->origCar = $origCar; } public function accelerate() { $this->origCar->accelerate(); // by default, delegates to the original object } // All methods bellow do the same: delegate the execution of the method with no changes public function break(){ } public function steer(){ } public function turnOnVentilation(){ } public function turnOffVentilation(){ } } class AirConditioningDecorator extends AbstractCarDecorator { // The following two methods are not part of the interface public function turnOnAirConditioning() {} public function turnOffAirConditioning() {} public function isOnAirConditioning() {} /* Now we change the implementation of these two methods * to make them use the air conditioning capability */ public function turnOnVentilation() { } public function turnOffVentilation() { } } class AbsDecorator extends AbstractCarDecorator { // changes the breaking process public function break() { } } Usando essa bugiganga toda: $spartanCar = new Mustang(); // sem ar e sem ABS $spartanCar->accelerate(); // ... $secureCar = new AbsDecorator(new Mustang()); $secureCar->accelerate(); // será delegado ao objeto Mustang $secureCar->break(); // será executado o método de freio do objeto Abs $luxuryCar = new AirConditioningDecorator(new AbsDecorator(new Mustang()); $luxuryCar->turnOnAirConditioning(); $luxuryCar->turnOnVentilation(); // liga a ventilação com ar condicionado Note que para os métodos não pertencentes à interface, só é possível fazer o acesso se eles forem parte do decorador mais externo. Se fizéssemos: $luxuryCar = new Abs(new AirConditioningDecorator(new Mustang()); $luxuryCar->turnOnAirConditioning(); // fatal error Obteríamos um erro fatal, já que [inline]AbsDecorator[/inline] não possui um método [inline]turnOnAirConditioning[/inline]. Existem algumas formas de tornar essa chamada possível, mas para não estender demais o post, não vou colocá-las aqui. Assim: class AirBagDecorator extends AbstractCarDecorator { // changes the breaking process, if too abrupt, air bags will inflate public function break() { } } $ultraLuxuryCar = new AirBagDecorator(new AbsDecorator(new AirConditioningDecorator(new Mustang()));
  2. 5 pontos
  3. 5 pontos
    O Princípio de Substituição de Liskov delimita regras para se utilizar a herança, uma vez que a regrinha do é um é meio subjetiva demais. Em seu lugar, Liskov propões que para se utilizar herança, façamos um outro questionamento: é substituível por? Em outras palavras, antes de estender uma classe X, criando uma classe Y, pergunte-se a si mesmo se é possível substituir objetos X por objetos Y sem alterar a funcionalidade do programa. Um exemplo claro onde o é um falha é no caso do Retângulo/Quadrado. Matematicamente, todo quadrado é um retângulo, então, inicialmente, faria sentido o seguinte código: class Rectangle {} class Square extends Rectangle {} Agora vamos pensar em implementação. Um retângulo é um paralelogramo que possui todos os ângulos retos e cujos lados tem medidas iguais 2 a 2: class Rectangle { private $width; private $height; public function __construct($width, $height) { $this->setWidth($width); $this->setHeight($height); } public function setWidth($width) { $this->width = (int) $width; } public function setHeight($height) { $this->height = (int) $height; } public function getWidth() { return $this->width; } public function getHeight() { return $this->height; } public function getArea() { return $this->height * $this->width; } } E agora, vamos à classe que representará um quadrado. Como sabemos, para ter um quadrado, precisamos de um retângulo e precisamos garantir ele que possui todos os lados iguais. Fazendo com herança, temos: class Square extends Rectangle { public function __construct($side) { $this->setWidth($side); $this->setHeight($side); } } Ok, a princípio funciona, mas há um bug: o que acontece se depois de instanciar um objeto [inline]Square[/inline] eu vou lá e resolvo setar um dos lados independentemente? $square = new Square(5); echo $square->getArea(); // 25 $square->setWidth(10); echo $square->getArea(); // 50 e não o esperado valor 100. Aaah, mas podemos forçar algo do tipo: class Square extends Rectangle { public function __construct($side) { $this->setWidth($side); } public function setWidth($width) { parent::setWidth($width); parent::setHeight($width); } public function setHeight($height) { parent::setWidth($height); parent::setHeight($height); } } Legal, agora funciona como esperado, mas você tem 2 atributos que precisa manter sincronizados entre si, além do desperdício de espaço, porque você precisa de um dado só. Além do mais, quando você altera a largura de um retângulo, você não espera que a altura seja afetada. Imagine que você utilize essas formas geométricas para algum outro fim, e você tem: public function doSomethingWithRectangle(Rectangle $r) { $r->setWidth($r->getWidht() * 2); // dobrando a largura } Entretanto, nada te impedirá de chamar essa função como: $obj->doSomethingWithRectangle(new Square(5)); Quando o código executar, sem saber, ele irá alterar não só a largura do objeto, mas também a altura. Isso é conhecido como efeito colateral, mas também pode ser chamado de bomba de bugs. Observe então que um objeto [inline]Rectangle[/inline] NÃO É SUBSTITUÍVEL por um objeto [inline]Square[/inline], logo, não deveríamos utilizar herança neste caso.
  4. 5 pontos
    Uso sempre que possível, acho que é mais uma questão de escrever menos do que qualquer outra coisa e também de gosto, é claro. Só não é legal usar quando se tem muitas comparações (respeitar também o limite - 120 caracteres por linha) ou usar ternário encadeado, dificulta e muito a leitura, então if's talvez seriam melhores nesse caso. Por exemplo na situação abaixo: public function doSomething(Foo $foo = null) { if ($foo === null) { $this->foo = new Foo(); } else { $this->foo = $foo; } } Poderíamos simplificar de várias formas, ainda sem ternário da pra dispensar o uso do else: public function doSomething(Foo $foo = null) { if ($foo === null) { $foo = new Foo(); } $this->foo = $foo; } Com operador ternário: public function doSomething(Foo $foo = null) { $this->foo = $foo === null ? new Foo() : $foo; } Ou, o caso acima ainda poderia ser reduzido a: public function doSomething(Foo $foo = null) { $this->foo = $foo ?: new Foo(); } Não me recordo se funciona em outras linguagens, mas em PHP caso a condição seja verdadeira e nada tenha sido especificado para a condição verdadeira o PHP retorna o próprio valor da condição. $foo = null; var_dump($foo ?: 10); // int(10) $foo = 20; var_dump($foo ?: 10); // int(20)
  5. 5 pontos
    O que você precisa entender é que há tipos de exceções, como as classes citadas por você mesmo (LogicException, RuntimeException...). Todas estas classes são filhas da superclasse (classe pai) Exception. A vantagem de se usar é facilitar o manuseio, por exemplo: class Foo { public function bar($value) { if (!is_int($value)) { throw new InvalidArgumentException('Value is not integer'); } if ($value < 0) { throw new LogicException('Value is negative'); } } } A lógica contida no exemplo é apenas uma foma demonstrativa.. O método bar() pode disparar dois tipos de exceções, LogicException e InvalidArgumentException. Agora supondo que eu deseje capturar apenas as exceções do tipo LogicException caso alguma seja disparada, isso é fácil. try { (new Foo)->bar(-10); } catch(LogicException $e) { echo $e->getMessage(); // Value is negative } Eu também poderia ter mais um bloco catch para tratar o tipo InvalidArgumentException: try { (new Foo)->bar('string'); } catch(LogicException $e) { echo $e->getMessage(); } catch(InvalidArgumentException $e) { echo $e->getMessage(); // Value is not integer } Se lembra quando eu disse que todos esses tipos de exceção são classes filhas da superclasse Exception? try { throw new RuntimeException('...'); } catch(RuntimeException $e) { var_dump($e instanceof Exception); // bool(true) } E caso você queira capturar qualquer um dos tipos de exceção faria: try { (new Foo)->bar(-10); } catch(Exception $e) { echo $e->getMessage(); // Value is negative var_dump($e instanceof LogicException); // bool(true) } Mas você também pode criar os seus próprios tipos de exceção estendendo qualquer classe de exceção tando a superclasse Exception quanto as classes filhas: class MyException extends Exception { } Usando.. throw new MyException('Message...'); Sempre que quiser tratar/capturar exceções.. exceções não capturadas como você já deve saber interrompem a execução. Espero que tenha entendido ;)
  6. 5 pontos
    Você está no caminho.. Não só para configurações, para qualquer uso globais não devem ser usadas. Ótimo! Nananinanão! São configurações, devem ser facilmente configuradas..sem contar que isso não seria configurável, você estaria preso as constantes. Acredito eu que não haja "melhor opção", o projeto deve dar suporte à opções. Bom, irei sugerir uma forma bacana..você poderia ter uma classe configurações que as carregasse de várias formas possíveis e ao mesmo tempo as representasse, por exemplo: class Config { private $configs = array(); public function __construct(array $configs) { foreach ($configs as $name => $config) { $this->set($name, $config); } } public static function load($configs) { if (is_string($configs) && is_file($configs)) { if (!file_exists($configs)) { throw new InvalidArgumentException(sprintf( 'Ops! File of configurations not exists in "%s', $configs )); } $ext = pathinfo($configs, PATHINFO_EXTENSION); switch ($ext) { case 'ini': $configs = parse_ini_file($configs, true); break; case 'php': $configs = include $configs; break; default: throw new InvalidArgumentException(sprintf( 'Extension "%s" not supported', $ext )); break; } } elseif (!is_array($configs)) { throw new InvalidArgumentException(sprintf( 'Type "%s" not supported for configurations', gettype($configs) )); } return new self($configs); } public function set($name, $value) { if (is_array($value)) { $value = new self($value); } $this->configs[$name] = $value; } public function get($name) { if (!isset($this->configs[$name])) { throw new InvalidArgumentException(sprintf( 'Configuration not found for "%s"', $name )); } return $this->configs[$name]; } public function __set($name, $value) { $this->set($name, $value); } public function __get($name) { return $this->get($name); } } Usando.. Carregando configurações a partir de um array: $config = new Config(array( 'database' => array( 'host' => 'localhost', // ... ) )); A partir de um .ini: $config = Config::load('/path/to/file.ini'); ou até mesmo um arquivo php com um array: file.php return array( 'host' => 'localhost', // ... ); $config = Config::load('/path/to/file.php'); Acessando parâmetros: echo $config->database->host; // saída: localhost Repare que todos os arrays se transformaram em objetos..e recursivamente, portanto: var_dump($config->database instanceof Config); // bool(true) Para resolução de nomes também é possível: echo $config->database->get('db.host'); Alterando ou adicionando um parâmetro: $config->database->host = '127.0.0.1'; Setando configurações: class Connection { public function setConfig(Config $config) { // ... } } $connection = new Connection(); $connection->setConfig($config->database); O exemplo é apenas uma forma de demonstrar.. Uma outra forma poderia ser: interface DatabaseConfiguration { public function getDatabaseConfig(); } class Configuration implements DatabaseConfiguration { public function getDatabaseConfig() { return array( 'host' => 'localhost', // ... ); } } Espero ter contribuído ;)
  7. 4 pontos
    No decorrer da minha experiência como dev, eu vi muitas decisões ruins, algumas delas eu mesmo sugeri. Mas, a que mais me impressionava era quanto ao projeto base e suas customizações. Pensando apenas em code (sem entrar em banco de dados), eu utilizaria uma mescla entre o GIT e o composer. Branch's e divisões No GIT: Dividir as branchs em 5 tipos (serão mais branchs): master, cutom-*, homologacao-*, dev-* e hotfix-*; A branch master será única e exclusivamente para o código base não customizado; A branch custom-*, será específica para o código homologado do projeto customizado para uma empresa (custom-empresa01, custom-empresa02, etc..); A branch homologacao-* será específica para homologar a transição do código de dev para prod, aonde testes de alto nível são aplicados. Cada branch de produção (master/custom) terá sua respectiva branch de homologação (homologacao-master, homologacao-custom-empresa01, etc); A branch dev-* é aonde é realizado o desenvolvimento, ela são livres, aonde o "desenvolvedor não conhece as leis" ou "o filho chora e mãe não vê", etc.. Você deve ter quantas forem necessárias, para cada implementação, cada GAP, cada moficação (dev-master-task-2784, dev-custom-empresa01-task-3500, etc...); A branch de hotfix-* é aquela correção rápida, aquele conflito do merge entre uma entre o código base e uma customização ou que está implicando em parada geral do sistema (aquele bug ou erro de português que passou pela homologação/testes), que não necessariamente deve passar por todos os passos de desenvolvimento/homologação/produção. O que nós normalmente chamamos de "codificar em prod"... Sim, isso existe na realidade de todos já fizeram. Essa é a definição da árvore do projeto. Os caminhos a serem seguidos: dev-master-* <--> homologacao-master <--> master --> homologacao-custom-* <--> custom-(todas as empresas); dev-custom-* <--> homologacao-custom-* <--> custom-*; hotfix-* <--> para aonde for necessário. Perceba que no fluxo, uma custom nunca deve levar o seu código para a master. Apenas a master pode levar códigos para a custom. Sempre utilizando a branch de homologação da custom. Fork Uma característica bem interessante dos serviços de controle de versionamento (bitbucket, github, etc...) é a possibilidade de criar um fork de um projeto. O seu projeto CORE será o repositório principal e, para cada cliente, você criará um novo fork. Logo, você terá o projeto master e os forks para cada cliente (master -> cliente-01 -> cliente-02, etc...). A divisão entre branchs, deve ser a mesma exemplificada exclusiva para a master. Ou seja, 4 tipos: master, homologação, dev-* e hotfix-*). A nomenclatura das branchs (mster, homologacao, dev-* e hotfix-*) segue a mesma definição anteriormente explicada. A parte de fluxo será o que está exemplificado abaixo: dev-* <--> homologacao <--> master; hotfix-* <--> para onde for necessário. O cuidado, vem na hora de sincronizar os forks. O BitBucket, por exemplo, lhe sugere um fork automático entre as branchs masters de cada repositório. Entretanto, para um melhor controle e validação do novo código, a sincronização deve ocorrer entre a branch master, do projeto master, para a branch homologacao do projeto customizado. Ou seja: Master:master --> Cliente-01:homologacao; Dessa forma, você pode homologar, corrigir e enviar para a produção (master) da customização de clientes. No BitBucket, para realizar tal feito, você pode ir no menu compare, escolha a branch da qual está o código (parte de baixo) e a branch na qual você quer enviar o novo código (branch de cima). Compare as diferenças e, no canto direito superior, o BitBucket lhe exibirá o botão merge. Feito o merge, o processo é exatamente o mesmo que utilizando branchs. Módulos Aqui é que entra a questão de módulos. Caso você implemente partes do sistema como módulos, você pode usar tanto o git-submodule ou o composer. Com ambos você poderá utilizar repositórios privados para baixar as suas dependências. Para cada módulo, você deverá ter o repositório separado e, caso o repositório separado seja customizado, poderá seguir a estruturação acima mencionada. Entretanto, no caso de módulos personalizados, acredito que com o git submodule não seja possível separar entre versões (branch/tags) específicas para cada projeto/branch. No caso do composer é possível, pois, cada branch/projeto, terá seu próprio composer que pode ser personalizado. Banco de dados Nesse caso, vai depender muito do que você irá utilizar para gerenciar o SGBD. Eu utilizei por muito tempo o MySQL WorkBench. Ele funciona perfeitamente quando o assunto é modelagem e sincronização. Entretanto, o formato de arquivo gerado por ele não é aberto e, em consequência, não pode ser versionado. Logo, quando uma tabela precisar ser diferente em algum projeto, você terá dois arquivos distintos. Há, também, a possibilidade de tratar tudo na forma de SQL scripts. Mas ficaria sem uma ferramenta de apoio. Talvez alguém conheça alguma ferramenta melhor para a situação. A contra-partida Quando você separa pequenas partes de um projeto em módulos e os adiciona como dependências do seu projeto, você pode encontrar uma situação denominada Dependency Hell. Esse termo também pode ser utilizado para a manutenção do código entre as branchs, pois, todas as suas customizações necessitam estarem atualizadas com a branch master. E se você almeja 30 empresas, pense que uma mudança no CORE precisa ser homologada para as 30 empresas. Considerações Sendo dicas como elas são, apenas dicas, você pode considerar demasiada estrutura e simplista ou exagerada demais e partir para uma abordagem meio termo ou mais robusta. Tudo dependerá de onde você está e para onde gostaria de chegar. Existem outras ferramentas e abordagens que pode lhe ajudar. Uma delas seria a integração contínua, o qual incluí N outras ferramentas de auxílio. Update Um sistema que gerencia suas próprias customizações acaba sendo limitado a campos e novas informações. Eu, particularmente, não gosto muito da prática. Entretanto, para evitar o problema com o SGBD, pode-se utilizar tabelas de cadastros par atributo-valor para cruzar informações dinâmicas e reduzir a necessidade de criar novas colunas e tabelas. Mas, é uma questão bem limitada. Update 2 Com a nova parte de forks (que eu não havia me lembrado anteriormente), seria a sugestão mais indicada. Pois, se você possuir uma equipe de desenvolvimento específica para cada cliente, poderá gerenciar muito melhor as permissões e acessos. O controle é bem superior a de um repositório apenas.
  8. 4 pontos
    Olá iMasters, É com grande satisfação que estamos adicionando o @wings ao grupo seleto de Masters do fórum iMasters, que inclui membros que fizeram grandes feitos pelo fórum e também pessoas que são tidas como grandes referências no que fazem. Durante suas atividades no fórum iMasters @wings foi um excelente moderador da área de Segurança e Malwares desde Novembro/2009 até Setembro/2013 quando saiu a pedido por falta de tempo. Neste tempo contribuiu em aproximadamente 800 tópicos com problemas diversos dos membros nesta área. Dr. Fernando José de Paiva Coelho, nome verdadeiro de wings, Era médico e professor com especialização e pós-graduação em ortopedia e traumatologia. Faleceu de infarto do miocárdio agudo em 06/02/2014; em Miguel Pereira - RJ ; aos 52 anos de idade. Receba @wings essa justa homenagem póstuma do fórum que você ajudou a crescer também na área de Segurança e Malwares. Descrição dos grupos do Fórum iMasters: http://forum.imasters.com.br/topic/297370-grupos-de-usurios-frum-imasters/#entry1089308
  9. 4 pontos
    Boa tarde ! À todos Crio este tópico para homenagear ele; pois sabemos se ele estivesse aqui; logo nos responderia . Uma imensa perda para a informática e para seus familiares . O analista Wings faleceu no dia 06/02/2014 ; em Miguel Pereira - RJ . http://www.hardware.com.br/comunidade/fiqueitriste-perdemos/1338398/ A esposa dele retribuiu o carinho e dedicação que ele tinha por nós . Abraços
  10. 4 pontos
    Experimente habilitar todos os erros do PHP e trabalhar em modo STRICT... Ate retorna o valor, mas vai te retornar tambem um Strict Standards... Sem contar que os namespaces não servem para "apelidar" as classes, ou só pra isso. Servem principalmente para trabalharmos melhor com autoload de classes, seguir o padrão da PSR-0 e evitar conflitos com nomes de métodos e classes de dferentes "vendors" Alguém pode me explicar como esta declaração abaixo utilizando somente o namespace esta pronta para uso. sem usar new ou classname::function() Veja um exemplo com o validation: Também fiquei curioso quando vi o código do Respect\Validation. Se você se aprofundar um pouquinho mais, talvez fique ainda mais curioso como eu fiquei, ao ver coisas como ReflectionClass e __callStatic, acho até que é essa parte que o fez ficar curioso no código... Chamar uma função de outra classe sem a instanciar ou a chamar diretamente pelo static (Class::method()) :rolleyes:
  11. 4 pontos
    Não. A discussão sobre goto começou há 46 anos, quando o Dijkstra publicou um dos artigos mais relevantes e populares da computação até os dias atuais, chamado Go To Statement Considered Harmful. Para começarmos com funções, lembremos que o conceito de uma função é um tanto quanto diferente do modo em que as usamos em linguagens imperativas. Uma função, no conceito puro, poderia ser representada pela seguinte imagem: Apesar de não parecer tão claro à primeira vista, a imagem simplesmente define o conceito de que uma função recebe valor(es) e retorna um valor, sempre de forma transparentemente referencial, ou seja, mesmo input => mesmo output. O que exclui esse conceito puro da maioria das linguagens é que nós precisamos, de algum modo, manipularmos coisas impuras (que não são transparentemente referenciais), como I/O, tempo e dados randômicos. Sem elas, programação seria apenas algo matemático, sem uso prático como temos hoje. Quando funções usam outras funções impuras, elas se tornam impuras pelo fato de perderem a transparência referencial. Outro ponto é que com isso fica justificada a existência de funções que não têm valor de retorno (void para os íntimos) e funções que não recebem parâmetros. Como exemplo, veja essa função abaixo: <?php function doImpureStuff() { echo 'I\'m impure!'; } doImpureStuff(); Ela não retorna nada, nem recebe nada, apenas imprime algo na tela, realizando um side-effect a cada chamada. Agora veja essa outra função: <?php function makeStringHappy($string) { return $string . ':)'; } $happyString = makeStringHappy('Heeey'); // 'Heeey :)' Esta recebe uma string e retorna uma string, retornando o mesmo valor para o mesmo input. Isso seria uma representação prática da imagem do início do post. Agora falando de gotos, eles são simplesmente uma chamada para um label, sem input, sem valor de retorno e sem escopo. É puramente uma forma de reutilização em programação procedural. Os mais próximos a ele seriam break e continue, mas não uma função. O ponto de uma função não é executar um comportamento, mas sim trocar mensagens (input => output). PS: Não faço ideia de como referential transparency seria traduzido para português, logo fiz a tradução ao pé da letra, usando transparência referencial.
  12. 4 pontos
    Vamos lá. O primeiro ponto é que estrutura de pastas não define ou muda absolutamente NADA. Isso é apenas uma questão de organização e não há padrão algum definido. Classes começam com letra maiúscula (StudlyCaps). É um padrão seguido por todas as linguagens há décadas. E se você quiser trocar isso? Terá que editar a classe, o que a torna não-reutilizável. Configuração não é parte da classe, é parte do objeto. Esses dados deveriam ser passados pelo construtor. mysql_* produz E_DEPRECATED a partir do PHP 5.5 e não tem suporte há anos. Além disso, arroba é uma má prática. A PDO substitui toda essa classe facilmente. Se sua intenção é tratar erros (o que é), use exceptions. Retornar true/false para isso é uma gambiarra tamanha (admissível em C). Todo o propósito da orientação a objetos vai por água abaixo aqui. Crud pode ser feito em qualquer tipo de data storage, não somente num banco de dados. Aqui você precisa ter uma abstração para diminuir o acoplamento. Guarde bem essas duas palavras, são bem importantes em OO. Todo construtor é void, ou seja, não retorna nada. Construtores apenas constroem objetos. Por que se a consulta falhar o sistema tem que morrer? Novamente, use exceptions. Side-effect não relacionado com CRUD, separe as responsabilidades das classes. O resultado disso é um erro Headers already sent piscando na telinha. Autoloading e PSR-0. E se esses campos não estiverem preenchidos? Um array não garante nada, é necessário, no mínimo, um isset. Outro ponto é que um cadastro deveria ser um simples VO, não há a necessidade de setters, basta um construtor. Você precisa de um URL router. Não é responsabilidade da view chamar um controller. :seta: Classes não são repositórios de procedimentos.
  13. 4 pontos
    Orientação a Objetos não tem como um dos mais básicos objetivos representar o mundo real de forma programática? Um objeto Porta representa uma porta no mundo real, com suas características (proprieddes) e ações (métodos). Declarar uma classe, que representa um objeto, como final é como dizer que aquele objeto não pode gerar subprodutos dele mesmo. Por exemplo, imagine um objeto Porta e um objeto Portão. Ambos são basicamente a mesma coisa, tem características partilhadas, ações em comum, mas um Portão tem algumas coisas que uma Porta comum não tem (controle remoto, talvez). Se você declarar a classe Porta como final, você está dizendo que não podem existir variações de uma Porta. Mas sabemos que um Portão é uma Porta, maior e com mais techie techie, mas ainda assim, na sua essência, uma Porta. Agora imagine o mesmo para um Portão. O que poderia derivar de um Portão? Uma ponte levadiça medieval talvez, mas lembremos que classes filhas compartilham características e comportamentos da classe-pai e um Portão tem coisas que não tinham na época dos castelos. Por isso declarar um Portão como final, é plausível, pois ele é um objeto final, Nada pode derivar dele. E se quiséssemos uma Ponte Levadiça, estenderíamos de Porta que é muito mais sensato. Conceitualmente, o mesmo vale para os métodos, mas para os métodos a coisa não é assim tão evidente e eu prefiro deixar que os especialistas em O.C.P expliquem.
  14. 3 pontos
    Orientações e Regras do Fórum de PHP Siga estas simples Orientações e Regras e seus tópicos serão até 1297% mais eficientes, com mais visualizações e respostas. Regras 1 - Use Títulos Condizentes Com Suas Dúvidas Descreva no título do tópico exatamente o que você precisa, qual é sua dúvida ou problema. Evite títulos como: "Ajuda", "Help" e títulos que sejam generalizados demais. Jamais escreva "URGENTE" o título do tópico. Tudo que é urgente é aquilo que deveria ter sido feito por você ontem mas não foi feito. 2 - Estamos Aqui Para Orientar Poste um trecho do que você já fez. Estamos aqui para te orientar e para te ajudar a aprender. Não vamos fazer seu trabalho por você. 3 - Tenha Calma e Paciência Não responda o próprio tópico com a intenção de atualizá-lo (UP). Todos nós temos trabalhos próprios e outros compromissos. Os membros do fórum responderão os tópicos quando possível. E vale lembrar que Moderadores não têm obrigação de responder tópicos. Eles estão aqui essencialmente para auxiliar na organização do fórum. 4. Para Dúvidas, Use o Fórum Não envie dúvidas por MP (mensagem privada). Para isso utilize o fórum, dessa forma em vez de apenas um, muitos membros poderão ajudar você a resolver seu problema, além de a solução ficará publicada, para ajudar muitos outros usuários. 5. O fórum de PHP é relacionado EXCLUSIVAMENTE à linguagem de Programação PHP Ao iniciar um tópico no fórum de PHP, certifique-se de que sua dúvida está relacionada com a linguagem PHP, seguindo o contexto do fórum. Se sua dúvida for relacionado a qualquer outra linguagem, tecnologia ou framework, como jQuery, Ajax, HTML, procure o fórum correspondente para tratar do assunto. Orientações 1. Seja Claro e Específico Descreva sua dúvida da forma mais clara possível. Explique o máximo que puder. Muitas vezes, você tem a ideia bem clara em sua cabeça e tudo parece simples, mas quem lê o tópico não vai entender, se você não explicar detalhadamente. 2. Use a Tag Código Sempre que postar códigos, adicione-o entre as tags [ code ] e [ /code ] (sem os espaços), para facilitar a leitura. Você também pode usar o Botão Code (símbolo "<>"), ao lado do Botão Imagem, no editor de textos do fórum. 3. Habilite Todas as Exibições de Erro Configure seu código para exibir TODAS as mensagens de erro, adicionando este código ao topo do script. ini_set('display_errors', true); error_reporting(E_ALL); 4. Leia as Mensagens de Erro Leia os erros que aparecerem, pois normalmente eles dizem o que há de errado no código. Verifique se o erro está na lista dos erros mais comuns do PHP. Você pode corrigi-lo facilmente, sem precisar abrir um tópico só para isso. Se não entender as mensagens de erro, poste-as em seu tópico, apontando a linha exata onde ele ocorre. Assim saberemos onde está o problema 5. Faça Debug de Suas Queries Exiba os erros do banco de dados, para ajudar no debug, seguindo estes exemplos: // Para MySQL mysql_query("sua query aqui") or exit(mysql_error()); // Para MySQLi // ($mysqli é o link de conexão, retornado por mysqli_connect) mysqli_query($mysqli, "sua query aqui") or exit(mysqli_error($mysqli)); // Para PDO sem Prepared Statements // ($PDO é o objeto PDO, retornado por "new PDO") $PDO->query("sua query aqui") or exit(print_r($PDO->errorInfo(), true)); // Para PDO com Prepared Statements // ($stmt é o objeto PDOStatement, retornado pelo método prepare) $stmt->execute() or exit(print_r($stmt->errorInfo(), true)); 6. Dúvidas Sobre Uma Função do PHP? Se a dúvida for sobre a utilização de uma função, leia o manual dela, acessando php.net/nome_da_funcao. 7. Marque Seus Tópicos Como Resolvido Quando um membro postar algo que resolva seu problema, marque esse post como solução. Uma vez marcado como resolvido, o post útil será mandado para o topo da página, facilitando a visualização de todos que o procurarem. 8. Evite Citação Desnecessária Ao utilizar o botão "Citação" ou "Multicitação", no canto inferior direito de cada post, o conteúdo do post será inserido em sua resposta, para citação. Isso ocupa bastante espaço na tela. Por isso, apenas cite quando realmente necessário. Prefira usar o botão Responder, inserindo apenas a sua resposta. 9. Apenas Uma Dúvida Por Tópico Ao criar seu tópico, seja claro na sua dúvida e mantenha somente uma dúvida por tópico. Não aproveite tópicos com dúvidas de outros usuários para postar sua dúvida. Nesse caso, abra um novo tópico 10. Utilize fonte simples Não escreva em CAIXA ALTA nem utilize formatação em todo o conteúdo do tópico, para deixar o texto mais visível (aumentar fonte, negrito/itálico). Formatação é necessária somente para destacar trechos importantes do texto, não para o conteúdo inteiro. Além de dificultar a leitura, existe maior chance de o tópico ser ignorado pelos membros do Fórum. 11. De Novo, Seja Paciente Lembre-se que o fórum é composto por voluntários que também possuem seus próprios problemas e compromissos. Não espere uma resposta imediata, muitas vezes um membro que pode ter a solução para seu problema ainda não leu sua dúvida. Equipe iMasters
  15. 3 pontos
    Nao tem nenhuma layer por cima no CSS?
  16. 3 pontos
    Há tempos estou devendo esse post... A espera acabou! :) Está aí o post, fresquinho: http://rberaldo.com.br/captcha-acessivel-sem-utilizacao-imagens/ :thumbsup:
  17. 3 pontos
    Essa resposta envolve vários conceitos! =D A sintaxe é um método estático mesmo. Métodos estáticos sempre são chamados como NomeDaClasse::NomeDoMetodo, por exemplo: class Exemplo { public function naoEstatico() { } public static function estatico() { } } Exemplo::estatico(); // Métodos estáticos não tem instância $foo = new Exemplo(); No exemplo do Respect\Validation ele na verdade usa o método mágico __callStatic, que é um pouco diferente. Ele é chamado quando você chama um método estático que não existe: class OutroExemplo { public static function euExisto() { } public static function __callStatic($nomeDoDesconhecido, array $argumentos) { } } OutroExemplo::euExisto(); // Esse existe, chama ele OutroExemplo::abacaxiOuAnanas(); // Não existe, cai pra callStatic O que o Respect\Validation faz internamente é usar esse mecanismo pra conseguir encadear várias chamadas. Você não pode encadear vários "new" na mesma chamada de métodos, mas pode encadear vários métodos que criam instâncias dentro =) Chamadas encadeadas por __callStatic: v::string()->alnum()->length(1,20); Sem chamadas encadeadas: $string = new Respect\Validation\Rules\String; $alnum = new Respect\Validation\Rules\Alnum; $length = new Respect\Validation\Rules\Length(1,20); $v = new Respect\Validator($string, $alnum, $length); A ReflectionClass é uma classe que dá informações sobre outras. Por exemplo, se você quiser saber todos os métodos da classe PDO, você pode usar a ReflectionClass assim: $reflection = new ReflectionClass("PDO"); // Cria uma nova reflection $methods = $reflection->getMethods(); // Obtém os métodos print_r($methods); A array que esse código vai exibir vai ter um monte de instâncias de outra classe, a ReflectionMethod, que serve pra saber coisas sobre os métodos. Se você quiser uma lista com todos os métodos da PDO, pode fazer: $reflection = new ReflectionClass("PDO"); // Cria uma nova reflection $methods = $reflection->getMethods(); // Obtém os métodos foreach ($methods as $method) { print $method->getName(); } O Respect\Validation usa o método "newInstanceArgs", que é a mesma coisa que um "new" da ReflectionClass pra repassar os dados do __callStatic pra uma nova instância.
  18. 3 pontos
    Em termos de material para iniciante em php procedural: http://www.guanabara.info/2007/09/curso-de-php-aula-01/ http://www.criarweb.com/php/ http://www.php.net/manual/pt_BR/ Isso acima foi tudo que usei para aprender a linguem procedural, o restante é pratica. Acompanhar a comunidade, Stack Overflow e o próprio Imaster, vai lhe ampliar bastante o horizonte da linguagem. Se esforçar para entender as duvidas e artigos vai lhe ajudar mais do que os livros pois você vai estar lidando com problemas práticos e reais relacionados a linguagem. Dito isso claro que ter uma boa base é importante, a serie use a cabeça é bem conceituada, mas contém alguns problemas técnicos que podem confundir um iniciante total na linguagem, mas como já vez um curso leia a errata que você tira de letra o resto. Leia também o capitulo de amostra no site da editora e se você curtir a metodologia do livro ele vale muito apena, o outro livro eu já não conheço. Recomendo também depois que estiver firme em php procedural parta para PHP orientado a objeto. Neste quesito o melhor é aprender Java primeiro, pode parecer perda de tempo aprender uma linguagem que você não vai usar mas acredite na verdade é economia, por conta da tipagem fraca e falta de material da linguagem PHP a curva de aprendizagem de orientação a objeto direto em php é muito maior. Você também vai precisar entender java para entender os livros mais importantes de Orientação a objeto. Neste Ponto eu recomendaria mais ou menos nesta ordem: - Java, Use a cabeça: Se você gostou da metodologia caso contrario procure outro de java iniciante. - Padrões de projeto, Use a cabeça: Mesmo que você não seja fã da serie esse vale apena conferir. - Código Limpo: Ajuda a melhorar muito o seu código além de lhe orientar em termos de bons princípios técnicos. - Padrões de Projeto - Soluções Reutilizaveis de Software Orientado a Objetos: Um catalogo. É obrigatório dominar todos os padrões deste livro. - Objetos PHP Padrões e Pratica - Zandstra: Depois que você aprender Orientação a Objeto e padrões vai precisar transpor isso para PHP esse livro vai lhe ajuda muito. Recomendaria ainda os seguintes livros eles não vão lhe acrescentar um grande conhecimento técnico depois que você ja leu todos os livros acima mas ainda sim vão lhe ajudar a se tornar um profissional melhor no que diz respeito a conduta e ao que se espera de um programador profissional. Pensando bem leias os livros abaixo antes que eles vão lhe apontar o caminho das pedras. O Programador Pragmatico Codificador LImpo
  19. 3 pontos
    Entendi! Então o jeito é começar a estudar o PDO também... Já que vamos melhorar, vamos melhorar em tudo, obrigado galera! :joia:
  20. 3 pontos
    Sou usuário do iMasters desde 2003. Geralmente, sou um observador e tento interagir nas dúvidas um pouco mais complexas ou, quando o bicho realmente está pegando para o usuário, dou uma mãozinha para ele tocar vida. Desta forma acredito que o membro tem um tempo maior para refletir na dúvida dele e ver se não consegue resolver seu problema sozinho ou com a ajuda de um outro membro que pode ter a paciência de ler um post onde a pessoa posta o site inteiro no tópico aberto (paciência esta que no meu comentário do perfil já deixo explícito que não tenho). Em algumas dúvidas, encontrei boas ideias para desenvolvimento, dentre as quais resolvi desenvolver e disponibilizar soluções, como um editor de etiqueta com jQuery, o qual agora também uso em projetos pessoais. Mesmo que eu pareça ser pouco ativo, diariamente - tanto pelo desktop quanto smartphone - sou um usuário sempre atento aos posts dos fóruns (principalmente PHP). Duas situações, completamente opostas, sempre me chamaram a atenção. A primeira, e mais satisfatória, é participar da construção do conhecimento do membro. É ver que ele realmente está se empenhando em resolver um caso e não simplesmente está esperando a resposta milagrosa cair no seu colo e ele possa ganhar dinheiro com aquilo ou resolver sua situação de maneira que nenhum conhecimento foi agregado. Acho que a grande "magia" de participar de um fórum, é ver que o seu conhecimento auxiliou no crescimento de uma outra pessoa. E, ao mesmo tempo, ver que aquela pessoa teve humildade e interesse em ler e estudar o material passado. Isto para mim é muito recompensador. Gosto muito, por exemplo, de ver os posts que o João participa, porque nota-se que ele dedica um tempo precioso da vida dele para ajudar outras pessoas. De igual forma, outras pessoas o fazem - desprendem-se do que estão fazendo para auxiliar outras pessoas. Isto mostra o real sentido de um fórum - ajudar na construção do conhecimento. A segunda, e muito frustrante, é a falta de humildade em alguns casos de quem procura ajuda. Na maioria absoluta das vezes, as respostas dadas a um tópico aberto são cuidadosamente pesquisadas pelo membro que se dispôs a ajudar, como comentado no parágrafo anterior. Ou até mesmo o membro já sabia de uma referência de cabeça e enviou para o membro que procura auxílio. Entretanto, em algumas situações, estas respostas são tratadas com desdém e ironias. Além de, na maioria destes eventos, esperarem as respostas prontas para códigos encontrados na net, para que os membros do fórum adaptem o código encontrado para "rodar" no ambiente deles. Na minha opinião, estes tipos de pessoas prostituem nosso mercado, fazendo com que cada vez mais nossos postos de trabalho (muitas vezes conquistados de forma muito suada) venham pagar cada vez menos por um bom profissional. As vezes, confesso que acabo perdendo um pouco a paciência com pessoas que fazem este tipo de coisa, mas também acho que nós, como profissionais de TI, deveríamos filtrar um pouco mais as respostas que vamos dar, no sentido de não fazer todo o trabalho para outrem, e sim, como já citado, ajudar na construção do conhecimento. Abraços.
  21. 3 pontos
    Boa tarde a todos Hoje recebi um pedido muito especial de um cliente, uma forma de que a pessoa selecione o pais e puxe os estados desse país. Logo saí a procura de uma lista pronta como era "obvio" que deveria existir, porem para minha surpresa não consegui encontrar nada que fosse satisfatório, apenas SQLs com continentes e países mas sem estados, ou apenas os estados brasileiros, depois de perder 2 horas procurando resolvi criar o meu próprio SQL e disponibilizar para quem, assim como eu, precisar utilizar algum dia. https://github.com/rodrigoborth/SQL_Mundi Gostaria de pedir a colaboração de todos para que possamos expandir e otimizar esse SQL, pois acredito que qualquer programador algum dia irá precisar de algo parecido e não temos tempo de conferir mais de 200 países e milhares de estados/províncias para sabermos se temos tudo que precisamos
  22. 3 pontos
    Fazendo dessa forma, você perde toda a integridade que um SGBD pode fornecer. O correto é utilizar uma tabela N:N, também conhecido como many-to-many (muitos para muitos). Nada mais é que uma tabela intermediária, entre categoria e artigo, que servirá como link entre um artigo e uma categoria. Tal como na imagem abaixo: Onde a tabela category_has_product cria um link entre category e product. Também parte da normalização de dados.
  23. 3 pontos
    Sim, o nome é este mesmo, dereferencing. A possiblidade de se utilizar chaves vem do contexto histórico do PHP e a influência de PERL e ShellScript na construção da sintaxe. É o mesmo motivo pelo qual todas as variáveis devem ser iniciadas com [inline]$[/inline]
  24. 3 pontos
    Uma solução e usar PDO, mysql_ esta obsoleto. Segue um slide com as principais vulnerabilidade http://odesenvolvedor.andafter.org/publicacoes/seguranca-com-php-slides-_1421.html
  25. 3 pontos
    Calcula, pra mim, a raiz quadrada de 1048576 e me diz se vale a pena ou não utilizar calculadora ;)
Esse placar de líderes está definido para São Paulo/GMT-02:00
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.