Category: Common Knowledge

  • When it comes to compensation and benefits, other than base salary, which is the most important to you?

    When it comes to compensation and benefits, other than base salary, which is the most important to you?

    When it comes to compensation and benefits, other than base salary, which is the most important to you?

    Pic5

    This blog post is part of Udacity Data Scientists Nanodegree Program. Detailed analysis with all required code is posted in my github repository and Jupyter notebook.

    My github repository:

    My github repository

    Jupyter notebook code:

    My Jupyter notebook code

    Data source:

    Data source

    Each stage of the CRISP-DM process. These stages are:

    1. Business Understanding
    2. Data Understanding
    3. Prepare Data
    4. Data Modeling
    5. Evaluate the Resultssults

    Business Understanding

    In this Notebook, I will explore the 2023 Stack Overflow results to gather some information about the organization, main field of study, important benefits, and the increase in salary with the years of learning how to program.

    There are 4 questions I want to find answers to:

    • Question 1: What type of company or organization do you work for?
    • Question 2: What is your main field of study in college or university/for your undergraduate studies in 2023?
    • Question 3: Which is the most important benefits to you?
    • Question 4: The more you learn, will the more salary you get?

    Data Understanding

    In order to understanding data. I will do these steps:

    • Handle categorical data
    • Analyze, Model, and Visualize

    Question 1: What type of company or organization do you work for?

    pic1

    Evaluate the Results

    Through the chart, we can easily see:

    • The number of people working in Privately-held limited companies, not in startup mode, accounts for the largest number, about more than 16,000 people.
    • The number of people working in Publicly-traded corporations accounts for the second largest number, about 6,000 people.
    • The number of people working in State-owned companies is small, about less than 1,000 people. Thus, the difference between the number of people working between a Privately-held limited company and a State-owned company is quite large, about 15,000 people

    Question 2: What is your main field of study in college or university/for your undergraduate studies in 2023?

    pic2

    Evaluate the Results

    Through the chart, we can easily see:

    • The proportion of people graduating from field Computer science or software engineering is the largest, about 43%.
    • The rate of people graduating from field Computer engineering or electrical/electronics engineering ranks second, about 9%.
    • The rate of people graduating from field A health science is the least, about 1%. Thus, the proportion of people graduating from field Computer science or software engineering is much larger than field A health science, about 42%. Thereby, we see that field Computer science or software engineering is a field that is very attractive to learnersers.

    Question 3: Which is most important benefits to you?

    pic3

    Evaluate the Results

    Based on the chart, we see:

    • The benefit users are most interested in is Vacation/days off, accounting for about 15%.
    • Remote options is the second most important benefit, accounting for about 13.7%.
    • Child/elder care and Other are benefits that receive little attention, accounting for about 2% and 1% respectively. Lastly, when it comes to compensation and benefits, other than base salary, Vacation/days off is the following are most important to users

    Question 4: The more you learn, will the more salary you get?

    pic4

    Evaluate the Results

    Based on the map, we can see:

    • We can achieve the highest salary when we have 20 years or more of study experience.
    • From 19 to 20 years of study, we can reach the 2nd highest average salary.
    • The average salary is lowest when we have less than 1 year of study experience. From there we conclude that the more years of experience accumulated working on a project, the higher the average salary and vice versa.

    Conclusion

    In this article, we took a look at main field of study, important benefits, and the increase in salary with the years of learning how to program according to Stack Overflow 2023 survey data.

    We gathered the advice of the masses as to how to increase in salary with the years, which showed that the more years of experience accumulated working on a project, the higher the average salary and vice versa.

    When it comes to compensation and benefits, other than base salary, we then looked at the satisfaction of important benefits. This showed that Vacation/days off is the following are most important to users. We found that field Computer science or software engineering is a field that is very attractive to learnersers.

    The findings here are observational, not the result of a formal study

    To see more about this analysis, see the link to my Github available here

    View a detailed analysis report on Medium

    Blog_Medium

    Files Description in the repo

    The Stack Overflow Survey – 2023.ipynb – Notebook containing the data Analysis

    stack-overflow-developer-survey-2023.zip – Developers Survey Result Data and Result Schema

    Requirements

    pandas, matplotlib, jupyter-notebook (if running locally)

    License

    License

    Acknowledgements

    Data source:

    Data source

  • Giúp background của View co giãn tối ưu với 9-patch image trong Android

    Giúp background của View co giãn tối ưu với 9-patch image trong Android

    Đã bao giờ bạn phải xử lý một Dialog, Button hoặc 1 cái CardView design đặc biệt tràn đầy graphical art các kiểu con đà điểu chưa? Có thể bạn nhìn file design một lúc và export nguyên cái ảnh ra để rồi nhận ra nếu nhiều chữ hơn hoặc màn hình bé hơn to hơn -> ảnh vỡ, code của bạn tèo ?

    pain...
    không chỉ ở làng Mưa, mà trong file design cũng có pain…

    Và rồi bạn đành phải work around, tự cắt các thành phần của một design ra nhiều phần nhỏ và dùng ImageView ghép lại theo định nghĩa phần có thể giãn và phần không cần giãn. Well, code bạn vẫn chạy ổn, nhưng chưa phải tối ưu.

    Để tạo background cho những component mang tính graphical như vậy, chúng ta đã 9-patch image hỗ trợ.

    9-patch Image là gì cơ?

    9-patch image là drawable dạng ảnh png đặc biệt có thể co giãn theo một định nghĩa nằm trong file này. Loại drawable này thường được sử dụng để làm background cho các View, Android OS sẽ xử lý background dạng 9-patch co giãn theo định nghĩa của file thay vì giãn đều như drawable bình thường. File 9-patch sẽ có đuôi 9.png.
    Btw, 9-patch là 9 mảnh vá đó ? (trích của anh Nguyen Van Toan)

    Cấu trúc của ảnh 9-patch

    Như ảnh bạn có thể thấy 9-patch image được chia làm 2 thành phần:

    • Stretchable area
    • Fill area (Padding box)

    Stretchable area là phần mà ảnh có thể được giãn nếu cần thiết.
    Fill area là phần mà content của bạn được phép nằm trong đó (Vì thế nên còn gọi là Padding box đó hehe).

    Ngoài ra thì 9-patch image còn hỗ trợ Optical Bounds. Optical bounds trên 9-patch image sẽ hiển thị bằng đường kẻ màu đỏ.

    Như bạn thấy, khi định nghĩa chuẩn, View của bạn sẽ được co giãn một cách tối ưu.

    Nghe hay phết, vậy tạo 9-patch như thế nào z bro?

    Cách tạo 9-patch image

    Để tạo ra 9-patch image, Android Studio đã có sẵn tool support đầy đủ, bạn không cần tải thêm bất cứ thứ gì khác. Ngoài ra thì cũng có cách khác là sử dụng Simple nine-patch generator trong bộ tools online của Roman Nurik.

    Tạo bằng Android Studio

    Bước 1: Chúng ta click chuột phải vào ảnh PNG gốc, chọn Create 9-Patch file…

    Bước 2: bắt đầu tuỳ chỉnh các phẩn Stretchable area và Fill area cho hợp lý

    Bước 3: Sử dụng file 9-patch như một drawable bình thường (không cần ghi đuôi .9)

    Tạo bằng Simple nine-patch generator

    Để hỗ trợ các density khác nhau của các device Android khác nhau, chúng ta cần tạo đủ các resources như drawable-ldpi, drawable-mdpi, drawable-hdpi, drawable-xhdpi… nên nếu tạo bằng tay từng cái một có thể sẽ là 1 đống việc. Nên chúng ta dùng Tool!

    Bước 1: Mở trang web Simple nine-patch generator chọn Select image và chọn đúng loại desity của source ảnh bạn chọn.

    Bước 2: Chỉnh Stretchable area và Fill area cho hợp lý. Nếu bạn sử dụng Optical bounds thì nó sẽ là viền đỏ trên file 9-Patch.

    Bước 3: Tải ảnh về khi đã edit xong, chúng ta sẽ click vào icon download ở góc phải trên cùng để tải về.

    Bước 4: Sử dụng file 9-patch như một drawable bình thường (không cần ghi đuôi .9)

    Việc tạo bằng tool sẽ giúp chúng ta tinh chỉnh dễ dàng hơn, đỡ phải take time tạo từng 9-patch image khác nhau cho các density mà chưa chắc đã có độ nhất quán tuyệt đối. Nhưng bên cạnh đó lại có một nhược điểm là bạn chỉ có thể tạo một Stretchable area trong một drawable. Android studio thì lại giúp bạn tuỳ ý tạo các Stretchable area khác nhau.

    Summary

    Để styling trong Android thì muôn vàn cách, 9-patch chỉ là một trong số cách đó. Trên đây chỉ là một vài ví dụ cơ bản về việc sử dụng 9-patch. Mong rằng bài viết đã giúp bạn có thêm một kiến thức mới – phép thuật mới cho chặng đường của một phù thủy Android ??

  • Testing SCD Loại 1 trong ETL validator

    Testing SCD Loại 1 trong ETL validator

    Xin chào mọi người, ở bài viết SCD (Slowly Changing Dimension) là gì? Các loại SCD và ví dụ cụ thể (https://magz.techover.io/2023/07/03/scd-slowly-changing-dimension-la-gi-cac-loai-scd-va-vi-du-cu-the/) chúng ta đã nắm được sơ lược về SCD type 1. Hôm nay chúng ta cùng đi tìm hiểu kỹ hơn về SCD type 1 và các test cases cần thiết trong quá trình kiểm thử nhé!

    1. Tìm hiểu về SCD type 1 (Ghi đè – Overwrite)

    Ở SCD1 các dữ liệu mới sẽ ghi đè dữ liệu cũ, không theo dõi dữ liệu lịch sử.

    Ví dụ:

    Original Record – Dữ liệu gốc

    Cust_ID Name City
    1001 Nguyễn Văn A HCM
    1002 Nguyễn Văn B Nam Định

    Updated Record – Dữ liệu được thay đổi

    Cust_ID Name City
    1001 Nguyễn Văn A Hà Nội
    1002 Nguyễn Văn B Nam Định

    Ưu điểm: Dễ bảo trì.

    Nhược điểm: Không kiểm tra được dữ liệu lịch sử.

    2. SCD1 validation test cases

    image

    Kiểm tra SCD Loại 1 khá đơn giản vì chúng ta có thể đạt được kết quả bằng cách so sánh đơn giản giữa dữ liệu nguồn và dữ liệu đích. Ví dụ chúng ta có bẳng nguồn và bảng đích như sau:

    Employee table – bảng nguồn với các cột:

    Cust_ID
    Name
    City

    EMPLOYEE_DIM SCD Type 1 – bảng đích với các cột dưới đây:

    Cust_ID
    Name
    City
    Partition_date

    2.1 Test case 1: Chúng ta sẽ đi kiểm tra số lượng cột, tên cột và data type từng cột có đúng với yêu cầu document không?

    VD: Cus_ID có type là bigint, thì trên bảng đích data type cũng là bigint.

    Target Query: Describe Table_Name; or Desc Table_Name

    2.2 Test case 2: Kiểm tra số lượng records.

    Source Query: Select count (*) from db.Emlpoyee

    Target Query: Select count (*) from db.Employee_Dim

    2.3 Test case 3: Kiểm tra logic insert

    1. Insert thêm records mới ở bảng nguồn:

    Chúng ta sẽ thêm các records mới tại bảng nguồn, rồi khởi chạy job ETL. Sau khi job chạy thành công thì kiểm tra dữ liệu ở bảng đích có lên đúng và đủ so với bảng nguồn không.

    1. Delete records ở bảng nguồn

    Ngược lại với thêm mới, chúng ta sẽ xóa bớt dữ liệu ở bảng nguồn rồi chạy job ETL. Sau khi job chạy thành công thì kiểm tra dữ liệu ở bảng đích và bảng nguồn có mapping với nhau không.

    2.4 Test case 4: Kiểm tra logic update

    Tại bảng nguồn chúng ta sẽ update các bản ghi trước đó, rồi chạy job ETL. Sau khi job chạy thành công, kiểm tra dữ liệu bảng đích có lên đúng so với bảng nguồn không.

    2.5 Test case 5: Kiểm tra dữ liệu có bị duplicate không? – Xác minh tính duy nhất của dữ liệu

    Target Query:

    Select Cust_ID, Name, City, Partition_date, count(*) from db.Employee_Dim group by Cust_ID, Name, City, Partition_date having count(*) > 1 ;

    Select Cust_ID, count(Cust_ID) from db.Employee_Dim group by Cust_ID having count(Cust_ID) > 1;

    2.6 Test case 6: Kiểm tra dữ liệu null

    Target Query:

    Select * from db.Employee_Dim where Cust_ID is not null;

    Kết luận

    • SCD1: các dữ liệu mới sẽ ghi đè dữ liệu cũ, không theo dõi dữ liệu lịch sử
    • Kiểm tra số lượng bản ghi bảng đích so với bảng nguồn
    • Sau khi thay đổi dữ liệu bảng nguồn (insert, delete, update) phải thực hiện quy trình ETL để EMPLOYEE_DIM có dữ liệu mới nhất
    • Sửa đổi một vài bản ghi trong bảng nguồn bằng cách cập nhật các giá trị trong các cột chính (key columns) để kiểm tra logic update
    • Xác minh tính duy nhất của dữ liệu
    • Xác minh rằng sự khác biệt là như mong đợi

    Trên đây là những chia sẻ của mình về testing SCD type 1 trong ETL testing, mong rằng bài viết này sẽ giúp ích được cho các bạn. Nếu mọi người có thắc mắc hay câu hỏi gì đừng ngần ngại comment và cùng nhau giải đáp nhé!

    Hẹn gặp lại mọi người trong bài viết tiếp theo.

  • SCD (Slowly Changing Dimension) là gì? Các loại SCD và ví dụ cụ thể

    SCD (Slowly Changing Dimension) là gì? Các loại SCD và ví dụ cụ thể

    Xin chào mọi người, ở bài viết trước mình đã chia sẻ về ETL testing và trong quá trình test ETL mình có nhắc đến việc chúng ta sẽ đi kiểm tra, theo dõi cách ghi/thay đổi dữ liệu trong bảng đích đã đúng yêu cầu hay chưa? Vậy cách ghi/thay đổi dữ liệu đó là gì nhỉ? Hôm nay chúng ta sẽ đi tìm hiểu về Slowly Changing Dimension (SCD) nhé!


    1. Slowly Changing Dimension (SCD) là gì?

    image

    SCD (Slowly Changing Dimension) có thể hiểu một cách đơn giản nhất đó là: so sánh dữ liệu nguồn với dữ liệu bảng đích hiện có bằng cách sử dụng Khóa nghiệp vụ – Business key (Khóa duy nhất – Unique Key).

    Nếu không có bản ghi nào khớp thì sẽ coi là Bản ghi mới hoặc Nếu bản ghi khớp thì sẽ so sánh các thuộc tính với các thuộc tính đã thay đổi nếu dữ liệu có vẻ được cập nhật thì nó cập nhật bản ghi hoặc nếu không thì nó để nguyên như không thay đổi.

    Slowly Changing Dimension sẽ kiểm tra các thuộc tính cho ba trường hợp: Bản ghi mới, đã thay đổi hoặc chưa thay đổi.

    2. Tại sao cần Slowly Changing Dimension?

    Trong thế giới Datawarehouse, đôi khi việc theo dõi sự thay đổi kích thước theo thời gian là rất quan trọng. Điều này giúp chúng ta theo dõi dữ liệu tốt hơn và cũng tạo ra các sản phẩm hiệu quả tùy thuộc vào các trường hợp sử dụng.

    3. Tại sao lại gọi là Slowly Changing Dimension?

    Slowly Chaning Dimension – gọi như trên có nghĩa là chúng ta sẽ phải sử dụng thành phần này chỉ cho các bảng không được cập nhật thường xuyên.

    Lưu ý: Không áp dụng cho bảng thường xuyên thay đổi, chỉ áp dụng trên các bảng kích thước (Dimension table) thay đổi chậm.

    4. Các loại SCD – Ví dụ về Slowly Changing Dimensions trong data warehouse (High-Level)

    Các loại SCD (High-Level)

    Sau đây là các loại SCD, mỗi loại đều có một số ưu điểm và nhược điểm riêng.

    1. Type – 0 Giữ lại dữ liệu gốc
    2. Type – 1 Ghi đè lên dữ liệu hiện có
    3. Type – 2 Thêm các bản ghi mới trên cùng một bảng
    4. Type – 3 Thêm cột mới trên cùng một bảng
    5. Type – 4 Sử dụng bảng lịch sử
    6. Type – 6 Phương pháp kết hợp (Loại 1 + Loại 2 + Loại 3)

    image

    SCD type 1 (Ghi đè)

    Loại hành động SCD đầu tiên có thể thực hiện được là ghi đè. Ở đây, các giá trị kích thước được ghi đè bởi các giá trị mới.

    Ví dụ: Khách hàng Nguyễn Văn A chuyển từ HCM đến Hà Nội, thì thành phố của anh ấy sẽ được cập nhật với giá trị mới nhất, tức là Hà Nội

    Original Record – Dữ liệu gốc

    Cust_ID Name City
    1001 Nguyễn Văn A HCM
    1002 Nguyễn Văn B Nam Định

    Updated Record – Dữ liệu được thay đổi

    Cust_ID Name City
    1001 Nguyễn Văn A Hà Nội
    1002 Nguyễn Văn B Nam Định

    Trong ví dụ trên, khách hàng đã di chuyển từ nơi này sang nơi khác và địa chỉ gần đây đã được ghi đè lên các bản ghi hiện có.

    Nhược điểm: chúng ta không thể truy xuất thông tin địa chỉ trước đây của anh ấy từ tình huống này.

    SCD type 2

    • Thêm bản ghi mới
    • Chúng ta có thể nắm bắt thay đổi thuộc tính bằng cách thêm một cột mới làm khóa thay thế (VD: IsActive)

    Khi giá trị của bản ghi hiện tại thay đổi, bản ghi hiện tại được đánh dấu là không hoạt động (inactive – 0) và bản ghi mới được insert vào.

    Kết quả, sẽ có 2 bản ghi được liên kết với Nguyễn Văn A trong bảng được cập nhật, nhưng chỉ có phiên bản mới nhất được đánh dấu là hoạt động (active – 1).

    Original Record – Dữ liệu gốc

    Cust_ID Name City IsActive
    1001 Nguyễn Văn A HCM 1
    1002 Nguyễn Văn B Nam Định 1

    Updated Record – Dữ liệu được thay đổi

    Cust_ID Name City IsActive
    1001 Nguyễn Văn A HCM 0
    1001 Nguyễn Văn A Hà Nội 1
    1002 Nguyễn Văn B Nam Định 1

    Ưu điểm: thỏa mãn điểm trừ trước đó theo dõi dữ liệu lịch sử bằng cách tạo mục nhập mới trên cùng một bảng.

    Nhược điểm: mặc dù nó nắm bắt dữ liệu lịch sử, nhưng nó có thể dẫn đến hoạt động tốn kém ở phía cơ sở dữ liệu.

    SCD Type 3 (Thêm cột giá trị trước đó)

    Loại SCD phổ biến thứ ba là thêm một cột giá trị trước đó. Ở đây, các phiên bản trước và hiện tại được duy trì trong một hàng.

    Hạn chế của phương pháp này là nó sẽ chỉ có hiện tại/trước đó chứ không phải toàn bộ lịch sử

    Original Record – Dữ liệu gốc

    Cust_ID Name City
    1001 Nguyễn Văn A HCM
    1002 Nguyễn Văn B Nam Định

    Updated Record – Dữ liệu được thay đổi

    Cust_ID Name Current City Previous City
    1001 Nguyễn Văn A Hà Nội HCM
    1002 Nguyễn Văn B Nam Định

    SCD Type 4: Thêm bảng mới (Bảng lịch sử)

    • Sử dụng bảng Lịch sử
    • Trong cách tiếp cận này, bảng lịch sử riêng biệt được tạo ra để theo dõi các thay đổi.
    • Bảng chính sẽ chỉ có dữ liệu mới nhất
    • Ưu điểm: Phản hồi nhanh hơn đối với các truy vấn yêu cầu dữ liệu mới nhất. Dễ quản lý và viết mã, thuận lợi cho các thuộc tính có tính biến động cao hoặc được sử dụng thường xuyên ở kích thước rất lớn.
    • Nhược điểm: Đôi khi tổng hợp/tham gia giữa dữ liệu hoạt động và lịch sử có thể mất thời gian và trở nên phức tạp

    Customer Table

    Cust_ID Name City
    1001 Nguyễn Văn A Hà Nội
    1002 Nguyễn Văn B Nam Định

    Customer History Table

    Cust_ID Name City Last_updated_date
    1001 Nguyễn Văn A HCM 11-03-2023
    1001 Nguyễn Văn A Hà Nam 11-05-2023
    1001 Nguyễn Văn A Bắc Ninh 11-06-2023

    SCD Type 6

    Phương pháp kết hợp (Loại 1 + Loại 2 + Loại 3)

    • Ưu điểm: Mọi bản chụp thay đổi dữ liệu đều có trong cùng một bảng
    • Nhược điểm: Phức tạp, khó quản lý, bảng lớn.
    Cust_ID Name City EffectiveFrom EffectiveTo IsActive
    1001 Nguyễn Văn A HCM 11-03-2023 11-05-2023 0
    1001 Nguyễn Văn A Hà Nam 11-05-2023 11-06-2023 0
    1001 Nguyễn Văn A Bắc Ninh 11-06-2023 03-07-2023 0
    1001 Nguyễn Văn A Hà Nội 03-07-2023 1
    1002 Nguyễn Văn B Nam Định 22-02-2023 1

    Ở ví dụ trên, dữ liệu lịch sử được theo dõi trong hàng mới được xác định bởi các trường ngày bắt đầu và ngày kết thúc. Ngoài ra, chúng ta có thể có trường cờ isActive để xác định bản ghi hiện tại từ danh sách. Chúng ta có thể duy trì lịch sử của tất cả các thay đổi đồng thời cập nhật giá trị hiện tại trên các bản ghi hiện có.


    Trên đây là những kiến thức về SCD (Slowly Changing Dimension), Các loại SCD và kịch bản kiểm thử, bài viết cũng khá dài rồi, nếu có cơ hội, bài viết tới mình sẽ chia sẻ chi tiết hơn về SCD type 2. Mong rằng bài viết này sẽ giúp ích được cho mọi người trong quá trình tìm hiểu về SCD. Nếu mọi người có thắc mắc hay câu hỏi gì đừng ngần ngại comment và cùng nhau giải đáp nhé!

    Hẹn gặp lại mọi người trong bài viết tiếp theo.

    Tài liệu tham khảo:

    https://www.expressanalytics.com/blog/what-is-a-slowly-changing-dimension-and-the-logic-in-implementation/

    https://www.learnmsbitutorials.net/slowly-changing-dimensions-ssis.php

  • Tìm hiểu về ETL Testing, ETL (Extract, Transform, and Load) Process

    Tìm hiểu về ETL Testing, ETL (Extract, Transform, and Load) Process

    Xin chào mọi người, chắc hẳn các bạn đã từng nghe qua thuật ngữ ETL và tự hỏi rằng ETL là gì? Đối với tester muốn test ETL cần phải làm gì? Quy trình ETL ra sao? Tại sao phải ETL nhỉ? Và test ETL khác gì so với test app, test web? Trước đây, mình cũng thế, đặt ra hàng vạn câu hỏi vì sao rồi đi tìm hiểu, sau quá trình học và có chút kinh nghiệm thực tế, hôm nay mình xin giới thiệu đôi chút kiến thức về ETL testing, tổng quan về quy trình ETL và test ETL khác gì so với test app, web.

    1. Khái niệm

    1.1. ETL Thử nghiệm/Kiểm thử ETL là gì?

    Kiểm thử ETL là quá trình kiểm thử được thực hiện để đảm bảo dữ liệu được tải từ nguồn đến đích sau khi chuyển đổi là chính xác, là việc xác minh dữ liệu ở các giai đoạn trung gian đang được sử dụng giữa nguồn và đích. ETL là từ viết tắt của Extract-Transform-Load.

    1.2. Kiểm tra kho dữ liệu (data warehouse) là gì?

    Kiểm tra kho dữ liệu là một phương pháp kiểm tra trong đó dữ liệu bên trong kho dữ liệu được kiểm tra tính toàn vẹn, độ tin cậy, độ chính xác và tính nhất quán để tuân thủ khung dữ liệu của công ty. Mục đích chính của thử nghiệm kho dữ liệu là để đảm bảo rằng dữ liệu được tích hợp bên trong kho dữ liệu đủ tin cậy để một công ty đưa ra quyết định.

    1.3. ETL là gì? ETL hoạt động như nào?

    ETL là viết tắt của Extract-Transform-Load, là một quy trình trích xuất dữ liệu từ các hệ thống nguồn khác nhau, sau đó chuyển đổi dữ liệu (như áp dụng phép tính, phép nối, v.v.) Và cuối cùng tải dữ liệu vào hệ thống Kho dữ liệu. Trích xuất, chuyển đổi và tải (ETL) hoạt động bằng cách di chuyển dữ liệu từ hệ thống gốc đến hệ thống đích trong các chu kỳ định kỳ. Quy trình ETL hoạt động theo ba bước:

    • Extract: Trích xuất dữ liệu có liên quan từ cơ sở dữ liệu nguồn
    • Transform: Chuyển đổi dữ liệu để phù hợp hơn cho việc phân tích
    • Load: Tải dữ liệu vào cơ sở dữ liệu đích

    image

    1.4 Tại sao chúng ta phải ETL dữ liệu?

    Nếu chúng ta vẫn để nguyên các dữ liệu trên các database của các dữ liệu nguồn, chúng ta vẫn làm được các báo cáo phân tích, … Vậy tại sao chúng ta phải ETL dữ liệu làm gì?

    Như đã nói trên, bạn dùng ETL dữ liệu để chuyển mục đích, và tối ưu hóa mục đích sử dụng dữ liệu của các phần mềm từ ghi nhận các nghiệp vụ phát sinh hàng ngày, sang mục đích khai thác, vận hành, và phân tích các dữ liệu này để các nhà quản trị tìm ra các cơ may phát triển, các hoạt động kinh doanh mới đề vận hành doanh nghiệp – và đây chính là mục đích của ETL, và là nguyên nhân bạn cần công cụ này – chuyển đổi công năng sử dụng dữ liệu để cung cấp cho nhà quản trị.

    2. Quy trình kiểm thử ETL

    Tương tự như các Quy trình kiểm thử khác, ETL cũng trả qua các giai đoạn khác nhau. Các giai đoạn của quá trình kiểm thử ETL như sau:

    image

    3. ETL Tools

    Trên thị trường, có rất nhiều tools ETL, nhưng dưới đây là vài tool nổi bật nhất mọi người hay dùng:

    • Marklogic: https://www.marklogic.com/product/getting-started/
    • Oracle: https://www.oracle.com/index.html
    • Amazon redshift: https://aws.amazon.com/redshift/?Nc2=h_m1

    4. Mình đã sử dụng AWS trong ETL testing như thế nào?

    Như ở trên, chúng ta đã hiểu, ETL testing là kiểm tra để đảm bảo dữ liệu được tải từ nguồn đến đích sau khi chuyển đổi là chính xác. Lý thuyết là vậy, còn thực hành sẽ như nào nhỉ?

    Thật khó để mình có thể chia sẻ hết kinh nghiệm trong quá trình tìm hiểu, học và kiểm thử ETL trong bài viết này, nhưng mình sẽ lấy 1 Ví dụ để mô tả một cách dễ hiểu nhất những gì 1 tester cần làm trong quá trình kiểm thử ETL. Từ đó, các bạn dễ hình dung, hiểu hơn về ETL testing và có thể áp dụng trong tương lai.

    Ví dụ: Dưới đây là luồng di chuyển dữ liệu từ hệ thống nguồn (Stream data source) đến hệ thống đích (S3 Data Lake Target) trên AWS. Tester sẽ cần làm gì để test dữ liệu từ Source lên S3?

    image

    • B1. Bạn sẽ cần chuẩn bị dữ liệu thô (VD: file csv, file parquet, …) để up lên source.
    • B2. Vậy làm cách nào để cho data chạy từ source lên hệ thống đích được nhỉ? Bạn sẽ cần phải khởi chạy ETL job.
    • B3. Sau khi chạy, chúng ta sẽ kiểm tra job ETL đã chạy thành công chưa?
    • B4. Sau khi job chạy thành công, kiểm tra hệ thống đích (VD: S3 Data Lake Target) có tạo bảng như mong đợi?
    • B5. Kiểm tra dữ liệu bảng đích. VD: Số lượng bản ghi, số lượng column, tên column, data type từng bản ghi, data trong từng column, … Kiểm tra, theo dõi cách ghi/thay đổi dữ liệu trong bảng đích đã đúng yêu cầu hay chưa.

    5. ETL testing giống và khác gì so với test mobile, test web?

    5.1. Giống nhau:

    • Trước hết, để test bất kỳ cái gì chúng ta đều phải đọc và hiểu tài liệu đặc tả. Lên kế hoạch kiểm thử và estimate thời gian kiểm thử.
    • Thiết kế test case, đảm bảo test đủ các trường hợp có thể xảy ra.
    • Chuẩn bị data test, môi trường test, …
    • Mục đích cuối cùng đều là đảm bảo chất lượng sản phẩm, đảm bảo đầu ra đúng với nhu cầu khách hàng.
    • ….

    5.2. Khác nhau:

    Vậy ETL testing có gì khác biệt so với test web và mobile? Dưới đây là một vài điểm khác biệt mà mình thấy được trong quá trình làm việc với ETL:

    • Test app, web để kiểm tra giao diện (UI), tương tác và trải nghiệm người dùng (UX) hay các chức năng, giá trị hiển thị, … thì chúng ta sẽ cần so sánh đúng với yêu cầu đặc tả (SRS)/mong muốn của khách hàng. Tức là chúng ta đã có sẵn yêu cầu đầu ra, việc cần làm là kiểm tra tính đúng đắn so với yêu cầu đó.
    • Test ETL thì chúng ta cần có kiến thức về SQL. Vì thực tế luôn có những chuyển đổi dữ liệu (transform) phức tạp, hoặc transform data từ nhiều nguồn, nhiều khoảng thời gian, … nên để tìm ra được output expect (kết quả đầu ra) là điều không dễ dàng. Do đó, chúng ta cần viết script SQL chuẩn, đúng với tài liệu để có được kết quả đầu ra, từ đó mới có thể so sánh và kiểm tra dữ liệu.

    Kết luận

    • ETL là viết tắt của Trích xuất, Chuyển đổi và Tải (Extract, Transform and Load)

    • ETL cung cấp phương pháp di chuyển dữ liệu từ nhiều nguồn khác nhau vào kho dữ liệu.

    • Trong bước trích xuất đầu tiên, dữ liệu được trích xuất từ hệ thống nguồn vào khu vực tổ chức.

    • Trong bước chuyển đổi, dữ liệu được trích xuất từ nguồn được làm sạch và chuyển đổi.

    • Tải dữ liệu vào kho dữ liệu đích là bước cuối cùng của quy trình ETL.

    Trên đây là những chia sẻ của mình về ETL testing, mong rằng bài viết này sẽ giúp ích được cho các bạn. Nếu mọi người có thắc mắc hay câu hỏi gì đừng ngần ngại comment và cùng nhau giải đáp nhé!

    Hẹn gặp lại mọi người trong bài viết tiếp theo.

    Tác giả bài viết

    HanhTM2

    Tài liệu tham khảo:

    Https://www.guru99.com/etl-extract-load-process.html

    Https://aws.amazon.com/vi/what-is/etl/

  • Combine big framework từ iOS 13

    Combine big framework từ iOS 13

    Định nghĩa

    Combine là một framework của Apple được tích hợp từ iOS 13. Combine cung cấp các API cho phép khai báo để xử lý các giá trị theo thời gian. Các giá trị này có thể đại diện cho nhiều loại sự kiện không đồng bộ. Combine cung cấp các Publishers hiển thị các giá trị có thể thay đổi theo thời gian và subscribers nhận các giá trị đó từ Publishers.

    Reactive có nghĩa là lập trình với các luồng giá trị không đồng bộ. Các bạn có thể tìm hiểu thêm về Reactive ở đây

    Functional programming là tất cả các chức năng trong lập trình. Trong Swift, các hàm có thể được truyền dưới dạng đối số cho các hàm khác, được trả về từ các hàm, được lưu trữ trong các biến và cấu trúc dữ liệu và được xây dựng trong thời gian chạy dưới dạng bao đóng.

    Trong style của declarative, bạn mô tả những gì chương trình thực hiện mà không mô tả luồng điều khiển. Theo style imperative, bạn viết cách thức hoạt động của chương trình bằng cách triển khai và xử lý một loạt tác vụ. Các chương trình imperative chủ yếu dựa vào trạng thái, thường được sửa đổi bằng các bài tập.

    Lập trình với Combine là sự kết hợp của declarative, reactive và functional. Nó liên quan đến các chức năng xâu chuỗi và chuyển các giá trị từ cái này sang cái khác. Điều này tạo ra các luồng giá trị, chảy từ đầu vào đến đầu ra.

    Lý thuyết là vậy, nhưng nếu chúng ta bỏ qua hết các định nghĩa thì Combine được thể hiện đơn giản như hình ảnh bên dưới đây:

    Và thệm trí có thể ngắn gọn hơn:
    Combine = Publishers + Subscribers + Operators

    Đến đây có vẻ chúng ta đã hiểu được Combine là gì rồi nhỉ, Tiếp tục đi đến các thành phần khác trong combine nhé.

    Publisher là gì?

    Publisher là gửi chuỗi giá trị theo thời gian đến một hoặc nhiều subscribers

    Combine publishers được tuân thủ theo protocol sau:


    Một publisher có thể gửi giá trị hoặc terminate với thành công hoặc lỗi. Output xác định loại giá trị mà publisher có thể gửi. Failure xác định loại lỗi mà nó có thể thất bại.

    Mothod receive(subscriber:) kết nối subscriber với publisher. Nó xác định hợp đồng: đầu ra của publisher phải khớp với đầu vào của subscriber và các loại lỗi cũng vậy.

    Subscriber là gì?

    Subscriber là để nhận các giá trị từ Publisher



    Một subscriber có thể nhận nhận giá trị với type Input hoặc termination với thành công hoặc lỗi

    các mothods receice mô tả các bước khác nhau trong vòng đời của người đăng ký. Chúng ta sẽ tìm hiểu vòng đời của subscriber này ở phần tiếp theo nhé!

    Kết nối Publisher với Subscriber

    Combine có hai methods được tích hợp sẵn: Subscribers.Sink và Subscribers.Assign. Bạn có thể kết nối chúng bằng cách gọi một trong hai method này bên dưới publisher

    • Sink(receiveCompletion:receiveValue:) để xử lý phần tử mới hoặc sự kiện hoàn thành trong một lần đóng.
    • assign(to:on:) để ghi phần tử mới vào một thuộc tính.


    1. Tạo ra một publisher Just gửi một signle giá trị và sau đó hoàn thành. Combine sẵn một số built-in trong đó có Just
    2. Kết nối publisher với subscriber bằng method sink

    Kết quả in ra lần lượt là:

    1
    finished

    Sau khi send 1 thì publisher tự động kết thúc, ở đây chúng ta không xử lý bất kì error nào, bởi vì Just không bao giờ thật bại.

    Subjects là gì?

    Subject là một lại publisher đặc biệt, nó có thể insert giá trị, truyền được giá trị từ bên ngoài vào. Giao diện của Subject cung cấp ba cách khác nhau để gửi các elements



    Combine có hai chủ thể tích hợp sẵn: PassthroughSubject và CurrentValueSubject.

    Bắt đầu với PassthroughSubject


    1. Tạo ra một passthrough subject. Chúng ta set Failure type là Never để cho nó biết rằng nó luôn kết thúc thành công.
    2. Đăng ký subject(hay nhớ rằng đó vẫn là một publisher).
    3. Gửi hai giá trị tới luồng và sau đó hoàn thành nó.

    Kết quả lần lượt như sau:

    Hello,
    World!
    finished

    Tiếp theo mình đi đến CurrentValueSubject


    1. Tạo ra một subject với giá trị khởi tạo là 1
    2. In ra giá trị hiện tại
    3. Cập nhật giá trị hiện tại thành 2 và in nó ra
    4. Đăng ký publisher

    Kết quả lần lượt như sau:

    1
    2
    2

    Combine Publisher and Subscriber Life Cycle

    Như đề cập ở bên trên, bây giờ chúng ta cùng tìm hiểu về life cycle của Publisher và Subscriber nhé!!!

    Sự kết nối giữ Publisher và Subscriber được gọi là subscription. Thông qua các bước của kết nối như vậy xác định vòng đời của Publisher và Subscriber


    Để ý đến operator print(_:to:) ở trên. Nó in ra các thông báo cho tất cả các sự kiện của Publisher vào console, từ các log được in ra thì chúng ta cũng có thể nắm được một phần nào đó về vòng đời của Publisher và Subscriber. Đây là log được ghi nhận từ console

    Từ log bên trên chúng ta đã có manh mối về vòng đời của publisher-subscriber. Với log ghi được, chúng ta sẽ đi phân tích từ đầu đến cuối nhé

    1. Subscriber kết nối với Publisher bằng cách gọi subscribe(S).

    2. Tạo một đăng ký tới Publisher bằng cách gọi receive(subscriber: S) trên chính nó.

    3. Publisher nhận yêu cầu đăng ký. Nó gọi receive(subscription:) trong subscriber

    4. Subscriber đăng ký một phần tử mà nó muốn nhận, Nó gọi đến request(:) và chuyển Request dưới dạng tham số. Nhu cầu xác định số lượng mục mà publisher có thể gửi cho subsriber thông qua subscription. Trong trường hợp này thì nhu cầu là không giới hạn (unlimited)

    5. Publisher gửi giá trị thông bằng cách gọi receive(_:) trên subscriber. Method này trả về một Demand, cho biết có bao nhiêu items mà subscriber mong muốn nhận được. Subscriber chỉ có thể tăng demand hoặc để nguyên, không thể giảm demand đi

    6. Kết thúc đăng ký với một trong những kết quả sau đây:
    – Cancelled Điều này có thể tự động xảy ra khi publisher được giải phóng, được hiển thị trong ví dụ bên trên. Một cách khác là hủy thủ công: token.cancel().
    – Finish thành công
    – Fail với một error.

    Chaining Publishers với Operators

    Operators là các methods đặc biệt được gọi bên dưới Publisher và trả ra một Publisher khác. Điều này cho phép áp dụng chúng một cách lần lượt, tạo ra một chuỗi. Mỗi operator đều biến đổi publisher cũ và được trả ra từ chính publisher cũ đó.

    Một operator đều tạo mới một publisher. Sau đó, các operators có thể áp dụng lần lượt. Mỗi operator nhận được được tạo ra từ publisher trước đó trong chỗi. Ở đây mình đề cập đến thứ tự tương đối của opetator là ngược dòng, nghĩa là operator liền trước và tiếp theo.

    Bây giờ chúng ta cùng nhau đến một ví dụ thông qua đó có thể xem cách xâu chuỗi operators khi xử lý request HTTP URL với Combine



    1. Tạo một request để tải kho GitHub. Mình đang sử dụng API GitHub REST.
    2. Combine được tích hợp tốt vào Swift system frameworks và SDK iOS. Điều này cho phép chúng ta sử dụng publisher để xử lý các tác vụ dữ liệu URLSession.
    3. Truyền dữ liệu phản hồi. Chúng ta sử dụng toán tử map(_:), biến đổi giá trị ngược dòng từ (data: Data, response: URLResponse) thành Data.
    4. Decode nội dung phản hồi bằng JSONDecoder.
    5. Kết nối sink subscriber. Nó in số lượng kho lưu trữ đã nhận và hoàn thành.

    Và đây là kết quả:

    V8tr has 30 repositories
    finished

    Thông qua bài này mình đã giới thiệu Combine đến các bạn
    Mình hi vọng bài viết có thể giúp ích được cho các bạn. Chúc các bạn thành công!

  • Schedulers in Swift Combine Framework

    Schedulers in Swift Combine Framework

    iOS 13 Apple đã giới thiệu đến các developer một big framework, có tên là Combine. Framework này cung cấp rất nhiều thứ thú vị, trong đó có Schedulers. Trong bài này mình sẽ giới thiệu đến các bạn Schedulers.

    Nội dung:

    • Scheduler trong Combine là gì?
    • Các kiểu của Scheduler trong combine.
    • Làm thế nào để switch schedulers?
    • Làm thế nào để perform asynchronous với Combine?
    • Sự khác nhau giữa receive(on:) và subscribe(on:)?

    Scheduler là gì?

    Scheduler Là cơ chế đồng bộ hoá của framework Combine. Nó xác định Context là gì, thực hiện công việc ở đâu (where), thực hiện công việc khi nào (when)

    • Where: Có nghĩa là Run loop hiện tại, dispatch queue hoặc operation queue.
    • When: Có nghĩa là thời gian ảo, tính theo thời gian của Scheduler, công việc được thực hiện bởi Scheduler phải tuân thủ theo thời gian của Scheduler, có thể không tương ứng với thời gian thực tế của hệ thống.

    Các kiểu của Scheduler trong combine

    Framework Combine cung cấp nhiều kiểu của Schedule khác nhau:

    • DispatchQueue: Thực hiện công việc trên một dispatch queue cụ thể: serial, concurrent, main and global. Thông thường serial, global dùng cho các công việc dưới background, và main queue sử dụng cho việc update UI. từ Xcode 11 GM Seed thì concurrent queues không được khuyến khích sử dụng.
    • OperationQueue: Tương tự như DispatchQueue, sử dụng OperationQueue.main cho các công việc liên quan đến UI, và các queue khác sử dụng cho công việc background. Theo như bài này trên một diễn đàn về Swift thì không khuyến khích sử dụng operationQueue với maxConcurrentOperations lớn hơn 1.
    • RunLoop: Thực hiện công việc trên một RunLoop cụ thể
    • ImmediateScheduler: Thực hiện các hành động đồng bộ ngay lập tức. App sẽ terminate với một fatalError nếu bạn cố gắng thực hiện delay task.

    Sử dụng RunLoop.main, DispatchQueue.main hoặc OperationQueue.main để thực hiện công việc liên quan UI. Không có sự khác biệt giữa chúng.

    Scheduler Mặc định

    Ngay cả khi bạn không chỉ định bất kì scheduler nào, Combine vẫn cung cấp cho bạn một scheduler mặc định, scheduler này sử dụng cùng thead với nơi nó được tạo ra. Ví dụ: nếu bạn bắn một sự kiện nào đó từ background thread thì bạn sẽ nhận được sự kiện đó cùng thread với nơi scheduler được tạo ra là background thread

    1. In ra true nếu nhận được sự kiện ở main thread và false nếu ở thead khác
    2. gửi một sự kiện đi từ main thread
    3. gửi một sự kiện từ global

    Và kết quả in ra ở đây lần lượt là true false. Đồng nghĩa là scheduler ở nơi nhận sự kiện giống với scheduler ở nơi sự kiện được sinh ra.

    Switching Schedulers

    Thông thường các hoạt như call API được xử lý ở background thread để UI không bị block. Sau khi call API thì thường update lại UI và công việc này được thực hiện trên main thread. Cách thức của Combine để thực hiện việc này là schitch schedulers. Nó được thực hiện với sự trợ giúp của hai methods: subscribe(on:) và receive(on:).

    • receive(on:) Method này thay scheduler của tất cả những operators sau nó

      Và đây là kết quả:

      Chúng ta có thể thấy map và sink đứng sau receive và đã thay đổi scheduler bởi receive.

      * Vị trí của receive là rất quan trọng bởi vì nó chỉ làm thay đổi scheduler của những operators đứng sau nó
    • subscribe(on:) Method này thay đổi scheduler của subscribe, cancel, and request operations.

      và đây là kết quả

      Nhìn khá giống với receive nhỉ? Cùng nhau đi đến một ví dụ nữa nhé. Cụ thể bây giờ chúng ta chuyển subscribe xuống một dong

      Lúc này kết quả in ra vẫn là false false

      * Vị trí của subscribe là không quan trọng, chỉ đơn giản là đăng ký event đó ở thread nào thôi.

    Thực hiện Asynchronous với Combine

    Trong thực tế khi lập trình chúng ta thường kết hơp hai methods subscribe(on:) and receive(on:). Cùng đi vào ví dụ cụ thể nhé!

    Ví dụ mình có một công việc cần thời gian dài để hoàn thành

    Khi call với main thread nó sẽ làm UI bị block trong 10s. Hãy nhớ rằng schuduler mặc định sẽ chạy cùng thread ở nơi nó được sinh ra

    Với lần call này thì ‘hello’ sẽ được in ra sau, cụ thể là đợi in ra ‘Received value’ sau đó mới thực hiện in ‘hello’. Block UI như thế này thực sự không cho phép trong lập trình. Cùng đi tiếp để xem hướng giải quyết vấn đề này trong trong Combile nhé!

    Pattern phổ biến để thực hiện asynchronous trong Combile là thực hiện subscribe ở background thread và recive ở main thread

    với lần call này thì ‘hello’ đã được in ra trước. Tuyệt vời! bài toán block UI đã được giải quyết.

    Bài viết này mình đã giới thiếu đến các bạn Scheduler, một phần trong Combile được Apple giới thiệu ở iOS 13

    Mình hi vọng bài viết có thể giúp ích được cho các bạn. Chúc các bạn thành công!

  • Kiểm tra kết nối của thiết bị với NWPathMonitor

    Kiểm tra kết nối của thiết bị với NWPathMonitor

    Hi các bạn, Trong quá trình develop của mình chắc hẳn các bạn đã sử dụng đến chức năng kiểm tra tình trạng kết nối của device. Đơn giản như việc kiểm tra internet khi call API hay download một cái gì đó.

    Trước đây thông thường chúng ta sử dụng Network Reachability.

    Network Reachability ở đây hiểu nôm na là trạng thái kết nối mạng của device. Chúng ta có thể sử dụng để xác định rằng device đang online hay offline, thậm chí là đang dùng mạng wifi hay gói dữ liệu data từ nhà mạng. Tuy nhiên đây không phải một thư viện chính thống từ Apple và chúng ta phải nhúng vào source code của mình trước khi sử dụng.

    Với iOS 12, Apple giới thiệu tới các developer một framework mới để kiểm tra tình trạng kết nối của device. NWPathMonitor có lẽ đây là một sự thay thế hoàn hảo cho Reachability.

    Trong sự kiện WWDC tháng 6 năm 2018, một framework mới có tên Network framework được giới thiệu dành cho iOS 12 trở đi. Một đối tượng có tên NWPathMonitor, framework này đem đến cho chúng ta một cách chính thống để xác định trạng thái kết nối mạng thay vì phải dùng thư viện của bên thư ba như từ trước tới nay.

    Dưới đây là cách sử dụng của NWPathMonitor

    Để sử dụng NWPathMonitor chúng ta chỉ cần import Network và sau đó tạo một đối tượng của NWPathMonitor như sau. Tất nhiên ứng dụng của các bạn phải hỗ trợ từ iOS 12 trở lên nhé.

    Với khởi tạo như ở trên thì chúng ta đang kiểm tra connect của tất cả tất cả các Interface type. Nếu chúng ta chỉ quan tâm đến Nếu chỉ quan tâm đến những thay đổi của một network adapter cụ thể ví dụ như Wifi chẳng hạn, chúng ta có thể khởi tạo bằng phương thức init(requiredInterfaceType:) với tham số truyền vào là một kiểu dữ liệu NWInterface.InterfaceType như sau:

    Đây là các interface type mà NWPathMonitor hỗ trợ theo dõi:

    • cellular
    • loopback
    • wifi
    • wiredEthernet
    • other

    Để nhận được các thay đổi về network state, chúng ta chỉ cần gán callback cho một thuộc tính có tên pathUpdateHandler, callback này sẽ được gọi đến bất cứ khi nào có sự thay đổi đối với network, ví dụ như khi điện thoại chuyển từ sử dụng cellular sang wifi. Trong callback có một giá trị trả về có kiểu NWPath giúp chúng ta có thể dễ dàng xác định được trạng thái đã connect hay chưa:

    Đối tượng NWPath có các thuộc tính mà qua đó chúng ta thể dùng để xác định khá nhiều trạng thái của network. Một trong số đó là một thuộc tính khá thú vị mang tên isExpensive dùng để xác định xem network hiện tại có được coi là đắt tiền hay không. Chúng ta cũng có thể kiểm tra xem có hỗ trợ DNS, IPv4 hoặc IPv6 hay không. Ngoài ra nếu muốn xem network trước khi bị thay đổi sang network hiện tại là gì chúng ta có thể sử dụng thuộc tính usedInterfaceType.

    Để bắt đầu lắng nghe trạng thái connect của device, chúng ta gọi phương thức start(). Và gọi stop() khi muốn kết thúc việc lắng nghe.

    Khi đã hoàn tất quá trình lắng nghe sự thay đổi, chúng ta chỉ cần đơn giản gọi phương thức cancel(). Lưu ý rằng một khi đã gọi phương thức cancel() chúng ta không thể gọi phương thức start() được nữa. Thay vào đó chúng ta cần khởi tạo một biến NWPathMonitor mới.

    Trên đây mình đã giới thiệu đến các bạn về NWPathMonitor một framework hỗ trợ từ iOS 12 của Apple, cũng như cách sử dụng của nó.

    Mình hi vọng bài viết có thể giúp ích được cho các bạn. Chúc các bạn thành công!

  • Tạo server mock bằng Postman

    Tạo server mock bằng Postman

    Hi mọi người. Trong quá trình develop chắc hẳn các bạn đã từng gặp trường trường hợp server đã define json response nhưng server deploy. Việc chờ server và làm UI trước thì cũng được, nhưng trong khi làm UI mà có một server để thực hiện request và có thể thay đổi response theo mong muốn của mình thì thật là tuyệt vời.

    Trong bài này mình sẽ hướng dẫn cách tạo ra một server mock thông qua postman.

    Tóm tắt nội dung của bài:

    • Gửi một request
    • Lưu request vào collection
    • lưu response
    • Tạo mock server từ collection
    • request đến server mock

    Bắt đầu nào!!!!

    Step 1: Gửi một request

    Send một request bất kì. Mục đích của việc send một request này là để lấy response và lưu lại

    Ở đây mình request với url https://postman-echo.com/get?test=123


    Đây là response từ https://postman-echo.com/get?test=123

    Step 2: Lưu request vào một collection

    Đầu tiền mình thực hiện tạo một collection mới và đặt tên là “Mock Collection”




    Tiếp theo lưu request vào Mock Collection

    Step 3: Lưu response

    Lưu response của request bên trên vào trong Mock Collection




    Sau khi lưu response, các bạn có thể đổi tên response đó, ở đây mình đổi tên thành “test-get”

    Step 4: Tạo Mock Server từ collection

    Tạo Mock Server cho Mock Collection vừa tạo ở trên.


    Đặt tên cho server mock và ấn tạo


    Về cơ bản thì thực hiện đến đây là server mock đã hoàn thành và có thể thực hiện request rồi. Các bạn nhớ copy url của server mock nhé!!!

    Step 5: Request đến server mock

    Dùng url đã copy ở step 4 và thực hiện một request bằng postman
    url mình đã copy ở step 4 như sau: https://f4205914-b48b-4ff4-9dfe-5cbf131a24d4.mock.pstmn.io


    Opp!!! lỗi rồi…. Lúc này server mock sẽ trả ra lỗi 404 như ảnh bên trên. Lý do lỗi ở đây là bạn chưa thêm path cho mock server url.

    Các bạn thêm đuôi /get cho url và đổi method thành GET. Lúc này server mock sẽ trả ra response như đã lưu ở step 3

    sau khi sửa url thì nó sẽ như thế này: https://f4205914-b48b-4ff4-9dfe-5cbf131a24d4.mock.pstmn.io/get



    Các bạn có thể đổi response của server mock theo mong muốn của mình
    Ở đây mình đổi json đã lưu ở step 3 thành {“title”: “Hello World”}. sau khi đổi json response thì ấn Save ở góc trên bên phải.


    Sau khi thay đổi và lưu response xong, thực hiện lại request đến server mock. Và kết quả như sẽ như response đã sửa ở trên

    Trên đây mình đã hướng dẫn các bạn tạo server mock và có thể chỉnh sửa response theo mong muốn của mình.

    Mình hi vọng bài viết có thể giúp ích được cho các bạn. Chúc các bạn thành công!

    Tham khảo: https://learning.postman.com/docs/designing-and-developing-your-api/mocking-data/mocking-with-examples/

  • Highlight text of UILabel in Swift

    Highlight text of UILabel in Swift

    Hi mọi người, mấy năm trước mình có làm một dự án mobile về mảng Logistics, trong ứng dụng thường sử dụng khá nhiều các text, một số từ được Highlight text đi kèm với các action tương tự như là một button nhằm mục đích gây sự chú ý với người dùng. Để làm được việc này chúng ta cần xác định được vị trí text cần Highlight để thực hiện thay đổi UI cho đoạn text đó gắn action cho nó. Mình thấy đây là một tính năng khá thú vị và sẽ gặp nhiều trong các dự án sắp tới của các bạn. Vậy nên mình xin chia sẻ cách làm của mình như sau.

    Cách Highlight text

    Về lý thuyết để highlight text trong swift thì chúng ta cần l xác định vị trí(position) và độ dài(lenght) của text cần highlight sau đó thực hiện thay đổi thuộc tính của đoạn text đó bằng NSAttributedString.

    Việc bắt sư kiện khi chúng ta tương tác với Highlight text cũng phải tìm vị trí và độ dài của đoạn text, sau đó chúng ta dựa vào điểm người dùng bấm vào trên Label để xác định xem người dùng có bấm đúng vị trí text được highlight hay không.

    1. Cách thực hiện Highlight text

    Đầu tiên chúng ta sẽ tạo một func trong extension của UILabel như sau:

    extension UILabel {
        func highlightText(_ text: String, highlightColor: UIColor, in mainText: String) {
            // chuyển mainText sang NSMutableAttributedString để xử lý tìm range của highlight text
            let highlightAttributedString = NSMutableAttributedString(string: mainText)
            // xác định vị trí, độ dài của text cần highlight
            let range = (mainText as NSString).range(of: text)
            // thêm thuộc tính cho đoạn text cần highlight
            highlightAttributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: highlightColor, range: range)
            // gán giá trị vào label
            self.attributedText = highlightAttributedString
        }
    }

    Khi sử dụng chúng ta sẽ làm như sau:

    Trường hợp này mình sẽ biến chữ “DaoNM2” trong “Good evening! DaoNM2” thành màu cam như sau

    lbInfo.highlightText("DaoNM2", highlightColor: .red, in: "Good evening! DaoNM2")
    Kết quả

    2. Bắt sự kiện và thực hiện hành động khi bấm vào text được Highlight

    Ở mục 1 mình đã hướng dẫn cách thực hiện đổi màu text của 1 đoạn text trong UILabel, vậy để bắt sự kiện khi chúng ta bấm vào thì làm cách nào?

    Đầu tiên chúng ta sẽ tạo một func trong extension của UITapGestureRecognizer, nhằm mục đích xử lí điểm chạm của người dùng và xác định xem có đúng vị trí của text đã được Highlight hay không như sau:

    extension UITapGestureRecognizer {
        func didTapHighlightedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
            guard let attributedText = label.attributedText else {
                return false
            }
    
            let mutableStr = NSMutableAttributedString(attributedString: attributedText)
            mutableStr.addAttributes([NSAttributedString.Key.font: label.font!], range: NSRange(location: 0, length: attributedText.length))
               
            // If the label have text alignment. Delete this code if label have a default (left) aligment. Possible to add the attribute in previous adding.
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.alignment = label.textAlignment
            mutableStr.addAttributes([NSAttributedString.Key.paragraphStyle: paragraphStyle], range: NSRange(location: 0, length: attributedText.length))
    
            // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
            let layoutManager = NSLayoutManager()
            let textContainer = NSTextContainer(size: CGSize.zero)
            let textStorage = NSTextStorage(attributedString: mutableStr)
               
            // Configure layoutManager and textStorage
            layoutManager.addTextContainer(textContainer)
            textStorage.addLayoutManager(layoutManager)
               
            // Configure textContainer
            textContainer.lineFragmentPadding = 0.0
            textContainer.lineBreakMode = label.lineBreakMode
            textContainer.maximumNumberOfLines = label.numberOfLines
            let labelSize = label.bounds.size
            textContainer.size = labelSize
               
            // Find the tapped character location and compare it to the specified range
            let locationOfTouchInLabel = self.location(in: label)
            let textBoundingBox = layoutManager.usedRect(for: textContainer)
            let textContainerOffset = CGPoint(x: (labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
                                              y: (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)
            let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x,
                                                         y: locationOfTouchInLabel.y - textContainerOffset.y)
            let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
            return NSLocationInRange(indexOfCharacter, targetRange)
        }
    }

    Trong hàm này mình sẽ dùng NSLayoutManager để xác định xem điểm chạm của người dùng mà UITapGestureRecognizer bắt được có đúng vị trí highlight text hay không.

    func này sẽ trả về cho chúng ta biết được vị trí người dùng đang chạm vào UILabel có trùng với range truyền vào hay không.

    Để ứng dụng nó vào bài toán của chúng ta thì chúng ta sẽ thực hiện nó như sau:

        private func setUpLabelInfo() {
            lbInfo.highlightText("More...", highlightColor: .red, in: "Two one-offs, a roadster and a coupé, mark the end of production of super sports cars powered by the V12 combustion engine in the lead-up to the hybrid era. More...")
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapMore(_:)))
            lbInfo.isUserInteractionEnabled = true
            lbInfo.addGestureRecognizer(tapGesture)
        }
        
        @objc
        private func tapMore(_ gesture: UITapGestureRecognizer) {
            let mainText = lbInfo.text ?? ""
            let highlightText = "More..."
            let highlightTextRange = ((mainText) as NSString).range(of: highlightText)
            if gesture.didTapHighlightedTextInLabel(label: lbInfo, inRange: highlightTextRange) {
                print("Did tap: \(highlightText), hightlightRange: \(highlightTextRange)")
            }
        }

    Ở viewDidLoad chúng ta chỉ cần gọi nó ra là xong.

       override func viewDidLoad() {
            super.viewDidLoad()
    
            lbTitle.textColor = .orange
            lbTitle.textAlignment = .center
            lbTitle.text = "Lambo"
            setUpLabelInfo()
        }

    Kết quả thu được như sau:

    Vậy là chúng ta đã có thể thêm action vào cho text được highlight.

    Từ ví dụ này chúng ta có thể tuỳ biến cho phù hợp dự án của bạn hoặc phát triển nó lên theo cách mà các bạn mong muốn.

    Mình hi vọng bài viết giúp cho các bạn có thêm phương án lựa chọn khi tham gia những dự án có yêu cầu tương tự. Chúc các bạn thành công!