Tại sao nhiều nhà phát triển PHP ghét sử dụng hàmetet () và / hoặc bất kỳ chức năng phòng thủ tương tự nào của PHP như rỗng ()?


27

Trên stackoverflow, tôi thấy vấn đề này luôn luôn xuất hiện:

Ngay cả Pekka (người cung cấp rất nhiều lời khuyên PHP vững chắc) đã gặp phải E_NOTICEcon quái vật đáng sợ và hy vọng có một giải pháp tốt hơn so với việc sử dụng isset(): isset () và trống () làm cho mã trở nên xấu xí

Cá nhân, tôi sử dụng isset()empty()ở nhiều nơi để quản lý luồng ứng dụng của mình. Ví dụ:

public function do_something($optional_parameter = NULL) {
    if (!empty($optional_parameter)) {
        // do optional stuff with the contents of $optional_parameter
    }
    // do mandatory stuff
}  

Ngay cả một đoạn đơn giản như thế này:

if (!isset($_REQUEST['form_var'])) {
    // something's missing, do something about it.
}

có vẻ rất logic với tôi Nó không giống như phình to, nó trông giống như mã ổn định. Nhưng nhiều nhà phát triển kích hoạt các ứng dụng của họ với E_NOTICEtính năng được kích hoạt, phát hiện ra rất nhiều thông báo "chỉ số mảng chưa được khởi tạo" bực bội, và sau đó nhăn nhó trước viễn cảnh kiểm tra các biến đã xác định và "xả rác" mã của họ isset().

Tôi giả sử các ngôn ngữ khác xử lý mọi thứ khác nhau. Nói từ kinh nghiệm, JavaScript không lịch sự như PHP. Một biến không xác định thường sẽ dừng việc thực thi tập lệnh. Ngoài ra, (nói từ thiếu kinh nghiệm ) Tôi chắc chắn các ngôn ngữ như C / C ++ sẽ từ chối biên dịch.

Vì vậy, các nhà phát triển PHP chỉ lười biếng? (không nói về bạn, Pekka, tôi biết bạn đang cấu trúc lại một ứng dụng cũ.) Hoặc các ngôn ngữ khác xử lý các biến không xác định một cách duyên dáng hơn là yêu cầu lập trình viên kiểm tra trước xem chúng có được xác định không?

(Tôi biết có những E_NOTICEthông điệp khác bên cạnh các biến không xác định, nhưng những thông báo đó dường như là những thông tin gây ra sự thất vọng nhất)

Phụ lục
Từ các câu trả lời cho đến nay, tôi không phải là người duy nhất nghĩ rằng isset()không phải là sự phình to mã. Vì vậy, bây giờ tôi đang tự hỏi, có vấn đề gì với các lập trình viên trong các ngôn ngữ khác lặp lại ngôn ngữ này không? Hay đây chỉ là một vấn đề văn hóa PHP?


4
Đáng buồn thay, tôi đã thấy các nhà phát triển php làm việc với "cảnh báo" cũng bị tắt.
Viper_Sb

Ôi. Đó buồn.
Stephen

1
Không phải là người dùng PHP Tôi tự hỏi: tại sao bạn cần kiểm tra các biến không xác định?
Winston Ewert

2
@Winston: Vấn đề với PHP (trái ngược với nhiều ngôn ngữ khác) là PHP cho phép nhiều kết hợp cấu hình. Chẳng hạn, lập trình viên có thể quyết định bỏ qua các cảnh báo, thông báo và thông báo phản đối. Các nhà phát triển có kinh nghiệm hơn sẽ làm việc với bộ lỗi báo cáo được thiết lập để báo cáo mọi thứ. PHP cũng có nhiều hàm ném lỗi và trả về mã trạng thái thay vì ném ngoại lệ. Người ta phải rất thân mật với ngôn ngữ để có thể viết mã phòng thủ và thành công. Nhiều ngôn ngữ khác không cho phép lựa chọn. Nghiêm thường là tùy chọn mặc định và duy nhất.
Wil Moore III

1
Tôi không thích ngay lập tức () vì tính dài dòng mà nó thêm vào. Một hình thức tốt hơn của @ sẽ là một lựa chọn tốt.
Kzqai

Câu trả lời:


34

Tôi mã đến E_STRICTvà không có gì khác.

Sử dụng kiểm tra trống và hiện không làm cho mã của bạn xấu đi, nó làm cho mã của bạn dài dòng hơn. Trong tâm trí tôi, điều tồi tệ nhất tuyệt đối có thể xảy ra khi sử dụng chúng là gì? Tôi gõ thêm một vài ký tự.

Câu hậu quả của việc không sử dụng chúng, ít nhất là cảnh báo.


7
Môi trường phát triển của tôi cũng vậy E_STRICT. Tôi loại bỏ tất cả các lỗi trong sản xuất, nhưng điều đó chỉ để đảm bảo không có gì vượt qua tôi trong quá trình phát triển.
Stephen

2
+1 Josh, tôi cũng vậy. Khi bạn lập trình trong E_STRICT, bạn biết rằng bạn sẽ không bao giờ có những bất ngờ trong mã của mình. Chỉ có cách bay, imo.
EricBoersma

3
@Stephen: Luôn tắt lỗi cho sản xuất. Đó chỉ là một mạng lưới an toàn. Phát triển nên (IMO) luôn E_STRICT. Viết mã và giải quyết tất cả các cảnh báo và lỗi.
Josh K

bạn đang vẹt tôi? :)
Stephen

@Stephen: Tôi đồng ý. :)
Josh K

17

Tôi nghĩ rằng các thông báo về các yếu tố không xác định là một lỗi thiết kế trong PHP. Tôi không chắc bây giờ có thể sửa lỗi, nhưng nó tạo ra rất nhiều mã soạn sẵn như if(isset($foo['abc']) && $foo['abc'] == '123')- mã này không nênisset, vì mục đích là kiểm tra xem có "123" ở một nơi nào đó không $foovà nếu không có gì ở đó chắc chắn không phải là '123'. Lý do duy nhất bạn phải viết gấp đôi số mã đó là do lỗi thiết kế không may này trong PHP. Và thật không may, các thông báo rất tốn kém trong PHP, thật không may, vì vậy việc vô hiệu hóa chúng không phải là một tùy chọn cho mã mà hiệu năng là một mối quan tâm.

Vì vậy, có, nó làm cho mã IMHO xấu xí và nó làm tôi khó chịu. Và đó không phải là vì thiếu kinh nghiệm - Tôi sử dụng PHP từ năm 1998 và tôi nhớ khi có .php3phần mở rộng và nó có nghĩa là "đó không phải là PHP 2". Có lẽ tôi lười biếng :) Nhưng sự lười biếng - ít nhất là một loại nào đó của nó - là một đức tính tốt cho một lập trình viên.

Mặt khác, việc sử dụng hợp lệ issetempty- giống như những người trong bài viết gốc - là tốt. Tôi chỉ nghĩ rằng PHP quá nhiệt tình về các cảnh báo ở những nơi isset/emptykhông thực sự cần thiết.


3
Đúng. Đó là một vấn đề dài dòng. $eg = isset($_GET['eg'])? $_GET['eg'] : null;là vô lý dài dòng. Tôi thực sự mong muốn có một toán tử khác không phải là "siêu lỗi" để hiểu theo nghĩa ngắn gọn là $eg = @$_GET['eg'];"chấp nhận sự không tồn tại của mảng này-key-as-a-null". Tôi có xu hướng sử dụng một chức năng ngắn, những ngày này.
Kzqai

7
Đã đồng ý. 4 năm sau, hãy nhập Toán tử Null Coalesce: wiki.php.net/rfc/isset_ternary cho chúng tôi$eg = $_GET['eg'] ?? null;
Steve

Hoặc chỉ cần thực hiện ngay bây giờ với toán tử triệt tiêu lỗi, vd $eg = @$_GET['eg'] ?: null;. Tôi thường không sử dụng nó, nhưng trong trường hợp này, chúng tôi rõ ràng đang mong đợi lỗi đó và quyết định bỏ qua nó. Đó là một ký tự dài hơn null kết hợp và nó không tốt bằng (nó loại bỏ tất cả các lỗi và có thể ArrayAccess thực hiện các công cụ thú vị ở đó, không chỉ là một mảng), nhưng nói chung nó thực hiện công việc.
El Yobo

12

Tôi tin rằng PHP, như một ngôn ngữ tự do, được giải thích và sử dụng trên web, có tỷ lệ rất cao các lập trình viên không chuyên nghiệp, không được đào tạo, những người không nhận thức đầy đủ về lý do tại sao họ nên viết mã phòng thủ và chỉ xem các cảnh báo là một lỗi không cần thiết khác .

Tôi nghe thấy những điểm này từ các nhà phát triển cơ sở và các lập trình viên tự viết kịch bản mọi lúc:

  • Tại sao lại khởi tạo một biến nếu nó sẽ xuất hiện?
  • Tại sao kiểm tra nếu một cái gì đó tồn tại trước khi chúng ta sử dụng nó, không xác định tương đương với sai?
  • Nếu tôi tiền tố với @ nó sửa mã của tôi, tại sao lại làm phức tạp mọi thứ?

Nếu họ chưa bao giờ trải nghiệm một ngôn ngữ được đánh máy mạnh mẽ, hoặc trải qua những cạm bẫy của các biến không được khai báo / không có căn cứ, thì họ có một số thuyết phục. Tôi thấy họ thường đưa ra một khi họ đã trải nghiệm niềm vui của việc gỡ lỗi mã trong một giờ hoặc lâu hơn để thấy đó là một lỗi đánh máy trong một tên biến gây ra rắc rối.

Yếu tố mạnh mẽ khác là việc sử dụng PHP trong ngành công nghiệp web, vốn có xu hướng quan tâm nhiều hơn đến thông lượng hơn là an toàn và chất lượng mã.


10
"Tôi tin rằng PHP [...] có tỷ lệ rất cao các lập trình viên không chuyên nghiệp, chưa được đào tạo" Là một nhà phát triển PHP chuyên dụng, tôi không thể đồng ý với bạn nhiều hơn. +1
Stephen

@Stephen Vâng, tôi mã hóa chủ yếu bằng PHP và jQuery gần đây, mặc dù tôi có giáo dục chính thức, nhưng mã mà bạn thấy là một chuyên gia mà bạn trở nên có trách nhiệm trước đây ... đôi khi nó bất chấp niềm tin. ;-)
Orble

1
Tôi nghĩ đó là một vấn đề thực sự với PHP. Bên cạnh một số điều kỳ quặc trong ngôn ngữ (mà họ đang dần giải quyết trong mỗi phiên bản mới), có một không khí nghiệp dư xung quanh nó. Tôi có thể tưởng tượng việc trở thành một nhà phát triển PHP chuyên nghiệp đôi khi có thể gây nản lòng, bởi vì bạn đang được so sánh với 'cháu trai của ông chủ ở khắp nơi'.
Erik van Brakel

1
@Erik PHP là một người họ hàng khá nghèo của Perl mười năm trước, giờ đây nó là một ngôn ngữ được giải thích khá hợp lý, đặc biệt là cho việc sử dụng web. Có một lý do các công ty như Facebook sử dụng nó. Nhưng vì nó có sẵn ở khắp mọi nơi, bộ nghiệp dư sử dụng nó rộng rãi và điều này làm mờ danh tiếng.
Orble

5

Vâng, họ lười biếng. Nhiều người trong số họ dù sao ...

Thật không may, tâm lý của nhiều lập trình viên PHP là "Không có mã hóa điểm phòng thủ nếu bạn có thể nhận được kết quả cuối cùng nhanh hơn bằng cách dựa vào ngôn ngữ để xử lý các lỗi gây ra bởi các biến bị thiếu, v.v." Tôi biết, tôi đã làm việc với một vài người trong số họ.

Họ cũng có xu hướng trở thành những người bí ẩn đi ăn trưa sớm khi họ không xử lý lỗi và báo cáo chính xác trong các máy chủ trực tiếp trong vài giờ ...


5
-1 cho ý kiến ​​chủ quan về các lập trình viên PHP.
Josh K

4
@Josh, đã là một lập trình viên PHP cao cấp trong 4 năm rưỡi và đã mã hóa PHP từ năm 1999, tôi e rằng tôi hơi chủ quan. Tôi nên có đủ điều kiện với "Mặt khác, các lập trình viên PHP có kinh nghiệm hơn không lười biếng và làm mọi thứ một cách chính xác" ...
Gruffputs

1
Điều đó bạn nên có.
Josh K

5

Tôi cố gắng tránh việc sử dụng isset () và blank () bằng cách tránh sử dụng mảng làm đối tượng truyền dữ liệu. Tạo một lớp có thể được cấu hình để chấp nhận một tập các thuộc tính giới hạn với mặc định lành mạnh và xác thực đầu vào cho các thuộc tính đó. Nó thậm chí có thể thực hiện giao diện ArrayAccess để bạn có thể sử dụng nó như một mảng. Điều này cũng cho phép bạn sử dụng gợi ý kiểu trong chữ ký phương thức của mình để bắt lỗi khi ai đó cố gắng chuyển loại thực thể sai sang phương thức của bạn.


Một cách tiếp cận rất thú vị.
Toby

2

Một trong những câu hỏi là của tôi, vì vậy hãy để tôi nhắc lại.

Nhiều nhà phát triển nhầm lẫn sự hiện diện của rất nhiều isset()dấu hiệu chất lượng. Nó mang lại vẻ ngoài đáng tin cậy và một số người nghĩ về nó ngay cả khi là tính năng bảo mật.

Nhưng bạn phải tính đến việc PHP không phải là ngôn ngữ được biên dịch. Đó là một ngôn ngữ kịch bản với một hệ thống loại động. Lỗi E_NOTICE chỉ là lỗi theo tên. Và nếu rất nhiều issetđược sử dụng với mục đích duy nhất là triệt tiêu các thông báo, thì thực ra bạn chỉ đang viết mã theo ngôn ngữ .

Vì vậy, các nhà phát triển PHP chỉ lười biếng?

Đó thực sự là trường hợp nếu bạn thấy rất nhiều thông báo và cảnh báo ném. Rất nhiều người mới không quan tâm đến các thông báo và đó thường là kết quả của việc bị vô hiệu hóa hoàn toàn error_reporting(0).

Tuy nhiên, bạn đã nhầm rằng các nhà phát triển khác đã không nhận ra E_NOTICE chỉ vì họ không bị ức chế @ hoặc hiện tại. Ít nhất đó là ý định của tôi đằng sau câu hỏi thông báo giữ lại . Chúng không phải là thứ để loại bỏ, nhưng đôi khi thông tin gỡ lỗi quan trọng.

Giống như tất cả các khái quát hóa, việc sử dụng không hợp lý củaetet không dẫn đến mã tối ưu. Điều quan trọng là phân biệt nơi issetemptycần thiết và nơi chúng là muối cú pháp .

Hay đây chỉ là một vấn đề văn hóa PHP?

Không, "lỗi" biến không xác định không phải là một vấn đề PHP. Bash, TCL và Perl hoặc JavaScript cho phép sử dụng các biến không xác định. Tuy nhiên, tính năng ngôn ngữ vô thường này không được coi là khiếm khuyết ở đó. Có các cấu trúc ngôn ngữ tương tự để kiểm tra các giá trị không xác định. Tuy nhiên, chúng không được sử dụng liên tục như trong PHP, do các giá trị không chính xác không bị nhầm lẫn là "lỗi".


1

Hấp dẫn. Tôi hầu như không bao giờ sử dụng isset (). Mã PHP của tôi hiếm khi ở trạng thái mà tôi không biết nếu một biến đã được đặt ở vị trí đầu tiên. Mỗi biến GET hoặc POST được sử dụng được truy cập thông qua một hàm sẽ cung cấp cho nó một mặc định nếu nó không tồn tại. Giá trị mặc định trong các lệnh gọi hàm thường được đặt rõ ràng thành 0 hoặc chuỗi rỗng.


+1. Truyền đến một hàm hoặc phương thức lớp là một giải pháp tốt. Tôi thực sự DO làm điều này, nhưng trong một véo ví dụ trên của tôi vẫn còn trông sạch sẽ và un-cồng kềnh đối với tôi.
Stephen

0

Tôi sử dụng ngay lập tức và rất nhiều trống. Nhưng chủ yếu là các địa điểm mà bạn đề cập, như xử lý $ _REQUEST, trong trường hợp bất kỳ ai cũng làm hỏng các tham số. Trong trường hợp tôi có quyền kiểm soát tất cả các biến bay xung quanh, tôi thấy rằng tôi thường không cần chúng.


0

Tôi không thích sử dụng isset, nhưng nếu có một khối lượng mã được thực hiện bởi người khác, thì đó có thể là một ân huệ tiết kiệm. Tôi đã viết mã nhỏ dưới đây để giải quyết vấn đề này, thay vì sử dụng ngay bây giờ () a ($ a, $ b) sẽ trả về $ b nếu $ a không được xác định hoặc trống hoặc hàm trả về null. Mọi cải tiến, xin chào mừng:

//returns var or NULL (if undefined)
//$reserve optional second value is returned as $default if undefined
function isseter(&$default,&$reserve=NULL)
{
$default = isset($default) ? $default : NULL;
$reserve = isset($reserve) ? $reserve : NULL;
if ((!$default) && ($reserve)) $default=$reserve;
return $default;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.