2008-12-06 35 views
22

Có lý do thuyết phục nào để không sử dụng debug_backtrace cho mục đích duy nhất là xác định lớp, tên và danh sách tham số của phương thức gọi không? Không cho mục đích gỡ lỗi. Nó có từ "debug" trong tên hàm, khiến tôi cảm thấy hơi bẩn khi sử dụng nó theo cách này, nhưng nó phù hợp với hóa đơn cho những gì tôi cần làm (một hàm duy nhất có thể gọi từ nhiều nơi và cần gọi phương thức gọi từ hệ thống khác). Nó hoạt động, nhưng đây vẫn là một ý tưởng tồi? Nếu vậy, tại sao?PHP debug_backtrace trong mã sản xuất để nhận thông tin về phương thức gọi điện?

+0

debug_backtrace có lỗi: đọc http://stackoverflow.com/q/4581969/632951 – Pacerier

Trả lời

13

Nó cảm thấy một chút bẩn thỉu, nhưng như đã được ghi chép, mở rộng và đánh bại đến chết ở nơi khác, PHP không phải là một hệ thống được thiết kế cho sự thanh lịch.

Một lý do rất phức tạp không dùng để sử dụng debug_backtrace cho logic ứng dụng là có thể một số nhà phát triển tương lai đang làm việc trên PHP có thể quyết định "đó chỉ là chức năng gỡ lỗi, hiệu suất không quan trọng".

Nếu bạn quan tâm đến cách "làm tốt hơn", bạn có thể sử dụng PHP's magic constants để chuyển sang phương thức gọi và tên lớp, sau đó sử dụng đối tượng ReflectionMethod để trích xuất bất kỳ thông tin nào bạn cần.

Tôi đặt tốt hơn trong dấu ngoặc kép vì, trong khi điều này sẽ sạch hơn và chính xác hơn, chi phí của việc tạo đối tượng Reflection có thể lớn hơn sử dụng hàm debug_backtrace.

+0

Có, tôi không biết về __CLASS__ hoặc __FUNCTION__ lúc đó. Hoặc đối tượng Reflection. Tôi nghĩ nếu tôi làm lại, tôi sẽ làm theo cách đó. – Sydius

+0

Một điều cần xem xét là mức độ thường xuyên bạn cần: Duy trì thông tin tương tự trong mã PHP sẽ thêm các chu kỳ quan trọng vào mọi yêu cầu, do đó, thỉnh thoảng một 'debug_stacktrace' sẽ được ưu tiên. Nói chung, mặc dù, tôi đồng ý với Konrad: bên ngoài gỡ lỗi/đăng nhập/nhu cầu bất thường, thiết kế không nên đòi hỏi nó. –

15

Có lý do thuyết phục nào để không sử dụng debug_backtrace với mục đích duy nhất là xác định lớp, tên và danh sách tham số của phương thức gọi không?

Có. Vấn đề là, nó thường là một dấu hiệu của thiết kế xấu nếu mã của bạn yêu cầu một khớp nối chặt chẽ như vậy mà callee phải có những thông tin về người gọi của nó. Do đó, nếu bạn cảm thấy cần phải sử dụng những thông tin này, bạn có thể nên suy nghĩ lại về thiết kế của mình.

Đặt thẳng thừng, không cần phải có những thông tin này để thực hiện nhiệm vụ của mình. Các ngoại lệ, tất nhiên, xoay quanh việc gỡ lỗi, ghi nhật ký và thường là các loại nội dung mã khác (nhưng ngay cả ở đó, hãy cẩn thận về nó).

+0

Nhiệm vụ của callee là gọi cùng một phương thức gọi là nó trên một máy tính khác. Đó là để tránh có một chức năng API khác nhau cho mọi nguồn có thể, làm giảm số lượng mã trong hệ thống đáng kể. Nó vẫn còn tệ? – Sydius

+0

Tôi thành thật phải nói rằng tôi không biết. Tôi không thể nhìn thấy bất kỳ cách nào để xử lý này khác nhau vì vậy đây có thể là một trường hợp thích hợp cho việc sử dụng như vậy. –

+0

nhưng nó là ok để sử dụng nó trong xử lý lỗi, phải không? – Mawg

4

debug_backtrace là một trong các hàm xử lý lỗi PHP. Hướng dẫn này khuyến khích người dùng xác định các quy tắc xử lý lỗi của chính họ, cũng như sửa đổi cách các lỗi có thể được ghi lại. Điều này cho phép bạn thay đổi và tăng cường báo cáo lỗi cho phù hợp với nhu cầu của bạn. Điều này cũng ngụ ý rằng hiệu suất đạt được từ việc sử dụng các hàm này là không đáng kể.

Tôi nghĩ rằng những gì bạn đang làm là tốt.

3

Bạn nói trong một chú thích

Nhiệm vụ của callee là để gọi phương thức tương tự mà gọi nó trên một máy tính khác nhau. Đó là để tránh có một chức năng API khác nhau cho mọi nguồn có thể, làm giảm số lượng mã trong hệ thống đáng kể.Là nó vẫn xấu

Vì vậy, bạn muốn làm như sau:

  • Chức năng foo() gọi
  • Chức năng phản xạ(), mà hiện một vết lùi gỡ lỗi và yêu cầu
  • http://example.com/REST/foo

Giả sử, tất nhiên, bạn sử dụng các yêu cầu HTTP để kích hoạt cuộc gọi từ xa.

Đây là một chút thiết lập lạ. Nếu bạn đang tạo hệ thống từ đầu thì tôi khuyên bạn nên cố gắng giải quyết nó. Nếu bạn shoehorning nó vào một hệ thống di sản sau đó tôi cho rằng tôi hiểu.

Tôi khuyên bạn nên luôn rõ ràng hơn khi có thể. Việc bạn sử dụng ma thuật ngăn xếp nội tâm có thể giúp bạn tiết kiệm một chút mã hóa, nhưng với một nhà phát triển khác, mã của bạn sẽ hoàn toàn bị bối rối. Nếu muốn đề nghị bạn chuyển tên lớp và hàm vào hàm mà trước đó đã thực hiện phép phản chiếu. Thế thì không có sự mơ hồ về những gì đang xảy ra.

  • Chức năng foo() gọi
  • Chức năng phản chiếu (__ CLASS__, __FUNCTION__), mà yêu cầu
  • http://example.com/REST/foo
+0

Tôi không biết về __CLASS__ và __FUNCTION__ khi lần đầu tiên tôi viết nó, hoặc nếu không tôi có thể sẽ có. Tôi muốn một cái gì đó dễ dàng để sao chép/dán (và liên tục). Tôi thực sự muốn PHP có macro (xấu như họ có thể bị lạm dụng). – Sydius

0

Tôi đang nghĩ về việc sử dụng debug_backtrace cho gỡ lỗi các câu lệnh mysql. Rất dễ xác định các truy vấn sai hoặc chậm khi bạn có tiêu đề như thế này khi bắt đầu mỗi truy vấn bên trong nhật ký cơ sở dữ liệu:

/*Called from /var/www/micimacko.php at line 28*/ SELECT count(*) FROM rofibeka; 

Câu hỏi vẫn còn. Điều gì về hiệu suất/độ tin cậy.

+1

Hàm trigger_error() thực hiện chính xác những gì bạn mô tả, cộng thêm lưu lỗi vào nhật ký lỗi Apache. Tôi sử dụng trigger_error (mysql_error()) để lưu tất cả các lỗi để đăng nhập hoặc hiển thị chúng trên màn hình (tùy thuộc vào việc tôi đang trên máy chủ sản xuất hay phát triển). –

2

Câu trả lời đúng là hoàn toàn là OK. Alan chỉ sự tinh tế của PHP, vì vậy tôi sẽ không nhắc lại điểm của anh ta. Lý do để (không ngại) sử dụng debug_backtrace trong mã thời gian chạy là vì PHP chủ yếu là một ngôn ngữ tự do ngữ cảnh. Mỗi chức năng không biết, cũng không thể biết "ý định" của người gọi mà không sử dụng tên hàm ma thuật (ví dụ trong một lớp - ví dụ __toString()) khi truyền. Cho phép xem xét trường hợp bạn có một lớp, trong đó (trong một phương thức), bạn muốn cung cấp quyền truy cập vào các thuộc tính của lớp gọi (bên ngoài). Nó thực sự là lộn xộn và dễ bị lỗi để vượt qua ($ this) xung quanh thông qua API chức năng. (Đặc biệt là khi bạn muốn array_map hoặc call_user_func_array.)

ví dụ:

<? 
class a { 
public $v = 'xyz'; 
function __construct($x,$y) 
{ 
    $b = new b(); 
} 
} 
class b { 
function __construct() 
{ 
    $start = microtime(); 
    $x = debug_backtrace(); 
    $end = microtime(); 
    echo ($end-$start) . "\n"; 
    print_r($x); 
    $obj = $x[1]['object']; 
    print_r($obj); 
} 
} 
$a = new a(1,2); 
?> 

debug_backtrace sẽ cho phép bạn truy cập vào ngữ cảnh của lớp trong __construct của b. Bây giờ bạn có thể vượt qua một số biến trạng thái từ lớp hiện tại mà không chuyển $ this around hoặc cố gắng divine nó từ tên lớp hoặc kludge nó bằng cách đặt nó vào globals.

Đối với những người quan tâm đến thời gian, microtime là 2,7E-5. Đủ nhanh. Chỉ cần không đặt nó trong một thời gian (1).

Các vấn đề liên quan