Java เป็น Clojure เขียนใหม่


97

ฉันเพิ่งถูก บริษัท ขอให้เขียนแอปพลิเคชัน Java ขนาดใหญ่ (50,000 บรรทัดเดียว) ใหม่ (เว็บแอปที่ใช้ JSP และ servlets) ใน Clojure มีใครมีคำแนะนำเกี่ยวกับสิ่งที่ฉันควรระวังอีกบ้าง?

โปรดจำไว้ว่าฉันรู้จักทั้ง Java และ Clojure ค่อนข้างดี

อัปเดต

ฉันเขียนใหม่และเริ่มผลิต มันค่อนข้างแปลกเพราะการรีไรท์จบลงเร็วมากจนเสร็จภายใน 6 สัปดาห์ เนื่องจากไม่จำเป็นต้องมีฟังก์ชั่นการใช้งานจำนวนมาก แต่ก็จบลงด้วย Clojure 3000 บรรทัด

ฉันได้ยินว่าพวกเขามีความสุขกับระบบและมันทำในสิ่งที่พวกเขาต้องการ ข้อเสียเพียงอย่างเดียวคือผู้ชายที่ดูแลระบบต้องเรียนรู้ Clojure ตั้งแต่เริ่มต้นและเขาก็ถูกลากเข้าไปเตะและกรีดร้อง ฉันได้รับโทรศัพท์จากเขาเมื่อวันก่อนบอกว่าเขารัก Lisp ตอนนี้ .. ตลกดี :)

นอกจากนี้ฉันควรพูดถึง Vaadin ให้ดี การใช้ Vaadin อาจจะช่วยประหยัดเวลาได้มากและความสั้นของโค้ดเหมือนกับที่ Clojure ทำ .. Vaadin ยังคงเป็นเว็บเฟรมเวิร์กอันดับต้น ๆ ที่ฉันเคยใช้แม้ว่าตอนนี้ฉันกำลังเรียนรู้ ClojureScript ด้วยความโกรธก็ตาม! (โปรดทราบว่าทั้ง Vaadin และ ClojureScript ใช้เฟรมเวิร์ก GUI ของ Google ภายใต้ประทุน)


55
ฉันต้องการทำงานให้กับ บริษัท ของคุณ
mtyaka

4
บริษัท ป้องกันบางแห่งในยุโรปเริ่มใช้ Clojure (ฉันได้ยินมา) แต่จำชื่อไม่ได้แล้ว :)
appshare.co

1
@Zubair: 50,000 Java LOC ไม่ได้อยู่ใกล้กับ "ใหญ่โต" นี่เป็นโครงการขนาดเล็กมาก ฉันมีโปรเจ็กต์ Java 250KLOC ถึง 300KLOC ที่นี่และมีขนาดกลาง ... ดีที่สุด
SyntaxT3rr0r

5
อันที่จริงฉันอาจทำผิดพลาดโดยกล่าวถึงขนาดของ codebase ว่าการลดขนาดโค้ดนั้นเป็นไปอย่างยุติธรรมไม่ใช่จุดมุ่งหมายของการเขียนซ้ำ จุดมุ่งหมายมีสองเท่า: 1) เพื่อให้โค้ดเบสเข้าใจได้ง่ายขึ้นและถูกกว่าในการรักษาโค้ด 2) อนุญาตให้ผู้ใช้เครื่องมือขยายผลิตภัณฑ์โดยใช้ตัวแก้ไข Clojure ในเว็บเบราว์เซอร์ (โดยใช้ eval และความดีไดนามิก Clojure อื่น ๆ ซึ่งมีราคาแพงกว่า ทำใน Java)
appshare.co

1
เฮ้ ... เพิ่งเห็นคำถามเก่ากว่านี้แล้วสงสัยว่ารีไรท์เป็นยังไง?
Levand

คำตอบ:


82

"ปัญหาการแปล" ที่ใหญ่ที่สุดน่าจะเกิดจากระเบียบวิธี Java / OOP ไปสู่กระบวนทัศน์การเขียนโปรแกรม Clojure / functional

โดยเฉพาะอย่างยิ่งแทนที่จะมีสถานะที่เปลี่ยนแปลงไม่ได้ภายในวัตถุ "Clojure way" คือการแยกสถานะที่เปลี่ยนแปลงไม่ได้ออกจากกันอย่างชัดเจนและพัฒนาฟังก์ชันบริสุทธิ์ (ปราศจากผลข้างเคียง) คุณคงรู้ทั้งหมดนี้แล้ว :-)

อย่างไรก็ตามปรัชญานี้มีแนวโน้มที่จะนำไปสู่รูปแบบการพัฒนาแบบ "จากล่างขึ้นบน" ซึ่งคุณจะมุ่งเน้นไปที่ความพยายามครั้งแรกในการสร้างชุดเครื่องมือที่เหมาะสมเพื่อแก้ปัญหาของคุณจากนั้นจึงต่อเข้าด้วยกันในตอนท้าย หน้าตาอาจจะประมาณนี้

  1. ระบุโครงสร้างข้อมูลหลักและแปลงเป็นแผนที่ Clojure ที่ไม่เปลี่ยนรูปหรือข้อกำหนดของบันทึก อย่ากลัวที่จะซ้อนแผนที่ที่ไม่เปลี่ยนรูปจำนวนมาก - มันมีประสิทธิภาพมากเนื่องจากโครงสร้างข้อมูลถาวรของ Clojure ควรค่าแก่การดูวิดีโอนี้เพื่อเรียนรู้เพิ่มเติม

  2. พัฒนาไลบรารีขนาดเล็กของฟังก์ชันเชิงตรรกะทางธุรกิจที่บริสุทธิ์ซึ่งทำงานบนโครงสร้างที่ไม่เปลี่ยนรูปเหล่านี้ (เช่น "เพิ่มสินค้าลงในตะกร้าสินค้า") คุณไม่จำเป็นต้องทำสิ่งเหล่านี้ทั้งหมดในครั้งเดียวเนื่องจากสามารถเพิ่มเพิ่มเติมในภายหลังได้ง่าย แต่จะช่วยได้ในช่วงต้นเพื่ออำนวยความสะดวกในการทดสอบและพิสูจน์ว่าโครงสร้างข้อมูลของคุณใช้งานได้ ..... ไม่ว่าจะด้วยวิธีใดก็ตาม ชี้ให้เห็นว่าคุณสามารถเริ่มเขียนสิ่งที่มีประโยชน์แบบโต้ตอบได้ที่ REPL

  3. แยกการพัฒนารูทีนการเข้าถึงข้อมูลที่สามารถคงโครงสร้างเหล่านี้ไปยัง / จากฐานข้อมูลหรือเครือข่ายหรือโค้ด Java เดิมได้ตามต้องการ เหตุผลที่ต้องแยกสิ่งนี้ออกจากกันคือคุณไม่ต้องการให้ตรรกะการคงอยู่ที่เชื่อมโยงกับฟังก์ชัน "ตรรกะทางธุรกิจ" ของคุณ คุณอาจต้องการดูClojureQLสำหรับสิ่งนี้แม้ว่าจะค่อนข้างง่ายในการตัดโค้ดการคงอยู่ของ Java ที่คุณชอบ

  4. เขียนการทดสอบหน่วย (เช่นด้วยclojure.test ) ที่ครอบคลุมทั้งหมดข้างต้น นี่เป็นสิ่งสำคัญอย่างยิ่งในภาษาไดนามิกเช่น Clojure เนื่องจาก a) คุณไม่มีตาข่ายนิรภัยมากนักจากการตรวจสอบประเภทคงที่และ b) ช่วยให้แน่ใจว่าโครงสร้างระดับล่างของคุณทำงานได้ดีก่อนที่คุณจะสร้างมากเกินไป ด้านบนของพวกเขา

  5. ตัดสินใจว่าคุณต้องการใช้ประเภทการอ้างอิงของ Clojure อย่างไร (vars, refs, agent และ atoms) เพื่อจัดการสถานะระดับแอ็พพลิเคชันที่ไม่แน่นอนแต่ละส่วน พวกเขาทั้งหมดทำงานในลักษณะเดียวกัน แต่มีความหมายของธุรกรรม / การทำงานพร้อมกันที่แตกต่างกันขึ้นอยู่กับสิ่งที่คุณกำลังพยายามทำ Refs น่าจะเป็นตัวเลือกเริ่มต้นของคุณ - อนุญาตให้คุณใช้พฤติกรรมการทำธุรกรรม STM "ปกติ" โดยการตัดโค้ดใด ๆ ในบล็อก (dosync ... )

  6. เลือกเว็บเฟรมเวิร์กโดยรวมที่ถูกต้อง - Clojure มีค่อนข้างน้อยอยู่แล้ว แต่ฉันขอแนะนำให้ Ring - ดูวิดีโอ " One Ring To Bind Them " ที่ยอดเยี่ยมนี้พร้อมทั้งFleetหรือEnliveหรือHiccupขึ้นอยู่กับปรัชญาการทำเทมเพลตของคุณ จากนั้นใช้สิ่งนี้เพื่อเขียนเลเยอร์การนำเสนอของคุณ (โดยมีฟังก์ชันเช่น "แปลตะกร้าสินค้านี้เป็นส่วน HTML ที่เหมาะสม")

  7. สุดท้ายเขียนใบสมัครของคุณโดยใช้เครื่องมือข้างต้น หากคุณทำตามขั้นตอนข้างต้นอย่างถูกต้องแล้วนี่จะเป็นเรื่องง่ายเพราะคุณจะสามารถสร้างแอปพลิเคชันทั้งหมดได้ด้วยองค์ประกอบที่เหมาะสมของส่วนประกอบต่างๆโดยมีแผ่นสำเร็จรูปน้อยมาก

นี่เป็นลำดับคร่าวๆที่ฉันจะโจมตีปัญหาเนื่องจากมันแสดงถึงลำดับการอ้างอิงในโค้ดของคุณอย่างกว้าง ๆ และด้วยเหตุนี้จึงเหมาะสำหรับความพยายามในการพัฒนา "จากล่างขึ้นบน" แม้ว่าจะอยู่ในรูปแบบว่องไว / ทำซ้ำที่ดี แต่คุณอาจพบว่าตัวเองผลักดันไปข้างหน้า แต่เนิ่นๆเพื่อไปสู่ผลิตภัณฑ์ขั้นสุดท้ายที่พิสูจน์ได้จากนั้นจึงกระโดดกลับไปที่ขั้นตอนก่อนหน้านี้ค่อนข้างบ่อยเพื่อขยายฟังก์ชันการทำงานหรือตัวปรับแต่งตามต้องการ

ps ถ้าคุณทำตามวิธีการข้างต้นฉันจะติดใจที่ได้ยินว่า Clojure ต้องใช้กี่บรรทัดเพื่อให้ตรงกับฟังก์ชันของ Java 50,000 บรรทัด

อัปเดต : เนื่องจากเดิมทีโพสต์นี้เขียนขึ้นมีเครื่องมือ / ไลบรารีพิเศษสองสามรายการที่อยู่ในหมวดหมู่ "ต้องตรวจสอบ":

  • นัวร์ - เว็บเฟรมเวิร์กที่สร้างขึ้นบน Ring
  • Korma - DSL ที่ดีมากสำหรับการเข้าถึงฐานข้อมูล SQL

4
Nitpick re: "ตัดสินใจเลือกประเภทการอ้างอิง STM ของ Clojure ที่คุณต้องการใช้เพื่อจัดการสถานะระดับแอปพลิเคชันที่ไม่แน่นอนของแต่ละส่วน": มีประเภทอ้างอิง STM เพียงประเภทเดียว IRef อื่น ๆ ไม่เกี่ยวข้องกับ STM อย่างอื่นดูเหมือนคำแนะนำที่มั่นคง

อืม ... ฉันเดาว่าฉันนับ refs ตัวแทนและอะตอมเป็นส่วนหนึ่งของระบบ Clojure STM / concurrency ตัวอย่างเช่นพวกเขาทั้งหมดสนับสนุนตัวตรวจสอบความถูกต้องและตัวแทนจะประสานงานกับการทำธุรกรรม แต่ฉันเข้าใจแล้วการอ้างอิงคือรูปแบบธุรกรรม "หลัก" จะแก้ไขอย่างรวดเร็ว
mikera

2
ถ้าเพียงแค่ฉันสามารถให้ +1 นี้ได้มากขึ้น ฉันดูทั้งสองวิดีโอที่คุณอ้างถึงและมันยอดเยี่ยมมาก ขอบคุณ.
jdl

1
ตอนนี้นัวร์เลิกใช้งานแล้ว ฉันคิดว่าคุณต้องพูดถึงเกี่ยวกับการแต่งเพลงแทนนัวร์
hsestupin

ลิงค์ One Ring To Bind พวกเขาเสีย!
Adam Arold

5

โครงการปัจจุบันของคุณมีส่วนใดบ้างของ Java การบันทึกธุรกรรมฐานข้อมูลธุรกรรมสำแดง / EJB เลเยอร์เว็บ (คุณกล่าวถึง JSP, servlets) ฯลฯ ฉันสังเกตเห็นว่าระบบนิเวศ Clojure มีไมโครเฟรมเวิร์กและไลบรารีต่างๆโดยมีเป้าหมายเพื่อทำงานหนึ่งอย่างและทำได้ดี ฉันขอแนะนำให้ประเมินห้องสมุดตามความต้องการของคุณ (และจะขยายขนาดในโครงการขนาดใหญ่หรือไม่) และตัดสินใจอย่างมีข้อมูล (ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียนbitumenframework ) สิ่งที่ควรทราบอีกประการหนึ่งคือกระบวนการสร้าง - หากคุณต้องการการตั้งค่าที่ซับซ้อน (dev, testing, staging, prod) คุณอาจต้องแบ่งโครงการออกเป็นโมดูลและมีสคริปต์กระบวนการสร้างสำหรับ ความสะดวก


Servlets, JSP, กรอบการคงอยู่ที่สร้างขึ้นเอง (อายุ 10 ปี) และ pojos แต่ไม่มี EJB
appshare.co

4
Servlets สามารถแทนที่ได้อย่างง่ายดายด้วย Ring + Compojure IMHO และ JSPs สามารถแทนที่ด้วย StringTemplate (หรือเทมเพลต FreeMarker / Velocity) ความคงอยู่ใน Clojure จะแตกต่างจาก Java หากคุณต้องการการแมปเชิงสัมพันธ์คุณสามารถดูที่ Clj-Record และ SQLRat (ยังไม่สมบูรณ์) ClojureQL รองรับเฉพาะ MySQL และ PostgreSQL ในขณะนี้ AFAICT ข้อ จำกัด ในปัจจุบันใน ccsql ในการไม่อนุญาตขีดล่างในชื่อคอลัมน์อาจเป็นเรื่องที่น่าประหลาดใจ ฉันคิดว่าการพูดคุยเกี่ยวกับแง่มุมการพัฒนาในรายการ Clojure ตามที่ต้องการจะเป็นประโยชน์ ขอให้โชคดีในโครงการ!
Shantanu Kumar

เนื่องจากโครงการนั้นฉันได้สร้างแอปพลิเคชันอื่นด้วย Clojure และ Clojurescript (nemcv.com) และฉันใช้ Ring ตอนนี้ลองใช้ ClojureQL แต่เปลี่ยนเป็น Korma เพื่อเข้าถึงฐานข้อมูล สามารถดูผลงานล่าสุดได้ที่github.com/zubairq/coils
appshare.co

4

ฉันพบว่าส่วนที่ยากที่สุดคือการคิดถึงฐานข้อมูล ทำการทดสอบเพื่อค้นหาเครื่องมือที่เหมาะสมที่คุณต้องการใช้ที่นั่น


1
ฉันได้ลองใช้ clojureql สำหรับการเข้าถึงข้อมูลแล้ว แต่มันแตกต่างอย่างสิ้นเชิงกับรูปแบบการเข้าถึงฐานข้อมูลของ Java ซึ่งขึ้นอยู่กับวัตถุ คุณไม่สนใจว่าคุณใช้การเข้าถึงฐานข้อมูลใดสำหรับ Java และคุณใช้อะไรกับ Clojure
appshare.co

1
เราลงเอยด้วยการคิดทบทวนสิ่งต่างๆมากมายและไปกับ mongodb เนื่องจากการคงอยู่ของโครงสร้างข้อมูล clojure นั้นเป็นธรรมชาติมาก
LenW
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.