E-Zine Exclusivo para o Whastapp

Qual a diferença entre uma linguagem de programação estática e dinâmica?

hack_02_thumb Qual a diferença entre uma linguagem de programação estática e dinâmica?
foto_ramos Qual a diferença entre uma linguagem de programação estática e dinâmica?

Ramos de Souza Janones

Janones, é um empreendedor brasileiro apaixonado por empreendedorismo e tecnologia. Ao longo dos anos trabalhando com o desenvolvimento de softwares desktop desde a linguagem Clipper, passando pelo Delphi e atualmente com Java.

Optou pela formação de Publicidade e Marketing por sua segunda empresa de tecnologia ter participado do "boom" da internet nos anos 90 e na procura de melhorar seus conhecimentos em negócios.

Em razão da principal formação e profundos conhecimentos em programação e banco de dados, é capaz de realizar o desenvolvimento de aplicativos web, desktop e mobile com maior criatividade e inovação que profissionais de desenvolvimento com uma formação única e mais especifica, dedicada somente ao desenvolvimento de softwares.

Com toda sua experiência com empresas de software, sua formação e paixão por negócios escreveu o livro "Marketing para Empresas e Profissionais de Software", publicado pela editora carioca Ciência Moderna em 2012. Além de outros livros sobre programação.
foto_ramos Qual a diferença entre uma linguagem de programação estática e dinâmica?

Há uma certa confusão em vários termos sobre este assunto. Em alguns casos não há uma definição formal aceita universalmente.

Popularmente as linguagens são classificadas pela sua tipagem, então linguagens estáticas formalmente são linguagem que possuem tipagem estática. E linguagens dinâmicas possuem tipagem dinâmica.

Algumas linguagens podem ser classificadas como dinâmicas por terem outras características. Elas permitem execução de código arbitrário (eval) ou a transformação de códigos existentes em tempo de execução. Cada vez é mais comum as linguagens modernas permitirem estas flexibilidades. Não importa a tipagem, então formalmente existem linguagens que são dinâmicas por esta definição e estáticas pela tipagem.

Definição

Estática

A definição básica da tipagem estática que uma linguagem de programação pode ter como característica é que há uma verificação dos tipos usados em dados e variáveis para garantir que sempre está sendo usado um tipo que é esperado em todas as situações. Esta verificação é feita no código fonte pelo processo de compilação. Esta análise ajuda na chamada segurança de tipos na utilização dos dados pelo programa permitindo que o programador se preocupe menos com esta questão. O compilador fornece garantias que alguns problemas não poderão ocorrer após o programa passar por esta verificação, ou seja, erros são detectados logo, antes do programa ser efeticamente executado.

Uma variável não pode mudar seu tipo.

No entanto a tipagem estática pode causar uma falsa sensação de segurança. Só uma parte dos erros podem ser descobertos antecipadamente.

Exemplo (está em C# mas poderia bem ser pseudocódigo):

 

Dinâmica

Na tipagem dinâmica esta verificação também ocorre mas ela é feita em cima do dado em si, já que as variáveis podem conter qualquer tipo de dado. Claro que em determinado momento uma variável só pode conter um tipo de dado e isto é verificado. Mas a principal diferença é que a esta verificação é feita em tempo de execução. Isto é feito através de uma infraestrutura auxiliar (uma máquina virtual ou uma biblioteca normalmente chamada de runtime). É comum o programador ter que fazer suas próprias verificações no programa ou em códigos externos de teste para garantir que todos os tipos estão corretos nos momentos certos. O programador tem que se preocupar mais com os tipos embora em soluções simples pode parecer que a preocupação não seja necessária.

O que é dinâmico efetivamente é o tipo da variável. Entender e documentar os tipos ainda são necessários. Há linguagens que incentivam fazer a documentação no código com notação húngara.

Dados precisam ser representados concretamente no computador. Variável é um design pattern. Portanto é uma abstração. Dados não podem assumir várias formas, no máximo pode ser interpretados de formas diferentes em casos específicos. Variáveis podem se referenciar a tipos de diferentes. Portanto a tipagem dinâmica costuma ser um caso especial da tipagem estática. Segundo Bob Harper, um dos criadores da linguagem Standard ML, “uma linguagem dinamicamente tipada é uma linguagem estaticamente tipada com apenas um tipo estático”.

Na prática a tipagem dinâmica é uma abstração também. Há uma ilusão que você pode se referenciar a um dado que possui diferentes tipos mas na prática existe apenas um marcador e há um apontamento para um dado estático diferente.

As técnicas mais comuns para alcançar esta ilusão é o uso de um tipo união (union em C/C++) e/ou ponteiros sem especificação de tipo (void * em C/C++). Todos os dados terão algum overhead de memória.

Exemplo (está em JavaScript mas poderia ser pseudocódigo, note que a sintaxe é idêntica ao exemplo anterior mas a semântica é diferente)

Performance

Outra grande diferença é em relação à performance. Embora seja possível fazer otimizações em um programa escrito com “linguagem dinâmica” para aproximar ou até ultrapassar a performance dos programas escritos em “linguagens estáticas”, pela dificuldade de alcançar isto normalmente não é feito com eficácia. Em teoria um compilador JIT tem mais condições de otimizar código com informações precisas de como o programa será executado e mesmo na prática pode até conseguir algum resultado melhor isoladamente.

Por outro lado se você já sabe com o que vai lidar, não precisa ter nada no código gerado auxiliando o funcionamento no programa e o próprio programa não precisa ter certas verificações escritas pelo programador. Se a verificação é feita antes da execução um programa com tipagem estática não precisa ter este trabalho durante a execução.

Não ajuda também o fato de que a maioria dos programas com tipagem dinâmica vão rodar em uma máquina virtual já que isto facilita o desenvolvimento da linguagem e permite algumas flexibilidades extras normalmente desejáveis em “linguagens dinâmicas”.

Na prática as linguagens não costumam ser 100% qualquer coisa. Ferramentas pragmáticas sabem quando fugir um pouco de um conceito para dar melhor vantagem para o programador.

Linguagens híbridas

Existem as linguagens híbridas. Na prática não é possível ter as duas formas de tipagem mas é possível usar parte de um ou de outro conceito.

Linguagem estática com tipos dinâmicos

react_do_zero_ao_profissional Qual a diferença entre uma linguagem de programação estática e dinâmica?Quando uma linguagem é considerada estática, formalmente ela tem tipagem estática, ela pode ter a infraestrutura necessária para guardar dados diferentes em uma variável. Mas os dados são guardados de uma forma diferente dos outros tipos. Você terá um tipo estático que pode guardar dados dinamicamente, mas a linguagem ainda tem tipagem estática em sua essência.

A grosso modo a linguagem usa uma estrutura de dados extra para guardar o seu tipo e indicar onde está o dado real. Normalmente é feito na biblioteca e costuma ter auxílio do compilador apenas para indicar que a verificação normalmente feita deve ser relaxada já que a verificação será feita por esta biblioteca até certo ponto e também pelo programador para evitar que determinados erros serão gerados em runtime através desta biblioteca.

Linguagem dinâmica com tipos estáticos

Linguagem com tipagem dinâmica não pode efeticamente ser parcialmente estáticas. Afinal uma linguagem dinâmica, formalmente que a tipagem seja dinâmica, deve sempre esperar qualquer tipo. Se ela começar esperar um tipo específico e fazer a verificação antes da execução, ela se transforma em “linguagem estática”. Não é possível reduzir o nível de abstração.

É até possível prover uma verificação de tipos anterior como recurso adicional da linguagem mas não faz muito sentido se não vier acompanhado da mudança na forma com que os dados são gerenciados na memória. Se o programa precisa ter seus tipos fixos e garantidos antecipadamente seria um desperdício ele usar uma estrutura que permita ter vários tipos. Esta estrutura tem custo de memória (tag do tipo, referências para o tipo em todas situações*) e de processamento (indireção extra, seleção do dado/método específico a ser utilizado).

Não faz sentido, mas as linguagens estão fazendo isto, quase todas linguagens mainstream estão adotando uma forma que se aproxima, sem ser, de tipagem estática.

Tipagem manifesta

É possível uma “linguagem dinâmica” usar tipagem manifesta sem mudar sua característica de tipagem dinâmica. A vantagem é pequena ou até questionável.

Mas também há casos de linguagens que conseguem compilar partes do código com tipagem estática e partes com tipagem dinâmica. A interface entre as partes precisam ser normalizadas para um jeito ou outro. Curiosamente algumas preferem se definir como estáticas ou dinâmicas para tentar incutir uma cultura predominante e usar a outra como exceção. Os puristas, para o bem ou para o mal, consideram uma escolha ruim. Na verdade existem duas linguagens muito semelhantes neste caso e não apenas uma.

*Algumas linguagens estáticas possuem referências para tipos quando os dados serão armazenados no heap. E mesmo no stack a informação ainda existirá no código para permitir reflexão, mas não haverá consumo de memória no stack para guardar o tipo.

Inferência

Tipagem estática não significa que todos os tipos precisam ser declarados explicitamente. É comum, na maioria das situações, que o compilador consiga inferir o tipo de uma variável de acordo com sua atribuição ou até mesmo sua utilização (menos comum).

A grande vantagem da tipagem estática está mais no fato que a variável não pode mudar seu tipo. Isto realmente ajuda muito o desenvolvimento. Ter que escrever o tipo explicitamente ajuda pouco ou nada. Alguns acham que fica mais legível quando o tipo é escrito, outros acham que é apenas deficiência do compilador.

Então é possível ter uma “linguagem estática” que usa tipagem implícita reduzindo parcialmente a cerimônia que estas linguagens costumam ter.

Hack

O PHP possui a possibilidade de fazer uma verificação de tipos antes da execução mas isto ajuda pouco porque a linguagem costuma ser executada de forma interpretada e principalmente porque ela não pode verificar todos os tipos, todas as situações, portanto você não tem segurança alguma. A segurança é definida pelo elo mais fraco. Durante a execução tudo é dinâmico.

Não conheço a linguagem Hack o suficiente para dizer como ela funciona mas parece que ela possui tipagem estática.

Eventualmente pode-se usar o tipo mixed que é aquela estrutura de dados que permitirá que qualquer dado seja guardado ali. É provável que o compilador trate este tipo de forma diferente. O programa trata dados de forma dinâmica por exceção, o programador diz que ali tudo pode acontecer porque é isto que ele quer.

Por várias razões parece que Hack é o PHP que bebe na água do C#, me parece que o mixed se comporta como o dynamic do C#.

Vantagens e desvantagens

Muitas vezes as vantagens e desvantagens variam de acordo com os olhos de quem vê. Programadores discordam do que realmente seja uma vantagem, até porque quase tudo é uma questão de trade-off, então [é mais fácil falar em diferenças. Algumas delas podem ser:

eGGGS-350x280 Qual a diferença entre uma linguagem de programação estática e dinâmica?

As principais vantagens das “linguagens estáticas” são a segurança, performance e auxílio em tempo de desenvolvimento (refatoração, completação de código, informação auxiliar, cobertura de código etc.).

As “linguagens dinâmicas” são flexíveis, rápidas para prototipar, concisas.

É bom entender que os bugs mais complicados continuam complicados igualmente nas duas tipagens.

Certamente há uma vantagem nas “linguagens dinâmicas” quando se pensa no desenvolvimento da própria linguagem. Definir a linguagem e criar uma implementação básica é muito mais simples que uma “linguagem estática”. Porém para criar uma implementação poderosa, que possa resolver algumas das suas desvantagens, se torna um trabalho dificílimo. Até hoje ninguém resolveu todas desvantagens.

Tipagem forte e fraca

Algumas vezes estes conceitos são confundidos com tipagem forte e fraca. Isto se explica em parte porque a força da tipagem não é bem definida e não é universalmente aceita.

Tipagem forte costuma ser a característica que não permite um mesmo dado ser tratado como se fosse de outro tipo. É muito comum linguagens estáticas terem tipagem forte. Mas existem exceções.

Isto dá mais robustez ao código.

C, por exemplo, permite que um dado seja acessado/interpretado como se fosse outro. Pode, por exemplo:

  • Gravar um int e acessá-lo como se fosse um ponteiro.
  • Gravar um float e acessar como se fosse um int. É certo que o resultado será catastrófico neste caso, mas é possível.
  • Obter um 0 e ser considerado falso ou outros números (não importa de que tipo) serem interpretados como verdadeiro em operações que exigem um booliano.
  • Gravar dois short em sequência e ler como um int. Provavelmente nada útil será obtido mas é possível.
  • Gravar “SOpt” e ler isto como se fosse um int, sei lá porque.

C é uma linguagem de tipagem fraca. C++ também, apesar dela tentar reforçar um estilo onde isto não seja tão usado.

Os compiladores de C/C++ tentam evitar que isto seja usado abusivamente.

Daí concluímos que segurança de tipos não é uma característica inerente de linguagens ditas estáticas. A segurança pode ser quebrada por outros fatores. Type safety é outro conceito diferente que pode ser confundido erroneamente com tipagem forte e tipagem estática.

Muitas “linguagens dinâmicas” possuem tipagem forte, mas outras possuem tipagem fraca, normalmente criando coerções implícitas. É comum existir coerção em algumas situações sob regras definidas. Exemplo: "1" == 1 é verdadeiro e 1 + "1""11".

A coerção implícita tem a vantagem de tornar o código ligeiramente mais curto. Isto costuma ser característica de linguagens de script, onde o tamanho do código faz diferença. Então, linguagens feitas para desenvolver aplicações, em oposição à scripts, não deveriam ter esta característica (hello PHP).

A definição destes termos não ajudam muito e dizer que uma linguagem é fracamente ou fortemente tipada de forma exclusiva também não costuma ser verdade.

Linguagens de script

Cada vez mais fica difícil definir linguagens de script. Elas costumam ser dinâmicas mas nada impede que sejam estáticas.

A tipagem dinâmica dá mais flexibilidade e ajuda fazer aplicações pequenas rapidamente. Estas linguagens costumam exigir pouca cerimônia e a tipagem dinâmica provê pouca cerimônia na tipagem. Mas é mais uma questão de adequação do que uma exigência.

Linguagens dinâmicas costumam executar mais de forma interpretada do que compilada e é outro fator indireto que ajuda a serem usadas para fazer scripts. Mas é apenas um facilitador, novamente, não é uma exigência.

Nenhuma linguagem quer perder espaço por isso cada vez mais as linguagens (de tipagem) estáticas permitem características de tipagem dinâmicas, reflexão, concisão, e execução de forma simplificada (ilusão de interpretação). Assim elas podem ser consideradas de script também, apesar de não ser seu foco principal.

Além da adequação, a característica de script está mais ligada à implementação do que à linguagem em si.

Uma reflexão

Se uma linguagem permite que seus tipos estáticos possuam valores inválidos ou que não correspondem ao que se espera neste tipo, um null por exemplo, ela ainda tem tipagem estática? Parece que sim, mas há dúvida se deveriam. Quebra a segurança de tipos e de uma certa forma pode ser interpretado como o dado podendo ter dois tipos. Obriga uma verificação em runtime para garantir que não haverá problemas com o tipo.

Qual é melhor?

A pergunta que não quer e provavelmente nunca vai calar é: qual é melhor?

É óbvio que não há universalmente uma melhor que a outra. Sempre podemos falar o clichê que existe uma ferramenta melhor para um problema.

Na prática eu vejo que a escolha recai, na maioria das vezes, em gosto e experiência. E isto é bom. Eu costumo dizer que antes de escolher a melhor ferramenta para o problema, escolha algo que você saiba e se sente confortável em usar: “a melhor ferramenta é aquela que você sabe usar”. É a velha disputa entre engenheiros que querem que tudo seja perfeito e administradores que querem que venha o melhor resultado. Uma serra elétrica corta madeira mais rápido e com mais precisão. Um marceneiro de fim de semana pode se machucar com uma serra elétrica.

Claro que há casos que tecnicamente uma é melhor que a outra mas isto está cada vez mais sutil.

Minha obervação pessoal é que programadores de “linguagens dinâmicas” costumam pensar menos no problema e criam designs excessivamente simplificados trazendo problemas futuros. Mas há casos que um design melhor não é vantagem.

Por outro lado vejo que programadores de “linguagens estáticas” tendem a pensar demais nos problemas e criam designs excessivamente complicados sem trazer muitas vantagens futuras e não resolvendo todos os problemas futuros.

Note que isto não define a qualidade do programador e muito menos que 100% dos programadores são assim em 100% dos casos. Há casos que o oposto acontece. E deveria mesmo. Quando se programa em “linguagens dinâmicas” o planejamento antecipado costuma ser mais importante.

Não posso afirmar que a tipagem em si seja responsável pela tendência (se ela for verdadeira). Pode ser o tipo de programador que a tipagem atrai. É o surfista indo ao mar com ondas e não o mar com ondas fazendo o sujeito virar surfista. Talvez as pessoas escolham a tipagem pelos motivos errados.

O que eu vejo acontecer muito é que programadores que usam “linguagens estáticas” não usam as facilidades dinâmicas existentes nestas linguagens a não ser que não tenha outro jeito. E os programadores de “linguagens dinâmicas” acham que verificar os contratos nunca deveriam ser feitos dentro do código (de fato estas linguagens não costumam fornecer facilidades para isto). Não sei se deveria ser assim.

PDF com algo mais formalizado para ler. E uma publicação bem completa e aparentemente muito bem fundamentada.

Top
%d blogueiros gostam disto: