소스 코드 생성은 안티 패턴입니까?


118

무언가를 생성 할 수 있다면 코드가 아닌 데이터입니다.

그렇다면 소스 코드 생성에 대한이 전체 아이디어가 오해가 아닙니까? 즉, 무언가를위한 코드 생성기가 있다면, 필요한 매개 변수를 수신하고 "생성 된"코드가 수행 한 올바른 조치를 수행 할 수있는 적절한 함수로 만들 수있는 이유는 무엇입니까?

성능상의 이유로 수행되면 컴파일러의 단점처럼 들립니다.

두 언어를 연결하기 위해 인터페이스 라이브러리가 부족한 것 같습니다.

여기에 뭔가 빠졌습니까?

코드도 데이터라는 것을 알고 있습니다. 내가 이해하지 못하는 것은 왜 소스 코드를 생성 합니까? 파라미터를 받아 들여서 작동 할 수있는 함수로 만들어 보지 않겠습니까?


11
코드 생성과 관련된 용어는 메타 프로그래밍
UselesssCat

4
en.wikipedia.org/wiki/Code_as_data , 리스프, FP, 스크립트, 메타 프로그래밍, 폰 노이만 / 수정 하버드 아키텍처 등이 포함되어있어 싫증을 . tl; dr 구별 "소스 코드"대 "출력 코드", "코드"대 "데이터"등은 사물 을 단순화 하기 위한 것입니다. 절대로 독단적 이되어서는 안됩니다 .
vaxquis

9
@Utku, 코드 생성을 수행하는 더 좋은 이유는 종종 현재 언어가 표현할 수있는 것보다 더 높은 수준의 설명을 제공하고자하는 것과 관련이 있습니다 . 컴파일러가 효율적인 코드를 만들 수 있는지 여부는 실제로 관련이 없습니다. 파서 생성기 (Parser Generators)를 고려해 보라-파서 생성기 flex또는 파서가 생성하는 파서 bison는 C로 직접 작성하는 동등 물보다 예측 가능하고 정확하며 실행 속도가 빠르다. 훨씬 적은 코드로 구축되었습니다 (따라서 유지 관리 작업이 적음).
Charles Duffy 2012

1
어쩌면 많은 기능적 요소가없는 언어에서 왔을 수도 있지만 많은 언어에서 함수는 일류입니다-전달할 수 있으므로 이러한 유형의 언어에서는 코드가 데이터이므로 그렇게 처리 할 수 ​​있습니다.
Restioson

1
기능 언어 코드의 @Restioson은 데이터가 아닙니다. 일급 함수는 정확히 다음을 의미합니다. 그리고 특히 좋은 데이터는 아닙니다. 함수 내 모든 덧셈을 뺄셈으로 바꾸는 것과 같이 반드시 약간만 뮤팅 할 수는 없습니다. 코드는 Homoiconic 언어의 데이터입니다. (대부분의 호모 닉 언어에는 일류 함수가 있지만 그 반대는 아닙니다.)
Lyndon White

답변:


149

소스 코드 생성은 안티 패턴입니까?

기술적으로, 코드를 생성 하면 사람이 읽을 수있는 텍스트 인 경우에도 소스 가 아닙니다 . 소스 코드 는 인간 또는 다른 진정한 지능에 의해 생성 된 원본 코드로, 기계적으로 번역되지 않으며 (직접) 간접적으로 (진실한) 소스에서 즉시 재현 할 수 없습니다.

무언가가 생성 될 수 있다면, 그것은 코드가 아니라 데이터입니다.

어쨌든 모든 것이 데이터 라고 말할 것 입니다. 심지어 소스 코드. 특히 소스 코드! 소스 코드는 프로그래밍 작업을 수행하도록 설계된 언어의 데이터 일뿐입니다. 이 데이터는 필요에 따라 다른 형식의 데이터로 변환, 해석, 컴파일 및 생성되어야하며, 그 중 일부는 실행 가능합니다.

프로세서가 메모리 부족 명령을 실행합니다. 데이터에 사용 된 것과 동일한 메모리 프로세서가 명령을 실행하기 전에 프로그램이 데이터 로 메모리에로드됩니다 .

따라서 모든 것이 데이터 이며 심지어 코드 입니다.

[생성 된 코드는 데이터]라는 점을 감안할 때 코드 생성에 대한이 전체 아이디어가 오해가 아닙니까?

컴파일 단계에서 여러 단계를 수행하는 것이 좋습니다. 그 중 하나는 텍스트로 중간 코드 생성이 될 수 있습니다.

즉, 무언가를위한 코드 생성기가 있다면, 필요한 매개 변수를 수신하고 "생성 된"코드가 수행 한 올바른 조치를 수행 할 수있는 적절한 함수로 만들 수있는 이유는 무엇입니까?

한 가지 방법이지만 다른 방법이 있습니다.


코드 생성의 결과물은 텍스트이며 사람이 사용하도록 설계된 것입니다.

모든 텍스트 형식이 사람이 소비하는 것은 아닙니다. 특히, 생성 된 코드 (텍스트)는 일반적으로 사람이 아닌 컴파일러 소비를위한 것입니다 .


소스 코드는 원본으로 간주됩니다. 마스터 — 편집 및 개발; 소스 코드 컨트롤을 사용하여 아카이브하는 것. 사람이 읽을 수있는 텍스트 인 경우에도 생성 된 코드는 일반적으로 원래 소스 코드 에서 재생성됩니다 . 일반적으로 말하면 생성 된 코드는 빌드 중에 재생성되므로 소스 제어를받을 필요가 없습니다.


1
의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
maple_shaft

65

실용적인 추론

좋아, 나는 코드도 데이터라는 것을 안다. 내가 이해하지 못하는 것은 왜 소스 코드를 생성하는 것입니까?

이 편집에서 나는 당신이 이론적 인 컴퓨터 과학이 아니라 오히려 실질적인 수준을 요구한다고 가정합니다.

Java와 같은 정적 언어로 소스 코드를 생성하는 고전적인 이유는 이와 같은 언어는 언어 도구를 사용하여 매우 역동적 인 작업을 수행하기가 쉽지 않기 때문입니다. 예를 들어, Java의 형성 시대로 거슬러 올라가면 동적 이름 (DB의 테이블 이름과 일치)과 동적 데이터 유형 (동일한 테이블의 속성과 일치) 및 동적 데이터 유형 (일치하는)을 가진 클래스를 쉽게 작성할 수 없었습니다. 상기 속성의 유형). 특히 Java는 컴파일 타임에 유형 오류를 잡을 수 있다는 점에서 매우 중요합니다.

따라서 이러한 설정에서 프로그래머는 Java 코드 만 작성하고 많은 코드 행을 수동으로 작성할 수 있습니다. 프로그래머는 종종 테이블이 변경 될 때마다 돌아가서 코드가 일치하도록 변경해야한다는 것을 알게됩니다. 그가 잊어 버리면 나쁜 일이 일어납니다. 따라서 프로그래머는 자신을 위해 도구를 작성하는 시점에 도달하게됩니다. 따라서 더 지능적인 코드 생성이 시작됩니다.

(예, 바이트 코드를 즉석에서 생성 할 수는 있지만 Java에서 그러한 것을 프로그래밍하는 것은 임의의 프로그래머가 도메인 코드의 몇 줄을 쓰는 것 사이에서하는 것이 아닙니다.)

이것을 매우 역동적 인 언어, 예를 들어 Ruby와 비교하면 대부분의 측면에서 Java에 대한 대립을 고려할 것입니다 (어쨌든 두 가지 접근법을 평가하지 않고 말하고 있음을 유의하십시오. 단순히 다릅니다). 여기에서 런타임에 클래스, 메소드 등을 동적으로 생성하는 것은 100 % 정상 및 표준이며, 가장 중요한 것은 프로그래머가 "메타"레벨로 가지 않고도 코드에서 간단하게 수행 할 수 있다는 것입니다. 그렇습니다. Ruby on Rails와 같은 것들은 코드 생성과 함께 제공되지만, 우리는 기본적으로 새로운 프로그래머를위한 일종의 고급 "자습서 모드"로 사용하지만, 얼마 지나지 않아 코드가 너무 적기 때문에 불필요한 것으로 나타났습니다. 생태계에서 작성하는 작업을 알고있을 때 생성 된 코드를 정리하는 것보다 수동으로 작성하는 것이 더 빠릅니다.

이것들은 "실제 세계"의 두 가지 실제 예입니다. 그런 다음 코드 데이터 인 LISP와 같은 언어가 있습니다 . 반면에, Java 또는 Ruby와 같은 런타임 엔진이없는 컴파일 된 언어에는 런타임에 클래스 또는 메소드 이름을 정의하는 개념이 없습니다. 따라서 코드 생성 빌드 프로세스는 대부분의 경우 선택하는 도구입니다 (다른 C / C ++ 특정 예제는 flex, yacc 등입니다).


1
나는 이것이 더 투표 된 답변보다 낫다고 생각합니다. 특히, Java 및 데이터베이스 프로그래밍에서 언급 한 예는 실제로 코드 생성이 사용되는 이유를 다루는 데 훨씬 효과적입니다.
Panzercrisis

요즘 Java에서 DB에서 동적 테이블을 만들 수 있습니까? 아니면 ORM을 사용해서 만?
누 메논

"(혹은 현대적인 C ++ 기능을 유지하지 못했습니다 ...)"확실히 함수 포인터 덕분에 20 년 이상 C ++에서 가능 했습니까? 테스트하지는 않았지만 char 배열을 할당하고 기계 코드로 채운 다음 첫 번째 요소에 대한 포인터를 함수 포인터로 캐스팅 한 다음 실행해야한다고 확신합니다. (대상 플랫폼에 보안 조치가 있다고 가정하면이를 방지 할 수 있습니다.)
Pharap

1
"char 배열을 할당하고 기계어 코드로 채우고 첫 번째 요소에 대한 포인터를 함수 포인터로 캐스트 한 다음 실행합니까?" 정의되지 않은 동작 외에도 "즉시 바이트 코드 생성"과 동등한 C ++입니다. 그것은 "일반 프로그래머들에 의해 고려되지 않은"과 같은 범주에 속합니다
Caleth

1
@Pharap, "이것은 확실히 20 년 이상 C ++에서 가능했습니다." C ++을 마지막으로 코딩 한 지 약 20 년이 지났습니다. :) 그러나 C ++에 대한 나의 문장은 어쨌든 나쁘게 공식화되었습니다. 나는 그것을 조금 변경했는데, 지금은 내가 의미하는 바가 분명해야합니다.
AnoE

44

왜 코드를 생성합니까?

펀치 카드 (또는 메모장의 대체 코드)로 프로그래밍 하는 것은 고통 스럽기 때문입니다.

성능상의 이유로 수행되면 컴파일러의 단점처럼 들립니다.

참된. 강요받지 않으면 성능에 관심이 없습니다.

두 언어를 연결하기 위해 인터페이스 라이브러리가 부족한 것 같습니다.

흠, 무슨 말인지 모르겠다.

생성되고 유지되는 소스 코드는 항상 그리고 영원히 고통 스럽습니다. 한 가지 이유만으로 존재합니다. 누군가는 한 언어로 일하기를 원하지만 다른 사람은 다른 언어로 일하기를 고집하고 아무도 서로 상호 작용하는 방법을 알아낼 수 없으므로 어느 누구도 자신이 좋아하는 언어를 부과 언어로 바꾸어 어떻게 할 수 있는지 알아낼 수 있습니다. 그들은 원한다.

내가 그것을 유지해야 할 때까지는 괜찮습니다. 어느 시점에서 당신은 모두 죽을 수 있습니다.

안티 패턴입니까? 안돼. 우리가 이전 언어의 단점에 작별 인사를하지 않고 이전 언어의 코드를 생성하는 것이 얼마나 많은 새로운 언어가 시작되는지에 따라 많은 언어가 존재하지 않을 것입니다.

그것은 내가 참을 수없는 반 변환 된 Frankenstein 괴물 패치 워크에 남겨진 코드베이스입니다. 생성 된 코드는 만질 수없는 코드입니다. 나는 만질 수없는 코드를 보는 것이 싫어. 그러나 사람들은 계속 확인하고 있습니다. 왜? 실행 파일을 체크인하고있을 수도 있습니다.

이제 나는 뛰고있다. 내 요점은 우리 모두 "코드 생성"입니다. 생성 된 코드를 소스 코드처럼 취급하여 나를 미치게 만들 때입니다. 소스 코드가 소스 코드가 아닌 것처럼 보이게하십시오.


41
생성하면 소스 코드가 아닙니다. 중간 코드입니다. 나는 지금 울 것이다.
candied_orange

65
ARG !!! 어떤 모습인지는 중요하지 않습니다 !!! 텍스트, 이진, DNA, 그것이 소스가 아니라면 변경을 할 때 만져야 할 것이 아닙니다. 내 컴파일 프로세스에 42 개의 중간 언어가 포함되어 있다면 비즈니스가 아닙니다. 만지지 마십시오. 체크인을 중지하십시오. 소스에서 변경하십시오.
candied_orange

24
XML은 텍스트이며 사람이 소비하는 것이 아닙니다. :-)
Nick Keighley

38
@utku : "사람이 소비하도록 의도 된 것이 아니라면 텍스트가되어서는 안됩니다": 나는 완전히 동의하지 않습니다. HTTP 프로토콜, MIME 인코딩, PEM 파일 등 어디에서나 base64를 사용하는 거의 모든 것입니다. 사람이 보지 않아도 데이터를 7 비트 안전 스트림으로 인코딩하는 데는 여러 가지 이유가 있습니다. 일반적 으로 인간이 상호 작용해서는 안되는 훨씬 더 큰 공간은 말할 것도없고 로그 파일, /etc/유닉스 파일 등
Daniel Pryden

12
"펀치 카드 프로그래밍"이 의미하는 바를 의미하지 않는다고 생각합니다. 나는 거기에 있었고, 그렇게했습니다. 예, 그것은 고통 이었습니다 . "생성 된 코드"에 연결되어 있지 않습니다. 천공 카드 데크는 디스크의 파일, 테이프의 파일 또는 SD 카드의 파일과 같은 다른 종류의 파일 일뿐입니다. 과거에는 카드 한 벌에 데이터를 쓰고 데이터를 읽었습니다. 따라서 우리가 코드를 생성하는 이유가 펀치 카드를 사용한 프로그래밍이 어려워서 모든 종류의 데이터 스토리지를 사용한 프로그래밍이 어려울 수 있음을 의미합니다 .
솔로몬 느린

41

소스 코드를 생성하는 이유

내 경력에서 작업해야했던 코드 생성기의 가장 빈번한 사용 사례는 생성기였습니다.

  • 어떤 종류의 데이터 모델이나 데이터베이스 스키마에 대한 높은 수준의 메타 설명을 입력으로 사용했습니다 (관계형 스키마 또는 XML 스키마)

  • 출력으로서 데이터 액세스 클래스를위한 보일러 플레이트 CRUD 코드 및 해당 SQL 또는 문서와 같은 추가 항목을 생성했습니다.

여기서 짧은 이점은 짧은 입력 사양의 한 줄에서 5-10 줄의 디버그 가능하고 형식이 안전하며 버그가없는 (코드 생성기 출력이 성숙하다고 가정) 코드를 직접 구현하고 유지 관리해야한다는 점입니다. 이것이 유지 관리 및 진화 노력을 얼마나 줄일 수 있는지 상상할 수 있습니다.

당신의 첫 질문에 답하겠습니다

소스 코드 생성은 안티 패턴입니까

아니요, 소스 코드 생성 자체는 아니지만 실제로 몇 가지 함정이 있습니다. Pragmatic Programmer에 명시된 바와 같이 , 이해하기 어려운 코드를 생성 할 때 코드 생성기를 사용하지 않아야합니다 . 그렇지 않으면이 코드를 사용하거나 디버깅하려는 노력이 증가하면 코드를 수동으로 작성하지 않아도 절약되는 노력보다 쉽게 ​​수행 할 수 있습니다.

또한 재생성으로 인해 수동 변경 사항을 덮어 쓰지 않는 방식으로 생성 된 코드 부분을 수동으로 작성된 코드와 물리적으로 분리하는 것이 좋습니다. 그러나 나는 또한 언어 Y로 유지 보수하려는 의도로 구식 X로 작성된 일부 코드를 더 현대적인 언어 Y로 마이그레이션하는 상황을 두 번 이상 처리했습니다. 일회성 코드 생성의 경우.


이 답변에 동의합니다. Torque for java와 같은 것을 사용하여 SQL 데이터베이스와 일치하는 필드로 Java 소스 파일을 자동 생성 할 수 있습니다. 이렇게하면 crud 작업이 훨씬 쉬워집니다. 주요 이점은 데이터베이스에 존재하는 필드 만 참조 할 수있는 것을 포함하여 형식 안전성입니다 (자동 완성 감사).
MTilsted

예, 정적으로 유형이 지정된 언어의 경우 중요한 부분입니다. 직접 작성한 코드가 실제로 생성 된 코드에 맞는지 확인할 수 있습니다 .
Paŭlo Ebermann

"오래된 언어로 작성된 일부 코드를 마이그레이션하십시오"-그럼에도 불구하고 일회성 코드 생성은 큰 고통이 될 수 있습니다. 예를 들어, 일부 수동 변경 후 생성기에서 버그를 감지하고 수정 후 생성을 다시 실행해야합니다. 운 좋게도 git 등은 일반적으로 통증을 완화시킬 수 있습니다.
maaartinus

13

왜 소스 코드를 생성합니까?

생성 된 (빌드 타임에, 체크인되지 않은) 코드에 대한 두 가지 유스 케이스가 발생했습니다.

  1. 이러한 것들을 지정하기 위해 만들어진 언어에서 getter / setter, toString, equals 및 hashCode와 같은 상용구 코드를 자동으로 생성합니다 (예 : Java 용 lombok 프로젝트)
  2. 일부 인터페이스 사양 (REST, SOAP 등)에서 DTO 유형 클래스를 자동으로 생성 한 후 기본 코드에서 사용합니다. 이것은 언어 브릿지 문제와 비슷하지만 생성 된 클래스없이 동일한 것을 구현하려고 시도하는 것보다 유형 처리가 더 깨끗하고 간단합니다.

15
표현이 많은 언어에서 반복성이 높은 코드. 예를 들어 필자는 필연적으로 유사하지만 동일하지 않은 많은 데이터 구조에서 동일한 작업을 수행 한 코드를 작성해야했습니다. 그것은 아마도 (헤이 아닌 C ++ 템플릿과 같이 함께 할 수 있었던 코드 생성?). 그러나 C를 사용하고있었습니다. 코드 생성으로 거의 동일한 코드를 많이 작성했습니다.
Nick Keighley

1
@NickKeighley 아마도 툴체인이 더 적합한 다른 언어를 사용하도록 허용하지 않았습니까?
Wilson

7
일반적으로 구현 언어를 고르지 않아도됩니다. 프로젝트는 C에 있었고 옵션은 아니 었습니다.
Nick Keighley

1
@ 표현력이 뛰어난 언어는 종종 코드 생성 (예 : 리스프 매크로, 루비 온 레일)을 사용하므로 그 동안 텍스트로 저장하지 않아도됩니다.
피트 Kirkham

4
예, 코드 생성은 본질적으로 메타 프로그래밍입니다. Ruby와 같은 언어를 사용하면 언어 자체에서 메타 프로그래밍을 수행 할 수 있지만 C는 그렇지 않으므로 대신 코드 생성을 사용해야합니다.
Sean Burton

13

Sussmann은 그의 고전적인 "컴퓨터 프로그램의 구조와 해석"에서 주로 코드-데이터 이중성에 대해 그런 것들에 대해 매우 흥미로웠다.

나를 위해 adhoc 코드 생성의 주요 용도는 사용 가능한 컴파일러를 사용하여 일부 도메인 특정 언어를 프로그램에 연결할 수있는 언어로 변환하는 것입니다. BNF를 생각하고, ASN1을 생각하고 (사실, 그렇지 않습니다, 추악합니다), 데이터 사전 스프레드 시트를 생각하십시오.

사소한 도메인 특정 언어는 시간을 크게 절약 할 수 있으며 표준 언어 도구로 컴파일 할 수있는 것을 출력하는 것은 그러한 것을 만들 때 갈 수있는 방법입니다. 자동 생성 또는 쓰기 또는 BNF?

텍스트를 출력 한 다음 일부 시스템 컴파일러에 공급하면 모든 컴파일러 최적화 및 시스템 특정 구성을 생각하지 않아도됩니다.

컴파일러 입력 언어를 다른 중간 표현으로 효과적으로 사용하고 있습니다. 문제는 무엇입니까? 텍스트 파일은 본질적으로 소스 코드가 아니며 컴파일러의 IR 일 수 있으며 C 또는 C ++ 또는 Java처럼 보이면 누가 신경 쓰나요?

이제 당신이 장난감 언어 파서의 OUTPUT을 편집 할 수 있다고 생각 하지 않는다면 , 다음에 누군가가 입력 언어 파일을 편집하고 다시 작성할 때 분명히 실망 할 것입니다. 답은 자동 생성 IR을 저장소에 커밋하지 않는 것입니다. 당신의 툴체인에 의해 생성됩니다 (그리고 당신의 개발자 그룹에 그런 사람들을 두지 마십시오, 그들은 일반적으로 마케팅에서 더 행복합니다).

때로는 사양의 일부를 자동으로 코드로 변환 할 수있는 형태로 얻을 수 있고 일반적으로 훨씬 적은 형태로 표현할 수 있다는 사실을 표현하기 때문에 언어 표현력의 실패가 아닙니다. 버그 및 유지 관리가 훨씬 쉬워집니다. 테스트 및 구성 담당자에게 스프레드 시트를 제공 할 수 있고 데이터를 가져 와서 ECU에서 플래시를위한 완전한 16 진수 파일을 추출하는 도구를 실행할 수 있다면 누군가 수동으로 번역하는 것보다 시간을 절약 할 수 있습니다 오늘의 언어로 된 상수 세트에 대한 최신 설정

Simulink에서 모델을 빌드 한 다음 RTW로 C를 생성 한 다음 어떤 툴이든지 적절한 대상으로 컴파일하기 위해 컴파일하는 것과 마찬가지로 중간 C는 읽을 수 없습니다. 높은 수준의 Matlab RTW는 C의 하위 집합 만 알아야하며 C 컴파일러는 플랫폼 세부 정보를 처리합니다. RTW 스크립트에 버그가있는 경우에만 인간이 생성 된 C를 통해 그 로브해야 할 때가 있으며, 이러한 종류의 작업은 명목상 사람이 읽을 수있는 IR로 디버깅하고 이진 구문 분석 트리만으로 훨씬 쉽게 디버깅 할 수 있습니다.

물론 바이트 코드 또는 실행 코드를 출력하기 위해 그러한 것들을 작성할 수는 있지만 왜 그렇게 할 것입니까? 우리는 IR을 그런 것들로 변환하는 도구를 얻었습니다.


이것은 좋지만, 어떤 IR을 사용할지 결정할 때 트레이드 오프가 있다고 덧붙입니다 .C를 IR로 사용하면 x86 어셈블리 언어와 비교할 때 어떤 것이 더 쉽고 어려워집니다. 예를 들어 Java 언어 코드와 Java 바이트 코드 중에서 선택할 때 한 가지 또는 다른 언어로만 존재하는 작업이 더 많기 때문에 선택이 훨씬 중요합니다.
Daniel Pryden

2
그러나 X86 어셈블리 언어는 ARM 또는 PPC 코어를 대상으로 할 때 IR이 열악합니다! 모든 것은 엔지니어링의 트레이드 오프이므로 엔지니어링이라고합니다. Java 바이트 코드의 가능성이 Java 언어의 가능성에 대한 엄밀한 상위 세트이고, 이는 일반적으로 툴체인에 관계없이 금속에 더 가까워지고 IR을 주입하는 곳에서 가능할 것으로 기대합니다.
Dan Mills

오, 나는 전적으로 동의합니다 : 내 의견은 왜 당신이 바이트 코드 또는 일부 하위 레벨을 출력했는지 질문하는 마지막 단락에 대한 응답으로 때로는 하위 레벨이 필요합니다. (자바에서는 자바 자체로는 할 수없는 바이트 코드로 할 수있는 유용한 것들이 많이있다.)
Daniel Pryden

2
나는 동의하지 않지만, 일반성뿐만 아니라 금속에 더 가깝게 IR을 사용하는 데 비용이 들지만 실제로는 실제로 성가신 낮은 수준의 최적화에 더 많은 책임을지게됩니다. 요즘 우리가 일반적으로 알고리즘 선택을 최적화하는 대신 알고리즘 선택을 최적화한다는 관점에서 컴파일러가 얼마나 멀리 왔는지에 대한 반영이며, 때로는 이러한 것들에 대해 금속에 가까워 야하지만 컴파일러를 버리기 전에 두 번 생각해야합니다. 너무 낮은 레벨의 IR을 사용하여 최적화하는 기능.
Dan Mills

1
"보통 마케팅에서 일하는 것이 더 행복합니다" Catty, 그러나 재미있었습니다.
dmckee

13

실용 답변 : 코드 생성이 필요하고 유용합니까? 독점적 인 코드베이스에 진정으로 매우 유용하고 필요한 것을 제공합니까, 아니면 차선책의 결과에 대한 지적 부담을 높이는 다른 방법을 만드는 것처럼 보입니까?

좋아, 나는 코드도 데이터라는 것을 안다. 내가 이해하지 못하는 것은 왜 코드를 생성하는 것입니까? 파라미터를 받아 들여서 작동 할 수있는 함수로 만들어 보지 않겠습니까?

이 질문을해야하는데 명확한 대답이 없다면 아마도 코드 생성이 불필요 할뿐 아니라 코드베이스에 이국주의와 많은 지적 오버 헤드를주는 것입니다.

한편 OpenShadingLanguage와 같은 것을 사용하는 경우 : https://github.com/imageworks/OpenShadingLanguage

... 그러한 질문은 인상적인 결과에 의해 즉시 답변되기 때문에 제기 될 필요가 없습니다.

OSL은 LLVM 컴파일러 프레임 워크를 사용하여 셰이더 네트워크를 즉시 (시간 또는 "JIT") 기계 코드로 변환하고, 그 과정에서 셰이더 매개 변수 및 기타 런타임 값에 대한 전체 지식을 바탕으로 셰이더와 네트워크를 크게 최적화합니다. 쉐이더가 소스 코드에서 컴파일 될 때 알려졌습니다. 결과적으로 OSL 쉐이딩 네트워크가 C에서 수작업으로 제작 한 동등한 쉐이더보다 25 % 더 빠르게 실행되는 것을 볼 수 있습니다! (이것은 이전 셰이더가 렌더러에서 작동 한 방식입니다.)

이 경우 코드 생성기의 존재 여부를 의심 할 필요가 없습니다. 이 유형의 VFX 도메인에서 작업하는 경우 일반적으로 "종료하고 내 돈을 가져라!" 또는 "와우, 우리도 이와 같은 것을 만들어야합니다."


셰이더 네트워크를 머신 코드로 변환합니다 . 이것은 코드 생성기보다는 컴파일러처럼 들립니다.
Utku

2
기본적으로 사용자가 연결하는 노드 네트워크를 사용하고 LLVM에 의해 JIT로 컴파일되는 중개 코드를 생성합니다. 컴파일러와 코드 생성기의 차이점은 일종의 퍼지입니다. C ++ 또는 C 전 처리기의 템플릿과 같은 언어로 된 코드 생성 기능에 대해 더 많이 생각하고 있었습니까?

소스 코드를 출력하는 생성기를 생각하고있었습니다.
Utku

출력이 여전히 인간 소비를위한 곳이라고 생각합니다. OpenSL은 또한 중간 소스 코드를 생성하지만 LLVM 소비를 위해 어셈블리에 가까운 저수준 코드입니다. 일반적으로 유지 보수하려는 코드는 아닙니다 (프로그래머가 코드를 생성하는 데 사용 된 노드를 유지 관리하는 대신). 대부분의 경우, 이러한 유형의 코드 생성기는 특히 빌드 프로세스의 일부로 코드를 지속적으로 재생성 해야하는 경우 가치를 정당화하기에 충분할 정도로 유용하지 않을 가능성이 높습니다. 때때로 그들은 여전히 ​​단점을 해결하기 위해 진정한 장소를 가지고 있습니다 ...

... 특정 도메인에 사용될 때 사용 가능한 언어. QT는 메타 객체 컴파일러 (MOC)와 관련하여 논란이되는 것들 중 하나를 가지고 있습니다. MOC는 일반적으로 C ++에서 속성, 반사 및 신호 및 슬롯 등을 제공하는 데 필요한 상용구를 줄이지 만 그 존재를 명확하게 정당화 할 정도로는 아닙니다. 나는 종종 MOC의 코드 생성 부담없이 QT가 더 나을 수 있다고 생각한다.

8

아닙니다. 중간 코드를 생성하는 것은 안티 패턴이 아닙니다. 질문의 다른 부분 인 "왜 그럴까요?"에 대한 대답은 매우 광범위하고 (별도의) 질문이지만 어쨌든 몇 가지 이유를 제시 할 것입니다.

사람이 읽을 수있는 중간 코드가없는 역사적 결과

가장 유명한 언어이므로 C와 C ++를 예로 들어 봅시다.

C 코드 출력을 컴파일하는 논리적 행렬은 기계 코드가 아니라 사람이 읽을 수있는 어셈블리 코드입니다. 마찬가지로 이전 C ++ 컴파일러는 C ++ 코드를 C 코드로 물리적으로 컴파일하는 데 사용되었습니다. 해당 이벤트 체인에서 사람이 읽을 수있는 코드 1에서 사람이 읽을 수있는 코드 2에서 사람이 읽을 수있는 코드 3을 기계 코드로 컴파일 할 수 있습니다. "왜?" 왜 안돼?

사람이 읽을 수있는 중간 코드가 생성되지 않은 경우 C 또는 C ++ 이 전혀 없을 수도 있습니다 . 그것은 확실히 가능성이다. 사람들은 자신의 목표에 대한 저항이 가장 적은 길을 가고 C 개발 정체로 인해 다른 언어가 먼저 증기를 앓는 경우 C는 아직 어릴 때 사망했을 수 있습니다. 물론 "하지만 다른 언어를 사용하고 있으면 더 나을 것"이라고 주장 할 수 있습니다. 어쩌면 더 나쁠 수도 있습니다. 아니면 우리 모두 여전히 집필을하고있을 것입니다.

사람이 읽을 수있는 중간 코드를 사용해야하는 이유는 무엇입니까?

  1. 다음 번 빌드 단계 전에 코드를 수정할 수 있도록 중간 코드가 필요한 경우가 있습니다. 나는이 점이 가장 약하다는 것을 인정할 것이다.
  2. 때로는 원본 작업이 사람이 읽을 수있는 언어가 아닌 GUI 모델링 도구로 수행 되었기 때문입니다.
  3. 때로는 매우 반복적 인 일을해야 할 필요가 있으며, 언어 틈새 적 일이나 복잡한 일이기 때문에 프로그래밍 언어의 복잡성이나 문법을 수용하기 위해 비즈니스를 수행 할 수없는 복잡한 일이기 때문에 당신.
  4. 때로는 매우 반복적 인 일을해야 할 때가 있으며, 일반적인 방식으로 원하는 것을 언어로 구할 수있는 방법이 없습니다 . 언어의 문법으로 표현되거나 상충 될 수 없습니다.
  5. 컴퓨터의 목표 중 하나는 사람의 노력을 줄이고, 때로는 다시 만질 가능성이 낮은 코드 (유지 가능성이 낮음)가 10 분의 1 초 안에 더 긴 코드를 생성하기 위해 메타 코드를 작성할 수 있습니다. 내가 2 주가 아닌 하루 만에 할 수 있고 그것이 유지 될 가능성이 없다면, 더 잘 생성 할 것입니다-그리고 실제로 그것을 유지해야 필요가 있기 때문에 지금 5 년 전 누군가가 성 가실 가능성이 있습니다. 어색한 코드를 유지하려는 1 주일 (그 시점에서 우리는 여전히 1 주일 앞서 있음)에 의해 2 주 동안 그것을 완전히 작성하거나 성가 시게 할 수 있으며, 그 유지 보수가 전혀 필요 하지 않은 경우 .
  6. 내가 간과하는 더 많은 이유가 있다고 확신합니다.

다른 문서의 데이터 또는 정보를 기반으로 코드를 생성해야하는 프로젝트를 수행했습니다. 예를 들어, 한 프로젝트에는 모든 네트워크 메시지와 상수 데이터가 스프레드 시트와 스프레드 시트를 통해 이동 하고 해당 메시지를 처리 ​​할 수 있는 많은 C ++ 및 Java 코드를 생성하는 도구가 정의되어 있습니다.

나는 그것이 그 프로젝트를 시작하는 가장 좋은 방법이라고 말하지는 않지만 (나는 시작의 일부가 아니었다), 그것이 우리가 가진 것이었고, 수백 (아마도 수천, 확실하지는 않음)의 구조와 객체와 상수 생성되고 있었다; 이 시점에서 랩소디와 같은 방식으로 다시 실행하려고 시도하기에는 너무 늦었습니다. 그러나 Rhapsody와 같은 방식으로 다시 작성 되었지만 Rhapsody에서 생성 된 코드는 여전히 있습니다 .

또한 스프레드 시트에 모든 데이터를 저장하는 것이 한 가지 방법으로 좋았습니다. 데이터가 소스 코드 파일에 모두있을 경우에는 가질 수 없었던 방식으로 데이터를 표현할 수있었습니다.

실시 예 2

컴파일러 구성 작업을 할 때 Antlr 도구를 사용하여 어휘 분석 및 구문 분석을 수행했습니다. 언어 문법을 지정한 다음 도구를 사용하여 C ++ 또는 Java로 많은 코드를 추출한 다음 생성 된 코드를 내 코드와 함께 사용하여 빌드에 포함했습니다.

다른 방법으로해야합니까? 아마도 다른 방법을 생각해 낼 수도 있습니다. 아마도 다른 방법이있을 것입니다. 그러나 그 작업을 위해 다른 방법은 내가 가진 생성 된 lex / parse 코드보다 나을 것입니다.


필자는 두 시스템이 호환되지 않지만 매우 난해한 스크립팅 언어로 안정적인 API를 가질 때 중간 코드를 일종의 파일 형식 및 디버깅 추적으로 사용했습니다. Wasnt는 수동으로 읽도록 의도되었지만 xml과 동일한 방식으로 가능했습니다. 그러나 이것은 누군가가 지적한 것처럼 모든 웹 페이지가 이런 식으로 작동 한 후에 생각하는 것보다 흔합니다.
joojaa

7

누락 된 것은 재사용 입니다.

우리는 소스 코드 텍스트를 이진 (컴파일러라고 함)으로 바꾸는 놀라운 도구를 가지고 있습니다. 입력은 잘 정의되어 있으며 (보통!) 최적화 작업을 개선하기 위해 많은 노력을 기울였습니다. 실제로 컴파일러 를 사용 하여 일부 작업을 수행하려는 경우 기존 컴파일러를 사용하고 직접 작성하지는 않습니다.

많은 사람들이 새로운 프로그래밍 언어를 개발하고 자체 컴파일러를 작성합니다. 예외없이 거의 모든 사람들이 언어를 제공하는 기능이 필요 하기 때문에 도전을 즐기기 때문에이 작업을 수행하고 있습니다 . 그들이하는 모든 일은 다른 언어로 이루어질 수 있습니다. 그들은 그 기능을 좋아하기 때문에 단순히 새로운 언어를 만들고 있습니다. 그래도 얻을 수없는 것은 잘 조정되고 빠르고 효율적이며 최적화 된 컴파일러입니다. 텍스트를 바이너리로 바꿀 수있는 것을 얻을 수 는 있지만 기존의 모든 컴파일러만큼 좋지는 않습니다 .

텍스트는 인간이 읽고 쓰는 것만이 아닙니다. 컴퓨터는 집에서도 완벽하게 텍스트를 사용합니다. 실제로 XML과 같은 형식 (및 기타 관련 형식)은 일반 텍스트를 사용 하므로 성공 합니다. 이진 파일 형식은 종종 모호하고 문서화가 잘되지 않아서 독자가 자신의 작동 방식을 쉽게 찾을 수 없습니다. XML은 상대적으로 자체 문서화되므로 사람들이 XML 형식 파일을 사용하는 코드를보다 쉽게 ​​작성할 수 있습니다. 그리고 모든 프로그래밍 언어는 텍스트 파일을 읽고 쓰도록 설정되어 있습니다.

따라서 인생을 편하게하기 위해 새로운 시설을 추가하고 싶다고 가정하십시오. 아마도 GUI 레이아웃 도구 일 것입니다. 아마도 Qt가 제공 하는 신호 및 슬롯 인터페이스 일 것입니다 . 아마도 그것은하는 방법 TI의 코드 컴포저 스튜디오 (Code Composer Studio)는 당신이 작업중인 장치를 구성하고 빌드에 적합한 라이브러리를 풀 수는. 아마도 데이터 딕셔너리와 자동 생성 typedef 및 전역 변수 정의를 사용하고 있습니다 (예, 이것은 임베디드 소프트웨어에서 여전히 많습니다). 그것이 무엇이든간에, 기존 컴파일러를 활용하는 가장 효율적인 방법은 무엇이든지 구성을 취하고 선택한 언어로 자동으로 코드를 생성하는 도구를 만드는 것입니다.

무슨 일이 일어나고 있는지 알고 소스 코드를 읽을 수 있기 때문에 개발하기 쉽고 테스트하기 쉽습니다. GCC와 경쟁하기 위해 컴파일러를 작성하는 데 수년을 소비 할 필요가 없습니다. 완전히 새로운 언어를 배우거나 다른 사람들에게 요구할 필요는 없습니다. 이 작은 영역을 자동화하기 만하면되고 나머지는 모두 동일하게 유지됩니다. 작업이 완료되었습니다.


여전히 XML의 텍스트 기반의 장점은 필요한 경우 사람이 읽고 쓸 수 있다는 것입니다 (일반적으로 일단 작동하면 신경 쓰지 않지만 개발 중에는 확실하게 수행 할 수 있습니다). 성능 및 공간 효율성 측면에서 이진 형식은 일반적으로 훨씬 우수합니다 (병목 현상이 다른 곳에 있기 때문에 중요하지 않음).
leftaroundabout

@leftaroundabout 성능과 공간 효율성이 필요하다면 반드시 확인하십시오. 요즘 많은 응용 프로그램이 XML 기반 형식으로 전환 한 이유는 성능과 공간 효율성이 이전의 최고 기준이 아니었고, 이진 파일 형식이 얼마나 빈약하게 유지되는지에 대한 기록이 있기 때문입니다. (고전적인 예를 들어 오래된 MS Word 문서!) 요점은 여전히 ​​그렇습니다. 텍스트는 컴퓨터가 사람처럼 읽을 수있는 것과 같습니다.
Graham

물론 잘못 설계된 이진 형식은 실제로 텍스트 형식을 통해 올바르게 생각하는 것보다 성능이 떨어질 수 있으며, 적절한 이진 형식조차도 일부 범용 압축 알고리즘으로 압축 된 XML보다 훨씬 컴팩트하지 않은 경우가 많습니다. IMO는 세계에서 가장 좋은 대수 데이터 형식을 통해 사람이 읽을 수있는 사양을 사용하고 이러한 형식의 AST에서 효율적인 이진 표현을 자동으로 생성하는 것입니다. 플랫 라이브러리를 참조하십시오 .
leftaroundabout

7

소스 코드가 무엇이고 무엇이 아닌지에 초점을 맞춘 좀 더 실용적인 답변. 소스 코드 생성은이 모든 경우에 빌드 프로세스의 일부이므로 생성 된 파일이 소스 제어에 들어 가지 않아야합니다.

상호 운용성 / 단순성

Google의 프로토콜 버퍼를 예로 들어 보겠습니다. 예를 들어 단일 고급 프로토콜 설명을 작성하여 여러 언어로 구현을 생성하는 데 사용할 수 있습니다. 종종 시스템의 다른 부분이 다른 언어로 작성됩니다.

구현 / 기술적 인 이유

TypeScript 사용-브라우저는이를 해석 할 수 없으므로 빌드 프로세스는 코드 변환 프로그램 ( transpiler )을 사용하여 JavaScript를 생성합니다. 실제로 많은 새롭고 난해한 컴파일 된 언어는 적절한 컴파일러를 얻기 전에 C로 변환하는 것으로 시작합니다.

사용의 용이성

C로 작성되고 단일 바이너리 (RTOS 또는 OS 없음) 만 사용하는 임베디드 프로젝트 (IoT 생각)의 경우 직접 링크하는 대신 일반 소스 코드처럼 컴파일 할 데이터로 C 배열을 생성하는 것이 매우 쉽습니다. 자원으로.

편집하다

프로토 타입 확장 : 코드 생성을 통해 생성 된 객체를 모든 언어의 일류 클래스로 만들 수 있습니다. 컴파일 된 언어에서 일반 파서는 키 값 구조를 반환해야합니다. 많은 상용구 코드가 필요하다는 것을 의미하므로 컴파일 타임 검사 (특히 키 및 값 유형)에서 누락되고 성능이 저하됩니다. 코드 완성이 없습니다. void*C의 모든 사람들 이나 std::variantC ++의 거대한 사람들 (C ++ 17이있는 경우)을 상상해보십시오 . 일부 언어에는 그러한 기능이 전혀 없을 수 있습니다.


첫 번째 이유로, OP의 아이디어는 각 언어 (프로토콜 버퍼 설명을 취한 다음 온-더-와이어 형식을 구문 분석 / 소비)로 일반적인 구현을하는 것이라고 생각합니다. 왜 이것이 코드 생성보다 더 나쁠까요?
Paŭlo Ebermann

@ PaŭloEbermann은 일반적인 퍼포먼스 인수와는 달리 이러한 일반적인 해석은 이러한 메시지를 컴파일 된 (및 해석 될 수있는) 언어의 일류 객체로 사용하는 것을 불가능하게합니다. . 물론 kv를 클래스로 가져올 수 있지만 많은 상용구 코드로 바뀔 수 있습니다. 그리고 코드 완성도 있습니다. 그리고 컴파일 시간 확인-컴파일러는 리터럴에 오타가 없는지 확인하지 않습니다.
Jan Dorniak

동의합니다 ...이 답변에 추가 할 수 있습니까?
Paŭlo Ebermann

@ PaŭloEbermann 완료
Jan Dorniak

6

소스 코드 생성은 안티 패턴입니까?

표현력이 부족한 프로그래밍 언어에 대한 해결 방법입니다. 적절한 내장 메타 프로그래밍이 포함 된 언어로 코드를 생성 할 필요가 없습니다.


3
또한보다 표현적인 언어를 위해 완전한 객체에서 네이티브로의 객체 코드 컴파일러를 작성해야하는 해결 방법입니다. C를 생성하고, 최적화기를 갖춘 컴파일러가 나머지를 처리하게하십시오.
Blrfl

항상 그런 것은 아닙니다. 때때로 버스와 같은 신호에 대한 일부 정의를 포함하는 하나 이상의 데이터베이스가 있습니다. 그런 다음이 정보를 모아서 일관성 검사를 수행 한 다음 버스에서 오는 신호와 코드에있을 것으로 예상되는 변수간에 인터페이스하는 코드를 작성하려고합니다. 메타 프로그래밍 기능이있는 언어를 보여 주면 클라이언트가 제공 한 일부 Excel 시트, 데이터베이스 및 기타 데이터 소스를 쉽게 사용할 수 있으며 필요한 데이터를 확인하고 필요한 데이터 유효성 및 일관성을 확인한 다음 꼭 보여줘
CodeMonkey

@CodeMonkey : Ruby on Rails의 ActiveRecord 구현과 같은 것이 떠 오릅니다. 코드에서 데이터베이스 테이블 스키마를 복제 할 필요가 없습니다. 클래스를 테이블에 매핑하고 열 이름을 속성으로 사용하여 비즈니스 로직을 작성하십시오. Ruby 메타 프로그래밍으로는 관리 할 수없는 코드 생성기에서 생성 할 수있는 패턴을 상상할 수 없습니다. C ++ 템플릿도 약간 강력하지만 매우 강력합니다. 리스프 매크로는 또 다른 강력한 언어 메타 프로그래밍 시스템입니다.
케빈 클라인

@kevincline 의미하는 것은 데이터베이스 자체가 아닌 데이터베이스의 일부 데이터를 기반으로 한 코드였습니다 (데이터베이스에서 생성 가능). 즉, Excel 표 A에서 어떤 신호를 수신하는지에 대한 정보가 있습니다.이 신호 등에 대한 정보가있는 데이터베이스 B가 있습니다. 이제이 신호에 액세스하는 클래스를 만들고 싶습니다. 코드를 실행하는 컴퓨터의 데이터베이스 또는 Excel 시트에 연결되어 있지 않습니다. 간단한 코드 생성기 대신 컴파일 타임에이 코드를 생성하기 위해 정말 복잡한 C ++ 템플릿을 사용합니다. codegen을 선택하겠습니다.
CodeMonkey

6

소스 코드 생성이 항상 반 패턴은 아닙니다. 예를 들어, 현재 지정된 사양에 따라 두 가지 언어 (Javascript 및 Java)로 코드를 생성하는 프레임 워크를 작성 중입니다. 프레임 워크는 생성 된 Javascript를 사용하여 사용자의 브라우저 조치를 기록하고 Selenium의 Java 코드를 사용하여 프레임 워크가 재생 모드에있을 때 실제로 조치를 실행합니다. 코드 생성을 사용하지 않으면 수동으로 두 가지가 항상 동기화되어 있는지 확인해야하는데, 이는 번거롭고 논리적 복제이기도합니다.

그러나 제네릭과 같은 기능을 대체하기 위해 소스 코드 생성을 사용하는 경우 안티 패턴입니다.


물론 코드를 ECMAScript로 한 번 작성하여 JVM의 Nashorn 또는 Rhino에서 실행할 수 있습니다. 또는 ECMAScript에서 JVM을 작성하거나 Emscripten을 사용하여 Avian을 WebAssembly로 컴파일하려고 시도하고 브라우저에서 Java 코드를 실행할 수 있습니다. 나는 그것들이 훌륭한 아이디어라고 말하지는 않지만 (아마도 그들은 끔찍한 아이디어 일 것입니다 :-D), 가능하지 않으면 적어도 가능합니다.
Jörg W Mittag

이론적으로는 가능하지만 일반적인 해결책은 아닙니다. 다른 언어 중 하나를 다른 언어로 실행할 수 없으면 어떻게됩니까? 예를 들어, pne 추가 사항 : 방금 코드 생성을 사용하여 간단한 Netlogo 모델을 만들고 시스템의 대화식 문서를 가지고 있으며 항상 레코더 및 플레이어와 동기화됩니다. 일반적으로 요구 사항을 만든 다음 코드를 생성하면 의미 적으로 함께 실행되는 항목이 동기화됩니다.
Hristo Vrigazov

6

여기에 뭔가 빠졌습니까?

중개자 코드가 성공의 원인으로 판명 된 좋은 예일까요? 나는 당신에게 HTML을 제공 할 수 있습니다.

HTML이 단순하고 정적 인 것이 중요하다고 생각합니다. 브라우저를 쉽게 만들 수 있었고 모바일 브라우저를 조기에 시작할 수있었습니다. 추가 실험 (Java 애플릿, Flash)에서 알 수 있듯이 더 복잡하고 강력한 언어로 인해 더 많은 문제가 발생합니다. . 사용자는 실제로 Java 애플릿에 의해 위험에 처해 있으며 그러한 웹 사이트를 방문하는 것은 DC ++를 통해 다운로드 한 게임 크랙을 시도하는 것만 큼 안전합니다. 반면 일반 HTML은 장치 보안에 대한 합리적인 신념을 가진 사이트를 체크 아웃 할 수있을 정도로 해가 없습니다.

그러나 HTML이 컴퓨터에서 생성되지 않았다면 HTML은 현재 어디에도 없습니다. 누군가가 데이터베이스에서 HTML 파일로 수동으로 다시 작성할 때까지 내 대답은이 페이지에 표시되지 않습니다. 운 좋게도 거의 모든 프로그래밍 언어에서 사용 가능한 HTML을 만들 수 있습니다. :)

즉, 무언가를위한 코드 생성기가 있다면, 필요한 매개 변수를 수신하고 "생성 된"코드가 수행 한 올바른 조치를 수행 할 수있는 적절한 함수로 만들 수있는 이유는 무엇입니까?

HTML을 생성 된 중간 코드로 사용하는 것보다 사용자에게 질문과 모든 답변과 의견을 표시하는 더 좋은 방법을 상상할 수 있습니까?


예, 더 나은 방법을 상상할 수 있습니다. HTML은 Tim Berners-Lee가 텍스트 전용 웹 브라우저를 빠르게 만들 수 있도록 결정한 유산입니다. 당시에는 완벽하게 문제가 없었지만, 후시의 이점으로도 그렇게하지 않았습니다. CSS는 모든 다양한 프리젠 테이션 요소 유형 (DIV, SPAN, TABLE, UL 등)을 불필요하게 만들었습니다.
케빈 클라인

@ kevincline 나는 HTML에 결함이 없다고 말하지 않고,이 경우 마크 업 언어 (프로그램에서 생성 할 수 있음)를 도입하는 것이 매우 효과적이라고 지적했습니다.
Džuris

따라서 HTML + CSS는 HTML보다 낫습니다. HTML + CSS + MathJax에서 직접 작업 한 일부 프로젝트에 대한 내부 문서도 작성했습니다. 그러나 내가 방문하는 대부분의 웹 페이지는 코드 생성기로 생성 된 것으로 보입니다.
David K

3

왜 소스 코드를 생성합니까?

특히 지루하고 반복적 인 작업을 위해 코드를 수동으로 작성하는 것보다 빠르고 쉽습니다 (오류가 덜 발생하기 때문에). 또한 한 줄의 코드를 작성하기 전에 고급 도구를 사용하여 설계를 확인하고 검증 할 수 있습니다.

일반적인 사용 사례 :

  • Rose 또는 Visual Paradigm과 같은 모델링 도구;
  • 하이 임베디드 SQL 또는 컴파일 가능한 무언가로 사전 처리해야하는 인터페이스 정의 언어와 같은 수준의 언어;
  • flex / bison과 같은 Lexer 및 파서 생성기;

"기능을 만들고 매개 변수를 직접 전달하지 않는 이유는 무엇입니까?"위의 어느 것도 실행 환경 자체는 아닙니다. 코드를 코드와 연결하는 방법은 없습니다.


2

때로는 프로그래밍 언어에 원하는 기능이 없기 때문에 실제로 원하는 기능이나 매크로를 작성하는 것이 불가능합니다. 또는 원하는 것을 할 는 있지만 작성하는 코드는 추악합니다. 간단한 Python 스크립트 (또는 이와 유사한 것)는 빌드 프로세스의 일부로 필요한 코드를 생성 할 수 있습니다.#include 하여 실제 소스 파일로 .

이것을 어떻게 알 수 있습니까? 다양한 시스템, 가장 최근에는 SourcePawn으로 작업 할 때 여러 번 도달 한 솔루션이기 때문에. 간단한 소스 코드 라인을 구문 분석하고 생성 된 코드의 2 ~ 3 줄을 생성하는 간단한 Python 스크립트는 생성 된 코드를 수동으로 만드는 것보다 훨씬 좋습니다.

사람들이 원한다면 데모 / 예제 소스 코드를 사용할 수 있습니다.


1

사람이 쉽게 섭취하려면 텍스트 형식이 필요합니다. 컴퓨터는 또한 텍스트 형식의 코드를 매우 쉽게 처리합니다. 따라서 생성 된 코드는 컴퓨터에서 가장 생성하기 쉽고 사용하기 쉬운 형태로 생성되어야하며 텍스트는 매우 쉽게 읽을 수 있습니다.

그리고 코드를 생성 할 때 코드 생성 프로세스 자체는 종종 사람에 의해 디버깅되어야합니다. 생성 된 코드를 사람이 읽을 수있어 사람이 코드 생성 프로세스에서 문제를 감지 할 수 있으면 매우 유용합니다. 결국 누군가는 코드를 생성하기 위해 코드를 작성해야합니다. 얇은 공기에서 발생하지 않습니다.


1

한 번만 코드 생성

모든 소스 코드 생성이 일부 코드를 생성 한 다음 절대로 만지지 않는 것은 아닙니다. 그런 다음 업데이트가 필요할 때 원래 소스에서 재생성하십시오.

때로는 코드를 한 번만 생성 한 다음 원래 소스를 버리고 앞으로 새 소스를 유지 관리합니다.

한 언어에서 다른 언어로 코드를 이식 할 때 가끔 발생합니다. 특히 나중에 원본의 새로운 변경 사항을 이전하지 않으려는 경우 (예 : 이전 언어 코드는 유지되지 않거나 실제로는 완전합니다 (예 : 일부 수학 기능의 경우)).

이를위한 코드 생성기를 작성하면 실제로 코드의 90 % 만 올바르게 변환 할 수 있습니다. 마지막 10 %는 손으로 고정해야합니다. 손으로 100 % 번역하는 것보다 훨씬 빠릅니다.

이러한 코드 생성기는 전체 언어 번역기 (예 : Cython 또는 f2c)에서 생성하는 코드 생성기와 매우 다릅니다 . 목표는 코드를 한 번 유지하는 것입니다. 그들은 종종 그들이해야 할 일을하기 위해 1 번으로 만들어집니다. 여러 가지면에서 포트 코드에 정규식 / 찾기-바꾸기를 사용하는 다음 단계 버전입니다. "도구 지원 포팅"이라고 말할 수 있습니다.

예를 들어 웹 사이트 스크랩에서 코드를 한 번만 생성하십시오.

일부 소스에서 코드를 생성하여 다시 액세스하지 않으려는 경우와 밀접한 관련이 있습니다. 예를 들어 코드를 생성하는 데 필요한 작업이 반복 가능하지 않거나 일관성이 없거나 수행 비용이 많이 드는 경우. DataDeps.jlDataDepsGenerators.jl 이라는 한 쌍의 프로젝트를 진행 하고 있습니다 .

DataDeps.jl은 사용자가 표준 ML 데이터 세트와 같은 데이터를 다운로드 할 수 있도록 도와줍니다. 이를 위해서는 RegistrationBlock이라는 것이 필요합니다. 파일을 다운로드 할 위치와 같은 메타 데이터와 체크섬, 데이터의 라이센스 상태가 무엇인지 사용자에게 설명하는 메시지 등의 메타 데이터를 지정하는 코드입니다.

이러한 블록을 작성하는 것은 성 가실 수 있습니다. 그리고이 정보는 종종 데이터가 호스팅되는 웹 사이트에서 (구조화되거나 구조화되지 않은) 정보로 제공됩니다. 따라서 DataDepsGenerators.jl은 웹 스크래퍼를 사용하여 많은 데이터를 호스팅하는 일부 사이트에 대해 RegistrationBlockCode를 생성합니다.

올바르게 생성되지 않을 수 있습니다. 따라서 생성 된 코드를 사용하는 개발자는이를 확인하고 수정해야합니다. 예를 들어 라이센스 정보를 잃어버린 적이 있는지 확인하려고합니다.

중요하게, DataDeps.jl로 작업하는 사용자 / 개발자는 생성 된 RegistrationBlock 코드를 사용하기 위해 웹 스크래퍼를 설치하거나 사용할 필요가 없습니다. (웹 스크레이퍼를 다운로드하여 설치할 필요가 없으므로 특히 CI 실행의 경우 상당한 시간이 절약됩니다)

소스 코드를 한 번 생성하는 것은 반 패턴이 아닙니다. 일반적으로 메타 프로그래밍으로 대체 할 수 없습니다.


"report"는 "port again"이외의 다른 의미의 영어 단어입니다. 문장을 더 명확하게하려면 "리포트"를 시도하십시오. (제안 된
Peter Cordes

좋은 생각입니다 @PeterCordes
Lyndon White

생성 된 코드가 얼마나 끔찍한 지에 따라 더 빠르지 만 잠재적으로 훨씬 덜 유지 관리가 가능합니다. Fortran to C는 그 당시의 일이었습니다 (C 컴파일러는 더 널리 사용 가능하므로 사람들은 f2c+를 사용할 것입니다 cc). 그러나 결과 코드는 실제로 C 버전의 프로그램 인 AFAIK의 좋은 출발점이 아닙니다.
Peter Cordes

1
잠재적으로 그렇지 않을 수도 있습니다. 일부 코드 생성기는 유지 관리 할 수없는 코드를 만드는 것이 코드 생성기 개념의 결함이 아닙니다. 특히, 모든 경우를 잡을 필요가없는 수공예 도구는 종종 완벽한 코드를 만들 수 있습니다. 예를 들어 코드의 90 %가 배열 상수의 목록 일 경우, 그 배열 생성자를 생성하는 것은 아주 훌륭하고 적은 노력으로 수행 할 수 있습니다. (다른 한편으로 Cython의 C 코드 출력은 인간이 유지할 수 없습니다. 의도하지 않았기 때문에. f2c하루 종일 말한 것처럼 )
Lyndon White

1
큰 테이블은 가장 단순하고 축소 된 주장이었습니다. for 루프 또는 조건을 변환하는 것과 비슷하다고 말할 수 있습니다. 실제로 sed먼 길을 갔지만 때로는 좀 더 표현력이 필요합니다. 프로그램 논리와 데이터 사이의 경계는 종종 좋은 것입니다. 때때로 구별이 유용하지 않습니다. JSON은 단지 자바 스크립트 객체 생성자 코드입니다. 내 예제에서 나는 또한 객체 생성자 코드 (?.?. 그것은 어쩌면 데이터 (때때로) 함수 호출을 가지고 있기 때문에 어쩌면 더 나은 코드로 처리하지 예입니다)를 생성하고
린든 화이트

1

"소스"코드 생성은 생성 된 언어의 부족을 나타냅니다. 이를 방지하기 위해 도구를 사용하고 있습니까? 절대로 아닙니다-설명하겠습니다.

결과 코드를 낮은 수준의 언어보다 훨씬 덜 장황하게 설명 할 수있는 높은 수준의 정의가 있기 때문에 일반적으로 코드 생성이 사용됩니다. 따라서 코드 생성으로 효율성과 간결함이 향상됩니다.

C ++을 작성할 때 어셈블러 또는 기계 코드를 사용하는 것보다 더 효율적인 코드를 작성할 수 있기 때문에 그렇게합니다. 여전히 머신 코드는 컴파일러에 의해 생성됩니다. 처음에 c ++는 단순히 C 코드를 생성 한 전 처리기였습니다. 범용 언어는 범용 동작을 생성하는 데 좋습니다.

같은 방식으로 DSL (도메인 특정 언어)을 사용하면 간결하지만 특정 작업에 제한된 코드를 작성할 수 있습니다. 이렇게하면 코드의 올바른 동작을 생성하는 것이 덜 복잡해집니다. 코드는 수단과 끝이라는 것을 기억하십시오 . 개발자가 찾는 것은 행동을 효율적으로 생성하는 방법입니다.

이상적으로 생성기는 조작 및 이해하기 쉬운 입력에서 빠른 코드를 생성 할 수 있습니다. 이것이 충족되면 생성기를 사용하지 않는 것이 안티 패턴 입니다. 이 반 패턴은 일반적으로 "순수한"코드가 "더 깨끗하다"는 개념에서 비롯됩니다. 목공 또는 다른 장인이 전동 공구를 사용하거나 공작물을 "생성"하기 위해 CNC를 사용하는 것과 같은 방식으로 ( 황금을 생각하십시오) 망치 ).

반면에, 생성 된 코드의 소스가 효율적이지 않은 코드를 유지하거나 생성하기가 더 어렵다면 사용자는 잘못된 도구를 사용하는 함정에 빠지게됩니다 (때로는 같은 황금 망치로 인해 ).


0

소스 코드 생성은 생성 된 코드가 데이터임을 의미합니다. 그러나 그것은 프로그램의 나머지가 조작 할 수있는 일류 데이터입니다.

내가 알고있는 가장 일반적인 두 가지 데이터 유형은 소스 코드에 통합되어 있으며 창 (다양한 컨트롤의 수와 배치) 및 ORM에 대한 그래픽 정보입니다. 두 경우 모두 코드 생성을 통한 통합으로 데이터를 조작하기 위해 추가 "특별한"단계를 수행 할 필요가 없기 때문에 데이터 조작이 쉬워집니다.

원본 (1984) Mac으로 작업 할 때 데이터를 이진 형식으로 유지하는 리소스 편집기를 사용하여 대화 상자 및 창 정의를 만들었습니다. "이진 형식"이 파스칼 인 경우보다 응용 프로그램에서 이러한 리소스를 사용하는 것이 어려웠습니다.

따라서 소스 코드 생성은 안티 패턴이 아니므로 응용 프로그램의 데이터 부분을 만들 수있어 사용하기가 더 쉽습니다.


0

코드 생성은 달성하는 것보다 비용이 많이들 때 반 패턴입니다. 이러한 상황은 A에서 B와 거의 같은 언어 인 A에서 B로 생성 될 때 발생하지만 A에서 B에 대한 모든 사용자 정의 도구 및 빌드 스테이징보다 적은 노력으로 A로 코딩하여 수행 할 수있는 약간의 확장이 있습니다. .

외부 텍스트 처리 스테이징을 통해 메타 프로그래밍을 달성하기가 복잡하고 부적절하기 때문에 메타 프로그래밍 기능이없는 언어 (구조적 매크로)가없는 언어의 코드 생성에 대해서는 트레이드 오프가 더 금지됩니다.

빈약 한 트레이드 오프는 또한 사용량과 관련이있을 수 있습니다. 언어 A는 B와 크게 다를 수 있지만 사용자 정의 코드 생성기가있는 전체 프로젝트는 하나 또는 두 개의 작은 위치에서만 A를 사용하므로 총 복잡도 (A의 작은 비트와 A-> B 코드 생성기, 주변 빌드 스테이징)은 B에서 수행 한 솔루션의 복잡성을 초과합니다.

기본적으로 코드 생성에 전념한다면 아마도 "큰 규모로 가거나 집에 가야한다"는 의미를 가지게하고 많이 사용하거나 귀찮게하지 않아야한다.


"Bjarne Stroustrup이 처음 C ++을 구현 한시기"단락을 제거한 이유는 무엇입니까? 재미 있었다고 생각합니다.
Utku

@Utku 다른 답변은 프로젝트의 나머지 부분이 완전히 작성된 전체적이고 정교한 언어를 컴파일하는 관점에서 이것을 다룹니다. 나는 그것이 "코드 생성"이라고 불리는 대부분을 대표한다고 생각하지 않는다.
Kaz

0

나는 이것이 명확하게 언급되지 않은 것을 보았습니다.

데이터를 작성하는 것처럼 코드를 생성하는 것은 문제가되지 않습니다. 이는 컴파일러를 2 차 목적으로 재사용하는 방법입니다.

생성 된 코드를 편집하는 것은 가장 교묘하고 사악하며 끔찍한 반 패턴 중 하나입니다. 이러지 마십시오.

기껏해야 생성 된 코드를 편집하면 많은 불량 코드가 프로젝트에 포함됩니다 (모든 코드 세트는 이제 더 이상 데이터가 아닌 소스 코드 임). 최악의 경우 프로그램에 가져온 코드는 중복성이 높고 이름이 잘못되어 거의 완전히 유지 관리 할 수 ​​없습니다.

세 번째 범주는 한 번 사용하는 코드 (gui 생성기?)를 시작하고 배우는 데 도움이되도록 편집한다고 가정합니다. 이것은 각각 조금씩입니다. 시작할 수있는 좋은 방법이지만 GUI 생성기는 "제너 러블 (Generatable)"코드를 사용하여 프로그래머로서 큰 시작이되지 않을 것입니다. 여분의 SOURCE 코드를 시스템으로 가져 오는 것을 의미하는 두 번째 GUI에 다시 사용하려고했습니다.

툴링이 생성 된 코드를 편집 할 수 없을 정도로 현명하다면이를 선택하십시오. 그렇지 않다면, 나는 그것을 최악의 반 패턴 중 하나라고 부를 것입니다.


0

코드와 데이터는 모두 정보입니다.

데이터는 정확히 필요한 형태 (및 가치)의 정보입니다. 코드는 또한 정보이지만 간접 또는 중간 형태입니다. 본질적으로 코드는 데이터의 한 형태입니다.

보다 구체적으로, 코드는 사람이 정보를 스스로 처리하지 못하도록하는 기계 정보입니다.

정보 처리에서 사람을 내리는 것이 가장 중요한 동기입니다. 인생을 편하게 만드는 한 중간 단계는 허용됩니다. 이것이 중간 정보 매핑 도구가 존재하는 이유입니다. 코드 생성기, 컴파일러, 트랜스 파일러 등

왜 소스 코드를 생성합니까? 파라미터를 받아 들여서 작동 할 수있는 함수로 만들어 보지 않겠습니까?

누군가가 당신에게 구현 기능이 모호한 매핑 기능을 제공한다고 가정 해 봅시다. 기능이 약속대로 작동하는 한 내부적으로 소스 코드를 생성하는지 여부에 관심이 있습니까?


0

무언가를 생성 할 수 있다면 코드가 아닌 데이터입니다.

나중에 해당 코드가 데이터임을 규정하는 한, 제안은 "무엇이 생성 될 수 있으면 코드가 아닙니다"로 줄어 듭니다. 그렇다면 C 컴파일러에 의해 생성 된 어셈블리 코드가 코드가 아니라고 말할 수 있습니까? 직접 작성한 어셈블리 코드와 정확히 일치하면 어떻게됩니까? 당신이 원한다면 당신은 거기에 갈 수 있지만, 나는 당신과 함께 오지 않을 것입니다.

"code"의 정의로 시작해 봅시다. 너무 기술적이지 않은 한,이 논의의 목적을위한 아주 좋은 정의는 "계산을 수행하기위한 기계 작동 가능 명령"입니다.

그렇다면 소스 코드 생성에 대한이 전체 아이디어가 오해가 아닙니까?

글쎄, 당신의 시작 제안은 코드를 생성 할 수 없다는 것이지만, 나는 그 제안을 거부합니다. "code"에 대한 나의 정의를 받아들이면 일반적으로 코드 생성에 개념적 문제가 없어야합니다.

즉, 무언가를위한 코드 생성기가 있다면, 필요한 매개 변수를 수신하고 "생성 된"코드가 수행 한 올바른 조치를 수행 할 수있는 적절한 함수로 만들 수있는 이유는 무엇입니까?

글쎄요 , 그 특성보다는 코드 생성을 채택한 이유 에 대해서는 전혀 다른 질문 입니다. 코드 생성기를 쓰거나 사용하는 대신 결과를 직접 계산하는 함수를 작성하는 대안을 제안하고 있습니다. 그러나 어떤 언어로? 누구나 기계 코드로 직접 작성했던 시절은 지났고, 다른 언어로 코드를 작성하는 경우 실제로 실행되는 프로그램을 생성하기 위해 컴파일러 및 / 또는 어셈블러 형태의 코드 생성기에 의존합니다.

그렇다면 왜 Java, C 또는 Lisp 등으로 작성하는 것을 선호합니까? 심지어 어셈블러? 나는 언어가 데이터 및 연산에 대한 추상화를 제공하여 수행하려는 계산의 세부 사항을 더 쉽게 표현할 수 있기 때문에 적어도 부분적으로 있다고 주장합니다.

대부분의 상위 코드 생성기에서도 마찬가지입니다. 원형 적 사례는 다음과 같은 스캐너와 파서 생성기 아마 lexyacc. 그렇습니다. 스캐너 나 파서를 C로 직접 작성하거나 다른 프로그래밍 언어 (원시 기계 코드)로 직접 작성할 수도 있습니다. 그러나 lex 또는 yacc와 같은 고급 특수 언어를 사용하면 복잡한 문제가 발생할 경우 수작업으로 작성한 코드를보다 쉽게 ​​작성, 읽기 및 유지 관리 할 수 ​​있습니다. 일반적으로 훨씬 작습니다.

또한 "코드 생성기"의 의미가 무엇인지 고려해야합니다. 나는 C 전처리와 C ++ 템플릿의 인스턴스화가 코드 생성 연습이라고 생각합니다. 당신은 이것에 반대합니까? 그렇지 않다면, 당신은 그것들을 받아들이지 만 다른 종류의 코드 생성을 거부하는 것을 합리화하기 위해 정신 체조를 수행해야한다고 생각합니다.

성능상의 이유로 수행되면 컴파일러의 단점처럼 들립니다.

왜? 당신은 기본적으로 사용자가 데이터를 공급하는 보편적 인 프로그램을 가지고 있어야하고, 일부는 "명령"으로 분류되고, 다른 것은 "입력"으로 분류되고, 계산을 수행하고 우리가 "출력"이라고 부르는 더 많은 데이터를 방출해야한다고 포지셔닝하고 있습니다. (특정 관점에서, 그러한 범용 프로그램을 "운영 체제"라고 부를 수 있습니다.) 그러나 왜 컴파일러가보다 범용적인 프로그램을 최적화하는 것만 큼 범용 프로그램을 최적화하는 데 효과적이어야한다고 가정하십니까? 프로그램? 두 프로그램은 특성과 기능이 다릅니다.

두 언어를 연결하기 위해 인터페이스 라이브러리가 부족한 것 같습니다.

당신은 마치 보편적 인 정도의 인터페이스 라이브러리를 갖는 것이 반드시 좋은 것이라고 말한다. 아마도 그럴 수도 있지만, 대부분의 경우 그러한 라이브러리는 크고 유지 관리하기가 어렵고 심지어 느릴 수도 있습니다. 그리고 그러한 짐승이 실제로 특정 문제를 처리하기 위해 존재하지 않는다면 코드 생성 방식으로 문제를 훨씬 빠르고 쉽게 해결할 수있을 때 누가 그것을 주장해야합니까?

여기에 뭔가 빠졌습니까?

몇 가지 생각합니다.

코드도 데이터라는 것을 알고 있습니다. 내가 이해하지 못하는 것은 왜 소스 코드를 생성하는 것입니까? 파라미터를 받아 들여서 작동 할 수있는 함수로 만들어 보지 않겠습니까?

코드 생성기는 한 언어로 작성된 코드를 일반적으로 저급 언어의 다른 코드로 변환합니다. 그렇다면 사람들이 여러 언어를 사용하여 프로그램을 작성하려는 이유, 특히 주관적으로 다른 수준의 언어를 혼합하려는 이유를 묻습니다.

그러나 나는 이미 그것을 만졌다. 특정 작업에 대한 언어의 명확성과 표현력에 따라 언어를 선택합니다. 코드가 작을수록 평균적으로 버그가 적고 유지 관리가 쉬우므로 최소한 대규모 작업에는 고급 언어에 대한 편견도 있습니다. 그러나 복잡한 프로그램에는 많은 작업이 포함되며, 일부 언어는 한 언어로 더 효과적으로 처리 될 수있는 반면, 다른 언어는 다른 언어로 더 효과적으로 또는 더 간결하게 처리 될 수 있습니다. 작업에 적합한 도구를 사용한다는 것은 때때로 코드 생성을 의미합니다.


0

귀하의 의견의 맥락에서 질문에 답변 :

컴파일러의 임무는 사람이 읽을 수있는 형태로 작성된 코드를 기계가 읽을 수있는 형태로 변환하는 것입니다. 따라서 컴파일러가 효율적인 코드를 만들 수 없으면 컴파일러가 제대로 작업하지 않는 것입니다. 그게 잘못이야?

컴파일러는 작업에 최적화되지 않습니다. 그 이유는 간단 합니다. 많은 작업 을 수행하도록 최적화되어 있습니다. 많은 사람들이 다양한 작업에 사용하는 범용 도구입니다. 작업이 무엇인지 알고 나면 도메인 별 방식으로 코드에 접근하여 컴파일러가 할 수없는 타협을 할 수 있습니다.

예를 들어, 분석가가 코드를 작성해야하는 소프트웨어를 개발했습니다. 그들은 C ++로 알고리즘을 작성할 수 있으며 의존하는 모든 범위 검사 및 메모 트릭을 추가 할 수 있지만 코드의 내부 작동에 대해 많이 알아야합니다 . 오히려 간단한 것을 작성하고 최종 C ++ 코드를 생성하기 위해 알고리즘을 던질 수 있습니다. 그런 다음 분석가가 견딜 수없는 정적 분석과 같은 성능을 극대화하기 위해 이국적인 트릭을 수행 할 수 있습니다. 코드 생성을 통해 도메인 별 방식으로 작성할 수 있으므로 범용 도구보다 제품을 쉽게 출시 할 수 있습니다.

나는 또한 정반대를했다. "코드 생성 없음"이라는 명령을 수행 한 또 다른 작업이 있습니다. 우리는 여전히 소프트웨어를 사용하는 사람들의 삶을 편하게 만들고 싶기 때문에 컴파일러가 코드를 즉시 생성 할 수 있도록 대량의 템플릿 메타 프로그래밍을 사용했습니다. 따라서 저는 업무를 수행하기 위해 범용 C ++ 언어 만 필요했습니다.

그러나 캐치가 있습니다. 오류를 읽을 수 있음을 보장하는 것은 매우 어려웠습니다. 이전에 템플릿 메타 프로그래밍 된 코드를 사용해 본 적이 있다면 단 한 번의 실수만으로도 100 줄의 이해할 수없는 클래스 이름과 템플릿 인수를 사용하여 무엇이 잘못되었는지 이해하는 오류가 발생할 수 있습니다. 이 효과는 구문 오류에 대해 권장되는 디버깅 프로세스가 "자신의 파일 중 하나에 오류가있을 때까지 오류 로그를 스크롤합니다. 해당 줄로 이동하여 원하는 것을 인식 할 때까지 찡그립니다. 잘못했다. "

코드 생성을 사용했다면 사람이 읽을 수있는 오류와 함께 훨씬 더 강력한 오류 처리 기능을 가질 수있었습니다. C'est la vie.


0

코드 생성을 사용하는 몇 가지 방법이 있습니다. 그들은 세 가지 주요 그룹으로 나눌 수 있습니다.

  • 컴파일 프로세스 단계에서 출력되는 다른 언어로 코드를 생성합니다 . 일반적인 컴파일러의 경우 이는 저급 언어이지만 JavaScript로 컴파일되는 언어의 경우와 같이 다른 고급 언어 일 수 있습니다.
  • 컴파일 프로세스의 단계로 소스 코드 언어 로 코드 생성 또는 변환 이것이 매크로 가하는 일입니다.
  • 일반 컴파일 프로세스 와 별도로 도구를 사용하여 코드 생성 이것의 결과는 일반 소스 코드와 함께 파일로 존재하고 함께 컴파일되는 코드입니다. 예를 들어, ORM의 엔티티 클래스는 데이터베이스 스키마에서 자동 생성되거나 SOAP의 WSDL 파일과 같은 인터페이스 스펙에서 데이터 전송 오브젝트 및 서비스 인터페이스가 생성 될 수 있습니다.

가장 논쟁의 여지가있는 형태이기 때문에 생성 된 코드의 세 번째 종류에 대해 이야기하고있는 것 같습니다. 처음 두 양식에서 생성 된 코드는 소스 코드와 매우 명확하게 분리 된 중간 단계입니다. 그러나 세 번째 형식에서는 소스 코드와 생성 된 코드 사이에 공식적인 분리가 없습니다. 단, 생성 된 코드에는 "이 코드를 편집하지 마십시오"라는 주석이있을 수 있습니다. 여전히 개발자가 생성 된 코드를 편집 할 위험이 있습니다. 컴파일러의 관점에서 생성 된 코드는 소스 코드입니다.

그럼에도 불구하고, 이러한 형태의 생성 된 코드는 정적으로 유형이 지정된 언어에서 실제로 유용 할 수 있습니다. 예를 들어, ORM 엔티티와 통합 할 때 데이터베이스 테이블에 대해 강력한 유형의 랩퍼를 갖는 것이 실제로 유용합니다. 물론 런타임에 통합을 동적으로 처리 할 있지만 유형 안전 및 도구 지원 (코드 완성)이 손실됩니다. 정적 형식 언어의 주요 이점은 런타임이 아니라 쓰기 형식의 형식 시스템을 지원한다는 것입니다. 반대로,이 유형의 코드 생성은 동적 유형 언어에서 널리 사용되지 않습니다. 이러한 언어에서는 런타임 변환에 비해 이점이 없기 때문입니다.

즉, 무언가를위한 코드 생성기가 있다면, 필요한 매개 변수를 수신하고 "생성 된"코드가 수행 한 올바른 조치를 수행 할 수있는 적절한 함수로 만들 수있는 이유는 무엇입니까?

타입 안전과 코드 완성은 컴파일 타임에 (IDE에서 코드를 작성하는 동안) 원하는 기능이지만 정규 함수는 런타임에만 실행됩니다.

F #은 기본적으로 컴파일 타임에 프로그래밍 방식으로 생성 된 강력한 형식의 인터페이스 인 형식 공급자의 개념을 지원합니다. 이 개념은 아마도 코드 생성의 많은 사용을 대체 할 수 있고 우려를보다 명확하게 분리 할 수 ​​있습니다.


0

프로세서 명령어 세트는 기본적으로 필수적 이지만 프로그래밍 언어는 선언적 일 수 있습니다 . 선언적 언어로 작성된 프로그램을 실행하려면 불가피하게 일부 유형의 코드 생성이 필요합니다. 이 답변 과 기타 에서 언급했듯이 , 사람이 읽을 수있는 언어로 소스 코드를 생성하는 주요 이유는 컴파일러가 수행하는 정교한 최적화를 활용하는 것입니다.


-3

무언가를 생성 할 수 있다면 코드가 아닌 데이터입니다.

당신은 잘못된 길을 찾았습니다. 읽어야한다

해석 가능한 것을 위해 생성기에 무언가를 공급할 수 있다면 데이터가 아니라 코드입니다.

해당 컴파일 단계의 소스 형식이며 싱크 형식은 여전히 ​​코드입니다.


1
소스 코드를 잘못 정의했습니다 . 소스 코드는 주로 작업하는 사람을위한 것입니다 (단, 사실은이를 정의 하고 FSF 가 제공하는 무료 소프트웨어 를 참조하십시오 ). 으로 생성 된 어셈블러 코드는 gcc -fverbose-asm -O -S항상 GNU에 제공 as되고 때로는 사람이 읽을 수있는 텍스트 형식 인 경우에도 소스 코드가 아니며 데이터가 아니거나 대부분이 아닙니다 .
바 실레 Starynkevitch

또한 많은 언어 구현 이 C 코드로 컴파일 되지만 생성 된 C는 실제 소스 코드가 아닙니다 (예 : 사람이 쉽게 처리 할 수 ​​없음).
바 실레 Starynkevitch

마지막으로 하드웨어 (예 : AMD 또는 Intel 칩 또는 컴퓨터 마더 보드)가 기계 코드를 해석하고 있습니다 (소스 코드가 아님). BTW IBM1620에는 키보드 입력 가능 (BCD) 기계어 코드가 있었지만 실제로는 "소스 코드"가 아니 었습니다. 모든 코드는 소스 가 아닙니다 .
바 실레 Starynkevitch

@BasileStarynkevitch 아, 거기 도착했다. 나는 재치있는 말을 너무 많이 압축하려고하거나 그 의미를 바꾸지 말아야한다. 마우스 오른쪽 단추로, 소스 코드는 첫 번째 컴파일 단계로 공급되는 대부분의 원본 코드이어야한다.
Bergi

인간을위한 코드는 소스 코드가 아닙니다. 음악 (사운드 대)으로 정의하는 것은 어렵고 주관적입니다. 소프트웨어를 사용하는 소프트웨어를 찾는 것은 문제가되지 않습니다.
바 실레 Starynkevitch
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.