ลิขสิทธิ์ในผลงานรับจ้างฟรีแลนซ์

ปรกติรับจ้างพัฒนาซอฟต์แวร์ในรูปแบบ “ฟรีแลนซ์” ตัวผลงานที่ออกมา จะอ้างอิงจากตัวลิขสิทธิ์ของการ “รับจ้างทำของ” ซึ่งทำให้ตัวผลงานนั้นเป็นของผู้ว่าจ้าง ไม่ใช่ของผู้สร้าง แต่เราก็สามารถทำเอกสารสัญญาเพิ่มเติมได้

ฉะนั้น เวลามีคนมาปรึกษาเรื่องรับจ้างพัฒนาซอฟต์แวร์ ผมจะแนะนำให้ทำเอกสารสัญญาพ่วงท้ายตกลงความเป็นเจ้าของให้ชัดเจนไปเลย ลงรายละเอียดในระดับ library, framework และ UI ด้วยเพื่อป้องกันความฟ้องร้อง หรืออ้างสิทธิ์ที่ไม่ชัดเจนภายหลัง

ตัวอย่าง

  1. ตัว UI โดยเฉพาะ web template มักจะมีประเด็นบ่อย เพราะบางครั้งเราซื้อสำเร็จรูปมา ก็ต้องลงไว้ว่าสำเร็จรูปมาจากที่นี่ ไม่งั้น เวลาคนว่าจ้างไปเห็นเหมือนกับตัวเอง เค้าจะมาฟ้องเราได้ ทั้ง ๆ ที่เราซื้อลิขสิทธิ์เป็นรายครั้งจากเว็บขายต่าง ๆ แยกลูกค้าแต่ละรายต่างหาก และกันความเข้าใจผิดว่าเราเอางานเค้าไปขายต่อ ทั้ง ๆ ที่ work flow ต่าง ๆ ในตัวโปรแกรมคนละอย่างเลย เป็นเรื่องละเอียดอ่อนที่ต้องทำไว้กันโดนฟ้อง
  2. library ที่สร้างใช้งานเอง หรือ plugin เฉพาะที่เราสร้างขึ้นมา อันนี้ก็ต้องลงไว้ ว่าเราให้สิทธิ์ใช้งานในโครงการนี้ และมิใช่การขายสิทธิ์ให้ผู้จ้าง รวมไปถึงการกระทำใด ๆ กับ library ชุดนี้จนทำให้เราเสื่อมสิทธิ์ไป เพราะผมเชื่อว่ามีหลายคนทำงานรับงานกันก็มักจะมี library หลายตัวที่มักใช้ซ้ำ ๆ เพื่อความรวดเร็วในการทำงาน ซึ่งบางตัวก็พัฒนาเฉพาะเพื่อให้สะดวกมากขึ้น
  3. ระบุว่า ผู้ว่าจ้าง มีสิทธิในเนื้องานระดับใด เช่น ทำซ้ำ แก้ไข ดัดแปลง เผยแพร่ ต่อยอดผลงาน หรือจำหน่ายจ่ายแจก ได้ไหม ตัวไหนไม่ควรก็ตัดออก เอาเฉพาะที่เค้าควรได้รับสิทธิ์ นอกเหนือจากนั้นก็ตกลงกันว่าจะเพิ่มเงินตามสิทธิ์ที่เพิ่มขึ้น
  4. ในส่วนของตัวซอสโค้ด ตรงนั้นต้องชัดเจนว่าการแก้ไข-ดัดแปลง หากเรารู้สึกว่าควรจะเป็นเราที่ควรแก้ไขได้เพียงผู้เดียวก็ลงไว้ หากมีการแก้ไขโดยไม่ใช่เรา ให้ถือว่าหมดประกัน และละเมิดลิขสิทธิ์
  5. จากข้อที่ 3. – 4. หากในตัวเนื้องานของเรา มีการใช้ library ภายนอกทั้งที่เป็น open source หรือ proprietary นอกเหนือจาก library พื้นฐานของภาษานั้น ๆ ควรตรวจสอบสัญญาณลิขสิทธิ์ให้ดีก่อนใช้งาน และพ่วงสัญญาพวกนี้ลงในสัญญาหลักด้วย เพื่อป้องกันปัญหาในอนาคต หากเจ้าของลิขสิทธิ์ library นั้น ๆ เค้าขอตรวจสอบ ซึ่งตรงนี้สำคัญ แม้จะเกิดขึ้นได้น้อย แต่ก็มีสิทธิ์ที่จะโดนได้หากใช้งานแล้วไม่ได้ตรวจสอบก่อน

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

เรื่องเล่า myujikkii.com และ music48voter.com ฉบับปี 2020

สำหรับเว็บ music48voter.com ตัวเว็บใช้บริการ DigitalOcean ด้วยเหตุผลการเข้าถึงได้ดีจากนอกประเทศ ราคาไม่แพง รวมทั้ง 6 อย่างที่เห็น จ่ายเดือนละ 30USD โดยให้ B/W ค่อนข้างเยอะ สเปคก็ค่อนข้างดี เร็วใช้ได้ (ปีก่อนมีปัญหา ตปท เข้าได้ยาก เพราะระบบอยู่ในไทย)

ใช้ VM จำนวน 4 ตัว เป็น LBx1 (HAProxy), Webx2 (docker-compose),DBx1 (MariaDB+Redis) ส่วนไฟล์สลิปไปฝากที่บริการ Spaces คล้ายๆ S3 ของ AWS เก็บแยกไปต่างหาก

เว็บพัฒนาบน .NET Core 3.1 (C#) ต่อยอดจากปีก่อน (ปีที่แล้ว .NET Core 2.0) docker image build บน Docker Hub
เหตุผลที่มี Webx2 เพราะกลัว deploy แก้ไขจะได้ไม่ล่มแบบปีก่อน ทำ auto deploy ร่วมด้วย (ปีก่อนแก้หรือ deploy แล้วเว็บจะ down แป็บนึง เพราะ start/stop Kestrel manual) และเหตุผลที่ไม่ใช้ K8s เพราะเครื่องมันจะเยอะขึ้นอีกตัว บวกกับขี้เกียจ (จบ ?)

myujikkii.com อันนี้อีกทีมนึงทำ ซึ่งด้านการ sync ยอด progress ดึงจาก music48voter อีกที (cache 5 นาที) ทีม myujikkii ก็จะได้ไม่ปวดหัวกับระบบหลังบ้าน เลยรวมที่เดียว และ myujikkii เอา cloudflare ทำ proxy cache ด้วยเพื่อให้โหลดเร็วขึ้นประหยัด B/W

ระบบหลังบ้านในการตรวจสลิป มีทีมตรวจแล้วแจ้งสถานะ approve/reject แล้วส่งอีเมลแจ้งสมาชิกในเว็บ (ปีก่อนไม่มีอีเมลแจ้ง) ถือว่าโอเค เพราะทีมหลังบ้านไม่ต้องคอยแจ้งหรือลุ้นว่าเค้าจะกลับมาแก้ไขไหม และทำให้ทีมงานเช็คยอดง่ายขึ้น (ตัวอีเมลใช้บริการ mailgun ส่งอีเมลฟรี 5,000 ฉบับ)

ส่วนฝั่งโค้ดโหวตก็เหมือนปีก่อน และสุดท้าย last word ตอนแรกจะใช้ Google Form แต่คิดว่าลำบากตรงเอาข้อความมาแปะ และตรวจยอด เลยเขียนเพิ่มให้ทีมงานบริการจัดการได้จากจุดเดียว โดยข้อมูลโดเนทและข้อความก็อยู่ฐานข้อมูลเดียวกันทั้งหมด เอาเวลาไปโฟกัสเรื่องยอดกับบิ้วโหวตดีกว่า

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

หวังว่าจะสนุกกับกิจกรรมของทีมงานที่ทำกันทุกคน ^^

DNS Propagation Check

เจอปัญหาว่าตอนเช็ค domain ที่ดูแล ว่าตอน client ไป resolve กับ DNS resolver เจ้าต่าง ๆ ได้ผลตอบกลับออกมาเป็น IP อะไรบ้าง เพื่อตรวจสอบว่าแต่ละ DNS resolver เข้าที่ CDN/Server ชุดไหน (ถ้ามีหลายเครื่อง) หรือตรวจสอบว่าเป็นข้อมูลล่าสุดแล้วหรือยัง

หากตรวจสอบแค่ 1-2 ISP หรือ Public DNS หลัก ๆ ก็ไม่ยาก แต่ถ้าเยอะ ๆ สัก 4-5 ตัวขึ้นไป ก็จะลำบากแล้ว ต้องมานั่ง dig ทีละ Nameserver ก็ยุ่งยากเสียเวลา หรือใช้ whatsmydns.net ก็มีไม่ครบสำหรับ ISP ในไทย

ก็เลยเขียน console app ง่าย ๆ เร็ว ๆ ไว้ใช้เอง (เขียนแบบลวกมาก แบบให้มันใช้ได้ก่อน)

แต่ก็เจอปัญหาอยู่บ้างว่ามี DNS resolver พวก ISP หลายที่เค้าไม่เปิด public ให้คนนอก ISP ใช้ ก็ลำบากนิดหน่อยแต่รวม ๆ ก็ทุ่นเวลาไปได้พอสมควรถ้าตรวจสอบกับ DNS resolver หลัก ๆ ได้ (ISP บางเจ้าข้อมูลอาจจะไม่อัพเดท เดี่ยวค่อยปรับรายการอีกที)

โปรแกรมชุดนี้พัฒนาด้วย C# บน .NET Core 3.1 ทำงานได้ทั้งบน Windows และ Linux ซึ่งตอนนี้บน GitHub ได้ build รองรับทั้ง 2 platform

สำหรับ binary ที่ได้จาก build ทดสอบบน Windows 10 (1909) และ Ubuntu 18.04 ซึ่งทำงานได้ตามวัตถุประสงค์

ตัว source code เปิด source อยู่ที่ GitHub นี้ DNS Propagation Check และ binary โหลดได้จากในส่วน Release ของ GitHub

เบื้องหลัง music48voter.com

เว็บ music48voter.com เป็นเว็บลูกของ music48project.com สร้างเพิ่มเติมขึ้นมาเพื่อเป็นช่วยในการรวบรวมคะแนนเพื่อวัดผลในการดำเนินกิจกรรมของกลุ่มแฟนคลับ Music BNK48 ต่อไป

ตัวระบบก็ปั่น “backend กึ่ง front-end” ช่วงปีใหม่ 3-4 วัน แม้ว่าจะทำเก็บมาเรื่อย ๆ แต่ว่ามันแค่โครง ๆ เป็นไอเดียในระดับ user management แล้วลองของเรื่อง .NET Core อีกหนึ่งตัว (มีอีกหลายตัวที่กำลังคิดว่าจะย้ายมาใช้ เพราะมันมีอนาคตกว่า) โดยจากการทำโครงการเล็ก ๆ ตัวนี้ เจ้า .NET Core ตั้งแต่ 2.x มาเป็นต้นมา มันเขียนสะดวก และง่ายขึ้นมาก ความสามารถต่าง ๆ ตาม .NET Framework เกือบทันแล้ว (บางจุดก็ใช้แรงหน่อย แต่รวม ๆ ก็พอไหว) เลยใช้แทน PHP ที่หลัง ๆ ยุ่งกับมันน้อยลงเยอะ

ตัวเว็บนี้ใช้ .NET Core version 2.1 ใช้ร่วมกับฐานข้อมูล MySQL version 5.7 ซึ่งตัวเดิม ๆ ที่ new project มามันไม่รองรับหรอก แต่เราใช้ Class provider อย่าง Pomelo MySql ที่เป็น Class provider ที่ on top บน Entity Framework Core มาทำงานแทน ทำให้ไม่ต้องเขียนคำสั่ง SQL จริง ๆ แต่ทำผ่าน LINQ และ ORM แทนซึ่งจบในตัว

สำหรับ background woker ใช้ Hangfire ตัว Free ก็เพียงพอ สำหรับใช้พวกส่งอีเมล เพื่อจัดคิวในการส่ง และแก้ปัญหาเรื่อง blocking UI คือกดแล้วรู้เลยว่าสมัครแล้ว ส่วนส่งอีเมลยืนยันการสมัครที่เราไปต่อ 3rd party SMTP ภายนอกที่มักทำงานช้า ในระดับหลักเกือบวินาที มันทำให้ฝั่งเว็บค้างไปแป็บนึงมาช่วยให้มันไม่ต้องรอจุดนั้น แถมยังลดปัญหา waiting ที่ thread ช่วงส่งเมล ส่วนในหน้า Ranking ตัว report เนี่ย มันใช้พลังในการ summary เยอะ ก็ใช้ schedule woker ที่อยู่ในตัว Hangfire อยู่แล้วทำ ให้มันทำงานทุก ๆ 5 – 10 นาทีเพื่อสร้างข้อมูลใหม่ใน report table แทน แล้วเวลาแสดงผลก็ให้มาดึงที่ตัวนี้แทน การแสดงผลตารางดังกล่าวจะได้ไม่หนักฐานข้อมูล

ในส่วนของ Front-end Lib ก็ใช้ Bootstrap 4 เอาง่าย ๆ โดยจะมึนหัวนิดนึงตอน upgrade มาใช้ เพราะตัว default ของ .NET Core 2.1 คือ Bootstrap 3 ก็เลยต้องใช้ bower มาช่วยในการจัดการตรงนี้ แก้ default style ที่มันค้างใน Framework อยู่เยอะพอสมควร แต่แลกกับการทำงานดีง่ายกว่ามาก สำหรับทีมออกแบบหน้าเว็บ ที่เป็นอีกทีมหนึ่ง ที่เค้าใช้ Bootstrap 4 เข้ามาช่วยกันแก้ไข และตบแต่งเพิ่มเติมให้ออกมาสวยงามขึ้นอีก ทั้ง layout และ stylesheet ถ้าใครติดตามตัวเว็บช่วงนั้นจะเห็นว่าเราปรับปรุงตลอดเวลา ยิ่งช่วงวันท้าย ๆ เรามีการปรับโทนสีของเว็บใหม่ทั้งหมด เพื่อให้เข้ากับแนวทางการทำกิจกรรมช่วงสุดท้าย

ตัว Binary ตอน deploy ขึ้นทำงานบน CentOS 7 ทั้งฝั่ง App และ Database โดยตัว App วิ่งผ่าน HAProxy ที่ทำหน้าที่ reverse proxy อีกที (เป็น best practice ที่ควรทำ เพื่อสำหรับ HA และทำ hot deploy ได้)

สำหรับขั้นตอนการตรวจสอบโค้ดโหวตในฝั่งแอปก็ไปแกะเอามาจาก javascript ของฝั่งเว็บโหวตเพื่อเอามาตรวจสอบอีกรอบก่อนเอาลงฐานข้อมูลเพื่อลดงานหลักบ้าน ส่วนงานตรวจสอบอีกชั้นว่าโหวต หรือไม่ก ็ทำระบบหลังบ้านให้ทีมงานมาตรวจสอบจาก screen recorder อีกที ซึ่งยุ่งยากหน่อย แต่มันเป็นทางเดียว เพราะจะให้แฟนคลับแต่ละคนมากรอก username และ password เพื่อให้เราไปดึง token ผ่าน OAuth2 แล้วเอาไปดึงข้อมูลจาก API ออกจากเว็บโหวตโดยตรงคงมีไม่กี่คนจะมาใช้

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

มีเรื่องฮา ๆ และตื่นเต้นคือ ตอนเปิดให้สมัครวันแรก คนเข้ามาเว็บค่อนข้างเยอะมาก หลักพันกว่าคน แล้วตอนนั้นหน้าลงทะเบียนดันมี bug เกิดขึ้น เลยต้อง hot deploy ใหม่ในช่วงนั้นไป ทำเอาคนสมัครตอนนั้นบ่นกัน timeline ไหม้เลย (ToT)/~~~

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

อันนี้บันทึกเท่าที่คิดออก ณ ตอนนี้ ไม่รู้ตกหล่นอะไรไหมนะ ԅ(¯﹃¯ԅ)

HTTP error ที่มักเจอบ่อย ๆ หากใช้งาน application gateway (พวก load balancer หรือ reverse proxy)

เวลาใช้ application gateway (พวก load balancer หรือ reverse proxy) ตัว error ที่พบได้บ่อย ๆ จะมี 3 ตัวหลัก ๆ (โน๊ตไว้สำหรับอธิบายในอนาคต)

1. HTTP 502 Bad Gateway
คือ request ที่เข้ามาไม่สามารถส่งต่อไปยัง back-end ได้
โดยมักจะเกิดจาก
– service ที่ handle port listening นั้นดับไป
– IP ผิด
– DNS ที่ resolve IP มาไม่ได้ IP ที่ถูกต้อง
– โดน firewall block

2. HTTP 503 Service Unavailable
คือ request ที่เข้ามาส่งต่อไปยัง back-end แล้วได้รับการตอบกลับมาเป็น Error Code ที่ถูกตั้งค่าว่าไม่ปรกติ (มักจะเป็นพวกที่ไม่ใช่ HTTP 200 OK หรือพวก HTTP 301/302 Redirect) โดยทั่วไปเกิดจากแอปส่งผลตอบกลับเป็น HTTP 500 Internal Server Error (หาก config เพิ่มเติม เราสามารถใช้การส่ง error ตัวนี้ในการปกปิด Error Code หรือ Exception Message ที่มีความเสี่ยงออกไปยัง user ได้)

3. HTTP 504 Gateway Timeout
คือ request ที่เข้ามาแล้วส่งต่อไปยัง back-end แล้ว application gateway รอการตอบกลับมานานเกินกว่าค่า timeout ที่ตั้งไว้ (ปรกติจะตั้งไว้ 30-60 วินาที) ซึ่งมักเกิดจากตัวแอปด้านหลังประมวลผลนานเกิน โดยปัญหาเกิดจากเข้าใช้งานเยอะจนตัวแอปตอบสนองต่อการใช้งานไม่ทัน (แอปอาจจะ query ข้อมูลอย่างหนัก และฐานข้อมูลก็ทำงานตอบสนองต่อตัวแอปไม่ทันอีกต่อหนึ่ง)

ปล. back-end อาจจะเป็น Web Server หรือ Application Server ก็ได้

Ref: List of HTTP status codes

 


GOV.UK voter registration – 504 Gateway Time-out error