การปรับโครงสร้างใหม่
เมื่อเรามีฟังก์ชั่นการทำงานแล้ว เราก็สามารถย้อนกลับไปและคิดว่าจะจัดโครงสร้างโค้ดของเราอย่างไรให้ดีที่สุด เป้าหมายคือการทำให้ปลั๊กอินของเรามีความชัดเจน เข้าใจได้ และบำรุงรักษาได้มากที่สุดเท่าที่จะเป็นไปได้ กระบวนการปรับปรุงและปรับปรุงโครงสร้างของโค้ดที่มีอยู่โดยไม่เปลี่ยนพฤติกรรมนี้เรียกว่าการปรับโครงสร้างใหม่
นี่คือฟังก์ชันเริ่มต้นอีกครั้ง:
(define (scheme-hello-world)
;; Set the message handler to output the message to a GUI dialog box
(lumi-message-set-handler 0)
(lumi-message "Hello world!\n")
;; Set the message handler to output the message to the Error Console
(lumi-message-set-handler 2)
(lumi-message "Hello world!\n")
;; Send the message to the terminal, the OS window that launched Lumi
(display "Hello world!\n"))ชื่อฟังก์ชันคือชื่อของฟังก์ชัน และพารามิเตอร์คือสิ่งที่ฟังก์ชันยอมรับเป็นอินพุต เนื้อความคือบล็อกของโค้ดที่ทำงานเมื่อมีการเรียกใช้ฟังก์ชัน
แบบฟอร์มบทคัดย่อ:
(define (function-name parameter)
body)การทำซ้ำโค้ด
ลบการทำซ้ำในช่วงต้น (lumi-message "Hello world!\n") ถูกทำซ้ำสองครั้ง และสตริงข้อความถูกทำซ้ำสามครั้ง ตัวแปรแก้สตริงที่ซ้ำกัน
ตัวแปร
ใน Scheme ตัวแปรจะมี “ขอบเขต” ซึ่งเป็นที่ทราบ และขอบเขตนั้นถูกตั้งค่าโดยใช้คำสั่ง let ตัวแปรถูกผูกไว้กับค่าในส่วนการโยง และตัวแปรมีขอบเขตอยู่ในเนื้อหาที่อนุญาต ตัวแปรเป็นที่รู้จักเฉพาะภายในบล็อกการอนุญาตและไม่สามารถเข้าถึงได้ภายนอก
(let ((variable value))
body)แนะนำตัวแปรที่เรียกว่า “ข้อความ”:
(define (scheme-hello-world)
(let ((message "Hello world!\n"))
;; Set the message handler to output the message to a GUI dialog box
(lumi-message-set-handler 0)
(lumi-message message)
;; Set the message handler to output the message to the Error Console
(lumi-message-set-handler 2)
(lumi-message message)
;; Send the message to the terminal, the OS window that launched Lumi
(display message)))ในตัวอย่างของเรา เราได้ใช้ตัวแปรชื่อ “ข้อความ” ที่เชื่อมโยงกับสตริง “Hello world!\n” ซึ่งช่วยให้เราสามารถเปลี่ยนแปลงเนื้อหาข้อความได้เพียงครั้งเดียวแทนที่จะเป็นสามครั้ง ซึ่งช่วยลดโอกาสที่จะเกิดข้อผิดพลาดและทำให้โค้ดมีความยืดหยุ่นมากขึ้น
การแยกฟังก์ชั่น
ในการเขียนโปรแกรมเชิงฟังก์ชัน การปรับโครงสร้างโค้ดเพื่อแยกตรรกะที่ใช้ซ้ำได้ออกเป็นฟังก์ชันที่แยกจากกันถือเป็นแนวทางปฏิบัติทั่วไป เมื่อทำเช่นนี้ ฟังก์ชันหลัก จะง่ายขึ้นมากและมุ่งเน้นไปที่เป้าหมายระดับสูงมากขึ้น ในขณะที่ ฟังก์ชันที่แยกออกมา จะดูซับซ้อนมากขึ้นเนื่องจากจะจัดการกับตรรกะโดยละเอียด นี่เป็นความตั้งใจและสอดคล้องกับหลักการสำคัญของการเขียนโปรแกรมเชิงฟังก์ชัน เช่น ความเป็นโมดูล การแยกข้อกังวล และความสามารถในการอ่าน นี่คือการปรับโครงสร้างใหม่ สวัสดีชาวโลก! หลังจากการสกัด
แยกตรรกะ:
# !/usr/bin/env lumi-scheme-interpreter-0.1
;; Main Function
(define (scheme-hello-world)
(let ((message "Hello world!\n"))
(send-message message 'gui)
(send-message message 'error-console)
(send-message message 'terminal)))
;; Function to handle message output to various destinations
(define (send-message message output)
(cond
;; Send to the Error Console
((eq? output 'error-console)
;; Set the handler to Error Console
(lumi-message-set-handler 2)
(lumi-message message))
;; Send to the GUI dialog box
((eq? output 'gui)
;; Set the handler to GUI dialog
(lumi-message-set-handler 0)
(lumi-message message))
;; Send to the terminal window
((eq? output 'terminal)
;; Terminal output is handled with display
(display message)))
;; Restore the default message handler to the Error Console
(lumi-message-set-handler 2))
(scheme-register-procedure "scheme-hello-world"
"Hello world!"
"A Scheme procedure plug-in"
"Mark Sweeney"
"Under GNU GENERAL PUBLIC LICENSE Version 3"
"2024")
(scheme-menu-register
"scheme-hello-world"
"<Image>/Funky")สัญลักษณ์
ในตัวอย่างข้างต้น มีการใช้ชนิดข้อมูลที่เรียกว่าสัญลักษณ์ เช่น ‘gui’ สัญลักษณ์จะถูกส่งผ่านเป็นพารามิเตอร์ไปยังฟังก์ชันส่งข้อความ และสามารถใช้เพื่อตัดสินใจตามเงื่อนไขง่ายๆ เช่นเดียวกับคีย์สัญลักษณ์ พวกมันเป็นตัวระบุที่ไม่ซ้ำกัน สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสัญลักษณ์ โปรดไปที่ หน้านี้
ลดความซับซ้อนของฟังก์ชันหลัก
ในฟังก์ชันดั้งเดิม (scheme-hello-world) ตรรกะทั้งหมดสำหรับการส่งข้อความไปยังเอาต์พุตต่างๆ (GUI, Error Console, Terminal) ได้ถูกผสมเข้ากับฟังก์ชันหลัก หลังจากการปรับโครงสร้างใหม่ ฟังก์ชันหลักจะเน้นไปที่ สิ่งที่ต้องทำ เพื่อส่งข้อความไปยังปลายทางต่างๆ
ฟังก์ชันหลักที่ปรับโครงสร้างใหม่นั้นง่ายกว่า:
- ระบุวัตถุประสงค์อย่างชัดเจน: ส่งข้อความเดียวกันไปยังเอาต์พุตหลายรายการ
- หลีกเลี่ยงไม่ให้ตรรกะหลักยุ่งเหยิงด้วยโค้ดที่ซ้ำกัน เช่น การตั้งค่าตัวจัดการข้อความสำหรับเอาต์พุตที่แตกต่างกัน
- อ่านและทำความเข้าใจได้ง่ายขึ้นในทันที
ความซับซ้อนของฟังก์ชันที่แยกออกมา
ในทางตรงกันข้าม ฟังก์ชัน (ส่งข้อความ) คือตำแหน่งที่มีตรรกะโดยละเอียดอยู่ ตอนนี้จัดการรูปแบบการทำงานที่แตกต่างกันสำหรับแต่ละเอาต์พุต (GUI, Error Console, Terminal) ฟังก์ชันนี้ซับซ้อนกว่าเดิมเล็กน้อย แต่ตอนนี้ รวมศูนย์ และ แยก แล้ว
เกี่ยวข้องกับสิ่งนี้กับการเขียนโปรแกรมเชิงฟังก์ชัน
ในการเขียนโปรแกรมเชิงฟังก์ชัน ฟังก์ชันต่างๆ จะถูกมองว่าเป็น พลเมืองชั้นหนึ่ง ซึ่งหมายความว่าสามารถนำกลับมาใช้ใหม่ ส่งต่อ และรวมเข้าด้วยกันเพื่อสร้างพฤติกรรมที่ซับซ้อนมากขึ้น เป้าหมายคือ:- แยกย่อยปัญหา ออกเป็นชิ้นเล็กๆ อิสระ
- แยกความซับซ้อน ออกเป็นฟังก์ชันเล็กๆ ที่จัดการงานเฉพาะ เช่น
send-message - ทำให้ฟังก์ชันระดับสูงกว่าเรียบง่าย เพื่อให้สามารถมุ่งเน้นไปที่การประสานโฟลว์ของข้อมูลและการดำเนินการ โดยไม่จำเป็นต้องทราบรายละเอียดว่าแต่ละงานบรรลุผลสำเร็จอย่างไร
- การแยกข้อกังวล: ฟังก์ชันจะดูแลวิธีการส่งข้อความตามประเภทเอาต์พุต ซึ่งแยกตรรกะนี้ออกจากฟังก์ชันหลัก
- ความเป็นโมดูล: ด้วยการจัดการตรรกะการส่งข้อความทั้งหมดในที่เดียว เราจึงสามารถทำการเปลี่ยนแปลงได้อย่างง่ายดาย (เช่น การเพิ่มตัวเลือกเอาต์พุตใหม่) โดยไม่ต้องเปลี่ยนแปลงฟังก์ชันหลัก
- การนำกลับมาใช้ใหม่ได้: ฟังก์ชัน
send-messageสามารถนำมาใช้ซ้ำได้ ซึ่งหมายความว่าหากเราต้องการส่งข้อความไปยังเอาต์พุตหลายรายการในโค้ดของเรา เราก็สามารถเรียกใช้ฟังก์ชันนี้แทนการเขียนตรรกะที่คล้ายกันใหม่ได้
ด้วยการปรับโครงสร้างใหม่ ฟังก์ชันหลักในตัวอย่างนี้จะกลายเป็นคำสั่ง ประกาศ ของสิ่งที่เกิดขึ้น (“ส่งข้อความไปยังสถานที่สามแห่ง”) ในขณะที่ความซับซ้อนของวิธีการส่งข้อความเหล่านั้นถูกแยกออกไปในฟังก์ชัน send-message