TypeScript มาเพิ่มคุณภาพของ Code ด้วย TsLint

Screen Shot 2560-02-04 at 10.23.56 AM.png

Linter นั้นคือเครื่องมือที่ช่วยให้ตรวจสอบลักษณะการเขียน Code ว่าเหมาะสมกับ Best Practices ที่ทาง Community ต่างๆแนะนำหรือไม่ ซึ่งจุดประสงค์หลักเพื่อช่วยให้ Source Code ของทั้งโปรเจคนั้นมีความ

  • อ่านง่าย และไปในทิศทางเดียวกัน
  • ดูแล แก้ไขง่าย
  • แก้ปัญหา Error แบบพื้นฐาน

โดยสำหรับ TypeScript นั้นgเครื่องมือนี้มีชื่อว่า TsLint

 การติดตั้งก็ใช้ npm เจ้าเก่า

$ npm install tslint typescript

จากนั้นก็ทำการสร้าง tslint.json ซึ่งจะเป็นไฟล์หลักที่ใช้ในการ Config ค่าต่างๆของ TsLint

$tslint –init

ลองเปิดดูไฟล์ tslint.json เราก็จะเห็นว่าทางค่าปกติที่ติดตั้งมานั้นมีกฏอะไรบ้าง ซึ่งใน version 4.4.2 ที่ผมใช้นั้นมันซัพพอร์ท JavaScript ด้วย

Screen Shot 2560-02-04 at 9.33.30 AM.png

กับอีกส่วนนึงคือ Node สำหรับ TypeScript ที่ใช้ชื่อ attribute ว่า rules เฉยๆ

Screen Shot 2560-02-04 at 9.36.27 AM.png

ทดสอบกับ Code ตัวอย่าง

ที่นี้มาลองเล่นกันกับ Code ตัวอย่างแบบง่ายๆกับ main.ts

// main.ts
class HERO{
 private name = 'HERO'
 public attack()
 {
 console.log(`${this.name} : do attack`);
 }
}

var player = new HERO();
player.attack();

หลังจาก compiled .ts ออกมาเป็น .js ก็จะออกมาเป็น

// main.js
var HERO = (function () {
 function HERO() {
 this.name = 'HERO';
 }
 HERO.prototype.attack = function () {
 console.log(this.name + " : do attack");
 };
 return HERO;
}());
var player = new HERO();
player.attack();

ลองรันดูก็ได้ผลออกมาตามนี้ครับ ซึ่งก็ถูกต้องดีหมายความว่า Code เรารันได้ดี 🙂

Screen Shot 2560-02-04 at 9.50.44 AM.png

ทีนี้ลองมารัน TsLint เพื่อดูว่า Code ของเรา 10 บรรทัดเนี่ยมันเขียนมาโอเคมั้ยกัน

$ tslint -c tslint.json *.ts -t stylish

ผลออกมากโดนไป 5 เรื่องครับ tslint จะรายงานมาว่าเราเขียนไม่ดียังไง ที่บรรทัดไหน ตัวอักษรที่เท่าไหร่

screen-shot-2560-02-04-at-9-54-26-am

เรื่องที่เราโดนรายงานครั้งนี้คือ

  1. ใช้ var แทนที่จะเป็น let หรือ const เพราะในโลกของ TypeScript เราแนะนำกันแบบนี้
  2. ลืมเว้นวรรค!!
  3. ใส่วงเล็บปีกกาเปิดผิดที่!@!#
  4. ตัวแปร String เราดันใช้ single quote ” แทนที่จะเป็น dobule quotes “” (ตามที่กำหนดไว้ใน tslint.json)
  5. ลืมเครื่องหมาย semi colon

จะเห็นว่าสิ่งที่มันรายงานผลมานั้นก็ดูดีมีประโยชน์ครับ(มั้ย?)

ที่นี้เรามาดู Code หลังจากแก้ไขไปแล้วดีกว่าเนอะ

Screen Shot 2560-02-04 at 10.15.16 AM.png

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

การทำให้ Software นั้น Maintain ได้ง่ายและมีคุณภาพ เป็นเกียรติ (Duty) ของ Developer นะครับ 🙂

node-ffi เรียก functions ใน dll ด้วย JavaScript กันตรงๆ

จากความเดิมตอนที่แล้วผมเคยเขียนเรื่องการสร้าง Node.js Module ด้วย C++ มาทีนึงแล้ว แต่ถึงอย่างนั้นถ้าเรา
– มี C++ Library อยู่แล้วล่ะ
– หรืออยากทำให้ Node สามารถเรียกใช้งานพวก System API โดยที่ไม่อยากศึกษาการเขียน Node Module แบบ Native
ผมก็ไปเจอว่ามี Community ที่ได้พัฒนา Framework มาตัวนึงซึ่งวันนี้เราจะมาพูดถึงกัน นั่นก็คือ Node-ffi ซึ่งย่อมาจาก Foreign Function Interface

Node-ffi นั้นเป็น Module ที่ทำหน้าที่เป็นตัวกลางในการทำการติดต่อระหว่าง JavaScript Code ไปที่ C++ Library โดยที่เราไม่ต้องเขียน Native Module เอง ประมาณรูป Diagram ด้านล่างครับ

ffi.png

เรามาลองดูการใช้งานกันดีกว่าครับ

ก่อนอื่นเรามี C++ Library ที่เป็น DLL ที่ต้องการจะเรียก ซึ่งผมลองเขียนมาแบบง่ายๆคือ dll ที่มี function ในการ ดึงค่า Version ของ OS

extern "C" DLLIMPORT int getVersion()
{
 DWORD dwVer = ::GetVersion();
 DWORD majorVer = (DWORD)(LOBYTE(LOWORD(dwVer)));
 return majorVer;
};

ซึ่ง API ::GetVersion นั้นเป็นของ Windows SDK ครับ ซึ่งสำหรับฝั่ง C++ ผมได้ทำการ  Compile ออกมาเป็น dll ชื่อ dev.dll

ทีนี้มาลองดูส่วนที่สำคัญของเราก็คือฝั่ง JavaScript

var ffi = require('ffi');

var devModule = ffi.Library('dev', {
 'getVersion': [ 'int', [] ]
});
console.log('Windows version : ' + devModule.getVersion());

จาก Code นี้ก็มี 3 ส่วนหลักๆครับ

  1. require module ‘ffi’
  2. ประกาศการทำ function binding
    ffi.Library('dev', {
      'getVersion': [ 'int', [] ]

    2.1 ทำการ binding กับไฟล์ library ชื่อ dev.dll
    2.2 ทำการ binding กับ function ชื่อ getVersion โดยมี ‘int’ เป็น Type ของ Return Value
    2.3 Function getVersion นี้ไม่มี parameter เลยใส่เป็น []

  3. เรียกใช้ ffi ด้วย  devModule.getVersion()

ผลของการรันก็เป็นดังนี้ครับคือได้ค่า ’10’ มาจาก getVersion

ffi_run.png

นอกจากนี้เรายังสามารถประกาศการทำ binding ทีละหลายๆ function ก็ได้เหมือนกันครับ(ขออนุญาติไม่โชว์ Code ฝั่ง C++ ที่เขียนเพิ่มเพื่อดึงค่า Minor,Build Version) เช่น

var devModule = ffi.Library('dev', {
 'getVersion': [ 'int', [] ] ,
 'getMinorVersion' : [ 'int', [] ],
 'getBuildVersion' : [ 'int', [] ]
});
console.log('Windows version : ' + devModule.getVersion());
console.log('Minor version : ' + devModule.getMinorVersion());
console.log('Build version : ' + devModule.getBuildVersion());

ผลการรันก็ดูดีครับและตรงกับ System Info จริงๆนะ 🙂

ffi_run2.png

สรุป : node-ffi น่าจะเป็นอีกหนึ่งทางเลือกสำหรับคนที่เขียน Node.Js ด้วย Context บางอย่างที่ต้องติดต่อกับ System หรือ OS ระดับ Low Level (เหมือนผม..) โดยที่เรานั้นไม่ต้องมาการเรียนรู้การเขียน Node Module แบบ Native ที่อาจจะมีความซับซ้อนกว่าทั้งในแง่การทำ Mapping พวก Data Types รวมถึงการมานั่งศึกษา V8 API  ซึ่งผมคิดว่า node-ffi อาจจะมีผลกระทบกับ Performance ในการ call function บ้าง แต่ผมก็ยังไม่ได้ลองวัด ทั้งนี้ทั้งนั้นใครมีข้อมูลเพิ่มก็แชร์กันได้ครับ

รู้จักกับ HTTP2 Server Push

ในโลกของ Web นั้น ทุกๆครั้งที่ทางฝั่ง Client หรือ Browser ทำการขอข้อมูลด้วยนั้นจะใช้ HTTP Request ซึ่งการ Request หนึ่งครั้งนั้นมันมี Cost ของมันอยู่โดยเฉพาะการทำ Network Negociation ที่จะต้องมีในทุกๆครั้งที่ทำ HTTP Request

พื้นฐานกันหน่อย

ทีนี้มาลองดูตัวอย่างเช่น มีเวปเล็กๆ 1 เวปที่มี

  • index.html
  • style.css
  • font.woff2

ถ้าหน้า index.html นั้นมีการใช้ทั้ง style.css และ font.woff2 เวลาที่ถูกโหลดหน้า index.html หนึ่งครั้งนั้นจะเกิด HTTP Request 3 ครั้งและมีการทำ Network negociation 3 ครั้งเช่นกัน ซึ่งก็คือจะเกิด 3 Round Trip (ซึ่งกระบวนการเริ่ม Request จนได้รับ Response นั้นเรียกว่า Round Trip) ซึ่งจุดนี้แหละครับที่ HTTP2 Push นั้นจะมาช่วยเพิ่ม Performance ของการโหลดเวปได้

แล้ว Round Trip มันสำคัญยังไง

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

Screen Shot 2559-12-10 at 9.56.08 AM.png
Network Tab จาก Chrome Debugger

จากรูปจะเห็นได้ว่าการทำ HTTP request 1 ครั้งนั้นจะมี Connection Setup รวมไปถึงเวลาที่ใช้ส่ง Request จนฝั่ง Server ได้รับก่อนจะเริ่มประมวลผลและส่งข้อมูลกลับ

ซึ่งจะเห็นได้ว่าทุก Round Trip นั้นมี ค่าใช้จ่ายของ overhead ที่ต้องเสียไป ซึ่งบางคนอาจจะดูแล้วเหมือนไม่เยอะเพราะมันแค่หลัก milli-sec แต่ถ้าเวปเริ่มซับซ้อนมันรวมๆกันก็เยอะนะครับอาจจะเป็นหลายวินาทีเลย

HTTP2 Server Push?

สรุปสั้นๆก็คือเป็นเป็นความสามารถของ HTTP2 ที่จะช่วยลด Round Trip ในการส่งข้อมูลจาก Server ไปให้ Client โดยการ Push ข้อมูลไปให้ Client โดยที่ฝั่ง Client นั้นไม่ต้องทำการ Request มาหา Server (เหมือนยัดเยียดให้นั่นแหละ)

มาดูภาพประกอบเพื่อเพิ่มความเข้าใจกัน

1_pushintro
รูปจาก  http://calendar.perfplanet.com/2016/http2-push-the-details/

จากรูปด้านบนนั้นเราแบ่ง design ออกเป็น 3 แบบ

  1. no push ซึ่งก็เป็นการ Request/Response ตามปกติซึ่งจะทำให้เกิด 3 Round Trip ตามหลักปกติของ HTTP
  2. push critical เป็น design ที่เริ่มการ Utilize ความสามารถของ push ในการที่เราเน้นแต่ resouce ที่จำเป็นเช่น โหลด html ก็แถม css ไปให้ด้วยเลย
  3. push everything เป็นอีกรูปแบบที่ทางฝั่ง Client นั้นแค่ request มาทีเดียวทาง server ก็ส่งสิ่งที่ขอมาพร้อมกับแถมทุกอย่างไปให้ client ซึ่งเป็นการประหยัด Round Trip กันแบบสุดๆ

มาถึงตรงนี้ดูแล้ว Push นี่ดูดีใช่มั้ยครับ

แต่ช้าก่อนสิ่งเหล่านี้จำเป็นต้องคิดเพิ่มว่าจะ PUSH ดีรึเปล่า

  • Cached ข้อมูลบางอย่างอาจจะมีการ Cached เอาไว้แล้วที่ Client ซึ่งถ้า Server ทำการ Push ไปให้ด้วยตลอดเวลาก็เหมือนกับว่าเป็นส่งของฟรีเสียทั้งเวลา, CPU, bandwidth เล่นๆ
  • Bandwidth เนื่องจากขนาดของ Bandwidth นั้นจำกัดซึ่งการ Push ข้อมูลไปที่ Client ทีละเยอะๆนั้นอาจจะทำให้เครื่องของ Client ช้าลงได้ซึ่งก็มีผลกระทบต่อการใช้งานของ User
  • Priority ทางฝั่ง Server ต้องคำนึงถึงการเรียง Priority ของสิ่งที่จะ Push ดีๆเช่นจะส่งรูป หรือ Script หรือไฟล์ text อะไรยังไงให้ User Experience ดีที่สุด เพราะการ Push ส่งข้อมูลซี้ซั้วอาจจะทำให้เวปแสดงผลได้ช้าลงไปอีก

 

เอาล่ะ พร้อมมาเริ่มรีดประสิทธิภาพให้เวปกัน!

อ้างอิง

http://calendar.perfplanet.com/2016/http2-push-the-details/

ทำไม Developer ควรทำ Side Project

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

Side Project คืออะไร?

ถ้าตอบสั้นก็คือ มันก็คือโปรเจคนอกเวลางาน ใช่ครับ Developer ที่ดีควรจะต้องจัดสรรเวลามาพัฒนาความรู้ตัวเองโดยการคิด Project ที่ตัวเองอยากทำ ซึ่งอาจจะเอา Skill ที่เราอยากจะเรียนรู้เป็นตัวตั้ง ซึ่งสิ่งเหล่านี้อาจจะหาไม่ได้จากงานประจำของเราๆซึ่งอาจจะรวมถึง Freelance หรือ Part Time นะ

ตัวอย่างในวงการอื่นที่ผมเห็นชัดคือ วงการเพลง J-Rock ของญี่ปุ่นครับ (อย่างผมชอบฟัง 90’s เช่น X-Japan, Luna Sea, L’arc en Ciel) จะเห็นได้ว่านักดนตรีของวงพวกนี้เวลาที่พวกเค้าว่างจากวงหลักของเค้า เค้าก็จะมีงาน Side Project ที่เรียกว่า Solo Album กัน ซึ่งผมว่ามันเป็นการเติมไฟ หรือหา Idea หรืออะไรใหม่ๆให้ชีวิตและ Refresh ตัวเองจากการทำงานประจำนะ 🙂

ข้อดีของ Side Project

  • ได้ลองอะไรใหม่ๆ ตามกระแสบ้าง หรือตามความชอบส่วนตัวบ้างโดยไม่มีข้อจำกัดด้าน Business ทุกอย่างนั้น Drive มาจากตัวเราเอง
  • ได้หัดคิด Project แบบ End to End รวมถึงหัดวิเคราะห์ทั้ง workflow ทั้งตัว Project และได้ลองตั้งเป้าหมายและพยายามที่จะได้ทำให้ได้ผลลัพธ์
  • ถ้า Skill ที่อยากฝึกนั้นอยู่ในเทรนด์หลัก ก็ไปลองเข้าหา community สร้าง connection ได้อีกด้วย
  • เพื่อ Idea เวิร์คก็ไปทำ Start Up เลย :p
  • ซักวันเราอาจจะได้มาใช้สิ่งที่ได้จาก Side Project หรือบาง Idea ไปใช้ในชีวิตการทำงานจริงก็ได้ (ใครจะรู้)
  • สร้างคุณค่าให้ตัวเอง 🙂 เพราะสิ่งสำคัญที่สุดมันคือการเพิ่มศักยภาพของตัวเราเอง!!!

เพียงแค่ลองเริ่มทำ  Side Project ดูแบบสั้นๆเช่นจบให้ได้ใน 1-3 เดือน ทำอาทิตย์ละ 0.5-1 วัน ผมเชื่อว่ามันจะทำให้คุณสร้างความแตกต่างจาก Developer ทั่วไปได้ครับ และท้ายที่ถ้าคุณทำเป็นนิสัยได้ ผมรับรองได้ว่าคุณก็จะสามารถยกระดับตัวเป็นให้เป็น Developer ที่ Above Average ได้ 🙂

main-qimg-40c5c6bafdcd821c937d9f3f6e9d54f5-c

ว่าแล้วตอนนี้คุณๆเราๆท่านๆมี Side Project ในมือแล้วหรือยัง ????

ทำให้ App บน Windows เป็นสีขาว-ดำ

เนื่องจากว่าผมได้พยายามลองทำให้ Application บน Windows นั้นเปลี่ยนเป็นสีโทนขาว-ดำ เลยอยากจะแชร์สิ่งที่ได้ลองทำนะครับ (ถึงแม้ว่าผลของการ Implement นั้นยังไม่ถูกใจเท่าที่ควร)

ก่อนอื่นเลยผมขอเรียก app นี้ว่า Mourning App และเนื่องจากว่าต้องการทำสำหรับ Windows App ดังนั้นภาษาที่ผมใช้คือ C++ และ Win32 API ซึ่งตัว API ที่ใช้หลักๆคือ Magnification API ซึ่งเป็น Windows API ที่ปกติเอาไว้ทำพวก Tool ที่เป็นแว่นขยายต่างๆ

หลักการของ Mourning App ที่ผมทำมี 4 ขั้นตอน คือ

  1. หา Process ที่เราสนใจจะทำการ apply การทำภาพขาวดำก่อน

    API ที่ผมใช้ส่วนนี้คือ

    ::EnumProcesses ซึ่งทำให้เราได้จำนวน Process ที่กำลังรันอยู่ทั้งหมดมาพร้อมทั้ง Process ID ซึ่งเราจะใช้เอาไว้หาชื่อ Process ที่เราสนใจได้

  2. หา Window Handle (hwnd) ที่มันทำการแสดงผลอยู่ (visible) ของ Process นั้นๆ

    Code หลักๆที่ใช้ก็คือ  ::EnumWindows
    ซึ่งจากนั้นใน Callback ของ EnumWindowsProc นั้นจะได้ hwnd มาเรื่อยๆซึ่งผมจำการเช็ค

    if (!::IsWindow(hwnd) && !::IsWindowVisible(hwnd))
    return true;

  3. Render ทับตำแหน่ง application จริงๆด้วย Magnifier window พร้อมกับแปลงให้เป็นสีแบบ Gray Scale

    ส่วนนี้เป็นส่วนสำคัญที่สุด ซึ่งใช้ Magnification API โดยการสร้าง Window ด้วย Style : MS_CLIPAROUNDCURSOR

    m_hwndMag = CreateWindow(WC_MAGNIFIER, TEXT(“MagnifierWindow”),
    WS_CHILD | MS_CLIPAROUNDCURSOR | WS_VISIBLE

  4. ทำการ Refresh รูปบ่อยๆเพื่อให้ภาพเนียนที่สุดเวลา Application มีการ update หน้าจอ

    ส่วนนี้ไม่มีอะไรมากก็คือการตั้ง Timer เพื่อทำการ Refresh UI ครับแต่เราจะ Refresh เฉพาะ window ไม่ใช่ทั้งหน้าจอ Desktop

ตัวอย่างที่ได้ครับ

vscode
vscode in grayscale
chrome.png
Chrome เป็นสีเทา แต่ Edge ยังเป็นสีปกติ
ffx2.png
เกม FFX-2 ก็ทำให้ขาว-ดำ ได้นะครับ

ที่นี้มาดูผลที่ยังไม่น่าพอใจใน Implement ครั้งนี้ครับ

  1. ตัว render ภาพขาว-ดำนั้นเป็น Top Window ซึ่งทำให้ถ้ามี App ที่เปิดทับมันก็จะเป็นสีขาว-ดำด้วย
  2. ช้า เนื่องจากการ refresh นั้นบ่อยๆมีผลกับ Performance ทำให้ภาพมี delay บ้าง
  3. CPU ขึ้นตลอดเวลา 5% เนื่องจากต้อง query Process ตลอดเวลาในการเช็คว่ามี Window ของ Process ที่เราจะทำการ render ขาว-ดำ เปิดมาใหม่รึเปล่า

สุดท้ายนี้ ใครสนใจอยากดูตัวอย่างก็ Github เลยครับผม https://github.com/anurocha/mourning-win-app

npm แล้วช้ามาลองใช้ yarn จาก facebook กัน

yarn-kitten-full

ทุกๆท่านที่เขียน Node.js ก็ต้องคุ้นเคยกับ npm กันอยู่แล้วนะครับ ซึ่งบางทีเรามักจะเจอว่า มัน install นาน รวมถึงเวลาเน็ตมีปัญหาแล้วมัน install ไม่ได้ มาวันนี้ Facebook ได้ประกาศ Open Source ตัว package manager ตัวใหม่ที่ทำงานบนพื้นฐานของ npm ซึ่งชื่อของมันก็คือ Yarn

ทาง Facebook ได้พูดถึงจุดเด่นหลักๆได้ประมาณนี้ครับ

  1. เร็ว – เพราะมีระบบการ Cache ถ้า pkg ไหนโหลดมาแล้วก็ไม่ต้องโหลด
  2. เชื่อถือได้ – ใช้ในการติดตั้ง package ได้เหมือนเจ้าอื่น
  3. ปลอดภัย – ทำการ check sum ซึ่งเป็นการตรวจเช็คว่าการ install นั้นถูกต้อง

ความสามารถหลักๆของมันคือเช่น

  • Offline Mode ถ้าเคย insatll package มาแล้วครั้งนึง ก็ไม่ต้องใช้ internet ในการ install แล้ว
  • ใช้ประโยชน์จาก Network อย่างเต็มที่ทำให้การ install นั้นเร็วขึ้น
  • ใช้ได้ทั้งกับ npm และ Bower
  • ทำการ retry ถ้าหากว่ามีปัญหาตอน install

อ่านรายละเอียดได้ที่ https://github.com/yarnpkg/yarn และ https://code.facebook.com/posts/1840075619545360 สำหรับ Architure และที่มาที่ไปของ Project นี้ครับ

เกริ่นมาพอแล้ว เรามาลองเล่นกันดีกว่าครับ

ก่อนอื่นก็

npm install -g yarnpkg

แล้วก็ลองเช็คดูครับว่าลงได้

yarnv.png

ที่นี้เดี๋ยวผมลอง install module เล่นๆ เอาเป็น socket.io ละกันครับ ดังนั้นผมสร้าง package.json ง่ายๆมาก่อน

{
“dependencies”: {
“socket.io”: “^1.5.0”
}
}

package.json

ที่นี้ลองรัน “yarn” ซึ่งเทียบเท่ากับ “npm install”

จะเห็นว่าเราจะได้ node_modules มารวมถึงเวลาที่ใช้ไป 3.61s

yarn_install.png

ทีนี้ผมลองลบ folder ‘node_modules’ ทิ้งเพื่อจะดูว่ามัน Offline install ได้จริงเปล่าแล้วก็ทำการ yarn อีกที ผลที่ได้คือ !!! 0.77s

yarn_reinstall

จะเห็นได้ว่า yarn นั้นทำการ cached ตัว package ที่เคยโหลดมาแล้วไว้ที่ Local Machine ซึ่งผมลองไปคุ้ยๆ Folder ดูก็เจอว่ามันไปเก็บไว้ที่  %localappdata%/yarn นี่เองสำหรับบน Windows

local_yarn.png

สรุป ผมว่า Tool ตัวนี้น่าสนใจครับ เดี๋ยวว่าจะเอาไปลองใช้ใน Production บ้าง โดยเฉพาะช่วงเน็ตช้าและต้องงานหลายๆ repo ที่อาจจะมีการใช้ npm package ซ้ำๆกันบ่อยๆ…

Published Android เกมแรกกับ Cactus Hip Hip

เนื่องจากส่วนตัวเคยเขียน Android มาสมัยแรกๆ แต่ก็ลองแต่เป็น apk แล้วเอามาลงในเครื่อง แต่แล้วผมเลยได้มีโอกาสทำเกมเล็กๆขึ้นมาแล้วลอง publish ขึ้น Google Play Store ครับ

เกมนี้ก็คือ Cactus Hip Hip เป็นเกมแนว Arcade เล่นง่ายๆแค่จิ้มๆให้ตัว Qewy โดดไปมาเก็บลูกกระบองเพชรสีเขียวให้จบและจะมีการ Upload คะแนนตอนท้าย

Screen Shot 2559-09-28 at 5.05.07 PM.png

มาพูดถึง Technologies ที่ผมใช้ดีกว่าซึ่งเกมนี้ใช้เวลาพัฒนาประมาณ 5 วันได้มั้ง (พอดีผมทำแค่วันเสาร์หรืออาทิตย์)

  • TypeScript เนื่องจากว่าได้ใช้ในงานประจำ :p
  • Phaser.IO ซึ่งเป็น Game Engine เอาไว้เขียนเกม 2D ด้วย JavaScript ที่ทำให้ชีวิตเราง่ายขึ้น เพราะช่วยจัดการระบบฟิสิกส์ การชนกันของภาพ การทำ animation รวมถึงเสียง
  • Apache Cordova ซึ่งเอาไว้ Build โปรเจคจาก HTML5/JavaScript ไปเป็น apps
  • CrossWalk ซึ่งเป็น WebEngine เนื่องจากผมเจอว่า เวลา App ที่เขียนด้วย Phaser นั้นรันบน Android ด้วย Webview ที่ติดมากับ OS นั้นมันช้ามาก ซึ่ง CrossWalk นั้นจะเป็นโปรเจคที่ทำให้เรา ship ตัว Webview ตัวล่าสุดไปกับ App (และทำให้ App ใหญ่ขึ้น 20MB  😦 )
  • LoopBack เอาไว้เขียน REST เพื่อเก็บ Score
  • Azure DocumentDB ซึ่งเป็น Service ของ Microsoft Azure ในการใช้ NoSQL  ซึ่งจริงๆแล้วก็คือ MongoDB
  • และอื่นๆ เช่น
    • ใช้ Cordova  กับ iOS
    • Bitbugget ใช้เก็บ private git repository

จะเห็นว่าแค่เกมเล็กๆ Developer อย่างเราก็ต้องรู้จัก Tech หลายหลายมาก..

และที่สำคัญได้ลอง publish App ขึ้น Store  ซึ่งทำให้รู้ว่าหลังจากจ่ายตังค์ขอ Dev License แล้วใช้เวลา 1-2 ชม ก็สามารถเอา App ขึ้นได้ละ  (และจะเห็นว่า URL ของ app ผมยังเป็น codova อยู่เลยและมันก็แก้ไม่ได้ ฮาาา…)

Linkhttps://play.google.com/store/apps/details?id=io.cordova.myappee96f2

เข้าสู่ C++ ยุคใหม่กับ Module System สำหรับ C++ 17/20

ไม่ยอมน้อยหน้าภาษา Modern เพราะหนึ่งใน Feature ที่มีการพูดถึงกันมากของมาตรฐานใหม่ของ C++ 17 ก็คือเรื่อง Module System (Link) ซึ่งเป็นแนวคิดทำให้ Library เป็น Module แบบจริงจัง โดยที่ทางกลุ่ม C++ Working Group ได้นำเสนอมานานแล้ว และมีแผนที่จะเอาเข้ามาเป็นส่วนหนึ่งของ C++ 17 แต่เหมือนว่าไม่น่าจะทัน C++ 17 แล้วครับ สรุปแล้วตอนนี้ Feature นี้อยู่ในขั้น Technical Specification ซึ่งน่าจะออกจริงใน C++ 20 (เลขข้างหลังเป็นเลขที่ เช่น 2017 หรือ 2020)

เป้าหมายของ Module System คือทำให้ C++ นั้นทำการ Compile ได้เร็วขึ้นและทำให้ Code นั้นมีการจัดการระดับ Component ได้ง่ายขึ้น เพราะปัจจุบัน #include นั้นใช้งานปนไปหมดทั้ง Headers, Inlines รวมทั้งบางทีมี Implemenation กันเลยทีเดียว

Microsoft นั้นได้ออก Preview สำหรับการทดลอง Module ใน Visual Studio 2015 Update 1+ มาลองดูกันเลยดีกว่า

ก่อนอื่นเลยครับ เนื่องจากว่า Visual Studio ในส่วนของ IDE นั้นยังไม่ Support ดังนั้นเราจะต้องทำการ Compile กับ Build ผ่าน Command Line นะครับ

สร้าง Module

ในการสร้าง Module นั้นให้เราสร้างไฟล์ใหม่มา ซึ่งโดยทั่วไปจะนิยมใช้ไฟล์ .ixx (ผมเดาว่ามาจาก Interface++)
เรามาสร้าง Module เอาไว้ Convert ค่าง่ายๆกัน

ไฟล์ converter.ixx

module converter;
export int CtoB(int x)
{
    return x + 543;
}

จาก code นี้จะเป็นการประกาศ Module ชื่อ converter ซึ่งมี function ‘CtoB’ ที่ทำการแปลง ค.ศ. ไป เป็น พ.ศ. ที่จะ export ออกไปให้ Code อื่นใช้

จากนั้นเราต้อง compile ด้วย commandline แบบนี้

cl /c /experimental:module converter.ixx

สิ่งที่ได้ก็คือไฟล์ converter.ifc กับ converter.obj

converter.png

เรียกใช้ Module

ที่นี้มาในส่วนของ Code หลักที่มี main entry point กันครับ ผมตั้งชื่อไฟล์ว่า main.cpp

ไฟล์ main.cpp

#include <iostream>
import converter;
int main()
{
 int year;
 std::cout << "Enter Year : ";
 std::cin >> year; 

 int bc = CtoB(year);
 std::cout << "Thai year is " << bc << std::endl;
 return 0;
}

Code ในส่วนนี้มีการเรียกใช้ Module ชื่อ ‘converter’ ด้วย keyword ที่ชื่อ import จากนั้นก็จะเรียกใช้ function ที่ชื่อ CtoB() ได้ทันทีเลยครับ

แน่นอนว่าเราต้อง compile ด้วย command line เช่นเคยโดยต้องระบุ converter.ifc เป็น parameter ของ module ที่จะเรียกใช้

cl /c /experimental:module /module:reference converter.ifc main.cpp

เมื่อรันเสร็จก็จะได้ main.obj มาครับ

main.png

ที่นี้จะเป็นว่าไม่มี .exe ให้เรา….สิ่งที่ต้องทำคือการสร้าง .exe ด้วย

link *.obj /OUT:main.exe

link.png

ทดสอบ

ลองรัน main.exe ที่ได้มาครับ ทำงานถูกต้องนะ 🙂

out.png

ลองด้วย Class

จากตัวอย่างข้างบนนั้นเป็นการสร้าง Module ด้วยการ export แค่ function แต่ถ้าเราอยากที่จะ  export Class ล่ะ เราก็ทำได้ครับ เช่น สร้าง Class  converter โดยมี method 2 ตัวให้เรียกใช้

module converter;
export namespace converterUtil
{
 class converter
 {
 public:
 int CtoB(int year)
 {
 return year + 543;
 }

 int CelsiusToFahrenheit(int c)
 {
 return (c * 1.8) + 32;
 }
 };
}

มาดูที่ main.cpp เราก็ทำการ import มาใช้และสร้าง Object ได้เลย เช่นใน ‘convt’ ตาม Code ด้านล่างนี้

#include <iostream>
import converter;
int main()
{
 converterUtil::converter convt;

 int year;
 std::cout << "Enter Year : ";
 std::cin >> year; 

 std::cout << "Thai year is " << convt.CtoB(year) << std::endl;

 int cel;
 std::cout << "Enter Temp in Celsius : ";
 std::cin >> cel; 
 std::cout << "Temp in Fahrenheit is " << convt.CelsiusToFahrenheit(cel) << std::endl;

 return 0;
}

ผลที่ได้ก็ Work ดีครับ!!

outex.png

สรุปแล้ว C++ Module น่าจะช่วยให้ C++ Developer ออกแบบและทำงานกับ Code ได้เป็นระเบียบเรียบร้อยขึ้น

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

ณ. ตอนนี้เราก็มาเฝ้ารอ C++ 20 กันเลยกัย Module System!!

ปล. ดู Code ได้ที่ https://github.com/anurocha/cpp_module เลยครับผมอัพไว้ละ

Node.js – LoopBack กับการต่อ Database

ความเดิมตอนแรกสุดเลยนั้น ผมใช้ datasources เป็น memory เพราะว่าใช้ในการ Development ที่นี้เนื่องจากว่าผมอยากใช้ database เป็น NoSQL ผมก็เลยลองหาวิธีการดู ซึ่งก็ไม่ผิดหวังครับ LoopBack นั้นจัดการให้เราได้อย่างง่ายๆเช่นเคย

บทความก่อนหน้าเพื่อความเข้าใจพื้นฐานมากขึ้น

Node.js เขียน REST API ด้วย LoopBack
Node.js – LoopBack มาต่อกันที่การเพิ่ม REST API กับ Query กัน

ที่นี้เปิดดูไฟล์ datasources.json กันก่อนครับ จะเห็นว่าเป็นการ define ว่าใช้ memory

{
  "db": {
    "name": "db",
    "connector": "memory"
  }
}

แก้ datasources.json
ผมก็แค่เปลี่ยน configuration ในนี้ให้เป็น  ‘mongodb’ ซึ่งผมทดสอบกับ Azure DocumentDB service นะครับ ไม่ได้ตั้ง mongoDB เอง

nosql.png

ที่นี้เราลองมารัน LoopBack กันอีกรอบนึงครับ ปรากฎว่ารันไม่ผ่าน เพราะ LoopBack ไม่รู้จัก configuration นี้

no-connector.png

ติดตั้ง Connector
สิ่งที่เราต้องทำคือการ install mongodb connector ครับ ด้วย npm command ข้างบน

npm install loopback-connector-mongodb

เมื่อ install เสร็จก็จะสามารถรันได้แล้วครับ เช่นเดิมคือ port เบอร์ 3000

has-connector.png

ทดสอบ
ที่นี้เราลอง POST เพื่อใส่ข้อมูลกัน ผม POST  – anurocha กับ destiny ไปครับ

post-db.png

ที่นี้ลอง Query ดูใน Azure Dashboard ก็จะเห็นว่าลองใช้ Query Explore บน Azure ดูก็ได้ค่าที่ POST ไปจาก localhost ที่เราต่อกับ mongoDB บน Azure ถูกต้อง

azure-db.png

จะเห็นได้ว่า LoopBack นั้นช่วยให้เรา Connect ไปที่ Database ได้โดยที่ผมยังไม่ได้เขียน Code หรือ SQL เลยโดยที่ datasource ที่ LoopBack นั้นมี Connector ก็ดูได้ตามนี้ครับ (Database connectors) ซึ่งคร่าวๆก็มีครบหมดครับสำหรับตัวยอดนิยม MongoDB, MySQL, Oracle, PostgreSQL, Redis, SQL Server, SQL Lite และอื่นๆ

เป็นไงครับ POWER FUL มากๆ…

Node.js – LoopBack มาต่อกันที่การเพิ่ม REST API กับ Query กัน

หลังจากที่ผมพูดถึงความสามารถเบื้องต้นของ LoopBack ไปแล้วนั้นใน Node.js เขียน REST API ด้วย LoopBack ซึ่งจะเห็นได้ว่าเราสามารถสร้าง REST API ได้ง่ายมาก แต่ทีนี้ถ้าเราต้องการที่เพิ่ม API ล่ะจะทำได้ยังไง

เรากลับมาดูที่ไฟล์ user.js กันก่อนครับ ซึ่งเป็นไฟล์ว่างๆ

'use strict';

module.exports = function(User) {

};

สิ่งที่ผมอยากจะได้ก็คือถ้าเราต้องการ API เพื่อที่จะเอาค่าของ User 4 คนที่ได้คะแนนสูงสุดจะต้องทำยังไงบ้าง
สิ่งที่เราต้องทำคือการเพิ่ม remoteMethod (ซึ่งทาง LoopBack Framework จะทำการ Route มาเข้า Method ของเราครับ

'use strict';

module.exports = function(User) {
User.getTopUsers = function(cb){
cb(null, "getTopUsers Response");
};

User.remoteMethod (
'getTopUsers',
{
http: {path: '/gettopusers', verb: 'get'},
returns: {arg: 'users', type: 'string'}
}
);
};

จะเห็นว่า Code User.remoteMethod นั้นทำการ define ว่าถ้ามี HTTP Request ที่เป็น GET เข้ามาที่ Path /gettopusers นั้นจะทำการเรียก Method User.getTopUsers นั่นเอง

และใน Method ที่ชื่อ User.getTopUsers นั้นตอนนี้ผมลองให้ส่งค่ากลับไปว่า getTopUsers Response ที่นี้ลองรันดู LoopBack เพื่อเป็น Server ดูครับ

ลองเช็คกับ API Explorer ก็จะเห็นว่า API ที่เราเพิ่งเพิ่มเข้าไปมาแล้ว

new-api.png

เนื่องจากเป็น GET ผมลองเรียกผ่าน Browser ครับก็ได้ Response มาแบบนี้ ตามที่เขียนไว้

new-api-response.png

ที่นี้จาก API ที่ผมต้องการนั้น ผมอยากได้ User ที่คะแนนสูงสุด ซึ่งทาง LoopBack นั้นก็มี Build-in API ให้เราใช้ในการ Query ข้อมูลจาก Model ได้ครับ (Querying data) เช่น

'use strict';

module.exports = function(User) {
User.getTopUsers = function(cb){
User.find({
order: 'score DESC',
limit : 4
}, (err, instances)=&gt;{
cb(null, instances);
});
};

User.remoteMethod (
'getTopUsers',
{
http: {path: '/gettopusers', verb: 'get'},
returns: {arg: 'users', type: 'string'}
}
);
};

ซึ่งจาก Code ข้างบนนี้จะเป็นการใช้ User.find ซึ่งเป็นการ Query หา Model โดยมี Filter ว่า หา ‘score’ ที่มีค่าสูงสุด 4 entries แรก

ที่นี้ลองทดสอบกันอีกทีครับ

ผมลองใส่ ข้อมูลไปแบบนี้ตาม Order

[
{
“name”: “alpha”,
“score”: 70,
“id”: 1
},
{
“name”: “beta”,
“score”: 45,
“id”: 2
},
{
“name”: “catto”,
“score”: 39,
“id”: 3
},
{
“name”: “delta”,
“score”: 86,
“id”: 4
},
{
“name”: “sigma”,
“score”: 34,
“id”: 5
},
{
“name”: “fanta”,
“score”: 12,
“id”: 6
}
]

ทีนี้ลองเรียกผ่าน API /gettopusers ดูครับ

result.png

เราก็จะได้ Response ที่ทำการ Order มาแล้วตาม score โดยที่ delta(80), alpha(70), beta(45), catto(39) ตามลำดับที่เราได้ทำ Query ไว้อย่างง่ายดาย

มาถึงตรงนี้เราก็จะได้เห็นความ Powerful ของ LoopBack ไปอีกหนึ่งเรื่องนะครับ 🙂

powered-by-lb-med