A day with Elixir

จากวันเสาร์ - อาทิตย์นี้พี่ @zkan ชวนมาทำ Hackathon กันที่ Pronto Tools เลยเป็นโอกาสเหมาะว่าจะทำอะไรที่มัน Out of comfort zone ซักหน่อยแล้วส่วนตัวผมอยากจะเขียน Elixir มานานหลายปีมากเลยเป็นที่มาของ Blog นี้ครับ เอาจริงๆ จนจบวันนี้ผมยังไม่รู้เลยว่าที่ผมเขียนไปมันถูก / ผิด idiom ของ Elixir ไปมากแค่ไหน แต่แค่อยากจะมาพูดถึงสิ่งที่ประทับใจในตัวภาษาจากมุมมองของคนที่เขียนแต่ Python เป็นหลักในชีวิต Project Structure mix.exs อยากแรกเลยที่เจอพอคิดว่าจะใช้ Elixir Implement คือ จะวางโครงสร้างมันยังไง จะเขียนเป็น script.ex เลย หรือต้องทำยังไง หลังจากลองผิดลองถูกอยู่ซักแปป ถึงรู้ว่าภาษามีสิ่งที่เรียกว่า Mix ซึ่งเป็น Build tools หลักของภาษาสามารถสร้างได้โดยใช้คำสั่ง $ mix new <name> ซึ่งพอ Generate ออกมาแล้วมันจะสร้าง structure project ให้เลยตามชื่อที่เราตั้ง ซึ่งมี mix.exs เป็น Project description file อารมณ์น่าจะคล้ายๆ package.json ของ Node สร้าง module เราให้ด้วยจะอยู่ใน lib/<name>.ex สร้างไฟล์เทสของ module เราให้ด้วยที่ test/<name>_test.exs รวมถึงสร้าง README.md ให้เราด้วยอัตโนมัติเลย ...

July 22, 2018 · 3 min

มารู้จัก Data classes กันครับ

เกือบจะไม่ได้มาเขียนต่อกันละสำหรับ Part 2 ของ dataclass ตอนที่หนึ่งอยู่ที่ โพสนี้ นะครับ แต่เพื่อไม่ให้เป็นการเสียเวลาไปมากกว่านี้ เราไปต่อกันที่ Part 2 เลยครับ ตอนที่แล้วเราได้รู้จัก dataclass ได้รู้ถึงเหตุผลว่าทำไมถึงเกิดมันขึ้นมา ตอนนี้เรามาจะมาโฟกัสกันว่า เราจะใช้ dataclass กับโค้ดเรายังไงครับ ตัวอย่างการใช้งาน dataclass อย่างแรกที่เราเห็นเลยคือ เราไม่ต้องเขียน __init__ method กันอีกแล้วครับ ตัว dataclass จะ generate โค้ดส่วนนั้นให้ และอีกอย่างที่เราสังเกตุเห็นเลยคือ dataclass ใช้ประโยชน์จาก Type hint เต็มๆ อย่างที่เราเห็นการประกาศ Attribute ข้างต้นจะมีการประกาศ Type ประกบด้วยทุกตัว ทำให้เราสามารถเข้าใจ Attribute แต่ละตัวได้ทันทีว่าใช้ Type อะไรโดยไม่ต้องเดา อย่างที่สองครับ Representation ตัว dataclass เนี่ยนอกจากจะ generate __init__ ให้เราแล้วอีกตัวที่ทำให้คือ __repr__ ครับ ซึ่งตัว dataclass เนี่ยจะใช้ข้อมูลจาก attribute ที่เรา define ไว้มาสร้างให้ซึ่งช่วยเพิ่มความสะดวกให้เราและทำให้เราเลิกคิดไปได้หนึ่งเรื่อง หน้าตาก็จะประมาณนี้ครับ ...

July 16, 2018 · 2 min

#100DaysOfPyCon2018 Day6: Big-O: How Code Slows as Data Grows

Talk ผมดูวนอยู่สองสามรอบ เพราะต้องการเก็บทุกเม็ดทุกหน่วยจริงๆ คือ ผมไม่เคยเจอ Talk ที่ดูแล้วตื่นตาตื่นใจขนาดนี้มานานมาก ตอนนี้ยกให้เป็น Talk อันดับหนึ่งในใจของ PyCon ปีนี้เลย ผมคิดว่า Talk นี้จะไม่สรุป Key Takeaway เพราะอยากให้คนที่มารู้จัก Talk นี้จากผมได้รับสารเต็มๆ จาก Ned Batchelder โดยการดู Talk นี้ครับ แต่ถ้าไม่มีเวลาดูจริงๆ แนะนำให้ไปอ่าน เวอร์ชั่น Text ที่เจ้าตัวเองถอดเขียนไว้ เป็นบทความที่ผม Recommend เลยครับ ทำให้ผมกลับมาคิดเรื่อง Algorithmic Analysis หลังจากหลงลืมมันไปนานมาก ลิ้งข้างล่างนี้ครับ Big-O: How Code Slows as Data Grows Big-O notation can be intimidating, but it doesn’t have to be. A common-sense approach will give you a good working technique for analyzing the time complexity of your code. — Ned Batchelder, about ...

May 23, 2018 · 1 min

#100DaysOfPyCon2018 Day5: Oops! I Committed My Password To GitHub!

Key takeaway คนที่เคย commit password ลง Git มีอยู่ 2 ประเภท ประเภทแรกคือเผลอพลาดจริงๆ อีกประเภทคือบอกว่า commit สิแต่ไม่เป็นไรเพราะ… ซึ่งเพราะนี่มีหลายคนที่บอกว่า เพราะมันเป็น private repo แต่เราไม่ควรมองอย่างงั้นเพราะว่า Private Repo มันไม่ได้ encrypt เพราะฉะนั้นคนที่อยู่ GitHub ก็ยังดูข้อมูลเราได้อยู่ รวมถึงถ้าวันนึงคนในทีมออกจากบริษัทไป คนๆ นั้นก็ยังมี password นั้นอยู่ อีกเหตุผลคือ ไม่เป็นไรเพราะ password เราใช้ใน internal service แนวคิดนี้มาจากการจำกัดบริเวณความเสียหาย ซึ่งก็ยังไม่ตอบโจทย์อยู่ดี วิธีการ (ไม่) แก้ password ที่เผลอ commit ไปคือ สร้าง commit ใหม่ที่จะลบ password ถ้าเราใช้ git เป็นประจำเราจะรู้ว่าเราสามารถดู history ได้ซึ่งวิธีนี้ก็ไม่ได้แก้ปัญหาอะไร อีกวิธีที่บางคนคิดว่าแก้ปัญหาคือ rebase commit แต่มันไม่ได้แก้ปัญหาถึงแม้ว่า history จะเปลี่ยนไป แต่ git เก็บทุกอย่างแล้ว commit นี้ยังอยู่ใน ref log แต่เป็น orphant อยู่จนกว่าจะโดน garbage collect ไป รวมถึงถ้าในเคสที่คนที่ลาออกไปก่อนที่เราจะ rebase สุดท้ายเค้ายังมี password อยู่ดี เพราะมันไม่ได้แก้ทุกเครื่อง วิธีแก้ที่ดีสุดคือ Revoke password ซะ นี่เป็นสิ่งแรกที่เราควรทำเมื่อรู้ตัวว่า password เราเผลอ commit ไปแล้ว สิ่งต่อมาที่ควรทำคือ เราควรจะเก็บ password / secret ไว้ใน environment variable ซึ่งวิธีการ access มันใน Python เราสามารถใช้ module os.environ ในการเรียกได้ โดย module นี้จะเก็บ environment variable ทั้งหมดที่ OS ป้อนให้ process เราในรูปแบบ Dictionary วิธีการเก็บ password ใน environment variable เราสามารถเก็บผ่าน .profile หรือ .bashrc สำหรับทุกโปรเจ็ค แต่ถ้าเป็นโปรเจ็คเดี่ยวๆ จะแนะนำ .env มากกว่า และสำคัญที่สุดคือ อย่าพิมพ์ password ใน shell เพราะ shell เก็บ history ทุกอย่างที่พิมพ์ และไฟล์ .env ก็อย่า commit ลง git แต่ให้เขียน .gitignore กันไว้จะดีที่สุด Python มี Package ชื่อ python-dotenv เอาไว้ใช้สำหรับ load environment variable โดยเฉพาะ ซึ่งแค่แปะฟังก์ชั่น load_dotenv() ก่อนจะใช้ค่าใน env ก็ใช้ได้แล้วสะดวกมาก ไม่ต้องมานั่ง export env เอง ก่อนรัน app ถ้า environment variable ยังไม่ปลอดภัยพอ เรายังมีตัวเลือกอีกมากเช่น Vault (Hashicorp) / Parameter Store (AWS) / Secret Object (K8S) / Vault (Ansible) ซึ่งพวกนี้นอกจากจะเก็บ secret ให้เราแล้วยัง encrypt ให้ด้วย DO and DON’T อย่าเขียน password / token ไว้ใน code จงเรียก Password / token จาก environment variable หรือ secret store จง Revoke ตัว secret เราที่เผลอเปิดเผยไปแล้ว อย่าใช้ service ที่ไม่มี option ในการ revoke access token อย่าใช้ password เดียวกันหลาย service อย่าใช้ credential เดียวกันทุก Users Original Post on: https://yothinix.medium.com/100daysofpycon2018-day5-oops-i-committed-my-password-to-github-300fd7704a34

May 20, 2018 · 2 min

#100DaysOfPyCon2018 Day4: Visual Testing with PyCharm and pytest

จริงๆ ดูจบตั้งแต่เมื่อเช้าแล้ว แต่คิดหนักมากว่าจะสรุปดีมั้ย เพราะทุกอย่างที่อยู่ใน Talk นี้คือรู้อยู่แล้ว ใช้อยู่ทุกวันอยู่แล้วไง แต่หลังจากคิดไปคิดเลยขอวางตัวเองออกไป แล้วคิดว่าไม่รู้อะไรเลยแล้วลองสรุปดีกว่า Key takeaway TDD crash course: Test ➡ Design & Develop วิธีที่เค้าเปรียบเทียบค่อนข้างจะน่าสนใจทีเดียว เค้าบอกว่าสมัยเรียนเวลาอ่าน text book มันใหญ่มาก บทนึงก็ยาว แต่เกือบทุกเล่มท้ายบทจะมีแบบทดสอบว่าเราเข้าใจรึเปล่า เค้าลดเวลาในการทำความเข้าใจทั้งบทด้วยการ อ่านคำถามท้ายบทก่อน แล้วค่อยไปหาอ่านเนื้อหา วิธีนี้ทำให้เข้าใจเนื้อหาได้เร็วทันทีแล้วไม่ต้องเสียเวลาอ่านน้ำ ถ้าเปรียบกับการเขียนโปรแกรมก็คงไม่ต่างอะไรกับเราไม่ต้องหลงทุ่งเขียนไปเรื่อย แต่ตั้งคำถามกับตัวเองว่าเรากำลังแก้ปัญหาอะไร แล้วพยายามแก้ปัญหานั้น Pytest สามารถรันเทสเป็นซับเซตได้ทั้งระดับ Directory, module หรือแม้กระทั้ง test case หรือใช้ marker, expression กำหนดว่าจะรันเทสไหน รวมถึงเพิ่ม option ให้รันแล้ว exit เลยเมื่อเทส failed หรือ รันเทสที่ failed ล่าสุดก่อน ฯลฯ Visual Testing vs CLI ต้องบอกว่าบางคนไม่ถูกกับ CLI จริงๆ เค้าเลยพยายามหาทางให้ทีมรันเทสให้ได้ง่ายขึ้นเลยมาจบที่ใช้ PyCharm ให้เรียก Pytest อีกที ซึ่งนอกจากจะใช้ครอบ Pytest ให้รันง่ายขึ้นแล้ว (ผ่าน gutter) ยังสามารถ debug test/code ไปพร้อมๆ กับรันเทสผ่าน breakpoint และ debugger ที่ติดมากับ PyCharm ได้ด้วย เราสามารถเทสฟังก์ชั่นเดิมแต่ใช้ input set ต่างกันได้ผ่าน pytest.mark.parameterize วิธีนี้ทำให้โค้ดเทสสะอาดขึ้นมาก เพราะเรา define แค่ parameter ตัวเทสก็เขียนเหมือนเดิมอยู่แล้ว ถ้าอยากศึกษาเพิ่มเติมเกี่ยวกับ PyTest ผมแนะนำหนังสือ Python Testing with pytest ครับ คนเขียนก็คนเดียวกับที่พูด Talk นี่แหละครับ นอกจากหนังสือนี้ทำให้รู้จักใช้ความสามารถต่างๆ ของ PyTest มากขึ้นแล้ว หนังสือเล่มนี้ทำให้ผมหลงรัก namedTuple ซึ่งเป็น data structure ที่คนมองข้ามมากตัวนึงเลยครับ Python Testing with pytest Python Testing with pytest, 2nd Edition 2nd edition is now in Beta, and purchasable as an eBook. All 16 chapters, plus 2 appendices, are in the Beta, available as an eBook. Copy editing and indexing are complete. The physical book is the next step. Final version expected Feb 2022 (or March, maybe)… — Python Testing ...

May 18, 2018 · 1 min

#100DaysOfPyCon2018 Day3: Dataclasses: The code generator to end all code generators

Key takeaways Sphinx ก็เอามาใช้ทำ Presentation ได้ แถมได้ document ที่อ่านง่ายกลับไปดูทีหลังได้ด้วย Code generator: tools that write code for you based on specification dataclasses มี learning curve ต่ำมาก ถ้ามองสามารถมองได้สองมุมคือ data holder เหมือน namedTuple หรือเป็น boilerplate เอาไว้เขียน class ประวัติศาสตร์แบบย่อๆ เริ่มต้นเรามี dict, tuple, hand-written class หลังจากนั้น namedTuple 🎉✨ ก็เกิดขึ้นแล้วตามมาด้วย types.SimpleNamespace ทำให้เราสร้าง data structure ได้ง่ายขึ้น (access ได้ง่ายขึ้นด้วย) ในอีกมุมนึง ORMs ก็กำเนิดขึ้นด้วยจาก Django, SQLAlchemy, PeeWee ซึ่งใช้ class เป็นเทคนิคในการสร้าง data structure หลังจากนั้นมี traitlets เกิดขึ้นเป็น package ไว้ใช้ทำ data validation โดยใช้ class attribute เป็นตัวกำหนด พอ Python 3.6 ออกก็เกิด Type Annotation, Variable Annotation ช่วยให้เราสามารถ define type ของ attribute ของ class ได้เลย ท้ายที่สุดเรามี library ชื่อ attrs เป็นแรงบันดาลใจในการสร้าง dataclass สามารถมองง่ายๆ ได้ว่าเป็น “Mutable namedtuples with defaults” Dataclass เบสิกเลยเขียนคล้าย namedTuple มาก ต่างกันแค่ dataclass ใช้ decorator dataclass แต่ NamedTuple ต้อง inheritance ออกมาจาก NamedTuple class ความสามารถของ Dataclass สร้าง repl ให้เราโดยอัตโนมัติจาก attribute definition เลย ใช้ replace() ในการ mutable attribute ได้ เช่น replace(c, hue=120) ถ้าเป็น namedTuple ต้องใช้ c._replace(hue=120) เพื่อป้องกัน namespace collision ใช้ asdict() หรือ astuple() ให้คืนค่าออกมาเป็น dict หรือ tuple ได้เลย ข้อสังเกตุของ asdict() คือ dataclass จะคืน Dict ออกมาให้เลยในขณะที่ namedTuple จะคืน OrderedDict เพราะเป็น implementation เก่า มี method __annotations__ เอาไว้ดู type annotation ของ attributes ได้ ข้อเสียของ dataclass คือ unpack ของได้ยากกว่า namedTuple (เพราะ implementation ข้างล่างสุดเป็น Dict) ทำให้ก่อน unpack ต้องแปลงเป็น tuple ก่อน ในเรื่องของ Performance / Resource ตัว dataclass จะมีขนาดใหญ่กว่า namedTuple แต่แลกมาด้วยความเร็วในการ access object ที่เร็วกว่า Dataclass สร้าง docstring, __repr__, __eq__ ให้เราโดยอัตโนมัติจาก attribute ที่เรา define ไว้แต่ไม่สร้าง __hash__ ให้นะ ถ้าเราใส่ option frozen = True ใน dataclass decorator จะเป็นการบอกว่า dataclass นี้เป็น immutable หรือถ้ามองง่ายๆ คือให้มันทำตัวเป็น namedTuple ใส่ option order = True ได้ด้วยแต่ผมฟังแล้วไม่ค่อยเข้าใจชัดเจนว่าตกลงมัน order ของอะไรกันแน่ Customize Fields Specification นอกจากจะกำหนดพฤติกรรมของ dataclass ได้จาก decorator แล้วเรายังสามารถใช้ฟังก์ชั่น field() ในการกำหนดพฤติกรรมของแต่ละ attribute ได้ด้วย ตัวอย่างข้างบนเป็น use case คล้ายๆ ของจริงที่ต้องการสร้าง data structure ของ employee ขึ้นมา แล้วเก็บข้อมูลต่างๆ ในนี้ใช้ความสามารถของ field() หลากหลายมาก ...

May 17, 2018 · 2 min

#100DaysOfPyCon2018 Day1: Pipenv: The Future of Python Dependency Management

Key takeaway: — กว่าจะมาเป็น pip ที่เราใช้กันทุกวันนี้ก็ผ่านอะไรมาเยอะมากตั้งแต่ยุค build tarball มายุค easy_install มาถึงยุค pip + virtualenv มันยาวนานมาก เพิ่งรู้ว่า easy_install ไม่มี easy uninstall แล้วสมัยนั้นมันลบกันยังไง — ข้อเสียของยุค pip + requirements.txt คือเราลง package เดียวกันคนละ version ไม่ได้ (Ruby ทำได้) แล้ววิธีที่แนะนำคือ pip freeze > requirements.txt ก็มีปัญหาคือมาดูทีหลังจะงงว่า อันไหนคือ package ที่เราต้องการจริงๆ และ pip-tools พยายามแก้ปัญหานี้แล้วโดยใช้ requirements.in กับ requirements.txt แต่มันก็ยังหลายไฟล์อยู่ — Virtualenv ปัญหาใหญ่สุดคือเข้าใจยากมากสำหรับคนที่เพิ่งใช้ เพราะ concept นี้ใกล้เคียงกับ unix ที่แยก home environment แต่ก้มีคนทำ virtualenv-wrapper (เกิดทันเว้ย) มาแก้ปัญหาในจุดนี้ — Pipfile ทำให้เราแยก group ของ package ที่ลงได้ packages กับ dev packages ...

May 16, 2018 · 1 min

#100DaysOfPyCon2018 Day2: There and Back Again: Disable and re-enable garbage collector at Instagram

Key takeaways — Garbage collector (GC) จะทำงานอยู่บนหลักการสองอย่างคือ Reference count กับ Copy-On-Write Semantic - Instagram disable GC ช่วยลด memory ได้จาก 500mb / process เหลือ 350mb / process (ลองคิดภาพ uWSGI ลดได้ขนาดนั้นแล้วรันซัก 100 กว่า process) - ใช้ perf ในการทำ profiling memory usage - Disable โดยใช้คำสั่ง gc.disable() ไม่เกิดอะไรขึ้น แต่ใช้ gc.set_threshold(0) ปิดได้จริงแต่สิ่งที่เกิดขึ้นคือ Instagram down เพราะ OOM ต้องแก้โดย hack atexit.register(os._exit, 0) แต่ปัจจุบันไม่ต้องแก้แล้วเพราะ hack นี้รวมไปใน Python 3.6 แล้ว - หลังจากปิด GC ไป Memory utilize ลดลง 15% มี shared memory เพิ่มขึ้น 100mb และ instruction / cycle เพิ่มขึ้น 10% ...

May 16, 2018 · 2 min

แนะนำ BuJo เมื่อชีวิตอยากติด Analog

มันมีสิ่งหนึ่งที่ผมสงสัยมานานหลายปีละว่าทำไมหลายคนถึงติดสมุด Moleskine มากๆ ทั้งๆ ที่มันก็ดูเหมือนสมุดธรรมดาๆ เล่มนึง ที่อาจจะมีเส้น ไม่มีเส้น เป็นตาราง ฯลฯ หลังจากถามไถ่หลายคนก็ยังไม่เคลียร์เพื่อคลายความสงสัยนั้น ผมเลยซื้อมาหนึ่งเล่มครับแล้วหลังจาก 3 เดือนที่ผ่านมา ผมค้นพบว่ามันก็สมุดธรรมดาๆ นี่แหละ แต่สิ่งที่ไม่ธรรมดามันเกิดขึ้นหลังจากนั้นครับ ตั้งแต่สมัยเรียนแล้ว ผมไม่ใช่คนประเภทใช้สมุดครับ ตั้งแต่ปี 2 แล้วผมได้ Thinkpad Edge 11 มาผมก็อยู่บน Evernote มาตลอด อาจจะเปลี่ยนไปใช้ OneNote ตอนอยู่ปีสี่บ้าง จนมาถึงทำงานที่ใช้ Bear หรือไม่ก็สร้างไฟล์จดลง git repo ตัวเองผมไม่เคยคิดจะกลับไปใช้สมุดเลยครับ ทุกอย่างจะสามารถ Search หาได้มี hashtag / group อะไรเก็บไว้อย่างเป็นระบบ หลายตัวเขียน Markdown ได้หรือมี Format ที่ทำให้เขียนแล้วดูดีขึ้นไปอีก จริงๆ ก็ยังใช้ Bear อยู่นะ ซึ่งจดอย่างนี้มันก็ไม่มีปัญหาอะไรนะครับ ไม่ได้จะบอกว่าเห้ยจดแบบนี้มันไม่ดีนะ แต่คือผมอยากลองอะไรใหม่ๆ ไง นอกจากเรื่องจดอีกเรื่องนึงคือ Todo list ครับ หลายต่อหลายปีมากที่ผมพยายามจะอยู่กับ App todo list แต่สุดท้ายแล้วอยู่กับ App ไม่รอดถึงมันจะ Sync หลาย Platform มีฟีเจอร์เตือน นั่นนู่นนี่ก็เหอะ ไม่รอดครับ เพิ่งรู้ตัวว่า Todolist ที่รอดสำหรับผมคือ ใช้แล้วทิ้ง นั่นก็คือ เขียนลง Post-it เวิร์คสุด ...

March 17, 2018 · 3 min

Python Type Annotation: ทำไม Python ต้องเขียน Type ด้วย

ตั้งแต่ Python 3.5 เป็นต้นมา Python ได้แปลงร่างจากภาษา Duck Typing เต็มตัว ให้มีความสามารถในการใส่ Type Annotation ในโค้ดซึ่งถูกพัฒนามาตั้งแต่ปี 2014 แต่ผมค้นพบว่าหลายๆ บริษัทการเขียน Type Annotation ในภาษา Python ยังไม่แพร่หลายอย่างที่มันควร ในบล็อคนี่เลยจะพาไปรู้จักตั้งแต่เหตุผลที่ว่าทำไมเราถึงควรใส่ Type Annotation จะใช้ Type Annotation ยังไง รวมถึงกลยุทธในการเพิ่ม Type Annotation เข้าไปใน Codebase และ workflow ของเราครับ ทำไมถึงต้องมี Type Annotation เป็นคำถามแรกเลยและคำถามสำคัญด้วย ทำไมเราถึงควรจะใส่ Type Annotation ให้กับภาษาที่เป็น Duck typing อย่าง Python ทำไมเราถึงอยากจะลดอิสระภาพในการประกาศอะไรก็ได้ ลองดูโค้ดตัวอย่างข้างล่างนี้ครับ ดูแว็บแรกก็เหมือนจะเข้าใจง่ายใช่มั้ยครับ เป็นฟังก์ชั่นไว้ยิง request รับ url, data, headers พอผ่านไปซักหกเดือนมันเกิดคำถาม data มันรับข้อมูลแบบไหน ? มันอาจจะเป็น text ก็ได้ อาจจะเป็น dict ก็ได้ เราไม่มีทางรู้ได้เลยแต่แรกจากโค้ดว่าควรจะส่ง data หน้าตาเป็นยังไง ทีนี้เราลองมาดูฟังก์ชั่นเดียวกันที่ใส่ Type Annotation แล้วนะครับ (อย่าเพิ่งสนใจ Syntax มากนะครับ พยายามดูแบบไม่ต้องคิดอะไรมากก่อน) ...

January 3, 2018 · 5 min