Month: August 2021

  • Kiểm soát chi phí sử dụng AWS thông qua việc tạo AWS Budget

    Kiểm soát chi phí sử dụng AWS thông qua việc tạo AWS Budget

    Bạn đã trải nghiệm với các dịch vụ trên AWS, nhưng không may bạn nhận được một bất ngờ không mong muốn trên hóa đơn AWS vào cuối tháng?

    Hoặc có lẽ ai đó trong tổ chức của bạn đã hỏi bạn về việc chi phí AWS tăng cao, có cách nào nhận thông báo chi phí đã sử dụng trên AWS theo hằng ngày được không.

    Đây là việc mà có lẽ hầu hết các kĩ sư cloud đã trải qua.

    AWS Budget sẽ giúp các bạn giải quyết các vấn đề đó. Theo dõi các bước bên dưới để thiết lập nó nhé.


    (1) Đăng nhập vào tài khoản AWS của bạn. Nhập AWS Budgets ở ô tìm kiếm. Sau khi hiển thị kết quả chọn AWS Budgets.

    budget1

    (2) Ở màn hình giao diện Budgets, chọn Create budget.

    budget2

    (3) Ở Step 1, chọn Budget types là Cost budget, sau đó ấn Next step.

    budget3

    (4) Ở Step2, nhập các thông tin budget như hình. Ở chỗ nhập Enter your budgeted amount nên nhập giá trị nhỏ, để Budget sẽ dễ dàng kiểm tra và thông báo cho bạn được thường xuyên. Mình hay để chỗ này tầm 5 hoặc 10$.

    budget4

    (5) Ở Step3, chọn Add an alert threadhold để cài đặt alert.

    budget5

    Trên giao diện Alert, mình sẽ cần nhập thông tin như bên dưới:

    • Threshold: Phần trăm cost sử dụng so với giá trị budget đã set ở Step2 để trigger thông báo. Mình hay để chỗ này tầm 50 hoặc 60.
    • Email recipients: Nhập các email bạn mong muốn để nhận thông báo cost. Các email sẽ cách nhau bởi dấu (,)

    budget6 Sau khi đã nhập xong thì mình chuyển sang step tiếp theo.

    (6) Ở Step4, mình sẽ để default không thay đổi gì cả và chuyển sang step tiếp theo. budget7

    (7) Ở Step5, mình sẽ nhìn lại các cài đặt ở các bước lúc trước. Nếu không có vấn đề gì thì mình chọn Create budget. budget8

    (8) Bạn sẽ nhận email có nội dung như bên dưới. budget9

  • CÁCH KHÔNG NHỚ LỆNH GIT MÀ VẪN DÙNG ĐƯỢC GIT NGON Ơ

    CÁCH KHÔNG NHỚ LỆNH GIT MÀ VẪN DÙNG ĐƯỢC GIT NGON Ơ

    TABLE OF CONTENT

    • Định nghĩa về Sourcetree
    • Cài đặt
    • Một số chức năng <br>

    Bạn có phải là một developer?

    Bạn đã từng tương tác với git qua những câu lệnh trên terminal rồi phải không?

    Bạn có bao giờ cảm thấy phát cáu vì bị lẫn lộn hoặc không nhớ được câu lệnh của git không?

    Nếu câu trả lời là không… vậy thì bye bye bạn nhé, bạn không cần phí thời gian để đọc bài viết này đâu.

    Nếu không phải case trên, xin chúc mừng vì tôi có một giải pháp cho bạn đây.

    SOURCETREE

    Sourcetree là một phần mềm giúp cho developer tương tác với git remote repository thông qua giao diện người dùng. Giao diện này thân thiện và dễ hiểu bởi con người hơn so với những dòng lệnh terminal khô khan. Nó thân thiện đến nỗi kể cả một user không phải developer cũng có thể dễ dàng đọc hiểu và tương tác được là bạn phải hiểu như thế nào rồi đấy.

    Xong phần định nghĩa, tiếp theo đi vào 1 trong những chủ đề chính đã được nêu ra ở title đó là

    CÀI ĐẶT SOURCETREE

    Download đã nào: các bạn download phần mền tại link Download SourceTree for Windows – Free – 3.4.5 (digitaltrends.com) hoặc có thể search với từ khóa download Sourcetree để download trên các trang khác.

    Đợi git được install xong thì click next nhé

    Nhập email mà bạn dùng để kết nối với git vào đây rồi click next nhé

    Tại đây click No nhé

    Vậy là việc cài đặt Sourcetree đã hoàn thành rồi. Bây giờ cùng xem cách sử dụng như nào nhé

    SỬ DỤNG SOURCETREE

    Như đã nêu ở phần định nghĩa, Sourcetree là một phần mềm giúp cho developer tương tác với git remote repository thông gia giao diện người dùng. Từ đó suy ra chúng ta phải kết nối được git trên remote repository với repository trên local thì mới sử dụng được. Vậy bây giờ chúng ta sẽ thực hiện đồng thời 2 việc clone project trên remote repository về máy local và connect remote repository với local repository nhé.

    Mở phần mềm Sourcetree lên và chọn tab Clone.

    Source Path / URL: link clone project lấy từ git

    Ví dụ, link source path lấy từ gitlab

    Destination Path: vị trí lưu project sau khi clone về

    Sau khi nhập đầy đủ các thông tin trên bạn click vào button clone

    Sau một vài giây nếu cửa sổ sau được hiển thị thì chúng ta đã cài đặt thành công.

    Phần BRANCHES là những branch trên local repository.

    Phần REMOTES là những branch có trên remote repository.

    Kết nỗi giữa local và remote repository đã xong, giờ đây bạn có thể thực hiện các chức năng thêm, sửa, xóa nhánh, add, commit, push, pull các nhánh và các chức năng khác của git thông qua chiếc tool có giao diện thân thiện này. Sau đây là ví dụ về một số chức năng của Sourcetree.

    1 Lấy nhánh từ remote repository về local repository

    Chuột phải vào tên nhánh trên remote và chọn checkout

    2 Đẩy thay đổi từ local repository lên remote repository

    Mình thử comment 1 dòng code

    Để add thay đổi click vào dấu cộng nhé

    Mở remote repository ra ta có thể thấy thay đổi mà ta vừa đẩy lên

    3 Tạo nhánh mới và đẩy lên remote repository

    Push nhánh vừa tạo lên remote repository (nếu có thay đổi source trên nhánh vừa tạo thì phải thực hiện commit source trước)

    Nhánh mới đã có trên remote repository

    Trên đây là hướng dẫn cơ bản để cài đặt và sử dụng chiếc tool sourcetree thay cho những dòng lệnh khô khan và khó nhớ ở git terminal. Hi vọng rằng bài viết này hữu ích đối với bạn.

  • IOS/Swift: Cách sử dụng Lazy Sequences để tối ưu hoá performance app ios

    IOS/Swift: Cách sử dụng Lazy Sequences để tối ưu hoá performance app ios

    Article overview

    Nói về Lazy property chúng ta đã quá quen thuộc với lazy var, nhưng bạn đã bao giờ sử dụng lazy property vào sequences ? Bài viết này sẽ giúp các bạn cách sử dụng lazy vào các phép xử lý map, filter, reduce một cách hiệu quả và tối ưu hoá performance app ios.

    Table of contents

    Lazy Sequences là gì ?

    Chúng ta cùng xem ví dụ sau, cho một collection mảng số nguyên từ 1 tới 1000, lọc mảng số nguyên chỉ lấy những giá trị là số chẵn, sau đó nhân đôi từng giá trị lên, rồi trả về kết quả giá trị đầu tiên value lớn hơn 10. Nếu không sử dụng lazy chúng ta có kết quả như sau:

    Image of article

    Nếu sử dụng lazy chúng ta sẽ có kết quả như sau:

    Image of article

    Chúng ta có thể thấy kết quả 2 bên đều = 12, nhưng có sự khác biệt lớn ở trường hợp không sử dụng lazy, phép xử lý filter chạy duyệt hết 1000 phần tử rồi tới phép xử lý map chạy tiếp và tương tự chạy 500 phần tử rồi mới tới phép xử lý tiếp theo. Nhưng nếu sử dụng lazy chúng ta thấy filter chỉ cần chạy 6 lần, map chỉ cần chạy 3 lần.

    Ở trường hợp không sử dụng lazy chúng ta thấy phép xử lý phải chạy hết 1000 phần tử nhưng với điều kiện bài toán của chúng ta thì không cần thiết phải duyệt hết 1000 phần tử, lazy sẽ giúp chúng ta chạy song song các phép xử lý tức là khi filter chạy duyệt 1 phần tử chúng ta có được 1 kết quả của phép filter sau đó kết quả này sẽ dùng chạy tiếp cho phép xử lý map rồi đến first và cứ lặp lại như vậy khi có được kết quả thoả mãn điều kiện bài toán sẽ dừng lại không chạy tiếp. Ở ví dụ này thì chúng ta thấy con số tương đối nhỏ nhưng hãy tưởng tượng nếu chúng ta có một bài toán tương tự nhưng phạm vi mảng tới hơn 1 triệu thì lazy sẽ giúp chúng ta tối ưu rất nhiều số lần duyệt mảng từ đó hiệu suất ứng dụng app sẽ tốt hơn.

    Nếu chúng ta có một collection ít phần tử thì việc sử dụng lazy cũng không mang lại tối ưu nhiều chính vì vậy chúng ta tránh lạm dụng lazy, chỉ nên sử dụng nếu chúng ta có một collection với nhiều phần tử.

    Lazy collections không được cache lại, với lưu ý này chúng ta cùng xem ví dụ sau:

    let modifiedLazyNumbers = (1...4)
        .filter { number in
            print("Even number filter")
            return number % 2 == 0
        }.map { number -> Int in
            print("Doubling the number")
            return number * 2
        }
        
    print("Ket qua ne print lan 1: \(modifiedLazyNumbers.first!)")
    print("Ket qua ne print lan 2: \(modifiedLazyNumbers.first!)")
    
    // Even number filter
    // Even number filter
    // Even number filter
    // Even number filter
    // Doubling the number
    // Doubling the number
    // Ket qua ne print lan 1: 4
    // Ket qua ne print lan 2: 4
    
    let modifiedLazyNumbers = (1...4)
        .lazy
        .filter { number in
            print("Even number filter")
            return number % 2 == 0
        }.map { number -> Int in
            print("Doubling the number")
            return number * 2
        }
        
    print("Ket qua ne print lan 1: \(modifiedLazyNumbers.first!)")
    print("Ket qua ne print lan 2: \(modifiedLazyNumbers.first!)")
    
    // Even number filter
    // Even number filter
    // Doubling the number
    // Ket qua ne print lan 1: 4
    // Even number filter
    // Even number filter
    // Doubling the number
    // Ket qua ne print lan 2: 4
    

    Các bạn có thể thấy sự khác nhau chính là vì lazy collection chỉ chạy các phép xử lý khi có request tới, chính vì vậy giá trị kết quả cuối cùng sẽ không được lưu ở output array, mỗi khi có request tới phép xử lý phải chạy lại.

    • Kết luận Chúng ta có thể thấy lazy collection mang lại hiệu quả tốt với performance nhưng chỉ nên áp dụng nếu chúng ta xử lý bài toán với phạm vi mảng lớn.

    Authors

    [email protected]

  • Gitlab CI/CD cho người mới bắt đầu

    Gitlab CI/CD cho người mới bắt đầu

    CI-CD in gitlab

    Chắc hẳn mọi người đã từng nghe tới CI-CD, rồi thắc mắc không biết nó là gì và chúng ta có thể làm gì với nó? Mình cũng như vậy, thắc mắc ấy đưa mình đến việc viết chuỗi bài này để chia sẻ về những gì mình đã học được về CI-CD.

    Trong bài này thì mình sẽ tập trung vào CI, cũng như cách config file .gitlab-ci.yml và chạy trên share runner của gitlab.

    I. Vậy CI-CD là gì?

    CI (Coutinous Integration) – tích hợp liên tục, là quá trình mà code của chúng ta được build và test trước khi tích hợp vào nhánh chính.

    CD (Continous Delivery) – truyền tải liên tục, là quá trình mà code được triển khai lên môi trường như development hoặc production, và nó diễn ra ngay sau CI

    II. Triển khai CI như thế nào?

    1. Thành phần

    Để có thể triển khai được CI thì trước hết, chúng ta cần biết về 2 thành phần chính cấu thành nên nó. Đó là file gitlab-ci.ymlgitlab runner.

    Mọi người có thể hiểu nôm na nếu gitlab runner như một anh tài xế mà bạn thuê, anh ta rất nhiệt tình, sẵn sàng lái xe đi bất cứ nơi đâu thay cho bạn, nhưng khổ nỗi anh lại không biết đường. Hmm… Làm sao bây giờ? File gitlab-ci.yml lúc ấy xuất hiện như một tấm bản đồ vạn năng.

    File này sẽ được gitlab tự động nhận diện khi bạn commit code lên từ local, và sẽ cấp cho bạn một anh "tài xế" shared runner để đi làm những việc bạn đã vạch sẵn ở trong gitlab-ci.yml.

    Lưu ý:

    Mặc định, gitlab có một số share runner mà người dùng có thể dùng ngay lập tức. Vì vậy, đối với một project vừa và nhỏ, số lượng job cho runner còn ít, thì bạn có thể tận dụng luôn những runner đã có sẵn này. Nhưng với một project lớn hơn, khi mà số lượng cũng như tần suất chạy job ngày càng tăng lên, thì chúng ta nên config riêng một gitlab-runner trên server của mình.

    2. Template

    
    stages:          
      - build
      - test
      - deploy
    
    build-job:      
      stage: build
      script:
        - echo "Compiling the code..."
        - echo "Compile complete."
    
    unit-test-job:
      stage: test   
      script:
        - echo "Running unit tests... This will take about 60 seconds."
        - sleep 60
        - echo "Code coverage is 90%"
    
    lint-test-job:   
      stage: test   
      script:
        - echo "Linting code... This will take about 10 seconds."
        - sleep 10
        - echo "No lint issues found."
    
    deploy-job:     
      stage: deploy  
      script:
        - echo "Deploying application..."
        - echo "Application successfully deployed."
    

    Templete cho một file gitlab-ci.yml

    Chúng ta sẽ cùng nhau đi qua một lượt xem nó có ý nghĩa gì nhé!

    Đầu tiên là stages: đây sẽ là khi chúng ta định nghĩa ra các giai đoạn mà trong pipeline, hay nói cách khác là các job mà runner sẽ phải thực hiện. Như đa số project, workflow sẽ bao gồm 3 giai đoạn, đầu tiên chúng ta sẽ tạo ra một bản build của project, tiếp sau đó sẽ test, và khi đã qua được các bước trên thì sẽ deploy lên môi trường development, staging hay production.

    stages:    
      - build
      - test
      - deploy
    

    Tiếp theo, chúng ta sẽ đi cụ thể tới các build stage nha (Các giai đoạn sau cũng tương tự).

    • build-job là tên của job, cái này các bạn có thể tự thay đổi theo ý mình nhé.
    • stage chỉ ra job này đang nằm trong giai đoạn nào trong 3 stages mà chúng ta đã định nghĩa trước ở trên.
    • script là những câu lệnh mà chúng ta sẽ chạy trong job này.
    build-job:      
      stage: build
      script:
        - echo "Compiling the code..."
        - echo "Compile complete."
    

    Ngoài ra thì còn rất nhiều những thông tin config khác mà các bạn có thể tìm ở đây nha!

    Và như bạn đã thấy ở templete trên, thì một pipeline có thể có nhiều giai đoạn và một giai đoạn có thể chứa nhiều job khác nhau và các job đó có thể được thực hiện song song.

    3. Ví dụ

    Mình sẽ lấy ví dụ từ bẳng việc check lint của một project nodejs nha!

    Bước 1: Chúng ta sẽ phải cài đặt eslint và babel-eslint cho project của mình.

    npm install eslint babel-eslint --dev
    

    Bước 2: Tạo file .eslintrc để config lint rule mà mình muốn:

    {
      "env": {
        "node": true,
        "es6": true,
        "mocha": true
      },
      "parser": "babel-eslint",
      "parserOptions": {
        "ecmaVersion": 2017
      },
      "extends": "eslint:recommended",
      "rules": {
        "comma-spacing": [
          "error",
          {
            "before": false,
            "after": true
          }
        ],
        "indent": [
          "error",
          2,
          {
            "SwitchCase": 1
          }
        ],
        "linebreak-style": [
          "error",
          "unix"
        ],
        "quotes": [
          "error",
          "double"
        ],
        "semi": [
          "error",
          "always"
        ],
        "no-unused-vars": [
          "off"
        ],
        "no-console": 0
      }
    }
    

    Bước 3: Thêm script cho việc check lỗi và fix lỗi lint trong file package.json

    Trong dấu "{}" ở câu lệnh lint là các folder mà mình muốn check lint, các bạn có thể để folder khác cho phù hợp với project của mình nhé!

    Bước 4: Chạy lần lượt hai câu script trên và đẩy code lên git.

    Bước này là để trước khi các bạn check xem những nhánh phụ merge vào có đúng theo rule lint mình đã định nghĩa không, thì nhánh chính của mình đã thỏa mãn những rule đó từ trước.

    Bước 5: Tạo file .gitlab-ci.yml

    
    
    stages:   
      - checklint
    
    lint-test-job: 
      stage: checklint    
      image: node:12.18-alpine 
      only:           
        refs:
          - merge_request
      script:
        - npm install eslint babel-eslint
        - npm run lint
    
    

    Ở đây sẽ có 2 từ khóa mới:

    image: dùng base image là node:12.18-alpine để tạo một node instance chạy các câu lệnh mình định nghĩa ở phần script

    onlyrefs: giới hạn việc chạy job này chỉ khi có merge request

    Bước 6: Tách nhánh mới, đẩy lại code lên gitlab và tạo merge request

    • Đây là ở merge request trước khi chúng ta đẩy file gitlab-ci.yml lên remote repo

    • Sau khi đẩy file gitlab-ci.yml lên

    Bây giờ nếu như mọi người thấy biểu tượng pipeline running như hình 2 ở trên là mình đã thành công rồi nha!

    Từ bây giờ mỗi khi bạn đẩy code mới lên remote repository thì gitlab runner sẽ tự động chạy test lint cho chúng ta!

    Nếu thích bài viêt này thì các bạn nhớ like and và share để ủng hộ mình có động lực viết phần tiếp theo về gitlab runner và CD nha <3

    P/s: Đây là bài viết đầu của mình nên không thể tránh khỏi những thiếu sót, có gì mong được mọi người bỏ qua và góp ý cho mình nha! Cảm ơn mọi người nhiều <3

  • ANT DESIGN – Điều gì khiến thư viện này vượt “mặt” Material-UI của Google?

    ANT DESIGN – Điều gì khiến thư viện này vượt “mặt” Material-UI của Google?

    anhbia Ant Design – Điều gì khiến thư viện này vượt "mặt" Material-UI của Google?

    Nếu bạn là một Front-End developer và thường xuyên sử dụng những thư viện UI cho các dự án của mình thì chắc chắn các bạn đều sẽ biết đến những cái tên rất quen thuộc như Material-UI (MU) do Google phát triển hay Bootstrap do hai kỹ sư tại Twitter làm ra, tất cả đều là các thư viện hỗ trợ thật sự tuyệt vời về tính Responsive cho các màn hình thiết bị khác nhau, các components Javascript có sẵn.

    Tuy nhiên, bạn biết đó, thời nào cũng sẽ có những anh hùng hào kiệt, một cái tên khác đang phất lên rất nhanh và cũng nhanh chóng được yêu thích của cộng đồng developers React Front-End đó là ANT DESIGN (ANTD) đạt 73,1k sao trên github và đang vượt lên so với Material-UI (70k sao). Có lẽ điều đầu tiên bạn sẽ biết về ANTD đó là thế lực tạo ra nó – Alibaba.

    Vậy ANTD có gì mà có thể vượt lên so với MU – một thư viện UI/UX do Google phát triển rất lâu trước đó?

    Tổng quan bài viết

    ANT DESIGN và ANT DESIGN PRO

    Bạn có phải lần đầu biết đến ANTD? Có khoảnh khắc nào trong những giây phút "chilling" bạn search google với keyword "ant design là gì?" nhưng chắc có lẽ bạn vẫn chưa biết tới cái tên ANT DESIGN PRO nếu chưa bao giờ sử dụng ANTD.

    ANT DESIGNANT DESIGN PRO là hai phần khác nhau của ANTD.

    ANT DESIGN: Dành cho những components đã được viết sẵn, bạn chỉ cần import và tái sử dụng lại những components đó, ví dụ như Carousels, Form, Upload, Modal, Badge,…etc.

    • Điều khiến ANTD trở nên đặc biệt là Document cực kì rõ ràng, các api của components đều có demo và ví dụ đi kèm, bạn có thể xem code trong codeSandbox/codepen/stackblitz. Một số components được ANTD viết với TypeScript, cùng nghía qua một "tí tẹo" document của ANTD nha:

    document

    Nếu những điều này chưa khiến bạn phải "quaoooo" thì hãy xem tới các props của ANTD và khả năng hỗ trợ Customize Base component của nó.

    Bạn biết đấy, đôi khi làm việc với các thư viện, bạn sẽ muốn thay đổi các base components để đáp ứng như cầu của khách hàng/dự án và props của ANTD sẽ là công cụ đắc lực giúp bạn dễ customize hơn và viết code tối giản hơn nhiều.

    Vậy còn ANTD PRO thì sao?

    ANT DESIGN PRO thì khác, nó là một theme gần như hoàn chỉnh dành cho các trang Admin, CMS ( Control Management System). Bạn có thể thấy được những gì mà ANTD PRO có thể hỗ trợ bạn qua <a href="https://preview.pro.ant.design/" target="_blank">website preview</a>.

    • Cài đặt ANTD PRO với npm hoặc yarn:

    install

    Sau khi cài đặt, bạn sẽ thấy rằng điều bạn cần làm là chọn những phần components bạn muốn và bắt đầu gọi API từ phía Back-end hoặc gỉa lập API với file _mock.js có sẵn của ANTD PRO luôn mà không cần phải đau đầu suy nghĩ về UI hay viết code làm sao. Rất tiện lợi đúng không?

    Chưa hết, ANTD PRO còn mang đậm tính "all-in-one", chỉ 1 lần cài đặt mà bạn có thể sử dụng luôn:

    1. Webpack (Webpack giúp tăng tốc độ cho dự án, đóng gói thành một file duy nhất,…)

    2. Less ( một CSS preprocessor giống với SCSS )

    3. Sự tuyệt vời đến từ UmiJS – cái tên bạn … chưa nghe qua bao giờ đúng không?

    UmiJS: chính là một thư viện Plugin enterprise-level cho React. Nghe thì xa tầm với nhưng ý lại nằm trong lời, UmiJS bao hàm bên trong là redux-saga, gọi api thay vì với Axios thì sẽ là Request.

    Ai cũng biết Axios hỗ trợ việc gọi api request tốt và "uy tín" như thế nào nhưng UMI-Request lại hơn thế đấy, cùng xem bảng so sánh của umi-request với Axios và Fetch sau:

    install

    Bạn đã bị thuyết phục chưa? Nếu chưa thì hãy tới mục số II nha.

    WEB COMPONENT vs MOBILE COMPONENT

    Giống như sự hỗ trợ của ANTD dành cho web version thì ANTD cũng đã dành điều đó cho cả <a href="https://mobile.ant.design/docs/react/introduce" target="_blank">mobile version</a>.

    Version dành cho Mobile là cái mà Material UI chưa làm nhưng ANTD đã làm và còn đầu tư chất lượng cho document của mobile không kém cạnh gì cho web version.

    => Có thể thấy ANTD là một thư viện UI được đầu tư, phát triển mạnh mẽ và đến đây chúng ta cũng có thể hiểu tại sao số sao trên github dành cho ANTD lại vượt nhanh hơn cả MU.

    Tips và ví dụ customize sử dụng PROPS của ANTD

    Từ mục I và II chúng ta đều được biết tới sự hỗ trợ "xịn xò" cho các developers React Front-End nhưng lại không biết nhược điểm của nó là gì và tips để sử dụng ANTD hiệu quả đúng không?

    Nhược điểm của ANTD:

    1. Document của ANTD vẫn còn một vài chỗ viết bằng tiếng Trung, đặc biệt là Document của ANTD PRO/UMIJS

    => Việc tiếng Trung còn nhiều khiến cho các developers gặp khó khăn khi muốn customize components hoặc đọc về API/Props hỗ trợ.

    1. Trên các trang như Stackoverflow, dev.to,… có ít các bài được giải thích hoặc hỗ trợ cho ANTD.

    => Vậy nên khi gặp bug, các bạn cũng có thể mất kha khá thời gian để sửa và kiểm tra lại.

    1. Tuỳ chỉnh Theme

    => Khả năng tuỳ chỉnh theme của ANTD không mạnh bằng MU khi chỉ có thể thay đổi các mặc định về màu sắc, kích thước,…

    Tips khi sử dụng ANTD:

    1. Hãy đọc kĩ các phần API, props của ANTD hỗ trợ.

    => Có thể khi đứng trước một vấn đề mà vấn đề đó cần customize một base component của ANTD mà bạn chưa có ý tưởng bắt đầu làm như thế nào, hãy đọc kì api/props mà component đó có, có thể bạn sẽ nhận ra mình đỡ bỏ lỡ một sự kết hợp hay ho đó.

    1. Hãy viết style bằng less

    => ANTD cũng không quá khắt khe cho việc viết style như khi dùng bootstrap nhưng để tối ưu việc style, responsive và sự tương thích với các trình duyệt khác nhau thì hãy viết với less nhé.

    • Ví dụ về customize sử dụng PROPS của ANTD

    Customize dropdown của <Select> với infinity scroll

    Có 5 bước chúng ta cần làm (nguồn: <a href="https://codesandbox.io/s/antd-select-infinite-scroll-90shp?file=/index.js:1649-2578)" target="_blank">click here to open codeSandbox</a>)

    Bước 1: Import các phần cần thiết và viết một component:

    import React from "react";
    import ReactDOM from "react-dom";
    import "antd/dist/antd.css";
    import "./index.css";
    import Select from "antd/lib/select";
    const { Option } = Select;
    
    class LazySelect2Input extends React.PureComponent {
      render() {
        return <div className="App"></div>;
      }
    }
    

    Bước 2: Viết hàm để render mock data:

    // Fetch at most 200
    // On scroll uses a queue
    // Pop
    
    const children = [...Array(20).keys()];
    const range = (start, stop, step) =>
      Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + i * step);
    const handleChange = (value) => console.log(`selected ${value}`);
    

    Bước 3: Khai báo constructor với props, state:

     constructor(props) {
        super(props);
        this.state = {
          lastScrollPos: 0,
          loadingMore: false,
          options: children,
          min: 0,
          search: undefined
        };
      }
    

    Bước 4: Viết function để thực hiện infinity scroll:

    handleScroll = (event) => {
      event.stopPropagation();
      let delta;
      const { options, min, loadingMore } = this.state;
      let newMin = min;
      if (event.wheelDelta) {
        delta = event.wheelDelta;
      } else {
        delta = -1 * event.deltaY;
      }
    
      if (!loadingMore) {
        if (delta < 0) {
          newMin = min + 1;
          if (newMin + 10 >= Math.max(...options)) {
            // Fetch more items when the list is exhausted.
            this.handleFetchMore(Math.max(...options) + 1, 10, newMin);
          }
        } else if (delta > 0 && min >= 1) {
          newMin = min - 1;
        }
    
        return this.setState({ min: newMin });
      }
    };
    
    handleFetchMore = (offset, limit, min) => {
      this.setState(
        {
          loadingMore: true,
          options: [...this.state.options, ...range(offset, offset + limit, 1)],
        },
        () =>
          this.setState({
            loadingMore: false,
            min,
          })
      );
    };
    

    Bước 5: Render và Return:

    render() {
        const { loadingMore, min, options, search } = this.state;
        let currentOptions = options;
        const extraProps = {};
    
        if (search) {
          currentOptions = options.filter(v => v.toString().indexOf(search) >= 0);
          extraProps.open = true;
          extraProps.key = "searching";
        }
        return (
          <div className="App">
            <Select
              mode="multiple"
              style={{ width: "100%" }}
              onChange={handleChange}
              // dropdownRender, filterOption, defaultActiveFirstOption
              // are props for customize of ANTD
              dropdownRender={menu => <div onWheel={this.handleScroll}>{menu}</div>}
              loading={loadingMore}
              onSearch={search => this.setState({ search })}
              filterOption={false}
              defaultActiveFirstOption={false}
              {...extraProps}
            >
              {currentOptions.slice(min, min + 10).map(i => (
                <Option key={i} value={i}>
                  {i}
                </Option>
              ))}
            </Select>
          </div>
        );
      }
    

    => Có thể thấy các props dropdownRender, filterOption, defaultActiveFirstOption đã hỗ trợ cho chúng ta bắt sự kiện scroll khi tag Select xổ xuống các option để việc thực hiện tải thêm data khi người dùng cuộn xuống phần đáy của tag select (popup container).`

    Tổng kết

    Chúng ta đã có một bài đọc khá dài về ANT DESIGN. Hi vọng những gì mình chia sẻ có thể giúp bạn hiểu thêm về nó và có thể dễ dàng bắt đầu sử dụng hơn nha. Cảm ơn các bạn đã đọc.

  • How to build an end to end scalable visual search system with AI Computer Vision and AWS

    How to build an end to end scalable visual search system with AI Computer Vision and AWS

    With the rise of e-commerce, online retail, visual search is a rapid trend because they are largely driven by visual content. In this article, I will share with you guys the visual search project that was built in 2018 for my Japanese partner.

    What are the problems?

    My partner is one of the biggest retailers of toys, clothing, and baby product in Japan. They have lots of stores all over the world. On holiday, the long queues of customers wait to checkout happen in lots of stores. So to solve this problem, they decide to apply the new store like Amazon Go, no queues, no checkout, just walk out of the store. In short, this not only improves their customers’ buying experience but also maximizes revenue growth.

    Why do we need Visual Search?

    provider

    My partner has lots of providers. Each of them distributes different types of products. The products will be updated frequently by weekly, monthly, or yearly. So visual search system needs to be updated the same as the scale of products.

    What is the core technology here?

    provider

    By the time I started this project in 2018, Triplet loss had proved efficient in Face Recognition. With that starting point, we decide to apply Triplet Loss as our core visual search technology because our problem is quite similar to Face Recognition. To get the highest accuracy and make the system scalable, we classify products into different categories and subcategories because Triplet loss will have the best performance when all the products are in the same domain property. For example, when you do Face Recognition, all the images are facial, right? Then in our problem, we train all the toys that have a similar domain with one AI Model. For example, the Lego toys will be trained together, the Figures will be trained together, and so on. And not only that, one of the most advantages here is when new products need to be updated, our system don’t need to re-training the whole model, the whole process which can reduce the cost. Normally, it’s very costly and takes us lots of time for training an AI model.

    The architecture overview

    provider As you can see, we have two main components: Serving and Training. The training component is built to fit with Admin, Operator, Providers, and Developers with different purposes. For any Machine Learning production, one of the most challenging parts is how your system can run automatically with the minimum of human interference. The serving component will host all APIs needed for our web app and mobile app.

    Triplet Loss training strategy

    Our strategy here to get the best model is: Clustering the categories to group categories with similar type samples. For each anchor image, we will pick 1 hardest positive, 1 hardest negative among the image batch. We will keep multiple anchors and compute the centroid of anchors for each category. To reduce computation cost we will first match with anchor centroids. If the distance is lower than TL and higher than TH, we will give an immediate decision that the product exists and doesn’t exist respectively. We are using two thresholds. Lower threshold, TL, and higher threshold And in the end, our model has very good accuracy, for the trained data, the accuracy is over 99 percent and 97 percent for un-trained data respectively.

    Alt text

    Demo

    A Video Worth a Million words, so, please see this demo below on how we increase customer engagement with AR and AI.

    Alt text

    Conclusion

    This article is focused on sharing the overview flow, architecture, and an example use case when AI is applied in the real world. If you are curious more about the technology, the development, or the business side, please follow my next articles.

  • Software Architecture: Bắt đầu từ đâu? – Part 3 Soft Skills  – Continuous Delivery

    Software Architecture: Bắt đầu từ đâu? – Part 3 Soft Skills – Continuous Delivery

    Trong phần trước, mình đã nói về Soft Skill — Decision, trong phần này sẽ đề cập tới một loại khác mà sẽ gây nhiều tranh cãi: Continuous Delivery.

    Continuous Delivery, hãy nói về mặt khả năng, chính xác hơn là điểm khác biệt với Manual Delivery ở 3 yếu tố: an toàn, nhanh chóng và bền vững (hoặc dùng từ Việt một chút là ổn định).

    Trong bài viết này sẽ không đánh đồng Continuous Delivery với các kỹ thuật automate, mà mọi người hay khá nhầm lẫn với việc Automation Delivery (một trong những kỹ thuật của CD). Dù sao thì, mình chỉ muốn xem xét về mặt văn hóa trong dự án phần mềm.

    Tại sao cần Continuous Delivery?

    Thời gian — tất nhiên rồi, ai cũng muốn đưa những tính năng mới nhất cho người dùng một cách nhanh nhất, đưa hệ thống trở lại khi downtime nhanh nhất (Mean Time To Repair) đồng nghĩa với việc business được duy trì, tiền kiếm được không bị ngừng trệ.

    Hãy xem xét 2 loại thời gian:

    • Lead time: lượng thời gian từ khi bắt đầu và kết thúc của một công việc trong quy trình
    • Cycle time: khoảng thời gian mà giữa 2 công việc liên tiếp được kết thúc, hay còn có thể hiểu là Deployment Frequency cho dễ hiểu

    Continuous Delivery Pipeline sẽ được hình dung như này

    image

    Còn đây là Lead time image

    Đây là Cycle time nè image

    Vậy thời gian bao nhiêu là đủ?

    image

    Credit: Forsgren PhD, Nicole. Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations (Kindle Location 564). IT Revolution Press. Kindle Edition.

    Nhìn chung thì khi chúng ta cố gắng tăng tần suất deploy chúng ta sẽ có thể giảm MTTR, có nghĩa chúng ta sẽ không tạo ra một sản phẩm có tính bền vững cao (robustness — như cách tiếp cận truyền thống), khi đó khả năng tự phục hồi sau lỗi (resilience) của sản phẩm được tăng lên (một cách tự nhiên), cùng với đó là giảm khả năng xảy ra lỗi vì gần như khi tăng tần suất deploy đến hằng ngày hoặc nhiều lần một ngày sản phẩm sẽ gần như lúc nào cũng sẵn sàng để đưa lên môi trường production (production ready).

    Như vậy chúng ta sẽ có một mô hình:

    1. Continuous Integration:

      • Integration sớm và thường xuyên
      • Mọi người cần đồng bộ trunk (ý nói đến phiên bản được deploy) hằng ngày
    2. Continuous Deployment:

      • Điều này có để dễ dàng đạt được, khi source code ở trunk khá ổn định và Deploy chỉ là stage cuối cùng của Continuous Integration, như vậy việc phát hiện các lỗi và fix chúng cũng nhanh hơn, kể cả khi bạn có những thành viên không quá giỏi trong tay. Với các công cụ khác nhau như Sonarquebe hay chính Unit Test sẽ hỗ trợ developer tạo nên những sản phẩm tốt hơn.
    3. Continuous Delivery:

      • Sau 2 vấn đề bên trên source code ổn định, deploy thường xuyên, bản vá được xử lý nhanh chóng ít ảnh hưởng, cuối chùng chúng ta có một phần mềm luôn ở trạng thái sẵn sàng.

    Nhưng

    Có thể các bạn sẽ nghĩ hay có câu hỏi như này: Lỗi vẫn xảy ra thì sao?

    Ồ thì tất nhiên lỗi vẫn xảy ra, nhưng chúng ta sẽ có lỗi ở những thời điểm sớm hơn. Hầu hết mọi người sẽ gặp các vấn đề thường xảy ra khi chúng ta tích hợp (các thành phần trong phần mềm với nhau), điều này khá khó chịu, và mọi người sẽ có xu hướng trì hoãn. Tuy nhiên hãy nghĩ đến trường hợp này: trong ví dụ ở phần trước giả sử client cứ làm theo requirement hoặc UX/UI được cung cấp, backend thiết kế hoàn toàn khác tuy nhiên vẫn đầy đủ thông tin, client sẽ phải call nhiều API cho màn hình thay vì 1 API như trong suy nghĩ, điều đó dẫn đến việc một trong 2 cần thay đổi, việc này tốn khá nhiều công và tiềm ẩn rủi ro. Vậy nên khi tích hợp sớm chúng ta sẽ làm việc trơn tru trong quãng thời gian còn lại và sẵn sàng release thay vì dành vài tuần hoặc vài ngày cuối để thay đổi toàn bộ interface.

    Bring the pain forward

    Hay đầy đủ là if it hurts, do it more often, and bring the pain forward.

    image

    Quay lại vấn đề giữa mobile và backend, giả sử sẽ vẫn có những khác biệt về suy nghĩ xây dựng interface giữa 2 bên, tuy nhiên chúng ta đã làm nó sớm, và chia nhỏ nó ra và bằng cách backend thường xuyên release phiên bản API mới (chưa nói đến việc backward compatibility nhé), mobile sẽ tích hợp tốt hơn, nhanh hơn vì những thay đổi khá nhỏ và dễ dàng đáp ứng. Trong khi đó mobile team cũng build ra app thường xuyên hơn, tester có thể verify nhanh hơn, sản phẩm được ổn định hơn, ít tiềm ẩn lỗi hơn.

    Điều này khá giống trong lý thuyết phát triển phần mềm, chi phí sửa lỗi càng nhiều cho các lỗi ở giai đoạn muộn của dự án.

    Continuous Delivery bằng cách nào

    image

    Continuous Delivery cho chúng ta một cách tiếp cận khác về việc quản lý dự án, chúng ta có thể định nghĩa lại done không phải là code xong mà là được delivery thành công. Toàn bộ quá trình nên sử dụng đối đa các nền tảng tự động như Unit-test, Automation Test, điều đó làm tăng tốc độ feedback trên các bản vá của source code cũng như infrastructure. Điều này càng quan trọng hơn khi chi phí End-to-end testing càng ngày càng lớn, chúng nên được thay thế bằng các danh mục testing như dưới đây (multi-faceted testing portfolio), điều này càng quan trọng hơn trong thế giới hiện nay khi Devops là xu hướng, và các quyết định về release càng ngày càng gắn liên với tình huống về mặt nghiệp vụ thay vì sự quyết định của một đội quản lý về vận hành.

    Practice Quantity Frequency Duration Environment
    Unit Testing 100 to 1000+ Per build < 30s total Local and Build
    Acceptance Testing 10 to 100+ Per build < 10m total Local and Build
    Exploratory Testing 10 to 100+ Per build Timebox Local and 3rd Party
    Contract Testing ~20 Per 3rd party deploy < 1m 3rd Party
    Smoke Testing ~5 Per deploy < 5m All
    Monitoring 10 to 100+ Always < 10s All
    Anomaly detection 10 to 100+ < 1m < 10s All
    Adaptive architecture N/A Always N/A All

    Như vậy có thể thấy là việc xử lý Continuous Delivery gần như không mang tính kỹ thuật mà mang tính định hướng về văn hóa làm việc cho dự án nhiều hơn, chính vì thế tại sao mình lại đặt nó là Soft Skill.

  • Software Architecture: Bắt đầu từ đâu? – Part 2 Soft Skills – Decision

    Software Architecture: Bắt đầu từ đâu? – Part 2 Soft Skills – Decision

    Như ở phần trước mình đã nói về các Soft Skills mà mình cho là yếu tố khác biệt giữa Developer và Software Architecture.

    Decision

    Về cơ bản thì với vai trò là Software Architecture bạn sẽ cần quyết định nhiều thứ.

    Đầu tiên hãy kể đến chính Kiến trúc, thứ mà bạn đang xây dựng.

    Nếu bạn có vài trò là người quyết định kiến trúc, bạn gần như sẽ là người đảm bảo duy nhất cho sự toàn vẹn của hệ thống, về mặt khái niệm thôi nhé. Tức là bạn sẽ là người đầu tiên hình dung ra hình dáng của hệ thống và thông thường những quyết định kiểu này sẽ được đặt ra trong những phase đầu tiên của phần mềm.

    Nhiều người sẽ thắc mắc nếu quyết định đó là sai, thực tế thì những quyết định bởi những người có kinh nghiệm sẽ thường phù hợp với tình hình ở thời điểm đó.

    Một câu hỏi khác: tại sao chỉ một người đảm bảo duy nhất cho sự toàn vẹn? Thông thường ở một mức độ nào đó, trong một đội dự án, Architect sẽ có sự hiểu biết tốt nhất về hệ thống cũng như các hard skill khác, và họ sẽ có một cách hình dung khá chung với những người có trình độ tương đương. Tuy nhiên việc này sẽ dẫn tới việc nghẽn cổ chai ở Architect, vậy nên việc này sẽ dẫn tới một khái niệm khác là Architectural Knowledge Management hay Software Architecture Knowledge Management (điều này giải thích tại sao các team thường có wiki hay những bản tài liệu được chia sẻ về kiến thức) Read more

    Vậy thực sự có thể nói họ sẽ làm những việc như này

    • Thiết kế kiến trúc
    • Định ra các nguyên tắc để quyết định về mặt công nghệ.

    Ví dụ: Bạn sẽ cần đưa ra quyết định về việc sử dụng API Gateway để làm một endpoint duy nhất cho cả mobile và web hay sẽ sử dụng Backend for Frontend trong mô hình microservice.

    Ồ thì dẫn đến một điều bạn cứ trả lời 2 câu hỏi dưới đây bạn sẽ biết là bạn có đang đưa ra các quyết định về mặt kiến trúc hay không:

    • Mức độ ảnh hưởng có ở toàn hệ thống hay không? Độ khó để implement quyết định đó?
    • Quyết định đó có giúp team quyết định về mặt công nghệ hoặc chỉ định cho họ.

    Một công việc hằng ngày bạn có thể thấy mấy tên Architect hay làm đó là ngồi tìm hiểu thực sự bạn đang làm gì trong dự án, bạn có hiểu vấn đề chung của dự án hay không, tìm các vấn đề quan trọng và giải quyết trước khi mọi thứ trở nên tồi tệ (chỗ này định ghi là một bãi rác).

    Trong một dự án IoT gần đây mình có tham gia, Architect của dự án đã quyết định cho team backend dừng công việc để chỉnh trang lại kiến thực chung.

    Hoặc đơn giản hơn, Architect có thể ngồi với developer để tìm ra một số đoạn code gây lock hệ thống, buổi chiều có thể sharing với dự án về những thứ khá phi kỹ thuật như việc những đoạn code của họ sẽ gây ảnh hưởng đến chi phí AWS.

    Bạn có thể thấy rằng việc bạn không thể hình dung dự án đang làm ra sản phẩm như nào rất nguy hiểm, giả như rằng bạn khăng khăng bạn sẽ phải code lại toàn bộ luồng OAuth2.0 cho toàn bộ các microservice để dùng chung một endpoint, nhưng thực tế là hoàn toàn bạn có thể để chúng riêng rẽ, điều quan tâm duy nhất là dùng chung Identity Pool, việc làm đó có thể khiến những team khác trong dự án bị trễ lịch đến hàng tuần.

    Tính đúng đắn của quyết định — Justifying decisions

    Rõ ràng quyết định đã được đưa ra, điều đó là tất yếu trong hoàn cảnh đồng hồ của dự án bắt đầu tính giờ. Tuy nhiên thì không phải quyết định nào cũng được chấp nhận (chỉ là được chấp nhận nhé, chưa bàn đến tính đúng sai)

    Hãy quay trở lại ví dụ bên trên về API Gateway và Backend for Frontend, đây thực chất là kết quả sau khi Architect đã xem xét rõ ràng (đúng hoặc sai), còn quá trình thì sao.

    Để bất đầu hãy xem xét kịch bản tại sao lại có sự lựa chọn:

    Giả sử bạn đang xây dựng một cửa hàng trực tuyến sử dụng Microservice và bạn đang triển khai trang product detail. Bạn cần phát triển nhiều phiên bản của giao diện người dùng chi tiết sản phẩm: cho cả web browser dưới dạng HTML5 hoặc Rest API để phục vụ cho mobile.

    Giao diện này cần có nhiều thông tin: thông tin về sản phẩm, số lượng, lịch sử mua, các tùy chọn mua, các sản phẩm thường được mua cùng (một dang recommendation), review, rating của người bạn…

    Và chúng ta có các service sau:

    • Product Info Service
    • Pricing Service
    • Order service
    • Inventory service
    • Review service
    • Recommendation service Như vậy trang product detail cần tất cả các service trên

    Bài toán được đặt ra là:

    Làm cách nào để client của một ứng dụng Microservices truy cập vào các dịch vụ riêng lẻ?

    Quyết định

    Api Gateway

    Sử dụng API Gateway là entrypoint duy nhất cho tất cả các client. API Gateway xử lý các yêu cầu theo một trong hai cách.

    • Một số yêu cầu chỉ đơn giản là proxied/routed đến service thích hợp.
    • Hoặc thay vì cùng cấp API kiểu one-size-fits-all, API Gateway cung cấp các API khác nhau cho từng client. image

    Backend For Frontend

    BFF tạo ra các Gateway riêng rẽ cho từng loại Client. image

    Các điều kiện và ràng buộc (Conditions and Contraints)

    Có nhiều yếu tô cần tính tới trong trường hợp này, nhưng mình sẽ tạm thời bỏ qua những vấn đề mang tính chủ quan của một dự án phần mềm: Con người (mặt bằng chung của team, broken comb, T-Shaped, …), process, stakeholder (rất nhiều khách hàng can thiệp vào architecture), mặc dù trên thực tế Architect thường nắm vai trò Technical Lead luôn nên sẽ cần cân nhắc. Hãy đi vào vấn đề kỹ thuật thôi.

    • Thường thì API do microservices cung cấp thường khác với những gì Client cần, về chi tiết nhé. Microservices thường cung cấp các API chi tiết, có nghĩa là client sẽ cần tương tác với nhiều service. Ví dụ, như được mô tả ở trên, client cần thông tin chi tiết về sản phẩm và cần tới nhiều dịch vụ.
    • Các Client khác nhau sẽ cần dữ liệu khác nhau. Ví dụ phần Recommendation cho phiên bản web sẽ nhiều hơn và có nhiều hành động hơn phiên bản API cho Mobile.
    • Đường truyền điện thoại với 3G, 4G sẽ khác với các trình duyệt ở trên máy tính được kế nối qua cáp quang cả về băng thông lẫn tính ổn định, thậm chí là chi phí. Có nghĩa là chúng ta có thể tăng số lượng request từ phía trình duyệt mà không ảnh hưởng quá nhiều đến trải nghiệm của người dùng lẫn chi phí băng thông, ngược lại với ứng dụng mobile.
    • Số lượng phiên bản của service và thông tin (host:port) thay đổi động
    • Việc thay đổi các phiên bản của service (upgrade, canary) không nên transparent với client
    • Một số dịch vụ được integration và sử dụng gRPC, webservice hoặc SOAP không thân thiện lắm với các client hiện nay.

    Cân nhắc — Consideration

    Với API Gatway chúng ta sẽ có một API thân thiện với client với protocol tiêu chuẩn. Việc triển khai Client sẽ đơn giản hơn vì logic của việc xử lý nhiều service sẽ nằm ở Gateway thay vì client. Tuy nhiên dánh đổi bằng việc tăng độ phức tạp — API Gateway là một phần khác phải được phát triển, triển khai và quản lý, ngoài ra thời giản xử lý request cũng tăng lên vì thêm có bước xử lý network hop ở Gateway, tuy nhiên vân ngắn hơn thời gian xử lý cho BFF.

    Quyết định về kiến trúc — Architecture decision

    API Gateway

    Biện luận

    API Gatway với Spring có thể sử dụng Netflix Zuul, việc sử dụng Gateway sẽ đem đến trải nghiệm người dùng tốt hơn, vấn đề effort cho develop, deploy có thể giảm bằng cách đồng nhất cách thức xử lý cho các service sẽ đc xây dựng (dùng cùng một tech-stack)

    Tài liệu hóa và trao đổi về quyết định về kiến trúc

    Trao đổi về kiến trúc (giữa Architect và Developer)

    Trong dự án phần mềm của bạn có các kênh trao đổi nào?

    Email

    Email (đơn thuần là email) thực tế không thích hợp để trao đổi nhất là về mặt kỹ thuật, có quá nhiều vấn đề trong quá trình xây dựng kiến trúc và thông tin trong email khá khó để tổng hợp và truyền đạt lại, hãy nghĩ đến việc bạn sẽ cho một thành viên mới dành cả 2 tuần lễ để đọc lại thread mail.

    Hãy document quyết định về kiến trúc

    Sử dụng wiki là một biện pháp ổn, nhanh, giao diện đẹp, dễ viết với Markdown và quan trọng nhất là tập trung. Một vấn đề nữa, hãy chỉ rõ hoặc quyết định luôn chỗ mà quyết định được lưu trữ (hơi nhiều từ quyết định, tho)

    Với các vấn đề quan trọng và ảnh hưởng lớn, hãy đảm bảo tất cả mọi người cần biết được biết về nó. Bảng trắng luôn là một lựa chọn tốt để trao đổi, nếu trong thời buổi WFH có thể sử dụng các công cụ trong kênh giao tiếp.

    image

    P/S: hãy ra quyết định một cách khôn ngoan nhé.

    Happy Coding.

    to be continued sigange
  • Triển khai CI/CD cho iOS – SonarQube & Blackduck

    Overview

    Tiếp tục với series CI/CD cho iOS, hôm nay chúng ta sẽ triển khai CI với hai nền tảng kiểm tra source code rất nổi tiếng là SonarQube và Blackduck.

    Triển khai CI với Blackduck

    Khác với SonarQube, Blackduck không đánh giá chất lượng mà giúp chúng ta quản trị open source code và source code từ các thư viện được thêm vào. Giúp chúng ta đánh giá và quản lý được các rủi ro về bản quyền, bảo mật khi sử dụng source code có sẵn trên mạng cũng như lưu hành trong cộng đồng.

    Do Blackduck không có Server public như Sonar, nên mình sẽ giả định chúng ta có một Server Blackduck được đặt tại địa chỉ sau:

    https://blackduck.techover.io

    Sau khi truy cập vào, chúng ta sẽ thấy danh sách các project đã có ở Dashboard. Ở đây mình đã tạo sẵn một Project W95.CICD, nếu muốn tạo mới chúng ta sẽ ấn nút Create Project ở góc trên bên phải.

    Dashboard của Blackduck

    Cũng giống như Sonar, để có thể đồng bộ các dữ liệu Scan chúng ta cần có một Token. Để tạo Blackduck Token, chúng ta sẽ vào màn hình quản lý Access Tokens như sau:

    Ấn vào Profile ở góc trên bên phải, chọn My Access Tokens

    Sau khi chuyển đến màn hình quản lý Access Token, chúng ta ấn Create New Access Token và điền thông tin.

    Màn hình quản lý Access Tokens
    Nhập thông tin và ấn Create

    Sau khi có token, chúng ta sẽ lưu lại để sử dụng sau này. Lưu ý, token sẽ không hiển thị lại lần thứ 2 nên hãy copy và lưu lại ngay và luôn nhé. Ví dụ mình sẽ lưu lại token lại dưới đây:

    YWJmYzc5MDMS05N2VjLWFkNGE4ZMS05N2VjLWFkNGE4Z--=/

    Đối với Blackduck, chúng ta cũng sử dụng gần giống như Sonar nhưng thay vì CLI, chúng ta sẽ sử dụng Java Archive, vì vậy hãy đảm bảo bạn đã cài Java trong thiết bị Runner nhé.

    Tải về phiên bản .jar mới nhất của blackduck ở đây

    Sau khi tải xong, chúng ta sẽ giải nén và lưu và một thư mục trong thiết bị Runner, ở đây mình sẽ lưu ở địa chỉ sau:

    /Users/jena/CICD/synopsys-detect/synopsys-detect-6.4.1.jar

    Rồi xong, tới công chuyện luôn!!

    Tiếp đó chúng ta chỉ cần cấu hình file .gitlab-ci.yml như sau:

    stages:
      - Lint
    blackduck-detect:
      stage: Lint
      only:
          - cicd
      script:
        - java -jar /Users/jena/CICD/synopsys-detect/synopsys-detect-6.4.1.jar \
          --blackduck.url=https://blackduck.techover.io \
          --blackduck.api.token=YWJmYzc5MDMS05N2VjLWFkNGE4ZMS05N2VjLWFkNGE4Z--=/ \
          --detect.project.name=W95.CICD
      tags:
        - w95

    Vậy là xong, mỗi khi có commit/merge lên nhánh cicd (hãy thay bằng master/main/develop) thì hệ thống sẽ tự động scan source code và gửi kết quả lên Server.

    Quên mất, còn một bước cuối cùng nữa là bạn có thể che đi các thông tin nhạy cảm trong file cấu hình .gitlab-ci.yml, đề phòng trong trường hợp file cấu hình bị rò rỉ, các thông tin về Server Blackduck cũng như Token cũng sẽ không bị ảnh hưởng. Để làm việc này chúng ta sẽ cấu hình một số thông tin sau vào biến môi trường của Gitlab-CI

    BLACKDUCK_SERVER = https://blackduck.techover.io
    BLACKDUCK_TOKEN = YWJmYzc5MDMS05N2VjLWFkNGE4ZMS05N2VjLWFkNGE4Z--=/

    Và kết quả, file .gitlab-ci.yml sẽ trông như sau:

    stages:
      - Lint
    blackduck-detect:
      stage: Lint
      only:
          - cicd
      script:
        - java -jar /Users/jena/CICD/synopsys-detect/synopsys-detect-6.4.1.jar \
          --blackduck.url=${BLACKDUCK_SERVER} \
          --blackduck.api.token=${BLACKDUCK_TOKEN} \
          --detect.project.name=W95.CICD
      tags:
        - w95

    Rồi xong, tới công chuyện luôn!! Như vậy là chúng ta đã hoàn thành cấu hình CI với Blackduck để scan các lỗi hổng bảo mật, bản quyền. Mặc dù liên quan đến CI còn rất nhiều section như Coverity, Build & Compile nhưng mình xin phép tạm dừng hạng mục CI và chuyển sang CD. Rất mong được các bạn ủng hộ.

  • Triển khai CI/CD cho iOS – SonarQube & Blackduck

    Triển khai CI/CD cho iOS – SonarQube & Blackduck

    Overview

    Tiếp tục với series CI/CD cho iOS, hôm nay chúng ta sẽ triển khai CI với hai nền tảng kiểm tra source code rất nổi tiếng là SonarQube và Blackduck.

    Triển khai CI với SonarQube

    Đôi chút về SonarQube, đây là một nền tảng mã nguồn mở sử dụng để kiểm tra chất lượng của source code, đánh giá các lỗi ở nhiều mức độ và tiêu chí khác nhau. Mục đích cuối cùng là để thống kê và cải thiện chất lượng của source code theo mọi mặt cũng như giúp lập trình viên đánh giá chất lượng của chính mình. Vì vậy, việc sử dụng SonarQube để hỗ trợ quá trình phát triển, nâng cao chất lượng source code luôn được các doanh nghiệp lớn áp dụng.

    Chúng ta sẽ thực hiện CI với SonarQube server ở địa chỉ sau: https://sonarcloud.io, bạn có thể sử dụng tài khoản GitLab của mình để đăng nhập và tạo project ở đây. Sau một vài bước đăng nhập, tạo organization và chọn plan thì chúng ta sẽ đến với step đầu tiên.

    Đối với một số trường hợp có Server riêng để host SonarQube, các bạn hãy truy cập host và sử dụng tài khoản/mật khẩu được cung cấp bởi admin.

    Cấu hình SonarQube

    Việc đầu tiên, chúng ta sẽ cần tạo một project, ở đây mình sẽ tạo một project như hình sau:

    Điền Project Key và Display name sau đó ấn Set Up

    Trong một số trường hợp, bước config tạo Project sẽ do admin tạo, các bạn chỉ cần đăng nhập là xem được các project mình được phân quyền.

    Sau khi ấn Set Up, chúng ta sẽ được suggest 3 lựa chọn, ở đây mình sẽ chọn Manually để có thể sử dụng ở nhiều nền tảng khác nhau (Không chỉ riêng GitLab-CI).

    Lựa chọn Manually

    Tiếp đó chúng ta sẽ chọn các lựa chọn như hình sau:

    Chọn Other(…) -> macOS

    Tiếp đó chúng ta ấn Download để tải CLI của SonarQube về, giải nén và lưu vào một thư mục trong thiết bị runner. Giả sử mình sẽ lưu ở địa chỉ sau:

    /Users/jena/Projects/sonar-scanner/bin

    Mình sẽ thêm thư mục bin vào trong PATH của macOS bằng câu lệnh sau

    export PATH=$PATH:/Users/jena/Projects/sonar-scanner/bin

    Sau đó, bạn có thể chạy lệnh sau để kiểm tra xem cli đã được nhận vào PATH chưa. Sẽ có một số lỗi yêu cầu cấp quyền để chạy CLI, bạn hãy vào System Preference -> Security & Privacy -> Tab General -> Allow Anyway tất cả

    sonar-scanner -v
    Sau khi cli được add vào PATH, bạn có thể chạy bằng lệnh sonar-scanner

    Tiếp đó, chúng ta sẽ vào GitLab và cài đặt biến môi trường SONAR_TOKEN như hình sau

    Tiếp đó, chúng ta sẽ cấu hình CI ở file .gitlab-ci.yml như sau, phần script sẽ được gen cùng với SONAR_TOKEN, các bạn chỉ cần copy và paster vào là được:

    stages:
      - Lint
    sonar-scanner:
      stage: Lint
      only:
          - cicd
      script:
        - sonar-scanner -Dsonar.organization=w95 -Dsonar.projectKey=CICD.iOS -Dsonar.sources=. -Dsonar.host.url=https://sonarcloud.io -Dsonar.branch=master
      tags:
        - w95

    Sau khi commit file .gitlab-ci.yml lên branch cicd, chúng ta sẽ có kết quả như sau:

    Job Sonar Scanner chạy thành công với log như trên
    Màn hình thống kê trên SonarCloud.io cũng sẽ hiển thị các thông số của source code

    Theo như ảnh trên, Quality Gate đang đánh giá Passed tức là source code đạt chất lượng, nhưng thật ra mình scan Starter Project của iOS nên mới không có lỗi, còn code của mình thì lắm lỗi lắm :p

    Như vậy là chúng ta đã hoàn thành bước cấu hình CI sử dụng SonarQube cho một project iOS. Mỗi khi có commit, merge hay sự thay đổi trên branch cicd (bạn sẽ đổi thành master/develop/main) thì hệ thống sẽ tự động chạy CI và đẩy thống kê lên Sonar server. Chúng ta chỉ cần lên đó, tracking các thông số và sửa các lỗi bị cảnh báo là được.

    Do bài viết hơi dài, nên mình sẽ để phần Blackduck sang bài viết sau. Cảm ơn các bạn đã đọc!

    Authors

    LinhNB1