디버거의 숨겨진 함정

"Debugging is like being the detective in a crime movie where you are also the murderer." - Filipe Fortes


그것은 어떻게 시작되었는가: 거짓된 환각


내가 첫 번째 프로그래밍 경험을 가지고 있을 때, 나는 디버거를 사용할 가능성을 전혀 몰랐다.
공교롭게도 나는 왜 나의 소프트웨어가 예상대로 작동하지 않았는지 이해해야 한다. 그래서 나는 무슨 일이 일어났는지 이해해야 한다. 유일한 방법은 코드 주위에 프린터 문장을 추가하는 것이다.
나중에 나는 디버거를 도구로 삼아 변수를 검사하고 소프트웨어가 특정 시간 동안의 상태를 이해할 수 있다는 것을 알게 되었다.
생각

"I can troubleshoot without adding new code!!
I will be faster than before!"


어떻게 지내십니까


여러 해 동안, 나는 많은 복잡한 프로젝트를 했고, 거의 완전히 생각을 바꾸었고, 디버거가 실제로 나를 늦추었다는 것을 깨달았다.
명확하게 말하자면, 나는 여전히 소수의 특정한 간단한 상황에서 디버거를 이용하는 것이 가치가 있다고 생각하지만, 복잡한 상황에서 나는 더욱 좋은 대체 방안이 있다고 생각한다.
무슨 일이 있었죠?
나는 디버거가 문제를 해결하는 유일한 방법이라고 생각해서 줄곧 그것을 사용하고 있다.
만약 내가 가장 긴장된 업무 시간으로 돌아간다면, 거의 모든 시간이 내가 코드를 이해하려고 했을 때, 몇 시간 동안 긴 디버깅 세션에서 대량의 코드 줄 변수와 창고 추적을 검사했다.
너는 네가 가장 긴장한 근무 시간을 기억하니?
너는 그 순간에 네가 장시간 디버깅을 하고 있었는지 기억하니?
아마도 너는 당시에 시도하고 있었을 것이다escape the legacy code matrix. 그러나 너는 1단계에 갇혔다. 이해 단계.

함정은 어디에 있습니까?


복잡한 용례에서 디버거를 사용하면 실제적으로 우리의 속도를 늦추고 우리의 스트레스와 인지적 부담을 증가시킬 수 있다고 생각하는 이유를 공유할 것이다
1. 학습 코드 포기
디버거를 사용하는 것은 자동차를 위해 네비게이션을 사용하는 것과 같다.그것은 실제로는 너에게 도움이 되지만, 때로는 어떤 원인 때문에, 그것은 작용하지 않는다. 그것이 발생할 때, 너는 방향을 완전히 잃게 된다. 왜냐하면 너는 경로를 모르기 때문이다.
곧 뛰어올라 코드 학습을 막고 읽기와 역방향 공학 기술을 향상시킨다.
이런 기술은 다른 사람이 쓴 점점 더 많은 코드를 읽어야만 얻을 수 있다.네가 많이 할수록, 너는 더욱 잘 그것을 이해할 수 있다.어떤 경우 디버거의 사용에 의존할 수 없기 때문에 대체안이 가장 좋다는 것을 기억하십시오.
2. 수동 조작
대량의 코드 줄과 변수를 검사하려면 수동적이고 매우 반복적인 조작이 필요하다. 예를 들어 단점을 설치하고 내부 함수를 입력하며 다음 줄로 넘어가거나 변수를 검사하고 시계를 추가하는 등이다.
수동 조작은 컴퓨터가 실행할 수 있는 자동 조작보다 훨씬 느리다.
많은 가변값과 응용 프로그램 상태를 기억하려면 높은 인지적 부하와 에너지가 필요하다.
3. 반복 동작
다음 유형의 차원 구조를 가지고 있다고 가정하십시오
data class University(val departments: List<Department>)

data class Department(val courses: List<Course>)

data class Course(val students: List<Student>)

data class Student(val name: String, val country: Country)

enum class Country {
    ITALY,
    SPAIN,
    FRANCE
}
너는 한 대학에 이탈리아에서 온 학생이 있는지 여러 번 검사해야 한다
매번 대학 학생의 나라를 검사해야 할 때, 최소한 다섯 번의 클릭, 변수 검사, 필기, 가치관 기억 등 다섯 가지 동작을 해야 한다
만약 네가 10번을 해야 한다면, 너는 50번의 클릭이나 디버거 검사를 해야 한다.
다른 방법은 다음과 같은 함수를 작성하는 것이다
fun logItalianPresenceInUniversity(university: University)
당신이 검사하고 싶은 내용을 인쇄하세요.몇 단락의 추가 코드만 작성하면 한 번만 누르면 결과를 실행하고 검사할 수 있습니다.
3. 시험에 대한 신뢰 부족
어떤 사람이 말하다

"A bug is just a missing test"


우리가 테스트하는 목적은 시스템의 행동을 정의하고 문제를 발견하는 데 도움을 주는 것이다.
디버깅을 통해 문제를 검사하는 또 다른 방법은 새로운 테스트를 추가해서 문제를 재현하는 것이다.
지금 만약에 우리가 디버거를 통해 버그를 발견한다면 우리는 트랩을 호출해서'테스트 세트가 나에게 도움이 되지 않기 때문에 나는 복구를 하고 테스트를 잊어버릴 것이다'고 생각할 수 있다.
그래서 저희가 이 위험한 순환에 들어갈 수도 있어요.

하나의 예시 사례: 많은 데이터 변환을 가진 마이크로 서비스


하나의 서비스가 요구를 충족시키기 위해 다른 서비스를 호출해야 하는 사용자에게 일부 기능을 공개할 것을 구상하다
복잡한 상황에서 controller와 다른 서비스에 대한 호출 사이에는 많은 데이터가 적응되어 있다

현재, 이 서비스에 버그가 있고, 외부 서비스에서 받은 일부 정보가 컨트롤러와 사용자에게 전송되지 않았다고 가정합시다.
너의 임무는 그것을 발견하고 복원하는 것이다. 너는 많은 적응층에 깊이 들어가야 한다.
당신은 어떤 선택이 있습니까?
1: 코드의 모든 세부 사항을 이해하고 기록한다
가장 안전한 선택은 코드를 자세히 읽고 이해하려 하며 필기를 하고 부족한 부분을 찾아내는 것이다.
이 옵션은 좋지만 코드 구조를 깊이 연구하는 데는 많은 시간과 정력이 필요할 것이다.유류 시스템에서나 시간이 많지 않을 때, 이것은 끊임없는 과정이 될 수 있다.다른 한편, 장기적으로 보면 코드를 읽는 능력을 향상시킬 수 있다.
2: 애플리케이션을 디버거와 함께 사용
우리는 컨트롤러와 클라이언트에 단점을 설정한 후에 응용 프로그램을 사용할 수 있다.
우리의 예에는 많은 적응층이 있는데, 이것은 많은 시간을 들여 세션을 디버깅하고 많은 정력을 들일 것이다.
평범하지 않은 상황에 대해서는 이런 방법이 최악일 수도 있다.
3: 코드에 탐색기가 있는 프로그램 사용하기
여기서 너는 무슨 뜻인지 알아맞힐 수 있다.
수동으로 디버거가 실행하도록 요구하는 동작을 자동으로 검사하기 위해 작은 탐지 함수를 작성할 수 있습니다.위에서 설명한 logItalianPresenceInUniversity 함수를 기억하십니까?
이런 상황에서 나 개인의 방법은
1. 검사할 코드 세그먼트의 시작과 끝을 확인합니다
이 경우 컨트롤러와 클라이언트
2. 탐지 함수를 작성하여 자동 검사
예를 들어 함수를 추가합니다. 이 함수는 데이터 구조에 내가 찾으려는 데이터를 포함할 때 인쇄합니다.
3. 탐색을 코드에 넣고 로컬 변경을 위한 git patch
4. 응용 프로그램을 실행하고 프로브 검사
5. 문제가 발견될 때까지 3단계를 반복합니다.
Abinary search algorithm는 시도를 제한할 수 있습니다.
6. 완료 후 로컬 변경 사항 롤백
복잡한 상황에서 나는 이런 방법이 더욱 빠르고 점진적이며 더 적은 인지적 부담이 필요하다는 것을 발견했다.

지금 뭐가 문제예요?


내가 어떻게 발견했든지 간에 나의 선호는:
  • 새로운 테스트를 작성하고 실패를 보고 문제를 강조합니다***
  • 수정 텍스트
  • 결론


    코드에서 문제를 발견해야만 할 때, 우리는 선택할 수 있는 많은 전략을 가지고 있다.
    디버거를 사용하는 것은 그 중의 하나일 뿐, 내가 보기에 어떤 상황에서는 결코 가장 좋은 방법이 아니다.
    한 가지 옵션만 있는 것이 아니라, 우리는 우리에게 더 적합한 상황을 선택할 수 있다.
    ***일부 경우 새로운 테스트를 작성하는 것이 어려울 수 있습니다. 의존 관계를 깨고 working effectively with legacy code에 기술된 코드 부분을 분리해야 할 수도 있습니다.

    좋은 웹페이지 즐겨찾기