어디에서나 데이터 검사를 도입 할 수있는 좋은 코드 스타일?


10

나는 크기가 충분히 커서 프로젝트를 더 이상 머리 속에 담을 수 없습니다. 나는 많은 클래스와 함수를 다루고 있으며 데이터를 전달하고 있습니다.

시간이 지남에 따라 오류가 계속 발생한다는 것을 알았습니다. 데이터를 다른 함수에 전달할 때 데이터의 정확한 형식을 잊어 버렸습니다. 예를 들어 하나의 함수는 문자열 배열, 다른 함수는 나중에 작성하여 사전 등에 보관 된 문자열을 허용하므로 작업중 인 문자열을 배열에 포함시키는 것에서 사전에 포함시키는 것으로 변환해야합니다 .)

항상 어떤 부분이 고장 났는지 파악하지 않으려면 각 함수와 클래스를 외부 코드에 의존하여 올바른 입력을 제공 할 수 없으며 입력 확인 자체를 수행해야한다는 의미에서 "격리 된 엔티티"로 취급하기 시작했습니다. 경우에 따라 데이터가 잘못된 형식으로 제공되는 경우 데이터를 다시 전송하십시오.

이것은 클래스와 함수 자체가 일부 입력이 잘못되었을 때 경고하고 때로는 수정하지 않기 때문에 내가 전달하는 데이터를 모든 함수에 맞추는 데 소요되는 시간을 크게 줄였습니다. 더 이상 전체 코드를 통해 디버거와 함께 가야 건초가 어디로 갔는지 알아낼 수 있습니다.

다른 한편으로는 전체 코드가 증가했습니다.
내 질문은이 코드 스타일 이이 문제를 해결하는 데 적합한 지 여부입니다.
물론 가장 좋은 해결책은 프로젝트를 완전히 리팩토링하고 데이터가 모든 기능에 대해 균일 한 구조를 갖도록하는 것입니다. 그러나이 프로젝트가 꾸준히 성장하고 있기 때문에 실제로 새로운 것을 추가하는 것보다 더 많은 비용을 지출하고 깨끗한 코드에 대해 걱정하게됩니다. .

(FYI : 저는 아직 초보자입니다.이 질문이 순진한 경우 실례합니다. 프로젝트는 Python입니다.)



3
@gnat 그것은 비슷하지만 내 질문에 대답하는 대신 OP가 언급 한 특정 인스턴스에 대한 조언 ( "가능한 한 방어 적")을 제공 합니다 . 이는 일반적인 쿼리와 다릅니다.
user7088941

2
"하지만이 프로젝트가 꾸준히 성장하고 있기 때문에 실제로 새로운 것을 추가하는 것보다 더 많은 비용을 지출하고 깨끗한 코드에 대해 걱정하게 될 것입니다."-이것은 깨끗한 코드에 대한 걱정을 시작해야하는 것처럼 들립니다. 그렇지 않으면 기존 코드로 인해 각각의 새로운 기능 비트가 추가하기가 점점 어려워 져 생산성이 느려지고 느려질 수 있습니다. 새로운 무언가를 추가하는 때문에 감동 코드는 나중에 다시 방문하고 싶은 무엇을 기록해 단지 그것을 만지는 기존 코드, 리팩토링의 하드 경우 모든 리팩토링의 요구, "완료"로
매트는 freake

3
사람들이 약한 유형의 언어를 사용하는 경우가 종종 있습니다. 좀 더 엄격하게 입력 된 언어로 전환하거나 원하지 않는 경우 대답은 "예,이 코드 스타일은이 문제를 해결하는 데 적합합니다" 입니다. 다음 질문?
Doc Brown

1
올바른 데이터 유형이 정의 된 엄격한 유형의 언어에서 컴파일러가이를 수행했을 것입니다.
SD

답변:


4

더 나은 솔루션은 Python 언어 기능과 툴링을 더 활용하는 것입니다.

예를 들어, 함수 1에서 예상되는 입력은 문자열 배열이며, 첫 번째 문자열은 제목을 나타내고 두 번째 문자열은 서지 참조를 나타냅니다. 함수 2에서 예상되는 입력은 여전히 ​​문자열 배열이지만 문자열의 역할은 반대로됩니다.

이 문제는로 완화됩니다 namedtuple. 가볍고 배열 구성원에게 의미 론적 의미를 쉽게 부여합니다.

언어를 전환하지 않고 일부 자동 유형 검사의 이점을 얻으려면 유형 힌트를 활용할 수 있습니다 . 좋은 IDE는 이것을 사용하여 바보 같은 일을 할 때 알려줍니다.

요구 사항이 변경 될 때 기능이 오래가는 것에 대해 걱정하는 것 같습니다. 이것은 자동화 된 테스트에 의해 포착 될 수 있습니다 .

수동으로 확인하는 것이 결코 적절하지 않다는 말은 아니지만 사용 가능한 언어 기능을 더 잘 사용하면이 문제를 유지 관리하기 쉬운 방법으로 해결할 수 있습니다.


namedtuple와 다른 멋진 것들을 가리켜 +1했습니다 . 나는 namedtuple자동화 된 테스트에 대해 알지 못했지만 실제로는 많이 사용하지 않았 으며이 경우 얼마나 도움이 될지 알지 못했습니다. 이것들은 모두 정적 분석만큼이나 좋은 것 같습니다. (정적 분석에서 포착되지 않는 모든 미묘한 것들을 포착 할 수 있기 때문에 자동화 된 테스트가 더 나을 수도 있습니다!) 다른 것을 알고 있다면 알려주십시오. 질문을 조금 더 열어 두겠습니다. 그러나 다른 답변이 없으면 답변을 드리겠습니다.
user7088941

9

실제로 실제 문제는이 답변 아래의 주석에 설명되어 있습니다.

예를 들어, 함수 1에서 예상되는 입력은 문자열 배열이며, 첫 번째 문자열은 제목을 나타내고 두 번째 문자열은 서지 참조를 나타냅니다. 함수 2에서 예상되는 입력은 여전히 ​​문자열 배열이지만 문자열의 역할은 반대로됩니다.

여기서 문제는 순서가 의미를 의미하는 문자열 목록을 사용하는 것입니다. 이것은 실제로 오류가 발생하기 쉬운 접근 방식입니다. 대신 title및 이라는 두 개의 필드로 사용자 정의 클래스를 작성해야합니다 bibliographical_reference. 그렇게하면 당신은 그것들을 섞지 않을 것이며, 나중에이 문제를 피할 것입니다. 물론 많은 장소에서 이미 문자열 목록을 사용한다면 약간의 리팩토링이 필요하지만 장기적으로는 저렴할 것입니다.

동적 유형 언어의 일반적인 접근 방식은 "오리진 입력"입니다. 즉, 전달 된 객체의 "유형"에 신경 쓰지 않고 호출하는 메소드를 지원하는 경우에만 신경을 써야합니다. 귀하의 경우, bibliographical_reference필요할 때 호출되는 필드를 간단히 읽을 수 있습니다. 이 필드가 전달 된 객체에 존재하지 않으면 오류가 발생하며 이는 잘못된 유형이 함수에 전달되었음을 나타냅니다. 이것은 유형 검사만큼이나 좋습니다.


때로는 문제가 더 미묘합니다. 올바른 유형을 전달하고 있지만 입력의 "내부 구조"가 함수를 엉망으로 만듭니다. 예를 들어 함수 1에서 예상 입력은 첫 번째 문자열 인 문자열 배열입니다. 는 무언가의 제목을 나타내며 두 ​​번째는 참고 문헌을 나타냅니다. 함수 2에서 예상되는 입력은 여전히 ​​문자열 배열이지만 이제 문자열의 역할은 반대로됩니다. 첫 번째 문자열은 서지 참조 여야하고 두 번째 문자열은 서지 참조 여야합니다. 이 검사가 적절하다고 생각합니까?
user7088941

1
@ user7088941 : "title"과 "bibliographical_reference"라는 두 개의 필드가있는 클래스를 사용하면 설명하는 문제를 쉽게 해결할 수 있습니다. 당신은 그것을 섞지 않을 것입니다. 문자열 목록의 순서에 의존하면 오류가 발생하기 쉽습니다. 아마도 이것이 근본적인 문제입니까?
JacquesB

3
이것이 답입니다. 파이썬은 객체 지향 언어이며 문자열 목록에서 정수로 지향되는 언어 (또는 무엇이든) 언어가 아닙니다. 따라서 객체를 사용하십시오. 객체는 자신의 상태를 관리하고 자신의 불변을 적용하는 책임이 있으며 다른 객체 (정확하게 설계된 경우) 손상시킬 수 없습니다 . 구조화되지 않은 데이터 또는 반 구조화 된 데이터가 외부에서 시스템으로 입력 되는 경우 시스템 경계에서 한 번 유효성 검증 및 구문 분석 하고 가능한 빨리 리치 오브젝트로 변환합니다.
Jörg W Mittag

3
"정말 리팩토링을 피하고 싶습니다"-이 정신적 장애는 당신의 문제입니다. 좋은 코드는 리팩토링에서만 발생합니다. 많은 리팩토링. 단위 테스트에 의해 지원됩니다. 특히 구성 요소를 확장하거나 발전시켜야 할 때.
Doc Brown

2
이제 알겠습니다. 모든 좋은 통찰력과 의견에 +1. 그들의 도움이되는 의견에 감사합니다! (내가 볼 수 있듯이 일부 클래스 / 객체를 사용하는 동안 언급 한 목록과 함께 산재했습니다. 이제는 좋은 생각이 아닙니다 .JETMs의 구체적인 제안을 사용하여 이것을 구현하는 가장 좋은 방법 은 여전히 ​​남아 있습니다. 버그가없는 상태를 달성하는 속도면에서 근본적인 차이를 만들었습니다.)
user7088941

3

우선, 지금 당장 경험하고있는 것은 코드 냄새 입니다. 냄새를 인식하게하는 원인을 기억하고 코드 냄새 가 빨리 나타날수록 "정신적 인"코를 연마하십시오. 근본적인 문제를 해결할 수 있습니다.

항상 어떤 부분이 깨 졌는지 파악하지 않으려면 각 함수와 클래스를 외부 코드에 의존하여 올바른 입력을 제공 할 수 없으며 입력 확인 자체를 수행해야한다는 의미에서 "격리 된 엔티티"로 취급하기 시작했습니다.

이 기술을 사용하는 방어 적 프로그래밍은 유효하고 자주 사용되는 도구입니다. 그러나 모든 것과 마찬가지로 적절한 양의 검사를 사용하는 것이 중요하며 너무 적은 수의 검사를 수행하면 문제가 발생하지 않으며 코드가 과도하게 늘어납니다.

(또는 경우에 따라 데이터가 잘못된 형식으로 제공되는 경우 데이터를 다시 전송하십시오).

좋은 생각이 아닐 수도 있습니다. 프로그램의 일부가 형식이 잘못된 데이터로 함수를 호출하는 것을 발견하면 FIX THAT PART 는 호출 된 함수를 변경하여 나쁜 데이터를 소화하지 못하도록합니다.

이것은 클래스와 함수 자체가 일부 입력이 잘못되었을 때 경고하고 때로는 수정하지 않기 때문에 내가 전달하는 데이터를 모든 함수에 맞추는 데 소요되는 시간을 크게 줄였습니다. 더 이상 전체 코드를 통해 디버거와 함께 가야 건초가 어디로 갔는지 알아낼 수 있습니다.

코드의 품질 및 유지 관리 성을 향상시키는 것은 장기적으로 시간을 절약 해줍니다 (여러 가지 기능에 내장 된 자체 수정 기능에 대해 다시 경고해야합니다. 버그의 교묘 한 소스 일 수 있습니다. 프로그램이 충돌하지 않으며 화상이 올바르게 작동한다는 것을 의미하지는 않습니다 ...)

마지막으로 귀하의 질문에 대답하려면 : 그렇습니다. 방어 적 프로그래밍 (즉, 제공된 매개 변수의 유효성을 확인하는 것)은 좋은 전략입니다. , 자신이 말했듯이 코드가 부적절 하고 냄새나는 부분을 ​​리팩터링하는 데 약간의 시간을 할애 할 것을 강력히 권장합니다. 깨끗한 코드에 대해 항상 걱정하고 더 많은 시간을 소비하고 싶습니다 - 당신은 깨끗한 코드를 유지하지 않을 경우 새로운 기능을 구현하는 부수 버그 깨끗한 코드를 유지하고 힘든 시간을하지 않습니다에서 "저장"두 배의 시간을 보내고 있습니다 ... 새로운 기능에 대한보다 "청소" 기술 부채 캔 당신을 분쇄하십시오.


1

괜찮아요. 나는 FoxPro에서 코딩을했는데, TRY..CATCH를 거의 모든 큰 기능에서 사용했습니다. 이제 JavaScript / LiveScript로 코딩하고 "내부"또는 "개인"기능의 매개 변수를 거의 확인하지 않습니다.

"확인해야 할 양"은 선택한 프로젝트 / 언어에 따라 코드 기술에 따라 다릅니다.


1
제 생각 엔, 캐치 ... 아이 그 노어입니다. 당신은 OP가 요구하는 것과 반대되는 일을했습니다. IMHO의 요점은 불일치를 피하면서 프로그램을 칠 때 프로그램이 폭발하지 않도록하는 것입니다.
maaartinus

1
@maaartinus 맞습니다. 프로그래밍 언어는 일반적으로 우리에게 폭파되는 것을 막기 위해 사용하기 쉬운 구문을 제공하지만 불일치를 방지하기 위해 프로그래밍 언어를 사용하는 구문은 사용하기가 훨씬 더 어려워 보입니다. 응용 프로그램의 정보 흐름. 이것은 정확히 내가 묻는 것입니다-이 문제를 해결하는 더 쉬운 방법이 있습니까?
user7088941

@ user7088941 그렇기 때문에 약한 유형의 언어를 피해야합니다. 파이썬은 환상적이지만 더 큰 것은 다른 곳에서 한 일을 추적 할 수 없습니다. 따라서 나는 다소 장황한 Java를 선호합니다 (Lombok 및 Java 8 기능에는 그다지 중요하지 않음). 정적 분석을 위해 엄격한 타이핑과 도구가 있습니다. 달리 해결하는 방법을 모르기 때문에 엄격하게 유형이 지정된 언어를 사용해 보는 것이 좋습니다.
maaartinus

엄격하고 느슨한 유형의 매개 변수가 아닙니다. 매개 변수가 올바른지 알아야합니다. (정수 4 바이트)를 사용하더라도 예를 들어 0..10 범위에 있는지 확인해야 할 수도 있습니다. 매개 변수가 항상 0..10이라는 것을 알고 있으면 확인할 필요가 없습니다. 예를 들어 FoxPro에는 연관 배열이 없으며 변수, 범위 등으로 작동하기가 매우 어렵습니다. 따라서 점검 점검을 확인해야합니다.
Michael Quad

1
@ user7088941 OO는 아니지만 "실패"규칙이 있습니다. 개인이 아닌 모든 메소드는 인수를 확인하고 문제가 발생하면 처리해야합니다. try-catch, 고치려는 시도 없음, 하늘 높이 날려 라. 더 높은 수준에서는 예외가 기록되고 처리됩니다. 테스트에서 사전에 대부분의 문제를 발견하고 아무런 문제도 숨기지 않기 때문에 코드는 오류가없는 경우보다 버그가없는 솔루션으로 훨씬 빠르게 수렴됩니다.
maaartinus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.