C 소스를 C++로 변환하는 중
상당히 크고(30만 이상) 상당히 성숙한 C 코드베이스를 C++로 변환하려면 어떻게 해야 합니까?
제가 염두에 두고 있는 CI의 종류는 모듈에 대략적으로 대응하는 파일(즉, 일반적인 OO 클래스 기반 분해보다 세분화되지 않음), 대신 개인 기능 및 데이터의 내부 링크, 공용 기능 및 데이터의 외부 링크로 나뉩니다.글로벌 변수는 모듈 간의 통신에 광범위하게 사용됩니다.매우 광범위한 통합 테스트 제품군을 사용할 수 있지만 유닛(즉, 모듈) 레벨 테스트는 없습니다.
저는 일반적인 전략을 염두에 두고 있습니다.
- C++의 C 부분 집합에 있는 모든 것을 컴파일하여 작동시킵니다.
- 모듈을 큰 클래스로 변환하여 모든 상호 참조가 클래스 이름으로 범위가 지정되지만 모든 함수와 데이터는 정적 멤버로 유지되고 작동합니다.
- 대량의 클래스를 적절한 생성자와 초기화된 상호 참조가 있는 인스턴스로 변환하고, 정적 멤버 액세스를 필요에 따라 간접 액세스로 교체한 후 작동합니다.
- 이제 프로젝트를 불량한 OO 애플리케이션으로 접근하고, 종속성이 다루기 쉬운 단위 테스트를 작성하고, 그렇지 않은 별도의 클래스로 분해합니다. 여기서 목표는 각 변환 시 작업 프로그램에서 다른 프로그램으로 이동하는 것입니다.
분명히, 이것은 꽤 많은 일이 될 것입니다.이런 종류의 번역에 대한 사례 연구/전쟁 이야기가 있습니까?대체 전략?다른 유용한 조언?
주 1: 프로그램은 컴파일러이며, 아마도 수백만 개의 다른 프로그램들은 변경되지 않는 동작에 의존하기 때문에, 전면적인 다시 쓰기는 거의 옵션이 아닙니다.
참고 2: 소스는 거의 20년이 되었으며, 매년 약 30%의 코드 전환(수정된 라인 + 추가된 라인/이전 총 라인)이 있습니다.다시 말해서, 그것은 크게 유지되고 확장됩니다.따라서 목표 중 하나는 유지관리성을 높이는 것입니다.
[질문을 위해, C++로의 번역은 필수이며, C로 남겨두는 것은 선택사항이 아니라고 가정합니다.이 조건을 추가하는 요점은 "C에 남겨두기" 답변을 제거하는 것입니다.]
전에 한 지 되지 않았습니다(는 스마트한 C와 "라는 된 광고 프로젝트에서).struct
"), 저는:-)의 "에 한 입씩 저는코끼를먹때것같을사는과전은사용하략한을것 :-싶철리용습제니다할을드요번고입하한 :-세에안씩학-)▁s:한요드),hy세▁i▁:번입▁you▁using▁the),▁elephant.
가능한 한 다른 부분에 미치는 영향을 최소화하면서 수행할 수 있는 단계로 분할합니다.페데리코 람포니가 제안한 것처럼 전면 시스템을 구축하는 것은 좋은 시작입니다. 모든 것이 C++ 전면을 가지고 있고 그것을 통해 소통되면, 모듈의 내부를 변경할 수 있습니다. 모듈 외부의 어떤 것에도 영향을 미치지 않는다는 것을 상당히 확실하게 말이죠.
우리는 이미 부분적인 C++ 인터페이스 시스템을 갖추고 있었습니다(이전의 작은 리팩터링 노력으로 인해). 그래서 이 접근법은 우리의 경우 어렵지 않았습니다.C++ 객체로 통신하는 모든 것을 갖게 되면(완전히 별도의 소스 코드 분기를 작업하고 승인된 대로 모든 변경 사항을 메인 분기에 통합하는 데 몇 주가 소요됨) 그날로 가기 전에 완전히 작동하는 버전을 컴파일하지 못하는 경우가 거의 없었습니다.
전환이 아직 완료되지 않았습니다. 중간 릴리스(몇 주마다 포인트 릴리스를 목표로 함)를 위해 두 번이나 중단했지만, 문제에 대해 불만을 제기하는 고객은 없습니다.저희 QA 직원들도 제가 기억하는 한 가지 문제만 발견했습니다. :-)
다음은 어떻습니까?
- C++의 C 부분 집합에 있는 모든 것을 컴파일하고 그것을 작동시킵니다.
- C 코드를 변경하지 않고 일련의 파사드를 구현하시겠습니까?
왜 "C++로의 번역이 필수입니까?"당신은 C 코드를 큰 클래스로 변환하는 등의 고통 없이 포장할 수 있습니다.
당신의 애플리케이션에는 많은 사람들이 작업하고 있으며, 손상되지 않을 필요가 있습니다.대규모로 OOO 스타일로 전환하려면 작업을 자동화하기 위한 대규모 변환 툴이 필요합니다.
기본 아이디어는 데이터 그룹을 클래스로 지정한 다음 코드를 재팩터링하여 해당 데이터를 클래스로 이동하고 해당 데이터에 대한 함수만 해당 클래스로 이동하며 해당 데이터에 대한 모든 액세스를 클래스의 호출로 수정하는 도구입니다.
자동화된 사전 분석을 수행하여 일부 아이디어를 얻기 위해 통계 클러스터를 구성할 수 있지만, 어떤 데이터 요소를 그룹화할지 결정하려면 애플리케이션 인식 엔지니어가 필요합니다.
이 작업을 수행할 수 있는 도구는 DMS Software Reengineering Toolkit입니다. DMS는 코드를 읽기 위한 강력한 C 파서를 가지고 있으며 C 코드를 컴파일러 추상 구문 트리로 캡처하며 (기존 컴파일러와 달리) 전체 300K SLOK에서 흐름 분석을 계산할 수 있습니다.DMS에는 "뒤로" 끝으로 사용할 수 있는 C++ 프론트 엔드가 있습니다. C 구문을 C++ 구문에 매핑하는 변환을 작성합니다.
대규모 항전 시스템에 대한 주요 C++ 재설계 작업은 이러한 종류의 활동에 DMS를 사용하는 것이 어떤 것인지에 대한 아이디어를 제공합니다.www.semdesigns.com/Products/DMS/DMSToolkit.html, 에서 기술 문서, 특히 자동 프로그램 변환을 통한 C++ 구성 요소 모델 재설계를 참조하십시오.
이 과정은 심장이 약한 사람들을 위한 것이 아닙니다.그러나 대규모 애플리케이션의 수동 리팩터링을 고려하는 사람들은 이미 힘든 작업을 두려워하지 않습니다.
네, 저는 그 회사의 수석 건축가로 일하고 있습니다.
저는 C 인터페이스를 통해 C++ 클래스를 작성할 것입니다.C 코드를 터치하지 않으면 실수할 가능성이 줄어들고 프로세스가 상당히 빨라집니다.
일단 C++ 인터페이스가 가동되면 코드를 복사하고 클래스에 붙여넣는 것은 간단한 작업입니다.말씀하신 대로 이 단계에서는 장치 테스트를 수행해야 합니다.
CGCC에서 C입니다.그들은 모든 것을 C와 C++의 공통 부분 집합으로 옮기는 것으로 시작했습니다., , 아래추니다습했가니로고에에서 된 모든 것에 대한 경고를 GCC에 추가했습니다.-Wc++-compat
그것은 당신이 여행의 첫 부분에 도착하게 할 것입니다.
후자의 경우, 실제로 C++ 컴파일러로 모든 것을 컴파일할 수 있게 되면 관용적인 C++ 컴파일러를 가진 것들을 대체하는 데 초점을 맞출 것입니다.예를 들어 C 매크로를 사용하여 정의된 목록, 맵, 세트, 비트 벡터, 해시 테이블 등을 사용하는 경우 C++로 이동하면 많은 것을 얻을 수 있습니다.OOO와 마찬가지로 이미 OOO 관용구(예: 구조 상속)를 사용하고 있으며 C++가 코드에 대해 더 명확하고 더 나은 유형 검사를 제공하는 이점을 찾을 수 있습니다.
당신의 목록은 괜찮아 보입니다. 다만 저는 테스트 스위트를 먼저 검토하고 코딩을 하기 전에 가능한 한 엄격하게 하는 것을 제안합니다.
또 다른 바보 같은 생각을 해보죠.
- C++의 C 부분 집합에 있는 모든 것을 컴파일하여 작동시킵니다.
- 모듈로 시작하여 대규모 클래스로 변환한 다음 인스턴스에서 해당 인스턴스로 C 인터페이스(시작한 인터페이스와 동일)를 구축합니다.나머지 C 코드가 해당 C 인터페이스와 함께 작동하도록 합니다.
- 필요에 따라 리팩터링하여 OOO 서브시스템을 C 코드에서 한 번에 하나의 모듈로 확장하고, C 인터페이스의 일부가 무용지물이 되면 폐기합니다.
어떻게 시작하고 싶은지 외에 고려해야 할 두 가지 사항은 무엇에 집중하고 싶은지와 어디에서 멈추고 싶은지에 있습니다.
코드 전환이 많다고 하면, 이것이 여러분의 노력에 집중할 수 있는 열쇠가 될 수 있습니다.코드에서 많은 유지보수가 필요하고 성숙한/안정적인 부품이 충분히 작동하고 있는 것으로 보이는 부분을 선택하는 것이 좋습니다. 따라서 아마도 파사드 등이 있는 윈도우 드레싱을 제외하고는 그대로 두는 것이 좋습니다.
중지하려는 위치는 C++로 변환하려는 이유가 무엇인지에 따라 달라집니다.이것은 그 자체로는 목표가 될 수 없습니다.타사 종속성 때문에 문제가 발생한 경우 해당 구성 요소에 대한 인터페이스에 노력을 집중합니다.
제가 작업하는 소프트웨어는 몇 년 전에 C에서 C++로 '변환'된 거대하고 오래된 코드 기반입니다.GUI가 Qt로 변환되었기 때문인 것 같습니다.지금도 대부분 수업이 있는 C 프로그램처럼 보입니다.공공 데이터 구성원들에 의해 야기된 의존성을 깨고, 절차적 괴물 방법을 가진 거대한 클래스를 더 작은 방법과 클래스로 재팩터링하는 것은 결코 진정으로 시작되지 않았다고 생각합니다.
- 작동 중인 코드와 개선할 필요가 없는 코드는 변경할 필요가 없습니다.이렇게 하면 기능을 추가하지 않고도 새로운 버그가 발생하며 최종 사용자는 이를 인식하지 못합니다.
- 리팩터를 안정적으로 수행하는 것은 매우 매우 어렵습니다.많은 코드 조각들은 너무 크고 매우 중요해서 사람들이 감히 그것을 만지지 못합니다.우리는 꽤 광범위한 기능 테스트 제품군을 가지고 있지만 충분한 코드 적용 범위 정보를 참조하십시오.결과적으로, 리팩터링 과정에서 문제를 발견할 수 있는 충분한 테스트가 이미 마련되어 있는지 여부를 확인하기가 어렵습니다.
- ROI를 설정하기가 어렵습니다.최종 사용자는 리팩토링의 혜택을 받지 못하므로 유지보수 비용을 절감해야 하며, 리팩토링을 통해 성숙한 새로운 버그, 즉 상당히 버그가 없는 코드를 도입하기 때문에 처음에는 이 비용이 증가할 것입니다.리팩터링 자체도 비용이 많이 들 것입니다.
NB. "레거시 코드로 효과적으로 작업" 책을 알고 계십니까?
당신은 당신의 도구가 컴파일러라고 언급하고, 그것은 "사실, 다중 디스패치에서 유형 매칭뿐만 아니라 패턴 매칭이 훨씬 더 나을 것입니다."라고 말합니다.
당신은 차를 만드는 것을 보는 것이 좋을 것입니다.AST에 대한 패턴 매칭은 물론 추상 문법의 AST 정의, 방문자, 트랜스포머 등을 제공합니다.
소규모 프로젝트나 학술 프로젝트(예: 10,000줄 미만)가 있는 경우에는 다시 작성하는 것이 가장 좋습니다.원하는 대로 인수 분해할 수 있으며, 시간이 많이 걸리지 않습니다.
실제 애플리케이션이 있다면 C++(일반적으로 기능 프로토타입 등을 주로 수정하는 것을 의미)로 컴파일한 다음 리팩토링 및 OO 래핑 작업을 하는 것이 좋습니다.물론 저는 C++ 코드를 수용하기 위해서는 코드가 OO구조화되어야 한다는 철학에 동의하지 않습니다.필요에 따라 (기능 또는 유닛 테스트 통합을 위해) 개별 변환, 재작성 및 리팩토링을 수행합니다.
제가 할 일은 다음과 같습니다.
- 코드가 20년이 되었으므로 파서/ 구문 분석기를 폐기하고 최신 lex/yacc/bison(또는 이와 유사한 모든 것) 기반 C++ 코드 중 하나로 교체하십시오. 이 코드는 훨씬 더 유지 관리가 가능하고 이해하기 쉽습니다.BNF가 있으면 개발 속도도 빨라집니다.
- 이전 코드로 수정되면 모듈을 클래스로 래핑하기 시작합니다.전역/공유 변수를 인터페이스로 바꿉니다.
- 이제 당신이 가지고 있는 것은 C++ 컴파일러가 될 것입니다.
- 시스템의 모든 클래스에 대한 클래스 다이어그램을 작성하고 해당 클래스가 어떻게 통신하는지 확인합니다.
- 같은 클래스를 사용하여 다른 클래스를 그리고 어떻게 의사소통해야 하는지 확인합니다.
- 코드를 리팩터하여 첫 번째 다이어그램을 두 번째 다이어그램으로 변환합니다.(이것은 지저분하고 까다로울 수 있습니다)
- 추가된 모든 새 코드에 대해 C++ 코드를 사용하는 것을 기억하세요.
- 시간이 조금 남으면 보다 표준화된 STL 또는 Boost를 사용하기 위해 데이터 구조를 하나씩 교체해 보십시오.
언급URL : https://stackoverflow.com/questions/199627/converting-c-source-to-c
'programing' 카테고리의 다른 글
쿼리에서 스프링 데이터 사용 OR (0) | 2023.06.30 |
---|---|
Vue.set /Vue.delete 대신 Vue.js 스프레드 연산자 (0) | 2023.06.30 |
Oracle like 절에서 밑줄이 작동하지 않습니다. (0) | 2023.06.30 |
Git 이등분 오류 실행 취소 (0) | 2023.06.30 |
PyTorch 모형의 총 모수 수 확인 (0) | 2023.06.30 |