마감 기한에 도달 한 후 더 이상 사용되지 않는 코드가 컴파일되지 않도록 방지 [닫기]


68

우리 팀에서 우리는 큰 모 놀리 식 프로젝트 (전체 클래스, 메소드 등)에서 많은 오래된 물건을 청소했습니다.

그 청소 작업 동안 나는 평소보다 어떤 종류의 주석이나 라이브러리가 더 멋진 지 궁금했다 @Deprecated. 이것은 @FancyDeprecated특정 날짜가 경과 한 후 기존 사용되지 않는 코드를 청소하지 않은 경우 성공하는 프로젝트의 빌드를 방지해야한다.

인터넷에서 검색했지만 아래 설명 된 기능을 가진 항목을 찾지 못했습니다.

  • 특정 날짜 이전에 삭제하려는 주석에 주석 또는 이와 유사한 것이어야합니다.
  • 그 날짜 전에 코드가 컴파일되고 모든 것이 정상적으로 작동합니다.
  • 이 날짜 이후에는 코드가 컴파일되지 않으며 문제에 대한 경고 메시지가 표시됩니다.

유니콘을 찾고 있다고 생각합니다. 어떤 프로그램 언어에도 비슷한 기술이 있습니까?

계획 BI는 "마감일"에 실패하기 시작하여 제거 될 코드의 단위 테스트로 마술을 만들 가능성을 생각하고 있습니다. 이것에 대해 어떻게 생각하십니까? 더 좋은 아이디어?


168
지원 중단은 날짜가 아니라 버전에 대해 수행 됩니다 . 더 이상 사용되지 않는 기능 사용을 중지하려면 해당 기능이없는 버전을 해제하십시오. 관심을 끌게되며 아직 할 수없는 경우 언제든지 롤백 할 수 있습니다. 많은 사람들이 구 버전에 갇혀 있습니다. 그들의 프로그램을 깨는 것은 갈 길이 아닙니다.
isanae

4
플랜 B가 제대로 들립니다. 추가 테스트를 통해 더 이상 사용되지 않는 이유에 대해 단위 테스트에 주석을 달 수 있습니다. 소스 코드에 주석을 추가해도 큰 모 놀리 식의 가독성에 도움이되지 않습니다
dwana

53
정말 악한 유니콘처럼 들립니다. 잘 컴파일되고 모든 테스트를 통과 한 소프트웨어를 고객에게 배송했습니다. 그런 다음 언젠가 소프트웨어를 다시 확인하면 정확히 동일한 개발 플랫폼에서도 빌드되지 않습니다. 이제 공식 테스트를 통과 한 코드를 수정하거나 컴퓨터 시계 롤백과 같은 악의적 인 해킹을 수행해야합니다.
Simon B

6
@ Deprecated_RemoveMe_2018_06_01로 만든 다음 2018-06-01에서 주석 자체를 삭제하십시오. Voila, 주석을 사용하는 모든 코드가 더 이상 컴파일되지 않습니다! (주석을 찾을 수 없기 때문에)
user253751

65
앞으로 몇 년 동안 새로 고용 된 개발자가 질문합니다. 왜 빌드 서버의 시간이 2016 년 1 월로 설정되어 있습니까? 그리고 10 년 동안 그곳에있는 사람은 그에게 필요하거나 빌드가 무작위 장소에서 중단된다고 말할 것입니다. 한숨.
Wilbert

답변:


62

이것이 컴파일을 실제로 금지 할 때 유용한 기능이라고 생각하지 않습니다. 2018 년 1 월 6 일에 전날 컴파일 된 코드의 많은 부분이 컴파일되지 않으면 팀에서 해당 주석을 신속하게 다시 제거하거나 코드를 정리했는지 여부를 결정합니다.

그러나 코드에 사용자 정의 주석을 추가 할 수 있습니다

@Deprecated_after_2018_07_31

이러한 주석을 스캔 할 수있는 작은 도구를 만듭니다. (리플렉션을 사용하지 않으려는 경우 grep의 간단한 라이너 하나만 사용하면됩니다.) Java 이외의 다른 언어에서는 "grepping"에 적합한 표준화 된 주석 또는 전 처리기 정의를 사용할 수 있습니다.

그런 다음 특정 날짜 직전 또는 직후에 해당 도구를 실행하고 여전히 해당 주석을 찾으면 해당 코드 부분을 긴급하게 정리하도록 팀에 상기 시키십시오.


9
@Bergi : 이봐, 이것은 단지 예일뿐입니다. OP는 제어에서 선호하는 모든 버전이나 날짜 태그를 사용할 수 있습니다.
Doc Brown

4
일반적인 지원 중단 기능을 사용하고 특정 날짜의 컴파일러 출력을 보는 것 보다이 작업을 수행 할 때 이점이 없습니다. 이미 존재하는 것을 다시 구현하기 위해 개발자 시간을 잘못 사용하는 것처럼 보입니다. 이미 많은 경고를 받았더라도 (정리해야 할 가치가 있음) 컴파일러가 모든 경고를 텍스트 파일에 뱉어 내고 grep하거나 검색하도록 할 수 있습니다.
jpmc26

4
@ jpaugh 나는 도구가 무엇이든간에 기존 도구로 이미 효율적으로 수행 할 수있는 작업을 수행하기 위해 새로운 도구를 만드는 데 시간 (주, 시간 = 돈)을 가라 앉 히지 않는 것이 좋습니다.
jpmc26

3
@ jpmc26 : 두 가지 (작은) 장점이 있습니다 : 더 많은 사용 중단 경고 (더 중요한 경고를 간과 할 위험이 있음)를 얻지 않고 코드 섹션마다 다른 사용 중단 기준 (날짜, 버전 등)을 도입 할 가능성이 있습니다. 또한 OP는 명시 적으로 지원 중단과 날짜를 결합하도록 요청했습니다.
Doc Brown

7
모호한 ??-??-YYYY 순서만으로 고통과 오해를 일으키는 것을 보았 기 때문에 예제의 날짜에 YYYY-MM-DD 순서를 사용하면 +1이됩니다.
mtraceur

284

이것은 시한 폭탄으로 알려진 기능을 구성합니다 . 시간 폭탄을 만들지 마십시오.

코드는 아무리 잘 구조화하고 문서화 하더라도 특정 연령 이상으로 살면 이해하기 어려운 신화적인 블랙 박스로 바뀔 입니다. 미래에 누군가가 필요로하는 마지막 일은 또 다른 이상한 실패 모드이며, 가능한 최악의 시간에, 그리고 명백한 해결책없이 완전히 놀라게합니다. 이러한 문제를 의도적으로 생성 한 데 대한 변명의 여지는 없습니다.

이 방법을 살펴보십시오. 노후화를 염두에두고 코드를 따라갈 수있을 정도로 코드 기반을 체계화하고 인식하고 있다면 코드 내에 메커니즘이 필요하지 않습니다 . 그렇지 않으면 코드베이스의 다른 측면에 대한 최신 정보가 없을 수도 있고 알람에 적시에 정확하게 응답하지 못할 수도 있습니다. 즉, 시한 폭탄은 누구에게도 좋은 목적을 제공하지 않습니다. 그냥 아니라고 말해!


74
+1 이것은 당신 물 것이다. 몇 개월 뒤. 긴급 배포를하려는 금요일에 금요일에. 그리고 주말이 길기 때문에 그것에 대해 아는 모든 사람들은 사무실 밖입니다. 하지마
Roger Lipscombe

3
동의하다. 노후화는 코딩 문제가 아닌 조직 문제입니다. 난 여전히 애플을 꽂고] [BASIC]을 쓸 수 있었지만 아무것도 막을 수 없었습니다. 그러나 내가 하고 싶 습니까?

19
"조직적이고 인식적인"방향으로 진행하는 올바른 해결책은 버그 추적 시스템에서 "<such and such> 제거"라고 말하고 제안 된 시간 내에 주석을 작성하는 것입니다. 그리고 6 개월 후에 다음 릴리스에서 수정 될 버그를 찾기 위해 버그 검토가 시작된 후 해당 기간이 임박한 경우 "이 시점을 수행 할 때"라고 말합니다. 기본 프로젝트 관리입니다.
궤도

1
실제로 출시 일정을 충분히 예측할 수 있다면 지금 이정표를 세우십시오.
궤도

13
대안 을 보려면 isanae의 의견 을 참조하십시오 . " 더 이상 사용되지 않는 기능을 사용하지 않으려면 해당 기능이없는 버전을 릴리스하십시오.주의를 기울여야하며 아직 할 수없는 경우 언제든지 롤백 할 수 있습니다. "
Stevoisiak

70

C #에서는 ObsoleteAttribute다음과 같은 방식으로 사용합니다 .

  • 버전 1에서는 기능이 제공됩니다. 방법, 클래스 등
  • 버전 2에서는 원래 기능을 대체하기 위해 더 나은 기능을 제공합니다. 기능에 사용되지 않는 속성을 배치하고 "경고"로 설정 한 후 "이 기능은 더 이상 사용되지 않습니다. 대신 더 나은 기능을 사용하십시오.이 라이브러리의 버전 3에서는 이러한 기능이 릴리스됩니다. 날짜,이 기능을 사용하면 오류가 발생합니다. " 이제 기능 사용자는 여전히 기능을 사용할 수 있지만 새 기능을 사용하려면 코드를 업데이트해야합니다.
  • 버전 3에서는 속성을 경고가 아닌 오류로 업데이트하고 "이 기능은 더 이상 사용되지 않습니다. 대신 더 나은 기능을 사용하십시오.이 라이브러리의 버전 4에서는 다음과 같이 릴리스됩니다. 날짜가되면이 기능이 실행됩니다. " 이전 경고에주의를 기울이지 않은 사용자에게는 여전히 문제를 해결하는 방법을 알려주는 유용한 메시지가 표시되며 이제 코드가 컴파일되지 않으므로 문제를 해결해야합니다.
  • 버전 4에서는 치명적인 예외가 발생하도록 기능을 변경하고 다음 버전에서 기능이 완전히 제거 될 것이라는 메시지를 변경합니다.
  • 버전 5에서는 기능을 완전히 제거하고 사용자가 불만을 표시하는 경우 세 가지 릴리스주기의 공정한 경고를 제공했으며, 사용자가 강하게 느끼면 버전 2를 계속 사용할 수 있습니다.

여기서의 아이디어는 영향을받는 사용자가 가능한 한 크게 고통을 겪지 않고 적어도 하나의 라이브러리 버전에서이 기능을 계속 사용할 수 있도록하는 것입니다.


2
나는 이것이 올바른 접근 방법이라고 생각하지만 한 가지를 바꿀 것입니다 ... "사용자가 불평하면" "사용자가 불평하면"
Liath

10
오류로 전환하면서 동시에 신체를 제거하는 것은 이상해 보입니다. 더 이상 사용되지 않는 오류 버전의 장점 중 하나는 이전 버전에 대해 작성된 코드가 계속 작동하면서 새로 컴파일 된 코드가이를 사용하지 못하도록한다는 것입니다. 따라서 API 호환성을 의도적으로 위반하면서 ABI 호환 상태를 유지합니다. 물론 완벽한 세계는 이전에 컴파일 된 응용 프로그램으로 새 코드를 실행하지 않지만 많은 프로젝트가 그 이상에 도달하지 않도록 semver 스타일 버전 관리 등을해야합니다.
케빈 카스 카트

@KevinCathcart : 좋은 지적입니다. 어쩌면 거기에 또 다른 단계가 보장됩니다! 텍스트를 업데이트하겠습니다.
Eric Lippert

1
실제로 SemVer를 사용하는 경우 XY0 버전에서 더 이상 사용되지 않는 버전 (더 이상 사용되지 않는 버전은 마이너 릴리스 여야 함)에서 X + 1.0.0으로 완전히 제거 할 수 있습니다. X + 2.0.0?까지 조금 더 나아가는 것이 좋지만이 5 단계 프로세스는 아마도 백합을 금색으로 만들었습니다. "경고"이후의 다음 단계는 "치명적 오류"여야합니다. 더 이상 사용되지 않는 기능이 오류 생성 코드로 대체되기 때문입니다. 이후 libfoo.so.2libfoo.so.3다른 잘 하나와 공존 할 수 있습니다, 그들은 전환 될 때까지 기존 라이브러리를 계속 사용할 수 있습니다 귀하의 다운 스트림.
Monty Harder

@MontyHarder : 물론입니다. 정확한 이벤트 순서는 개발자 및 사용자 커뮤니티의 요구에 따라 결정될 수 있습니다. 더 큰 요점은 이해 관계자에게 명확하게 전달되는 이러한 종류의 버전 관리 문제를 처리하기위한 사고 정책이 있어야한다는 것입니다.
Eric Lippert

24

"더 이상 사용되지 않음"의 의미를 잘못 이해했습니다. 더 이상 사용되지 않는 방법 :

일반적으로 대체 되었기 때문에 사용 가능하지만 더 이상 사용하지 않는 것이 가장 좋습니다.

옥스포드 사전

더 이상 사용되지 않는 기능은 여전히 ​​컴파일됩니다.

특정 날짜에 기능 을 제거하려고 합니다. 괜찮아. 그렇게하는 방법은 해당 날짜에 제거하는 것입니다 .

그때까지는 더 이상 사용되지 않거나 사용되지 않거나 프로그래밍 언어에서 호출하는 것으로 표시하십시오. 메시지에 제거 할 날짜와이를 대체하는 날짜를 포함하십시오. 다른 개발자가 새로운 사용을 피하고 가능하면 오래된 사용을 대체해야한다는 경고가 표시됩니다. 이러한 개발자는이를 준수하거나 무시할 것이며 누군가 제거 될 때 그 결과를 처리해야합니다. (상황에 따라 본인이거나 본인이 사용하는 개발자 일 수 있습니다.)


downvoter가 동의하지 않는 것에 관심이 있습니다.
jpmc26

2
+1. 민첩한 개발에 JIRA를 사용하는 경우 작업을 생성하고 향후 스프린트에 배치하십시오. 다른 프로젝트 관리 도구 및 방법론을 따르십시오. 이것은 비 기술적 인 방법으로 가장 잘 해결됩니다.
Matthew 읽기

1
또한 Class / Lib은 Xx 버전에서 감가 상각 및 / 또는 제거 된 상태로 문서에 남아 있어야합니다.
Phil M

12

이미 출시 된 소프트웨어 버전을 지원하려면 이전 버전의 코드를 빌드하고 디버깅하는 기능을 유지해야합니다. 특정 날짜 이후 빌드를 방해하면 향후 합법적 인 유지 관리 및 지원 작업을 수행하지 못하게 될 위험이 있습니다.

또한 컴파일하기 전에 1 ~ 2 년 내 컴퓨터의 시계를 다시 설정하는 것은 간단한 해결 방법처럼 보입니다.

"더 이상 사용되지 않음"은 앞으로 무언가가 사라질 것이라는 경고입니다. 사람들이 해당 API를 사용하지 못하게 하려면 관련 코드를 제거하십시오 . 어떤 메커니즘으로 코드를 사용할 수 없게 만들면 코드베이스에 코드를 남겨 둘 필요가 없습니다. 코드를 제거하면 찾고있는 컴파일 타임 검사가 제공되며 사소한 해결 방법이 없습니다.

편집 : 귀하의 질문에 "사용하지 않은 오래된 코드"를 참조하십시오. 코드가 실제로 사용되지 않으면 더 이상 사용되지 않을 것입니다. 그냥 삭제하십시오.


가장 좋은 대답은 아마도 코드를 삭제하는 것이 답변에서 더 빨리 문제를 해결하는 가장 좋은 방법이라는 것입니다. 텍스트 답변 벽을 지나서 쉽게 스크롤 할 수 있습니다
Clint

6

나는 전에 그런 기능을 본 적이 없다-특정 날짜 이후에 효력을 발휘하는 주석.

@Deprecated하지만, 충분한 수있다. CI에서 경고를 포착하고 존재하는 경우 빌드 수락을 거부합니다. 이는 컴파일러에서 빌드 파이프 라인으로 책임을 이동하지만 추가 단계를 추가하여 빌드 파이프 라인을 (반) 쉽게 변경할 수 있다는 이점이 있습니다.

이 답변 문제를 완전히 해결 하지는 못합니다 (예를 들어 경고가 있지만 개발자 컴퓨터의 로컬 빌드는 여전히 성공할 것임). CI 파이프 라인이 설정되어 실행중인 것으로 가정합니다.


4

캘린더 나 할 일 목록을 찾고 있습니다.

또 다른 대안은 코드베이스에 경고가 거의없는 경우 사용자 정의 컴파일러 경고 또는 컴파일러 메시지를 사용하는 것입니다. 경고가 너무 많으면 추가 작업 (약 15 분)을 소비 하고 각 빌드에서 지속적 통합이 제공 하는 빌드 보고서에서 컴파일러 경고를 선택해야합니다 .

코드를 수정해야한다는 점을 기억하십시오. 때때로 이러한 알림에는 실제 마감일이 엄격하기 때문에 타이머를 설정해야 할 수도 있습니다.

목표는 사람들에게 문제가 존재하고 주어진 시간 프레임을 사용하여 수정해야 함을 지속적으로 상기시키는 것입니다. 특정 시간에 빌드를 중단시키는 기능은 아닙니다. 그러나 그 기능 자체는 주어진 기간으로 고정됩니다.


1
동의하다. 그러나 문제가 존재하고 특정 기간 내에 수정해야하는 경우 적시에 누군가의 최우선 순위가되어야합니다. 회의에서 관리자가 "최우선 순위"를 주었다가 나중에 " 이것이 당신의 최우선 순위"(다른 것) 라고 말한 것을 기억합니다. 상사는“ 가지 우선 순위를 가질 수 없습니다 !”라고 말했습니다. 매니저는 깜짝 놀랐다. 그가 생각한 것 같아 "적시에"고칠 무언가를 계획하는 것은 시간이 부족할 것입니다.

3

이것에 대해 생각하는 한 가지 방법은 시간 / 날짜로 의미하는 것 입니까? 컴퓨터는 이러한 개념이 무엇인지 모릅니다. 어떻게 든 프로그래밍해야합니다. 유닉스 형식으로 "시간 이후 초"로 시간 을 나타내는 것이 일반적이며 OS 호출을 통해 특정 값을 프로그램에 공급하는 것이 일반적입니다. 그러나이 사용법이 아무리 흔하더라도 "실제"시간이 아니라 단지 논리적 표현이라는 점을 명심해야합니다.

다른 사람들이 지적했듯이,이 메커니즘을 사용하여 "마감일"을 정했다면 다른 시간에 먹이를주고 "마감일"을 깨는 것은 사소한 일입니다. NTP 서버 요청과 같은보다 정교한 메커니즘도 마찬가지입니다 (자체 인증서, 인증 기관을 대체하거나 암호화 라이브러리를 패치 할 수 있기 때문에 "보안"연결을 통해서도). 처음에는 그러한 개인이 당신의 메커니즘을 해결하는 데 잘못되었다고 생각 될 수도 있지만, 자동 적이고 합당한 이유로 수행 된 것일 수도 있습니다 . 예를 들어, 재현 가능한 빌드 를 사용하는 것이 좋으며 , 결정적이지 않은 시스템 호출을 자동으로 재설정 / 차단할 수있는 도구가 있습니다. libfaketime 은 정확히 그렇게합니다.모든 파일의 타임 스탬프를로 설정하고 1970-01-01 00:00:01Qemu의 레코드 / 재생 기능은 모든 하드웨어 상호 작용 등을 위조합니다.

이것은 Goodhart의 법칙 과 유사합니다 . 프로그램의 동작이 논리 시간에 의존하게되면 논리 시간은 "실제"시간의 측정 기준이되지 않습니다. 다시 말해서 사람들은 일반적으로 시스템 시계를 엉망으로 만들지 않지만 이유를 제시하면 사람들은 그렇습니다.

시간에 대한 다른 논리적 표현이 있습니다. 그 중 하나는 소프트웨어 버전 (앱 또는 일부 종속성)입니다. 이는 UNIX 시간보다 "마감일"에 대해 더 바람직한 표현입니다. 이는 관심있는 기능 (특성 세트 / API 변경)에 더 구체적이기 때문에 직교 관심사를 짓밟을 가능성이 적기 때문입니다 (예 : UNIX 시간을 마감 시한을 지키면 로그 파일, 크론 작업, 캐시 등이 손상 될 수 있습니다.)

다른 사람들이 말했듯이, 라이브러리를 제어하고이 변경 사항을 "푸시"하려는 경우 기능을 더 이상 사용하지 않는 새 버전 (경고를 유발하고 소비자가 사용법을 찾아 업데이트하는 데 도움이 됨)을 제거한 다음 완전히 기능. (다시) 버전은 단지 시간의 논리적 표현이기 때문에 "실제"시간과 관련 될 필요가 없기 때문에 원한다면 서로 즉시 게시 할 수 있습니다. 시맨틱 버전 관리가 도움이 될 수 있습니다.

대체 모델은 변경을 "풀"하는 것입니다. 이것은 "계획 B"와 같습니다. 소비 애플리케이션에 테스트를 추가하십시오.이 종속성의 버전이 최소한 새로운 값인지 확인합니다. 일반적으로 빨강 / 녹색 / 리 팩터는 코드베이스를 통해이 변경 사항을 전파합니다. 기능이 "나쁜"또는 "잘못된"것이 아니라 "이 사용 사례에 적합하지 않은"경우 더 적합 할 수 있습니다.

"풀 (pull)"접근 방식의 중요한 질문은 종속성 버전이 " 기능 "단위로 계산되는지 여부 와 테스트 가 필요한지 여부입니다 . 또는 단지 "개인"구현 세부 사항인지의 여부, 실제 단위 ( 기능 ) 테스트 일부로 만 실행되어야합니다 . 나는 말할 것입니다 : 의존성 버전 사이의 구별이 실제로 응용 프로그램의 기능으로 계산되면 테스트를 수행하십시오 (예 : Python 버전이 3.x 이상인지 확인). 그렇지 않다면, 하지시험을 추가하십시오 (취약하고 유익하지 않으며 지나치게 제한적이므로); 라이브러리를 제어하는 ​​경우 "푸시"경로로 내려갑니다. 라이브러리를 제어하지 않으면 제공되는 버전을 사용하십시오. 테스트가 통과되면 자신을 제한 할 가치가 없습니다. 그들이 통과하지 않으면 바로 거기에 "마감"입니다!

의존성 기능의 특정 사용을 권장하지 않으려는 경우 (예 : 나머지 코드와 잘 어울리지 않는 특정 기능 호출), 특히 의존성을 제어하지 않는 경우 다른 방법이 있습니다 : 코딩 표준을 금지하십시오 / 이러한 기능의 사용을 권장하지 않으며, 검사 기능을 린터에 추가하십시오.

이들 각각은 서로 다른 상황에서 적용됩니다.


1

패키지 또는 라이브러리 레벨에서이를 관리합니다. 패키지를 제어하고 가시성을 제어합니다. 가시성을 자유롭게 철회 할 수 있습니다. 나는 이것을 대기업에서 내부적으로 보았으며 패키지가 오픈 소스이거나 무료로 사용 되더라도 패키지 소유권을 존중하는 문화에서만 의미가 있습니다.

고객 팀은 단순히 아무것도 바꾸고 싶지 않기 때문에 항상 지저분합니다. 따라서 특정 고객과 협력하여 마이그레이션 마감 기한에 동의하여 지원을 제공 할 때 화이트리스트 만 필요합니다.


나는 지원 부분을 좋아한다. 모든 변화는 더 매끄럽고, 즐겁고, 어려울 것입니다. 그것은 부분적으로 심리적 효과입니다. 좋은 지원은 협조적입니다. 관련된 모든 것이 심각합니다. 대조적으로, 위와 관련없이 위로부터 부과 된 변경은 무시되고 비협조적인 느낌을줍니다. (친절 함은 끊임없는 드라이브와 짝을 이루어야하지만 변화를
Peter A. Schneider

1

한 가지 요구 사항은 빌드에 시간 개념을 도입하는 것입니다. C와 같은 전 처리기 1 을 사용하는 C, C ++ 또는 기타 언어 / 빌드 시스템 에서 빌드 타임에 전처리기에 대한 정의를 통해 타임 스탬프를 도입 할 수 CPPFLAGS=-DTIMESTAMP()=$(date '+%s')있습니다. 이것은 아마도 makefile에서 일어날 것입니다.

코드에서 토큰을 비교하고 시간이 초과되면 오류가 발생합니다. 함수 매크로를 사용하면 누군가가 정의하지 않은 경우를 잡을 수 TIMESTAMP있습니다.

#if TIMESTAMP() == 0 || TIMESTAMP() > 1520616626
#   error "The time for this feature has run out, sorry"
#endif

또는 때가되면 문제의 코드를 간단히 "정의"할 수 있습니다. 아무도 사용하지 않으면 프로그램을 컴파일 할 수 있습니다. "api.h"라는 api를 정의하는 헤더가 old()있고 특정 시간 이후에는 전화를 걸 수 없습니다 .

//...
void new1();
void new2();
#if TIMESTAMP() < 1520616626
   void old();
#endif
//...

비슷한 구조는 아마도 old()일부 소스 파일에서 함수 본문을 제거했을 것입니다 .

물론 이것은 바보의 증거가 아닙니다. TIMESTAMP다른 곳에서 언급 된 금요일 밤 긴급 구조의 경우 단순히 오래된 것을 정의 할 수 있습니다 . 그러나 그것은 오히려 유리하다고 생각합니다.

이 기능은 라이브러리 를 다시 컴파일 할 때만 작동합니다. 그 후에는 더 이상 사용되지 않는 코드가 더 이상 라이브러리에 존재하지 않습니다. 그래도 클라이언트 코드가 더 이상 사용되지 않는 바이너리에 연결되는 것을 막을 수 는 없습니다 .


1 C #은 숫자가없는 전 처리기 기호의 단순한 정의 만 지원하므로이 전략을 실행할 수 없습니다.


또한이 전 처리기 정의는 TIMESTAMP모든 빌드에서 사용 되는 모든 코드를 강제 로 다시 컴파일 해야한다는 점에 주목할 가치가 있습니다. 또한 같은 도구를 사용할 수 없게됩니다 ccache. 이는 증분 빌드의 일반적인 컴파일 시간이 이러한 방식으로 더 이상 사용되지 않는 기능에 의해 영향을받는 코드베이스의 양에 따라 크게 증가 함을 의미합니다.
mindriot

@mindriot 그것은 흥미로운 측면입니다. 나는 그것이 코드에 시간 개념을 도입하는 모든 방법에서 사실이라고 생각합니다-OP는 명시 적으로 "특정 날짜가 지난 후"라고 말했습니다. 그래도 빌드 시스템의 시간 측면을 처리하고 코드 만 그대로 둘 수 있습니다. 그러나 OP는 명시 적으로 "코드에 넣은 것"을 요구했다. 내 솔루션은 특정 빌드 방법과 독립적이라는 이점이 있습니다. 속일 수는 있지만 어떤 식 으로든 수용해야합니다.
피터 A. 슈나이더

당신 말이 맞아요 귀하의 솔루션은 본질적으로 OP의 실제 질문에 대한 실질적인 솔루션을 제공하는 유일한 솔루션 입니다. 그럼에도 불구하고 단점을 지적하는 것이 중요하다는 것을 알았습니다. 찬반 양론을 측정하는 것은 OP에 달려 있습니다. TIMESTAMP예를 들어 86400으로 값을 나누어서 매일 세분성을 확보하고 다시 컴파일하는 횟수를 줄이면 건강한 중간 지점을 달성 할 수 있다고 생각합니다 .
mindriot

0

Visual Studio에서는 특정 날짜 이후에 오류를 발생시키는 사전 빌드 스크립트를 설정할 수 있습니다. 컴파일이되지 않습니다. 2018 년 3 월 12 일 이후에 오류를 발생시키는 스크립트는 다음과 같습니다 ( 여기에서 가져옴 ).

@ECHO OFF

SET CutOffDate=2018-03-12

REM These indexes assume %DATE% is in format:
REM   Abr MM/DD/YYYY - ex. Sun 01/25/2015
SET TodayYear=%DATE:~10,4%
SET TodayMonth=%DATE:~4,2%
SET TodayDay=%DATE:~7,2%

REM Construct today's date to be in the same format as the CutOffDate.
REM Since the format is a comparable string, it will evaluate date orders.
IF %TodayYear%-%TodayMonth%-%TodayDay% GTR %CutOffDate% (
    ECHO Today is after the cut-off date.
    REM throw an error to prevent compilation
    EXIT /B 2
) ELSE (
    ECHO Today is on or before the cut-off date.
)

이 스크립트를 사용하기 전에이 페이지의 다른 답변을 읽으십시오.


-1

나는 당신이하려는 일의 목표를 이해합니다. 그러나 다른 사람들이 언급했듯이 빌드 시스템 / 컴파일러는 아마도 이것을 시행하기에 적합한 장소가 아닐 것입니다. 이 정책을 시행하기위한보다 자연스러운 계층은 SCM 또는 환경 변수라고 제안합니다.

후자를 수행하는 경우 기본적으로 사용 중단 사전 실행을 표시하는 기능 플래그를 추가하십시오. 더 이상 사용되지 않는 클래스를 구성하거나 더 이상 사용되지 않는 메소드를 호출 할 때마다 기능 플래그를 확인하십시오. 하나의 정적 함수를 정의하고 assertPreDeprecated()더 이상 사용되지 않는 모든 코드 경로에 추가하십시오. 설정된 경우 어설 션 호출을 무시하십시오. 예외가 발생하지 않는 경우 날짜가 지나면 런타임 환경에서 기능 플래그를 설정 해제하십시오. 더 이상 사용되지 않는 코드 호출은 런타임 로그에 표시됩니다.

SCM 기반 솔루션의 경우 git 및 git-flow를 사용한다고 가정합니다. 그렇지 않은 경우 논리는 다른 VCS에 쉽게 적용 할 수 있습니다. 새 분기를 만듭니다 postDeprecated. 해당 분기에서 더 이상 사용되지 않는 코드를 삭제하고 컴파일 될 때까지 참조 제거 작업을 시작하십시오. 모든 정상적인 변경 사항은 master지점에 계속 적용됩니다 . 의 비 사용되지 관련 코드 변경 병합 유지 master에 다시 postDeprecated통합 문제를 최소화 할 수 있습니다.

지원 중단 날짜가 끝난 후에서 새 preDeprecated분기를 만듭니다 master. 그런 다음에 postDeprecated다시 병합하십시오 master. 릴리스가 master지점을 벗어나는 것으로 가정하면 이제 날짜 이후에 더 이상 사용되지 않는 지점을 사용해야합니다. 응급 상황이 발생하거나 시간 내에 결과를 전달할 수없는 경우 언제든지로 롤백하고 preDeprecated해당 지점에서 필요한 사항을 변경할 수 있습니다.


7
그 접근법은 물류 악몽처럼 들립니다. 거의 중복 된 병렬 분기를 유지 관리하기 시작하면 모든 시간을 소비하게됩니다. 총 폐기물.
궤도

6
더 이상 사용되지 않는 기능을 실제로 제품에서 제거하기 전에 여러 버전을 제거하기 위해 하나를 사용하여 병렬 분기를 유지 관리하는 것이 어떤 방식 으로든 "산업 표준"이라는 데 동의하지 않습니다. 그 목적은 무엇입니까? 예, VCS는 자동으로 일부 병합을 수행 할 수 있지만 논리적 충돌을 해결하기 위해 개발자의 눈 으로 병합 수행 해야 합니다 (그리고 어휘 적으로 해결할 수없는 충돌이 발생하면 어떻게됩니까?). 이를 위해 매일 빌드 시스템을 임의로 병합하는 것은 무의미합니다. 제거 할시기가되면 기능을 제거하십시오.
궤도

3
릴리스 브랜치를 유지해야 할 이유가 있기 때문입니다 (중요 패치를 백 포트). "나중에 내가 할 수있는 일"을 유지해야 할 이유는 없습니다. 이점이없는 오버 헤드입니다. 그렇게 간단합니다.
궤도에서 가벼움 경주

4
어디서 구했습니까? 말 그대로 사용 중단의 정의입니다. 나중에 제거 할 수있는 것을 사용하지 않습니다. 따라서 불일치, 목표 게시물의 이동 및 확실히 "논쟁을 이길"물건을 만들지 않습니다. 이것은 내가 일하고 싶은 조직에서 "SCM 분기의 교과서 사용 사례"가 아닙니다! 동의하지 않으면 동의해야한다고 생각합니다. 좋은 밤 보내요!
궤도에서 가벼움 경주

2
@lightness-공식적으로 폐기 된 코드가 단순히 "우리 갈 때마다 할 있는 것"이 아닌 많은 이유가 있습니다 . 더 이상 사용되지 않는 코드는 공식 지원이 중단되는 라이브러리를 사용합니다. 더 이상 사용되지 않는 코드는 고정 날짜 후에 라이센스가 만료되는 IP 일 수 있습니다. 주어진 날짜 이후에 새로운 규정이 있으며 코드가 호환되지 않을 수 있습니다. 상아탑에 살면 솔루션이 모두 훌륭합니다. 그러나 실제 조직은 항상 이러한 유형의 상황을 처리합니다. 소프트웨어는 비즈니스 요구를 충족시켜야하며 그 반대도 아닙니다.
user79126
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.