PHP에서 클래스의 필드를 선언하는 것이 실제로 유해합니까?


13

과거에 실제로 몇 번이나 만든 평범한 프로그래밍 오류로 인해 세터가 의도적으로 깨진 다음 코드를 고려하십시오.

<?php

    class TestClass {

        private $testField;

        function setField($newVal) {
            $testField = $newVal;
            // deliberately broken; should be `$this->testField = $newVal`
        }

        function getField() {
            return $this->testField;
        }

    }

    $testInstance = new TestClass();
    $testInstance->setField("Hello world!");

    // Actually prints nothing; getField() returns null
    echo $testInstance->getField(); 

?>

내가 $testField클래스의 최상위에 선언했다는 사실은 저의 프로그래밍 오류를 숨기는 데 도움이됩니다. 필드를 선언하지 않으면이 스크립트를 호출 할 때 오류 로그에 다음 경고와 비슷한 내용이 표시됩니다.이 오류는 디버깅에 도움이 될 것입니다. 특히 크고 복잡한 실제 응용 프로그램 :

PHP 공지 : 정의되지 않은 속성 : 13 행의 /var/www/test.php에있는 TestClass :: $ testField

선언하면 경고가 없습니다.

어쩌면 나는 뭔가를 놓치고 있지만 PHP에서 클래스 필드를 선언 해야하는 두 가지 이유 만 알고 있습니다. 첫 번째로 선언은 문서로 작동하고 두 번째로 선언 없이는 privateprotected수정자를 사용할 수 없다는 것입니다. 틀림없이 유용하다. 후자의 주장은 객체의 선언되지 않은 필드에 할당하면 공개 필드에 적용되지 않으므로 공개 필드 선언을 적어도 주석 처리해야한다고 생각합니다. 주석은 똑같은 문서 값을 제공하지만 초기화되지 않은 필드를 읽으려고하면 경고의 이점이 있습니다.

그러나 더 생각하면 거기서 멈추는 것이 합리적이지 않은 것 같습니다. 내 경험상 초기화되지 않은 필드를 읽으려는 것은 개인 또는 보호 된 필드를 부적절하게 읽거나 수정하려고 시도하는 것보다 오류의 훨씬 더 일반적인 원인이기 때문에 (저는 짧은 프로그래밍 경력에서 이미 여러 번 수행했지만 후자는 결코 아닙니다. ), 공개 선언뿐만 아니라 모든 필드 선언을 주석 처리하는 것이 가장 좋습니다.

주저하는 것은 다른 사람이 코드에서 그것을 본 적이 없다는 것입니다. 왜 안돼? 내가 모르는 클래스 필드를 선언하면 이점이 있습니까? 또는 실제 필드 선언을 사용하고 "정의되지 않은 속성"경고의 이점을 얻을 수 있도록 필드 선언의 동작을 변경하는 방법으로 PHP 구성을 수정할 수 있습니까? 아니면 내가 분석에서 놓친 것이 있습니까?


1
틀림없이 유용한가 ? 귀하가 언급 한 혜택은 매우 중요합니다. 명시 적 속성 선언이없는 코드 작업을 거부 할 것입니다 .
Michael

2
실제로 이러한 오류로부터 자신을 보호하는 방법은 단위 테스트를 통해 신중하게 오류를 확인하는 것입니다.
Michael

1
먼저 변수를 선언하지 않고 변수를 사용하는지 알려주는 PHP 오류보고 (통지 수준)가 내장되어 있습니다.
Crayon Violent

3
@MarkAmery 저는 엄청나게 변화하는 스타트 업이 엄격한 단위 테스트를 채택하는 가장 중요한 장소 중 하나라고 생각합니다. 항상 코드를 변경하기 때문에 항상 깨뜨릴 수 있습니다. 이것이 바로 엄격한 테스트와 TDD의 정확한 목적입니다. 예, 밑줄을 사용하면 개인 정보에 액세스하고 있음을 기억하는 데 도움이 될 수 있지만 오류를 방지하기 위해 특정 코딩 표준을 채택한다는 아이디어는 불안합니다. TRUE === $variable비교하지 않고 실수로 할당하는 것을 방지 하는 것과 같습니다.
Michael

1
@MarkAmery 가시성 키워드는 자동화 된 문서 도구에 의해 구문 분석 되므로 수동으로 입력하는 주석보다 더 많은 "문서화 값"을 제공합니다.
Michael

답변:


15

항상 클래스 속성을 미리 선언해야합니다. PHP는 동적 언어이며 런타임에 속성을 작성하는 것과 함께 행복하게 진행되지만이 경로에는 몇 가지 단점이 있습니다.

  • 컴파일러는 선언 된 속성을 최적화 할 수 있습니다. 동적으로 속성을 선언하면 컴파일러가 동적 속성을 저장하기 위해 동적 해시 테이블을 만들어야하기 때문에 성능이 저하됩니다.
  • 나는 이것에 100 %는 아니지만 APC와 같은 바이트 코드 최적화 프로그램은 수업에 대한 전체 그림이 없기 때문에 유용하지 않을 것이라고 생각합니다. (그리고 APC와 같은 옵티마이 저는 필수입니다 )
  • 코드를 1000 배 읽기 어렵게 만듭니다. 사람들이 당신을 미워할 것입니다.
  • 실수 확률이 1000 배 더 높습니다 . (getId 또는 getID였습니까? 잠깐, 둘 다 사용했습니다. 실패)
  • IDE 자동 완성 또는 유형 힌트가 없습니다.
  • 문서 생성기는 속성을 볼 수 없습니다.

설명 한 문제는 실제로 클래스 정의에서 속성을 선언 하지 않는 문제와 비교할 때 사소한 문제입니다 . 좋은 해결책이 있습니다.

속성의 기본값을 선언하는 데 익숙해 지십시오.

private $testField = null;
private $testField = '';
private $testField = 0;
private $testField = []; //array()
private $testField = false;

객체를 저장할 속성을 제외하고는 저장할 기본 유형의 대부분을 다룹니다. 객체를 저장할 속성은 생성자에서 설정할 수 있습니다.

클래스 디자인의 좋은 규칙은 객체가 생성되고 생성자가 실행 된 후에는 "정의되지 않은"속성이 없어야한다는 것입니다.


5 가지 단점에 대한 답변 : 1 (성능) : 이에 대한 소스가 있습니까? 2 (가독성) : 잘 모르겠습니다. 제안은 선언을 제거하는 것이 아니라 선언을 주석 처리하기위한 것이므로 어떤 가독성이 손실됩니까? 약간 덜 친숙한 구문 강조 표시와 주변 댓글과 구별하기가 어려울 수 있습니다. 3 : 이건 전혀 이해가 안 돼요; 당신은 명확히 할 수 있습니까? 4 (IDEs) : 충분합니다-IDE로 PHP를 코딩 한 경험이없고 Eclipse의 유형 힌트에 대해 몰랐습니다. 5 (문서 생성기) : 충분합니다.이 중 하나를 사용하지 않았습니다.
Mark Amery

나는 당신의 의견에 대해 당신의 라인을 보지 못했습니다. 어쨌든, 위의 사항들이 여전히 적용됩니다-어떤 것이 활성화되어 있거나 합법적으로 주석 처리되었는지 어떻게 알 수 있습니까?
Jarrod Nettles

제안 된 솔루션에 대한 응답으로 : 이것은 내가 피하고 싶은 것입니다-기본값이 무의미하고 기본값을 절대 사용해서는 안되는 경우에도 기본값을 할당하십시오. 이러한 기본값 (및 할당이없는 선언, null을 할당하는 문제)의 문제는 프로그래밍 실수로 인해 생성자에서 무언가에 값을 할당하지 않으면 PHP 대신에 나중에 그 값을 사용하려고 할 때 경고-오류를 발견하는 데 도움이됩니다-수업이 중단 되더라도 모든 것이 잘 작동하는 것처럼 보입니다.
Mark Amery

2
@MarkAmery 프로그래밍 실수는 본질적으로 오타에 해당합니다. 우린 모두 가지고 있었지만 여기서 폭탄을 폭발시켜 파리를 죽이려하고 있습니다.
Jarrod Nettles 23

당신이 옳을 수도 있습니다. 오늘 몇 시간 동안 버그를 추적하는 데 몇 시간을 보냈는데, 오타로 인해 완전히 발생했으며 나중에 필드 선언 만 사용하지 않으면 통지를 받았음을 갑자기 깨달았 습니다. 내 오류가 발생한 위치를 즉시 알 수 있습니다 (어쨌든 항상 이러한 상황에서 발생할 것이라고 생각했습니다. 필드를 null로 초기화 한 선언을 인식하지 못했습니다). 그 경험의 즉각적인 접근성은 아마도 재발 가능성이나 방어 할 가치가 있는지에 대한 나의 판단을 왜곡시키는 것일 수 있습니다.
Mark Amery

2

동적으로 생성 된 객체 속성을 사용하는 코드를 작성했습니다. 동적으로 생성 된 객체 속성을 사용하는 것이 꽤 멋지다고 생각했습니다 (제 생각에는 사실입니다). 그러나 내 프로그램을 실행하는 데 7 초가 걸렸습니다. 동적 객체 속성을 제거하고 각 클래스의 일부로 선언 된 객체 속성을 대체했습니다 (이 경우 공개). CPU 시간이 7 초 이상에서 0.177 초로 증가했습니다. 꽤 실용적입니다.

동적 객체 속성을 사용하는 방식에 문제가있을 수 있습니다. 구성이 어떤 식 으로든 손상되었을 수도 있습니다. 물론, 나는 내 컴퓨터에 매우 평범한 바닐라 PHP 구성이 있다고 말해야합니다.

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