프로덕션 시스템의 재사용 및 회귀 테스트 비용과 관련된 소프트웨어 엔지니어링 원칙이 있습니까?


12

저는 연금 및 투자를 돌보는 은행을 위해 대규모 금융 거래 시스템에서 일했습니다. 15 년간의 기능 변경 후 수동 회귀 테스트 비용은 릴리스 당 2 억 달러로 상승했습니다. (1 천만 LOC, 매일 천만 달러 거래). 이 시스템은 또한 회사 주변의 19 개 다른 시스템과 인터페이스하여 많은 양의 데이터를 이동시킵니다. 이 시스템은 Java로 구현되었습니다.

그러나 우리가 관찰하는 것은 '재사용'이 많을수록 회귀 테스트 비용이 증가한다는 것입니다. ( "터치 한 코드를 테스트해야"하고 재사용 / 공유 코드는 터치 할 때 여러 위치에 영향을 미칩니다. 따라서 '건조-반복하지 마십시오'에도 불구하고 코드를 복사하여 붙여 넣지 마십시오. -코드 복사 및 붙여 넣기에 대한 재정적 인센티브를 관찰합니다. 이것은 회귀 테스트 비용을 낮추기위한 것입니다. 공유 할 수있는 코드를 수정하고 싶지 않기 때문에 회귀 테스트에 큰 영향을 미치기 때문입니다.)

내 질문은 재사용 및 회귀 테스트 비용 간의 관계를 설명하는 소프트웨어 엔지니어링 원칙이 있습니까?

내가이 질문을 한 이유는 시스템을 테스트 할 작은 부품으로 분해 할 때 비용 이점이 있기 때문이다.

가정 :

  1. '회귀 테스트'는 '허용 테스트'를 의미합니다. 즉, 다른 그룹은 환경 및 데이터 설정을 포함하여 비즈니스를 대신하여 시스템에 대해 새 테스트를 작성하고 기존 테스트를 재사용하는 데 시간을 소비합니다.

  2. 큰 회귀 테스트 비용에 대한 무자비한 반응은 '보다 자동화 된 테스트'라는 것을 알고 있습니다. 이것은 좋은 원칙입니다. 이 환경에는 몇 가지 과제가 있습니다.

    (a) 자동화 테스트는 시스템의 자동화 테스트 범위가 높지 않으면 시스템 경계에서 유용하지 않습니다. (영향의 구체).

    (b) 시스템이 이미 크고 복잡 할 때 높은 자동화 된 테스트 적용 범위에 프로그래머 시간이나 자본 투자에 대한 모멘텀을 얻는 것은 문화적으로 어렵습니다.

    (c) 자동화 된 테스트 유지 비용은 프로젝트에서 숨겨져 있으므로 프로젝트 수준에서 쉽게 폐기됩니다.

    (d) 이것은 은행에서 일하는 문화적 현실 일 뿐이다.

    (e) 나는이 문제를 다른 방법으로 분해하기 위해 노력하고 있습니다 (분해).


2
우리가 더 '재사용'할수록 [수락] 테스트 비용이 더 많이 든다는 것을 관찰하고 […] 관찰 할 수 있습니다. 승인 테스트가 상속 계층 구조와 같은 구현 세부 사항을 무시하고 대신 사용 시나리오를 통해 재생해서는 안됩니까?
amon

2
귀하의 질문은 흥미롭지 만 "재사용은 OO의 결과"또는 @amon 부분과 같은 매우 편향된 가정을 포함합니다. 핵심 질문은 프로그래밍 언어 또는 OO 프로그래밍과 무관하므로 "OO"부분을 완전히 삭제하는 것이 좋습니다. 그리고 어떤 종류의 "재사용"을 염두에두고 있는지는 확실하지 않습니다. "재사용"은 광범위한 용어입니다. 복사-붙여 넣기 재사용은 구성 요소 또는 라이브러리 재사용과 다릅니다.
Doc Brown

도움이되었습니다. OO에 대한 참조를 제거하고 공유 코드 (또는 공유 코드가 될 코드)를 만지는 아이디어를 확장했습니다.
hawkeye

1
현재의 형태로, 나는 당신의 질문에 단지 "아니, 나는 그렇게 생각하지 않는다"라고 대답 할 것입니다-나는 당신에게 매우 만족스럽지 않을 것이라고 생각합니다. 또는 자체 제작 한 재사용 가능한 구성 요소로 시스템과 같은 큰 시스템을 구축 할 때 실제로 테스트 비용을 줄이는 원칙과 관행에 관심이 있습니까?
Doc Brown

답변:


11

공유 할 수있는 코드를 수정하고 싶지 않습니다. 큰 회귀 테스트에 영향을 미치기 때문입니다.

위의 소리가 내게 맞습니다. 코드가 중요할수록 코드가 더 많이 공유 될수록 품질 요구 사항이 높아질수록 변경 될 때 더 많은 품질 보증이 필요합니다.

시스템이 Java로 구현되었으므로 Java 표준 라이브러리 (JDK)에서 바로 위의 예를 볼 수 있습니다. 주요 릴리스는 드물며 테스트에 많은 노력이 소요됩니다. 그리고 마이너 릴리스조차도 매우 포괄적 인 JCK 테스트 스위트를 통해 회귀가 없는지 확인합니다.

이것이 공유 코드의 진화를 방해한다고 생각할 수도 있습니다. 그렇습니다. 코드 변경과 관련된 영향과 위험이 많을수록 코드 변경에 대해주의를 기울여야하며 릴리스 테스트에 더 많은 노력이 필요합니다.

이상적으로 광범위하게 공유 된 코드의 릴리스 품질은 큰 변화가 전혀 필요하지 않은 수준이어야합니다 (드물게 개선되는 경우를 제외하고 저장). 이 생각은 Joshua Bloch유명한 인용문에 반영됩니다 .

다이아몬드와 같은 공개 API는 영원합니다. 당신은 그것을 올바르게 얻을 수있는 기회가 있으므로 최선을 다하십시오.


위에서 말했듯이, 당신이 설명하는 문제 중 일부는 비효율적 인 공유 코드 개발 전략으로 인한 것 같습니다. 특히, 재사용 코드의 경우이 코드를 복제하거나 즉시 "핵심"공유 라이브러리에 포함하는 두 가지 옵션 만 고려되는 것이 특히 문제가됩니다.

이 두 가지 옵션으로 만 제한하는 것은 불필요하며 다시 사용하는 JDK에서 더 잘 수행 할 수있는 방법에 대한 예를 찾을 수 있습니다. java.util.concurrent패키지 ( JSR 166 )를 살펴보십시오. Java 5 릴리스까지는 JDK 릴리스의 일부가 아닌 별도의 라이브러리였습니다.

생각해보십시오. 이것은 여러분이 간과 한 세 번째 옵션이며 상당히 실용적인 방법으로, 새로운 공유 코드의 "시작"에서 고려해야하는 옵션입니다. 2-3 개의 구성 요소간에 공유 할 수있는 일부 코드 만 파악 하면 시스템의 핵심 API에 해당 코드 를 즉시 포함시킬 수 있습니다.

이 "미성숙 한"공유 코드를 Java 동시 유틸리티와 마찬가지로 별도의 라이브러리로 패키지하고 릴리스 할 수 있습니다. 이 방법을 사용하면 비교적 적은 양의 관련 구성 요소 만 사용할 수 있으므로 전체 회귀 테스트가 필요 없습니다. 결과적으로이 공유 코드를 수정 및 개선하고 프로덕션 환경에서 작동 방식을 테스트 할 여지가 더 많습니다.

라이브러리가 성숙하고 안정화되면 추가 변경이 거의 없을 것이라는 확신을 갖게되면 동시 유틸리티가 JDK에 포함 된 것처럼 시스템의 핵심 라이브러리에 포함시키는 것을 고려할 수 있습니다.


재사용도가 높은 코드를 변경하는 데 얼마나 많은 노력 (테스트 포함)이 포함될 수 있는지에 대한 구체적인 예는 JDK에서 다시 찾을 수 있습니다. 릴리스 7u6에서는 성능 String변경과 관련된 내부 표현을 변경했습니다 substring. Reddit의 기능 개발자의 의견은 이 변경에 얼마나 많은 노력이 참여했는지를 설명합니다.

초기 분석은 2007 년에 GC 그룹에서 나왔습니다.

내부적으로 Oracle 성능 팀은 성능 변화를 평가하는 데 사용하는 대표적이고 중요한 앱 및 벤치 마크 세트를 유지 관리합니다. 이 앱 세트는 부분 문자열 변경을 평가하는 데 중요했습니다. 성능의 변화와 설치 공간의 변화를 면밀히 살펴 보았습니다. 필연적으로 중대한 변화의 경우와 마찬가지로 일부 앱에는 회귀가 있었으며 다른 앱에는 이득이있었습니다. 성능이 여전히 수용 가능하고 정확성이 유지되는지 확인하기 위해 회귀 분석을 조사했습니다.

제 답변은 철저한 것이 아니라 거의 6 개월 동안 헌신적 인 작업에 대한 간략한 요약입니다 .


우리 둘 다 비슷한 생각을 많이하면서 동시에 대답을 한 것 같습니다 ...
Doc Brown

그래 @DocBrown, 그것은 질문 형태로 편집 한 후, 우리는 또한 한 시간 정도, 거의 동시에 응답 한 흥미로운
모기

9

"회귀 테스트 비용 / 재사용 된 코드의 LOC 계산"에 대한 메트릭이 없다고 생각합니다. 그리고 나는 누군가가 동일한 "큰"시스템을 두 번, 많은 재이용 가능한 구성 요소가있는 버전과 그에 대한 진지한 연구를하기 위해 하나의 버전을 구축하기 위해 많은 시간과 돈을 투자 한 적이 없다고 생각합니다.

그러나 나는 당신과 같은 재사용으로 인한 문제를 보았으며 아마도 이것을 더 잘 처리하는 방법에 대한 생각에 관심이있을 것입니다.

첫째, 실제로 재사용 하는 것이 아니라 문제입니다. 재사용 가능한 구성 요소를 직접 작성하여 시스템 전체에서 사용하려는 시도입니다. 문제가 발생하지 않는 큰 소프트웨어 패키지를 많이 재사용하고 있다고 확신합니다. 사용중인 전체 Java 스택 또는 일부 타사 구성 요소 (해당 구성 요소에 만족한다고 가정)를 생각하십시오. 그러나 Java 라이브러리와 같은 소프트웨어와 다른 점은 있지만 재사용 가능한 자체 구성 요소로 인해 추가 회귀 테스트 비용이 많이 발생합니까? 다음은 내가 생각할 수있는 몇 가지 사항입니다.

  • 그 구성 요소는 매우 성숙하고 안정적입니다

  • 그들은 완전히 다른 조직에 의해 독립적으로 개발되고 완전히 테스트되었습니다.

  • 그것들을 (재) 사용하기 위해, 그것들을 변경할 필요가 없습니다 (사실 소스 코드를 유지하지 않기 때문에 원하는 경우에도 할 수 없습니다)

  • 매일 새 버전을 얻지 못하고, 작은 업데이트 만 (최대 한 달에 한 번) 또는 주요 업데이트를 매년 간격으로받습니다.

  • 대부분의 업데이트는 100 % 하향 호환, 특히 작은 업데이트와 호환되도록 설계되었습니다

따라서 자신의 재사용 가능한 구성 요소를보다 성공적으로 만들려면 위의 내용 중 일부를 자신의 개발에 맞게 조정해야합니다.

  • 재사용 가능한 구성 요소의 경우 유지 관리 담당자에게 명확한 책임을 맡고 구성 요소를 재사용하는 모든 사람이 문제가 발생할 경우 즉시 버그 수정을받을 수 있는지 확인하십시오.

  • 엄격한 버전 관리 및 릴리스 정책을 설정합니다. 재사용 가능한 구성 요소를 진화시킬 때 매일 "모든 사람에게"릴리스하지 마십시오 (적어도 시스템에서 2 억 달러의 회귀 테스트를 실행해야한다는 의미는 아닙니다). 대신 새 버전을 수시로 게시하고 해당 구성 요소의 사용자가 새 버전의 변경 사항을 연기 할 수있는 메커니즘을 제공하십시오.

  • 구성 요소를 자주 재사용할수록 안정적인 인터페이스와 하향 호환되는 동작을 제공하는 것이 중요합니다.

  • 재사용 가능한 구성 요소는 독립적으로 테스트하기 위해 매우 완벽한 테스트 스위트가 필요합니다.

이러한 것들이 많으면 구성 요소 자체를 구축하는 데 드는 비용이 증가하지만 회귀 실패로 인한 변경 비용이 감소한다는 의미입니다.


0

더 많은 테스트가 필요하기 때문에 비용이 "상당히"증가 할 수 있지만, 이러한 유형의 리팩토링은 일반적으로 시스템의 기술적 부채를 줄일 때 코드를보다 유지 보수하기 쉽게 만듭니다.

이를 통해 향후 버그를 줄이고 새로운 기능을 구현하거나 기존 기능을 쉽게 구현할 수 있습니다.

더 쉽게 말하면 시간이 덜 걸리므로 비용이 적게 든다는 의미입니다.

줄어드는 것이 쉽고, 더 쉽고, 덜 어려워서 여기에 미래의 저축 (또는 저축을 희망하는)은 아직 일어나지 않았기 때문에 계산이 불가능합니다.

코드 기반이 단순하면 신규 직원이나 기존 직원이 프로젝트를 진행할 때 특히 대규모 시스템의 속도가 빨라집니다.

또한 기존 프로젝트 멤버의 사기를 개선 할 수있는 직원 이직률을 줄일 수 있습니다.

물론 이러한 이점을 얻을 수 있다고 보장 할 수는 없지만 측정 할 수있는 비용 (예 : 테스트 증가)과 함께 고려해야 할 사항입니다.

사실, 코드 내용이 좋을수록 초기 비용이 증가하더라도 코드가 향상되면 결국 테스트 비용이 줄어 듭니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.