JavaRush /จาวาบล็อก /Random-TH /คอฟฟี่เบรค #88 พลังของเมทาดาทา: วิธีทำงานกับโค้ดสปาเก็ตตี...

คอฟฟี่เบรค #88 พลังของเมทาดาทา: วิธีทำงานกับโค้ดสปาเก็ตตี้ การรวบรวมขยะใน Java - วิธีการทำงานและข้อดีของมันคืออะไร

เผยแพร่ในกลุ่ม

พลังของเมทาดาทา: วิธีทำงานกับโค้ดสปาเก็ตตี้

ที่มา: Hackernoon เราทุกคนพยายามใช้วิธีการทั่วไปและรูปแบบที่ทราบเพื่อสร้างแอปพลิเคชันโดยใช้ความพยายามน้อยที่สุดและให้ผลกระทบสูงสุด เรามีไลบรารีที่ยอดเยี่ยมและเฟรมเวิร์กอันทรงพลังที่ดำเนินการตามปกติให้เรา เราใช้ทั้งหมดนี้เพื่อมุ่งเน้นเฉพาะตรรกะทางธุรกิจเท่านั้น อย่างไรก็ตาม การแสวงหานี้มักจะนำเราไปสู่โค้ดสปาเก็ตตี้ โดยเฉพาะอย่างยิ่งเมื่อเป็นเรื่องของการนำฟังก์ชันไปใช้โดยไม่มีโซลูชันสำเร็จรูป ในบทความนี้ ฉันต้องการแบ่งปันเครื่องมืออันทรงพลังอย่างหนึ่งที่นักพัฒนาบางคนไม่เห็นคุณค่าจากประสบการณ์ของฉัน เครื่องมือนี้มีอยู่ในภาษาการเขียนโปรแกรมส่วนใหญ่ และมักใช้ในหลายเฟรมเวิร์ก - คำอธิบายประกอบ คอฟฟี่เบรค #88  พลังของเมทาดาทา: วิธีทำงานกับโค้ดสปาเก็ตตี้  การรวบรวมขยะใน Java - วิธีการทำงานและข้อดีของมันคืออะไร - 1

คุณชอบสปาเก็ตตี้ไหม?

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

ช่วยเหลือในคำอธิบายประกอบ

บันทึกแอปพลิเคชันจากโค้ดสปาเก็ตตี้คำอธิบายประกอบนี้ ในการกำจัดโค้ดที่ไม่รองรับ ฉันจำเป็นต้องย้ายตรรกะในการพิจารณาว่าคอลัมน์ใดที่จะแยกวิเคราะห์ ประเภทข้อมูลในเซลล์ และข้อมูลอื่นๆ ทั้งหมดไปยังตำแหน่งอื่น เมื่อต้องการทำสิ่งนี้ ฉันได้สร้างคำอธิบายประกอบซึ่งฉันระบุชื่อคอลัมน์สำหรับแต่ละฟิลด์คลาส ในคำอธิบายประกอบ ฉันยังเพิ่มตัวแปรที่ช่วยให้คุณสามารถเลือกสีและแบบอักษรของเซลล์ได้ ดังนั้นโค้ดในคลาสการแยกวิเคราะห์จึงลดลงอย่างมาก โปรเซสเซอร์เพียงตัวเดียวเท่านั้นที่สร้างสเปรดชีตแบบไดนามิกตามพารามิเตอร์ที่นำมาจากคำอธิบายประกอบ มันเป็นชัยชนะ จากนั้น หากต้องการเปลี่ยนแปลงแอปพลิเคชัน ฉันเพียงแค่ต้องสร้างคลาสที่มีคำอธิบายประกอบ วิธีแก้ปัญหานี้ชวนให้นึกถึงไลบรารีของ Jackson ซึ่งแยกวิเคราะห์ JSON โดยใช้คำอธิบายประกอบ และฉันคิดว่าไม่จำเป็นต้องบอกว่า Jackson หรือไลบรารีที่คล้ายกันสะดวกเพียงใด
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnExcel {

    String name() default "";

    int position();

    ExcelColumnDataFormat cellTypePattern() default ExcelColumnDataFormat.NONE;

    IndexedColors cellColor() default IndexedColors.AUTOMATIC;

    ExcelTotalFormula total() default ExcelTotalFormula.NONE;

}
ColumnExcel columnExcel = field.getAnnotation(ColumnExcel.class);
เมื่อแอปพลิเคชันพัฒนาขึ้น ก็ได้รับคำอธิบายประกอบใหม่ที่สามารถใช้เพื่อสร้างเซลล์ในสเปรดชีตที่มีฟังก์ชันอยู่ข้างใน เขตข้อมูลต่างๆ สามารถคูณ ลบ และสามารถใช้ฟังก์ชัน Excel ทั่วไปได้ ฉันยังเพิ่มแถวผลรวมเพื่อแสดงผลรวมตามคอลัมน์ และฉันทำทั้งหมดนี้เพียงแค่แก้ไข parser หลักเล็กน้อยและเพิ่มคำอธิบายประกอบให้กับคลาส
@ColumnExcel(
            name = "Views",
            position = 4,
            total = ExcelTotalFormula.SUM)
    private BigDecimal variableC;

    @ColumnExcelFormula(
            name = "Conversion",
            position = 5,
            cellTypePattern = CellDataTypeFormatPattern.PERCENTAGE
    )
    public String variableD(int rowNumber) {
        return new CellAddress(rowNumber, 4).formatAsString() + "*"
		+ new CellAddress(rowNumber, 2).formatAsString();
    }

    @ColumnExcelTotalFormula(position = 4, cellTypePattern = CellDataTypeFormatPattern.RUR)
    public static String getVariableCTotalFormula(int firstRowNum, int lastRowNum) {
        return "SUM( " + new CellAddress(firstRowNum, 4).formatAsString() + ":"
		+ new CellAddress(lastRowNum, 4).formatAsString() + ")";
    }

การรวบรวมขยะใน Java - วิธีการทำงานและข้อดีของมันคืออะไร

ที่มา: Dev.to Garbage collection หมายถึงการทำลายหรือล้างวัตถุที่ไม่ได้ใช้ในหน่วยความจำ Java จัดการการจัดสรรหน่วยความจำโดยอัตโนมัติเนื่องจากเมื่อวัตถุถูกสร้างขึ้น มันจะใช้หน่วยความจำบางส่วนบนฮีป คอฟฟี่เบรค #88  พลังของเมทาดาทา: วิธีทำงานกับโค้ดสปาเก็ตตี้  การรวบรวมขยะใน Java - วิธีการทำงานและข้อดีของมันคืออะไร - 2

มันทำงานอย่างไร?

ก่อน Java ภาษาโปรแกรมยอดนิยมคือ C หรือ C++ หากคุณพูดภาษาเหล่านี้ คุณควรรู้ว่าพวกเขาจัดการหน่วยความจำของตนเองด้วยตนเอง ตัวอย่างเช่น C มีเมธอดเช่นcalloc() , malloc()และrealloc()ที่จะช่วยให้คุณใช้หน่วยความจำบัฟเฟอร์ได้ คุณต้องกำหนดจำนวนหน่วยความจำที่คุณต้องการสำหรับโปรแกรมของคุณและระบุสิ่งที่เรียกโดย API นี้ จากนั้นคุณจะได้รับบัฟเฟอร์หน่วยความจำเพื่อสร้างโหนดรายการที่เชื่อมโยงหรืออย่างอื่น เมื่อโปรแกรมของคุณหยุดทำงาน คุณยังต้องรับผิดชอบในการล้างหน่วยความจำนั้นด้วย ดังนั้นแอปพลิเคชันขนาดใหญ่ที่เขียนด้วยภาษา C จะจัดสรรหน่วยความจำบัฟเฟอร์และบางครั้งก็ลืมล้างข้อมูล ในที่สุดสิ่งนี้ทำให้เกิดการรั่วไหลของหน่วยความจำและปัญหามากมายในแอปพลิเคชัน ภาษา Java ต่างจาก C และ C++ ตรงที่มีการจัดการหน่วยความจำอัตโนมัติผ่านเธรดที่เรียกว่าตัวรวบรวมขยะ วัตถุประสงค์หลักคือเพื่อเพิ่มหน่วยความจำฮีปโดยการทำลายวัตถุที่ไม่สามารถเข้าถึงได้ ตัวรวบรวมขยะจะทำงานอยู่เบื้องหลังเสมอ

วัตถุที่ไม่สามารถเข้าถึงได้ใน Java คืออะไร?

วัตถุจะมีโอกาสเริ่มเก็บขยะเมื่อใด หากมีวัตถุที่ไม่สามารถเข้าถึงได้ - วัตถุที่ไม่มีลิงก์ที่ใช้งานอยู่ ลองดูตัวอย่าง:
public static void main(String[] args)
{
// StringBuffer object sb is not eligible for garbage collection
StringBuffer sb = new StringBuffer("Flower Brackets");
System.out.println(sb);
// StringBuffer object sb is eligible for garbage collection
sb = null;
}
ในวิธีการหลัก ฉันได้สร้าง วัตถุ StringBufferและการอ้างอิงถึงมัน ณ จุดนี้ วัตถุ StringBufferไม่มีสิทธิ์สำหรับการรวบรวมขยะ ตอนนี้ฉันจะตั้ง ค่าวัตถุ StringBufferเป็น "null" ขณะนี้วัตถุมีสิทธิ์สำหรับการรวบรวมขยะและกลายเป็นวัตถุที่ไม่สามารถเข้าถึงได้ในหน่วยความจำฮีป นั่นคือ โดยทั่วไปการรวบรวมขยะจะใช้ได้ในกรณีที่วัตถุไม่สามารถเข้าถึงได้ ซึ่งหมายความว่าวัตถุมักจะถูกสร้างขึ้นในบริบทของ "if block" หรือวิธีการ ดังนั้นออบเจ็กต์จะออกจากขอบเขตเมื่อการดำเนินการวิธีการเสร็จสิ้นและผู้รวบรวมขยะสามารถกำจัดทิ้งได้ เนื่องจากการอ้างอิงจากอ็อบเจ็กต์เก่าไปยังอ็อบเจ็กต์ใหม่นั้นมีอยู่ในจำนวนที่จำกัด ซึ่งหมายความว่าอ็อบเจ็กต์ที่มีอยู่ในแอปพลิเคชันของคุณมาเป็นเวลานานมักจะไม่ใช่อ็อบเจ็กต์ที่สร้างขึ้นใหม่ ต่อไปนี้เป็นคำศัพท์สองสามคำที่เราควรทำความคุ้นเคย หนึ่งในนั้นคือวัตถุที่มีชีวิต เป็นวัตถุในแอปพลิเคชันที่ถูกอ้างอิงโดยวัตถุอื่นในแอปพลิเคชันเดียวกัน มีวัตถุ "ตาย" อยู่ด้วย วัตถุที่ไม่ทำงานเป็นวัตถุที่ไม่สามารถเข้าถึงได้ซึ่งถูกสร้างขึ้นในระหว่างการเรียกเมธอด และเมื่อการเรียกเมธอดเสร็จสิ้น วัตถุนั้นจะไม่อยู่ในบริบทและอยู่บนฮีป

วัตถุจะมีสิทธิ์ในการรวบรวมขยะเมื่อใด

หากออบเจ็กต์ไม่มีตัวแปรอ้างอิงใดๆ แสดงว่าออบเจ็กต์นั้นมีสิทธิ์สำหรับการรวบรวมขยะ

จะทำให้วัตถุพร้อมสำหรับการรวบรวมขยะได้อย่างไร?

ด้านล่างมีหลายวิธี:
  1. null reference variable
    Student obj = new Student();
    obj = null;

  2. re-assign reference variable
    Student obj1 = new Student();
    Student obj2 = new Student();
    obj1 = obj2;

  3. reate anonymous object
    new Student();

    เมื่อวัตถุถูกจัดเตรียมให้กับคนเก็บขยะแล้ว มันจะไม่ถูกทำลายในทันที

เมื่อ Java Virtual Machine รันตัวรวบรวมขยะ เฉพาะอ็อบเจ็กต์เท่านั้นที่จะถูกทำลาย หมายเหตุ: ตัวรวบรวมขยะจะรวบรวมเฉพาะออบเจ็กต์ที่สร้างขึ้น โดยใช้คีย์เวิร์ด “new” สำหรับออบเจ็กต์ที่ไม่มีคีย์เวิร์ด “new” ให้ใช้เมธอดFinalize() มีหลายวิธีในการรันตัวรวบรวมขยะใน Java Virtual Machine:
  1. วิธีการSystem.gc()

  2. วิธีการสรุป ()

  3. Runtime.getRuntime().gc()วิธีการ

เมธอด gc()แบบคงที่อยู่ใน คลาส System เมธอดนี้ขอให้ JVM โทรหาตัวรวบรวมขยะ มาดูกันว่าแอปพลิเคชัน Java เรียกตัวรวบรวมขยะ โดยใช้ เมธอด gc() อย่างไร
public class GarbageCollector
{
public static void main(String[] args)
{
Employee obj1 = new Employee();
Employee obj2 = new Employee();
obj1 = null;
obj2 = null;
System.gc();
}
public void finalize()
{
System.out.println("object garbage collected");
}
}
ผลลัพธ์:
รวบรวมขยะวัตถุ รวบรวมขยะวัตถุ
เมธอดFinalize()ถูกเรียกก่อนที่วัตถุจะถูกล้างข้อมูล วิธีการนี้ถูกกำหนดไว้ใน คลาส Object :
protected void finalize() throws Throwable
  1. วิธีการFinalizeใช้เพื่อปิดการเชื่อมต่อกับฐานข้อมูล

  2. เมธอดนี้ถูกเรียกโดยตัวรวบรวมขยะ ไม่ใช่ JVM

  3. เรา จำเป็นต้องแทนที่ เมธอด Finalize() เนื่องจากมีการดำเนินการที่ว่างเปล่า

  4. มันถูกเรียกเพียงครั้งเดียวต่อวัตถุ

เมธอดgetRuntime().gc()มีอยู่ในคลาสรันไทม์ ส่งคืน อ็อบเจ็กต์ รันไทม์ที่เกี่ยวข้องกับแอปพลิเคชัน Java ปัจจุบัน ลองดูวิธีนี้ในโปรแกรม Java
public class Demo
{
public static void main(String[] args)
{
Demo obj1 = new Demo();
Demo obj2 = new Demo();
// nullifying reference variable
obj1 = null;
// nullifying reference variable
obj2 = null;
// running Garbage Collector
Runtime.getRuntime().gc();
}
@Override
protected void finalize() throws Throwable
{
System.out.println("Garbage collector called");
System.out.println("Object garbage collector: " + this);
}
}
ผลลัพธ์:
ตัวรวบรวมขยะที่เรียกว่าตัวรวบรวมขยะวัตถุ: Demo@2130772 ตัวรวบรวมขยะที่เรียกว่าตัวรวบรวมขยะวัตถุ: Demo@cd4e940

ประโยชน์ของการเก็บขยะ:

  1. การรวบรวมขยะใน Java เกิดขึ้นโดยอัตโนมัติ ซึ่งช่วยเราจากภาระเพิ่มเติมในการเพิ่มหน่วยความจำที่ใช้แล้ว ทำให้หน่วยความจำของโปรแกรม Java มีประสิทธิภาพมากขึ้น
  2. การรวบรวมขยะช่วยให้มั่นใจถึงความสมบูรณ์ของโปรแกรม
  3. เราไม่จำเป็นต้องเขียนโค้ดเพิ่มเติมใดๆ เนื่องจากตัวรวบรวมขยะเป็นส่วนหนึ่งของ JVM
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION