Globals เป็นสิ่งที่หลีกเลี่ยงไม่ได้
มันเป็นการสนทนาเก่า แต่ฉันยังอยากจะเพิ่มความคิดบางอย่างเพราะฉันคิดถึงพวกเขาในคำตอบที่กล่าวถึงข้างต้น คำตอบเหล่านี้ทำให้โลกเข้าใจง่ายขึ้นและนำเสนอวิธีแก้ปัญหาที่ไม่ใช่วิธีแก้ปัญหาทั้งหมด ปัญหาคืออะไรคือวิธีที่เหมาะสมในการจัดการกับตัวแปรส่วนกลางและการใช้คำหลัก global? ก่อนอื่นเราต้องตรวจสอบและอธิบายว่าโลกคืออะไร
ดูรหัสของ Zend - และโปรดเข้าใจว่าฉันไม่ได้แนะนำว่า Zend เขียนไม่ดี:
class DecoratorPluginManager extends AbstractPluginManager
{
/**
* Default set of decorators
*
* @var array
*/
protected $invokableClasses = array(
'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud',
'htmltag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
'tag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
);
มีการอ้างอิงที่มองไม่เห็นมากมายที่นี่ ค่าคงที่เหล่านั้นเป็นคลาส คุณยังสามารถดู require_once ในบางหน้าของกรอบงานนี้ Require_once เป็นการพึ่งพาส่วนกลางดังนั้นการสร้างการอ้างอิงภายนอก นั่นเป็นสิ่งที่หลีกเลี่ยงไม่ได้สำหรับกรอบ คุณจะสร้างคลาสเช่น DecoratorPluginManager ได้อย่างไรโดยไม่ต้องใช้รหัสภายนอกจำนวนมากซึ่งขึ้นอยู่กับ มันไม่สามารถทำงานได้โดยไม่ต้องมีของแถมมากมาย การใช้ Zend framework คุณเคยเปลี่ยนการใช้งานอินเทอร์เฟซหรือไม่? อินเทอร์เฟซเป็นสากล
แอปพลิเคชันอื่นที่ใช้กันทั่วโลกคือ Drupal พวกเขากังวลมากเกี่ยวกับการออกแบบที่เหมาะสม แต่เช่นเดียวกับกรอบงานใหญ่ ๆ พวกเขามีการพึ่งพาภายนอกมากมาย ดูบอลโลกในหน้านี้:
/**
* @file
* Initiates a browser-based installation of Drupal.
*/
/**
* Root directory of Drupal installation.
*/
define('DRUPAL_ROOT', getcwd());
/**
* Global flag to indicate that site is in installation mode.
*/
define('MAINTENANCE_MODE', 'install');
// Exit early if running an incompatible PHP version to avoid fatal errors.
if (version_compare(PHP_VERSION, '5.2.4') < 0) {
print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the <a href="http://drupal.org/requirements">system requirements</a> page for more information.';
exit;
}
// Start the installer.
require_once DRUPAL_ROOT . '/includes/install.core.inc';
install_drupal();
เคยเขียนการเปลี่ยนเส้นทางไปยังหน้าเข้าสู่ระบบหรือไม่? นั่นคือการเปลี่ยนแปลงมูลค่าทั่วโลก (แล้วคุณไม่ได้พูดว่า 'WTF' ซึ่งฉันถือว่าเป็นปฏิกิริยาที่ดีต่อเอกสารที่ไม่ดีของแอปพลิเคชันของคุณ) ปัญหาเกี่ยวกับ globals ไม่ใช่ว่าพวกเขาเป็นลูกโลกคุณต้องใช้เพื่อให้มีแอปพลิเคชันที่มีความหมาย ปัญหาคือความซับซ้อนของแอปพลิเคชันโดยรวมซึ่งอาจทำให้เป็นฝันร้ายในการจัดการ เซสชันเป็นแบบโกลบอล $ _POST เป็นโกลบอล DRUPAL_ROOT เป็นโกลบอลรวม / install.core.inc 'เป็นโกลบอลที่ไม่สามารถแก้ไขได้ มีโลกใบใหญ่ภายนอกฟังก์ชันใด ๆ ที่จำเป็นเพื่อให้ฟังก์ชันนั้นทำงานได้
คำตอบของกอร์ดอนนั้นไม่ถูกต้องเพราะเขาใช้ความเป็นอิสระของฟังก์ชันมากเกินไปและการเรียกฟังก์ชันว่าคนโกหกทำให้สถานการณ์ง่ายขึ้น ฟังก์ชั่นไม่โกหกและเมื่อคุณดูตัวอย่างของเขาฟังก์ชั่นนั้นได้รับการออกแบบอย่างไม่เหมาะสมตัวอย่างของเขาคือบั๊ก (ฉันเห็นด้วยกับข้อสรุปนี้ว่าควรแยกรหัสออก) คำตอบของการหลอกลวงไม่ใช่คำจำกัดความที่เหมาะสมของสถานการณ์ ฟังก์ชันจะทำงานภายในขอบเขตที่กว้างขึ้นเสมอและตัวอย่างของเขาก็ง่ายเกินไป เราทุกคนจะเห็นด้วยกับเขาว่าฟังก์ชันนั้นไร้ประโยชน์โดยสิ้นเชิงเพราะส่งคืนค่าคงที่ ฟังก์ชั่นนั้นเป็นการออกแบบที่ไม่ดี แต่อย่างใด หากคุณต้องการแสดงให้เห็นว่าการปฏิบัตินั้นไม่ดีโปรดมาพร้อมกับตัวอย่างที่เกี่ยวข้อง การเปลี่ยนชื่อตัวแปรตลอดทั้งแอปพลิเคชันไม่ใช่เรื่องใหญ่หากมี IDE ที่ดี (หรือเครื่องมือ) คำถามเกี่ยวกับขอบเขตของตัวแปรไม่ใช่ความแตกต่างของขอบเขตกับฟังก์ชัน มีเวลาที่เหมาะสมสำหรับฟังก์ชันในการทำหน้าที่ในกระบวนการ (นั่นคือเหตุผลที่สร้างขึ้นตั้งแต่แรก) และในเวลาที่เหมาะสมนั้นอาจมีผลต่อการทำงานของแอปพลิเคชันโดยรวมดังนั้นการทำงานกับตัวแปรส่วนกลาง . คำตอบของ xzyfer คือคำสั่งที่ไม่มีการโต้แย้ง Globals มีอยู่ในแอปพลิเคชันเช่นเดียวกับหากคุณมีฟังก์ชันขั้นตอนหรือการออกแบบ OOP สองวิธีถัดไปในการเปลี่ยนแปลงมูลค่าของโลกมีลักษณะเหมือนกัน: ดังนั้นการทำงานกับตัวแปรทั่วโลก คำตอบของ xzyfer คือคำสั่งที่ไม่มีการโต้แย้ง Globals มีอยู่ในแอปพลิเคชันเช่นเดียวกับหากคุณมีฟังก์ชันขั้นตอนหรือการออกแบบ OOP สองวิธีถัดไปในการเปลี่ยนแปลงมูลค่าของโลกมีลักษณะเหมือนกัน: ดังนั้นการทำงานกับตัวแปรทั่วโลก คำตอบของ xzyfer คือคำสั่งที่ไม่มีการโต้แย้ง Globals มีอยู่ในแอปพลิเคชันเช่นเดียวกับหากคุณมีฟังก์ชันขั้นตอนหรือการออกแบบ OOP สองวิธีถัดไปในการเปลี่ยนแปลงมูลค่าของโลกมีลักษณะเหมือนกัน:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
ในทั้งสองกรณีคือค่าของ $ z ที่เปลี่ยนแปลงภายในฟังก์ชันเฉพาะ ในการเขียนโปรแกรมทั้งสองวิธีคุณสามารถทำการเปลี่ยนแปลงเหล่านั้นในที่อื่น ๆ ในโค้ดได้ คุณสามารถพูดได้ว่าการใช้ global คุณสามารถเรียก $ z ได้ทุกที่และเปลี่ยนที่นั่น ใช่คุณสามารถ. แต่คุณจะ? และเมื่อทำในสถานที่ที่ไม่เหมาะสมแล้วจะไม่เรียกว่าจุดบกพร่องหรือไม่?
Bob Fanger แสดงความคิดเห็นเกี่ยวกับ xzyfer
ทุกคนควรใช้อะไรและโดยเฉพาะอย่างยิ่งคำหลัก 'global'? ไม่ แต่เช่นเดียวกับการออกแบบประเภทใด ๆ ลองวิเคราะห์ว่ามันขึ้นอยู่กับอะไรและขึ้นอยู่กับอะไร พยายามค้นหาว่าเมื่อใดเปลี่ยนแปลงและเปลี่ยนแปลงอย่างไร การเปลี่ยนแปลงค่าส่วนกลางควรเกิดขึ้นเฉพาะกับตัวแปรที่สามารถเปลี่ยนแปลงได้กับทุกคำขอ / การตอบกลับ นั่นคือเฉพาะกับตัวแปรที่เป็นของโฟลว์การทำงานของกระบวนการเท่านั้นไม่ใช่เพื่อการนำไปใช้ทางเทคนิค การเปลี่ยนเส้นทางของ URL ไปยังหน้าการเข้าสู่ระบบเป็นของขั้นตอนการทำงานของกระบวนการซึ่งเป็นคลาสการนำไปใช้สำหรับอินเทอร์เฟซไปยังการใช้งานทางเทคนิค คุณสามารถเปลี่ยนเวอร์ชันหลังได้ในระหว่างเวอร์ชันต่างๆของแอปพลิเคชัน แต่ไม่ควรเปลี่ยนทุกครั้งที่มีการร้องขอ / การตอบกลับ
เพื่อให้เข้าใจมากขึ้นว่าเมื่อใดที่เป็นปัญหาในการทำงานกับ globals และคำหลัก global และเมื่อใดที่ฉันจะไม่แนะนำประโยคถัดไปซึ่งมาจาก Wim de Bie เมื่อเขียนเกี่ยวกับบล็อก: 'Personal yes, private no' เมื่อฟังก์ชันกำลังเปลี่ยนค่าของตัวแปรส่วนกลางเพื่อประโยชน์ในการทำงานของตัวเองฉันจะเรียกการใช้ตัวแปรส่วนกลางและจุดบกพร่องนั้นเป็นการส่วนตัว แต่เมื่อมีการเปลี่ยนแปลงตัวแปร global สำหรับการประมวลผลที่เหมาะสมของแอปพลิเคชันโดยรวมเช่นการเปลี่ยนเส้นทางของผู้ใช้ไปยังหน้าเข้าสู่ระบบนั่นคือในความคิดของฉันอาจเป็นการออกแบบที่ดีไม่ใช่โดยความหมายที่ไม่ดีและไม่แน่นอน ต่อต้านรูปแบบ
ในการย้อนกลับไปที่คำตอบของ Gordon, Deceze และ xzyfer: พวกเขาทั้งหมดมี 'ใช่ส่วนตัว' (และข้อบกพร่อง) เป็นตัวอย่าง นั่นคือเหตุผลที่พวกเขาไม่เห็นด้วยกับการใช้โกลบัล ฉันก็จะทำเกินไป อย่างไรก็ตามพวกเขาไม่ได้มาพร้อมกับตัวอย่าง "ใช่ส่วนตัวไม่ส่วนตัว" เหมือนที่ฉันเคยทำในคำตอบนี้หลายครั้ง