Month: May 2021

  • การเข้ารหัสข้อมูลด้วย ORACLE DBMS_CRYPTO

                  ข้อมูลที่ส่งผ่านในโลกอินเตอร์เน็ตอาจมีความจำเป็นต้องเข้ารหัสข้อมูลเพื่อความปลอดภัย แม้ว่าระบบการป้องกันจะดีแค่ไหน แต่การปล่อยข้อมูลในรูปแบบที่อ่านได้ (Plain Text) ให้วิ่งผ่านเน็ตเวิร์ค ดูเป็นสิ่งที่ไม่ปลอดภัยเป็นอย่างยิ่ง

                  ข้อมูลบนระบบจัดการฐานข้อมูล ORACLE มีฟังก์ชันสำหรับการเข้ารหัสข้อมูล (Encrypt) และถอดรหัสข้อมูล (Decrypt) สำหรับข้อความได้ในหลายๆ Algorithm ดังนี้

    ENCRYPT_DESData Encryption Standard. Block cipher. Uses key length of 56 bits.
    ENCRYPT_3DES_2KEYData Encryption Standard. Block cipher. Operates on a block 3 times with 2 keys. Effective key length of 112 bits.
    ENCRYPT_3DESData Encryption Standard. Block cipher. Operates on a block 3 times.
    ENCRYPT_AES128Advanced Encryption Standard. Block cipher. Uses 128-bit key size.
    ENCRYPT_AES192Advanced Encryption Standard. Block cipher. Uses 192-bit key size.
    ENCRYPT_AES256Advanced Encryption Standard. Block cipher. Uses 256-bit key size.
    ENCRYPT_RC4Stream cipher. Uses a secret, randomly generated key unique to each session.

    สำหรับตัวอย่างในวันนี้จะแสดงการเข้ารหัสข้อมูลด้วย Algorithm DES ซึ่งคีย์จะมีความยาว 56 bits

    เนื่องจากการเข้ารหัสและถอดรหัสจะใช้งานคู่กัน ดังนั้นเราสามารถเขียนทั้งสองฟังก์ชันไว้ใน Package ดังนี้

    CREATE OR REPLACE PACKAGE EN_DE
    AS
    FUNCTION ENCRYPT (p_plainText VARCHAR2) RETURN RAW DETERMINISTIC;
    FUNCTION DECRYPT (p_encryptedText RAW) RETURN VARCHAR2 DETERMINISTIC;
    END;
    /
    
    
    CREATE OR REPLACE PACKAGE BODY "EN_DE"
    AS
    encryption_type PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_DES
    + DBMS_CRYPTO.CHAIN_CBC
    + DBMS_CRYPTO.PAD_PKCS5;
       /*
       ENCRYPT_DES is the encryption algorithem. Data Encryption Standard. Block cipher. Uses key length of 56 bits.
       CHAIN_CBC Cipher Block Chaining. Plaintext is XORed with the previous ciphertext block before it is encrypted.
       PAD_PKCS5 Provides padding which complies with the PKCS #5: Password-Based Cryptography Standard
       */
       encryption_key RAW (32) := UTL_RAW.cast_to_raw('OneTwoThree');
    -- The encryption key for DES algorithem, should be 8 bytes or more. 
    
    FUNCTION ENCRYPT (p_plainText VARCHAR2) RETURN RAW DETERMINISTIC
     IS
        encrypted_raw      RAW (32767);
     BEGIN
        encrypted_raw := DBMS_CRYPTO.ENCRYPT
        (
           src => UTL_RAW.CAST_TO_RAW (p_plainText),
           typ => encryption_type,
           KEY => encryption_key
        );
       RETURN encrypted_raw;
     END ENCRYPT;
    
     FUNCTION DECRYPT (p_encryptedText RAW) RETURN VARCHAR2 DETERMINISTIC
     IS
        decrypted_raw      RAW (32767);
     BEGIN
        decrypted_raw := DBMS_CRYPTO.DECRYPT
        (
            src => p_encryptedText,
            typ => encryption_type,
            KEY => encryption_key
        );
        RETURN (UTL_RAW.CAST_TO_VARCHAR2 (decrypted_raw));
     END DECRYPT;

    END;
    /

    
    
    
    
    

    จากคำสั่งการสร้าง Package ข้างต้นเป็นการเข้ารหัสและถอดรหัสโดยใช้ Algorithm แบบ DES การเรียกใช้งานสามารถเรียกผ่านคำสั่งบน SQL Plus ได้ดังภาพ

    จากการทำงานจะพบว่าเราสามารถเข้ารหัสข้อมูลอย่างง่ายด้วย Algorithm DES ได้ หากต้องการใช้ Algorithm อื่น สามารถเปลี่ยนค่าได้จากที่กำหนดไว้ใน Package ได้ โดยต้องคำนึงถึงขนาดของคีย์ที่เข้ารหัสด้วย เช่น AES ต้องมีขนาดคีย์เป็น 128 bits, 256 bits เป็นต้น

  • ETL ต้องตรวจสอบอะไรบ้างเพื่อความมั่นใจในโอน ย้ายข้อมูล

    ETL (Extract, Transform, Load) ประโยชน์ที่สามารถนำไปประยุกต์ใช้

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

    ============================

    ETL Tools ตอนนี้มีอยู่หลายค่ายหลายโปรแกรม ทั้งฟรีและขาย สามารถนำมาประยุกร์ใช้งานได้ ตัวอย่างเช่น

    • Microsoft SQL Server Integration Services (SSIS)
    • Oracle Data Integrator
    • Oracle Warehouse Builder
    • IBM – Infosphere Information Server
    • Pentaho Data Integration
    • Apache Nifi 
    • SAP – BusinessObjects Data Integrator
    • Sybase ETL

    ==========================

    ต้องตรวจสอบอะไรบ้างเมื่อท่านต้องทำ ETL

    1. Metadata Testing เป็นการทดสอบส่วนประกอบของข้อมูลพวกชนิดของข้อมูล ขนาดและเงื่อนไขต่างๆของข้อมูล
    2. Data Completeness Testing ความสมบูรณ์ของข้อมูลต้องสุ่มทดสอบข้อมูล เช่น คีย์ที่ใช้เชื่อมข้อมูลระหว่างตารางไม่ควรจะเป็น NULL
    3. Data Quality Testing คุณภาพของข้อมูล เช่นข้อมูลชื่อประเทศเดียวกันต้องสะกดเหมือนกันทั้งหมด การหาข้อมูลซ้ำซ่อนแบบไม่ปกติ
    4. Data Transformation Testing ดักจับ error ระหว่างการถ่ายโอนข้อมูล
    5. ETL Regression Testing ทดสอบเมื่อมีการเปลี่ยนแปลงกระบวนการในการทำ ETL
    6. Reference Data Testing การทดสอบกับข้อมูลที่เป็นสากลทั่วไปใช้กัน เช่น ชื่อ ตำบล อำเภอ จังหวัด ควรต้องตรงกันกับข้อมูลของราชการเท่านั้น
    7. Incremental ETL Testing เป็นการทดสอบโดยการค่อยๆเพิ่มกระบวนการถ่ายโอนข้อมูลเป็นขั้นๆเพื่อหาปัญหาของการถ่ายโอน
    8. ETL Integration Testing เป็นการทดสอบภาพรวมของการทำงานรวมกันของ module เงื่อนไขต่างๆในการถ่ายโอนข้อมูล
    9. ETL Performance Testing เป็นการประเมินเรื่องเวลาและปริมาณข้อมูลเพื่อจะได้ทราบถึงระยะเวลาการทำงานที่ควรจะเกิดขึ้นกับข้อมูลปริมาณที่ต้องการ

    Metadata Testing สิ่งที่ต้องตรวจสอบ

    1. Data Type ชนิดของข้อมูลระหว่าง Source และ Target 
    2. Data Length ความยาวของข้อมูลแบบต่างๆ เช่น String Char Varchar
    3. Index / Constraint ตรวจสอบว่ามีการกำหนดข้อจำกัด และดัชนีที่เหมาะสมบนตารางฐานข้อมูลตามข้อกำหนดที่ออกแบบได้ ตรวจสอบว่าคอลัมน์ที่ไม่สามารถเป็นค่าว่างมีข้อ จำกัด “NOT NULL” ตรวจสอบว่ามีการจัด Index หรือ Key ต่างๆครบถ้วนหรือไม่
    4. ช่วงของข้อมูล เช่น พ.ศ.ต้องมีช่วงประมาณไหน เพื่อหาความผิดปกติ ช่วงของวันที่ต่างๆ
    5. Build in Function ต่างๆรอบรับความต้องการที่จะดำเนินการหรือไม่ เช่น Oracle Build in funciton TO_DATE จะรองรับข้อมูลวันที่เป็น ค.ศ. เท่านั้น
    6. การตั้งชื่อที่สื่อได้ดีเป็นที่เข้าใจทั่วกัน
    7. เงือนไขหรือ logic การเพิ่ม Compute Column ที่เหมาะสม
    8. การแปลงข้อมูลไม่ควรเกิดจากหลายๆแหล่งเพราะจะทำให้การแก้ไขทำได้ลำบากมากขึ้น เช่น มีการสร้าง View มาหลายชั้นก่อนที่จะมาผ่านกระบวนการ ETL หรือเมื่อผ่านกระบวนการ ETL แล้วค่อยไปคำนวณหรือจัดการข้อมูลอีกขั้นตอนต่อๆไป 

    การตรวจสอบการเปลี่ยนแปลงของข้อมูลของการทำ ETL แต่ละรอบ

    1.Track changes ตรวจสอบ metadata ตามเวลาที่กำหนด ทั้ง Source และ Target และส่วนของการพ้ฒนา

    2.Compare table metadata ทั้ง Source และ Target และส่วนของการพ้ฒนา ชื่อของตารางและColumn  ขนาดของ Column

    3.Compare column data types

    4.ตรวจสอบ Look Up table ต่างๆว่าข้อมูล Update ให้เหมาะสมและครบถ้วนแล้วหรือไม่

    Data Completeness Testing

    1. Record Count Validation เป็นพื้นฐานคือนับจำนวน records ต้นทาง ปลายทาง โดยลอง Group by ข้อมูลแบบต่างๆและที่สำคัญตรวจสอบ Null Values ข้อมูลสำคัญๆ
    2. Column Data Profile Validation ค่าที่สามารถนำมาทดลองได้คือเปรียบเทีบย unique values, max, min, avg, max length, min length ค่าของ Column และ null values ของ Column
    1. เปรียบเทียบภาพร่วมของข้อมูลทั้งหมดของ Source และ Target เช่น การนับจำนวนตามกลุ่มที่เหมาะสม

    Data Quality tests ตรวจสอบคุณภาพของข้อมูล

    1. Duplicate Data Checks
    SELECT fst_name, lst_name, mid_name, date_of_birth, count(1) FROM Customer GROUP BY fst_name, lst_name, mid_name HAVING count(1)>1
    1. Data Validation Rules  ธรรมชาติของข้อมูลในแต่ละ Column ค่าควรเป็นอย่างไร เช่น ช่วงของข้อมูลอายุคนไม่ควรจะเกิด 120 เป็นต้น ช่วงของข้อมูลแบบวันที่ควรจะไม่เกินเท่าไรในแต่ละช่วงข้อมูล
    2. Data Integrity Checks
      1. นับค่า null ของ foreign key ในตารางลูก
      2. นับค่าที่ไม่มีของ foreign key ในตารางลูก

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

  • Blazor Server Application : วิธีการแปลงรูปภาพ เป็น base64 สำหรับเก็บข้อมูล

    แนะนำวิธีการแปลงรูปภาพ เป็น base64 เพื่อเก็บข้อมูล มีขั้นตอนดังนี้

    1) สร้าง Project ผ่าน Visual Studio 2019 เลือก Blazor Server App

    2) เลือก Framework เป็น .NET 5.0

    3) ติดตั้ง Add-on ชื่อ System.Drawing.Common ผ่านทาง NuGet

    4) เปิดไฟล์ Index.razor จากนั้นเขียน Code ดังนี้

    5) หน้าจอแสดงปุ่ม “การแปลง (ไฟล์รูปภาพ เป็น Base64)”

    6) ผลลัพธ์จากการแปลงไฟล์รูปภาพ เป็น Base64

    หมายเหตุ: นามสกุลไฟล์รูปภาพ (picture.png) ต้องตรงกับ data:image/png;base64 สำหรับแสดงผล

  • โหมดไม่ระบุตัวตน ?

    สวัสดีท่านผู้อ่านทุกท่าน Blog ปิดท้ายของเดือนพฤษภาคม ปี 64 นี้ ผู้เขียนขอเล่าในเรื่องของความรู้เพิ่มเติมในการใช้ Browser ละกันเนอะ

    จากการใช้งานท่องเว็บของเราในแต่ละวัน คาดว่าผู้อ่านแต่ละท่าน คงจะคุ้นเคยกับคำว่า โหมดไม่ระบุตัวตนกันมาบ้างแล้ว

    จริงๆ ในแต่ละ Browser เนี่ย ชื่อเรียกมันก็จะต่างกันนะ เช่น Incognito , Private หรือ Inprivate เป็นต้น ซึ่งทั้งหมดทั้งมวลมันก็คือ โหมดไม่ระบุตัวตนนั่นแหละ

    โหมดไม่ระบุตัวตน คืออะไร ?

    เอาแบบภาษาบ้านๆ พูดง่ายๆ ก็คือ เป็น Feature นึงที่มีอยู่ในทุกๆ Browser โดยโหมดนี้ จะทำให้ Browser ของเราจะไม่จัดเก็บข้อมูลของเว็บที่เราเข้า ไม่มีที่อยู่ ไม่มี cookie ไม่มีข้อมูลที่เราป้อนก่อนหน้า ก็คือไม่มีอะไรเลย ! มันก็คงคล้ายๆ กับการทำให้ Browser ของเราความจำเสื่อมชั่วคราวนั่นแหละนะ

    คราวนี้มาขยายความแบบทางการกันหน่อย

    • Browser จะไม่เก็บประวัติการเข้าใช้งานเว็บไซต์
    • Browser จะไม่เก็บ cookie ของเว็บไซต์ และ ข้อมูลที่กรอกในฟอร์มต่างๆ
    • แต่ถ้ามีการ bookmarks หรือดาวน์โหลดไฟล์ระหว่างใช้งาน ข้อมูลเหล่านั้นก็จะยังคงอยู่ ถึงแม้จะเราจะปิดโหมดนี้ไปแล้ว
    • ผู้ให้บริการอินเทอร์เน็ตยังคงเห็นการเข้าใช้งานของเราตามปกติ
    • IP ที่เข้าใช้งานเว็บไซต์ ไม่ว่าจะโหมดปกติ หรือโหมดไม่ระบุตัวตน ยังเป็น IP เดียวกัน และโหมดไม่ระบุตัวตนมันไม่ได้ซ่อนที่อยู่ IP ของเราให้นะทุกคนนนน !!
    • การใช้งานโหมดนี้ในเครื่องสาธารณะ หรือเครื่องที่มีความเสี่ยง โหมดนี้ไม่ได้ช่วยให้ความเสี่ยงเหล่านั้นลดน้อยลง

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

    แล้วมันเหมาะ หรือไม่เหมาะ กับการใช้งานแบบใดกันละ ?

    ถ้าตามความเข้าใจของผู้เขียน ผู้เขียนเข้าใจว่า

    1. เหมาะกับกรณีที่เราไปใช้งานตามร้าน Internet cafe หรือ เครื่องสาธารณะ ที่เราไม่ต้องการให้ Browser มีการเก็บประวัติการเข้าใช้งาน
    2. เหมาะกับกรณีที่เราต้องการเข้าใช้บริการต่างๆ พร้อมกันมากกว่า 1 account
    3. ข้อนี้ส่วนตัว แหะๆ ผู้เขียนคิดว่ามันเหมาะกับงานของผู้เขียน คือ ใช้สำหรับใช้ทดสอบระบบ หรือเว็บที่เราพัฒนา เนื่องจากจะไม่มีการจำ cache ใด ให้เราปวดหัว ^^
    4. ไม่เหมาะกับกรณีที่เราไปใช้งานในทางที่ไม่ดี เพราะมันยังสามารถโดนติดตามได้อยู่ … อย่าลืมระวังข้อนี้ด้วยนะ !!
    5. หากสิ่งที่ท่านผู้อ่านต้องการ ที่ไม่ใช่แค่ไม่เก็บประวัติ ไม่เก็บ cookie เหล่านี้ ทางผู้เขียนขอแนะนำให้ไปศึกษาใช้การ VPN หรือ Proxy ควบคู่ไปกับการใช้โหมดไม่ระบุตัวตน

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

    ขอบคุณแหล่งข้อมูลข่าวสาร และความรู้ >>> https://www.techhub.in.th/

  • วิธี Install Windows Service (ที่เขียนด้วย VS.Net) ตัวเดียวกันมากกว่า 1 ครั้ง

    ปกติวิธี Install Windows Service ที่เขียนด้วย VS.Net เป็นดังนี้

    InstallUtil.exe MyService.exe

    และคำสั่ง Uninstall Windows Service ที่เขียนด้วย VS.Net เป็นดังนี้

    InstallUtil.exe /u MyService.exe

    อย่างเช่นมีไฟล์ Windows Service ชื่อ KillLoginSession โดยจะมีทั้ง file exe และ file config

    ไว้ใน folder C:\service1 ดังรูป

    เมื่อ run คำสั่งดังนี้

    %WINDIR%\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe c:\service1\KillLoginSession.exe

    แล้วเปิด Services ของ Windows ขึ้นมา จะมี Service KillLoginSession ปรากฎดังรูป

    ซึ่ง Service ตัวนี้จะมี Properties ดังนี้

    คือมี Service name = KillLoginSessionService

    และมี Display name = ALIST Kill Login Session Service

    ถ้าต้องการติดตั้ง Service KillLoginSession เพิ่ม เพราะบางครั้งต้องการใช้ Service เดิมแต่ปรับแก้ค่าที่ config file

    ก็ทำการ copy Service KillLoginSession ไปไว้เพิ่มใน folder C:\service2 ดังรูป

    แล้ว run คำสั่ง

    %WINDIR%\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe c:\service2\KillLoginSession.exe

    จะปรากฎ error ดังรูป

    คือมี service นี้ติดตั้งอยู่แล้ว

    วิธีแก้คือ ให้ใส่ code ดังนี้

    sc create <servicename> binpath= “<pathtobinaryexecutable>” [option1] [option2] [optionN]

    <servicename> คือ ชื่อ service ที่กำหนดขึ้นมาโดยต้องไม่ตรงกับ service ที่ทำงานอยู่

    <pathtobinaryexecutable> คือ ตำแหน่งที่ตั้งของ file service ที่จะทำการ Install

    [option] ไว้สำหรับใส่คำสั่งอย่างอื่นเพิ่ม เช่น Display Name จะมีหรือไม่มีก็ได้

    ใส่ code ตามข้างบนได้ดังนี้

    sc create KillLoginSessionTest binpath=”C:\service2\KillLoginSession.exe” DisplayName=”ALIST Kill Login Session Test”

    จะได้ผลดังรูป

    มี Properties ดังนี้

    คือมี Service name กับ Display name ตามที่ได้กำหนดไว้

    คำสั่งสำหรับ Uninstall ก็คือ

    sc delete <servicename>

    ถ้าต้องการ Uninstall Service ที่สร้างขึ้นก็ใส่ code ดังนี้

    sc delete KillLoginSessionTest

  • สร้างเงาให้กับวัตถุด้วย SmoothShadow

    ปัจจุบันเทรนการออกแบบเว็ปไซต์ต่างๆมักจะมีการใช้เงามาเป็นส่วนประกอบ ทำให้วัตถุชิ้นนั้นมีความโดดเด่น สร้างจุดสนใจของเว็ปไซต์ได้ หรือเพื่อความสวยงาม ดูมีมิติ แต่การที่เราใส่เงาให้กับวัตถุนั้นๆ เราก็จะต้องมาตั้งค่า Box-shadow หลาย parameter กว่าจะได้เงาสวยๆออกมาสักแบบหนึ่ง นั่งสุ่มตัวเลขความเบลอ ความเข้มของเงา หรือระยะห่างของเงา เว้นแค่ไหนดี ตัวเลขแค่นี้เพียงพอแล้วหรือยัง วันนี้ผมจะมาแนะนำ SmoothShadow เครื่องมือหนึ่งตัวที่มีประโยชน์และช่วยลดเวลาในการเขียน code ของเราได้มาก Smooth Shadow เป็นเว็ปไซต์ที่เราสามารถเข้าไปปรับแต่งเงาผ่าน UI บนเว็ปไซต์และสามารถ copy ออกมาใช้งานได้เลย
    หน้าตาของ SmoothShadow จะประกอบไปด้วยกล่องสี่เหลี่ยมอันหนึ่งกลางหน้าจอ ส่วนนี้จะแสดงรูปแบบเงาที่จะแสดงจริงๆบนเว็ปไซต์ โดยจะแสดงเงาตามการตั้งค่าจากแถบข้างขวา และมี CSS box-shadow แสดงไว้สำหรับการ copy ไปใช้งาน และส่วนของแถบข้างขวาจะแสดงแถบ customize เงา เราสามารถปรับแต่งเงาได้โดยการลาก adjustment bar ตามค่าต่างๆได้หรือลากปรับเส้นกราฟการไล่แสงเงาได้ ซึ่งประกอบไปด้วย 5 ส่วนหลักๆ

    Layer of shadows คือจำนวนชั้นของเงา ปกติโดยทั่วไปเราจะใช้งานกันประมาณ 1-2 layer ซึ่งจำนวนของชั้นเงานี้จะสัมพันธ์กับตัวปรับแต่งด้านล่าง เช่นในรูปตั้งไว้ที่ 4 layers หรือเงา 4 ชั้น เราก็จะสามารถปรับกราฟการไล่เงาซึ่งจะแบ่งไว้ 4 ช่วงของแสงไล่ตั้งแต่ขาวไปดำ 4 ระดับ ถ้าปรับเป็น 7 layers ระบบก็จะซอยช่วงเทาเพิ่มมามากขึ้น ก็จะไล่จากขาวไปดำ 7 ระดับ

    Final transparency คือความเข้ม/ความโปร่งใสของเงา ค่ายิ่งน้อยเงาของเราจะยิ่งโปร่งแสง(จางขึ้น) ค่ายิ่งมากเงาของเราก็จะยิ่งทึบแสง(เข้มขึ้น) ส่วนของกราฟจะแสดงถึงการไล่แสงของเงา โดยเราจะสามารถดึงจุดวงกลมสีชมพูได้ เพื่อปรับความโค้งของกราฟ เงาก็จะมีการไล่แสงที่ต่างกันออกไป และส่วนของ Reverse alpha คือการกลับกันของเงา ไล่จากขาวไปดำ

    Final vertical distance คือการไล่แสงในแนวตั้ง ซึ่งจะสามารถไล่แสงได้แค่ทิศทางเดียวคือ แสงจากบนลงล่าง เงาด้านล่างของวัตถุ ยิ่งเพิ่มค่ามากเงาก็จะเพิ่มมาด้านล่างมากขึ้น ค่าลดลงเงาในแนวตั้งก็จะน้อยลง ส่วนกราฟจะแสดงปริมาณของเงาในแต่ละ layer สามารถดึงวงกลมสีชมพูเพื่อปรับแต่งได้

    Final blur strength คือระดับความเบลอของเงา ยิ่งเพิ่มค่าเบลอ เงาของเราก็จะเบลอ ดูนวลตา กลมกลืนมากขึ้น ถ้าลดค่าความเบลอ เงาก็จะยิ่งชัดขึ้นจะเป็นสี่เหลี่ยม แสงแข็ง เห็นชัดเจน ส่วนกราฟจะความเบลอในแต่ละ layer สามารถดึงวงกลมสีชมพูเพื่อปรับแต่งได้เช่นกัน

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

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

    อ้างอิง Smoother & sharper shadows with layered box-shadows | Tobias Ahlin , @brumm (@funkensturm) / Twitter

  • สร้างข้อความแจ้งเตือนด้วย Blazored Toast

    ข้อความแจ้งเตือนการดำเนินการต่าง ๆ ไม่ว่าจะเป็นข้อความ Success, Error, Warning หรือ Information ภายในแอพ เป็นอีกหนึ่งฟังก์ชั่นที่มีการนำมาใช้งานบ่อยๆ เพื่อทำให้ระบบน่าใช้งานมากยิ่งขึ้น ในการเขียนแอพด้วย Blazor ก็มีของฟรีให้ติดตั้งและใช้งานได้เลย ชื่อว่า Blazored Toast ซึ่งเป็น JavaScript ที่ได้รับการ Implement ให้ใช้งานกับ Blazor ได้

    ตัวอย่างการใช้ Blazored Toast

    ก่อนอื่นให้สร้าง Blazor Server App Project ตามขั้นตอนใน Blog(เขียนเว็บแอพแบบ SPA ด้วย Blazor (C#)) ก่อน จากนั้นทำตามขั้นตอนดังนี้

    ติดตั้ง Blazored Toast ผ่าน NuGet package manager

    1. คลิกเมนู Project

    2. คลิก Manage NuGet Packages

    จะปรากฎหน้าจอ NuGet Package Manager ให้ทำดังนี้

    1. คลิก Browse

    2. พิมพ์ Blazored Toast

    3. คลิกเลือก Blazored.Toast 4. เลือกเวอร์ชั่นล่าสุด และคลิก Install

    การตั้งค่า

    1. Register Services โดยการปรับปรุงไฟล์ Startup.cs ใส่โค้ด Using Blazored.Toast และเพิ่มโค้ด services.AddBlazoredToast(); ในฟังก์ชั่น ConfigureServices ดังรูป

    2. เปิดไฟล์ _Import.razor เพิ่มโค้ดดังนี้

    @using Blazored.Toast

    @using Blazored.Toast.Services

    3. ตั้งค่าเริ่มต้นก่อนใช้งานใน MainLayout.razor โดยการเปิดไฟล์ MainLayout.razor และเพิ่มโค้ดดังรูป

    4. อ้างอิง Style sheet ในไฟล์ _Host.cshtml

    <link href=”_content/Blazored.Toast/blazored-toast.min.css” rel=”stylesheet” />

    การนำไปใช้งาน

    1. สร้างไฟล์ใหม่ชื่อ ToastDemo.razor โดยคลิกขวาที่โฟลเดอร์ Pages เลือก Add -> Razor Components ดังรูป

    2. เลือก Razor Component ตั้งชื่อไฟล์ ToastDemo.razor และคลิกปุ่ม Add

    3. เขียนโค้ดใช้งาน โดยให้ inject IToastService ก่อน จากนั้นจึงเขียนโค้ดตัวอย่างโดยให้ Toast ทำงานเมื่อคลิกปุ่ม 4 ปุ่ม เพื่อแสดงข้อความแจ้งเตือน Information, Warning, Success และ Error

    4. กด F5 และเปิด Url  https://localhost:44381/ToastDemo จากนั้นลองคลิกแต่ละปุ่มจะได้ผลลัพธ์ดังรูป

    จะเห็นว่าเราไม่จำเป็นต้องเขียน JavaScript เองก็สามารถใช้งาน Toast ได้ ถือว่าเป็นการประหยัดเวลาในส่วนนี้ และทำให้เราสามารถโฟกัสการเขียนโค้ดในส่วนที่เป็น Core หลักของระบบได้อย่างเต็มที่

  • การใส่ลายเซ็น (Signature) ในเอกสาร Google Forms

    การประยุกต์ใช้ Google forms ในการใช้ทำแบบสอบถาม แบบฟอร์มต่างๆ และให้ผู้กรอกแบบสอบถามสามารถเซ็นชื่อในเอกสาร สามารถใช้เครื่องมือที่ชื่อว่า Signature มาดูกันว่ามีวิธีการอย่างไร

    1. เปิด Google Drive เลือกสร้าง Google Forms เพื่อสร้างแบบสอบถาม ดังรูป

    2. สร้างแบบสอบถาม ตัวอย่างเป็นฟอร์มรายงานตัวออนไลน์ ที่ให้กรอก ชื่อ-สกุล และเบอร์โทร ดังรูป

    3. เมื่อสร้าง Google Forms เรียบร้อยแล้ว ให้ไปสร้าง Google Sheet สำหรับจัดเก็บเป็นฐานข้อมูล ดังรูป
    4. เมื่อสร้าง Google Sheet จะได้ ดังรูป

    5. เมื่อเราสร้างแบบสอบถามเรียบร้อยแล้ว ต่อมาก็มาติดตั้ง Add-ons โดยคลิก “Add-ons” ดังรูป

    6. ส่วนนี้จะเป็น Add-ons ของ Google ทั้งหมด ซึ่งหากใครต้องการเลือก Add-ons ที่มาใช้งานก็มาเลือกจากส่วนนี้ได้ แต่ในที่นี่เราจะใช้ Signature เพื่อนำไปใช้เป็นลายเซ็นของเอกสารของเรา เลือกค้นหาคำว่า “Signature” และคลิกเพื่อติดตั้ง ดังรูป

    7. ต้องการติดตั้ง Add-ons คลิก “Install” ดังรูป
    8. คลิก “CONTINUE” เพื่อติดตั้ง Signature ดังรูป

    9. เลือก User ที่ต้องการติดตั้ง ดังรูป

    10. คลิก “Allow” ดังรูป

    11. ติดตั้งเรียบร้อย ไปใช้งานกันเลย คลิก “NEXT” ดังรูป

    12. เริ่มใช้งานคลิกเลือก “Signature” ดังรูป

    13. คลิก “Start” ดังรูป
    14. คลิก “Login” ดังรูป
    15. เลือก “Multiple Signatures (new)” ดังรูป

    16. คลิก “Submit” ดังรูป

    17. คลิก “Confirm” ดังรูป

    18. การใช้งานแบบสอบถามที่ต้องการให้มีลายเซ็น จะต้องใช้ลิงก์จากการคลิก “Get Link” เท่านั้น ดังรูป

    19. เมื่อนำลิงก์มาใช้งานจะปรากฎดังรูป หากผู้อ่านอยากลองใช้านสามารถทดลองจาก ตัวอย่าง

    20. เขียนลายเซ็น และคลิก “บันทึก” ดังรูป

    21. เมื่อลงลายเซ็นและบันทึกเรียบร้อยแล้ว จะให้ยืนยันอีกครั้ง คลิก “ยืนยัน” ดังรูป

    22. ต้องการกลับไปยังหน้าแบบสอบถาม คลิก “1.คัดลอก” “2.กลับสู่แบบฟอร์ม” ตามลำดับ ดังรูป

    23. เมื่อกลับมายังหน้าแบบฟอร์ม ให้วางที่ลายเซ็น จะได้ลิงก์จากที่ Copy ก่อนหน้า ดังรูป

    24. เมื่อไปดูจาก Google Sheet จะแสดงลิงก์ที่ช่องของ ลายเซ็น ดังรูป คลิกลิงก์เพื่อไปตรวจสอบการกรอกข้อมูล ดังรูป

    25. เมื่อบันทึกเรียบร้อยการแสดงผลจะได้ ดังรูป

    จากตัวอย่างที่ได้ทำมาทั้งหมด เป็นการประยุกต์ที่แบบง่าย ที่ใครๆ ก็ทำได้ ลองทำกันดูนะคะ

  • Flutter : ดึงข้อมูลจาก RESTFul API

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

    ขั้นตอนการติดตั้งบน Windows และเตรียมเครื่องมือสามารถอ่านได้ที่ https://flutter.dev/docs/get-started/install/windows

    ในบทความนี้ผมใช้ Visual Studio Code นะครับโดยติดตั้ง Extention เพิ่มเติมดังนี้

    1. เปิด Visual Studio Code
    2. คลิกเมนู View > Command Palette
    3. พิมพ์ “install”, จากนั้นเลือก Extensions: Install Extensions.
    4. พิมพ์ “flutter” เลือก install
    5. พิมพ์ “dart” เลือก install
    6. เมื่อติดตั้งเสร็จเรียบร้อยจะมีรายการ Extention ดังรูปครับ

    จากนั้นทำการสร้างโปรเจค ดังนี้ครับ

    1. คลิกเมนู View > Command Palette
    2. พิมพ์ “flutter”, จากนั้นเลือก Flutter:New Application Project
    3. จะได้โปรเจคที่มีโครงสร้างไฟล์ดังรูปครับ

    สำหรับท่านใดที่อยากเห็นหน้าตาแอปพลิเคชันเริ่มต้น ให้เปิด USB Debuging ที่มือถือให้เรียบร้อย ต่อเข้ากับคอมพิวเตอร์ จากนั้นที่มุมขวามือล่างของ Visual Studio Code ให้เลือกชื่อมือถือของท่าน จากนั้นกด F5 ได้เลยครับ

    ในการเชื่อมต่อกับ API เราจะต้อง import package เพิ่มโดยพิมพ์คำสั่งที่ terminal > cmd ดังรูปครับ

    จากนั้นแก้ไขในไฟล์ main.dart โดยเริ่มจากการ import ดังนี้ครับ

    import 'dart:async';
    import 'dart:convert';
    
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    

    ด้านล่างเป็น Code ที่เชื่อมต่อ API โดยใช้ http.get เพื่อดึงข้อมูลแบบ Get จากนั้นก็ return ค่า response โดยใช้ประเภท Future เทียบกับภาษาอื่นๆ ประเภทข้อมูลนี้ก็คือ CallBack นั้นเองครับ เอาไว้อ่านค่าที่ได้จาก api เมื่อได้ข้อมูลมาแล้ว (ในอนาคต ไม่รู้ตอนไหน เมื่อเสร็จจะบอก ประมาณนั้น) ซึ่งข้างในเป็นค่าประเภท dynamic ที่ได้จาก jsonDecode

    Future<dynamic> fetchAlbum() async {
      final response =
          await http.get(Uri.parse('https://jsonplaceholder.typicode.com/albums'));
    
      if (response.statusCode == 200) {
        return jsonDecode(response.body);
      } else {
        throw Exception('Failed to load album');
      }
    }

    ตรงนี้เป็นการสร้าง Widget สำหรับแสดงข้อมูลเป็นแถวๆ

    Widget _buildRow(String dataRow) {
      return ListTile(
        title: Text(
          dataRow,
          style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
        ),
      );
    }

    ต่อไปก็จะเป็น Main Function ที่มีการประกาศ state เพื่อเก็บข้อมูลไว้แสดงผลในรูปแบบ ListView เมื่อได้ข้อมูลจาก API มาแล้วนะครับ

    void main() => runApp(MyApp());
    
    class MyApp extends StatefulWidget {
      MyApp({Key? key}) : super(key: key);
    
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      late Future<dynamic> futureAlbum;
    
      @override
      void initState() {
        super.initState();
        futureAlbum = fetchAlbum();
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Fetch Data Example',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
            appBar: AppBar(
              title: Text('Fetch Data Example'),
            ),
            body: Center(
              child: FutureBuilder<dynamic>(
                future: futureAlbum,
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return ListView.builder(//สร้าง Widget ListView
                        padding: EdgeInsets.all(16.0),
                        itemBuilder: (context, i) {
                           //หากไม่สร้าง Object สามารถเรียกใช้งานแบบนี้ได้เลย
                          return _buildRow(snapshot.data[i]["title"].toString()); 
                        });
                  } else if (snapshot.hasError) {
                    return Text("${snapshot.error}");
                  }
    
                  // รูป Spiner ขณะรอโหลดข้อมูล
                  return CircularProgressIndicator();
                },
              ),
            ),
          ),
        );
      }
    }

    เมื่อ Run ดูก็จะได้หน้าตาประมาณนี้ครับ

    เรียกได้ว่าสัมผัสแรกกับ Flutter รู้สึกประทับใจทั้งในด้าน Extension ที่มีใน Visual Studio Code ให้ความรู้สึกไม่ต่างจากการพัฒนาด้วย .Net Framwork เพราะสามารถ Debug ได้ มี Intellisense ครบถ้วน ในด้าน Syntax เนื่องจากเป็นภาษาใหม่ยังต้องทำความเข้าใจอีกพอสมควร ในด้านการออกแบบ UI สำหรับท่านใดที่เคยใช้ React Native มาน่าจะพอเข้าใจ Concept ของ View Widget (เทียบเท่า Component) ได้ไม่ยากนัก ถ้าหากได้นำมาใช้ในงาน Production จริงๆ แล้วจะนำประเด็นที่น่าสนใจอื่นๆมาแชร์กันเพิ่มเติมครับ

    อ้างอิง

    https://flutter.dev/docs/get-started/codelab

    https://flutter.dev/docs/cookbook/networking/fetch-data