Linguagens de programação

Tenho um problema com os conceitos que desenvolvo sobre algumas coisas ou pessoas: uso com excessiva freqüência o "instinto" para dizer se algo é bom ou ruim, certo ou errado etc. Costuma ter uma taxa de acerto muito alta, mas cria um problema na hora de explicar racionalmente o porquê daquela impressão; sem falar que é um expediente tipicamente feminino, o que deixa meu ego masculino em má situação.

A favor do meu ego, está o fato de que as grandes massas costumam também tomar decisões (acertadas) através desse mesmo processo. Em várias questões, as pessoas serão capazes de defender apaixonadamente sua opinião, ainda assim falhando completamente em apresentar razões científicas que embasem tal opinião.

Só quando nos acostumamos a fazer trabalhos com metodologia científica, percebemos o quanto baseamo-nos em opiniões empíricas/instintivas, e quantas vezes corremos o risco de tomar decisões erradas. Metodologia científica é nada mais que indicar a fonte de afirmações existentes, ou então produzir prova rigorosa das afirmações novas, proporcionando assim uma amarração perfeita.

Na área de informática, uma discussão religiosa do gênero, que volta e meia provoca debates apaixonados é: qual a melhor linguagem de programação ?

Eu sempre defendi o Clipper como uma linguagem boa (na sua época), e o mercado corroborou minha opinião, embora os puristas da época sempre torcessem o nariz a ele. A atitude dos ex-clippeiros, muitos deles hoje metidos a acadêmicos, é a dos ex-delinqüentes juvenis: "eu era jovem, precisava do dinheiro".

Em minha vida profissional, também lidei com uma e outra linguagem de "4a geração", ou seja, linguagens embutidas em sistemas de banco de dados. Lidei bastante com o ZIM, cheguei a ser um programador razoável, mas nunca senti "amor" por ele.

Depois, na migração para o ambiente gráfico Windows, desgostei do CA-dbFast, do CA-Visual Objects, do Access e do Visual Basic. Só me senti confortável quando conheci o Delphi, outra linguagem consagrada pelo mercado, apesar das pressões da Microsoft. Parece que sou uma maria-vai-com-as-outras.

Depois veio a onda Java, até fiz algumas coisas pequenas com ele, mas sua única vantagem aparente sobre Delphi - rodar em qualquer computador - não se concretizava na prática. Um applet simplório testado no Netscape não funcionava no Internet Explorer... E performance de execução ainda importava bem mais que hoje em dia; e os interpretadores Java eram ainda mais lentos.

Quando comecei a lidar com sistemas free software em 1998, que coincidiu com uma fase mais "escovadora de bits", o único caminho foi aprofundar os conhecimentos em C, e posteriormente em C++. O Object Pascal nunca teve penetração grande nessa comunidade.

Quanto às linguagens interpretadas, não consegui gostar de Perl, embora tenha feito um grande esforço para isso. Gosto de shell scripts, dentro do seu âmbito que é administração do sistema.

Também acho o PHP bastante razoável. Não sinto prazer em programar em PHP, mas ele funciona. (Devo ter deixado os puristas de cabelo em pé.)

Mas confesso que, quando programava apenas em Windows, me sentia completamente satisfeito com o Delphi. É uma sensação de que não desfruto hoje; nenhuma das linguagens que atualmente uso em ambiente livre proporciona a mesma sensação. Falta algo.

Como disse, sou, assim como "cristão nascido de novo", também um "escovador de bits nascido de novo". Comecei a estudar ciência da computação a partir de 1998, embora já trabalhasse com informática desde 1987.

Conhecer "cientificamente" as linguagens de programação para mim é algo novo. Nessa área devo boa parte do meu aprendizado a meus colegas de #d00dz (osvaldo, rudá e gwm em particular).

Sempre distingui as linguagens entre fortemente tipadas e fracamente tipadas, e tendo a preferir as primeiras. Mas esta classificação é incompleta; é como classificar as pessoas como "esquerda", ou "direita" , sem estabelecer diferenças entre Stalin e Ghandi; ou entre George Washington e Hitler.

A classificação tem de ser no mínimo bidimensional:

No meu entendimento anterior, empírico, errôneo, a linguagem fracamente tipada seria dinâmica, e a linguagem fortemente tipada seria estática.

Começando com a primeira linguagem citada: Clipper. Ela possem uma tipagem dinâmica, porém surpreendentemente forte (!). O seguinte techo de código passa pelo compilador, mas dá erro na execução:

local a,b
a = 1
b = 2
b = "x"
? a + b

O Clipper 5 introduziu a diretiva "local", que permite declarar as variáveis no início da função ou procedimento. É um passo em direção à tipagem estática; o plano da Nantucket era tornar o Clipper mais parecido com C ao longo de sua evolução.

Já em PHP, fracamente e dinamicamente tipado, o seguinte trecho de código executa sem problemas:

$a = 1;
$b = 2;
$b = "x";
echo($a + $b); // mostra "1"
echo($a . $b); // mostra "1a";

A conversão implícita de número para string causa uma situação embaraçosa, onde somar string + string resulta em um número; e precisamos de um operador adicional, o ponto, para concatenar strings.

O Visual Basic / Access não é tão fracamente tipado quanto o PHP, mas também tem um operador "." para concatenar strings.

Naturalmente, qualquer dos programas acima, se feito em C, C++ ou Delphi, não passaria sequer na compilação. A tipagem estática é, nesse aspecto, bastante confortável para o programador.

Uma linguagem com tipagem estática é, a priori, fortemente tipada. Parece impossível desfazer essa relação de implicância. Mas C++ permite "enfraquecer" os tipos criados pelo usuário, usando as funções "operator". Exemplo:

class tipo {
	tipo(char*);

	operator char*() {
	...
}
	...
};
 
tipo a;
char *b = a;  // conversão automática, via operator char*()
tipo c = b;   // conversão automática, via construtor

Esse recurso, um dos mais poderosos do C++, é um dos mais controversos e mal usados, pois cria efeitos colaterais imprevisíveis. O próprio Stroustroup recomenda usá-lo com muita parcimônia. Felizmente, os tipos primitivos em C++ não podem ser enfraquecidos ou modificados desta forma. Imagine o dano causado se as funções a seguir fossem admissíveis:

int operator+(const int x, const int y) {
	// depura esta, otário
	return x + y + 997;
}
 
operator int(const char* s)  {
	return atoi(s);
}
 
char* a = "1";
char* b = "2";
 
// a saída vai ser "12", "3" ou "1000" ?
cout << a + b << endl; 

Vejamos agora outras "dimensões" de classificação de uma linguagem.

Extensibilidade do sistema de tipos

Em Object Pascal (Delphi) e Java, é impossível fazer as "bobagens" que fizemos em C++. Embora o Object Pascal denomine as classes como "Types", não há recursos suficientes na linguagem para fazer esses "tipos" novos fazerem-se passar por tipos nativos.

É bem verdade que o Delphi introduz alguns recursos interessantes, pontuais, como as propriedades default. Mas são recursos (efetivos) para limpar a sintaxe no código-cliente, não ferramentas para criação de tipos novos. Delphi também possui o tipo String como tipo primitivo. (Em Java e C++, string é um tipo criado inteiramente na própria linguagem.)

O Java até possui alguns recursos no estilo operator, mas são apenas alguns, o suficiente para permitir uma implementação de Strings como classe, que aliás é lenta à beça.

Ainda sobre Delphi/Java, todas as classes são obrigatoriamente descendentes de um pai (TObject ou Object), o que coloca-as definitivamente em seu devido lugar. As classes são tipos de segunda classse :P

Supondo um objeto que contenha uma consulta SQL. Preciso oferecer o valor de um campo ou coluna da forma mais elegante possível ao usuário do objeto. C++:

int a = consulta["campo"];

Object Pascal:

Integer a = consulta.GetField("campo").AsInteger;

Em Object Pascal, a inexistência do operator obriga a uma verdadeira ginástica; mas tenho a garantia que o compilador pegará qualquer discrepância.

Em C++, eu trapaceei um pouco. Para implementar a leitura do valor do campo daquela forma, eu seria obrigado a usar operator[] e também templates. Nesta situação o template também enfraquece o sistema de tipos. Se eu definir erradamente o tipo da variável "a", o compilador não pegará o erro.

A comparação com linguagens de tipagem dinâmica, que resolvem nomes em run-time, é verdadeiramente covarde; mas por completeza:

a = tabela->campo         // Clipper
$a = $linha->campo;       // PHP
a = linha.campo           ## Python

Nova trapaca aqui. O Clipper suporta nativamente a sintaxe acima para tabelas DBF, mas não me permite definir um novo tipo com essa sintaxe. Já PHP e Python permitem criar tipos com atributos dinâmicos, confortáveis ao usuário.

Das linguagens estáticas, C++ realmente fornece todas as ferramentas para criar-se tipos quase indistinguíveis dos primitivos, e inclusive evitar completamente o uso de ponteiros, new e delete. Infelizmente, boa parte dos programadores C++ insiste em usar ponteiros em demasia, e isso acaba trazendo injusta má fama à linguagem.

Em C, naturalmente não há que falar em criação de novos tipos. Não há sequer classes. Clipper também não permite criar nem tipos nem classes. O pretenso sucessor do Clipper, CA-Visual Objects, abriu a possibilidade de criar classes, obedecendo aos planos originais da Nantucket.

Das linguagens dinâmicas, Python parece oferecer as melhores ferramentas para fabricação de tipos novos, através dos métodos-operadores __add__, __mul__, __del__, etc.

Riqueza e direcionamento da biblioteca

Uma linguagem é inútil sem uma boa biblioteca que facilite a vida do programador.

Esse é o *grande* mal do C++ hoje, em particular no mundo do software livre. A STL torna difícil a vida do programador em 2 fases. Primeiro, é difícil de entender e usar. Quando o programador supera essa fase, descobre que STL não tem uma coisa óbvia como acesso a banco de dados, ou um simples tipo data/hora.

Linguagens muito mais despretensiosas que C++ não falharam nesse quesito. Um bom exemplo é PHP. É uma linguagem ruim, com tipagem fraca, lenta, mas *brilha* no quesito bibliotecas. Torna fácil fazer absolutamente qualquer coisa.

O próprio C acaba ficando melhor na foto que C++ neste quesito; porque qualquer ferramenta oferece uma API C, mas dificilmente uma API C++.

Felizmente, Python também possui uma biblioteca muito rica, e é uma linguagem melhor que PHP. Sem dúvida isso ajuda no sucesso do Python.

O sucesso de linguagens como Access, Visual Basic, Delphi etc. pode em grande parte ser explicado pela riqueza da biblioteca. Não só a riqueza, mas também o correto direcionamento; ou seja, tornar fácil aquilo que o programador típico vai querer fazer com a linguagem. A grande maioria dos aplicativos PHP vai ser sistemas baseados; em Web, então tornou-se fácil lidar com HTML e HTTP. A maioria dos aplicativos Delphi vai lidar com bancos de dados, então há toneladas de componentes para auxiliar nessa tarefa. E assim por diante.

Mas o direcionamento da biblioteca também não pode ser a ponto de obstar o uso para outros fins que não os previstos pelo criador da linguagem.

As linguagens de "4a geração", atreladas a bancos de dados, tinham o hábito de fornecer pacotes fechados, sem possibilidades de extensão (nem mesmo em C ou assembler). Funcionava bem para programas normais, mas fazer qualquer coisa diferenciada é um pesadelo. Com o tempo (tempo demais, em minha opinião) essa severa limitação empurrou de volta as software-houses de volta para linguagens de "3a geração".

Uma e outra linguagem de 4a geração que sobrou, evoluiu para tornar-se extensível. Um exemplo é o Access, que implementa um dialeto Visual Basic mas pode chamar qualquer função em DLL.

Ainda neste contexto, o Clipper foi uma linguagem interessante porque tinha uma boa biblioteca, que supria todas as necessidades do desenvolvimento em modo texto, com acesso aos bancos de dados DBF. O tipo "date" (data) do Clipper ainda considero melhor que todas as demais linguagens que usei a seguir. A cada linguagem nova em que faço um sistema, reimplemento as funções ctod(), dtoc() e dtos().

Na migração para o ambiente gráfico, tanto a linguagem Clipper como a biblioteca seriam insuficientes. O Clipper precisaria de algumas melhorias para continuar no mercado. Aí a Nantucket foi vendida para a Computer Associates, que não soube conduzir o processo.

O resultado desastroso foi o CA-Visual Objects: lento apesar de compilado para binário, bugado, incrivelmente complexo, e ainda assim sem auto-suficiência alguma (não era possível construir um novo componente em VO). E sua biblioteca padrão não tinha nada muito diferente do Clipper.

O visual Objects falhou principalmente porque jogou fora o que o Clipper tinha de melhor: a) simplicidade e b) biblioteca suficiente para o usuário típico. O fato de ser muito bugado também não ajudou. Nem a imensa audiência do Clipper salvou o VO. Hoje estamos dispersos entre Delphi, Visual Basic, Java... mas ainda procuramos nosso novo Santo Graal, que talvez seja o Python.

Auto-suficiência

A auto-suficiência de uma linguagem é, para mim, uma das maiores provas de sua força. Ela pode acontecer em vários níveis.

Auto-suficiência na biblioteca, se grande parte dela, ou toda ela é feita na própria linguagem.

Surpreendentemente era uma característica do Clipper. Os fontes inclusive eram fornecidos no pacote, era possível analisar e modificar a biblioteca padrão.

Aqui também brilham Python, Perl e Java. Já o PHP é fraco nessa área, pois sua interpretação é muito lenta (mesmo depois de convertido para bytecode), o que impede o uso de grandes bibliotecas em PHP.

Naturalmente, C e C++ também são totalmente auto-suficientes, e também são as linguagens subjacentes das demais citadas.

Auto-suficiência no sistema de componentes, se podemos criar componentes novos na própria linguagem. Isso é algo mais importante em linguagens para ambiente gráfico.

Exemplo de linguagem com baixa auto-suficiencia aqui era (é) é o Visual Basic: um componente novo tinha (tem) de ser escrito em C++, o que implicava em profundo conhecimento de MFC e Win32.

Já o Delphi era diametralmente oposto: componentes e IDE eram escritos em Delphi, o usuário poderia criar e/ou instalar novos componentes, numa linguagem mais fácil, com uma biblioteca de base (VCL) muito mais confortável que a MFC.

O Java também é poderoso, enquanto linguagem, para criar seus próprios componentes, mas um pouco lento. As bibliotecas gráficas Swing desenham todos os widgets em puro Java, o que uniformiza sua aparência em qualquer sistema, à custa de lentidão.

Auto-suficiência perfeita, quando o compilador da linguagem é escrito na própria linguagem. Isso obviamente tem importância nas linguagens estáticas compiladas.

Delphi e Java são linguagens nesse grupo, assim como C e C++.

* Extensibilidade

Como já foi dito, um erro das linguagens "de 4a geração" foi limitar demais o escopo, impedindo fazer qualquer coisa não previamente suportada na linguagem.

Uma linguagem não precisa ser boa para absolutamente tudo, mas algumas tentam. O C++ é o resultado dessa tentativa: extremamente completo, porém excessivamente complexo ("não cabe na cabeça").

Nos tempos do MS-DOS, um dos fatores de sucesso do Clipper foi a facilidade de extensão. A linguagem em si era fácil, e podia-se fazer qualquer coisa a mais em C ou assembler. Chegou a existir uma boa quantidade de bibliotecas de terceiros, uma edição primitiva e anterior dos componentes Delphi.

Felizmente, qualquer linguagem em uso corrente facilita a extensibilidade em maior ou menor grau. Uma menção especial para Python que permite um desenvolvimento progressivo de uma classe ou função, primeiramente em Python e posterior reescrita em C se for necessário.

* Orientação a objetos

C++ não faz zeramento automático dos tipos primitivos ao criar um novo objeto (também não faz para novas variáveis), sob a alegação de que isso prejudica muito a performance. Não concordo com isso porque o Delphi garante zeramento automático e é rápido.

C++ Também encoraja o uso de objetos em pilha, como se fossem tipos, pois isso desincumbe o programador de gerenciar memória (realmente verdadeiro) e segundo muitos aumenta a velocidade por evitar o overhead da alocação dinâmica (falso, porque o Delphi aloca todos os objetos dinamicamente e é rápido).

Usar C++ de forma racional implica em usar maciçamente objetos em pilha, e evitar o uso de ponteiros, bem como new e delete. Se absolutamente necessário, "cercar" tais práticas "perigosas" em um tipo/classe muito bem testado.

Existe uma situação que somos obrigados a usar ponteiros: polimorfismo. Esse é um "defeito" de todas as linguagens estáticas (C++, Java, Object Pascal), que induz ao uso excessivo de hierarquias de classes, o que engessa os programas e bibliotecas.

Já em Python (e em outras linguagens dinâmicas creio eu) o polimorfismo é perfeito. Se o objeto, seja qual for o seu tipo, possuir o método "bla", a chamada

obj.bla()

funciona. Já em C++, eu seria obrigado a declarar "obj" como uma superclasse, e apenas objetos-descendentes seriam aceitáveis. Existem alguns truques sujos que se pode usar com RTTI, tanto em C++ como em Delphi, talvez tenham uso legítimo em bibliotecas de legado, mas em geral são coisas sempre mal usadas...

Reflexividade e delegação

Reflexividade é a possibilidade de explorar o sistema de tipos em tempo de execução. C não tem esse recurso, C++ tem apenas RTTI opcional para classes, insuficiente para desenvolvimento em IDE.

No Delphi, que é estático, o RTTI é habilitado para todas as classe, e introduziu-se as propriedades "published". Tais proprieades têm características de sistemas dinâmicos, como possibilidade de consulta pelo nome em run-time, e serialização de/para "streams". Os demais métodos não-publicados são resolvidos estaticamente.

A propósito: uma "propriedade" em Delphi é um conjunto de dois métodos getx() e setx() que são usados pelo usuário da classe como um simples membro da classe. É poderoso, agradável e bastante útil em programação GUI, onde muitas atribuições têm de ter efeito colateral (imagine janela.largura = 600). Em C++ esse recurso não existe nativamente, embora seja possível (a duras penas) emulá-lo com um objeto proxy.

A consulta em run-time inclui consulta em tempo de *desenvolvimento*. Quando o programador edita as propriedades de um componente, está justamente lidando com as propriedades "published". Os valores dessas propriedades são armazenadas (serializadas) num arquivo em separado do fonte Pascal, e recarregadas dali conforme a necessidade. (Sim, os componentes do Delphi estão em *execução* parcial mesmo durante o desenvolvimento. Alguns chegam ao ponto de carregar imagens, fazer consultas SQL etc.)

O C++ Builder estendeu o C++ com as características acima, para poder usar componentes Delphi e também facilitar a vida dos programadores. Não há nada parecido em C++ "puro". Certamente pode ser implementado, mas não seria uma tarefa fácil.

Java e C# são linguagens mais novas, pós Visual-Basic e Delphi; a praticidade dos componentes já era bem conhecida. Tais linguagens têm provisão nativa para reflexividade.

Nas linguagens dinâmicas como Python e PHP, tal recurso está naturalmente disponível.

Outro recurso muito usado em programação GUI é a delegação, quando um objeto delega a outro o tratamento de determinado evento ou tarefa. O tratamento disso em linguagens estáticas é bastante variável.

Em C++, é necessário usar 2 ponteiros explicitamente: um para o método e outro para o objeto. Além dessa preocupação explícita, a sintaxe para ponteiros a métodos é terrível.

A biblioteca C++ Qt criou um mecanismo paralelo, os "signals/slots", para tratar eventos de forma mais simples ao desenvolvedor. É um mecanismo totalmente dinâmico (usa strings como rótulos etc.), o que causa um certo overhead (nada preocupante, na verdade).

Os signals/slots são usados como "extensões" da própria linguagem C, o que deixa o código limpo, mas exige um passo adicional na compilação, o compilador "moc" que deve ser rodado antes do compilador C++ normal.

A existência do "moc" é muito criticada, mas a opção seria partir para a criação de um dialeto C++ não portável, tal qual o C++Builder.

Em Object Pascal/Delphi, o tipo "procedure of object" contém 2 ponteiros implicitamente. Normalmente, o objeto-delegado está contido no objeto-delegador (e.g. um botão dentro de uma janela), então não é difícil ao delegado saber de onde veio a mensagem.

Nas linguagens C# e Java, a delegação também foi tornada fácil com recursos da linguagem. Em linguagens dinâmicas, a resolução dinâmica dos métodos elimina de plano qualquer dificuldade com delegação.

Velocidade e consumo de memória

Uma linguagem com tipagem estática e forte tem obrigação de apresentar boa performance.

Na prática, as linguagens não estáticas / não fortes têm apresentado desempenho entre suficiente e surpreendente. Uma linguagem que nunca decepcionou na performance foi o Clipper. Muitos anos depois de começar a usá-lo, descobri que o executável Clipper é na verdade uma máquina virtual + bytecodes. Nunca tinha suspeitado disso antes.

Em testes recentes que fizemos, Python apresentou performance muito melhor que Java. E, com o uso de um compilador JIT para Python, o Psyco, a performance encostou em C++.

O desempenho de C continua imbatível, mas porque ele transfere ao programador a responsabilidade de implementar *tudo*.

O consumo de memória das linguagens dinâmicas é compreensivelmente bem mais alto que o das linguagens estáticas, pois implica na carga de uma máquina virtual.

Com a boa peformance, existência de JIT e ainda a possibilidade de reescrever funções críticas em C, por que algum desenvolvimento novo ainda seria feito em linguagem estática?

Penso ainda que, com a crescente importância do cache de CPU no desempenho dos computadores de uso geral, uma VM de linguagem interpretada que caiba no cache vai ter desempenho cada vez mais próximo a um binário grande que invalida o cache de instruções freqüentemente.

A tipagem dinâmica torna o desenvolvimento inseguro?

Um possível argumento é que a linguagem dinâmica ou fraca aumenta a insegurança no desenvolvimento. Entenda por insegurança a possibilidade de erros de run-time na cara do usuário, erros que uma linguagem estática pegaria em tempo de compilação. É um problema não negligenciável.

Alguém diria que "em C++ o erro também acontece mas vai ser um 'Segmentation Fault' ao invés de uma mensagem clara". Esta é uma visão estreita. O bom uso do C++ evita violações de acesso *mesmo na fase de desenvolvimento*. Mas reconheço que é difícil chegar a este nível de conhecimento do C++.

O Delphi resolve o problema de outra forma: usa ad nauseam a arquitetura de componentes, que "esconde" praticamente todo o tratamento de ponteiros, criação e destruição de objetos etc. Para o programador iniciante, a linguagem parece até ter garbage collection.

Mas voltando ao tema. Em minha opinião particular, uma linguagem de tipos fracos (e.g. PHP) é problemática para desenvolvimento de sistemas de médio/grande porte, pois não só mascara problemas em tempo de compilação/interpretação, mas também em tempo de run-time. Ao invés de um erro, o usuário recebe um resultado errado...

Problemas semelhantes ocorrem com programas C++ que usam excessivamente recursos como operator tipo(), que enfraquecem o sistema de tipos.

Se tipagem forte é pré-requisito para uma boa linguagem, sobra a decisão entre tipagem estática e dinâmica.

De minha parte, sempre achei muito confortável a tipagem estática. Cometo muitos erros de digitação, e o uso de C++ me tornou ainda mais preguiçoso nesse aspecto (às vezes deixo erros propositadamente para ser "avisado" depois pelo compilador).

Por outro lado, tenho programas em Clipper rodando há 14 anos por aí, então a tipagem dinâmica não deve ser tão ruim. Ok, o compilador Clipper pega erros flagrantes de sintaxe, mas sobra muita coisa "falhável".

Mas o segredo do sucesso com uma linguagem dinâmica é um só: testar, testar, testar. Ter certeza de que todas as partes do programa foram executadas nos testes.

O Clipper não encoraja particularmente uma boa metodologia de testes, pelo fato de ter compilação explícita, além de não ser orientado a objetos. Linguagens modernas como Python oferecem todos os recursos possíveis para testes, inclusive testes automatizados.

Como um programa C++ também tem de ser testado, mesmo que passe na compilação, é certo que programar numa linguagem dinâmica é mais produtivo, e também seguro. E sem violações de acesso ;)

Realmente não há motivos para desenvolvimento de coisas novas que não em linguagens dinâmicas, dentro deste contexto sendo Python provavelmente a melhor opção.

Apêndice: A segregação entre C e C++ no software livre

Um pequeno choque cultural que sofri quando iniciei o uso de software livre é a separação entre compiladores (e bibiotecas) C e C++.

Tanto assim que um dos motivos do ambiente gráfico GNOME surgir foi o fato do melhor ambiente até então, o KDE, ser feito em C++, e a implementação do compilador C++ GNU ser (na época) muito ruim. O GNOME implementa um esquema de "objetos" totalmente baseado em C e macros.

Naturalmente, teria sido mais racional tratar de melhorar o compilador C++, o que felizmente aconteceu ao longo do tempo.

Já no mundo Windows, não existe mais essa distinção. Todo compilador C é C++ implicitamente. Em um certo sentido, a linguagem C "pura" morreu no Windows.

Para certos tipos de desenvolvimento, alguns recursos do C++ têm de ser "criminalizados". Por exemplo, uso de STL na programação de um kernel de sistema operacional. É fácil policiar isso, ou no próprio controle de versão do codigo-fonte, e não linkando a biblioteca libstdc++, o que vai dar um erro bem feio se alguém tentar usar STL.

Mas, no mundo do software livre, ainda existe um considerável preconceito contra C++, e uso do mesmo em projetos de grande porte. Acaba-se usando C que, sendo franco, é uma linguagem insuficiente. (E grande parte dessa insuficiência deriva da falta de um tipo string. O Delphi, como foi dito, não permite criar novos tipos, mas quase ninguém sente falta.)

De minha parte, considero correto o que aconteceu no mundo Windows. O mercado novamente tomou a decisão correta. Quando faço um programa "em C", estou na verdade fazendo em C++, e compilo com o g++ mesmo não tendo usado um recurso sequer fora do ANSI C. O compilador C puro (gcc) é para mim o compilador do kernel e nada mais.

blog comments powered by Disqus