เรื่องของตัว S (Single Responsibility) ในหลักการ SOLID

Screen Shot 2560-08-23 at 12.04.58 AM.png

หลังจากที่ผมได้เกริ่นเกี่ยวกับหลักการ SOLID ไปแล้วนั้น วันนี้เราจะมาลองดูกันกับตัวแรกของเรา ซึ่งก็คือตัว S ซึ่งย่อมากจาก Single Responsibility หรือแปลว่า หลักการทำหน้าที่เดียวพอ ซึ่งผมจะขอใช้ตัวอย่างด้วย TypeScript ครับ

Single Responsibility Principle (SRP) นั้นกล่าวถึงการออกแบบ Class ในภาษา Object Oriented เพื่อที่จะทำให้ Class นั้นดูแลและจัดการได้สะดวกมากขึ้น

เริ่มต้น ผมมี Class ตัวอย่างที่ชื่อว่า SmartPhone

class SmartPhone {
   // properties
   private apps : Array<string>;
   private contacts : Array<string>;
   private phoneNumber : string;
   private phoneModel : string;
   private screenWidth : number;
   private screenHeigth : number;

   // methods
   public call( telNum : number){
   }
   public ring(){
   }
   public installApp(appName : string){
      this.apps.push(appName);
   }
   public launchApp(appName : string){
      let app = this.apps.filter(element => element === appName);
   }
   public addContact(contact : string){
      this.contacts.push(contact);
   }
   public getScreenPixel() : number {
      return this.screenWidth * this.screenHeigth;
   }
   public getModel() : string {
      return this.phoneModel;
   }
}

ซึ่งจาก Code ตัวอย่างนี้จะเห็นได้ว่า Class SmartPhone นี้ก็ออกแบบมาตามหลัก OO ระดับหนึ่ง ซึ่งถ้าเรามาดูรายละเอียดดีๆนั้นจะเห็นว่ามันมี 3 ส่วนด้วยกัน

  1. การจัดการ Apps
  2. การจัดการ Contact
  3. ข้อมูลของตัว SmartPhone เอง

แต่จะเห็นว่า Code นี้ยังไม่ได้ใช้หลักการของ SRP เลย ดังนั้นสิ่งที่เราต้องทำคือ เราจะมาลองเปลี่ยน Code ให้สอดคล้องกับหลักการนี้ ขั้นตอนนี้เราเรียกว่า การ Refactor 

สิ่งที่ต้องทำก็คือจะใช้เทคนิคการ  Refactor ที่ชื่อว่า Extract Class ก็คือเป็นการแยก Code ในส่วนของ Properties และ Methods ที่น่าจะรวมกันเป็น Class ใหม่ได้ออกมา

ดังนั้นเราเราจะได้ Class ใหม่มาเพิ่มอีก 3 Class คือ Apps และ Contacts

  1. Class Apps จะเอาการเก็บข้อมูล Array และ Methods การ install กับ launch มาไว้ใน Class นี้
class Apps {
   private apps : Array<string>;
   public install(appName : string){
      this.apps.push(appName);
   }
   public launch(appName : string){
      let app = this.apps.filter(element => element === appName);
   }
}

2. Class Contacts จะเอาไว้จัดการเกี่ยวกับ Contact List

class Contacts {
   private contacts : Array<string>;
   public add(contact : string){
      this.contacts.push(contact);
   }
}

3. Class PhoneInfo เราจะเอามาเก็บข้อมูลทั่วไปเช่น เบอร์โทร ชื่อรุ่น ขนาดหน้าจอ

class PhoneInfo {
   private phoneNumber : string;
   private phoneModel : string;
   private screenWidth : number;
   private screenHeigth : number;
   constructor(model : string){
      this.phoneModel = model;
      this.screenWidth =5;
      this.screenHeigth =10;
   }

   public getModel() : string {
      return this.phoneModel;
   }

   public getScreenPixel() : number {
      return this.screenWidth *this.screenHeigth;
   }
}

ซึ่งเมื่อมาถึงตรงนี้แล้วเราก็ต้องทำการแก้ Class หลักของเราก็คือ Class SmartPhone ให้มาเรียกใช้งานทั้ง 3 Classes นี้

// Smart Phone V2
class SmartPhone {
   private apps : Apps; // เรียกใช้ Class Apps
   private info : PhoneInfo; // เรียกใช้ Class PhoneInfo
   private contacts : Contacts; // เรียกใช้ Class Contacts

   constructor(){
      this.apps =new Apps();
      this.info =new PhoneInfo('S10');
      this.contacts =new Contacts();
   }

   public call( telNum : number){
   }

   public ring(){
   }

   public installApp(appName : string){
       this.apps.install(appName); // เรียกใช้ Method ของ Class Apps
   }

   public launchApp(appName : string){
      this.apps.launch(appName);// เรียกใช้ Method ของ Class Apps
   }

   public addContact(contact : string){
      this.contacts.add(contact);// เรียกใช้ Method ของ Class Contacts
   }

   public getScreenPixel() : number {
      return this.info.getScreenPixel();// เรียกใช้ Method ของ Class PhoneInfo
   }

   public getModel() : string {
       return this.info.getModel();// เรียกใช้ Method ของ Class PhoneInfo
   }
}

หลังจากทำการ Refactor เสร็จก็จะเห็นได้ว่า Class SmartPhone Verion 2 นั้นจะเป็นระเบียบมากขึ้น ไม่ต้องมาเก็บตัวแปรที่เป็น String หรือ Array ที่ไม่เกี่ยวข้องอะไรกับตัว Class นี้เองเลย แต่จะย้ายไปเก็บใน Class ย่อยๆแทนเพื่อที่จะให้ Code นั้นเหมาะสมกับ Class แต่ละ Class จริงๆ

เท่านี้เพื่อนๆก็จบหลักสูตร Single Responsibility Principle กันแล้วครับ หวังว่าจะเป็นประโยชน์กับทุกคน แล้วเจอกันตอนหน้าด้วยหลักการตัว O 🙂

หลักการ SOLID สำหรับคนที่เขียน OOP

SOLID เป็นหลักการ 5 ข้อที่จะช่วยให้ Developer ที่เขียนภาษา Object Oriented เช่นพวก C#, Java, C++) นั้นสามารถเขียน Code ได้ดูเป็นระบบระเบียบมากขึ้น รวมถึงสามารถที่จะดูแลและแก้ไขได้ง่ายและสุดท้ายทำให้พวกเราดูเป็น Profressional กันด้วย 🙂

ถึงแม้ว่าหลักการของ SOLID นั้นมีมาก็หลาย 10 ปีแล้วแต่ผมคิดว่าสำหรับนักพัฒนาที่เขียนภาษา OO ก็เป็นสิ่งที่ยังควรรู้ รวมถึงคนที่เขียนภาษาอื่นๆเช่นพวก Script หรือ Dynamic languages ก็อาจจะเอาไปประยุกต์ใช้ได้เหมือนกัน

เอาล่ะเรามาดูกันว่าหลักการ 5 ข้อนั้นย่ามาจากอะไรบ้าง

S – Single Responsibility Principle

กล่าวถึง Class หนึ่งๆนั้นควรจะมีแค่หน้าที่ ความรับผิดชอบเดียวเท่านั้น

O – Open Closed Principle

กล่าวถึง ระบบของ Software นั้นควรง่ายและเป็นระบบเปิดต่อการต่อยอดโดยที่แก้ไขระบบหลักให้น้อยที่สุด

L – Liskov substitution Principle

กล่าวถึง Object ของ Class ที่ระบบได้เรียกใช้นั้นควรจะสามารถเรียกใช้ Class ลูกๆได้โดยที่ไม่ต้องแก้ไขระบบเลย (ข้อนี้อาจจะเข้าใจยากนิดนึงนะครับ อาจจะต้องลองดูตัวอย่าง)

I – Interface segregation Principle

กล่าวถึงการแบ่งย่อย Interface ให้เป็นสัดสวนตามหน้าที่ของมัน ดีกว่ามี Interface เดียวที่มีหลายๆ Methods

D – Dependency Inversion Principle

กล่างถึงการที่ Class ต่างๆติดต่อกับอีก Class อื่นๆนั้น ควรจะติดต่อกันผ่าน Interface มากกว่า Object ของ Class นั้นๆตรงๆ

 

 

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

ref : https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

WebAssembly เมื่อการพัฒนาเว็บเข้าสู่อีกโลกนึง

ในยุคที่มองไปทางไหนก็มีแต่การพัฒนา Software ด้วย Web Technology ไปหมดทุกทางและยิ่งเป็น Modern Web ที่มี JavaScript เป็นหัวใจสำคัญแล้วนั้น หลายๆปัญหาทางด้าน Performance ก็จะไปติดคอขวดอยู่ที่ Layer ของ JavaScript Engine ดังนั้นทางออกหนึ่งที่ทาง Community นั้นได้มองเห็นก็คือการต่อตรงกับ OS ไปเลยแทนที่จะต้องผ่านการแปล JavaScript ซึ่งนี่ก็คือหนึ่งในที่มาของ WebAssembly

WebAssembly คือการนำ Low Level Code ที่เขียนด้วย C/C++ (และอาจจะมีภาษาอื่นๆในอนาคตเพราะตอนนี้ก็มีภาษา Rust ที่ใช้ได้ด้วยเหมือนกัน) มาทำการรันภายใต้ Web Browser เพื่อให้ได้ Performance  สูงที่สุดรวมทั้งยังสามารถติดต่อกับ JavaScript ได้ด้วย ซึ่งหมายความว่ามันไม่ได้เป็นภาษาใหม่ที่จะมาแทน JavaScript แต่มันคือสิ่งที่จะช่วยยกระดับการพัฒนาเวปมากกว่าครับ และที่สำคัญโปรเจคนี้พัฒนาด้วยเจ้าใหญ่แห่งวงการทั้งนั้น เช่น Mozilla Microsoft Google Apple

เนื่องจากว่า WebAssembly นั้นค่อนข้าง Low Level มาก(แค่มีคำว่า Assembly ก็แลดูน่ากลัวแล้ว) ดังนั้นนักพัฒนาที่สนใจในเรื่องนี้ก็จำเป็นต้องรู้จักสิ่งเหล่านี้ก่อนครับ

  • Source Code แน่นอนว่าคือไฟล์ที่พวกเราเขียน Code ลงไปโดยจะแบ่งเป็น 2 ส่วนคือฝั่ง C/C++ กับฝั่ง JavaScript ครับ
  • Compiler เป็นตัวแปลงภาษา C/C++ ไปเป็น Bytes Code หรือ Machine Code ซึ่งภาษาที่ต้องใช้ Compiler นั้นจะเป็นภาษาที่มี Performance สูงกว่าภาษาพวก Script เพราะไม่ต้องแปลง Code ตอน เวลา Runtime
  • Bytes Code เป็นภาษาระดับกลางที่ทาง WebAssembly Runtime นั้นเข้าใจและทำงานติดต่อกับ OS ตรงๆ
  • Interoperability เป็นการทำงานเชื่อมกันระหว่างระบบหนึ่งกับอีกระบบหนึ่งเช่น การเรียกให้ Module ที่เขียนด้วย C++ ทำงานด้วย Code ของภาษา JavaScript หรือด้านสลับกัน

หลักการพัฒนาเว็บด้วย WebAssembly ก็คือ

  1. Developer เขียนโปรแกรมด้วย C/C++
  2. Developer ทำการ Compile C/C++ ที่เขียนไว้ให้เป็น WebAssembly Bytes Code (ไฟล์ .wasm) เพื่อให้พร้อมที่จะรันได้ใน Browser
  3. Developer ต้องเขียน JavaScript ให้ทำการโหลด .wasm ไฟล์มาไว้ใน Memory เพื่อให้ WebAssembly Runtime ที่อยู่บน Browser นั้นทำการแปลง Bytes Code ให้เป็น JavaScript Object
  4. Developer เรียกใช้งาน function ที่เขียนด้วย C/C++ ผ่าน JavaScript

ทีนี้เรามาลองดูแบบ Step by Step กัน

ก่อนอื่นเลยผมมี Code ที่เขียนด้วย C ง่ายๆคือ function การบวกเลข ช่ือไฟล์ demo.c

Screen Shot 2560-03-05 at 7.04.29 PM.png

สิ่งที่ต้องทำขั้นต่อไปคือ Compile Code ชุดนี้ให้เป็น .wasm ซึ่งเครื่องมือที่ใช้ค่อนข้างซับซ้อนสำหรับมือใหม่(อย่างผม) ซึ่งใช้ emcc (Emscriptenซึ่งเป็น Open Source โปรเจคซึ่งติดตั้งจาก ที่นี่

$emcc demo.c -Os -s WASM=1 -s SIDE_MODULE=1 -o democ.wasm

ด้วย command ข้างบนนี้เราก็จะได้ democ.wasm ซึ่งเป็นไฟล์ Bytes Code ที่ใช้งานได้กับ Browser ที่สนับสนุนแล้ว เช่น Google Chrome 57+ ขึ้นไป

หน้าตาของไฟล์ .wasm ก็เป็นแบบนี้ครับ!! อ่านไม่ออกแน่นอน เพราะเป็น Bytes Code 🙂

Screen Shot 2560-03-05 at 7.03.33 PM.png

ถัดมาเราก็มาเขียน JavaScript ให้การโหลดไฟล์ democ.wasm ซึ่งผมใช้ fetch API ครับและหลังจากนั้นเป็นการเรียกใช้งาน function

Screen Shot 2560-03-05 at 7.06.57 PM.png

จาก Code นี้ในฝั่งของ JavaScript นั้นผมขอแบ่งออกเป็น 4 ส่วนครับ

  1. โหลดไฟล์ .wasm ด้วย fetch API
  2. ทำการประกาศ imports Object เพื่อให้ตัว WenAssembly ทำงานได้ถูกต้อง เช่นการกำหนดขนาดของ  Memory
  3. เป็นการสร้าง Module Object จาก .wasm
  4. เป็น Code ที่ใช้เรียก function “add” ที่เขียนด้วยภาษา C (ในการ Compile นั้นทาง Compiler ได้เติม _ เพื่อเป็น prefix ให้กับชื่อ function ทำให้เราต้องเรียก function นี้ด้วย _add แทน)

ทีนี้ลองมารันดูครับด้วย localhost:8080/demo.html แต่ก่อนอื่นเราต้องมี Browser ที่รองรับก่อน

เตรียม Browser ให้พร้อม

ผมเลือกใช้ Google Chrome Canary Build (ซึ่งเป็น Google Chrome เวอร์ชั่นทดสอบ) ซึ่งตอนนี้เป็นเวอร์ชั่น 59 ครับ เราต้องเปิด flag สำหรับ WebAssembly ด้วยเพราะตอนนี้ยังเป็นแค่ฟีเจอร์สำหรับการทดสอบอยู่ด้วย

chrome://flags/#enable-webassembly

Screen Shot 2560-03-05 at 8.34.54 PM.png

ผลของการทำงานก็จะเห็นได้ว่า function _add นั้นทำการบวกค่าได้อย่างถูกต้อง

Screen Shot 2560-03-05 at 7.11.48 PM.png

สรุป

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

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 ในมือแล้วหรือยัง ????