일상/IT

리팩토링에서의 대담함

얇은생각 2023. 8. 27. 07:30
반응형

레거시 프로젝트

어려운 부분은 레거시 프로젝트의 코드를 터치하는 것입니다. 컨설턴트로서 자주 그렇게 해야 했습니다. 백만 줄의 코드가 있는 프로젝트에 들어가 리팩토링을 시작합니다.

좋은 점은 우리가 모두 비슷하다는 것입니다. 프로젝트를 만든 엔지니어들은 비슷한 책과 비슷한 사고 과정을 통해 훈련을 받았습니다. 그들의 논리를 이해하면 그들이 왜 무엇을 했는지 이해할 수 있습니다. 하지만 어려움의 대부분은 도구에 있습니다. 20년 전에 만들어진 프로젝트는 더 이상 사용할 수 없는 도구를 사용했습니다. 이 코드는 더 이상 현대 IDE에서 컴파일되지 않을 수도 있습니다. 우리의 즉각적인 반응은 오래된 IDE와 오래된 도구를 사용하는 것입니다.

 

 

리팩토링에서의 대담함

 

 

그건 실수 

오래된 도구는 오래된 비트를 썩게 합니다. 지금은 기회입니다. 프로젝트를 다시 방문하고 도구를 업데이트하십시오. 몇 년 전에 나는 이전 C++ 코드베이스를 위해 몇 가지 작업을 했습니다. 코드베이스를 이해하지 못했지만 원래 개발자들은 비주얼 스튜디오의 이전 버전에서 만들었습니다. LLVM VS 코드로 맥에서 작동하도록 하는 것은 움직이는 조각을 더 명확하게 시각화하는 데 도움이 되었습니다. 일단 디버거를 실행하고 나면 버그와 이상한 문제를 수정하는 것은 사소한 일이 되었습니다. 내가 그 코드베이스를 완전히 이해했다고 말할 수는 없습니다. 그러나 도구를 포팅하고 업데이트하는 과정은 많은 뉘앙스와 문제에 노출되었습니다.

 

 

할 수 없을 때

반대로 기존의 레거시 시스템이 고객 요구사항인 경우를 들 수 있습니다. 저는 외부 블랙박스인 레거시 시스템과의 통합을 구현해야 했습니다. 코드를 터치할 필요는 없었지만 이러한 시스템과 인터페이스하고 그들의 행동에 의존해야 했습니다. 이것은 매우 어려운 상황입니다.

그러한 경우에 대한 우리의 해결책은 다양한 시나리오를 시뮬레이션하고 테스트할 수 있도록 시스템의 모의실험을 만드는 것이었습니다. 그러한 상황 중 하나에서, 우리는 간단한 레코더를 만들기 위해 요청을 보내고 "블랙박스"의 응답을 저장하는 앱을 작성했습니다. 그런 다음 우리는 구현에서 테스트의 기초로 녹음을 사용했습니다. 때때로 블랙박스는 생산에 직접 연결되기 때문에(한 경우 주식 시장에 직접 연결되기 때문에) 이것은 옵션이 아닐 수 있습니다.

그런 블랙박스를 다루는 나의 규칙은 다음과 같습니다:

하나의 고립된 모듈이 모든 연결을 처리합니다. 이를 통해 장애에 대한 균일한 해결책을 구축할 수 있습니다. 이 특정한 경우에 이상적인 물리적으로 격리된 마이크로 서비스를 사용할 수 있습니다.

비동기 호출을 사용하여 결과 노출 - 기존 시스템의 교착 상태와 과부하를 방지합니다. 장애가 발생하면 결과 콜백이 호출되지 않으므로 대기열을 사용하여 장애의 원인을 매핑하고 오류 처리가 더 간단해집니다.

우리는 방어적으로 코딩해야 합니다. 회로 차단기, 로깅 및 일반 관찰 도구를 사용합니다. 이 프로젝트에서 가장 논쟁적인 부분이 될 것이기 때문에 모든 구석에서 실패를 예상합니다.

일단 그 레거시를 포장하면 실패에 대한 경고를 트리거해야 합니다. 일부 실패는 사용자 인터페이스에 버블업되지 않고 성공한 재시도를 트리거할 수 있습니다. 이는 심각한 문제가 될 수 있습니다. 예를 들어 주식 시장 구매 명령이 실패한 경우 거래자가 재시도를 눌러 새로운 성공 명령을 발행할 수 있습니다. 그러나 원래 명령은 레거시 시스템에서 암묵적으로 재시도할 수 있으며 두 개의 구매로 끝날 수 있습니다.

그러한 실수는 비용이 많이 들고 블랙박스에서 비롯될 수 있습니다. 레거시 코드를 완전히 검토하고 이해하지 못하면 보장할 수 없습니다. 우리가 할 수 있는 일은 이러한 유형의 실패에 신속하고 정확하게 대응하는 것입니다. 이러한 상황에서는 디버깅성이 중요하므로 이러한 블랙박스에서는 관찰 가능성과 격리가 중요합니다.

 

 

관측 가능성을 통한 신뢰도

과거에는 새로운 릴리스를 누를 때마다 서버 로그를 보곤 했습니다. 사용자 불만이 쏟아지기를 기다리고 있습니다. 관찰 가능성 덕분에 우리는 프로덕션의 문제에 대해 처음 알게 되었습니다. 관찰 가능성은 스크립트를 뒤집었습니다.

불행하게도, 문제에 대해 알고 이해하는 것과 문제를 수정하는 것, 그리고 인식하는 것 사이에는 큰 차이가 있습니다. 우리가 관찰 가능성 콘솔을 보면 문제를 강조하는 이상 징후를 발견할 수 있지만 회귀가 발생하더라도 경고를 트리거하지 않을 수 있습니다. 그 좋은 예는 계산 착오일 수 있습니다. 응용 논리를 변경하면 잘못된 결과가 보고될 수 있으며 이는 관찰 가능성 데이터에 표시될 가능성이 거의 없습니다.

이론적으로, 테스트는 그 문제를 발견했어야 했지만, 테스트는 우리가 예측한 일이 일어나지 않았다는 것을 검증하는 데 매우 뛰어납니다. 예를 들어, 우리는 재무 계산을 위해 필드 크기를 할당할 수 있고 그것은 미국에 기반을 둔 우리의 개발자들에게 매우 효과적이었습니다. 그러나 엔에서 일하는 일본의 고객은 훨씬 더 많은 수를 가지고 있고 그 한계 때문에 회귀를 경험할 수 있습니다.

개발자 관측 도구로 그러한 문제를 디버깅할 수 있지만 레거시 시스템을 깊이 통합할 때 관측 계층이 문제를 알 수 있는 방식으로 페일 패스트 원리를 깊이 적용해야 합니다. 기대를 주장하고 테스트가 아니라 생산 코드의 조건을 확인해야 합니다. 여기서 실제 오류는 은밀한 버그보다 나을 것입니다.

언어의 null이 아닌 기능에 많은 초점이 맞춰졌습니다. 하지만 계약에 의해 설계의 에펠과 같은 언어로 개척된 개념은 구식이 되었습니다. 이해할 수 있습니다. 그런 종류의 코드를 작성하는 것은 어렵고 어색합니다. 체크된 예외는 종종 자바 언어의 가장 싫어하는 특징입니다. 모든 입력에 대해 기대하는 모든 제약 조건을 작성해야 한다고 상상해 보세요.

환경 상태에 대한 의존성은 말할 것도 없습니다. 이것은 유지 가능하지 않으며 이 체크인 런타임을 시행하는 것은 훨씬 더 비용이 많이 들 것입니다. 그러나 이것은 우리가 의식적으로 모듈 또는 마이크로서비스의 진입 지점에서 할 수 있는 일입니다. 결과의 예측할 수 없는 특성 때문에 레거시 시스템과 통합할 때 실패-빠른 원리는 필수적입니다.

반응형