Java가 범용 언어이고 프로그램을 빌드하는 것이 Java 언어를 사용하여 설명 할 수있는 것이라면 왜 이것이 빌드 파일을 작성하는 가장 좋은 방법이 아닌 대신 Ant, Maven 및 Gradle과 같은 도구를 사용합니까? 더 간단하지 않고 또 다른 프로그래밍 언어를 배울 필요가 없습니까? (BTW-이 질문은 C #과 같은 다른 언어에도 적용될 수 있습니다)
Java가 범용 언어이고 프로그램을 빌드하는 것이 Java 언어를 사용하여 설명 할 수있는 것이라면 왜 이것이 빌드 파일을 작성하는 가장 좋은 방법이 아닌 대신 Ant, Maven 및 Gradle과 같은 도구를 사용합니까? 더 간단하지 않고 또 다른 프로그래밍 언어를 배울 필요가 없습니까? (BTW-이 질문은 C #과 같은 다른 언어에도 적용될 수 있습니다)
답변:
다변
범용 언어는 종종 너무 장황합니다. Java로 빌드를 관리해야한다면 짐승의 크기에 따라 매우 빨리 우울해질 것입니다. 그러나 Java로 작성된 DSL을 사용하여 쉽게 관리 할 수 있습니다. 그리고 어느 정도까지 Gradle (Groovy)과 Buildr (Ruby)를 볼 수 있습니다.
어려움
범용 언어는 어렵다. 글쎄, 나는 프로그래밍이 어렵다고 생각하지 않으며 누군가가 선택할 수는 없지만 요점은 빌드 엔지니어가 반드시 프로그래머가 아니라는 것입니다!
목적
난이도 와 세부 정보 의 교차점에서 어느 정도 입니다. 언어는 목적을 위해 설계되었으며 여기서는 매우 구체적인 것에 대해 이야기하고 있습니다. 그럼 왜 필요하거나 사용하려는 것이 일반적인 목적의 언어를? 빌드에는 다음이 필요합니다.
더 이상 필요하지 않습니다.
빌드 시스템이 특별한 유스 케이스에 충분히 유연하지 않은 것처럼 보일 때 성가 시지만 대부분의 사람들의 대안보다 훨씬 낫습니다.
그렇기 때문에 대부분의 프로그래밍 가능 프로그램보다 선언적 빌드 시스템을 선호하는 사람들 사이에 극성이있는 이유는 아마도 개발자가 상자에서 벗어날 수있는 방법을 찾는 자연스러운 경향이있을 것입니다.
또 다른 관련 질문은 다음과 같습니다. 실제로 빌드 도구가 필요합니까? 그들이 모든 언어로 존재한다는 사실이 처음부터 거기에 있어서는 안되는 간격을 메운다는 표시가 아닙니까?
일부 언어에는 반드시 빌드 도구가 필요하지 않습니다. 예를 들어, 대부분의 스크립팅 언어는 언어를 필요로하지 않으며로드시 해결됩니다. 또는 컴파일러가 당신을 위해 모든 것을 처리 할 Go를 가져 가십시오 .gcc와 같은 컴파일러에 갑자기 모든 플래그, 링커 및 makefile이 필요하지 않으면 어떻게해야합니까? 또는 javac에 build.xml 또는 pom.xml이 필요하지 않은 경우 어떻게해야합니까? 의존성이 최종 프로그램의 일부이기 때문에 의존성 관리가 언어 자체 툴링의 일부가 아니어야합니까?
분명히 사용자 (빌더)에게는 훨씬 간단한 접근법처럼 보입니다. 비록 그들이 단지 후드 아래에서하고 있고 빌드 프로세스에 영향을 줄 수있는 선택과 기회를 제거한다고 주장 할 수는 있지만 (그러나 그러한 도구는 컴파일러 확장과 비슷한 것들을 허용하기를 바랍니다). 또한 우리는 도구와 언어를 별개의 두 가지로 보았 기 때문에 갑자기 도구가 너무 밀접하게 결합되어 있지 않은 것처럼 보일 수 있습니다.
프로그램을 빌드하는 데 사용하는 언어가 sthe 문제라고 생각하지 않습니다. 프로그래밍에 사용하는 언어와 핵심 플랫폼 및 툴링이 중요하며, 우리는 여전히 진전을 보이고 있습니다.
개인적으로, 나는 make / gmake / autotools / pmk를 사용하여 C에 만족했고, 우리가 만든 모든 것이 개미 였을 때 Java로 시작했으며 이제는 일반적으로 이러한 모든 대안보다 Maven을 선호합니다. gradle, buildr 및 기타에서 가치를 볼 수 있지만 더 큰 변화가 발생할 때까지 지금까지 maven의 보급을 좋아합니다. 또한 나는 그것이 단단하다는 것을 좋아 하지만 여전히 필요한 경우 그 문제를 해결할 수 있습니다. 쉽지 않은 것은 좋은 것입니다.
빌드 도구입니다. 그것을 받아들이는 법을 배우고 싸우지 마십시오. 지는 전투이다. 또는 적어도 매우 긴 것.
Java
되는 필수 , 언어 Ant
, Maven
등이다 선언적 언어 :
차이점을 다음과 같이 정의 할 수 있습니다.
- 명령형 프로그래밍 : "기계" 에게 무언가를 수행 하는 방법 을 알려 주면 결과적으로 원하는 일이 발생합니다.
- 선언적 프로그래밍 : "기계" 에게 무슨 일이 일어나고 있는지 말하고 컴퓨터가 어떻게해야하는지 알아 내십시오. 1
빌드 언어는 빌더 에게 수행해야 할 작업, 수행 위치 등을 알려 줍니다. 빌드 를 실행 하는 엔진 (@ElliottFrisch와 같이 명령형 언어로 작성 됨)은이 지침을 읽고이를 이행합니다.
빌드 작업은 일반적으로 완전히 동일하기 때문에 선언적 언어는 빌드 시나리오에서 더 적절 해 보일 수 있으며 본격적인 코드 형식보다 해당 형식으로 유지 관리가 쉽고 읽기 쉬운 것으로 간주됩니다.
일반적인 빌드 시스템의 기능을 살펴보면 다음을 찾을 수 있습니다.
일부 언어 (Java / C # / Python / etc)를 사용하여 일련의 빌드 파일을 작성하기로 설정 한 경우 약 3 ~ 4 회 반복하여 (a) 대부분의 데이터와 외부 명령을 데이터로 유지 (b) 좋아하는 언어로 "빌드 엔진"을 작성하십시오.
또한 XML의 일부 데이터를 해석 된 언어로 취급하여 빌드 엔진의 다양한 기능을 트리거하는 것이 유용하다는 것을 알 수 있습니다. 데이터에서 일부 매크로를 해석하거나 문자열 대체를 수행 할 수도 있습니다.
즉, Make 또는 Ant, Rake 또는 MsBuild로 마무리합니다. 잘하는 일을위한 명령형 언어, 그리고 현재 XML로하고 싶은 것을 설명하는 데이터 구조.
이 경우 Java / C ++ / C # 사용에 대한 여러 가지 요소가 있습니다.
먼저, 빌드 스크립트를 실행하여 앱을 빌드하기 전에 빌드 스크립트를 컴파일해야합니다. 빌드 스크립트를 빌드하는 데 필요한 패키지, 플래그, 컴파일러 버전, 도구 경로를 어떻게 지정 하시겠습니까? 확실히, 당신은 그 주위에 방법을 생각해 낼 수 있지만, 그 빌드 단계를 필요로하지 않는 언어 (예 : 파이썬) 또는 빌드 도구가 기본적으로 이해하는 언어를 갖는 것이 훨씬 간단합니다.
둘째, 빌드 파일은 데이터가 많은 반면 Java / C ++ / C #은 코드 및 알고리즘 작성에 훨씬 적합합니다. Java와 친구는 저장하려는 모든 데이터를 간결하게 표현하지 못합니다.
셋째로, Java와 친구는 유효하려면 많은 상용구가 필요합니다. 빌드 파일은 가져 오기가 모두 포함 된 클래스 내의 메소드 내에 있어야합니다. 스크립팅 언어 또는 사용자 정의 언어를 사용할 때 모든 상용구를 피하고 빌드 세부 정보를 가질 수 있습니다.
과연! 사람들이 종종 (초기) 생각하는 것보다 복잡한 문제에 강력 하고 표현력있는 언어를 사용하지 않겠습니까? 특히 문제에 직면 한 사람들이 이미 그러한 언어에 능숙 할 때. (빌딩은 프로그래머 자신의 문제이며 프로그래머가 가장 잘 해결합니다.)
또한 몇 년 전에이 질문을 저에게 물었고 Java는 특히 Java 프로젝트의 빌드를 정의하기에 좋은 언어라고 결정했습니다. 결과적으로 나는 그것에 대해 무언가를 시작했습니다.
면책 조항 :이 답변에서 나는 개발중인 빌드 시스템 인 iwant을 홍보 하고 있습니다. 그러나 이것은 어쨌든 의견이 많은 토론이므로 괜찮습니다.
Java (power and expressiveness) 또는 iwant의 이점에 대해 구체적으로 설명하지 않겠습니다. 관심이 있으시면 iwant 페이지 에서 더 많은 것을 읽을 수 있습니다 .
대신 Java (및 기타 GPL)가 구축하기에 부적합한 것으로 쉽게 해산되는 이유를 살펴 보겠습니다. 여기에 많은 답변과 의견이 그러한 사고의 좋은 예입니다. 일반적인 주장 중 일부를 고려해 봅시다.
"자바는 필수적이지만 빌드는 선언적인 방식으로 정의하는 것이 가장 좋습니다 ."
참된. 그러나 언어를 내부 DSL 의 금속 언어로 사용할 때 실제로 중요한 것은 구문 입니다. Java와 같은 명령형 언어조차도 선언적 으로 속일 수 있습니다. 선언적으로 보이고 느껴지면 (실제적인 목적으로) 선언적입니다. 예를 들면 다음과 같습니다.
JacocoTargetsOfJavaModules.with()
.jacocoWithDeps(jacoco(), modules.asmAll.mainArtifact())
.antJars(TestedIwantDependencies.antJar(),
TestedIwantDependencies.antLauncherJar())
.modules(interestingModules).end().jacocoReport(name)
이것은 iwant 데모 프로젝트의 실제 예입니다 .
실제로, 이것을 "테스트"또는 "컴파일"과 같은 명령형 동사에 사용자를 노출시키는 일부 선언적 빌드 시스템과 비교하십시오. 위의 선언에는 명사 만 있고 동사는 없습니다. 컴파일 및 테스트는 사용자가 원하는 명사를 부여하기 위해 iwant에 의해 암시 적으로 처리되는 작업입니다. 언어가 아닙니다. 당신이 그것을 사용하는 방법입니다.
"자바는 장황하다"
예, 많은 Java 코드가 상세합니다. 그러나 다시, 그것은 언어가 아니며, 그것이 당신이 그것을 사용하는 방법입니다. 구현이 장황한 경우 멋진 추상화 뒤에 캡슐화하십시오. 많은 GPL이이를위한 적절한 메커니즘을 제공합니다.
XML로 작성된 위의 Java 스 니펫을 상상해보십시오. 괄호를 꺾쇠 괄호로 바꾸고 움직이십시오. 그런 다음 모든 키워드를 닫기 태그로 복제하십시오 ! 구문 으로서의 Java 는 장황 하지 않습니다 .
(XML과 비교하면 아기에게서 사탕을 먹는 것과 같지만 많은 빌드가 XML로 정의 되기만합니다.)
"빌드 스크립트를 컴파일해야합니다"
이것은 유효한 포인트입니다. 그럼에도 불구하고 해결해야 할 사소한 기술적 문제 일뿐입니다. 나는 콩 껍질 이나 다른 통역사를 사용하여 해결할 수있었습니다 . 대신 다른 빌드 문제로 처리하고 간단한 Java 부트 스트 래퍼를 컴파일하고 실행하는 간단한 쉘 또는 개미 스크립트로 iwant을 부트 스트랩하여 문제를 해결했습니다.
"자바는 상용구가있다"
참된. 클래스를 가져와야하며 "public", "class"등을 언급해야합니다. 그리고 여기에 간단한 외부 DSL이 초기에 쉽게 승리합니다.
그리고 프로젝트가 너무 사소한 경우이 상용구가 중요하다면 축하합니다. 당신의 문제는 어려운 문제가 아니며 실제로 어떻게 해결하든 문제가되지 않습니다.
그러나 많은 프로젝트는 컴파일, 커버리지 보고서 및 패키징 이상의 기능을 필요로합니다. Java의 상용구가 고객의 문제에 허용되는 경우 문제를 해결하지 않으시겠습니까? 왜 다른 사람의 아이들을 위해서만 신발을 만드나요?
다른 답변에서 언급하지 않은 한 가지는 이러한 빌드 언어의 한계와 투명성이 유용한 언어의 큰 부분이라는 것입니다. 예를 들어 Maven을 보자. 예, 빌드를 실행하지만 종속성도 정의합니다. 이를 통해 Maven 빌드가 해당 종속성을 풀고 해당 종속성 등을 볼 수 있습니다.
이것이 Java로 직접 수행되었는지 고려하십시오. 빌드 도구는 종속성이 있음을 알 수 있습니다. 그런 다음 다른 Java 응용 프로그램을 풀다운하여 실행하여 종속성이 무엇인지 확인해야합니다. 그러나 Maven의 경우 단순히 종속성 선언을 살펴 봅니다. maven 빌드 파일은 투명합니다. 튜링 완성 언어는 본질적 으로 투명하지 않으므로 이와 같은 일부 목적에서는 열등합니다.