Faça um grande negócio de == verdadeiro?

105

Há um colega meu que escreve constantemente:

if (someBool == true)

Me leva até a parede! Devo fazer um grande negócio ou simplesmente largar?

JoelFan
fonte
12
Eu prefiro o explícito, if (some_flag == true)mas o implícito if (is_something)ou if (has_something). Observe os nomes das variáveis.
Fredoverflow 18/10/10
69
Lembre o seu colega de que o tipo de someBool == truetambém é booleano; portanto, pela mesma lógica que deveria ser if ((someBool == true) == true).
Mike Seymour
2
@GSto: Suponho que você saiba, mas no PHP você pode fazer isso para "converter" qualquer coisa em um bool e pode ser realmente útil.
zneak
2
@ zneak Ou você pode ser mais claro e usar $var = (bool) some_expression. E na maioria dos casos, isso nem importa, já que o PHP fará as conversões necessárias dinamicamente.
precisa
4
verifique sempre o primeiro, se (true someBool ==) constante, no caso de você acidentalmente digitou = em vez de == [sim eu estou brincando!]
Steven A. Lowe

Respostas:

126

É apenas código redundante, não vida ou morte. Contudo....

Se isso estiver acontecendo muito, pode haver um problema com o someBoolnome. Um bom nome pode contribuir bastante para eliminar a necessidade de==true

if(IsSomeCondition)

ou

if(hasCondition)

ou

if(somethingExists)

por exemplo.

Robert Harvey
fonte
Isso soa muito verdadeiro para mim. Tudo se resume à clareza e à arte de nomear, a sintaxe original não é tão ruim, mas esse é o caminho certo para um melhor código.
TJB 19/10/10
2
Bata-me para isso! Sem nomeação apropriada, a equivalência mais sucinta não faz nenhum sentido.
Troy caça
4
Eu tive que usar o someBool == truecódigo legado várias vezes para maior clareza. Mas se eu escrever do zero, if (isSomething)
nomeio
Concordo que, mesmo que a nomeação resolvesse isso, assumindo que o nome fosse SomeBool, poderia significar qualquer coisa e ser de qualquer tipo (um número inteiro igual à quantidade de booleanos em uma matriz, talvez?). Os booleanos precisam de algum tipo de verbo existencial, ou sempre serão difíceis de ler por si próprios.
Morgan Herlocker 19/10/10
Eu concordo, é tudo uma questão de legibilidade. Se as variáveis ​​forem bem nomeadas, você não precisará delas. Se a expressão lê melhor com ela, eu usaria "== true", também será consistente se você usar "== false" em vez de (o feio) "if (! ())".
Ronny Brendel
71

Quando vejo someBool == true, não consigo deixar de sentir que o programador não internalizou a ideia de avaliação , que é uma deficiência bastante fundamental.

No entanto, minha perspectiva é distorcida porque passei vários verões na faculdade ensinando programação para crianças, que frequentemente escreviam expressões como essa porque realmente não dominavam o exercício mental de avaliar uma expressão. Depois que eles adotaram o conceito, a redundância se tornou óbvia.

Para um programador profissional competente, esse provavelmente não é o caso. Provavelmente é apenas um mau hábito que eles desenvolveram nos seus primeiros dias de programação e nunca se abalaram. Mas ainda me assustaria um pouco se fosse a primeira coisa que vi alguém fazer em uma entrevista.

Tim Goodman
fonte
Eu não iria rapidamente atribuir isso ao hábito. Eu ouvi algumas coisas realmente impressionantes da boca dos programadores profissionais. Normalmente, seguido pouco depois por um dos grokkers, "Como isso nunca funcionam?"
traço-tom-bang
12
Concordo plenamente com a avaliação. Na ocasião, eu me perguntava: "Onde isso pára?" if (((((= = true) == true) == true)! = false) // //)) // e assim por diante ...
yawmark
1
Às vezes eu escrevia if (c == true) return true; else return false;, mas 99% do tempo (o 1% existe, já que nunca posso ter certeza de que não perdi alguns) notarei imediatamente e substituirei a coisa toda return c. Espero que a maioria dos programadores competentes faça algo semelhante se desenvolverem o hábito no início de sua carreira. O que eu não esperaria é uma resposta wtf.
Lie Ryan
1
Oh garoto, a arte de pensar. Eu literalmente deparei com isso em nossa base de código na semana passada. if (!someCondition) { someCondition = false; }Eu já vi algumas (er, muitas) redundâncias, bem como algumas impossibilidades em nosso código, mas essa foi tão simples, mas tão irritante ao pensar que alguém realmente a escreveu. Várias vezes, até.
Anthony Pegram
1
Basta notar que eu tenho visto alguns casos de if(x) x=true;que não foram redundante, mas sim o equivalente a x=!!x;(normalizar x a 0/1)
jkerian
58

Isso também me deixa louco, mas eu diria que mencione a redundância de uma maneira construtiva e a abandone, mesmo que não concorram.

Como alternativa, você pode tentar esta abordagem:
Você : Você pode começar a usar a seguinte convenção de código para avaliar os booleanos?

if (someBool==true)&&(true==true) {}

Eles: Por que faríamos isso? A segunda metade dessa afirmação é redundante, sempre avaliada como verdadeira.

Você: Por George, você está certo. Eu tolo. Vamos apenas seguir uma versão sem toda redundância. E se?

if (someBool) {}
JohnFx
fonte
6
Sim, concordou. É bobagem, mas você precisa escolher suas lutas, e esse código está realmente fazendo o que seu colega faz. Mencione isso de uma forma que não "O que diabos está errado com você ?!" tipo de caminho, então largue-o. Apesar de se começar a puxar porcaria como "if (! SomeBool = true)" ou "if (! SomeBool == true)" ou outros tais circunvoluções, que pode ser uma luta vale a pena escolher ....
BlairHippo
3
Como (someBool == false) é pior do que if (someBool == true)?
FinnNk
5
true=truenão compilar, você não pode atribuir a true;-)
fredoverflow
1
Eu me acostumei com if(somebool == false)ou !=, mas sempre contra falso e não verdadeiro. Acho que é redundante, mas como o padrão de codificação insiste que if()parece uma função chamar o espaço em branco entre os parênteses me ajuda a lê-lo. Sozinho, um bool é um bool, mas if (somePointer)não voa; Eu prefiro, if (somePointer != NULL)pois um ponteiro não é um bool.
dash-tom-bang
5
É sobre a legibilidade, não falta de lógica ou (micro) -redundancy
Ronny Brendel
45

Penso que, se algo tão trivial é o seu maior problema com seus colegas de trabalho, você deve se considerar bastante sortudo.

GrandmasterB
fonte
5
Bem colocado, é bom procurar a perfeição, mas certamente existem peixes maiores para fritar
TJB
3
Eu acho que você diz isso sobre todo problema que merece discussão.
Dave Van den Eynde 19/10/10
2
É potencialmente indicativo de problemas muito maiores. Uma pequena mancha marrom no teto da sua garagem pode não parecer grande coisa, mas pode significar que você tem um grande vazamento de água.
19339 Josh
42

Você definitivamente deveria parar com esse mau hábito. Suavemente...

É fácil esquecer de escrever os dois sinais de igual, transformando o código em:

if (someBool = true)

Em C #, por exemplo, isso produzirá apenas um aviso, não um erro. Portanto, a menos que você trate os avisos como erros, o código será executado, defina a variável como true e sempre insira a condição.

Guffa
fonte
6
Este não é um argumento relevante. Se você estiver trabalhando em um idioma como esse, poderá simplesmente mover o verdadeiro para o outro lado. A questão é sobre a inclusão ou não da verdade.
Cam
8
@Cam: Faltando o ponto é você. Lógica reversa, não estou sugerindo.
Guffa 18/10/10
15
@Cam - Ele está dando um exemplo do mundo real de quando isso pode ser um problema. Eu diria que isso é bastante relevante.
ChaosPandion
1
@Guffa Cam está muito certo. Este não é um motivo para parar de usar == (anyType) nos blocos if.
Ronny Brendel
2
@ Ronny: Não, isso não pode acontecer com nenhum tipo (a menos que o idioma realmente permita qualquer tipo como condição). A declaração if (answer = 42) {}simplesmente não é compilada porque a expressão não é booleana.
Guffa
21

Eu concordo com você, mas vou interpretar o advogado do diabo aqui:


Dependendo do idioma e do nome da variável, x == true é apropriado:

Considere a seguinte situação em um idioma com digitação estática e coerção de tipo para tipos integrais:

if (actionsAllowed){
    //do actions, since they are allowed
    //...
}

Alguém que esteja lendo esta seção do código pode não perceber imediatamente que actionsAllowed é uma variável booleana - também pode ser um número inteiro, representando o número de ações permitidas. Portanto, adicionando == true, fica claro que x é um booleano e não um número inteiro sendo coagido a um booleano:

if (actionsAllowed == true){
    //do actions, since they are allowed
    //...
}
Cam
fonte
13
readability == GoodThing
Muad'Dib
5
if ((legibilidade == GoodThing) == true) ...
JoelFan
1
bool isGoodThing = legibilidade? true: (codingStandards? true: (internalizationOfConcept? true: false));
19123 johnc
17
Então, renomeie a variável actionsAreAllowed.
Graeme Perrow
9
Ao escrever, if (x) { ...você já está afirmando que xé um booleano ou é conversível em um booleano. O que você chama é irrelevante.
quer
15

E os bools anuláveis?

bool? MyFlag = null;

if (MyFlag == true)
    ;  

if (MyFlag)  // error, doesn't compile!
    ; 
Steve Wellens
fonte
if (MyFlag.Value)
johnc
1
Nem todos os idiomas possuem bools anuláveis, e muitos deles aceitam sua segunda construção.
Zneak 19/10/10
1
@johnc: "if (MyFlag.Value)" pode realmente não fazer o que você quer, pois pode gerar uma exceção se MyFlag for nulo (que você pode testar verificando MyFlag.HasValue).
Ludovic Chabant
4
Esta é minha irritação com bools anuláveis ​​:)
Jarrod Dixon
3
bool? isValid = null; if (isValid ?? false);
Skolima 19/10/10
11

Normalmente, você não deseja fazer um grande acordo com as convenções de codificação, a menos que a convenção esteja de alguma forma impedindo o projeto de maneira significativa. Eu já vi muitos argumentos acalorados escalarem coisas tão pequenas quanto as regiões de código e os principais sublinhados.

Dito isto, não vejo problema em adicionar == truea uma declaração condicional. Por uma questão de fato, eu tenho o hábito de usar, == falseem oposição a um ponto de exclamação principal, ao testar condições negativas. Eu acho que é mais legível.

Se houver uma convenção estabelecida, digo segui-la, a menos que haja motivos para mudar. No entanto, não vale a pena levantar muito.

Casey
fonte
1
Dependendo do seu idioma, someValue pode não ser necessariamente o equivalente a true, mesmo que seja avaliado como true. Por exemplo, (9 == True)avalia como false em Python e eu imagino semelhante em C ++.
dash-tom-bang
regiões de código e sublinhados principais me fazem querer dar um soco na cara das pessoas.
MGOwen
11

Ack. Eu sou esse cara. A vergonha, a vergonha. É como eu aprendi, e é como eu "formato automaticamente" na minha cabeça. A única vez em que uso a sintaxe preferida de Joel é quando a variável bool tem um prefixo de verbo como "is". Eu preciso do verbo, seja "is", "can", "did", ou então preciso do == para fornecer o verbo "equals". Talvez eu nunca quebre esse hábito, então vou entender se você não me der um 'oi' na rua.

Scott Fletcher
fonte
7
Não é uma coisa ruim. Código que se parece com texto real é muito melhor do que implícito. Mantenha esse hábito por questões de legibilidade.
Ronny Brendel
11

lembre-me do "código booleano da loucura", é como estes

if(someBool == true)
   otherBool = false;
else
   otherBool = true

Ao invés de:

 otherBool = !someBool
Marcelo de Aguiar
fonte
Que engraçado, eu tive que manter um sistema que os deixava espalhados por todo o lado. Isso me deixou louco.
Tjaart 20/10/10
8

Pessoalmente, não gosto muito da maneira de dizer "não" em idiomas baseados em C. Esse pequeno ponto de exclamação é fácil demais de ignorar.

Por isso, escrevo-o na íntegra:

if (someCondition == false) {

Depois de ler isso por um tempo, quero simetria também com

if (someCondition == true) {

Portanto, considere um artefato de C usando em !vez de not.

user1249
fonte
3
C ++ realmente tem o notoperador, e C (assim que você inclui o cabeçalho padrão <iso646.h>). Se você não quer (ou não pode) usar este cabeçalho (ou se você está preso com Java ou C #), sugiro colocar um espaço após o ponto de exclamação: if (! condition). Isso o torna um pouco mais visível.
Konrad Rudolph
1
Eu faço Java. notnão é uma opção.
6

Depende do idioma, mas geralmente é uma má ideia ...

Em C, nunca faça isso. É muito fácil encontrar uma situação em que o valor que você está testando não é falso (diferente de zero), mas também não é igual ao valor único definido como "verdadeiro".

No Ruby, faça isso apenas se tiver certeza absoluta de que deseja falhar em tudo, exceto em Boolean true.

No C ++ e em outras linguagens estáticas com um tipo bool, é redundante e pode levar a erros de programação quando você digita incorretamente em =vez de ==ou a erros de promoção, conforme mencionado nos comentários.

AShelly
fonte
Na verdade, em idiomas em que o operador de atribuição retorna um valor ... como C ++ ... if (b == true) {não é apenas redundante. Também é um pouco arriscado, porque você pode acidentalmente atribuído truea b.
Stephen C
4
Não é apenas redundante em C ++, é perigoso. Se você escreve if (b == true)e bnão é booleano, as conversões de tipo seguem o caminho errado. A boolé um tipo integral que normalmente é promovido para um tipo integral apropriado com o valor 1. Se você escrever, digamos, int b(2); if (b == true)se truetorna um intcom 1 para fins de comparação, em vez de bser coagido no tipo bool, o que daria o resultado certo.
David Thornley
@ DavidThornley, ative os avisos no seu compilador. Tratar avisos como erros é melhor técnica de programação defensiva do que evitar ==.
Abyx
5

Você acha que isso é ruim? E se:

if(someCondition) {
  return true;
} else {
  return false;
}
Sverre Rabbelier
fonte
2
Garoto, quantas vezes eu já vi isso. Isso é um bom argumento para uma ferramenta como o ReSharper.
Job
Sim - se você contratar torrões, compre o ReSharper.
Kirk Broadhurst
4

eu prefiro

if (bVal)

ou

if (!bVal)

também, mas tenho medo de que isso surja irritar as pessoas, então meu conselho é esquecê-lo. Desculpa!

grokus
fonte
4
Pelo amor de tudo o que é sagrado, desde que não seja, if (!bNotVal) nem if (bNotVal)mesmo em primeiro lugar. Ugh negativos nos nomes tornam tudo mais difícil de ler.
Dash-tom-bang
2
Eu conhecia um desenvolvedor que booleano é NotConnected; se (isNotConnected == true) ... yuck
johnc 19/10/10
4

você deve dizer a ele que ele está fazendo errado.

Está

if (true == someBool) {

}

se ele esquecer um = está com um grande problema no estilo de escrever.

Mostrar nome
fonte
3

E se

if (x == "true")

POR QUE ISSO É UMA CORDA ?!

atfergs
fonte
Estou trabalhando em algum código php legado corretamente e, ocasionalmente, encontro algo parecido if(preg_match('/title/', implode($_POST))){. PHP, basta dizer, eu preciso encontrar um emprego melhor.
Keyo 19/10/10
4
sim, eu também vejo se (x == "1"), mas isso geralmente faz com um design de banco de dados ruim.
Atfergs 19/10/10
Usei construções semelhantes quando xvieram da entrada do usuário (arquivo de configuração ou serviço da web, por exemplo). No entanto, eu normalmente permito outros valores ilegais, então acaba sendo mais parecido comif x.lower().strip() in ["true", "yes", "on", "1"]
eswald
3

Na verdade, se for anulável, seria necessário testar x == true. :)

Matt Sherman
fonte
3

Eu escrevo código assim!

Aqui está o porquê:

"if bla == true" lê como uma frase, enquanto que "if bla" não ocorre em muitos casos. Parece errado, ao ler o código real.

Além disso, o compilador avisa sobre atribuições nos blocos if, portanto, não há realmente nenhum perigo em usar == true. (confundindo com =)

Também os caras que não escrevem "== true" usam esse "! ()" Para "== false"? Eu acho isso muito feio. E se você usar "== false", é muito consistente também usar "== true", em vez de ter duas maneiras distintas de verificar a verdade.

Ronny Brendel
fonte
3
Você diz "se bla" não lê como uma sentença ... isso significa que a variável não é nomeado corretamente ... o que está errado com este: if (userHasRights) doSomething ()
JoelFan
"em muitos casos". Sim você está certo. Renomear também é bom. Com "if (QWidget :: acceptDrops () == true)", você não tem a possibilidade de renomear. talvez seja bom dar o nome de doesAcceptDrops () ... É muito trabalhoso (e é impossível ser consistente usando essa regra de omissão em qualquer API), portanto, seja consistente com outros "== seja qual for" -se Eu sugiro fortemente que não o omita, para que não "pareça" diferente, portanto pareça consistente.
Ronny Brendel
3

Lembre-se de que você está trabalhando como parte de uma equipe, por isso precisa resolver essas coisas juntos. "Se diverte com os outros" ainda é um importante traço de personalidade, mesmo depois do ensino fundamental :)

cdkMoose
fonte
2

Geralmente omitirá o '== true', mas dificilmente vale um minuto para discuti-lo, a menos que você o inclua nos padrões de codificação da sua equipe.

FinnNk
fonte
3
Além disso, se estiver nos padrões de codificação da equipe, você realmente precisará reavaliar os padrões para se livrar de trivialidades como essa.
JohnFx
Acordado! Apenas no caso de ...
FinnNk 18/10/10
2

Embora eu concorde como desenvolvedor principalmente de C #, não posso dizer que esse seja sempre o caso. Por exemplo, em Javascript, o === executará coalescência do tipo. Então, assumindo var x = 3 então:

if(x) --> true

enquanto

if (x === true) --> false

Eu acho que é diferente de ==, pois mesmo em JS eu não usaria se (x == true), mas apenas algo para pensar.

Esse tipo de toque em outro ponto que surgiu no meu escritório:

bool b = false;

Em C #, bool b; seria suficiente e inicializaria b para falso . No entanto, é mais explícito escrever a linha acima e, de qualquer forma, deve ser arrancada pelo compilador durante a otimização.

Portanto, acho que meu argumento é que nem sempre é tão óbvio o que é e o que não é uma boa prática, e muito disso se resume à preferência, bem como às características / peculiaridades do idioma.

statichippo
fonte
bool b;somente inicializa como false quando bé um campo. Você deve inicializar variáveis ​​locais explicitamente.
Matthew Flaschen
+1 concordou. É o mesmo problema com outras linguagens (de script) também. Você deve ser explícito se quiser testar booleano trueou apenas "true". Por exemplo, qualquer string não vazia é considerada, == truemas não === trueem alguns idiomas.
Martin Wickman
2

Ah sim, mas e se a variável for anulável? (bool?)

Alguns idiomas (C #) exigirão e converterão ou serão comparados com 'true'.

bool? isAccepted = true;

if((bool)isAccepted)
{...}

if(isAccepted == true)
{...}
Jared G
fonte
2

Os jovens conhecem as regras, mas os velhos conhecem as exceções;)

No mais recente C#, se você estiver lidando com um null-able bool, precisará:

bool? x = null;
bool? y = true;
bool? z = false;
if (x == true || y == true || z == true) {
    // That was the only way that is reasonably readable that I know of
    // to accomplish this expression.
}

Se tristate não for um problema, geralmente não deve haver um motivo para comparar algo com true/ True. No entanto, em Pythonvários idiomas, como C/C++você pode executar uma ifexpressão não-booleana. Esses idiomas têm regras exclusivas para interpretar números inteiros, ponteiros, listas etc. como verdadeiros ou falsos. Às vezes você não quer isso. Por exemplo, neste trecho de código Python:

x = True
y = 'abcdef'
z1 = x and y
z2 = (x == True) and (y == True)

Aqui zdeveria estar True, mas z2deveria estar False. Agora, uma Clojurelinguagem aborda isso de outra maneira - a andfunção não necessariamente avalia como a bool, mas ifpode lidar com isso.

Independentemente do idioma, sempre que você se comparar a algo Trueou False, provavelmente vale a pena comentar.

Trabalho
fonte
O primeiro problema deriva de uma IMO premissa falsa usando nomes de variáveis ​​terríveis. Suponha que x, y, z foram nomeados notExceptButHasX, exceptNotButIsntY, doNotUnlessIsExceptZ? Como isso contribui para a legibilidade do seu problema? Se x, y, z foram nomeados com algo como "isEnabled", "isEffective", "hasProperty", então sua instrução se torna isEnabled || isEffective || hasPropertymuito mais legível do que comparar com trueou false.
Thomas
1

Essa codificação também teria me atrapalhado antes. Embora seu identificador de exemplo seja chamado "someBool", o uso inadvertido desse estilo de codificação em uma variável que não era garantida como booleana pode ter um comportamento não intencional. Se o valor de "someBool" não for exatamente "true" ou "false", o resultado será falso.

Eu encontrei um bug muito sutil no ano passado, causado por um estilo de codificação difícil de identificar, porque os olhos de alguém refletem essas construções. Você pensaria: "Como isso pode estar errado?" O mesmo vale para expressões bem compreendidas como "(var)" ou "(! Var)", que você as lê ou codifica sem verificar o comportamento delas.

Então, eu introduzi alguns padrões de codificação para reduzir a existência de tais erros na base de código e a probabilidade de que esses erros sutis se infiltrem acidentalmente em algum momento no futuro.

  1. Todas as expressões devem estar entre parênteses de acordo com sua intenção.
  2. Todos os testes booleanos devem ser expressos em negativo, como "suchBool! = False".

Ao limpar o código que não está em conformidade com o novo estilo, identifiquei e corrigi mais algumas instâncias desses erros sutis.

Huperniketes
fonte
1
Ter algum someBool capaz de ser algo diferente de TRUE / FALSE é uma prática ruim de codificação.
precisa
@AttackingHobo, essa é uma das armadilhas de não ter tipos booleanos em um idioma e / ou não usar uma classe para fornecer o comportamento exato desejado.
Huperniketes 19/10/10
1

Tinha que usar isso o tempo todo no ActionScript 2 (agora reconhecidamente uma linguagem morta), porque:

var something:Boolean = org.black.box.unknown.ThisMightNotExistYet();

// this is slightly ambiguous
if(something)
{
}

// because if you allow undefined you might actually mean
if(false != something)
{
}

// which can mean something different than
if(true == something)
{
}

// and comparing against what you actually MEAN is less script than
if(undefined != value && value)
{
}

Por isso, quase sempre era melhor ser específico.

bburbank
fonte
1

Concordo. É uma construção redundante, especialmente em idiomas de tipos fortes.

Para adicionar outro uso indevido de booleanos, eu encontrei esse tipo de construção várias vezes em Javascript (especialmente em algumas funções de monstros semelhantes a espaguetes, como em mais de 100 linhas):

//create the variable, not initializing it
var flag;
//...
//assing a value to the var, by the example 
flag=$("mycheckbox").selected;
//...

//and at the moment of use it:
if(flag!=true) {
   //code to execute when the checkbox is unchecked
}

Parece que, devido à falta de uma definição estrita de tipo nessa linguagem, alguns programadores preferem não ter que mexer com os false|undefinedvalores.

Tomas Narros
fonte
1

Eu tenho um colega que terá algum código como este:

if(something == true)

E então, para algum tipo de teste / depuração, ele desejará não chamar esse bloco, então ele mudará para:

if(something == true && false)

E então, ocasionalmente, ele muda para:

if(false)

O pior é que esse tipo de depuração passou para mim de vez em quando e é muito ruim para outros desenvolvedores lerem!

ingh.am
fonte
0

Eu diria que a consistência é o rei em uma base de código. Portanto, você deve usar o estilo, usado principalmente em sua organização. Tente fazer do seu estilo preferido parte das diretrizes oficiais de codificação da empresa. Se já estiver nas diretrizes, basta segui-las.

(Dito isto, também me incomodaria muito - mas provavelmente não o suficiente para fazer um grande negócio com isso).

driis
fonte
0

Prefiro não colocar o extra == true, mas às vezes eu o incluo acidentalmente e não percebo. A pessoa pode não ter percebido e colocado acidentalmente. Reli o meu código e, às vezes, percebo que coloquei o extra == true, então removo o == true. Às vezes, eu não percebo e gostaria de receber alguém que me disse que eu o coloquei de forma redundante.

sange
fonte
0

que tal:

int j = 1;
for (int i=1; i>=j; i++) ...

Sim, eu já vi.

Dave
fonte