Unit test ตอนที่ 3 งานจริง เขียนจริง แก้จริง รักจริง

งานจริง เขียนจริง แก้จริง รักจริง

งานจริง

ผมเขียนเกี่ยวกับ Unit test ไว้ 4 ตอน คุณสามารถกด Link ด้านล่างเพื่ออ่านที่เกี่ยวกับ Unit test ตอนต่างๆได้เลย

ผมได้รับมอบหมายงานตัวนึงเป็นง่ายไม่ซับซ้อนมาก (แต่ผมทำให้มันซับซ้อน) มันคืองานทำตัว FTP ไว้ Download และ Upload ไฟล์ ปัญหามันเกิดจากลูกค้าเนี่ยไม่จะไม่ยอม Implement ช่องทางการส่งข้อมูลเลย ไม่ว่าจะทำ API หรือ ทำ Queue หรืออะไรก็แล้วแต่ เขาจะทำอย่างเดียวคือ FTP ครับ คือจริงๆผมไม่ค่อยชอบการรับส่งข้อมูลประเภทนี้เท่าไหร่ เพราะมันไม่มีการแจ้ง Error ห่าเหวอะไรเลยระหว่างคนส่งคนรับให้ทราบเลย บางทีอ่านไฟล์มาแล้วไฟล์แม่งไม่ถูก Format เราก็ไม่รู้จะทำยังไงเพื่อบอกว่ามัน Error

  • ส่งเมลล์ไปบอกเหรอว่า Error ประเด็นคือแม่งอ่านเมลล์รึเปล่า
  • สร้างไฟล์บอกว่า Error ว่าอะไรแล้วส่งกลับไปให้เขาเหรอ ประเด็นคือ API แม่งยังไม่ยอมเขียนเลย แม่งจะมีมาเขียนอ่านว่า Error อะไรเหรอ

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

เอาเถอะครับมันเป็นสิ่งที่เรียกว่าข้อจำกัด เมื่อข้อจำกัดมีเท่านี้ก็ต้องทำเท่านี้ ผมก็ทำอะไรไม่ได้นอกจากบ่นแล้วก็มาคิดว่าจะทำยังไงต่อ

โจทย์ที่ได้รับ

โจทย์ที่ได้มาคือเขียน Program ที่

  1. มันใช้รับส่ง FTP ได้ โดยทำได้ทั้ง Upload และ Download
  2. ต้องรองรับทั้ง FTP, FTPS, SFTP
  3. ในขั้นตอนการ Download เมื่อ Download เสร็จแล้ว สามารถเลือกได้ว่าจะ Delete file ทิ้ง หรือ Move file ไปไว้ที่ Directory อื่นของเครื่อง Server
  4. สามารถเลือก File Extension อะไรที่ Download หรือ Upload เช่น จะเอาเฉพาะไฟล์ xml txt เท่านั้น

Design แบบกระโหลกกะลาปลากระป๋อง

ผม Design Control flow ของ Upload และ Download ประมาณนี้ โดยเริ่มจาก Connection List file แล้วเอามาทำ Upload หรือ Download จากนั้นทำการ Clear ข้อมูล ถ้าสำเร็จบันทึกเข้า Success List ถ้าไม่สำเร็จเอาเข้า Fail List ดูง่ายๆเนอะ บางคนอาจบอกว่า Class กระจอกแบบนี้ เขียน 2 ชั่วโมงเสร็จ ครับ 2 ชั่วโมงอาจจะเสร็จจริงๆครับ แต่ผมใช้เวลาประมาณ 1 สัปดาห์ (สกิลการ Coding ของผมกากมากๆครับ)

เงื่อนไขต่อไปที่ผมคิดขึ้นมาคือ ผมจะเรียกใช้มันทุก 10 วินาที ซึ่งมันเป็น Schedule Task ซึ่งพอจะทำเป็น Schecdule Task ตัวที่จะถูกเรียกใช้งานจะต้อง Implement Runable Interface แล้วตัว Schecdule Task จะเรียกใช้งานตัว method run() ทุก 10 วินาที

คิด Case ก่อนเขียน

ถ้าจะเขียน Unit test ต้องคิด Case เขียน Unit test ก่อนเขียน Code เสมอ แต่คุณสามารถคิดวิธีเขียน Code ไปในหัว เขียน Flow ก็ได้

เริ่ม Download Task ก่อน

โอเคมันจะมี Case อะไรบ้าง

  • ถ้า Connect แล้ว Error จะทำยังไง ตรวจสอบยังไงว่ามันทำงานถูกต้อง
  • ถ้า List file บน Server แล้วเกิด Error จะทำยังไง ตรวจสอบยังไงว่ามันทำงานถูกต้อง
  • ถ้า Save file ลง Local ไม่สำเร็จจะทำยังไง ตรวจสอบยังไงว่ามันทำงานถูกต้อง
  • ถ้า Clean up file ไม่สำเร็จจะทำยังไง ตรวจสอบยังไงว่ามันทำงานถูกต้อง
  • ถ้าห่มผ้าเองแล้วมันไม่หนาว อันนี้ไม่เกี่ยวเป็นมุก

ลางร้ายเริ่มปรากฎ (แต่ผมไม่ได้เป็นคนแต่งเรื่องที่กำลังเล่าเรื่อง แล้วก็ไม่ได้มีเด็ก 3 คนเดินเรื่อง)

มันจะเขียน Test ยังไงวะ มันไม่ Return ค่าออกมา (เนื่องจากใช้ method : run() ในการทำงาน) จะ Assert มันยังไง นี่เป็นปัญหาอย่างแรกๆที่เราเขียน Unit test บางหลักการเขียน Code ถึงกับบอกว่า Function ที่ไม่มี Return เนี่ย เป็น Function ที่ไม่ปกติ ไม่สะอาด เขามองว่าถ้าสั่งแบบนี้มันมี ผลข้างเคียง ลองอ่านเพิ่มเติมเกี่ยวกับ Functional Programming ได้ครับ สนุกดี ผมชอบหลายๆอย่าง ชอบตรงแนวคิดที่ใส่ A และ B เข้า Function เดิมมันก็ควรได้ค่าเดิมตลอด เพราะมันคือ Function ตามคณิตศาสตร์ แต่ผมไม่ชอบเรื่องเวลาต่อ Function ยาวๆ แล้วมันวงเล็บซ้อนวงเล็บ อ่านแล้วมันชวนอ้วกแปลกๆ

ตัวอย่าง Unit test ที่เขียน

ค่อยๆดูปัญหาแต่ละข้อครับ

run_NormalCase_NoIdeaToVerify

ตัวอย่างนี้จะเห็นว่าผมไม่รู้ว่าจะ Assert ค่ายังไง พีคจริงๆครับอันนี้ จริงๆผมมีวิธีเลี่ยงที่คิดไว้ในหัวละคือสร้าง List ที่เก็บ Success กับ Fail แล้วสร้าง getter setter ออกมา Assert แต่พอจะเห็นปัญหาแล้วนะครับว่า ถ้าเขียน Function ไม่มี Return มันจะตรวจสอบยาก ต้องหาวิธีทำอ้อมๆ อันนี้โชคดีที่เป็น Object ต้องสร้าง instance เลยมีตัวแปรอื่นๆได้และไม่ต้องกลัว Race condition (กรณีถ้าคุณไม่เอา Object นี้ไปใช้หลายๆ Thread ) แต่ถ้าเป็น static Class แล้วคุณสร้างตัวแปร List ที่เก็บ Success กับ Fail ตัวแปรที่สร้างจะเป็น static คราวนี้มันจะกลายเป็น Global variable แล้วหลาย Thread สามารถเรียกใช้มันพร้อมกันได้ง่ายๆ (จากความไม่รู้) และเกิด Bug แบบงงๆ แบบเกิดบ้างไม่เกิดบ้าง

run_FtpConnectionError_ThrowIOException และ run_FtpListFileError_ThrowIOException

อันนี้เนื่องจาก method : run() ของ Runable ห้าม Throw Exception ออกมา ทำให้เราไม่สาารถดัก Exception อะไรได้เลย

  • ผมจะรู้ได้ไงว่ามัน Error ตอนไหนกันแน่ระหว่าง Connection หรือ ListFile แล้วผมจะรู้ได้ไงว่ามันทำการ Connection ก่อน ListFile แล้วผมจะรู้ได้ไงว่า ถ้า ListFile แล้วได้ Error แล้วมันมีการ Close connection จริง (ผมอยากรู้เพราะว่ามันต้องพิสูจน์ว่า Connection ถูกปิดหลังจากเกิดปัญหา การ Clanup Resource เป็นเรื่องที่โปรแกรมเมอร์ต้องทำ)

  • แล้วผมจะทำยังไงให้มัน Connection Error แล้วทำยังไงให้มัน ListFile Error โดยไม่ต้องแก้ Code Unit test หรือ Config ทุกครั้งที่ Run ลองนึกภาพตอน Test แล้วต้องสร้างเครื่อง Ftp server จะ Test ปกติต้องตั้งค่าให้ถูก จะ Test ไม่ปกติต้องไปตั้งค่าให้ผิด แล้วมันจะ Test ครั้งเดียวแล้วรู้ได้ไงว่ามันถูก แก้ไปแก้มาปวดหัวตาย

จะแก้เรื่องนี้ต้องแก้ที่ Design

ปัญหาทั้งหมดถ้าจะแก้เราต้องแก้ Design ครับ เพราะ Code ที่เราเขียนตอนนี้ไม่เปิดโอกาสให้เรา Test ได้ง่ายๆเลย ถ้าเขียน Code แบบตรงไปตรงมาจะได้ Code ประมาณนี้ เอ่อ ไม่อยากเขียนเลยอะ มันยาวมาก ขอสมมติแทนส่วนที่เป็นพวก Connection , Download , Cleanup นะครับ

จาก Code ที่ผมเขียนจะเห็นว่าการทำงานทุกอย่างนั้นอยู่ใน Class : FtpDownloadTask หมดเลย ซึ่งเราไม่สามารถแทรกแทรงอะไรตอน Test ได้เลย Code จะทำงานตามที่เขียนอย่างงั้นเลย เวลาจะสร้างเหตุการณ์ Error ต่างๆนั้นต้องไปทำที่ตัว FTP Server ซึ่งมันจะไม่เป็นไปตามที่ผมเคยบอกว่าไว้ว่า : โดยไม่ต้องติดต่อกับส่วนจริงๆที่เกี่ยวข้องกับ Code ส่วนนั้น วิธีกจะแก้ปัญหานี้เราต้องทำการแก้ Design ของ Code : FtpDownloadTask เสียใหม่ แต่ก่อนที่จะทำแบบนั้น ผมขออธิบายอีกเรื่องหนึ่งก่อนจะไปเรื่องแก้เรื่อง Design

Mock(ingjay)

พอเขียน Unit test มาถึงระดับนึง มันจะมีปัญหานึงเกิดขึ้นมาเมื่อเราต้องเรียกใช้งาน Component อื่น เช่น

เราได้โจทย์ให้เขียน
Class : DebtManagement : Method : public List findCompanyToAlertDebt(Integer debt)

โดย step การทำงานคือดึงข้อมูลลูกค้าออกมาจากแหล่งข้อมูล จากนั้นทำค้นหาว่าลูกค้าเจ้าไหนบ้างที่มีหนี้มากกว่าหรือเท่ากับที่เรากำหนด ถ้าเกินกว่าก็จะ Return ค่าออกมาเป็น List บริษัทที่เกิน โดยส่วนทีทำการดึงข้อมูลนั้นถูกแยกให้ออกจาก DebtManagement และให้มาเพียง Interface ประมาณนี้

ซึ่งตัว Class จริงๆยังไม่มีคนเขียน และคุณเองก็ถูกสั่งห้ามเขียน(จริงๆไม่ได้ห้ามทำงานไม่ทัน) เพราะคุณถูกมอบหมายให้เขียนส่วนจัดการหนี้ และ ส่วน Business Logic อื่นๆ ปัญหาคือคุณจะเขียน Unit test ยังไง และมันจะ Test ได้ยังไง เพราะตัวที่เป็น Dao จริงๆไม่มี มีแต่ Interface

  • วิธีธรรมดาที่เราพอคิดได้

ผมก็ไปเขียน Class ที่มัน Implement Interface : CustomerDebtDao แล้วให้มี Return ค่าง่ายๆออกมาตามเงื่อนไข ถ้ามีหลาย Case ผมก็ไปเพิ่ม If else เข้าไปเพิ่ม เช่น เรียกรอบแรก return ออกมา 10 ตัว เรียกรอบที่สอง return ออกมา 5 ตัว ตามแต่ Case หรือ สามารถตั้งเงื่อนไขต่างๆได้

ซึ่งนี่แหละคือคำตอบ แต่จะให้โปรแกรมเมอร์ทั่วโลกมาเขียนอะไรแบบนี้ทุกครั้งมันก็ลำบาก โปรแกรมเมอร์จำนวนหนึ่งสร้าง Lib ที่ทำอะไรอย่างที่ผมอธิบายไปขึ้นมาให้ใช้งาน เขียนง่าย ไม่ต้อง If อะไรมากแบบที่นั่งทำเอง ต่อไปจะเป็นตัวอย่างที่ใช้วิธีการที่ผมบอกโดยใช้ Lib ที่ชื่อ mockito มีดูตัวอย่างการใช้ Mockito มาเขียน Unit test

อธิบาย Code กัน

Code อาจมากแต่จริงส่วนสำคัญมีนิดเดียว

CustomerDebtDao customerDebtDao = mock(CustomerDebtDao.class);

ส่วนนี้เป็นการจำลอง CustomerDebtDao ขึ้นมาโดยใช้ method mock ของ mockito คือ อยากจำลองอะไรก็เอาใส่ class นั้นเข้าไปเลย จากนั้น mockito จะ return obj ทีแทน class นั้นออกมาได้เลย ตัวอย่างของผมนี่มีแค่ Interface ก็สามารถจำลอง Class ออกมาได้แล้ว โคตรเจ๋ง

when(customerDebtDao.findAll()).thenReturn(returnData);

ส่วนอันนี้เป็นการจำลอง Case ต่างๆ โดยตัวอย่างนี้เราจะทำการจำลอง method : findAll โดยผมจำลองให้มัน return ค่าออกมาตามที่กำหนด เพื่อให้เป็น Case ต่างๆเช่น Case ปกติ Case ที่มีค่าซ้ำ เพื่อดูว่าตัว findCompanyToAlertDebt ทำงานถูกต้องไหม

when(customerDebtDao.findAll()).thenThrow(IOException.class);

เมื่อกี้มีสร้าง Case ปกติแล้ว อันนี้คือการสร้าง Case Exception

ตัดจบแขวนคนดู

รู้สึกตอนนี้จะเริ่มยาวเกินไปละ ตอนแรกว่าจะเอาให้จบเลยแต่ยิ่งเขียนยิ่งยาว พอยาวมากๆคนจะไม่อยากอ่าน เลยขอตัดตรงนี้เลยละกัน ในตอนนี้ผมได้ยกตัวอย่างงานจริงที่ผมได้รับ แล้วพอเอามาเขียน Unit Test ก็ติดปัญหาว่าจะ Assert ค่ายังไง จะจำลอง Case ต่างๆยังไง ซึ่งวิธีแก้ปัญหาคือทำการแก้ Design ซึ่งมันจะอธิบายยาวมาก เลยขอแยกมาอธิบายเรื่องการ Mock ก่อนว่ามันเป็นยังไง หลักการเขียนมันประมาณไหน แล้วค่อยไปอธิบายการแก้ Design ในตอนหน้าแทน

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

เพลงประกอบการเขียนบทความนี้

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

ref :

https://th.wikipedia.org/wiki/%E0%B8%AD%E0%B8%A2%E0%B8%B2%E0%B8%81%E0%B9%83%E0%B8%AB%E0%B9%89%E0%B9%80%E0%B8%A3%E0%B8%B7%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B8%99%E0%B8%B5%E0%B9%89%E0%B9%84%E0%B8%A1%E0%B9%88%E0%B8%A1%E0%B8%B5%E0%B9%82%E0%B8%8A%E0%B8%84%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%A2
https://th.wikipedia.org/wiki/%E0%B8%A1%E0%B9%87%E0%B8%AD%E0%B8%81%E0%B8%81%E0%B8%B4%E0%B9%89%E0%B8%87%E0%B9%80%E0%B8%88%E0%B8%A2%E0%B9%8C
https://www.facebook.com/bnk48official.kaew/

Unit test ตอนที่ 2 เริ่มต้นเขียน Unit test แบบง่ายๆ

เริ่มต้นเขียน Unit test แบบง่ายๆ

เริ่มเขียน Unit test ที่ง่ายที่สุดในโลก

ผมเขียนเกี่ยวกับ Unit test ไว้ 4 ตอน คุณสามารถกด Link ด้านล่างเพื่ออ่านที่เกี่ยวกับ Unit test ตอนต่างๆได้เลย

ตอนนี้มาเขียน Unit test แบบง่ายๆกันก่อนเลย ตามความหมายที่ผมให้ไปบทที่แล้ว (ความหมายไม่เป็นทางการ ไม่ต้องเอาไปตอบอาจารย์ตอนสอบนะ) ว่า Unit test คือ “การเขียน Code ไว้ Test Code ส่วนหนึ่งว่ามันทำงานถูกต้องตามที่ต้องการหรือไม่ โดยไม่ต้องติดต่อกับส่วนจริงๆที่เกี่ยวข้องกับ Code ส่วนนั้น” วันนี้เรามาเริ่มง่ายๆกับการ “การเขียน Code ไว้ Test Code ส่วนหนึ่งว่ามันทำงานถูกต้องตามที่ต้องการหรือไม่”

ในส่วนที่จะเขียน Unit test ต่อจากนี้ทั้งหมดอันนี้ผมขอเขียนด้วยภาษา Java ใช้ Junit5 เป็นตัวทำ Unit test แต่ขอบอกไว้ตรงนี้เลยว่า ถ้าคุณเข้าใจหลักการวิธีการเขียน คุณจะไปใช้กับภาษาอะไรก็ได้ เพราะหลักการ แนวทาง วิธีเขียนมันก็จะไปในทางนี้แหละ แค่ต้องไปหาว่า Lib หรือ Frame work นั้นเขาใช้คำสั่งหรือวิธีไหนเมื่อเทียบกับ Junit5

Set up กันก่อนนะครับ

ถ้าขี้เกียจเขียน Code หรือสร้าง Project ขึ้นมาเอง ก็สามารถใช้ source code ของผมที่ https://github.com/surapong-taotiamton/example-unit-test.git

โดยสามารถนำเข้าตัว eclipse โดยสามารถทำตาม Link นี้ได้เลย

เนื่องจากผมใช้ junit5 ซึ่งมันไม่ได้ใส่มาโดยอัตโนมัติพร้อมกับ Eclipse (เพราะมันยังใหม่ระดับหนึ่ง) ดังนั้นเลยต้องทำการ Config เพิ่มให้กับ Eclipse โดยสามารถทำตาม Link นี้ได้เลย

ตัวอย่างมาตรฐาน

ถ้าพูดถึงตัวอย่างมาตรฐานก็ Code การบวกเลขเลย อันนี้ไม่ต้องสนใจมากแค่เอาเลขมาบวกกัน

ต่อไปเป็นส่วน Test ครับ

มาเริ่มอธิบายกันเลย

@Test

ส่วนนี้เป็นการบอกให้ตัว Junit ทราบว่า method นี้จะเป็น unit test โดยใน 1 Class จะมีกี่ unit test ก็ได้ แต่ตามหลักการนะครับ 1 unit test ควรจะ Test แค่ 1 เรื่อง โดยจากตัวอย่างของผม Unit test อันนี้คือ

plus_Normal_ReturnSuccessValue

ตัว Unit test มีหลักการตั้งชื่อนะครับ เพื่อให้เข้าใจว่า Unit test นี้กำลังจะ Test อะไร Case ไหน และผลลัพธ์ที่ควรได้คืออะไร เพื่อให้เวลา Run Unit test ไม่ผ่านจะได้รู้คร่าวๆว่าติดที่ Case ไหน โดยหลักการตั้งชื่อที่นิยมกันสามารถอ่านได้ตามนี้เลย https://dzone.com/articles/7-popular-unit-test-naming

โดยจากตัวอย่างผมตั้งชื่อตามหลัก MethodName_StateUnderTest_ExpectedBehavior

Body ของ Unit test

ตัว Unit test ตามหลักการที่ผมตามอ่านมา จะแบ่งออกเป็น 3 ส่วนหลักๆคือ ARRANGE , ACT, ASSERT

ARRANGE

ในส่วนนี้จะเป็นการตั้งค่าต่างๆตัวอย่างเช่น กำหนดค่า Input ที่จะส่งเข้าไปในส่วนที่ Test , กำหนดผลลัพธ์ที่คาดว่าน่าจะได้ , กำหนด Environment ต่างๆเพื่อจะให้เกิด Case ที่ต้องการ คุณฟังไม่ผิดครับ คุณสามารถสร้าง Case อะไรก็ได้ ตราบเท่าที่คุณออกแบบให้มันเอื้ออำนวย

ACT

ในส่วนนี้คือส่วนที่สั่งให้ Code ส่วนที่ต้องการ Test ทำงาน ในส่วนนี้ไม่ค่อยมีอะไรมาก จริงๆอาจจะน้อยที่สุดเลยด้วย

ASSERT

ส่วนนี้จะเป็นการตรวจสอบว่า Code ส่วนที่ Test ทำงานถูกต้องหรือไม่ โดยการตรวจสอบจะมีการตรวจสอบค่า Return ออกมา หรือ ตรวจสอบการทำงานของส่วนอื่นของ Code (ส่วนนี้ยังไม่พูดถึง) โดยจากตัวอย่าง ผมทำการ Test ว่ามันเอาค่ามาบวกกันแล้วได้ค่าถูกต้องไหม โดยใช้ method ที่ชื่อว่า assertEquals โดย method ทำนองนี้มีมากมายหลายตัวเลย ไปทดลองใช้กันดูนะครับ

ข้อแนะนำ และ ควรทำตาม

  1. ใน 1 Unit Test นั้นควรจะทำการ Test แค่เรื่องเดียวกรณีเดียว อย่าไป Test หลายอย่างใน Unit Test เดียว เพราะมันจะทำให้ Unit test นั้นซับซ้อน แล้วถ้ามันซับซ้อนอ่านยาก เข้าใจยาก และอาจจะทำให้เกิด Bug ใน Unit test เอาง่ายๆ สุดท้าย พยายามทำให้ง่ายเข้าไว้

  2. พยายามเขียน Unit test ให้เป็นระเบียบ เขียนให้อ่านง่าย เหมือนกับเขียน Code ครับ อย่าลืมว่า Unit test ก็เป็น Code และมันมีโอกาสที่จะมีคนมาอ่านต่อ หรือ แก้ไข Unit test นี้ ดังนั้นเขียน Unit test นี้ให้ดี ให้เรียบร้อยครับ

ตัวอย่างที่ยากขึ้นมาหน่อย

อันนี้สมมุติว่ามีคนบอกว่าต้องการ Util Class ที่ทำงานเกี่ยวกับ Order โดย Class นี้มีหนึ่ง Method ที่ให้หา index ของ Array ตาม Order ทีส่งเข้าไป โดยกฏเบื้องต้นคือ Array ต้อง Unique งงล่ะสิ ผมก็ไม่รู้จะอธิบายยังไงอธิบายเป็น Case ละกัน

method : int indexOfOrder(int[] array, int order)

Array = { 3, 1, 2}

Order ที่ต้องการคือ 3

ความหมายของมันก็คือ หา index ของค่าที่อยู่ที่ลำดับ 3 ของ Array นี้ จากตัวอย่าง อันดับ 3 ของ Array คือ 3 ซึ่ง 3 อยู่ที่ index 0 (เริ่มนับ index ที่ 0) ดังนั้นคำคอบของกรณีนี้คือ 0

คิด Case แล้วเขียน Unit test

โอเค Case แบบธรรมดาทั่วไปมีเท่านี้ คราวนี้ตามหลักการการเขียน Unit test เราต้องคิด Case อื่นด้วย เช่น

  • ถ้ามันส่งค่า Array ที่เป็น Null เข้ามาล่ะจะเป็นยังไง
  • ถ้า Order ที่ส่งเข้ามามันมากกว่าขนาดของ Array
  • ถ้า Array ที่ส่งเข้ามาไม่ Unique ล่ะ
  • ถ้า Order ทีส่งเข้ามาเป็น 0 หรือค่าติดลบล่ะ

ไอ้ถ้าทั้งหมดที่ผมว่าไปทั้งหมดจะกลายเป็น Unit test แต่ละอันไปเลยตามนี้

มี Test แล้วก็เขียน Code

บอกตามตรงโจทย์ง่ายๆแบบนี้ผมเขียนแบบเร็วๆก็มีหลุดไปเหมือนกัน คือ ผมลืมลบตรง order ออก 1 ทำให้มันทำงานผิด แต่พอ Run Test ก็ขึ้นฟ้องเลยว่าไม่ผ่าน พอกลับไปดูก็เจอเลยว่าผิดที่อะไร ตัวอย่าง Code ที่ผมเขียนเป็นแบบนี้

ตัดจบไปดูตอน 3

สำหรับตอนนี้ก็ได้อธิบายวิธีการเขียน Unit test แบบพื้นฐานมากๆ พื้นฐานจนบางคนไม่อยากอ่าน ครับตอนแรกก็อยากจะข้ามตอนนี้ไปเลย แต่ไหนๆจะเขียนละไม่อยากลัดเดี๋ยวคนที่หัดเขียนใหม่ๆจะช็อกตายเอาก็เลยมีตอนนี้เข้ามา คล้ายกับการฝึกวรยุทธ์ต้องฝึกลมปราณให้กล้าแข็งก่อนแล้วค่อยฝึกวิชาขั้นต่อๆไป อย่าไปฝันถึง กบวิเศษที่ต้วนอื้อกิน งูที่ก้วยเจ๋งกิน ที่เป็นทางลัดช่างฝัน แต่ขอให้ฝึกวิชาเหมือน เซียวฟง ผู้ฝึกพื้นฐานจนแข็งแกร่งและใช้วิชา ฝ่ามือปราบมังกร 18 ท่า (เวอร์ชันแรกเรียกแบบนี้ เวอร์ชันใหม่จะเป็น 18 ฝ่ามือพิชิตมังกร) ปราบทั้งยุทธภพ (ไปลองหาอ่านแล้วจะเห็นว่าท่าธรรมดาๆชนะได้ทั้งยุทธภพเป็นยังไง) เหมือนจะนอกเรื่องไปเยอะละ ตอนหน้าจะเอางานจริงที่ทำ แล้วตอนเขียน Unit test เจออะไร แก้ยังไง และ Test โดยไม่ต้องใช้ตัวจริงทำยังไง

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

เพลงประกอบการเขียนบทความนี้

อีกหนึ่งเพลงเศร้าที่ฟังแล้วทำให้เศร้าแล้วเศร้าอีก เจ็บปวดกับการที่รู้สึกว่าเป็นส่วนหนึ่งของใครสักคน แต่จริงๆแล้วมันไม่เคยเป็นอะไรสักอย่างของเขาเลย

ref :
https://www.eclipse.org/community/eclipse_newsletter/2017/october/article5.php
https://dzone.com/articles/7-popular-unit-test-naming
https://medium.com/@samueleresca/concepts-of-maintainable-unit-tests-ccb816d93c2b
https://github.com/collab-uniba/socialcde4eclipse/wiki/How-to-import-a-GitHub-project-into-Eclipse
https://howtodoinjava.com/junit5/expected-exception-example/
https://pixabay.com

ปรัชญา ประวัติศาสตร์ สายธารแห่งปัญญา - A Little History of Philosophy

ความเบื่อหน่ายที่พามาพบกับ “ปรัชญา”

ปรัชญา ประวัติศาสตร์ สายธารแห่งปัญญา - A Little History of Philosophy

ตอนเด็กๆเคยได้ยินคำว่า “ปรัชญา” ตอนนั้นก็ไม่รู้ว่ามันคืออะไร เข้าใจว่ามันคงเป็นศาสตร์หนึ่งที่จะได้เรียนตอนโต ตัดฉากมาตอนโตขึ้นมาอีกนิดก็ได้ยินคำว่าปรัชญาในวิชาสังคม ได้ยินคำว่านักปรัชญา แต่ก็ไม่เคยได้เรียนวิชาปรัชญาเลย จนเรียนจบทำงานได้ 2 - 3 ปีก็ไม่เคยรู้ว่ามันคืออะไร

จนมาช่วงหนึ่งที่ชีวิตเริ่มไร้สีสัน เบื่อกับการอ่านข่าวเทคโนโลยีบนเว็บที่ส่วนใหญ่จะมาโม้เรื่องยอดขาย เรื่องอะไรที่อ่านแล้วประมาณว่า “แล้วไงวะ” บางทีอ่าน Comment คนที่มาคุยกันนึกว่าจะถกประเด็นเรื่องความเป็นไปได้ เรื่องการนำไปใช้งาน แต่กลายเป็นดราม่าอวยบ้าง ข่มบ้าง จนถึงขีดสุดเลยต้องหาหนังสือมาอ่านแก้ความเบื่อหน่ายและความเหงาเวลาอยู่บนรถไฟฟ้า BTS จนมาลงเอยที่หนังสือ “A Little History of Philosophy” (จริงๆได้ส่วนลดมา ฮ่าๆๆ)

คนที่ตั้งคำถามและพยายามหาคำตอบ

หลังจากซื้อมาด้วยราคาที่แพงระดับหนึ่ง แถมเขาห่อพลาสติกไม่ให้อ่านเนื้อหาด้านในด้วย มันเลยเป็นเหมือนการซื้อของที่ไม่รู้ว่าข้างในเป็นยังไง คือมันมีโอกาสที่เปิดมาอ่านแล้วรู้สึกว่า “ไม่น่าซื้อมาเลย” (แต่จริงๆปกก็สวยดีนะ) พออ่านไปบทแรกที่พูดถึง โสเครตีส ก็เริ่มสนุกเลย คือเคยแต่ได้ยินชื่อแต่ไม่เคยรู้ว่าเขาคือใคร พอได้รู้ประวัติและวีรกรรมของเขา ซึ่งสมมติถ้าได้ได้เจอตัวแกจริงๆก็คงจะปวดหัวน่าดู เพราะหนังสือบอกว่า โสเครตีส เป็นคนที่ชอบตั้งคำถาม แถมคำถามที่ถามนั้นเป็นคำถามที่พอตอบแล้วจะมีคำถามที่พร้อมจะโต้แย้งไอคำตอบแรกของเรา เช่น

  • A : คุณคิดว่าการมีความซื่อ เป็นเรื่องที่ดีและต้องปฏิบัติตลอดใช่หรือไม่
  • ฺB : ใช่การเป็นคนซื่อเป็นเรื่องที่ดีและต้องปฏิบัติตลอด
  • A : งั้นถ้าเพื่อนคุณจะฆ่าตัวตาย คุณได้แย่งมีดจากเขาเพื่อไม่ให้เขาฆ่าตัวตาย ด้วยการนั้นเป็นการทำไม่ซื่อ ตกลงแล้วความซื่อยังเป็นเรื่องที่ดีที่ควรปฏิบัติอยู่ตลอดเวลาไหม
  • A : ……

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

  • ผม : สิ่งศักดิ์สิทธิ์นี่ต้องทำแต่สิ่งที่ดี เรื่องที่ถูกต้องใช่ไหม
  • แม่ : ใช่
  • ผม : งั้นการขังเด็กไว้ในถ้ำนี่จัดว่าเป็นสิ่งที่ดีเหรอ แล้วเรายังจะนับถือไอสิ่งที่ขังเด็กไว้ในถ้ำเป็นสิ่งศักดิ์สิทธิ์ด้วยเหรอ

ผมจำไม่ได้ว่าหลังจากนั้นเราคุยอะไรกันต่อแต่ที่รู้ๆกลายเป็นการทะเลาะที่รุนแรงระดับหนึ่ง ผมกลายเป็นคนลบหลู่สิ่งที่มองไม่เห็น สิ่งศักดิ์สิทธิ์ ซึ่งจริงๆผมกำลังใช้เหตุผลคุยกับแม่ จริงๆผมอาจจะกำลังจะบอกว่า สิ่งที่ขังเด็กอยู่เนี่ย (ถ้าเด็กถูกขังจริงๆ) มันต้องอะไรสักอย่างที่ไม่ใช่สิ่งที่แม่กำลังอ้อนวอนให้ปล่อย เพราะสิ่งนั้นคงต้องไม่ใช่สิ่งศักดิ์สิทธิ์แน่

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

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

พระเจ้ามีตัวตนไหม การพยายามหาคำตอบ ด้วยวิธีการต่างๆ

แต่ละบทของหนังสือเล่าถึงนักปรัชญาแต่ละคน ไล่เรียงไปตามยุคสมัย แต่ละคนมีคำถาม และ พยายามจะหาทฤษฏีมาให้คำตอบ และหนึ่งคำถามที่ยิ่งใหญ่ที่สุดคำถามหนึ่งคือ “พระเจ้ามีตัวตนไหม” นักปรัชญาหลายคนพยายามหาคำตอบ ซึ่งแต่ละคนมีทฤษฎีมารองรับมากมาย ตัวอย่างเช่น

  • ถ้าคุณคิดถึงพระเจ้านั่นแปลว่าพระเจ้าต้องมีอยู่จริง เปรียบเหมือนจิตรกรวาดภาพ ภาพนั้นมีตัวตนในความคิดของเขา แล้วเขาจึงวาดภาพนั้นออกมาจากสิ่งที่อยู่ในความคิดของเขาให้มามีตัวตนจริงๆ พระเจ้าก็คล้ายๆกัน

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

คืออ่านแล้วมันก็พอทำให้ผมเชื่อได้นะว่าพระเจ้ามีจริงๆ คืออ่านแล้วมันมีอะไรมาสนับสนุนเรื่อยๆ แต่เชื่อเถอะครับในโลกนี้มีคนคิดค่างเสมอ (ผมก็หนึ่งในนั้นกับการคิดต่างเรื่องพระเจ้า) หลายคนพยายามโต้แย้งสิ่งเอ่ยอ้างว่าพระเจ้ามีตัวตน เช่น ทฤษฎีแรกที่ว่าแค่คิดก็มีอยู่จริง งั้นลองจินตนาการถึง เกาะที่สมบูรณ์แบบมีทุกสิ่งที่อย่างอยู่ที่ใดที่หนึ่งกลางมหาสมุทรอันกว้างใหญ่ที่ไม่มีใครเคยไป คุณคิดว่ามันมีอยู่จริงไหม แค่การยกตัวอย่างนี้ก็ทำลายทฤษฏีแรกไปแบบไม่เหลืออะไรให้เชื่อละ

แต่สำหรับผมมีทฤษฏีหนึ่งที่ผมชอบในการที่จะบอกว่าพระเจ้ามีตัวตนมากๆ แต่จริงๆจะใช้คำว่าบอกว่ามีตัวตนไม่ถูกนะต้องใช้คำว่าเราควรเชื่อว่ามีพระเจ้าไหม มันคือทฤษฏีของ เบลส ปาสกาล คือที่ใช้ทฤษฎีความน่าจะเป็นและผลลัพธ์ที่ตามมาที่จะช่วยให้เราควรเชื่อว่ามีพระเจ้าไหม ว่าง่ายๆเลย การเชื่อว่าพระเจ้ามีจริงก็คือการพนันแบบ 50 / 50 อันนี้เหมือนโยนเหรียญ ถ้าคุณเป็นนักพนันมืออาชีพ คุณจะต้องดูว่าผลลัพธ์กับความเสี่ยงที่ได้รับก่อนการพนัน

  • ทางเลือกที่จะไม่เชื่อสิ่งที่คุณจะได้คือ คุณจะใช้ชีวิตแบบไหนก็ได้ เป็นอะไรที่อยากเป็น ทำอะไรที่อยากทำ ทำดีทำชั่วช่างหัวแม่งเพราะพระเจ้าไม่มีจริง แต่ความเสี่ยงที่คุณจะได้รับคือ ถ้าพระเจ้ามีจริง คุณจะต้องตกนรกไม่ได้ไปไหนชั่วนิรันดร์ ไม่ได้ไปแดนสวรรค์หรือพันธสัญญา

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

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

ลงมือทำดีกว่า

บทหนึ่งที่ผมชอบที่สุดคือบทที่พูดถึงนักปรัชญาชื่อ วอลแตร์ ในช่วงของเขามีทฤษฎีที่ว่า “สิ่งที่เกิดขึ้น เป็นสิ่งที่ถูกต้อง” เพราะพระเจ้าท่านทรงคิดว่ามันดี คือผมได้ยินทฤษฎีนี้แล้วแบบ เฮ้ย บ้ารึเปล่าวะ มันดีจริงๆเหรอ มันพิสูจน์ได้ยังไงว่าดี คนดีถูกคนชั่วใส่ร้ายป้ายสีแล้วนอนคุกฟรีมันเป็นสิ่งที่ถูกต้องเหรอ ถ้าเป็นผมผมคงแหกปากบอกคนอื่นๆว่ามันไม่ใช่โว้ยแล้วยกตัวอย่างให้ฟัง(และผมคงโดนจับเข้าคุกและอาจโดนแขวนคอ) แต่วอลแตร์ไม่ได้ทำแบบบั้น เขาเขียนนิยายครับ เป็นนิยายชื่อ Candide ว่าด้วยเรื่องของนักเดินทางที่เดินทางไปพบกับเรื่องราวเลวร้ายต่างๆ คนนึงเป็นนักบวชเชื่อเสมอว่า “สิ่งที่เกิดขึ้น เป็นสิ่งที่ถูกต้อง” กับอีกคนที่เป็นผู้ติดตามก็เชื่อเหมือนกัน แต่เมื่อผ่านเรื่องราวเลวร้ายต่างๆไปเรื่อยๆตลอดการเดินทาง ผู้ติดตามเริ่มสงสัยว่ามันใช่สิ่งที่ถูกต้องเหรอวะ หนังสือเล่าเรื่อยๆจนถึงตอนจบไม่มีการตัดสินว่าอะไรถูกหรืออะไรผิด แต่สิ่งที่ตัวผู้ติตตามพูดตอนจบคือ ต่อให้มันจริงไม่จริงเราก็ต้อง “ทำสวน” ทำสวนในที่นี้ของวอลแตร์คือ “การทำประโยชน์ให้โลก” ผมว่ามันดีกว่าการมาบอกว่า “สิ่งที่เกิดขึ้นเป็นสิ่งที่ถูกต้องแล้วงอมืองอเท้าไม่ทำอะไร”

ยังมีอีกหลายเรื่องในหนังสือเล่มนี้ (เล่าหมดเดี๋ยวไม่ซื้อมาอ่านกันพอดี)

จริงๆยังมีอีกหลายเรื่องในหนังสือเล่มนี้ซึ่งอ่านแล้วว้าวมากๆ ไม่ว่าจะเป็น การค้นพบทางวิทยาศาสตร์มีผลยังไงกับปรัชญา กระบวนการทางวิทยาศาสตร์ที่เป็นระบบระเบียบขนาดนี้มาจากไหน ปรัชญาก่อให้เกิดรูปแบบแนวคิดการเมืองการปกครองอย่างไร การทดลองทางศีลธรรมที่น่าสนใจที่ทำให้เราคิดว่าทำไมเราถึงยอมรับบางกรณีได้ แต่อีกกรณีทำไมไม่ยอมรับทั้งที่ผลลัพธ์เดียวกัน ทฤษฏีต่างๆที่น่าสนใจจากนักปรัชญาหลายคนในประวัติศาสตร์

อ่านแล้วได้อะไร

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

ref :
https://medium.com/literally-literary/voltaires-candide-is-the-hero-we-need-59e1c9e9292
https://pixabay.com

Unit test ตอนที่ 1 เรื่องที่ดูเหมือนง่าย แต่ทำยาก

เรื่องที่ดูเหมือนง่าย แต่ทำยาก

Unit test คืออะไร

ผมเขียนเกี่ยวกับ Unit test ไว้ 4 ตอน คุณสามารถกด Link ด้านล่างเพื่ออ่านที่เกี่ยวกับ Unit test ตอนต่างๆได้เลย

คำว่า Unit test นั้นผมได้รู้จักตอนเรียนปี 4 ในวิชา Object Oriented Analysis and Design (จริงๆเป็นวิชาของปี 3 หลักสูตรใหม่ ผมเรียนหลักสูตรเก่าเลยไปลงเรียนกับน้อง) เพราะอาจารย์ให้เขียน App และต้องส่ง Unit test ไปให้ด้วย ตอนนั้นก็งงๆว่ามันคืออะไร ทำไมต้องเขียน ก็เข้าใจคร่าวๆว่ามันเป็นการ Test Code ของเราว่าทำงานถูกต้องไหม ซึ่งตอนเรียนในส่วนนี้พูดถึงหลายอย่างมากไม่ว่าจะ Mock, Stub, Spy และอีกหลายๆอย่างเลย

นิยามแบบทางการผมแนะนำให้ตามไปอ่านที่ wiki หรือ อ่านจากของนักพัฒนาท่านอื่นซึ่งมีมากมายเช่น ของคุณ Tanapol Nearunchorn หรือ ของคุณ Minseo Chayabanjonglerd ซึ่งอธิบายไว้แล้ว แต่สำหรับผมโปรแกรมเมอร์บ้านๆมันคือ “การเขียน Code ไว้ Test Code ส่วนหนึ่งว่ามันทำงานถูกต้องตามที่ต้องการหรือไม่ โดยไม่ต้องติดต่อกับส่วนจริงๆที่เกี่ยวข้องกับ Code ส่วนนั้น” อ่านแล้วงงสินะ ผมเลยแนะนำให้อ่านของคนอื่นไงล่ะ

เข้าส่วนการอธิบาย

Code ส่วนหนึ่ง

ความหมายคือ Function , Control Flow, Class หรือส่วนหนึ่งส่วนหนึ่งของ Code ก็ได้

โดยไม่ต้องติดต่อกับส่วนจริงๆที่เกี่ยวข้องกับ Code ส่วนนั้น

ความหมายคือ อ่า อธิบายยากละ คือ โดยปกติเวลาเราพัฒนาโปรแกรมที่เริ่มซับซ้อนเนี่ยมันจะไม่ทำงานได้โดย Code เพียงส่วนเดียว ยกตัวอย่างง่ายๆอย่าง Web application ที่ต้องมี ส่วน Presentations ส่วน Business Logic ส่วนติดต่อ Database (อันนี้ผมแบ่งแบบคร่าวๆไม่ได้ยึดหลักอะไรเลย) จะเห็นว่ามีส่วนที่เกี่ยวข้องกันคือ ส่วน Business Logic เกี่ยวข้องกับส่วน Database ดังนั้น ถ้าผมจะทำการเขียน Unit test code ส่วนหนึ่งที่เรียกว่า Business Logic ผมจะต้องเขียน Unit test โดยไม่ต้องติดต่อกับส่วน Database ตัวจริง

อะไรวะ

อย่าพึ่งตกใจครับ ตอนผมเริ่มศึกษาการเขียนอันนี้ผมก็รู้สึกเหมือนที่คุณกำลังรู้สึกคือ อะไรวะ ไม่เอาของจริงไป Test แล้วมันจะ Test ได้ยังไง บ้า บ้า มันต้องบ้าไปแล้ว แต่ถ้าอ่านไปเรื่อยๆ(น่าะจะหลายบท)จะค่อยๆเริ่มเข้าใจเองว่ามันทำได้ยังไง

ทำไมต้องทำ ทำแล้วได้อะไร

เวลาเราจะทำอะไรอย่างหนึ่งในโลกของโปรแกรมมันจะต้องมีเหตุมีผลคือ ทำไมต้องทำ ทำแล้วได้อะไร

ทำเพื่อให้เรามั่นใจว่า Code ที่เราเขียนนั้นทำงานถูกต้อง

อันนี้กำปั้นทุบดินมาก เขียน Test ก็เพื่อไว้เช็คว่า Code ทำงานถูกไหม

ทำเพื่อให้เราสามารถ Refactor code ได้

อันนี้เป็นเรื่องที่หลายคน หลายองค์กร หลายบริษัท เพิกเฉยหรือถึงกับบอกว่าไร้สาระมากๆ คือมันจะมีคำพูดคำพูดนึงบอกว่า “จะไปแก้ Code ที่ทำงานได้แล้วทำไม” หรือ “แก้แล้วรายได้บริษัทเพิ่มไหม มีแต่เพิ่ม Cost” ผมทำงานมาประมาณ 3 ปี (ณ เวลานี้) ได้ยินคำพูดนี้บ่อยมาก บ่อยจนเบื่อ คือในทางธุรกิจการ Refactor code มันไม่ได้เพิ่มรายได้หรอกครับ

แต่ในทาง Technical มันเป็นการช่วยลด Cost ที่ต้องมาอ่าน Code ทำความเข้าใจ Code ถ้าเปรียบง่ายๆคือ ระหว่างโกดังที่ของจัดระเบียบเรียบร้อยมีการจัดหมวดหมู่สินค้าต่างๆ กับ โกดังที่สักแต่ว่าเก็บห่าอะไรเข้าไป ใส่ส่งๆใส่เร็วๆ คุณคิดว่าถ้าวันนึงต้องเอารูปน้องเฌอปราง น้องแนทเธอรีน มาชื่นชมความงาม โกดังไหนจะหาของเจอก่อนกัน ถ้าพูดกันตามทฤษฎี อะไรที่ถูกเก็บเป็นระเบียบย่อมถูกหาได้เร็วกว่าอะไรที่เก็บแบบมั่วๆซั่วๆ (นึกภาพการหาข้อมูลใน Array กับ การหาข้อมูล AVL Tree) เช่นกัน ถ้า Code ที่ทำการ Refactor ให้อ่านง่าย เป็นระเบียบ มันย่อมทำความเข้าใจง่ายกว่า Code เหี้ยๆที่เขียนแบบชุ่ยๆ
แต่อย่างว่าบริษัทหรือองค์กรส่วนใหญ่มักจะสนใจแต่รายได้และด้วยความที่ไม่เขาไม่ได้เข้าใจเนื้องานจริงๆของการ Develop เขาจะไม่เคยเห็น Cost แฝงพวกนี้ มันเป็นเรื่องยากที่จะพูดให้เข้าใจและสุดท้ายมันรำคาญมากจนไม่อยากจะพูดให้เข้าใจ

คำถามต่อไปแล้วมี Unit test แล้วมันทำให้ Refactor ได้ยังไง คำถามเวลาที่เราจะแก้ Code จะมีคือ “จะมั่นใจได้ไงว่า Code ที่แก้ทำงานถูกต้อง” บอกเลยว่าเป็นคำถาม Classic (ยังกะเพลง Canon) คำตอบมันก็มีมากมายเลย เช่น เชื่อมือผม , ผม Test แล้ว, เอาหัวเป็นประกัน แต่คำคอบของคำถามนี้จริงๆมันคือ “ต้อง Test โว้ย” ซึ่งถ้าคุณต้อง Test เอง คุณต้อง Test ทุก Case ของส่วนที่คุณแก้ ถ้าส่วนนี้มี 100 Case แล้ว Manual Test ก็ “ขอให้โชคดี ขอให้มีสุข” แต่ถ้าคุณเขียน Unit test คุณจะแค่สั่ง Run แล้วมัน Test ทุก Case ให้คุณ คุณจะไม่กลัวการ Refactor code เพราะถ้า Refactor แล้วมีอะไรหลุด คุณจะทราบจาก Unit test

ทำแล้วคุณจะได้คิดก่อนเขียน คุณจะเห็นกรณีที่คุณมองข้ามไป

การเขียน Unit test มันจะเป็นการบีบบังคับให้คุณคิดก่อนที่เขียน เพราะตามหลักการเขียน Unit test คุณต้องเขียน Unit test ก่อนที่จะเขียน Code ดังนั้นคุณจะต้องคิด คิด คิด แล้วก็คิด ว่ามันจะมี Case อะไรบ้าง เช่น ถ้าคุณเขียนส่วน Business Logic เกี่ยวกับการกรองข้อมูลลูกค้าออกกลุ่มๆตามเงื่อนไข คุณก็จะเริ่มคิดว่า Input มันมีอะไรได้บ้าง ถ้าใส่ค่าว่างจะเป็นยังไง มันต้อง Return อะไร ถ้าส่ง Null ล่ะ ถ้าส่งค่าที่ไม่มีใน Master File ล่ะ ถ้า … มันจะค่อยๆเข้ามาเวลาคิด เพราะเราเปลี่ยนความคิดจาก เราเขียน Code ให้เสร็จ มาเป็นคิดว่า Code ที่เราจะเขียนมี Input อะไร Output อะไร เราจะเห็นภาพรวม เราจะเห็นจุดที่ควรระวัง จุดที่มีปัญหาเกี่ยวกับ Design แล้วไปคุยกับทีม ซึ่งเสียเวลาน้อยกว่า การเขียน Code ไปครึ่งทางแล้ว “ฉิบหาย มันมี Case นี้ดวยว่ะ แล้วจะเอาข้อมูลมาจากไหนวะ” หรือ อ้าว ตรงนี้มันใช้วิธีนี้ไม่ได้ ต้องแก้ใหม่หมด

ทำแล้วคุณจะได้ Code ที่ยืดหยุ่นระดับหนึ่ง

เมื่อคุณต้องเขียน Unit test คุณจะเจอกับคำว่า โดยไม่ต้องติดต่อกับส่วนจริงๆที่เกี่ยวข้องกับ Code ส่วนนั้น ไอตัวนี้แหละที่เป็นข้อบังคับทำให้เราต้องเขียน Code เพื่อให้เอื้ออำนวยในการทำแบบนี้ (วิธีไหนเดี๋ยวอธิบายอื่นละกัน เดี๋ยวจะยาวกว่านี้ ซึ่งตอนนี้ก็น่าจะอ่านจนเบื่อละ) ซึ่งถ้าทำตามนั้น Code ของคุณจะยืดหยุ่นขึ้นมาระดับหนึ่งเลยล่ะ

ปัญหาที่ต้องเจอ

เวลาที่เพิ่มขึ้น

มันเป็นเรื่องปกติมากที่เวลาจะต้องเพิ่มขึ้น ก็ถ้าคุณเพิ่มจากการวิ่งรอบสนาม 1 รอบมาเป็นวิ่งรอบสนาม 2 รอบ คุณคิดว่าจะใช้เวลามากขึ้นไหมซึ่งถ้าคุณไม่ใช่ The Flash ที่ระยะทาง 800 เมตร กับ 400 เมตรนั้นใช้เวลาห่างกันไม่เกิน ns คุณคงตอบว่าต่างแน่นอน พอเวลาเพิ่มขึ้นมันก็หมายถึง Cost ที่เพิ่มขึ้น ซึ่งบริษัท องค์กร ส่วนใหญ่คงจะไม่ค่อย OK สักเท่าไหร่ นี่เป็นกำแพงด่านแรกๆที่คุณจะต้องเจอ วิธีเอาชนะกำแพงพวกนี้ก็คงจะต้องบอกว่ามันจะลด Cost ในอนาคต ลดความเสี่ยง ซึ่งผมไม่เคยข้ามกำแพงห่านี่ได้เลย เลยต้องเพิ่มเวลาเข้าไป (ทำโอฟรี) เพื่อเพิ่ม Unit test เข้าไปในงานของตัวเอง

มารในใจ

ผมว่าทุกคนจะต้องเจอมารในใจแน่นอนครับ การเขียน Unit test บางครั้งมันก็เป็นอะไรที่น่าเบื่อ เซ็ง เอาเสียมากๆ (เดี๋ยวพอได้ลองเขียนจะรู้เอง) จนบางทีมันแบบ “โอ้ย ทำไมต้องมาเขียนอะไรแบบนี้ด้วยวะ” ดังนั้นหลายคน หลายท่าน ก็จะยอมแพ้และเลิกเขียนมันไป ผมแนะนำว่าก็อดทนเขียนไปเถอะครับ มันเป็นการลงทุนระยะยาว ตัวคุณในอีก 7 วัน 1 เดือน 1 ปี ข้างหน้า หรือ คนอื่นที่มาทำงานต่อ อาจจะขอบคุณคุณก็ได้

เขียนไม่เป็นโว้ย

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

เนื่องด้วยเหตุผลในข้อนี้ ผมเลยอยากจะเขียนแชร์ว่าเขียน Unit test ที่ผมเคยเขียนในงานเนี่ยมันเขียนยังไง ซึ่งอาจจะไม่ใช่ Unit test ที่ดีเลิศหรืออะไร แต่มันคงพอเป็นแนวทางให้คนอื่นๆอ่านแล้วไปลองทำตามได้

Unit test ไม่ใช่ยาวิเศษ ไม่ใช่กระสุนเงินฆ่าปิศาจ ไม่ใช่รักแท้ที่เยียวยาทุกสิ่ง

ผมขอบอกไว้ก่อนว่า Unit test ไม่ใช่ยาวิเศษที่ทำแล้วจะไม่เกิด Bug หรือ เกิดข้อผิดพลาดอะไร มันแค่เป็นตัวช่วยให้เรามั่นใจใน Code ของเราว่าทำงานถูกต้อง ภายใต้ Case ที่เราคิดขึ้นมาได้ในตอนนั้น แต่ถ้ามี Case ใหม่ๆเกิดขึ้นมันก็แน่นอนอยู่แล้วว่าต้องหลุด หน้าที่ของเราคือเอาไอ Case หลุดเหล่านี้ไปใส่เพิ่มใน Unit test เพื่อการันตีว่า คราวหน้ามันจะหลุด Case อีก

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

เพลงประกอบการเขียนบทความนี้

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

ref :
https://life.wongnai.com/%E0%B9%81%E0%B8%99%E0%B8%A7%E0%B8%84%E0%B8%B4%E0%B8%94%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B9%80%E0%B8%82%E0%B8%B5%E0%B8%A2%E0%B8%99-unit-test-b5f89ef871b0
https://medium.com/fungjai/%E0%B8%A1%E0%B8%B2%E0%B8%97%E0%B8%B3%E0%B8%84%E0%B8%A7%E0%B8%B2%E0%B8%A1%E0%B8%A3%E0%B8%B9%E0%B9%89%E0%B8%88%E0%B8%B1%E0%B8%81-unit-test-%E0%B8%AA%E0%B8%B3%E0%B8%AB%E0%B8%A3%E0%B8%B1%E0%B8%9A-android-developer-%E0%B8%81%E0%B8%B1%E0%B8%99%E0%B9%80%E0%B8%96%E0%B8%AD%E0%B8%B0-817ac642b44c
https://www.dccomics.com/characters/the-flash
https://www.facebook.com/bnk48official.cherprang/
https://www.facebook.com/bnk48official.natherine/
https://th.wikipedia.org/wiki/%E0%B9%82%E0%B8%94%E0%B8%A3%E0%B8%B2%E0%B9%80%E0%B8%AD%E0%B8%A1%E0%B8%AD%E0%B8%99
https://pixabay.com/

ทำ MAVEN Repositoty ด้วย NEXUS

ความหลากหลายทางชีวภาพ (ทางเทคโนโลยี)

ในปัจจุบันภาษาที่ใช้ในการเขียนโปรแกรมนั้นมีมากมายหลายภาษา ยิ่งเป็น Framework นี่ไม่ต้องพูดถึงครับ มีมากมายมหาศาล ซึ่งมันเหมือนจะดีนะครับแต่มันมีการศึกษาเกี่ยวกับการมีทางเลือกแล้วพบว่า ยิ่งคนเรามีทางเลือกมากเท่าไหร่ ยิ่งทำให้คนเราไม่ตัดสินใจที่จะเลือก หรือเลื่อนเวลาที่จะตัดสินใจออกไป ซึ่งมันเกิดจากเรากลัวว่าทางที่เราเลือกนั้นไม่ใช่ทางที่ดีที่สุด (ผมอ่านมาจากนิตยสาร Creative Thailand มีแจกฟรีที่หอศิลป์กรุงเทพ, อ่านออนไลน์ หรือสมัครสมาชิกก็ได้นะ เนื้อหาดีกว่าหนังสือพิมพ์บางฉบับเสียอีก) ซึ่งก็ตรงกับสถาการณ์ของโปรแกรมเมอร์ในปัจจุบัน คือ ภาษา , Framework, Database, Vendor ที่ให้บริการ แต่ละคนก็บอกข้อดีเย้ยอีกฝั่งแบบ โอ้พี่ขายของกันได้น่ากลัวจริงๆ การจะเริ่มเขียนโปรแกรมมันเลยแบบ “กูจะเขียนภาษาอะไรดีวะ แล้วจะใช้ Datbase อะไร Framework ไหน” ตามนิตยสารเขาบอกไว้ว่า ให้เลือกเลยครับ หาเหตุผลมาเลือก จากนั้นเขียนเหตุผลตัวโตๆๆๆๆๆ ไว้ จากนั้นเวลาเสียใจให้กลับมาอ่านว่าทำไม เราถึงเลือกทางเลือกนี้ แล้วอีกอย่างนึงที่ผมชอบคือ ก่อนจะเลือกทางเลือกไหนให้ยอมรับการที่จะเดินทางบนทางเลือกนั้น ถ้าคุณจะใช้ nodejs คุณก็ต้องพร้อมเจอการทำงานบบ Async ถ้าคุณจะเขียน Assembly คุณก็ต้องยอมรับที่จะอ่านเลขฐาน 16 ต้องจำ interrupt หมายเลขต่างๆ ต้องเข้าใจฮาร์ดแวร์และเข้าใจข้อจำกัดต่างๆ ถ้าเทียบกับชีวิตจริง ถ้าอยากเป็นเจ้านายตัวเอง คุณต้องยอมรับให้ได้ว่าคุณต้องทำงานเองเกือบทุกอย่างตั้งแต่ติดต่อลูกค้า จัดทำเอกสาร ทำบัญชี ไม่มีหยุดเสาร์อาทิตย์ (ในช่วงแรก) ให้ได้ คุณทำได้ไหม
ถ้าทำไม่ได้ก็แนะนำให้ไปเลือกทางเลือกอื่นครับ

มาเรื่องจริงบ้าง

เนื่องจากบริษัทที่ผมทำงานอยู่ใช้ภาษาในการพัฒนามากเช่น PHP, java, Javascript, C# ซึ่งจริงๆที่มันเยอะอาจมาจาก ลูกค้าหน้า… ที่มีความต้องการแบบต่างๆเช่น ผมอยู่บนโลก Windows คุณต้องเขียน C# หรือบางที่บอก เราไม่ให้ใช้ Java เพราะมันไม่ปลอดภัย (เอ้า ไอเชี่ยไม่ปลอดภัยยังไงวะ) หรือ มาจากปัญหาในการข้อจำกัดในการพัฒนาในช่วงนั้น

ในตอนก่อนๆผมเล่าเรื่องการทำ Repository ไว้เก็บ Lib กลางให้บริษัทใช้ซึ่งตอนก่อนๆผมทำ npm ให้ภาษา javascript ซึ่งตอนนี้มีคนมาใช้ได้แล้ว (คนเดียว) ต่อไปก็ถึงคิว Java กันแล้ว โดย Java ตัวนี้จะใช้เป็น Maven repository มาเริ่มกันเลยดีกว่า(ชักแม่น้ำมาเยอะละ)

ลงมือกันเลย

ส่วนของผู้ที่จะเอา Lib ของ Java ขึ้น Maven

ถ้าคุณมี Project ที่เขียนด้วย Java และใช้ Maven อยู่แล้วนี่ง่ายมากครับที่จะเอา lib ขึ้น Maven repo ขั้นแรกให้เพิ่ม Tag เหล่านี้ไปใน pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<!-- Tag อื่นๆ เช่น dependency อยู่ด้านบน -->

<!-- เพิ่มอันนี้เข้าไปใน pom.xml -->
<distributionManagement>
<repository>
<id>nexus-release</id>
<name>nexus-release</name>
<url>http://192.168.56.101:8081/nexus/repository/maven-releases/</url>
</repository>
</distributionManagement>

</project>

ที่เพิ่มเข้าไปนี้คือการบอกว่า เราจะ deploy code ของเราไปที่ไหนบ้าง โดยอันนี้ผมจะให้มัน deploy ไปไว้ที่ http://192.168.56.101:8081/nexus/repository/maven-releases/ (อันนี้เป็น repository เครื่องจำลองของผมเอง) โดย url นี้ไปเอามาได้จากตรงนี้เลย

จากนั้นต้องไป setting ไฟล์ของ maven ที่ลงที่เครื่องกันครับโดย Folder ของมันชื่อ .m2 แต่ละ os จะมีที่วางไม่เหมือนกัน

1
2
3
4
5
6
7
8
9
10

Windows
C:\Documents and Settings\{your-username}\.m2
หรือ
C:\Users\{your-username}\.m2

Mac and Linux
~/.m2

~ หมายถึง Home ของ User ที่เข้าใช้งานครับ

โดยไปที่ Folder : .m2 แล้วไปที่ไฟล์ settings.xml โดยหากไม่มีให้ไปเอาตัวอย่างได้จาก ตัวอย่างไฟล์ settings.xml

จากนั้นทำการเพิ่ม tag server ภายใน servers

1
2
3
4
5
6
7
<servers>
<server>
<id>nexus-release</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>

โดยตรง id นั้นจะต้องตรงกันกับใน pom.xml ที่เรากำหนดไป สังเกตว่า id ของทั้งสองอันคือ nexus-release เหมือนกันครับ ส่วน username password ก็ username password ของ nexus ที่ตั้งไว้ อันนี้เป็น admin admin123 ครับ (จริงๆมันคือค่า Default)

จากนั้นลองทำการสั่ง mvn deploy ที่ Folder project หรือถ้าใช้ ide ก็สั่งให้มัน run ผ่าน ide หากไม่มีอะไรผิดพลาดตัว project จะโผล่ใน maven repo ใน nexus ตามภาพ

สำหรับคนที่จะเอา Lib จาก repo ลงมาใช้งาน

อันนี้เราต้องทำการเพิ่มข้อมูลที่ไฟล์ pom.xml ของ Project ที่ผมใช้ทำ Lib ไว้ Deploy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<!-- มี Tag อื่นๆ อยู่ด้านบน -->

<dependencies>
<dependency>
<groupId>test.maven</groupId>
<artifactId>helloworld</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>

<!-- Tag อื่นๆ เช่น dependency อยู่ด้านบน -->
<repositories>
<repository>
<id>nexus-release</id>
<url>http://192.168.56.101:8081/nexus/repository/maven-public/</url>
</repository>
</repositories>
</project>

โดยส่วนนี้คือการทำการเพิ่ม repository ที่เราจะเอา Lib มาใช้ โดยหากท่านไม่เคยไปทำการเพิ่มค่า server ที่ไฟล์ settings.xml แล้วล่ะก็ให้ไปทำการเพิ่มด้วยนะครับ โดยทำแบบหัวข้อด้านบนเลย ส่วน url ที่ใส่มานั้นหาได้จาก maven-public โดยตัว maven-public ตัวนี้คือช่องทางให้เราเข้าไปโหลด lib ลงมานั่นเอง

จากนั้นเราก็แค่ไป copy ตัว dependency tag มาใส่ เท่านั้นก็สามารถนำ Lib มาใช้งานได้แล้วครับ สำหรับตอนนี้ขอจบเพียงเท่านี้ เจอกันใหม่ตอนหน้า กะจะทำส่วนที่เป็น Docker แต่ไม่รู้จะทำได้หรือเปล่า

ตัวอย่าง pom.xml ที่ใช้ Deploy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test.maven</groupId>
<artifactId>helloworld</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<name>helloworld</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.10</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>10</source>
<release>10</release>
</configuration>
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>6.2</version>
<!-- Use newer version of ASM -->
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>nexus-release</id>
<name>nexus-release</name>
<url>http://192.168.56.101:8081/nexus/repository/maven-releases/</url>
</repository>
</distributionManagement>
</project>

สำหรับใครไม่รู้จะเลือกภาษาอะไรมาเขียนโปรแกรม ผมแนะนำอันนี้เลย

ref :
http://www.baeldung.com/maven-deploy-nexus
https://gist.github.com/ozkansari/5882919
https://github.com/sonatype/nexus-book-examples/blob/master/maven/apache-maven/conf/settings.xml
http://www.tcdc.or.th/creativethailand/magazine/28436
http://www.tcdc.or.th/upload/iblock/1ff/1ff1be239418097ab4841770df53e085.pdf
https://codeburst.io/what-programming-language-should-i-learn-f3f164ca376c

เพลงประกอบการเขียนบทความนี้ :

Line Alert Forward Project Part 1

งานประจำที่น่าเบื่อ

ถ้าถามว่าการเป็นโปรแกรมเมอร์แล้วอะไรน่าเบื่อที่สุดก็คงจะเป็นงานประจำนี่แหละ คือมันน่าเบื่อที่เราต้องมาทำอะไรเดิมๆเรื่อยๆ บางทีเราต้องเจอ Legacy code บางทีต้องมารับงานทำตามใจลูกค้า แก้โน่นนี่นั่นที่เราดูแล้วมันไม่น่าตื่นตาตื่นใจ ย้ายโน่นย้ายนี่ในหน้าจอ มันไม่สวยเลย บลาๆๆๆ อยากได้อะไรที่จู้จี้จุกจิกน่าเบื่อ งานบางงานเป็นงานที่ไม่น่าทำไม่น่าคุ้มแต่ก็ต้องทำ เราอยู่ในสภาพคนไม่อยากทำที่ต้องทำงาน ถ้าตามพระพุทธศาสนาคือการขาด ฉันทะ คือ ความพอใจในเรื่องที่ทำซึ่งถ้าไม่มีงานมันคงออกมาไม่ดี ไอเรื่องแบบนี้เวลาเจอนานๆมันก็เริ่มสะสมขึ้นเรื่อยๆจนพอกพูนขึ้นเรื่อยๆจนเกิดเป็นอาการเบื่อ ยิ่งคนที่ไม่มีอะไรทำอยู่แล้วด้วยยิ่งเคว้งคว้าง จะเล่นเกมส์เหมือนตอนเด็กๆก็ไม่ค่อยสนุกแล้วเพราะเกมส์มันมี Pattern ซ้ำๆ เล่นแปปๆก็เบื่อ จะเล่นเกมส์ MOBA ก็แก่เกินแกงละ จะไปเล่นโชว์ NOOB ให้คนอื่นเขาหัวร้อน (รวมทั้งตัวเอง) ก็ไม่ค่อยจะคุ้มกับเวลาในชีวิตที่เหลือน้อยลงทุกวันๆ (เคยคิดจะอยู่ถึงสัก 80 ตอนนี้ 60 จะถึงรึเปล่ายังไม่รู้)

ลงกับเขียน Code ละกัน

ในเมื่องานประจำมันน่าเบื่อนัก ก็มาเขียน Code ที่แม่งไม่เกี่ยวกับงานประจำแม่งเลย (จริงๆอาจเกี่ยวก็ได้) ละกัน ในวงการเขาเรียก Project พวกนี้ว่า Side Project ซึ่งข้อดีของไอ Project พวนกนี้คือ อยากทำห่าอะไรก็ทำ อยากลองอะไรก็ลอง ไม่มีข้อจำกัดห่าเหวอะไรทั้งสิ้น ไม่มีลูกค้าหน้าหมามาชี้นิ้วว่าอยากได้แบบไหน ทุกอย่างเป็นอย่างที่เราต้องการจะสร้างสรรค์ยังไงก็ได้ จะให้หน้าจอมันออกมาเป็นแบบโบราณ ออกมาแบบ 8 Bit จะใช้ภาษาไหน Framework อะไรก็ได้

Line Alert Forward

ครับนี่คือชื่อ Side Project ที่ผมจะทำครับ ชื่อมันอาจจะผิดหลักไวยากรณ์หน่อย (ถึงมากที่สุด) ตอนแรกจะใช้ชื่อผู้หญิงที่ตัวเองชอบมาเป็นชื่อ Project ละ แต่กลัวว่ามันจะเป็นตราบาปให้เธอไปตลอดชีวิตมากกว่า เลยเอาชื่อแบบมั่วๆละกัน

ที่มาและความสำคัญ

ชื่อหัวข้อแม่งยังกะกับเล่ม Project เลย จริงๆที่มาไม่มีอะไรมากไปกว่าเบื่อกับ Code แบบเดิมๆที่ไม่ตามใจตัวเอง อยากลองอะไรใหม่ๆ ไอตัว Project นี้เนี่ยมันเริ่มมาจากที่บริษัทที่ทำงานอยู่เนี่ยมีปัญหาเรื่องการแจ้งเตือนเวลา Service มีปัญหา คือจริงๆมันมีระบบแจ้งเตือนละคือ e-mail ไงล่ะพ่อคุณ แต่ไอ e-mail ห่าเนี่ยมันกลายเป็นอะไรที่คนไม่ค่อยอ่านตั้งแต่เมื่อไหร่ไม่รู้ (คงตั้งแต่เริ่มมี Chat) หรือจริงๆเมลล์มันมีไว้สำหรับคุยงานแบบที่เป็นทางการคนเลยเริ่มเบื่อที่จะอ่าน ผมเลยกะทำ Project นี้ขึ้นมาเพื่อทำการส่ง Alert เข้า Line ผู้เกี่ยวข้องกับ Service (คนไทยใช้ Line กันเยอะจริงๆ น่าแปลกใจเหมือนกัน)

ใช้อะไร + ทำอะไร

Project นี้กะใช้อะไรบ้าง แล้วก็ทำอะไรบ้าง

  • Line api : เห็นคนอื่นเขาใช้มานานละ ใช้กันจนแม่งเลิกฮิตละ ว่าง่ายๆว่าตกรถละเลยต้องวิ่งตาม แต่ก็ดีตรงที่เวลาเรามาช้ากว่าเราจะเห็นมี Resource ให้ดูเยอะแยะเต็มไปหมด (มองโลกในแง่ดีเกินไป)
  • Typescript : ไอภาษานี้ผมอยากเขียนตั้งแต่มันออกมาใหม่ๆตั้งแต่เมื่อ 3 ปีที่แล้ว ปลุกปล้ำหัดเขียนอยู่คนเดียว ชวนใครเขียนก็ไม่ค่อยมีคนเอาด้วย บางคนบอกว่ามันน่ารำคาญ มาเขียนภาษา script แล้วต้องมา strict type จนสุดท้ายก็ไม่ได้เขียน บางทีก็ไปอ่านเล่นๆว่ามันยังมีคนใช้อยู่ไหม
  • Hexagonal Architecture : คือการออกแบบ Application ให้สามารถถอดประกอบเข้ากับ Application อื่น หรือส่วนที่เกี่ยวข้องอื่นๆได้ง่าย ไอต้วนี้ผมได้รู้จักตอนเรียนปี 3 ปี 4 ตอนนี้ก็ผ่านมาได้ 4 ปีกว่าๆละ เคยพยายามจะลองเขียนกับ Application ตัวแรกที่ได้รับมอบหมายโดยใช้แนวคิดนี้ ก็ไปได้ดีพอสมควรแต่พอมีคนมาอ่านต่อก็มีคนมาถามว่า “มึงเขียนอะไรของมึง ยุ่งยากชิบหาย” แล้วก็ไม่เป็นที่นิยมในบริษัท ตัวนี้เลยอยากลองเอามาเขียนอีกรอบ
  • เขียน Test : อันนี้เคยใช้ Mocha เขียนดูละแต่เหมือนจะยังเขียนได้ไม่ดีแถมเป็นแค่ Unit test รอบนี้เดี๋ยวลองเขียน Test แบบอื่นๆดู
  • ทำ Docker Image : อันนี้เคยทำแล้วแต่เป็นแบบ Mount Volume แล้วเอา app ไปรัน ไม่เคยทำ Image ตัวเป็นๆแล้วเลยสักตัว
  • ใช้ Jenkins : อันนี้อยากทำตอนทำงานได้ปีกว่าๆ แต่ไม่ได้ทำสักที ติดโน่นนี่นั่น นั่นโน่นนี่
  • ใช้ SonarQube : จริงๆตัวนี้ใช้พอได้แบบงูๆปลาๆละ แต่ไม่เคยเอามาใช้จริง เลยกะเอามาใช้จริงเลย
  • เขียน Blog โม้ไปด้วย : จริงๆคือหมดเรื่องจะเขียน Blog ไม่รู้จะเอาอะไรมาเขียน ก็เอาเรื่องนี้ละมาเขียน Blog ซะเลย
  • เขียน Code ให้ลืมเธอ : อันนี้เอาเวลาคิดถึงใครสักคนที่เหมือนอยู่คนละโลก การเขียน Code คงจะช่วยให้ลืมได้ง่ายขึ้น (ลองแก้ BUG สักตัวดูสิจะรู้ว่าเวลามันผ่านไปไวแค่ไหน )

คืบหน้าแล้วจะมาเล่าให้ฟังว่าทำอะไรบ้าง

สำหรับหน้านี้ขอแค่โม้ละกันว่าจะทำอะไรละกัน จริงๆลง Code ไปนิดๆหน่อยละแต่เป็นอะไรที่แบบ โห มึงไม่ต้องมาโพสก็ได้มั้ง ลาไปด้วยภาพนี้กับ SideProject ก่อนๆของตัวเอง

ref :
https://www.creativebloq.com/infographic/cartoon-reveals-importance-completing-side-projects-31619566
http://fideloper.com/hexagonal-architecture
https://www.imdb.com/title/tt4964598/
https://www.typescriptlang.org/index.html

Jasper Report Server

Report , Form PDF เจ้าปัญหา

การเขียนโปรแกรม CRUD นั้นไม่ได้วุ่นวายอะไรเลยสำหรับโปรแกรมเมอร์ทั่วทั้งสากลโลก แต่มันเริ่มมามีปัญหาตรงที่ลูกค้าเพิ่ม Requirement ตาม Field งานที่ตัวเองจะเอาไปใช้ เช่น เอาไปทำโปรแกรมบัญชี บัญชีบ้าบอคอแตกหักเงินโน่นนี่นั่น แล้วมันมีวิธีคิดประหลาดๆ หรือ เอาไปใช้กับการนำเข้าส่งออก ที่เงื่อนไขมันเยอะแยะเหลือเกิน แบบโน้นแบบนี้แบบนั้น และหนึ่งในปัญหาที่น่าปวดหัวอย่างหนึ่งคือ Report, Form PDF

คือไอพวก Report, Form PDF นี้มันจะเป็นความต้องการของลูกค้าที่อยากได้กระดาษออกมา ประหลาดตรงที่อยากลดกระดาษ ลดขั้นตอน แต่ยังอยากได้กระดาษออกจากระบบ ซึ่งผมก็พอใจนะว่าเขาก็อยากได้อะไรที่มันเอาไปเป็นหลักฐานในโลกความเป็นจริง แต่บางทีเขาให้ความสำคัญกับไอพวกเวรนี่มากกว่าการทำงานของระบบว่ามันจะเสถียร ข้อมูลถูกต้อง บางทีอยากได้ Report Form ก่อนโปรแกรมจะมี Flow สมบูรณ์เสียอีก

ลูกค้าอยากได้อะไรก็ต้องได้

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

  1. Lib ประเภทให้เราสร้าง PDF ขึ้นมาจากศูนย์เลย

    Lib ประเภทนี้จะให้เราเริ่มสร้าง PDF จากลากเส้น วาดวงกลม วาดสี่เหลี่ยม วาดตัวอักษรที่ตำแหน่งต่างๆ แบบนี้จะโคตร Dynamic เราสามารถเล่นลูกเล่นแปลกๆได้เต็มที่ซึ่งเป็นข้อดีแบบสุดๆ แต่ก็แลกมาด้วยความยากในการสร้าง PDF อันนึงขึ้นมา นึกถึงตอนเริ่มทำที่เราต้อง เขียน Code เขียนเสร็จแล้วก็ Run ว่าได้อย่างที่เราอยากได้ไหม ทำวนไปเรื่อยๆจนกว่าจะเสร็จ

  2. Lib ที่ทำการสร้าง Template Form ขึ้นมาแล้วค่อยเอาค่าไปใส่

    Lib ประเภทนี้จะมีการให้สร้าง Template ขึ้นมา คล้ายๆกับสร้างไฟล์ Word ขึ้นมาแต่เว้นช่องว่างให้ใส่ตัวแปร หรือใส่เงื่อนไขบางอย่างเพื่อให้ได้ค่าออกมา โดย Lib ประเภทนี้มีข้อดีคือมันมีตัว Designer ทำให้เราเห็นตัวอย่างคร่าวๆของ Report หรือ Form ที่เป็น PDF ก่อนได้ อีกทั้งยังมีให้ลากเส้น วาง Layout แต่ถ้าจะพูดจริงๆแล้ว ไอตัว Lib ประเภทนี้มันเกิดมาจากประเภทที่แล้วนั่นแหละ แต่เขาพัฒนาตัว Designer มาครอบให้เราอีกทีทำให้เราทำงานง่าย (แล้วจะแบ่งทำซากอะไร)

หมายเหตุ การแบ่งประเภทของผมนั้นไม่เป็นมาตรฐานแต่แบ่งตาม Lib ที่เคยเจอตอนทำงาน

ซึ่งจากการที่ผู้หลักผู้ใหญ่ในบริษัทที่ผมทำงานได้ทดลองมาหลายๆ Lib และหลายสถานการณ์แล้วพบว่า Lib แบบที่เป็น Template มี Designer ช่วยให้ทำงานนั้นมีข้อดีมากกว่าเพราะตัว Template และ Designer นั้นเราสามารถแบ่งงานไปให้คนอื่นที่ไม่จำเป็นมีความรู้เกี่ยวกับ Lib ตัวนั้นมากสามารถเอางานไปทำได้ วาง Layout วางค่าตัวแปรไว้ได้

หลังจากพร่ำเพ้อมายาวนานหลายบรรทัดก็มาถึงพระเอกของบทความนี้ซึ่งก็คือ Jasper Report นั่นเอง โดยตัว Jasper นั้นรองรับได้ทุก Platform (ก็เป็น Java นี่หว่า Write once bug anywhere) สามารถสร้าง Form , Report PDF ได้ อีกทั้ง Form ยังขึ้นหน้าใหม่ มี Header Footer แบบกำหนดได้ ทำ Summary ทำ Report ซ้อน Report ทำกราฟ และข้อดีที่สุดหอมหวลสำหรับบริษัทเล็กๆที่ไม่ได้มีเงินมากมายคือมันฟรีครับ

*หมายเหตุ ตัว Designer ชื่อ Jasper Studio

งานและปัญหา งานและปัญหา งานและปัญหา …. ที่คนนอกไม่เห็น

โดยปกติตัว Jasper นั้นสามารถทำการสร้าง Report, Form PDF ออกมาได้โดยการใช้ Java ทำการ Render ออกมา ซึ่งถ้าคุณโชคดีพัฒนา Application ที่ต้องการสร้าง PDF ด้วยภาษา JAVA คุณสามารถใช้ Lib ของ Jasper มาใส่ใน Application ของคุณ แล้วทำการสร้าง Report ได้เลย แต่ถ้าคุณโชคไม่ดีใช้ภาษาอื่นพัฒนา คุณอาจต้องไปหา Lib ที่เขียนมา Intregrate กับตัว Java ซึ่งส่วนใหญ่ก็เป็นการใช้ commandline เรียกไฟล์ jar แล้วส่ง parameter เข้าไป ซึ่งการทำแบบนี้ก็เป็นปัญหาเหมือนกันเพราะคุณต้องควบคุมการเรียกใช้งานไฟล์ jar นี้เพราะทุกครั้งที่คุณเรียกใช้ jar ก็ต้องสร้าง process ใหม่ขึ้นมา ถ้ามีคนเรียกใช้หลายๆคนก็กลายเป็นการสร้าง Process จำนวนมหาศาลขึ้นมา ซึ่งเมื่อสร้าง Process ขึ้นมาเยอะๆจะเกิดปรากฏการ Thrashing ซึ่งคือการไม่ต้องทำอะไรนอกจากสลับไปทำงานไปมาระหว่าง Process ไปๆมาๆไม่เสร็จสักตัว

ปัญหาต่อไปคือไอพวก Report PDF เนี่ยมันมีแบบที่ให้สร้างแบบ รายวัน รายเดือน ทุกวันที่ 5 ทุกวันที่ 13 หรือ ทุกวันที่ x แล้วแต่ความต้องการของลูกค้าที่จะพิสดารได้มากแค่ไหน ซึ่งนั่นทำให้โปรแกรมเมอร์ต้องปวดหัวเพราะต้องมาคอย Design ตัว Application ให้สามารถทำงานแบบนั้นได้ อีกทั้งยังมีเรื่องการกำหนดให้มันเริ่มสร้าง Report PDF ตอนกี่โมง เพราะถ้าเราทำให้มันเป็น Reprot แบบออกเมื่อไหร่ก็ได้มันจะส่งผลกระทบกับ Performance ของระบบ ลองนึกภาพการอยากได้ Report รายเดือนแล้วมันมีจำเป็นต้องใช้ข้อมูลในการสร้าง Report เป็น 1 ล้าน Row ซึงมันกระทบต่อ Performance ซึ่งนั่นทำให้โปรแกรมเมอร์อย่างเราต้องมาทำการ Design ว่าจะทำยังไงให้ทำการสร้าง Report แบบ Cron ได้อีก

ยังยังไม่จบ ปัญหามันเยอะเหลือเกิน หากคุณต้องการทำการสร้าง Form, Report , PDF ที่มีจำนวนมากมายมหาศาล คุณคงต้องเปลี่ยนจากการออกแบบ Synchonous เลย มาใช้เป็นแบบ Asynchonous แทน พอมาใช้แบบ Asnychonous ตัว Application ก็ต้องทำตัว Schedule คอยจัด Queue การสร้าง PDF สร้างความยุ่งยากให้กับโปรแกรมเมอร์ที่งานเยอะอยู่แล้วเข้าไปอีก

ยังยังไม่จบ (เรื่องที่เราต้องทำมันมีมากกว่าที่คนนอกมองเห็นเสมอ) ไอพวก Report PDF เนี่ยหลังจากสร้างเสร็จแล้วลูกค้าเขาอยากให้ส่งเข้าเมลล์นั่น เมลล์นี่อีก ซึ่งนั่นทำให้เราทำส่วนนั้นเพิ่มเติมเข้าไปอีก ทำตัวส่งเมลล์ที่สามารถ Config ได้ว่าส่งให้ใคร ทำหน้าจอให้ config ได้อีก คงเป็นเรื่องที่เพิ่มเวลาในการ Dev

ยังยังไม่จบ (ยังจะมีอีกเหรอวะ) ทั้งหมดที่พูดมาคือเวลาที่อยู่ในแผนก Dev แต่อย่าลืมว่าการพัฒนา Application ไม่ได้จบที่แค่แผนก Dev มันต้องส่งต่อไปแผนก QA ที่ต้องทำการ Test อีก ซึ่งกว่าจะได้ทั้งหมดนี้อาจกินเวลาและงบประมาณจำนวนมาก และไปๆมาๆงานที่ไม่ใช่งานหลักอย่าง Report , Form PDF นั้นใช้เวลาทำนานกว่าตัว Flow หลักของโปรแกรมเสียอีก

Jasper server

งาน ปัญหา ด้านบนที่ว่ามานั้นโปรแกรมเมอร์ในสากลโลกได้เจอและปวดหัวกับมันจนมีกลุ่มคนร่วมกันสร้างตัว Jasper server ขึ้นมาเพื่อแก้ปัญหาที่ผมกล่าวมาทั้งหมดข้างบน ซึ่งตัว Jasper server ซึ่งตัวนี้ฟรีด้วยนะครับ (ของฟรียังมีในโลก แต่ต้องอ่าน Manual เอง Support ตัวเอง) แต่แบบเสียเงินก็มีแถม Feature จะดีกว่าแบบฟรีแบบหลายขุมเลยทีเดียว

ชักแม่น้ำจนไม่เป็นเรื่องราว จริงๆอยากจะถามว่าเธอน่ะรักฉันไหม

หลังจากชักแม่น้ำเล่าเรื่องไร้สาระสำหรับชาวโปรแกรมเมอร์มายาวนานแล้ว เรามาเริ่มใช้งานตัว Jasper server เลยดีกว่า

เนื่องจากในป้จจุบันมีเทคโนโลยี Container ซึ่งง่ายในการพัฒนา Application ดังนั้นจึงขอใช้ Docker ในการพัฒนา

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: '3'
services:
mariadb:
image: "bitnami/mariadb:latest"
environment:
ALLOW_EMPTY_PASSWORD : "yes"
MARIADB_USER : "bn_jasperreports"
MARIADB_DATABASE : "bitnami_jasperreports"
volumes:
- /root/jasper_server/maria:/bitnami

jasperreports:
image: bitnami/jasperreports:latest
environment:
JASPERREPORTS_DATABASE_USER : "bn_jasperreports"
JASPERREPORTS_DATABASE_NAME : "bitnami_jasperreports"
ALLOW_EMPTY_PASSWORD : "yes"
depends_on:
- mariadb
ports:
- 4080:8080
volumes:
- /root/jasper_server/jasper:/bitnami
1
2
3
4
5
6
7
8
9
10
11
12
13
*หมายเหตุในตรงส่วน
volumes:
- /root/jasper_server/maria:/bitnami
คือส่วนที่ทำการ map ข้อมูลที่อยู่ใน database ของ container maria มาไว้กับเครื่องจริง เวลาลบ container ไปแล้วข้อมูลจะได้ยังคงอยู่

volumes:
- /root/jasper_server/jasper:/bitnami
คือส่วนที่ทำการ map ข้อมูลที่อยู่ใน app ของ container jasperreports มาไว้กับเครื่องจริง เวลาลบ container ไปแล้วข้อมูลจะได้ยังคงอยู่

ports:
- 4080:8080

อันนี้เป็นส่วนที่ map port ครับ โดยผม map เข้า port เครื่องจริง 4080 เข้ากับ port 8080 เครือ่ง container

จากนั้นสั่ง

1
docker-compose up

ตัว docker-compose จะทำการ container ให้เราตามที่ต้องการ

จากนั้นลองเข้าไปใช้งานโดยเข้าผ่าน Browser เพียงเท่านี้คุณก็มี jasper server ให้ใช้งานแล้ว ผ่าน http://your_ip:4080/jasperserver/ โดยของผมจะเป็น http://192.168.56.101:4080/jasperserver/

ในส่วนนี้ขอตัดจบเพียงเท่านี้ ในตอนหน้าจะทำการสอนใช้งานกับตัว Server

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

ref :
https://hub.docker.com/r/bitnami/jasperreports/
https://community.jaspersoft.com/

เพลงเพราะๆของพี่แอนธิติมา :

ดูพระอาทิตย์ขึ้น

พระอาทิตย์ขึ้นเมื่อนานมาแล้ว

ได้มีโอกาสมีทำงานนอกสถานที่ที่ต่างจังหวัดครั้งแรกและได้พักที่โรงแรมที่ติดทะเล ระหว่างนอนคืนสุดท้ายอยู่ๆก็นึกถึงภาพทะเลกับขอบฟ้าและพระอาทิตย์

ตอนที่ได้เห็นพระอาทิตย์ขึ้นครั้งแรกจริงๆคงเป็นเมื่อเรียนอยู่ ม.3 ตอนนั้นไปทัศนศึกษาที่แถวๆหาดไรสักอย่าง เขาให้นักเรียนไปว่ายน้ำดูปะการัง เรียนรู้ว่าปะการังสำคัญยังไง ถ้าไม่มีจะเกิดอะไรขึ้น และการอนุรักษ์ปะการังทำยังไงบ้าง ที่น่าสนใจที่สุดคือเขาพยายามปลูกปะการังกันด้วย โดยปลูกโดยใช้ท่อ PVC เป็นฐานแล้วปลูก ตอนนั้นนี่ว้าวมากถ้าเราปลูกปะการังได้เยอะๆมันจะช่วยดูดก๊าซคาร์บอนไดออกไซด์ซึ่งมันดีตรงที่ปะการังอยู่ใต้น้ำมันจึงไม่ไปสร้างปัญหาเรื่องพื้นที่ อีกทั้งถ้าปะการังเยอะมันก็มีปลามาอยู่ สภาพแวดล้อมตรงนั้นก็จะดีขึ้น ซึ่งไม่รู้มันจะจริงรึเปล่าเพราะตอนนั้นเป็นเด็ก ม.3 รู้อะไรไม่เยอะ (ตอนนี้ก็ไม่รู้นะว่ามันจริงไหม)

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

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

ไม่รู้ว่าตอนนี้อาจารย์ที่สอนเราจะเป็นยังไงบ้าง เพื่อนร่วมรุ่นจะเป็นยังไง บางคนก็ไปเป็นหมอ บางคนไปเป็นวิศวกร บางคนไปเรียนสายศิลป์ แต่สิ่งหนึ่งที่ผมเชื่อว่าทุกคนที่เรียนวิทย์ - คณิต ได้ไปคือ การใช้เหตุผล

ทำได้แค่คิดถึง

บังเอิญเจอ

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

ผลลัพธ์ที่เรารู้แต่ต้น

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

สิ่งที่เหลือ

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

สุดท้าย

เจอกันครั้งหน้าซึ่งไม่รู้ว่าจะมีอยู่จริงไหม เวลาคงจะชะล้างความรู้สึกแบบนั้นให้หายไปจากใจผมและเธอ สุดท้ายถ้าเธอได้มาอ่านสิ่งที่ผมเขียนนี้ก็ขออวยพรให้โชคดี ทำอะไรสำเร็จอย่างที่เธอหวัง ได้ทำอะไรที่ใจเธอรัก อย่าทำอะไรที่ไม่ถูกใจอีก อ้อแล้วก็หนังซอมบี้มันไม่ได้น่ากลัวหรอกนะ เราว่ามันไม่น่ากลัวเลยออกน่าเบื่อด้วยนะ เราแนะนำให้ไปดูหนังไซไฟหรือสืบสวนสอบสวนมากกว่านะ ถ้าอยาก Load bittorrent เราว่าไม่ต้องอัดวิดีโอสอนแล้วนะ ให้ Teamviewer มาเลยดีกว่าเดี๋ยวเราลงโปรแกรมพร้อมสอนให้เลย สุดท้าย เราชอบเธอนะ เราหวังว่าวันนึงเราคงกลับมาคุยกันได้เหมือนเดิม เป็นเพื่อนที่ดีต่อกัน

ขีดจำกันของคุณเป็นเพียงแค่จุดเริ่มต้นของคนอื่น - Break Out

พยายามมามากแต่ก็แพ้คนอื่น

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

ขีดจำกันของคุณเป็นเพียงแค่จุดเริ่มต้นของคนอื่น - Break Out

อ่านตามคำแนะนำ

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

สังคมแห่งการแข่งขัน

ในปัจจุบันนั้นเป็นสังคมแห่งการแข่งขันจริงๆ แข่งขันกันหาที่เรียนดีๆ แข่งขันหาที่ทำงานดีๆสบายๆ หนังสือเล่มเล่าเรื่องได้เห็นภาพสังคมจีนที่คนเยอะ พอคนเยอะแต่ที่เรียนน้อย ที่ทำงานน้อยแต่ละคนก็ต้องแข่งขัน บางคนแข่งขันด้วยความรู้้ไม่ได้ก็ใช้แรงกายทำงานหนักยันดึกยันดื่น ที่น่าแปลกคือไอคนที่เราคิดว่าน่าจะอยู่สบายๆอย่างลูกผู้ดีมีเงินที่เราฝันว่าถ้าเกิดเป็นลูกคนรวยจะนอนนิ่งๆอยู่บ้านสบายๆ คนพวกนี้กลับกลายเป็นคนที่ขยันแบบสุดๆ หยุดเสาร์อาทิตย์ไปเรียนเพิ่มหาความรู้ เย็นมีเรียนพิเศษต่อ ต้องหาความสามารถพิเศษเพิ่มตลอดเวลา ซึ่งก็ปฏิเสธไม่ได้ที่พ่อแม่ของเขามีส่วน แต่เด็กเองมันก็ดันอยากไปด้วยนี่สิที่ประหลาด แต่พอมามองดูดีๆ คนที่สำเร็จในสังคมที่เป็นลูกคนรวยเขาก็ไม่ได้อยู่ดีๆเก่งขึ้นมา ก็เห็นเขามีต้องไปเรียนโน่นนี่เพิ่ม ความสามารถเขาก็เยอะอยู่สมการเป็นลูกคนรวย

ไม่มีสูตร ไม่มี Action Reply

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

อ่านแล้วได้อะไร

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