Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

yoda

prototype-based programming in PHP

Mensagens Recomendadas

mjamado

A questão que se impõe é: porquê?

O paradigma orientado a objectos é bem suportado pelo PHP, melhor ficou com a chegada dos namespaces e ainda melhor ficará com a chegada do strong typing; debaixo de que pedra saiu agora a prototipagem?

Eu uso a prototipagem extensivamente, mas em linguagens onde não existe suporte directo a classes, nomeadamente e mais notavelmente em JavaScript; agora em PHP, vai ser mais uma coisa onde se perdeu imenso tempo, e que pouca gente vai usar - para além de ser, na minha opinião, má programação.


"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
IceBrain

Eu concordo que prototipagem em PHP não faz grande sentido, mas outros conceitos como object monkeypatching eram bem vindos, na minha opinião. Em certas situações bem delimitadas são extremamente úteis - tal como as funções anónimas, por exemplo.

Agora, não percebo o objectivo de ter strong typing numa linguagem dinâmica. ST oferece duas vantagens: informação ao compilador sobre o tipo de objectos, e testes em "compile-time" sobre os tipos, à custa de flexibilidade.

Numa linguagem dinâmica nenhum deles se aplica, por isso não vejo o propósito. Espero que pelo menos tenha  type inference, para verborreia já basta o Java.

Btw, sobre isso: http://mindview.net/WebLog/log-0025


❝The idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying.❞- John Carmack on software patents

A list  of command line apps

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
mjamado

IceBrain, incorrendo no offtopic:

Eu considero que a vantagem ou não do strong typing seja altamente discutível. Eu - e muitos mais - acho que é bom; há quem ache que é mau. Eu vou continuar a usar, sempre que possível. Os outros, possivelmente, vão continuar a não usar. Couldn't care less...

Mas as vantagens do strong typing não se esgotam na informação ao compilador, nem na utilidade ao desenvolver.

Quanto à flexibilidade... O GOTO também é uma instrução altamente flexível; aliás, deve ser a instrução mais flexível de sempre. Pergunta: conheces algum programador digno desse nome que a use?

Nem toda a flexibilidade é boa, e basear toda uma argumentação nesse ponto... é fraquito. Não estou a dizer que és tu, mas sim que é a argumentação padrão para esta questão do strong typing.


"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
IceBrain
I think goto's are fine, and they are often more readable than large

amounts of indentation. That's _especially_ true if the code flow isn't

actually naturally indented (in this case it is, so I don't think using

goto is in any way _clearer_ than not, but in general goto's can be quite

good for readability).

Of course, in stupid languages like Pascal, where labels cannot be

descriptive, goto's can be bad. But that's not the fault of the goto,

that's the braindamage of the language designer.

Linus Torvalds at LKML: http://lkml.org/lkml/2003/1/12/128

Mas a minha questão era mais não ter percebido como é que se implementa strong typing quando o código só é analisado quando está a correr. Lança uma excepção? Se assim é, qual é a vantagem em relação ao duck typing?


❝The idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying.❞- John Carmack on software patents

A list  of command line apps

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Triton

Quanto à flexibilidade... O GOTO também é uma instrução altamente flexível; aliás, deve ser a instrução mais flexível de sempre. Pergunta: conheces algum programador digno desse nome que a use?

Epa uso goto quando são a solução adequada. Agora se sou digno de nome fica à vossa descrição.


<3 life

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
mjamado

Linus Torvalds at LKML: http://lkml.org/lkml/2003/1/12/128

Leste a discussão onde isso estava inserido? Percebeste de onde veio essa resposta?

No pedaço de código referente a essa troca de comentários, duas chavetas e um ponto de exclamação tinham retirado a necessidade do goto e, na minha opinião, o código ficava mais lógico e legível.

Nem tudo o que Linus Torvalds (ou Bill Gates, ou Seetharaman Narayanan, ou Steve Wozniak, ou...) faz é bem feito. Neste caso, as opiniões dividem-se. Eu acho que é péssima programação. Edsger Dijkstra também pensava. O que é certo é que não vejo um goto em código há anos.

Mas a minha questão era mais não ter percebido como é que se implementa strong typing quando o código só é analisado quando está a correr. Lança uma excepção? Se assim é, qual é a vantagem em relação ao duck typing?

Sim, lançar uma excepção ao chamar um método ou instanciar uma classe com parâmetros já não era mau. Numa equipa, por exemplo, nem todo o código está nas tuas mãos, e a única maneira de garantires que os parâmetros que estás a aceitar num método são os esperados é espalhar testes condicionais, com a consequente penalização na performance. Não seria muito mais eficaz restringir à partida os tipos aceites na assinatura do método?

Como nota adicional, o PHP "actual" já permite forçar os tipos array e object na assinatura; o PHP 6 vai permitir, finalmente, qualquer tipo na assinatura dos métodos.

Epa uso goto quando são a solução adequada. Agora se sou digno de nome fica à vossa descrição.

Exemplos de "soluções adequadas" que não possam ser reconstruídas doutra maneira, por favor.

P.S.: não sei se estas discussões, os goto e o strong typing vs. duck typing, já foram abordadas aqui no P@P, mas, se não foram, é uma falta. São duas das maiores discussões de programadores por esse mundo fora. Se algum moderador tiver a amabilidade de partir este tópico... é que já estamos a abusar do OT.


"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
IceBrain
Nem tudo o que Linus Torvalds (ou Bill Gates, ou Seetharaman Narayanan, ou Steve Wozniak, ou...) faz é bem feito. Neste caso, as opiniões dividem-se. Eu acho que é péssima programação. Edsger Dijkstra também pensava. O que é certo é que não vejo um goto em código há anos.

Perguntaste-me se conhecia algum programador digno desse nome que a use. Eu acho que o Torvalds é digno desse nome.

Btw, o Djikstra também disse:

Object-oriented programming is an exceptionally bad idea which could only have originated in California.
Sim, lançar uma excepção ao chamar um método ou instanciar uma classe com parâmetros já não era mau. Numa equipa, por exemplo, nem todo o código está nas tuas mãos, e a única maneira de garantires que os parâmetros que estás a aceitar num método são os esperados é espalhar testes condicionais, com a consequente penalização na performance. Não seria muito mais eficaz restringir à partida os tipos aceites na assinatura do método?

Essa restrição é um teste condicional! Simplesmente tem uma sintaxe integrada, mas numa linguagem dinâmica, a verificação é sempre feita em à custa de ciclos, visto que não há fase de verificação em compile-time, é tudo em run-time.

Eu prefiro não fazer nenhum tipo de verificação específica. A responsabilidade de seguir as regras é de quem chama o método. Se correr mal lança-se uma excepção.

É o método EAFP (Easier to Ask Forgiveness than Permission) e em geral tem melhor performance em linguagens dinâmicas, visto que se quem chama cumprir as regras não se perde tempo com verificações.


❝The idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying.❞- John Carmack on software patents

A list  of command line apps

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
mjamado

Perguntaste-me se conhecia algum programador digno desse nome que a use. Eu acho que o Torvalds é digno desse nome.

A pergunta era meramente retórica, mas enfim... Mas já que estamos numa de preciosismos, é líquido que Torvalds tenha voltado a usar goto's desde 2003 para cá? Alerta: esta pergunta, de novo, é apenas retórica. Serve para contrariar a argumentação, que é ad hominem, e não o dito cujo.

Btw, o Djikstra também disse:

Mau! Mas então agora vamos fundamentar a discussão em argumentos ad hominem? Só porque ele disse uma coisa que eu considero errada, devo descartar tudo aquilo que ele disse que considero correcto? Se assim for, esquece lá isso, esta discussão acaba já pela minha parte.

Essa restrição é um teste condicional! Simplesmente tem uma sintaxe integrada, mas numa linguagem dinâmica, a verificação é sempre feita em à custa de ciclos, visto que não há fase de verificação em compile-time, é tudo em run-time.

Com uma pequenininha diferença: esse teste condicional é feito internamente pelo interpretador. Será (bem) mais rápido, não?

Eu prefiro não fazer nenhum tipo de verificação específica. A responsabilidade de seguir as regras é de quem chama o método. Se correr mal lança-se uma excepção.

É o método EAFP (Easier to Ask Forgiveness than Permission) e em geral tem melhor performance em linguagens dinâmicas, visto que se quem chama cumprir as regras não se perde tempo com verificações.

E lanças uma excepção exactamente como? Ah, espera: com um teste condicional? :biggrin:

Não te esqueças que há coisas que, per se, não dão erro, mas são erradas. Pensa na diferença entre "0", 0 e false em PHP. Além disso, quantas coisas em PHP vêm do cliente? Não tens que as verificar nalgum ponto? Exemplo rápido: imagina um script onde aceitas um id para mostrar qualquer coisa. Ao receberes o id por GET ou POST, não lhe fazes nada? No mínimo dos mínimos, escapas potenciais aspas e pelicas, certo? E o resto, é um salve-se quem puder até dar erro, porque aquela gaita não é um número, mas uma tentativa de SQL injection...

Com uma linguagem strong typed, podias substituir esses controlos por um cast explícito para int1 e falhava logo ali. Ou, ao passar para o método onde se ia buscar o registo correspondente, ser feito um cast implícito via tipo definido na assinatura, e falhava.

1 o intval não é a mesma coisa que um cast: intval("isto_é_um_valor_inválido") == 0 [true]


"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
IceBrain
Com uma pequenininha diferença: esse teste condicional é feito internamente pelo interpretador. Será (bem) mais rápido, não?

Isso só com benchmarks, mas duvido que a diferença seja significativa. Em qualquer caso, não ter os teste de todo será sempre mais rápido.

E lanças uma excepção exactamente como? Ah, espera: com um teste condicional?

Não! Por exemplo, a função da standard library do Python, que recebe um path (String) e devolve-o normalizado:

def normcase(s):
    """Normalize case of pathname.

    Makes all characters lowercase and all altseps into seps."""
    return s.replace('\\', '/').lower()

Como vês, não há testes condicionais. Se alguém passar um objecto que não implemente o método 'replace(String, String) : String', o intérprete lança uma excepção por causa disso.

A diferença é que essa verificação (existência do método) será feita independentemente de uma condição anterior, por isso esta versão é sempre mais rápida.

Pensa na diferença entre "0", 0 e false em PHP.

Isso é coisa que sempre desgostei no PHP. Mas por outro lado, se o método Math.abs() funciona com um a string "0", que corra. Quem chama o método é que deve responsabilizar-se.

Além disso, quantas coisas em PHP vêm do cliente? Não tens que as verificar nalgum ponto? Exemplo rápido: imagina um script onde aceitas um id para mostrar qualquer coisa. Ao receberes o id por GET ou POST, não lhe fazes nada? No mínimo dos mínimos, escapas potenciais aspas e pelicas, certo? E o resto, é um salve-se quem puder até dar erro, porque aquela gaita não é um número, mas uma tentativa de SQL injection...

Receber valores externos é completamente diferente. Mas:

Se queres receber um int,

if(!ctype_digit($id)) 
    //fail
else
     $id = intval($id);

Além disso, as SQL injections são strings com caracteres inválidos, não strings a serem convertidas noutros valores. Strong typing não corrige nada disso, tens que usar verificação a sério.

intval("STRING_INJECTADA") == 0, so what? Como é que é possível receber um 0 na 'id' ser um problema se segurança? E se o valor passado fosse um inteiro mesmo, com o valor "O"?


❝The idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying.❞- John Carmack on software patents

A list  of command line apps

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pedrotuga

Por acaso é precisamente isso que se faz, usa-se o intval para sanear IDs numéricos. Se lá vier uma string e for interpretada como zero isso não tem problema absolutamente nenhum, já que o objectivo era mesmo só assegurar que o parâmetro era numérico. De resto nada te impede de colocares um zero aí onde tens essa string.

Com uma pequenininha diferença: esse teste condicional é feito internamente pelo interpretador. Será (bem) mais rápido, não?

Não. Em 99%+ dos casos é a mesma coisa. Não tem qualquer diferença. O tempo de execução de determinada aplicação na esmagadora maioria dos casos hoje em dia depende da entrada e saída de dados e não da eficiencia de meia dúzia de expressões condicionais, essas são absolutamente insignificantes em termos de performance.

E se o código estiver bem estruturado e todo DRY, acredita que ficam poucos testes condicionais espalhados pelo código e que se encontram bem.

Claro que isto depende do tipo de programação que se faz. Eu não vou programar um UI para um telemovel em PHP. Assim como já poucos há que escrevam aplicações web em C.

Os defensores de linguagens mais tradicionais em que os tipos de dados têm que ser definidos explicitamente, argumentam que dessa forma são apanhados muitos mais erros aquando da compilação que não vão chatear em runtime. do que não se apercebem é que esse tipo de erros só é problemático precisamente quando falamos de linguagens desse tipo. No caso do PHP e de outras linguagens com tipagem dinâmica as verificações só precisam de ser feitas ao nível do conteudo das variáveis, partindo do principio que lá pode esta o que quer que seja.

Os utilizadores de linguagens de tipagem dinâmica tipicamente não perdem tempo com essa discussão porque tambem são ou já foram programadores de outras  linguagens mais clássicas e no geral sabem que essa dicussão é idiota.

Já agora em relação ao GOTO,

Eu quanto andei na faculdade, na minha primeira cadeira de programação, o professor disse para não usar o GOTO.

Porquê?

-"Porque não!"

É esta a resposta tipica do ensino de programação em portugal. É feito de mandamentos sagrados que não podemos por em causa. Se há coisa que mais me irrita são esses chavões de "isso é fraco".  Hoje em dia é o PHP o alvo desse tipo de críticas, noutros tempos foi o visual basic. Sinceramente conheço muito hobista/hacker que escolheu estas linguagens para os seus desenvolvimentos e que chegou a um nível bem mais avançado que a maioria dos teóricos professores de universidades.

Mas voltando ao tema inicial. Alguem me explica aquilo melhor? Qual é o objectivo? Poder adicionar funcionalidade e um objecto sem redefinir uma classe? Em que medida é que isso é um paradigma diferente? Algum exemplo?

EDIT:ok, o icebrain acabou por responder primeiro... as minhas desculpas por ser repetitivo

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
yoda

Da minha parte, postei o link porque tencionava dar a conhecer (a quem não conhecia claro) o método e as novas funcionalidades do PHP 5.3 (que ainda nem estão como deviam ser), e tenciono também fazer alguns benchmarks para verificar se existe alguma razão para usar prototipagem numa liguagem dinâmica ou se é fetiche de alguém da dev team do php.

edit: de notar também o uso dos namespaces, que a meu ver é definitivamente uma mais-valia na OOP do PHP.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
mjamado

Isso só com benchmarks, mas duvido que a diferença seja significativa. Em qualquer caso, não ter os teste de todo será sempre mais rápido.

Claro, só com benchmarks - infelizmente, é impossível fazê-los, visto que o PHP ainda não o suporta. Eu penso que a diferença seja significativa, por analogia com algumas extensões em C que já fiz para o PHP, cuja diferença de performance foi abismal. Quando o PHP 6 sair na sua versão final, voltamos a conversar.

Não! Por exemplo, a função da standard library do Python, que recebe um path (String) e devolve-o normalizado:

Como vês, não há testes condicionais. Se alguém passar um objecto que não implemente o método 'replace(String, String) : String', o intérprete lança uma excepção por causa disso.

A diferença é que essa verificação (existência do método) será feita independentemente de uma condição anterior, por isso esta versão é sempre mais rápida.

Tem lá paciência, mas estamos a falar de PHP. No PHP, não há esse tipo de controle para uma string ou para um número, porque não são objectos...

Isso é coisa que sempre desgostei no PHP. Mas por outro lado, se o método Math.abs() funciona com um a string "0", que corra. Quem chama o método é que deve responsabilizar-se.

Tu e eu. Mas é com isto que temos que lidar. E responsabilizar o que vem de fora continua-me a parecer over the edge, devido à tal coisa do que vem do cliente.

Receber valores externos é completamente diferente. Mas:

Se queres receber um int,

if(!ctype_digit($id)) 
    //fail
else
     $id = intval($id);

Eh pá, eu sei sanear inputs... :biggrin: Mas isso é (holly shit!) um teste condicional... outra vez.

Além disso, as SQL injections são strings com caracteres inválidos, não strings a serem convertidas noutros valores. Strong typing não corrige nada disso, tens que usar verificação a sério.

Errado. Corrige logo de gás (imagina o PHP com strong typing):

$id = $_POST['id'];
$novoId::Integer = new Integer($id); // se não for um número, dá erro

intval("STRING_INJECTADA") == 0, so what? Como é que é possível receber um 0 na 'id' ser um problema se segurança? E se o valor passado fosse um inteiro mesmo, com o valor "O"?

Não é um problema de segurança (embora o possa ser, também), é um problema lógico. A questão é só essa.

Por acaso é precisamente isso que se faz, usa-se o intval para sanear IDs numéricos.

No shit, Sherlock! Mas não é isso que está em causa...

Se lá vier uma string e for interpretada como zero isso não tem problema absolutamente nenhum, já que o objectivo era mesmo só assegurar que o parâmetro era numérico. De resto nada te impede de colocares um zero aí onde tens essa string.

Respondido acima.

Não. Em 99%+ dos casos é a mesma coisa. Não tem qualquer diferença. O tempo de execução de determinada aplicação na esmagadora maioria dos casos hoje em dia depende da entrada e saída de dados e não da eficiencia de meia dúzia de expressões condicionais, essas são absolutamente insignificantes em termos de performance.

Estas estatísticas inventadas à pressão partem-me todo... Fundamento? Estou especialmente curioso em ver benchmarks duma coisa que ainda não foi implementada...  :D O resto do parágrafo, apesar de correcto, não tem rigorosamente nada a ver com a discussão, mas ok.

Os utilizadores de linguagens de tipagem dinâmica tipicamente não perdem tempo com essa discussão porque tambem são ou já foram programadores de outras  linguagens mais clássicas e no geral sabem que essa dicussão é idiota.

Uma discussão idiota que se arrasta há anos, com programadores absolutamente galáticos dum lado e de outro da mesma. Mas ainda bem que te temos a ti. Só para que saibas, o meu trabalho profissional neste momento é como webdev (em PHP) já há alguns anos, mas o meu background foi de anos e anos em C#. Logo, sou um desses de que falas. E não considero a discussão idiota, é até muito premente, visto que o PHP está a introduzir strong typing e o C# está a introduzir (já introduziu) dynamic typing. Mas isto devo ser eu...

Já agora em relação ao GOTO,

Eu quanto andei na faculdade, na minha primeira cadeira de programação, o professor disse para não usar o GOTO.

Porquê?

-"Porque não!"

É esta a resposta tipica do ensino de programação em portugal. É feito de mandamentos sagrados que não podemos por em causa. Se há coisa que mais me irrita são esses chavões de "isso é fraco".  Hoje em dia é o PHP o alvo desse tipo de críticas, noutros tempos foi o visual basic. Sinceramente conheço muito hobista/hacker que escolheu estas linguagens para os seus desenvolvimentos e que chegou a um nível bem mais avançado que a maioria dos teóricos professores de universidades.

Não discuto. O ensino está fraquinho, toda a gente sabe. Mas o goto foi, durante muitos anos, o principal responsável por spaghetti code, pelo que foi sendo gradualmente abandonado. O que alguns programadores defendem (o já citado Torvalds, mas também o super-galático Knuth) é que pode ser usado, em circunstâncias muito particulares e com muita, muita parcimónia, por quem saiba exactamente o que está a fazer.

Pensa assim: quando estás a tirar a carta, nenhum instrutor te deixa passar pela direita de um carro que está parado para virar à esquerda. No entanto, depois de teres experiência de condução, já o fazes, em segurança, sem colocares em risco os outros utentes da via. É a mesma coisa. Primeiro aprendes correctamente e depois de saberes exactamente o que estás a fazer, podes permitir-te alguns "luxos".

Mas voltando ao tema inicial. Alguem me explica aquilo melhor? Qual é o objectivo? Poder adicionar funcionalidade e um objecto sem redefinir uma classe? Em que medida é que isso é um paradigma diferente? Algum exemplo?

O PHP não suporta, nem vai suportar prototipagem, ok? Aquilo é o aproveitamento duma funcionalidade nova do PHP que permite, entre outras coisas, emular prototipagem (o Late Static Binding), o que vai dar sensivelmente ao mesmo.


"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.