Por que o java não é usado como uma linguagem de construção?


24

Se Java é uma linguagem de uso geral, e a criação de um programa é algo que pode ser descrito usando a linguagem Java, por que essa não é a melhor maneira de escrever arquivos de construção e, em vez disso, usamos ferramentas como Ant, Maven e Gradle? Isso não seria mais direto e também eliminaria a necessidade de aprender outra linguagem de programação? (BTW - essa pergunta também pode ser aplicada a outros idiomas, como C #)


7
Você pode ter uma pergunta um pouco mais interessante sobre "por que as linguagens de uso geral não são usadas para linguagens de construção" - quero dizer, C também não é uma linguagem de construção. Eu também sugerem a olhar para a cerimônia em torno de compilar um único arquivo .java em Java

8
Provavelmente, isso pode ser generalizado como "Por que se preocupar com DSLs?"
FrustratedWithFormsDesigner

11
Uma pergunta melhor pode ser; Por que os IDEs / compiladores / ferramentas são tão ruins que as ferramentas de construção são necessárias em primeiro lugar.
Brendan

6
@Brendan não é uma pergunta, pois as ferramentas de construção e os IDEs servem a propósitos diferentes.
28414 jjenting

11
Como as linguagens de "uso geral" nunca devem ser usadas em vez das linguagens simples e específicas de domínio bem definidas e simples. E, se a necessidade de aprender "mais uma linguagem de programação" lhe interessar, você realmente não deveria estar programando, tente outro tipo de comércio.
SK-logic

Respostas:


21

Ferramenta específica para uma finalidade específica

  • Verbosidade

    Linguagens de uso geral geralmente são muito detalhadas. Se eu tivesse que gerenciar uma compilação em Java, ficaria muito deprimido muito rapidamente pelo tamanho da fera. No entanto, pode ser facilmente gerenciável usando uma DSL escrita em Java. E, até certo ponto, é assim que você pode ver Gradle (para Groovy) e Buildr (para Ruby).

  • Dificuldade

    Linguagens de uso geral são difíceis. Bem, eu não acho que a programação seja difícil e não possa ser entendida por ninguém, mas o ponto é: seu engenheiro de construção não é necessariamente seu programador!

  • Finalidade

    Isso é mais ou menos na interseção de dificuldade e verbosidade . Uma linguagem é projetada para um propósito, e aqui estamos falando de algo muito específico. Então, por que você precisaria ou desejaria usar uma linguagem de uso geral ? Para compilações, você precisa:

    • ramificações e condicionais para lidar com configurações, ambientes, etc ... separados
    • um conjunto de instruções para extrair dados do seu ambiente,
    • um conjunto de instruções para produzir entregas.

    Você realmente não precisa de muito mais.

Claro que é chato quando seu sistema de compilação parece não ser flexível o suficiente para aquele caso de uso especial que você procura, mas provavelmente é muito melhor do que a alternativa para a maioria das pessoas.

Provavelmente é por isso que existe uma polaridade entre as pessoas que preferem sistemas declarativos de construção em detrimento da maioria das forças programáveis: acho que um desenvolvedor pode ter uma tendência natural a procurar maneiras de sair da caixa.

Espere, precisamos mesmo de uma ferramenta?

Outra pergunta relacionada seria: realmente precisamos de uma ferramenta de construção? Não é o fato de que eles existem em todas as línguas o sinal de que preenchem uma lacuna que nem deveria estar lá em primeiro lugar?

Alguns idiomas não exigem necessariamente uma ferramenta de construção. Por exemplo, a maioria das linguagens de script não precisa de uma e resolve em tempo de carregamento. Ou pegue o Go, cujo compilador cuidará de tudo para você, o que é um bom contraponto: e se um compilador como o gcc de repente não precisasse de um monte de sinalizadores, um vinculador e um makefile para deixar tudo junto? Ou se o javac não precisasse de um build.xml ou pom.xml para dizer a ele o que fazer? O gerenciamento de dependências não deve fazer parte diretamente das ferramentas do próprio idioma, pois as dependências fazem parte do programa final?

Certamente parece uma abordagem muito mais simples para o usuário (o construtor). Embora se possa argumentar que eles estão apenas se escondendo e tirando sua escolha e oportunidades de influenciar o processo de criação (mas você esperaria que essa ferramenta permita extensões do compilador e coisas semelhantes). Além disso, costumávamos ver as ferramentas e a linguagem como duas coisas separadas, então ele pode parecer impuro de repente tê-las tão fortemente acopladas.

Não acho que o idioma que você usa para criar seus programas seja o problema. É a linguagem que você usa para programar e sua principal plataforma e ferramentas que devem importar, e ainda estamos avançando nisso.


Pessoalmente, eu usei make / gmake / autotools / pmk e fiquei feliz com eles no C, e comecei com Java quando tudo o que tínhamos era make, depois ant, e agora geralmente prefiro o Maven a todas essas alternativas. Embora eu possa ver valor em gradle, buildr e outros, mas eu gosto da prevalência de maven até agora, até que ocorra uma mudança mais significativa. Além disso, eu gosto que seja rígido, mas ainda assim você terá a capacidade de contornar isso, se necessário. Que não é fácil é uma coisa boa.

É uma ferramenta de construção. Apenas aprenda a abraçá-lo e não lute contra ele. É uma batalha perdida. Ou pelo menos muito, muito longo.


Realmente gosto do seu pragmatismo. Minha pergunta é por curiosidade. Eu uso o maven (que já usou make e formiga no passado) e faz "magia negra", que às vezes é boa e às vezes ruim. Mas ainda é mágico.
vainolo

11
"Ou se o javac não precisou de um build.xml ou pom.xml para dizer a ele o que fazer?" - heh. isso não acontece e nunca aconteceu.
precisa saber é o seguinte

@immibis: isso é discutível. Eu realmente não gostaria de construir meus projetos no escritório apenas com javac :) Certamente seria necessário um pouco de cola com um Makefile ou um script de shell ou, no mínimo, aliases de shell para juntar as coisas. Ou um programa gigantesco com tudo em uma pasta e todos os detalhes no repositório. Não é realmente algo que eu gostaria! :) Mas esse é outro debate inteiramente, não relacionado à pergunta do OP.
haylem

A integração do sistema de compilação ao idioma também é problemática para projetos poliglotas. Se eu usar os idiomas A e B e quiser ter um único processo de compilação para eles, qual sistema de compilação do idioma devo usar?
Sebastian Redl

@SebastianRedl Então, como o problema fica mais fácil com a introdução de um terceiro idioma? Basta escolher o idioma que funciona melhor para você. (E, claro, se você precisar de uma terceira língua, Java também pode ser isso.)
Ville Oikarinen

21

Javaé um imperativo linguagem, Ant, Maven, etc, são declarativas línguas:

Poderíamos definir a diferença da seguinte maneira:

  • Programação imperativa: dizendo à "máquina" como fazer algo e, como resultado, o que você deseja que aconteça.
  • Programação declarativa: diga à "máquina" o que você gostaria que acontecesse e deixe o computador descobrir como fazê-lo. 1

As linguagens de compilação informam ao construtor o que deve ser feito, de onde deve ser tirada etc. O mecanismo que executa a compilação (escrito em uma linguagem imperativa, como o @ElliottFrisch observou), lê essas instruções e as cumpre.

Linguagens declarativas podem parecer mais apropriadas em cenários de compilação, pois as tarefas de compilação geralmente são as mesmas em todo o caso e é considerado mais fácil de manter e legível nesse formato do que no código de código completo.


3
Há pelo menos um sistema de compilação que usa uma linguagem imperativa. O Scons usa Python.
user16764

Torná-lo imperativo não é mais difícil do que escrever uma classe que pode conter uma lista de dependências, e um método para resolvê-las. Suspeito que exista outro motivo - como o tempo de inicialização da JVM, talvez.

2
@ Lee: Quase todas as ferramentas de compilação usadas no mundo Java (Ant, Maven, Gradle, SBT, ...) também geralmente são executadas na JVM (com as exceções de Rake, Buildr ou Scons, que podem , mas não possuem). para executar na JVM).
Jörg W Mittag 26/03

6
@vainolo "A maioria das pessoas realmente não gosta de Ant / Maven / Make"? Essa é uma afirmação ousada!
Ben Thurley 26/03

11
@BenThurley que eu gostava de fazer, por que a formiga foi criada? e se gostava de formiga, por que era maven? E agora, por que as pessoas estão usando Gradle? Mas concordo que é uma afirmação ousada, e que só é apoiado por evidências "anedótica" de algumas dezenas de desenvolvedores java
vainolo

4

Se você observar os recursos de um sistema de compilação típico, encontrará:

  1. Muitos dados: nomes, comutadores, configurações, itens de configuração, strings, etc.
  2. Muita interação com o ambiente: comandos, variáveis ​​de ambiente
  3. Um "mecanismo de compilação" relativamente simples que lida com dependências, encadeamentos, registros etc.

Se você deseja escrever uma série de arquivos de compilação usando alguma linguagem (Java / C # / Python / etc), por volta da terceira ou quarta iteração, deve optar por (a) manter a maioria dos dados e comandos externos como dados em algo como XML (b) escrevendo o "mecanismo de compilação" no seu idioma favorito.

Você também consideraria útil tratar alguns dos dados em seu XML como uma linguagem interpretada, para acionar vários recursos no mecanismo de construção. Você também pode interpretar algumas macros ou executar substituições de string nos dados.

Em outras palavras, você terminaria com Make, Ant, Rake ou MsBuild. Uma linguagem imperativa para o que faz bem e estruturas de dados para descrever o que você deseja fazer, agora geralmente em XML.


2

Vários fatores contam com o uso de Java / C ++ / C # nesses casos.

Em primeiro lugar, você teria que compilar seu script de construção antes de executá-lo para criar seu aplicativo. Como você especificaria pacotes, sinalizadores, versões do compilador, caminhos de ferramentas necessários para criar seu script de construção? Certamente, você pode encontrar uma maneira de contornar isso, mas é muito mais fácil ter uma linguagem que não precise dessa etapa de construção (por exemplo, python) ou uma linguagem que sua ferramenta de construção compreenda nativamente.

Em segundo lugar, os arquivos de construção são pesados, enquanto Java / C ++ / C # são muito mais voltados para a escrita de código e algoritmos. Java e amigos não têm uma representação muito sucinta de todos os dados que você deseja armazenar.

Em terceiro lugar, Java e amigos precisam de muito clichê para serem válidos. O arquivo de construção precisaria estar dentro de um método dentro de uma classe com todas as suas importações. Ao usar uma linguagem de script ou linguagem personalizada, você pode evitar todo esse clichê e ter apenas os detalhes da compilação.


0

De fato! Por que não usar uma linguagem poderosa e expressiva para um problema mais complexo do que as pessoas costumam pensar (inicialmente)? Especialmente quando as pessoas que enfrentam o problema já são competentes com esse idioma. (Construir é o próprio problema dos programadores e é melhor resolvido pelos programadores.)

Eu também me fiz essa pergunta anos atrás e decidi que Java é uma boa linguagem para definir builds, especialmente para projetos Java. E, como resultado, comecei a fazer algo a respeito.

AVISO LEGAL : Nesta resposta, estou promovendo o iwant , um sistema de construção que estou desenvolvendo. Mas como essa é uma discussão opinativa, tenho certeza que está tudo bem.

Não vou detalhar os benefícios do Java (poder e expressividade) ou quero especificamente. Se você estiver interessado, pode ler mais na página iwant .

Em vez disso, considerarei por que o Java (e outras GPLs) é tão prontamente descartado como inadequado para a construção. Muitas respostas e comentários aqui são bons exemplos desse pensamento. Vamos considerar alguns dos argumentos típicos:

"Java é imperativo, mas as compilações são melhor definidas de maneira declarativa" , eles podem dizer.

Verdade. Porém, ao usar uma linguagem como metalinguagem para uma DSL interna , o que realmente conta é sua sintaxe . Mesmo uma linguagem imperativa como Java pode ser enganada para ser declarativa. Se parece e parece declarativo, é (para fins práticos) declarativo. Por exemplo:

JacocoTargetsOfJavaModules.with()
    .jacocoWithDeps(jacoco(), modules.asmAll.mainArtifact())
    .antJars(TestedIwantDependencies.antJar(),
            TestedIwantDependencies.antLauncherJar())
    .modules(interestingModules).end().jacocoReport(name)

Este é um exemplo real do projeto de demonstração do iwant .

De fato, compare isso com alguns sistemas de construção supostamente declarativos que expõem seus usuários a verbos imperativos como "teste" ou "compilação". A declaração acima contém apenas substantivos, sem verbos. Compilar e testar são tarefas tratadas implicitamente por iwant, a fim de conceder ao usuário os substantivos que ele / ela deseja. Não é a linguagem. É como você o usa.

"Java é detalhado"

Sim, muitos códigos Java lá fora são detalhados. Mas, novamente, não é a linguagem, é como você a usa. Se uma implementação for detalhada, encapsule-a atrás de uma boa abstração. Muitas GPLs fornecem mecanismos adequados para isso.

Imagine o snippet Java acima, escrito em XML. Substitua parênteses por colchetes angulares e mova-os. E duplique cada palavra - chave como uma tag de fechamento! Java como uma sintaxe não é detalhado.

(Eu sei, comparar com XML é como pegar doces de um bebê, mas muitas compilações são definidas em XML.)

"Você precisaria compilar seu script de construção"

Este é um ponto válido. No entanto, é apenas um pequeno problema técnico a ser resolvido. Eu poderia ter resolvido isso usando casca de feijão ou algum outro intérprete. Em vez disso, resolvi-o tratando-o como apenas mais um problema de compilação e iniciando o boot com um simples shell ou script ant que compila e executa um bootstrapper Java simples.

"Java tem clichê"

Verdade. Você precisa importar classes, mencionar "public", "class" e assim por diante. E aqui DSLs externos simples obtêm uma vitória fácil inicial.

E se o seu projeto é tão trivial que esse padrão é significativo, parabéns. Seu problema não é difícil e realmente não importa como você o resolve.

Mas muitos projetos precisam muito mais do que compilação, relatório de cobertura e embalagem. Se o padrão do Java é aceitável para os problemas dos clientes, por que não criar problemas? Por que fazer sapatos apenas para os filhos dos outros?


0

Uma coisa que não acho que as outras respostas tenham abordado é que as limitações e a transparência dessas linguagens de construção são uma grande parte do que as torna úteis. Vamos pegar o Maven, por exemplo. Sim, ele executa compilações, mas também define dependências. Isso permite que uma compilação do Maven abaixe essas dependências e veja suas dependências e assim por diante.

Considere se isso foi feito diretamente com Java. A ferramenta de construção verificaria que há uma dependência. Seria necessário puxar para baixo outro aplicativo Java e executá-lo para determinar quais são suas dependências. Mas para o Maven, ele simplesmente analisa as declarações de dependência. O arquivo de compilação do maven é transparente. Uma linguagem completa de Turing é inerentemente não transparente e, portanto, é inferior para alguns propósitos como este.


Como Gradle se encaixa nisso? Ele define dependências em um estilo declarativo, usando uma linguagem de uso geral (Groovy). Em uma ferramenta baseada em Groovy, JavaScript ou Lisp, é natural usar o compilador ou intérprete da linguagem para analisar declarações, se você deseja apenas lê-las ou 'executá-las' (aplique alguma função). Essa dualidade de código e dados não faz parte do idioma Java geralmente aceito, embora não seja impossível. A integridade de Turing não impede uma boa representação de dados. Isso abre a possibilidade de seus dados fazerem algo que você não esperava.
joshp

@joshp Não estou familiarizado com Gradle. É descrito como um DSL e as coisas parecem bastante declarativas. Basear-se no Groovy não significa necessariamente que seja equivalente ao Groovy em seu poder. Você provavelmente estaria em uma posição melhor para dizer se Gradle é de fato uma linguagem completa de Turing. Os exemplos de dependência que olhei parecem bastante simples. Você pode usar expressões arbitrárias do Groovy em coisas como declarações de dependência?
21417 JimmyJames

Pessoalmente, eu nem gosto de dependências transitivas. Geralmente, eles causam surpresas no caminho de classe (várias versões incompatíveis de bibliotecas). É por isso que o maven tem o elemento de exclusão, mas o aborrecimento não vale a pena. Dependências explícitas tornam a vida mais simples. Ainda assim, dependências transitivas podem ser implementadas com Java. Fiz algo assim com o iwant , reutilizando as definições de compilação de outros projetos.
Ville Oikarinen

@VilleOikarinen Por acaso concordo principalmente com você. Eu acho que também causa uma tonelada de inchaço, já que não há custo percebido para atrair mais dependências, mesmo que você não as use. No entanto, no contexto desta resposta, não estou comentando o valor ou a sabedoria desse recurso, mas sobre como o uso de uma DSL é útil para alcançá-lo.
21417 JimmyJames

11
@VilleOikarinen Acho que chegamos ao final disso, mas só quero esclarecer que não estou falando de pom / maven. Este é um exemplo de DSL de construção, mas não penso muito nisso. Eu o uso de má vontade e acho desajeitado. Mas o que tem o pom tão dominante são as declarações de dependência. Eu usei o Buildr por um tempo e ele lê pom para dependências, mas não as usa para as especificações de compilação. Existem várias ferramentas que não são baseadas em Java que entendem esse pom, mas o AFAIK, o que mais importa é as dependências.
precisa saber é o seguinte
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.