Home Blog Page 95

Các vòng lặp trong Python

Các vòng lặp trong Python

Bài viết được sự cho phép của tác giả Nguyễn Chí Thức

Chắc hẳn bạn cũng đã khá quen thuộc với khái niệm vòng lặp trong C, hoặc C++. Ngôn ngữ Python cũng cung cấp cho bạn các kiểu vòng lặp như vòng lặp while, vòng lặp for, cấu trúc lồng vòng lặp. Bên cạnh đó, để hỗ trợ cho trình thực thi của vòng lặp, Python cũng hỗ trợ một số lệnh điều khiển vòng lặp như lệnh break, lệnh continue và lệnh pass. Phần tiếp theo chúng ta sẽ tìm hiểu sơ qua về từng loại này.

Các vòng lặp trong Python

Vòng lặp while: lặp đi lặp lại một lệnh hoặc một nhóm lệnh trong khi một điều kiện đã cho là TRUE. Nó kiểm tra điều kiện trước khi thực thi phần thân của vòng lặp.

Vòng lặp for: nó có khả năng lặp qua các item của bất kỳ dãy nào như một list hoặc một string.

Lồng vòng lặp: bạn có thể sử dụng một hoặc nhiều vòng lặp bên trong bất kỳ vòng lặp while, for hoặc do…while nào.

Tuyển python lương cao các công ty IT hàng đầu

Các lệnh điều khiển vòng lặp trong Python

Các lệnh điều khiển vòng lặp thay đổi trình thực thi thông thường. Khi trình thực thi rời khỏi một phạm vi, thì tất cả các đối tượng tự động được tạo trong phạm vi đó sẽ bị hủy. Python hỗ trợ các lệnh điều khiển vòng lặp sau:

Lệnh break: kết thúc lệnh vòng lặp và truyền trình thực thi tới lệnh ngay sau vòng lặp đó.

Lệnh continue: làm cho vòng lặp nhảy qua phần còn lại của thân vòng lặp và tự động kiểm tra lại điều kiện của nó trước khi lặp lại vòng mới.

Lệnh pass: được sử dụng khi một lệnh là cần thiết theo cú pháp, nhưng bạn lại không muốn bất cứ lệnh hoặc code nào được thực thi.

Vòng lặp while trong Python

Vòng lặp while trong Python thực thi lặp đi lặp lại các lệnh hoặc phần thân của vòng lặp miễn là điều kiện đã cho là true. Khi điều kiện là false, thì điều khiển sẽ thoát ra khỏi vòng lặp. Dưới đây là cú pháp của vòng lặp while trong Python:

while bieu_thuc:
   cac_lenh

Ở đây, cac_lenh có thể là một lệnh đơn hoặc một khối lệnh. Bieu_thuc có thể là bất kỳ biểu thức nào. Điều đáng chú ý về vòng lặp while là vòng lặp này có thể không chạy. Bởi vì khi điều kiện được kiểm tra là false, thì phần thân vòng lặp sẽ bị bỏ qua và lệnh đầu tiên ngay sau vòng lặp sẽ được thực thi.

Ví dụ minh họa cho vòng lặp while trong Python:

count = 0
while (count < 9):
   print 'So thu tu cua ban la:', count
   count = count + 1

print "Good bye!"

Khi code trên được thực thi sẽ cho kết quả:

So thu tu cua ban la: 0
So thu tu cua ban la: 1
So thu tu cua ban la: 2
So thu tu cua ban la: 3
So thu tu cua ban la: 4
So thu tu cua ban la: 5
So thu tu cua ban la: 6
So thu tu cua ban la: 7
So thu tu cua ban la: 8
Good bye!

Trong ví dụ trên, gồm lệnh print và lệnh tăng, khối code sẽ được thực thi lặp đi lặp lại tới khi count không còn nhỏ hơn 9 nữa. Với mỗi lần lặp, giá trị của count được hiển thị và sau đó được tăng thêm 1.

  Python: Cách in mà không cần dòng mới

Vòng lặp vô hạn trong Python

Một vòng lặp vô hạn là vòng lặp mà điều kiện của nó là luôn true. Bạn phải đặc biệt chú ý khi sử dụng các vòng lặp while bởi vì tồn tại khả năng là điều kiện của nó sẽ không bao giờ false, tức là làm cho vòng lặp không bao giờ kết thúc.

Một vòng lặp vô hạn có thể là rất hữu ích trong lập trình client/server, tại đó server cần chạy liên tục để mà các chương trình client có thể giao tiếp với nó khi cần thiết.

var = 1
while var == 1 :  # Lenh nay tao mot vong lap vo han
   num = raw_input("Hay nhap mot so  :")
   print "So da nhap la: ", num

print "Good bye!"

Khi code trên được thực thi sẽ cho kết quả:

Hay nhap mot so  :20
So da nhap la:  20
Hay nhap mot so  :29
So da nhap la:  29
Hay nhap mot so  :3
So da nhap la:  3
Hay nhap mot so between :Traceback (most recent call last):
  File "test.py", line 5, in <module>
    num = raw_input("Hay nhap mot so :")
KeyboardInterrupt

Ví dụ trên là một vòng lặp vô hạn, và để thoát khỏi nó thì bạn cần nhấn phím CTRL+C.

Sử dụng lệnh else với vòng lặp while trong Python

Python cho phép bạn có một lệnh else được sử dụng kết hợp với một lệnh vòng lặp. Khi else được sử dụng với một vòng lặp while, thì lệnh else được thực thi khi điều kiện là false.

Ví dụ sau minh họa sự kết hợp của lệnh else với một lệnh while để in các số, miễn là số này nhỏ hơn 5, nếu không lệnh else được thực thi.

count = 0
while count < 5:
   print count, " la nho hon 5"
   count = count + 1
else:
   print count, " la khong nho hon 5"

Khi code trên được thực thi sẽ cho kết quả:

0 la nho hon 5
1 la nho hon 5
2 la nho hon 5
3 la nho hon 5
4 la nho hon 5
5 la khong nho hon 5

Suite: lệnh while trên một dòng đơn

Tương tự như cú pháp của lệnh if, nếu mệnh đề while của bạn chỉ gồm một lệnh đơn, thì nó có thể được đặt trên cùng một dòng như là header của lệnh while này, ví dụ:

flag = 1

while (flag): print 'Flag da cung cap nay la true!'

print "Good bye!"

Bạn không nên thử ví dụ này vì nó là một vòng lặp vô hạn và bạn cần nhấn CTRL+C để thoát.

  Hướng dẫn từng bước lập trình web với Python

Vòng lặp for trong Python

Vòng lặp for được sử dụng để lặp một biến qua một dãy (List hoặc String) theo thứ tự mà chúng xuất hiện. Sau đây là cú pháp của vòng lặp for:

for bien_vong_lap in day_sequense:
   cac_lenh

Nếu một dãy day_sequense gồm một danh sách các biểu thức, nó được ước lượng đầu tiên. Sau đó, item đầu tiên trong dãy được gán cho biến vòng lặp bien_vong_lap. Tiếp theo, các khối lệnh cac_lenh được thực thi và khối lệnh này được thực thi tới khi dãy này đã được lặp xong.

Dưới đây là ví dụ minh họa vòng lặp for trong Python:

for letter in 'Python':     # Vi du dau tien
   print 'Chu cai hien tai :', letter

qua = ['chuoi', 'tao',  'xoai']
for qua in qua:        # Vi du thu hai
   print 'Ban co thich an :', qua

print "Good bye!"

Khi code trên được thực thi sẽ cho kết quả:

Chu cai hien tai : P
Chu cai hien tai : y
Chu cai hien tai : t
Chu cai hien tai : h
Chu cai hien tai : o
Chu cai hien tai : n
Ban co thich an : chuoi
Ban co thich an : tao
Ban co thich an : xoai
Good bye!

Lặp qua index của dãy

Một cách khác để lặp qua mỗi item là bởi chỉ mục index bên trong dãy đó. Bạn theo dõi ví dụ đơn giản sau:

qua = ['chuoi', 'tao',  'xoai']
for index in range(len(qua)):
   print 'Ban co thich an :', qua[index]

print "Good bye!"
Khi code trên được thực thi sẽ cho kết quả:

Ban co thich an : chuoi
Ban co thich an : tao
Ban co thich an : xoai
Good bye!

Ở đây, chúng ta sử dụng hàm len(), có sẵn trong Python, để cung cấp tổng số phần tử trong tuple cũng như hàm range() để cung cấp cho chúng ta dãy thực sự để lặp qua đó.

  Python Lists: Append vs Extend (Có ví dụ)

Sử dụng lệnh else với vòng lặp for trong Python

Python cho phép bạn có một lệnh else để liên hợp với một lệnh vòng lặp. Với vòng lặp for, lệnh else được thực thi khi vòng lặp đã lặp qua hết các phần tử trong list.

Ví dụ sau minh họa sự kết hợp của một lệnh else với một lệnh for để tìm kiếm các số nguyên tố từ 10 tới 20.

for num in range(10,20):  #de lap tu 10 toi 20
   for i in range(2,num): #de lap tren cac thua so cua mot so
      if num%i == 0:      #de xac dinh thua so dau tien
         j=num/i          #de uoc luong thua so thu hai
         print '%d la bang %d * %d' % (num,i,j)
         break #de di chuyen toi so tiep theo, la vong FOR dau tien
   else:                  # else la mot phan cua vong lap
      print num, 'la so nguyen to'

Khi code trên được thực thi sẽ cho kết quả:

10 la bang 2 * 5
11 la so nguyen to
12 la bang 2 * 6
13 la so nguyen to
14 la bang 2 * 7
15 la bang 3 * 5
16 la bang 2 * 8
17 la so nguyen to
18 la bang 2 * 9
19 la so nguyen to

Lồng vòng lặp trong Python

Ngôn ngữ lập trình Python cho phép bạn sử dụng một vòng lặp bên trong một vòng lặp khác. Dưới đây là cú pháp và một số ví dụ để minh họa điều này.

Cú pháp lồng vòng lặp for trong Python

for bien_vong_lap in day_seq:
   for bien_vong_lap in day_seq:
      cac_lenh
   cac_lenh

Cú pháp lồng vòng lặp while trong Python

while bieu_thuc:
   while bieu_thuc:
      cac_lenh
   cac_lenh

Một ghi chú khác trong lồng vòng lặp là bạn có thể đặt bất cứ kiểu vòng lặp nào bên trong kiểu vòng lặp khác. Ví dụ như bạn có thể đặt một vòng lặp for bên trong một vòng lặp while hoặc ngược lại.
Ví dụ sau sử dụng lồng vòng lặp để tìm số nguyên tố từ 2 tới 100.

i = 2
while(i < 100):
   j = 2
   while(j <= (i/j)):
      if not(i%j): break
      j = j + 1
   if (j > i/j) : print i, " la so nguyen to"
   i = i + 1

print "Good bye!"

Khi code trên được thực thi sẽ cho kết quả:

2 la so nguyen to
3 la so nguyen to
5 la so nguyen to
7 la so nguyen to
11 la so nguyen to
13 la so nguyen to
17 la so nguyen to
19 la so nguyen to
23 la so nguyen to
29 la so nguyen to
31 la so nguyen to
37 la so nguyen to
41 la so nguyen to
43 la so nguyen to
47 la so nguyen to
53 la so nguyen to
59 la so nguyen to
61 la so nguyen to
67 la so nguyen to
71 la so nguyen to
73 la so nguyen to
79 la so nguyen to
83 la so nguyen to
89 la so nguyen to
97 la so nguyen to
Good bye!

Chúc các bạn thành công!

Bài viết gốc được đăng tải tại ucode.vn

Xem thêm Việc làm IT Hà Nội, đà nẵng, hcm hấp dẫn trên TopDev

Fix lỗi “Fopen Failed To Open Stream: Permission Denied Windows Server”

fix lỗi

Bài viết được sự cho phép của BQT Kinh nghiệm lập trình

Xin chào mọi người, mình quay trở lại rồi đây. Hôm nay mình chia sẻ 1 trick rất rất nhỏ và đơn giản để fix các vấn đề liên quan tới quyền truy cập trong Windows Server. Đọc tới đây không ít bạn tặc lưỡi, cái này thì mặc định rồi thì cần gì fix nhỉ? Ồ vậy mà khi đối mặt với nó, nếu không biết cách xử lý chúng ta sẽ tốn rất nhiều thời gian và chuốc lấy muôn vàn cay cú, rồi lại tự ngẫm, biết thế dùng server Linux có phải đỡ mệt không? Tuy nhiên đôi lúc chúng ta vẫn phải tìm cách sống chung với lũ trong khi chưa thấy phao cứu sinh ở đâu.

  Fix lỗi "Fopen Failed To Open Stream: Permission Denied Windows Server"
  Fix Lỗi "RDP Authentication Error Has Occurred – The Function Requested Is Not Supported"

Nguyên nhân????

Lỗi trên xuất hiện khi nào? Lỗi trên găp phải khi chúng ta deploy phần mềm thao tác với các file, folder trong ổ C của Windows Server, nơi mà không phải lúc nào ta cũng có quyền read/write/delete một cách tùy tiện.

Thông thường các bạn sẽ nhận được message như sau khi phát triển hệ thống với PHP:

“fopen failed to open stream: Permission denied windows server”

Cách xử lý

window-server-kho-chiuMột hệ điều hành cực kỳ tiện dụng nhưng cũng nhiều ràng buộc khó chịu!!!

Nguyên nhân rất rõ ràng rồi: chúng ta không đủ quyền để thao tác với folder/file mà ta đang cần xử lý. Vậy cách xử lý rất đơn giản: Cấp quyền.

Khoan!!! Nhưng mà cấp quyền gì, cho tài khoản nào nhỉ? Và cấp như nào???

Phần này đôi khi khiến chúng ta mất rất nhiều thời gian để mò mẫm, hỏi bác gu gồ, nhìn có vẻ dễ nhưng chả hiểu sao mãi lại không xử lý được nhỉ. Và thực tế thì nó rất dễ. Mình đã xử lý như sau:

==>>> Gán quyền “write” cho IUSR_SERVER và DONE.

Chúc các bạn thành công, và không tốn nhiều thời gian vào những bug lặt vặt như trên đây.

kinhnghiemlaptrinh.com

Bài viết gốc được đăng tải tại kinhnghiemlaptrinh.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Kế thừa là gì? Các kiểu kế thừa trong C++ và cách sử dụng

Kế thừa trong C++

Bài viết được sự cho phép của tác giả Khiêm Lê

Kế thừa trong lập trình hướng đối tượng là một tính chất rất quan trọng, do đó, các bạn nên nắm kỹ phần này để có thể học tốt lập trình hướng đối tượng. Trong các kỳ kiểm tra, phỏng vấn xin việc cũng thường được hỏi về tính chất này. Để đọc hiểu về kiến thức kế thừa trong C++ tốt nhất, các bạn nên có biến thức Cơ bản về class trong C++, nếu chưa hãy dành một ít thời gian đọc bài viết về class của mình. Nếu bạn đã sẵn sàng thì hãy bắt đầu thôi!

Kế thừa là gì?

Kế thừa là một trong các tính chất đặc trưng của lập trình hướng đối tượng, bên cạnh tính đóng gói (encapsulation), che giấu thông tin (hiding information), tính đa hình (polymorphism) và tính trừu tượng (abstraction). Vậy thì kế thừa là gì?

Kế thừa (inheritance) là một tính chất đặc trưng của lập trình hướng đối tượng. Nó có nghĩa là một class thừa hưởng lại tất cả các thuộc tính, phương thức của class mà nó kế thừa.

Class kế thừa từ một class khác gọi là lớp con (child class hay subclass) hay lớp dẫn xuất (derived class). Class được lớp khác kế thừa được gọi là lớp cha (parent class hay superclass) hay lớp cơ sở (base class).

Kế thừa là gì?

Ví dụ như bạn có một class con người, có các thuộc tính cơ bản như họ tên, ngày sinh, quê quán, mình khai báo thêm một class sinh viên kế thừa từ class con người. Vậy, class sinh viên sẽ có các thuộc tính họ tên, ngày sinh, quê quán từ class con người mà không cần phải khai báo. Class con người sẽ là lớp cha và class sinh viên là lớp con.

Ngoài các thuộc tính của class cha, class con còn có thể có thêm các thuộc tính, phương thức của riêng mình. Ví dụ như sinh viên thì có thêm các thuộc tính như MSSV, tên trường, chuyên ngành…

Chúng ta đã hiểu được kế thừa là gì rồi. Vậy thì câu hỏi đặt ra lúc này là tại sao cần có kế thừa? Hãy cùng tìm hiểu tiếp nhé.

  1001 Tips: Con trỏ và hàm (Pointer & Function) trong C++
  Bảng băm trong C++

Tại sao cần có kế thừa?

Trong lập trình, chắc hẳn các bạn sẽ gặp phải rất nhiều hành động lặp đi lặp lại, và chắc chắn một điều rằng sẽ không ai rảnh mà ngồi code lại chúng từ đầu cả. Thay vào đó, họ sẽ sử dụng lại các đoạn code đã có để thực hiện công việc tương tự. Nói đến đây chắc các bạn cũng đã hiểu kế thừa có tác dụng gì rồi đúng không nào!

Kế thừa giúp ta có thể tái sử dụng lại những đoạn code đã có, tránh việc giải quyết lại các bài toán con đã có lời giải trước đó, gây lãng phí thời gian. Nếu chỉ là một, hai hoặc ba hành động cần giải quyết thì không thành vấn đề, nhưng nếu là một trăm thì đó lại là chuyện khác, sẽ tốn của bạn kha khá thời gian nếu bạn không biết tận dụng những gì đã có đấy!

Trong ví dụ ở đầu bài viết, các bạn có để ý thấy mối quan hệ giữa class con người và sinh viên không? Đúng vậy, mối quan hệ đó là “sinh viên là một con người”, sinh viên cũng có các thông tin như họ tên, ngày sinh, quê quán… và được biểu diễn bằng các thuộc tính trong class. Vậy thì tính kế thừa giúp cho chúng ta có thể dễ dàng thể hiện mối quan hệ giữa các đối tượng hơn (sẽ được trình bày bên dưới).

Sinh viên ngoài có những đặc điểm của class con người ra, còn có thể có thêm các đặc điểm của riêng mình ví dụ như tên trường, tên ngành, năm học… Đây là mối quan hệ tổng quát hóa – đặc biệt hóa trong kế thừa. Class con người chính là tổng quát hóa và class con sinh viên chính là đặc biệt hóa.

Mối quan hệ giữa các đối tượng

Có hai mối quan hệ giữa các đối tượng trong C++, quan hệ “Has-A” và quan hệ “Is-A”.

Quan hệ Has-A

Có 3 loại quan hệ “has a” giữa các đối tượng, mối quan hệ một – một, mối quan hệ một – nhiều và mối quan hệ nhiều – nhiều.

Quan hệ một – một (1 – 1) là mối quan hệ giữa hai đối tượng thuộc hai class khác nhau, mỗi đối tượng thuộc class này có quan hệ duy nhất với một đối tượng thuộc class kia và tương tự mỗi đối tượng của class kia cũng chỉ có quan hệ duy nhất với một đối tượng thuộc class này.

Ví dụ như mỗi lớp chỉ có một giáo viên chủ nhiệm, mỗi giáo viên chỉ được chủ nhiệm một lớp, mỗi một quốc gia chỉ có một thủ đô, một thành phố chỉ có thể là thủ đô của một quốc gia…

Quan hệ một – nhiều (1 – n) là mối quan hệ giữa đối tượng thuộc hai class khác nhay, mỗi đối tượng thuộc class này có quan hệ duy nhất với một đối tượng thuộc class kia, nhưng mỗi đối tượng thuộc class kia có thể có quan hệ với nhiều đối tượng thuộc class này.

Ví dụ như mỗi học sinh chỉ có một lớp học, nhưng mỗi lớp học lại có thể có nhiều học sinh, hay mỗi nhân viên chỉ có thể làm cho một công ty nhưng một công ty lại có thể có nhiều nhân viên…

Quan hệ nhiều – nhiều (n – n) là mối quan hệ giữa đối tượng thuộc hai class khác nhau, mỗi đối tượng thuộc class này có thể quan hệ với nhiều đối tượng thuộc class kia, và mỗi đối tượng thuộc class kia cũng có thể có quan hệ với nhiều đối tượng thuộc lớp này.

Ví dụ như mỗi bệnh nhân có thể thăm khám bệnh ở nhiều bác sĩ khác nhau, và mỗi bác sĩ lại có thể chữa cho nhiều bệnh nhân…

Quan hệ tổng quát – đặc biệt hóa là mối quan hệ giữa đối tượng thuộc hai class khác nhau khi đối tượng thuộc class này là một trường hợp đặc biệt của class kia, và đối tượng thuộc class kia là trường hợp tổng quát của đối tượng thuộc class này.

Ví dụ như con người là tổng quát hóa của sinh viên, còn sinh viên là đặc biệt hóa của con người, xe máy hiệu exciter là đặc biệt hóa của xe máy và xe máy là tổng quát của xe máy hiệu exciter…

Quan hệ Is-A

Mối quan hệ Is-A giữa các đối tượng chính là class này là một class kia. Cũng ví dụ từ đầu bài viết đến giờ, sinh viên là một con người (student is a human). Đó chính là mối quan hệ có được do thực hiện kế thừa.

Các loại kế thừa trong C++

Chúng ta đã cùng tìm hiểu qua về kế thừa là gì và tại sao cần có kế thừa, tiếp theo, hãy cùng tìm hiểu xem có những loại kế thừa nào nha.

Các loại kế thừa trong C++

Kế thừa đơn

Kế thừa đơn (single inheritance) là một class con kế thừa duy nhất từ một class cha. Ví dụ như class sinh viên chỉ kế thừa duy nhất từ class con người, đó là một kế thừa đơn.

Kế thừa đơn

Kế thừa đa cấp

Kế thừa đa cấp (multilevel inheritance) là một class con kế thừa từ một class cha, class cha đó lại kết thừa từ một lớp khác. Ví dụ như class sinh viên kế thừa từ class học sinh, class học sinh lại kế thừa từ class con người, đó là một kế thừa đa cấp.

Kế thừa đa cấp

 

Kế thừa phân cấp

Kế thừa phân cấp (hierarchical inheritance) là khi có nhiều hơn một class con kế thừa từ class cha. Ví dụ như class sinh viên và class công nhân đều kế thừa từ class cha là con người.

Một sơ đồ class không chỉ có một trong 3 loại kế thừa trên, nó thậm chí có thể có cả 3 và điều này hoàn toàn bình thường và gặp rất thường xuyên.

kế thừa tổng hợp trong c++

Vậy là chúng ta đã tìm hiểu xong các loại kế thừa, giờ hãy xem cú pháp thực hiện kế thừa trong C++ như thế nào.

Cú pháp

Cú pháp để khai báo một lớp kế thừa từ một lớp như sau:

class <tên_class_con> : <phạm_vi_truy_cập> <tên_class_cha>
{
    // code goes here
};

Trong đó, class cha và class con đã được trình bày ở bên trên, phạm vi truy cập sẽ được mình trình bày ngay bến dưới.

Giả sử mình có một class A với các thuộc tính, phương thức bên trong. Mình muốn khai báo một class B kế thừa từ class A, mình sẽ có cú pháp như sau:

class B : public/private/protected A
{
    // code goes here
};

Khi này, các thuộc tính trong class A sẽ được class B kế thừa. public/private/protected là phạm vi truy cập của các thuộc tính sẽ được kế thừa. Hãy cùng tìm hiểu xem cụ thể phạm vi truy cập là như thế nào ngay bên dưới.

Phạm vi truy cập

Trong bài Cơ bản về Class trong C++ mình đã có giới thiệu qua về phạm vi truy cập (access modifier). Tuy nhiên, phạm vi truy cập trong bài đó khác với phạm vi truy cập trong kế thừa.

Có hai loại phạm vi truy cập, truy cập các thành phần từ bên ngoài đối tượng được gọi là truy cập theo chiều ngang. Truy cập các thành phần của class cha từ class con được gọi là truy cập theo chiều dọc. Phạm vi truy cập trong bài Cơ bản về Class trong C++ chính là truy cập theo chiều ngang.

Đối với phạm vi truy cập trong kế thừa, đó là truy cập theo chiều dọc. Giả sử mình có class B kế thừa từ class A, cụ thể các phạm vi truy cập đó là như sau:

  • public:
    • Các thuộc tính public của A sẽ trở thành thuộc tính public của B
    • Các thuộc tính protected của A sẽ trở thành protected của B
  • private:
    • Các thuộc tính public của A sẽ trở thành thuộc tính private của B
    • Các thuộc tính protected của A sẽ trở thành private của B
  • protected:
    • Các thuộc tính public của A sẽ trở thành thuộc tính protected của B
    • Các thuộc tính protected của A sẽ trở thành thuộc tính protected của B

Đối với một class, thuộc tính protected cũng tương tự như private, chỉ có khác ở chỗ class con có thể truy cập thành phần protected, còn private lại không cho phép truy cập.

Phạm vi truy cập giúp đảm bảo tính đóng gói và che giấu thông tin của đối tượng. Ví dụ như khi thuộc tính public ở class cha, được kế thừa private sang class con, thì nó cũng trở thành private ở class con và không thể được truy cập từ bên ngoài class con. Ví dụ:

class A
{
public:
    int publicMethod;
};

class B : private A
{
};

// bên trong hàm main
B b;
cout << b.publicMethod; // lỗi vì lúc này publicMethod trở thành private method của B rồi

Cài đặt

Từ đầu bài viết đến giờ, mình nói khá nhiều về lý thuyết mà chưa có đoạn code nào cả. Để cho các bạn dễ hiểu hơn, mình sẽ sử dụng lại các ví dụ trong bài viết và code chúng bằng C++. Hãy bắt đầu với các quan hệ Has-A trước.

Quan hệ 1 – 1:

class GVCN
{
public:
    LopHoc lopHoc;
};

class LopHoc
{
public:
    GVCN gvcn;
};

Bạn nào chưa biết về vector có thể xem lại bài viết Vector trong C++ của mình nha.

Quan hệ 1 – n:

class HocSinh
{
public:
    LopHoc lopHoc;
};

class LopHoc
{
public:
    vector<HocSinh> hocSinh;
};

Quan hệ n – n:

class BenhNhan
{
public:
    vector<BacSi> bacSi;
};

class BacSi
{
public:
    vector<BenhNhan> benhNhan;
};

Quan hệ Is-A:

class ConNguoi
{
public:
    string hoTen;
    string ngaySinh;
    string queQuan;
};

class SinhVien : public ConNguoi
{
public:
    string MSSV;
    string tenTruong;
    string lop;
    string chuyenNganh;
};

Truy xuất thành phần từ lớp cơ sở

Khi class con kế thừa thành phần từ class cơ sở, các thành phần của nó cũng sẽ được thừa hưởng từ class cơ sở. Điều này có nghĩa là, bạn có thể sử dụng con trỏ this để thao tác với thành phần của class hiện tại như bình thường. Ví dụ:

class A
{
public:
    int count;

    void sayHello()
    {
        cout << "Hello, welcome to KhiemLe.Dev!";
    }
};

class B : public A
{
public:
    B() // constructor
    {
        this->count = 0; // thuộc tính count được kế thừa và có thể truy cập qua con trỏ this
        this->sayHello(); // phương thức cũng được kế thừa
    }
};

Override phương thức từ lớp cơ sở

Trong khi sử dụng tính kế thừa, bạn sẽ gặp phải trường hợp hai phương thức ở class con và class cha trùng tên nhau. Trong trường hợp này, phương thức được khai báo và định nghĩa ở class con sẽ ghi đè lên phương thức ở class cha và thay thế hoàn toàn nó. Ví dụ:

class A
{
public:
    void sayHello()
    {
        cout << "Hello, welcome to khiemle.dev!";
    }
};

class B : public A
{
public:
    void sayHello()
    {
        cout << "Chao mung ban den voi trang web cua Khiem Le!";
    }
};

// trong hàm main
B b;
b.sayHello(); // Chao mung ban den voi trang web cua Khiem Le!

Vậy thì bạn có thể thấy được là, nếu như mà phương thức bị trùng tên thì nó bị ghi đè, vậy thì không còn đảm bảo được tính tái sử dụng code của tính kế thừa. Vậy làm sao chúng ta có thể tái sử dụng lại đoạn code của phương thức ở class cha?

Sử dụng toán tử phân giải phạm vi (::), chúng ta có thể gọi được phương thức từ class cha, ngoài ra chúng ta còn có thể bổ sung được những đoạn code của riêng phương thức ở class con. Ví dụ:

class A
{
public:
    void sayHello()
    {
        cout << "Hello, welcome to khiemle.dev!";
    }
};

class B : public A
{
public:
    void sayHello()
    {
        A::sayHello(); // Gọi lại phương thức ở class A
        // Thêm các đoạn code các bạn muốn
        cout << endl;
        cout << "Nho like va share nha ^^!";
    }
};

// trong hàm main
B b;
b.sayHello();
// Hello, welcome to khiemle.dev!
// Nho like va share nha ^^!

Thật đơn giản đúng không nào!

Upcasting và downcasting

Nhiều bạn có thể sẽ thắc mắc, ví dụ “sinh viên là một con người”, vậy thì con trỏ kiểu sinh viên có thể trỏ đến con trỏ kiểu con người hoặc ngược lại hay không. Đây chính là vấn đề upcasting và downcasting. Tuy nhiên, để đảm bảo tính toàn vẹn dữ liệu, bạn chỉ nên xem tham khảo chứ không nên dùng, do có thể gây mất mát dữ liệu hoặc nhận dữ liệu không mong muốn.

Upcasting

Upcasting là chuyển đổi đối tượng kiểu class con sang kiểu class cha. Tức là, con trỏ kiểu class cha có thể trỏ đến con trỏ kiểu class con, nhưng không bảo toàn được những thuộc tính, phương thức của class con. Việc chuyển kiểu này được thực hiện ngầm định bởi trình biên dịch C++. Các phương thức bị override sẽ bị override ngược lại bởi class cha. Ví dụ:

class A
{
public:
    void sayHello()
    {
        cout << "Hello, welcome to khiemle.dev!";
    }
};

class B : public A
{
public:
    void sayHello()
    {
        cout << "Nho like va share nha ^^!";
    }

    void sayGoodbye()
    {
        cout << "Goodbye!";
    }
};

// Trong hàm main
A *p = new B;
p->sayHello(); // Hello, welcome to khiemle.dev!
p->sayGoodbye(); // Lỗi do A không có phương thức này

Rõ ràng, nếu như sinh viên là một con người, thì con trỏ kiểu con người có thể lưu trữ được sinh viên đúng không bởi vì sinh viên là con người mà!

Tuy nhiên, do class cha là class tổng quát hóa, có ít thông tin hơn so với class con, do đó, khi chuyển kiểu ta không thể đảm bảo sự toàn vẹn dữ liệu được.

Downcasting

Downcasting thì ngược lại với upcasting, tức là chuyển đối tượng kiểu class cha sang đối tượng kiểu class con. Cách này lại không được trình biên dịch thực hiện tự động mà bạn phải tự chuyển kiểu nó. Tuy nhiên, các thuộc tính, phương thức ở class con nhiều hơn class cha, do class con là cụ thể hóa của class cha. Do đó, các thuộc tính không có ở class cha sẽ nhận giá trị rác không mong muốn. Ví dụ:

class A
{
public:
    void sayHello()
    {
        cout << "Hello, welcome to khiemle.dev!";
    }
};

class B : public A
{
public:
    int propInB;

    B()
    {
        this->propInB = 0;
    }

    void sayHello()
    {
        A::sayHello();
        cout << endl;
        cout << "Nho like va share nha ^^!";
    }
};

// trong hàm main
B *p = (B *)new A;
cout << p->propInB; // Một số ngẫu nhiên

Đa kế thừa

Đa kế thừa nghĩa là thay vì một class dẫn xuất kế thừa từ một class cơ sở, class dẫn xuất này có thể có kế thừa từ nhiều class cơ sở khác nhau. Ví dụ như một loài động vật thì sẽ kế thừa đặc điểm từ cả bố và mẹ của chúng.

Trong C++, để thực hiện đa kế thừa, cú pháp tương tự như kế thừa, nhưng class cơ sở có thể có nhiều hơn 1, ngăn cách nhau bởi dấu phẩy (,). Ví dụ:

class A {
public:
    A() {}
};
class B {
public:
    B() {}
};

// Class C kế thừa từ class A và B
class C : public A, public B {
public:
    C() {}
};

Khi thừa kế từ nhiều class cơ sở, bạn thấy sẽ có một vấn đề phát sinh chính là khi lớp cơ sở có phương thức trùng tên, khi gọi phương thức sẽ xảy ra sự mơ hồ. Sự mơ hồ nghĩa là trình biên dịch không biết bạn đang gọi phương thức từ class dẫn xuất nào. Ví dụ:

class A {
public:
    A() {}

    void sayHello() { cout << "Hello in class A"; }
};
class B {
public:
    B() {}

    void sayHello() { cout << "Hello in class B"; }
};

// Lớp C kế thừa từ lớp A và B
class C : public A, public B {
public:
    C() {}

    void sayHello() {
        sayHello(); // Báo lỗi do mơ hồ, không biết sayHello ở class A hay B
    }
};

Để giải quyết sự nhập nhằn này, bạn có thể sử dụng toán tử phạm vi (::) để chỉ rõ phương thức ở class nào như sau:

class A {
public:
    A() {}

    void sayHello() { cout << "Hello in class A"; }
};
class B {
public:
    B() {}

    void sayHello() { cout << "Hello in class B"; }
};

// Lớp C kế thừa từ lớp A và B
class C : public A, public B {
public:
    C() {}

    void sayHello() {
        A::sayHello(); // Gọi lại phương thức sayHello ở class A
    }
};

Tổng kết

Trong phần kế thừa này, cơ bản nó không khó, chỉ cần bạn phân tích đặc tả được dữ liệu mà đề bài cho, hoặc trong tình huống thực tế, bạn sẽ làm được nó. Trong thời gian tới mình sẽ cố gắng tổng hợp bài tập về phần này để các bạn nắm được về kế thừa trong C++.

Vậy là qua bài này, mình đã giới thiệu cho các bạn biết về kế thừa trong C++ nói riêng và trong lập trình hướng đối tượng nói chung. Hi vọng là các bạn thấy thấy bài viết của mình, đừng quên chia sẻ cho bạn bè cùng biết nha.

Nếu có bất kỳ thắc mắc hoặc góp ý nào, các bạn có thể comment phía bên dưới bài viết. Cảm ơn các bạn đã đọc bài viết!

Bài viết gốc được đăng tải tại khiemle.dev

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Building Microservices Application – Phần 3: Xác thực API bằng Oauth 2.0

microservices

Bài viết được sự cho phép của tác giả Edward Thien Hoang

Trong các bài viết trước chúng ta đã làm quen với Netflix Eureka, Ribbon, Zuul và Hystrix. Trong bài này hãy cùng làm quen với việc xác thực API sử dụng OAuth 2.0

Các bạn có thể tham khảo bài viết tiếng Anh tại: http://callistaenterprise.se/blogg/teknik/2015/04/27/building-microservices-part-3-secure-APIs-with-OAuth/

  Building Microservices Application - Phần 1: Sử dụng Netflix Eureka, Ribbon và Zuul
  Building Microservices Application - Phần 2: Xử lý "Chain of Failures" dùng Circuit Breaker Pattern với Netflix Hystrix

1. GIỚI THIỆU VỀ OAUTH VÀ SINGLE SIGN ON

Các hệ thống phân tán (decentralized system) ngày càng trở lên phổ biến và xác thực là một khía cạnh quan trọng của tất cả chúng. Xác thực Single Sign On (SSO) ngày càng trở nên cần thiết hơn bao giờ hết. Ngày nay, hầu hết các trang web đều yêu cầu xác thực để truy cập tới các tính năng và nội dung của nó. Với số lượng các trang web và dịch vụ đang tăng lên, một hệ thống đăng nhập tập trung (centralized login system) trở nên cần thiết.

SSO giải quyết một vấn đề lớn: làm thế nào để quản được số lượng người dùng đang tăng lên trên toàn bộ hệ thống gồm nhiều ứng dụng và dịch vụ. Các framework chẳng hạn như OpenID Connect và các dịch vụ chẳng hạn như Auth0 làm cho việc tích hợp Single Sign On vào các ứng dụng mới hoặc đã có của bạn trở nên dễ dàng hơn nhiều. Nếu bạn đang triển khai xác thực trên một ứng dụng hay dịch vụ mới hãy xem xét tích hợp SSO.

Đọc thêm tại: https://techmaster.vn/posts/34688/xac-thuc-single-sign-on-la-gi-va-no-hoat-dong-nhu-the-nao

OAuth2 là một chuẩn mở để ủy quyền/phân quyền (authorization), OAuth2 cũng là nền tảng của OpenID Connect, nó cung cấp OpenID (xác thực – authentication) ở phía trên của OAuth2 (ủy quyền – authorization) để có một giải pháp bảo mật hoàn chỉnh.

Đọc thêm tại: https://techmaster.vn/posts/34473/authentication-va-authorization-openid-vs-oauth2-vs-saml

Tiếp theo hãy vào phần áp dụng

2. KIẾN TRÚC

Chúng ta sẽ thêm một microservice mới có tên product-api hoạt động như một external API (hay còn gọi là Resource Server trong thuật ngữ của OAuth) và được expose thông qua edge server đóng vai trò token relay, tức là chuyển tiếp OAuth access tokens từ client đến resource server. Chúng ta cũng sẽ thêm OAuth Authorization Server và OAuth client ở phía Service consumer.

Phần được thêm mới được đóng khung màu đỏ trong diagram dưới đây:

1

Ghi chú:

  • Trong phần này chúng ta sẽ xây dựng một máy chủ OAuth authorization đơn giản để minh họa toàn bộ quá trình. Trong thực tế, bạn nên sử dụng các cơ chế SSO có sẵn từ Google, Facebook, Twitter.
  • Bài viết cũng chỉ sử dụng HTTP thay vì TSL như HTTPS

3. CHECKOUT SOURCE CODE

Yêu cầu Java SE 8, Git và Gradle.

git clone https://github.com/callistaenterprise/blog-microservices.git
cd blog-microservices
git checkout -b B3 M3.1
./build-all.sh

Nếu đang sử dụng Windows, bạn có thể thực thi tập tin bat tương ứng build-all.bat!

Hai phần mới được thêm vào là OAuth Authorization Server (auth-server) và OAuth Resource Server (product-api-service):

2

4. DIỄN GIẢI SOURCE CODE

4.1 GRADLE DEPENDENCIES

Để có thể sử dụng OAuth 2.0, chúng ta sẽ cần spring-cloud-security và spring-security-oauth2:

Đối với auth-server:

compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.security.oauth:spring-security-oauth2:2.0.6.RELEASE")

Đối với product-api-service:

compile("org.springframework.cloud:spring-cloud-starter-security:1.0.0.RELEASE")
compile("org.springframework.security.oauth:spring-security-oauth2:2.0.6.RELEASE")

4.2 AUTH-SERVER

Trước tiên là thêm @EnableAuthorizationServer annotation. Sau đó, sử dụng một configuration class để đăng ký các ứng dụng khách được approved (lưu trên memory thôi), chỉ định client-id, client-secret, allowed grant flows và scopes:

@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("acme")
.secret("acmesecret")
.authorizedGrantTypes("authorization_code", "refresh_token", "implicit", "password", "client_credentials")
.scopes("webshop");
}
}

Lưu ý: đây chỉ là cách chúng ta phát triển một OAuth server đơn giản để mô phỏng các máy chủ ủy quyền OAuth trong thế giới thực như Google, LinkedIn hoặc GitHub.

Để xem mã nguồn đầy đủ, hãy xem AuthserverApplication.java.

Đăng ký người dùng (Resource Owner trong thuật ngữ của OAuth) và mô phỏng Identity Provider (IdP) được thực hiện bằng cách thêm một dòng config cho mỗi user trong tệp application.properties, ví dụ:

security.user.password=password

Để xem mã nguồn đầy đủ, hãy xem application.properties.

Ngoài ra còn có hai giao diện người dùng web đơn giản dùng để user đăng nhập và cấp quyền, xem mã nguồn để biết chi tiết.

4.3 PRODUC-API-SERVICE

Để Produc-API-Service hoạt động như một máy chủ OAuth, chúng ta cần thêm @EnableOAuth2Resource annotation:

@EnableOAuth2Resource
public class ProductApiServiceApplication {

Để xem mã nguồn đầy đủ, hãy xem ProductApiServiceApplication.java.

Produc-API-Service rất giống với Composite service trong phần 2. Để có thể xác minh rằng OAuth hoạt động, chúng ta sẽ xuất ra log: id người dùng và access token, lưu ý việc output access token ra log chỉ nên được dùng trong môi trường test thôi nhé:

@RequestMapping("/{productId}")
@HystrixCommand(fallbackMethod = "defaultProductComposite")
public ResponseEntity getProductComposite(
@PathVariable int productId,
@RequestHeader(value="Authorization") String authorizationHeader,
Principal currentUser) {

LOG.info("ProductApi: User={}, Auth={}, called with productId={}",
currentUser.getName(), authorizationHeader, productId);
...

4.4 SỬA LẠI EDGE SERVER

Cuối cùng, chúng ta cần làm cho Edge Server chuyển tiếp OAuth access tokens đến API-service.

zuul:
ignoredServices: "*"
prefix: /api
routes:
productapi: /product/**

URL sample:
http://localhost:8765/api/product/123

Chúng ta cũng thay thế các route đến composite-service sang api-service.

5. KHỞI ĐỘNG SYSTEM

Việc khởi động cũng giống như trong phần 2.

Đầu tiên start RabbitMQ:

$ ~/Applications/rabbitmq_server-3.4.3/sbin/rabbitmq-server

Sau đó start các infrastructure services:

$ cd support/auth-server; ./gradlew bootRun
$ cd support/discovery-server; ./gradlew bootRun
$ cd support/edge-server; ./gradlew bootRun
$ cd support/monitor-dashboard; ./gradlew bootRun
$ cd support/turbine; ./gradlew bootRun

Và các business services:

$ cd core/product-service; ./gradlew bootRun
$ cd core/recommendation-service; ./gradlew bootRun
$ cd core/review-service; ./gradlew bootRun
$ cd composite/product-composite-service; ./gradlew bootRun
$ cd api/product-api-service; ./gradlew bootRun

Nếu đang sử dụng Windows, bạn có thể thực thi tập tin bat tương ứng start-all.bat!

Khi các microservices được khởi động và được đăng ký với máy chủ khám phá dịch vụ, chúng sẽ ghi các thông tin sau vào log:

DiscoveryClient … – registration status: 204

6. OAUTH AUTHORIZATION GRANT FLOWS

Đặc tả OAuth 2.0 giới thiệu bốn luồng cấp quyền để nhận access token:

3

LƯU Ý : Trong đó có Code và Implicit flow là được sử dụng rộng rãi nhất và trong bài viết này chỉ xét 2 trường hợp đó.

6.1 AUTHORIZATION CODE GRANT

Trước tiên, chúng ta cần lấy code grant (giống như one time password) bằng trình duyệt web:

http://localhost:9999/uaa/oauth/authorize? response_type=code& client_id=acme& redirect_uri=http://example.com& scope=webshop& state=97536

Đăng nhập ( user/ password) và đưa ra sự đồng ý của bạn trong các trang web được hiển thị. Trình duyệt web sẽ chuyển hướng đến URL dưới đây:

http://example.com/?
code=IyJh4Y&
state=97536

Lấy tham số code từ URL và lưu trữ nó trong một biến môi trường:

CODE=IyJh4Y

Bây giờ sẽ dùng code grant để lấy về access token:

curl acme:acmesecret@localhost:9999/uaa/oauth/token \
-d grant_type=authorization_code \
-d client_id=acme \
-d redirect_uri=http://example.com \
-d code=$CODE -s | jq .
{
"access_token": "eba6a974-3c33-48fb-9c2e-5978217ae727",
"token_type": "bearer",
"refresh_token": "0eebc878-145d-4df5-a1bc-69a7ef5a0bc3",
"expires_in": 43105,
"scope": "webshop"
}

Lưu access token trong biến môi trường để sử dụng sau này khi chúng ta truy cập tới API:

TOKEN=eba6a974-3c33-48fb-9c2e-5978217ae727

Nếu bạn thực hiện lấy thêm mã token lần nữa bằng code grant trước đó, sẽ có thông báo lỗi vì code grant đó chỉ có giá trị one time.

curl acme:acmesecret@localhost:9999/uaa/oauth/token \
-d grant_type=authorization_code \
-d client_id=acme \
-d redirect_uri=http://example.com \
-d code=$CODE -s | jq .
{
"error": "invalid_grant",
"error_description": "Invalid authorization code: IyJh4Y"
}

6.2 IMPLICIT GRANT

Với implicit grant, chúng ta bỏ qua code grant, thay vào đó sẽ yêu cầu access token trực tiếp từ trình duyệt web (bảo mật thấp hơn). Sử dụng URL sau trong trình duyệt web:

http://localhost:9999/uaa/oauth/authorize? response_type=token& client_id=acme& redirect_uri=http://example.com& scope=webshop& state=48532

Đăng nhập ( user/ password) và đưa ra sự đồng ý cấp quyền. Trình duyệt web sẽ chuyển hướng đến URL dưới đây:

http://example.com/#
access_token=00d182dc-9f41-41cd-b37e-59de8f882703&
token_type=bearer&
state=48532&
expires_in=42704

Lưu access token trong biến môi trường để sử dụng sau này khi truy cập API:

TOKEN=00d182dc-9f41-41cd-b37e-59de8f882703

7. ACCESS ĐẾN API

Bây giờ, khi đã có access token, chúng ta có thể bắt đầu truy cập API.

Trước tiên, hãy thử truy cập vào API mà không có access token, nó sẽ không thành công:

curl 'http://localhost:8765/api/product/123' -s | jq .
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}

Tiếp theo, hãy thử với một access token không hợp lệ, nó cũng sẽ thất bại:

curl 'http://localhost:8765/api/product/123' \
-H "Authorization: Bearer invalid-access-token" -s | jq .
{
"error": "access_denied",
"error_description": "Unable to obtain a new access token for resource 'null'. The provider manager is not configured to support it."
}

Bây giờ, chúng ta thực hiện một request đúng cung cấp một trong các access token có được ở bước phía trên:

curl 'http://localhost:8765/api/product/123' \
-H "Authorization: Bearer $TOKEN" -s | jq .
{
"productId": 123,
"name": "name",
"weight": 123,
"recommendations": [...],
"reviews": [... ]
}

Ngon!

Check log events trong product-api-service:

2015-04-23 18:39:59.014 INFO 79321 --- [ XNIO-2 task-20] o.s.c.s.o.r.UserInfoTokenServices : Getting user info from: http://localhost:9999/uaa/user
2015-04-23 18:39:59.030 INFO 79321 --- [ctApiService-10] s.c.m.a.p.service.ProductApiService : ProductApi: User=user, Auth=Bearer a0f91d9e-00a6-4b61-a59f-9a084936e474, called with productId=123
2015-04-23 18:39:59.381 INFO 79321 --- [ctApiService-10] s.c.m.a.p.service.ProductApiService : GetProductComposite http-status: 200

Chúng ta có thể thấy rằng API liên hệ với máy chủ ủy quyền để nhận thông tin về người dùng và sau đó in ra tên người dùng và access token trong log!

Cuối cùng, hãy thử làm mất hiệu lực của access token, bằng cách ví dụ như làm cho nó hết hạn. Một cách để làm điều đó là khởi động lại auth-server (nó chỉ lưu trữ thông tin trong bộ nhớ…) và sau đó thử lại:

curl 'http://localhost:8765/api/product/123' \
-H "Authorization: Bearer $TOKEN" -s | jq .
{
"error": "access_denied",
"error_description": "Unable to obtain a new access token for resource 'null'. The provider manager is not configured to support it."
}

Access token được chấp nhận trước đây hiện bị từ chối.

8. TÓM TẮT

Các hệ thống phân tán (decentralized system) ngày càng trở lên phổ biến và xác thực là một khía cạnh quan trọng của tất cả chúng. SSO giải quyết một vấn đề lớn: làm thế nào để quản được số lượng người dùng đang tăng lên trên toàn bộ hệ thống gồm nhiều ứng dụng và dịch vụ. Các framework chẳng hạn như OpenID Connect và các dịch vụ chẳng hạn như Auth0 làm cho việc tích hợp Single Sign On vào các ứng dụng mới hoặc đã có của bạn trở nên dễ dàng hơn nhiều. Nếu bạn đang triển khai xác thực trên một ứng dụng hay dịch vụ mới hãy xem xét tích hợp SSO.

Bài viết đã trình bày, mô phỏng cách xác thực với OAuth 2.0. Lưu ý khi triển khai thực tế, các bạn nên dùng luôn các cơ chế xác thực của Google, Facebook.

9. TIẾP THEO

Trong bài viết tiếp theo, chúng ta sẽ đến với việc quản lý log tập trung sử dụng ELK stack bao gồm: Elasticsearch, LogStash and Kibana.

Series này là phần tiếp theo series Microservices: Từ Thiết Kế Đến Triển Khai, tập trung vào việc hiện thực hóa các khái niệm đã mô tả ở phần lý thuyết. Hi vọng sẽ giúp ích được cho các bạn khi làm quen với microservies. Các bạn có thể tham khảo thêm về phần Architecture căn bản ở đây nhé.

Tổng hợp và dịch by edwardthienhoang

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Các Chuyên Gia Đầu Ngành Hội Tụ Tại “CEO & CMO Summit 2021”

Tiếp nối thành công của năm vừa qua, Hội nghị “CEO & CMO Việt Nam 2021” sẽ chính thức trở lại với những đột phá về nội dung lẫn quy mô vào ngày 18.06 sắp tới.

CEO & CEO Summit là hoạt động thường niên do Hiệp hội Mobile Marketing (MMA) toàn cầu tổ chức. Với sự góp mặt của hơn 1,000 C-levels đến từ các doanh nghiệp, tập đoàn đa quốc gia thuộc nhiều lĩnh vực khác nhau, sự kiện năm nay hứa hẹn mang đến cho các nhà tiếp thị cơ hội được gặp gỡ, bàn luận với các chuyên gia, lãnh đạo tiên phong trong ngành.

Cùng điểm qua những điểm nóng chủ đề đang được mong chờ nhất tại “CEO & CMO Summit 2021”

CEO & CMO Summit 2021 sẽ xoay quanh chủ đề “Pivot to the New Normal” (tạm dịch: Bước vào sự bình thường mới). Các diễn giả khách mời sẽ chia sẻ, bàn luận về những vấn đề đang được quan tâm, những cải tiến, xu hướng mới nhất của ngành Tiếp thị Di động tại Việt Nam và thế giới. Từ đó, các doanh nghiệp sẽ có cái nhìn tổng quát hơn về thị trường và đưa ra những giải pháp cho chiến lược Marketing phù hợp nhất, đặc biệt là trong tình hình phải đối mặt với những biến động chưa từng có do đại dịch Covid-19 gây ra.

Mở đầu cho sự kiện năm nay, Ông James Griffin, Phó Giám đốc Marketing mảng Beauty & Personal Care tại Unilever Việt Nam, sẽ luận bàn về Purpose Led Marketing và vai trò cốt lõi của phương châm này trong ngành tiếp thị hiện đại. Khách mời tham gia sẽ được chia sẻ về những chiến dịch được thực hiện với mục đích cụ thể nhằm xây dựng hình ảnh thương hiệu gắn liền với giá trị xã hội, cũng như cách nắm bắt sức mạnh của Purpose Led Marketing để vượt qua đại dịch lần này.

Tiếp theo, người tham dự sẽ được lắng nghe chia sẻ từ Ông Pablo Gomez – Regional Media Lead từ Kantar Media Châu Á về “Lựa chọn kênh truyền thông hiệu quả”. Trong tình hình đại dịch diễn biến phức tạp, các nhà tiếp thị đang phải làm việc với áp lực về ngân sách ngày càng tăng cao. Ông Pablo sẽ trình bày nghiên cứu 5 năm của mình về cách xây dựng một chiến lược digital marketing hiệu quả, từ đó giúp các doanh nghiệp có thể thành công vượt qua giai đoạn khó khăn này.

Đặc biệt, trong phiên thảo luận buổi sáng, ba “ông lớn” trong ngành Facebook, Google và Unilever sẽ có một cuộc đối thoại trực tiếp trong panel với chủ đề về Hiệu quả Tiếp thị (Marketing Effectiveness), thước đo mức độ hiệu quả của một chiến dịch tiếp thị. Người tham gia sẽ được lắng nghe những chia sẻ đến từ Bà Nguyễn Thị Mai – Phó Giám Đốc Marketing (Homecare) Unilever Việt Nam, Bà Nguyễn Thị Giáng Xuân – Head of Agency, Global Business Group Facebook Việt Nam và Ông Deepak Chandran – Head of Insights Google.

Đổi mới Khuôn khổ về Tiếp thị Tăng trưởng (Marketing Growth Frameworks Rethink) sẽ là chủ đề được Ông Greg Stuart – CEO of the Mobile Marketing Association (MMA) chia sẻ trong hội nghị năm nay, hứa hẹn là một mô hình hiệu quả giúp các doanh nghiệp có thể định hướng lại hướng đi chiến lược của mình để thu hút khách hàng và tối đa hóa lợi nhuận.

Ngoài ra, người tham dự sẽ được tham gia các buổi chia sẻ về “Social Commerce tại Việt Nam” từ Ông Aniq Syed – Deputy Managing Director Publicis Media, “Những Tiêu Điểm của Thương Mại Điện Tử tại Việt Nam” từ Ông Nguyễn Ngọc Dũng – Vice Chairman Vecom, và “Kỷ Nguyên Mới của Tiếp thị” từ Bà Naree Nguyễn – TikTok Việt Nam. Đại diện từ kênh mạng xã hội đang “làm mưa làm gió” này sẽ chia sẻ về cách TikTok đã tạo nên làn sóng ảnh hưởng mới chỉ trong một khoảng thời gian ngắn ở các thị trường khác nhau, từ đó chỉ ra những cơ hội để cải tiến, thay đổi cách tiếp cận về Độ phủ (Reach) và Mức độ liên quan (Relevance).

Trong phiên thảo luận buổi chiều, CEO & CMO Summit 2021 sẽ tập trung vào những xu hướng, công nghệ mới nhất trong ngành như Omni Channels, Cookieless Advertising, Blockchain, …

Trong bài phát biểu keynote thứ hai của sự kiện, Bà Trâm Nguyễn, Giám đốc Quốc gia Google (Việt Nam, Lào và Campuchia), sẽ bàn luận về một chủ đề đang rất “nóng” hiện nay: “Privacy-First Future: Cookieless Advertising”. Khi lượng người dùng online ngày càng tăng do những tác động của đại dịch, bảo mật thông tin người dùng trở nên quan trọng hơn bao giờ hết. Đại diện từ Google sẽ chia sẻ những biện pháp mà tập đoàn toàn cầu này đang thực hiện để bảo vệ sự an toàn thông tin của người dùng nói riêng và mạng Internet nói chung: thông qua việc phát triển sản phẩm, cho phép người dùng toàn quyền kiểm soát thông tin cá nhân, …

Nối tiếp chương trình sẽ là các phần chia sẻ từ CEO và CMO của các doanh nghiệp danh tiếng. Ông James Dong, CEO của Lazada Việt Nam sẽ chia sẻ về những xu hướng công nghệ mới nhất trong ngành Marketing. Bà An Đặng – CMO Provence và Ông Cường Nguyễn – Marketing Director Biti’s sẽ cùng dẫn dắt phần bàn luận về những mô hình marketing phù hợp để tiếp cận trong thời kỳ đại dịch như xây dựng mức độ liên quan, cải tiến sản phẩm, thực hiện hợp tác thương hiệu, chiêu thị hiệu quả,…

Ông Gowthaman Ragothaman – CEO của Aquiliz sẽ nhấn mạnh làm rõ chủ đề “Tái kiến tạo MarTech bằng Blockchain”. Trong tương lai gần, các nền tảng kỹ thuật số sẽ loại bỏ không sử dụng những dữ liệu cookie từ bên thứ 3 nhằm mục đích bảo vệ quyền riêng tư của người dùng. Vì vậy, Blockchain chính là một trong những giải pháp đang được các công ty hướng đến để thích ứng được với một tương lai “không cookie” sắp đến gần.

Hình ảnh được chia sẻ từ sự kiện MMA Global – CEO & CMO Summit

Ngoài ra, các lãnh đạo đầu ngành trong những buổi đối thoại trực tiếp về “Data” và vai trò thiết yếu của nó trong Tiếp thị Hiện đại dưới sự tham gia của các tổ chức tài chính lớn như FE Credit, Techcombank và cả Cốc Cốc cùng đại diện của Dentsu Group tại Việt Nam. Trong buổi thảo luận CMO Talk, ba vị Giám đốc Marketing từ Marico, Mondelez và Castrol sẽ nói về tầm quan trọng và làm thế nào để phát triển mối quan hệ với khách hàng thông qua “Omni channel” dưới sự dẫn dắt của Giám Đốc Điều Hành Mindshare Việt Nam, bà Kristy Toomer. Họ sẽ cung cấp những kinh nghiệm quý báu về những cải tiến, công nghệ và xu hướng hiện nay, từ đó giúp doanh nghiệp đạt được thành công cao nhất.

Với bản danh sách “phong phú” những diễn giả và hơn 1,000 khách mời là các C-level đến từ các nhãn hàng, agency trong hệ sinh thái trong và ngoài Việt Nam, đây chắc chắn là sự kiện về Mobile Marketing không thể bỏ qua trong năm 2021.

CEO & CMO Summit 2021 được tổ chức duy nhất một ngày 18/06/2021 thông qua nền tảng online. Chỉ cần scan mã QR dưới đây để đăng ký. Cùng theo dõi những thông tin, những chủ đề về sự kiện tại các Podcast được phát sóng trên fanpage MMA Việt Nam trong thời gian sắp tới.

MMA CEO & CMO Summit 2021 sẽ được tổ chức trực tuyến trên Air Meet vào lúc 9:00 – 17:00 ngày 18/06/2021. Tất cả các CEO và CMO từ các doanh nghiệp, nhãn hàng… đều được chào đón tại sự kiện. 

Đặc biệt, hãy nhanh tay đăng ký ngay hôm nay thông qua mã QR code để nhận được thư mời trực tiếp từ MMA Việt Nam hoặc liên hệ theo số Hotline: 0704874556.

Thông tin về sự kiện CEO & CMO Summit 2021 vui lòng xem thêm tại: https://bit.ly/3vafgO6 

Kỹ Năng Giao Tiếp Trong Tuyển Dụng Và Cách Cải Thiện

kỹ năng giao tiếp trong tuyển dụng
Kỹ Năng Giao Tiếp Trong Tuyển Dụng Và Cách Cải Thiện

Trao đổi thông tin được xem là hiệu quả khi hai bên có thể hiểu rõ những vấn đề được chia sẻ và có thể tương tác với nhau một cách thoải mái. Người có kỹ năng giao tiếp tốt sẽ biết cách giao tiếp hai chiều và giúp buổi nói chuyện phát triển với nhiều nội dung hấp dẫn. Do đó, không khó hiểu khi đây được đánh giá là một trong những kỹ năng mềm cực kỳ quan trọng và được chú ý trong quá trình tuyển dụng. Vậy làm thế nào để cải thiện kỹ năng giao tiếp trong tuyển dụng? Không chỉ ở phía của ứng viên mà với các nhà tuyển dụng, đây cũng là khả năng quan trọng để thúc đẩy một buổi phỏng vấn diễn ra suôn sẻ và thành công.

kỹ năng giao tiếp trong tuyển dụng
Kỹ năng giao tiếp trong tuyển dụng đóng vai trò rất quan trọng

Kỹ năng giao tiếp trong tuyển dụng quan trọng như thế nào?

Kỹ năng giao tiếp từ lâu đã được xem là một kỹ năng quan trọng trong cả công việc lẫn cuộc sống đời thường. Kỹ năng giao tiếp được thể hiện thông qua việc bạn có thể truyền đạt thông tin đến người khác một cách dễ hiểu cũng như nắm được những thông tin mà người khác cung cấp.

Kỹ năng giao tiếp không chỉ được đánh giá thông qua cách nói chuyện mà còn được thể hiện thông qua nhiều kỹ năng liên quan như kỹ năng thuyết trình, khả năng đặt câu hỏi đúng trọng tâm vấn đề hay hiểu những thông tin đối phương đang nói và điều chỉnh cuộc nói chuyện theo đúng hướng,…

Thực tế ngày nay cho thấy không phải ai cũng có khả năng giao tiếp tốt, nhất là với những ứng viên trẻ, mới ra trường và chưa có nhiều kinh nghiệm làm việc. Do đó, kỹ năng giao tiếp của ứng viên trong quá trình phỏng vấn được các nhà tuyển dụng rất quan tâm và đề cao.

Ngược lại, từ phía nhà tuyển dụng, nếu biết cách giao tiếp tốt cũng có thể khơi gợi cho ứng viên cách nói chuyện và trao đổi nhiều thông tin hữu ích, giúp hai bên có sự thấu hiểu về cách làm việc cũng như bản chất môi trường công ty chẳng hạn.

  5 phát ngôn cần tránh khi giao tiếp với người lãnh đạo của bạn
  Giao tiếp hiệu quả giữa các Microservice

Nhận biết một ứng viên có kỹ năng giao tiếp tốt

Có thể đánh giá khả năng giao tiếp của ứng viên thông qua những tiêu chí cơ bản dưới đây.

Trao đổi thông tin một cách dễ hiểu và logic

Thông thường khi ứng tuyển vào một cách công ty, bạn sẽ chỉ có thể tương tác với nhà tuyển dụng thông qua CV và quá trình phỏng vấn. Do đó, hãy tận dụng tối đa cơ hội được nói chuyện trực tiếp với người phỏng vấn để thể hiện những gì mình có với họ.

Bạn nên có sự chuẩn bị sẵn sàng về những gì mình sẽ chia sẻ trong buổi phỏng vấn, tìm hiểu trước về văn hóa công ty cũng như những công việc mình sẽ làm nếu được nhận vào công ty. Có sự chuẩn bị trước sẽ giúp bạn nói đúng trọng tâm vấn đề, dễ hiểu và chắc chắn sẽ được nhà tuyển dụng đánh giá cao hơn.

Chia sẻ vừa đủ về bản thân

Phỏng vấn là cơ hội để bạn tự PR về bản thân với nhà tuyển dụng, về những gì bạn đã làm được và có thể cống hiến cho công ty trong tương lai. Điều đó rất tốt, tuy nhiên, cần biết điểm dừng và chia sẻ vừa đủ về bản thân với nhà tuyển dụng. Một người có khả năng giao tiếp khôn khéo sẽ không bao giờ nói quá nhiều về bản thân hay tâng bốc chuyên môn của mình một cách quá đà.

Một nhà tuyển dụng chuyên nghiệp sẽ đánh giá ứng viên không chỉ qua chuyên môn mà còn qua kỹ năng giao tiếp trong tuyển dụng. Nhiều bằng chứng đã cho thấy rằng một ứng viên “nói ít làm nhiều” đa phần là những người có năng lực và có chính kiến riêng. Họ luôn nỗ lực để đưa những sản phẩm tốt, những dự án tốt thay vì nói rất nhiều nhưng không chú tâm đến công việc.

kỹ năng giao tiếp của ứng viên

Biết cách lắng nghe và tương tác với nhà tuyển dụng

Trong quá trình phỏng vấn, việc bỏ thời gian để lắng nghe những gì nhà tuyển dụng chia sẻ giúp bạn trở nên chuyên nghiệp và thể hiện được tinh thần cầu thị với đối phương hơn. Việc bạn chú tâm đến những gì nhà tuyển dụng chia sẻ giúp họ cảm thấy rằng bạn đang thật sự quan tâm đến thông tin mà họ cung cấp cũng như quan tâm đến môi trường làm việc tại công ty.

Một ứng viên có kỹ năng giao tiếp là người không chỉ trao đổi thông tin một cách dễ hiểu mà còn biết lúc nào nên dừng lại và lắng nghe. Dựa trên những gì được chia sẻ, ứng viên nên đặt ra những câu hỏi hay vấn đề có liên quan để tiếp tục phát triển buổi nói chuyện thay vì chỉ chú tâm vào những gì mình muốn nói. Việc lắng nghe đúng cách cũng thể hiện được tính cách và thái độ làm việc của bạn như cách mà bạn chia sẻ thông tin với nhà tuyển dụng.

Xem thêm Nguyên tắc 7C – Checklist hoàn hảo cho cuộc giao tiếp hiệu quả

Thể hiện ngôn ngữ hình thể trong quá trình phỏng vấn

Nhắc đến kỹ năng giao tiếp mà bỏ qua việc thể hiện ngôn ngữ hình thể chắc chắn sẽ là một thiếu sót. Cần có sự phối hợp nhịp nhàng giữa từng cử chỉ, ánh mắt, nụ cười, giọng nói với những thông tin mà bạn đang chia sẻ. Quan trọng là việc chia sẻ thông tin kết hợp với ngôn ngữ hình thể cần được thể hiện đúng chừng mực và biết cách tiết chế đúng lúc. Đừng quá sa đà vào những cử chỉ tay chân vì sẽ khiến đối phương cảm thấy khó chịu.

Một vấn đề quan trọng khác của ngôn ngữ hình thể là hãy mỉm cười. Mỉm cười nhẹ nhàng khi chào hỏi và trong suốt quá trình nói chuyện sẽ giúp buổi phỏng vấn trở nên thân thiện và tạo bầu không khí cởi mở hơn. Đừng bao giờ tiết kiệm nụ cười, nhất là trong những cuộc trò chuyện có tính chất quan trọng như thế này, vì nó sẽ giúp bạn tạo ấn tượng tốt hơn trong mắt nhà tuyển dụng.

Kỹ năng giao tiếp có quan trọng với nhà tuyển dụng?

Với ứng viên, kỹ năng giao tiếp tốt sẽ giúp họ đạt được những mục tiêu quan trọng và được đánh giá cao hơn trong những buổi phỏng vấn. Và đối với nhà tuyển dụng, nắm chắc được kỹ năng giao tiếp cũng quan trọng không kém vì sẽ giúp người phỏng vấn khai thác được tối đa thông tin từ ứng viên.

Kỹ năng giao tiếp trong tuyển dụng của nhà tuyển dụng được thể hiện khá đa dạng và có sự phối hợp giữa nhiều hình thức khác nhau. Để làm được điều này, nhân sự phỏng vấn nên có sự nghiên cứu kỹ càng về CV của ứng viên để nắm được sơ bộ những ưu, khuyết điểm của họ và biết cách khai thác câu hỏi hợp lí hơn. Trong quá trình phỏng vấn, việc ghi chú lại những thông tin quan trọng là rất cần thiết cho quá trình đánh giá sau này.

người phỏng vấn chuyên nghiệp

Bên cạnh đó, một người phỏng vấn chuyên nghiệp cũng sẽ biết cách nói chuyện để tạo bầu không khí thân thiện và khơi gợi cho ứng viên chia sẻ thông tin tốt hơn. Một buổi trao đổi thoải mái và dễ chịu chắc chắn sẽ giúp cho cả hai bên cảm thấy vui vẻ và sẵn lòng chia sẻ mọi khúc mắc nếu có.

Cải thiện kỹ năng giao tiếp là quá trình rèn luyện lâu dài

Kỹ năng giao tiếp quan trọng như vậy nên dù là ai cũng nên luyện tập và trau dồi khả năng này cho bản thân. Đây là kỹ năng mềm được kết hợp với nhiều yếu tố khác như vốn hiểu biết sâu rộng, khả năng sáng tạo cũng như linh hoạt trong mọi tình huống. Do đó, đừng vội vàng mà hãy kiên nhẫn luyện tập khả năng nói chuyện cho bản thân. Nhất là với những ứng viên đang còn e dè và luôn cảm thấy thiếu tự tin trong những buổi phỏng vấn, việc luyện tập chắc chắn là cần thiết.

Xem thêm 5 phát ngôn cần tránh khi giao tiếp với người lãnh đạo của bạn

Bạn có thể cải thiện kỹ năng giao tiếp bằng cách:

  • Đứng trước gương và thực hành nói bằng cách tự trả lời những câu hỏi phỏng vấn cơ bản. Việc làm này sẽ giúp tạo sự tự tin và bạn có thể kiểm tra được mọi thông tin thông qua quá trình lặp lại nhiều lần.
  • Thực hành phỏng vấn với người khác cũng được xem là giải pháp rất có hiệu quả. Vì nó tạo không khí như một buổi phỏng vấn thật sự khi có người tương tác với bạn. Tốt nhất hãy tìm một người có khả năng đánh giá và nhận xét về những gì bạn chia sẻ để tìm ra câu trả lời tốt nhất cho mình.
  • Bình tĩnh và luôn luôn duy trì ánh mắt tự tin cùng nụ cười thân thiện chắc chắn sẽ khiến bạn trông chuyên nghiệp hơn hẳn.

Kỹ năng giao tiếp là yếu tố cực kỳ quan trọng sẽ giúp bạn không chỉ thành công trong công việc mà còn cả cuộc sống. Hãy luyện tập và trau dồi thêm cho bản thân để tự tin hơn khi giao tiếp với mọi người xung quanh bạn nhé. Đón đọc thêm những bài viết khác cùng TopDev để tích lũy thêm nhiều kinh nghiệm hơn cả trong lĩnh vực nhân sự và công nghệ thông tin đầy hấp dẫn.

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Thuật toán tìm kiếm trong C++

Thuật toán tìm kiếm trong C++

Bài viết được sự cho phép của tác giả Khiêm Lê

Vì sao cần có thuật toán tìm kiếm?

Trong thực tế, có rất nhiều bài toán, nhưng hầu như tất cả chúng đều quy về một bài toán duy nhất, đó chính là bài toán tìm kiếm. Ví dụ như khi bạn giải một bài toán, bạn có làm cách nào đi nữa thì mục đích cuối cùng của bạn chính là đi tìm lời giải của bài toán. Hay khi bạn thực hiện sắp xếp, lọc các phần tử của danh sách, mục đích của bạn cũng là tìm kiếm những phần tử thỏa mãn yêu cầu.

Từ những nhu cầu thực tế đó, bài toán tìm kiếm dẫn đến chúng ta phải tạo ra thuật toán tìm kiếm để giải quyết nó. Vậy thì thuật toán tìm kiếm là gì? Thuật toán tìm kiếm (searching algorithm) là thuật toán giúp ta tìm ra trong một tập dữ liệu đã cho một hoặc nhiều phần tử thỏa mãn yêu cầu tìm kiếm.

Tùy theo cấu trúc dữ liệu mà chúng ta sẽ có những thuật toán tìm kiếm khác nhau phù hợp cho mỗi cấu trúc đó. Do đó, chúng ta không nên học thuộc lòng thuật toán tìm kiếm trên một tập dữ liệu, một cấu trúc dữ liệu trong một ngôn ngữ cụ thể nào đó. Hãy học ý tưởng của thuật toán và áp dụng nó linh hoạt cho các cấu trúc dữ liệu khác nhau trong các ngôn ngữ lập trình khác nhau.

Trong bài này, mình sẽ dùng C++ để minh họa cho các thuật toán tìm kiếm, các bạn có thể áp dụng nó cho bất kỳ ngôn ngữ lập trình nào mà các bạn thích như Java hay Python…

  10 Kỹ năng quan trọng cần có của Front-end để tìm công việc dễ dàng hơn
  10 trang web hàng đầu để tìm hiểu WordPress

Tham khảo việc làm C++ hấp dẫn tại TopDev

Các thuật toán tìm kiếm

Trong bài viết này, mình sẽ giới thiệu đến các bạn 3 thuật toán tìm kiếm phổ biến nhất: tìm kiếm tuyến tính, tìm kiếm nhị phân và tìm kiếm nội suy. Giờ hãy bắt đầu tìm hiểu về các thuật toán tìm kiếm này nhé!

Tìm kiếm tuyến tính

Tìm kiếm tuyến tính (linear search) hay tìm kiếm tuần tự (sequential search) là thuật toán tìm kiếm bằng cách duyệt qua tất cả các phần tử của danh sách cho đến khi gặp phần tử cần tìm hoặc là đã hết danh sách. Do cách tìm kiếm duyệt từ đầu đến cuối này, độ phức tạp thời gian của thuật toán này sẽ là O(n).

Chúng ta có một mảng A có n phần tử bắt đầu từ vị trí 0. Để tìm kiếm phần tử x trong mảng A này, ta làm như sau:

  1. Gán i = 0.
  2. So sánh giá trị của A[i] và x:
    • Nếu A[i] == x thì dừng và trả về giá trị của i (vị trí của x trong mảng A).
    • Nếu A[i] != x thì sang bước 3.
  3. Gán i = i + 1:
    • Nếu i == n (tức hết mảng) thì dừng lại và trả kết quả là -1 (không tìm thấy x).
    • Nếu i < n thì quay lại bước 2.

Tìm kiếm tuyến tình

Dựa trên những thao tác trên, chúng ta có thể viết lại code trong C++ như sau:

int LinearSearch(int A[], int n, int x)
{
    int i = 0;
    while (i < n && A[i] != x)
        i++;
    if (i == n)
        return -1; // không tìm thấy x
    return i;  // tìm thấy x, trả về vị trí của x trong mảng a
}

Thông thường, các bạn hay sử dụng for cho nó đơn giản như sau:

int LinearSearch(int A[], int n, int x)
{
    for (int i = 0; i < n; i++)
        if (A[i] == x)
            return i;
    return -1; // duyệt hết mảng, không tìm thấy x
}

Chúng ta có thể cải tiến nó một chút bằng phương pháp đặt lính canh như sau: gán A[n] = x, trong lúc kiểm tra không cần kiểm tra i < n nữa bởi vì nếu chạy đến cuối cùng thế nào cũng gặp x chính là “lính” chúng ta vừa đặt. Vậy thuật toán trở thành:

int LinearSearch(int A[], int n, int x)
{
    int i = 0;
    A[n] = x;
    while (A[i] != x)
        i++;
    if (i == n)
        return -1;
    return i;
}

Tìm kiếm nhị phân

Tìm kiếm nhị phân (binary search) hay còn một số tên gọi khác nữa như tìm kiếm nửa khoảng (half-interval search), tìm kiếm logarit (logarithmic search), chặt nhị phân (binary chop) là thuật toán tìm kiếm dựa trên việc chia đôi khoảng đang xét sau mỗi lần lặp, sau đó xét tiếp trong nửa khoảng có khả năng chứa giá trị cần tìm, cứ như vậy cho đến khi không chia đôi khoảng được nữa. Thuật toán tìm kiếm nhị phân chỉ áp dụng được cho danh sách đã có thứ tự hay đã được sắp xếp.

Ví dụ như bạn có một dãy số tăng từ 1 đến 100, yêu cầu bạn tìm số 30. Bạn xem phần tử chính giữa của dãy số thì thấy là số 50, vậy thì bạn biết chắc là 30 chỉ có thể nằm trong khoảng dưới 50 thôi, vậy thì giới hạn tìm kiếm được thu hẹp lại một nửa. Ví dụ như tìm số 70 chẳng hạn thì 50 lại nhỏ hơn 70, do đó ta biết chắc 70 chỉ có thể nằm trong khoảng từ 51 đến 100 thôi. Cứ tiếp tục như thế cho đến khi tìm gặp hoặc không thể chia đôi khoảng nữa.

Do cách tìm kiếm chia đôi khoảng này, sau mỗi lần lặp, khoảng đang xét lại được chia đôi, và tiếp tục khoảng tiếp lại chia đôi khoảng đã được chia trước đó. Do đó, độ phức tạp thời gian của thuật toán này sẽ là O(log(n)), tốt hơn rất rất nhiều so với tìm kiếm tuyến tính.

Cho một mảng A có n phần tử bắt đầu từ vị trí 0, mảng A được sắp xếp tăng dần (lưu ý là thứ tự tăng dần, đối với giảm dần chúng ta sẽ có cách cài đặt khác một chút sẽ được trình bày bên dưới). Để tìm phần tử có giá trị x trong mảng A chúng ta sẽ cài đặt thuật toán tìm kiếm nhị phân như sau:

  1. Gán left = 0, right = n – 1.
  2. Gán mid = (left + right) / 2 (lấy phần nguyên, đây là phần tử chính giữa của khoảng hiện tại)
    • Nếu như A[mid] == x:
      • Dừng lại và trả về giá trị của mid (chính là vị trí của x trong mảng A).
    • Nếu như A[mid] > x (có thể x nằm trong nửa khoảng trước):
      • right = mid – 1 // giới hạn khoảng tìm kiếm lại là nửa khoảng trước
    • Nếu như A[mid] < x (có thể x nằm trong nửa khoảng sau):
      • left = mid + 1 // giới hạn khoảng tìm kiếm lại là nửa khoảng sau
  3. Nếu left <= right:
    • Đúng thì quay lại bước 2 (còn chia đôi được).
    • Sai thì dừng và trả về kết quả -1 (không tìm thấy x)

Tìm kiếm nhị phân

Thuật toán đã có, giờ hãy xem cài đặt nó trong C++ như thế nào nha:

int BinarySearch(int A[], int n, int x)
{
    int left = 0;
    int right = n - 1;
    int mid;
    while (left <= right)
    {
        mid = (left + right) / 2;
        if (A[mid] == x)
            return mid; // tìm thấy x, trả về mid là vị trí của x trong mảng A
        if (A[mid] > x)
            right = mid - 1; // Giới hạn khoảng tìm kiếm lại là nửa khoảng trước
        else if (A[mid] < x)
            left = mid + 1; // Giới hạn khoảng tìm kiếm lại là nửa khoảng sau
    }
    return -1; // không tìm thấy x
}

Đối với mảng được sắp xếp giảm, các bạn chỉ cần thay đổi chỗ so sánh A[mid] và x như sau:

  • A[mid] < x:
    • right = mid – 1
  • A[mid] > x:
    • left = mid + 1

Tìm kiếm nội suy

Tìm kiếm nội suy (interpolation search) là một thuật toán cải tiến từ thuật toán tìm kiếm nhị phân. Thay vì xác định điểm chính giữa của danh sách, thuật toán tìm kiếm nội suy xác định điểm gần với vị trí của phần tử cần tìm, do đó tối ưu được thời gian hơn so với thuật toán tìm kiếm nhị phân. Độ phức tạp thời gian cũng vì thế mà tốt hơn là O(log(log(n))).

Tuy nhiên, thuật toán tìm kiếm nhị phân luôn ổn định với độ phức tạp thời gian là O(log(n)), thuật toán tìm kiếm nội suy lại không như vậy. Trong những trường hợp xấu nhất như dãy tăng/giảm phân bố không đều, thuật toán tìm kiếm này đạt độ phức tạp là O(n), không khác gì dùng thuật toán tìm kiếm tuyến tính cả. Do đó, bạn nên sử dụng thuật toán tìm kiếm nhị phân để đảm bảo được độ phức tạp O(log(n)).

Vẫn là mảng A, vẫn n phần tử bắt đầu từ 0 và tăng dần. Tìm x trong mảng này dùng thuật toán tìm kiếm nội suy như sau:

  1. Gán left = 0, right = n – 1.
  2. Gán mid = left + (right – left) * (x – a[left]) / (a[right] – a[left]):
    • Nếu như A[mid] == x:
      • Dừng lại và trả về giá trị của mid.
    • Nếu như A[mid] > x:
      • right = mid – 1
    • Nếu như A[mid] < x:
      • left = mid + 1
  3. Nếu left <= right và x >= A[left] và x <= A[right] (x còn nằm trong đoạn [A[left]; A[right]]):
    • Đúng thì quay lại bước 2.
    • Sai thì dừng và trả về kết quả -1 (không tìm thấy x)

Và tương tự với mảng giảm dần, bạn chỉ cần sửa lại:

  • A[mid] < x:
    • right = mid – 1
  • A[mid] > x:
    • left = mid + 1

Giờ hãy cùng xem cài đặt thuật toán tìm kiếm nội suy trong C++ với mảng tăng nha:

int InterpolationSearch(int A[], int n, int x)
{
    int left = 0;
    int right = n - 1;
    int mid;
    while (left <= right && x >= A[left] && x <= A[right])
    {
        mid = left + (right - left) * (x - A[left]) / (A[right] - A[left]);
        if (A[mid] == x)
            return mid;
        if (A[mid] > x)
            right = mid - 1;
        else if (A[mid] < x)
            left = mid + 1;
    }
    return -1; // Không tìm thấy x
}

Lưu ý: khi sử dụng thuật toán tìm kiếm nhị phân hoặc nội suy, nếu như mảng chưa được sắp xếp, nên sử dụng kèm với các thuật toán sắp xếp có hiệu suất cao như Quick Sort hay Merge Sort để sắp xếp nhằm tối ưu hóa thuật toán. Nếu tìm kiếm nhanh mà sắp xếp chậm cũng không có ý nghĩa gì đối với tập dữ liệu lớn.

Tổng kết

Vậy là qua bài viết này, mình đã giới thiệu đến các bạn 3 thuật toán tìm kiếm phổ biến nhất mà các lập trình viên nên biết. Trong hầu hết các bài tập, các bạn sẽ cần dùng đến các thuật toán tìm kiếm này, đừng quên luyện tập thật nhiều để thành thục các thao tác trên các cấu trúc dữ liệu khác nhau nha.

Nếu như các bạn thấy hay, đừng quên chia sẻ cho bạn bè cùng biết nha. Bạn cũng có thể để lại bình luận bên dưới bài viết nếu có bất kỳ thắc mắc hoặc góp ý nào. Cảm ơn các bạn đã theo dõi bài viết!

Bài viết gốc được đăng tải tại khiemle.dev

Có thể bạn quan tâm:

Xem thêm It Job for Developer hấp dẫn trên TopDev

Hibernate Interceptor & StatementInspector

Hibernate Interceptor & StatementInspector

Bài viết được sự cho phép của tác giả Giang Phan

1. Hibernate Interceptor

1.1. Hibernate Interceptor là gì?

Interceptor là một tính năng rất hữu ích cho ứng dụng để kiểm soát đối tượng với các sự kiện nhất định xảy ra bên trong Hibernate.

Một đối tượng đi qua các giai đoạn khác nhau trong lifecycle của nó. Interface Interceptor trong Hibernate cung cấp các phương thức có thể được gọi ở các giai đoạn khác nhau, để thực hiện một số nhiệm vụ được yêu cầu.

Các Interceptor được đăng ký dưới dạng callback và cung cấp các liên kết liên lạc giữa session và application của Hibernate. Với một callback như vậy, một ứng dụng có thể kiểm tra và thay đổi các thuộc tính của một đối tượng persistent trước khi nó được save, update, delete or load.

  Hibernate là gì? Sao phải dùng nó thay JDBC?
  Kiểm tra tính hợp lệ của dữ liệu đầu vào form Spring Web MVC bởi Hibernate Validator

Có 2 cách để tạo một Interceptor:

  • Implement org.hibernate.Interceptor interface.
  • extend org.hibernate.EmptyInterceptor class.

Nếu không có yêu cầu đặc biệt, chúng ta nên extends class EmptyInterceptor và chỉ override các phương thức được yêu cầu.

Interface org.hibernate.Interceptor bao gồm các phương thức sau:

  • instantiate() : Phương thức này được gọi khi một lớp persistent được khởi tạo.
  • onLoad() : Phương thức này được gọ khi một đối tượng được load từ database và khởi tạo.
  • onSave() : Phương thức này được gọ khi một đối tượng được lưu.
  • onDelete() : Phương thức này được gọi khi một đối tượng bị xóa.
  • preFlush() : Phương thức này được gọi trước khi flush.
  • postFlush() : Phương thức này được gọi sau khi flush và một đối tượng đã được update trong bộ nhớ.
  • isUnsaved() : Phương thức này được gọi khi một đối tượng được truyền vào phương thức saveOrUpdate() .
  • findDirty() : Phương thức này được gọi khi phương thức flush() được gọi trên một đối tượng Session.
  • onFlushDirty() : Phương thức này được gọi khi Hibernate phát hiện ra rằng một đối tượng là dirty (tức là đã được thay đổi) trong quá trình flush.
  • Ngoài ra còn nhiều phương thức khác, các bạn tham khảo thêm Hibernate Interceptor javadoc.

Một Interceptor có thể được sử dụng ở: Session hoặc SessionFactory scope.

1.2. Ví dụ sử dụng Hibernate Interceptor

1.2.1. Create Interceptor

package com.gpcoder;

import com.gpcoder.entities.Tag;
import lombok.extern.log4j.Log4j2;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Iterator;

@Log4j2
public class LoggingInterceptor extends EmptyInterceptor {

@Override
public String onPrepareStatement(String sql) {
log.debug("onPrepareStatement: {}", sql);
return super.onPrepareStatement(sql);
}

@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
log.debug("onSave: {}", entity);
return super.onSave(entity, id, state, propertyNames, types);
}

@Override
public void preFlush(Iterator entities) {
log.debug("preFlush: {}", entities.next());
super.preFlush(entities);
}

@Override
public void postFlush(Iterator entities) {
log.debug("postFlush: {}", entities.next());
super.postFlush(entities);
}
}

1.2.2. Register Interceptor

Cấu hình Interceptor ở mức Session:

Session session = sessionFactory
.withOptions()
.interceptor(new LoggingInterceptor() )
.openSession();

Trường hợp muốn cấu hình Interceptor ở mức SessionFactory, nghĩa là tất cả Session đều áp dụng Interceptor này:

package com.gpcoder.utils;

import com.gpcoder.LoggingInterceptor;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtils {

private static final SessionFactory sessionFactory = buildSessionFactory();

private HibernateUtils() {
super();
}

private static SessionFactory buildSessionFactory() {
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() //
.configure() // Load hibernate.cfg.xml from resource folder by default
.build();
Metadata metadata = new MetadataSources(serviceRegistry).getMetadataBuilder().build();
return metadata.getSessionFactoryBuilder()
.applyInterceptor( new LoggingInterceptor() ) // Register interceptor
.build();
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}

public static void close() {
getSessionFactory().close();
}
}

Trong trường hợp muốn đảm bảo thread-safe, chúng ta cần xác định session context trong file hibernate.cfg.xml:

<property name="current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</property>

1.2.3. Tạo lớp ứng dụng

package com.gpcoder;

import com.gpcoder.entities.Tag;
import com.gpcoder.utils.HibernateUtils;
import lombok.extern.log4j.Log4j2;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

@Log4j2
public class HibernateInterceptorExample {

public static void main(String[] args) {
try (SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session = sessionFactory
.withOptions()
.interceptor(new LoggingInterceptor()) // Register interceptor
.openSession();
) {

session.getTransaction().begin();

Tag tag = new Tag();
tag.setName("Hibernate Interceptor");
session.persist(tag);

session.getTransaction().commit();
}
}
}

Output:

2020-Apr-02 22:41:38 PM [main] DEBUG com.gpcoder.LoggingInterceptor - onPrepareStatement: select nextval ('tag_id_seq')
2020-Apr-02 22:41:38 PM [main] DEBUG org.hibernate.SQL - select nextval ('tag_id_seq')
2020-Apr-02 22:41:38 PM [main] DEBUG com.gpcoder.LoggingInterceptor - onSave: Tag(id=43, name=Hibernate Interceptor)
2020-Apr-02 22:41:38 PM [main] DEBUG com.gpcoder.LoggingInterceptor - preFlush: Tag(id=43, name=Hibernate Interceptor)
2020-Apr-02 22:41:38 PM [main] DEBUG com.gpcoder.LoggingInterceptor - onPrepareStatement: insert into Tag (name, id) values (?, ?)
2020-Apr-02 22:41:38 PM [main] DEBUG org.hibernate.SQL - insert into Tag (name, id) values (?, ?)
2020-Apr-02 22:41:38 PM [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [Hibernate Interceptor]
2020-Apr-02 22:41:38 PM [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [BIGINT] - [43]
2020-Apr-02 22:41:38 PM [main] DEBUG com.gpcoder.LoggingInterceptor - postFlush: Tag(id=43, name=Hibernate Interceptor)

2. Hibernate StatementInspector

Một tính năng Hibernate rất hữu ích nhưng ít được biết đến là khả năng chặn (Interceptor) và sửa đổi bất kỳ câu lệnh SQL nào được tạo tự động bằng tiện ích Hibernate StatementInspector. Trong phần tiếp theo của bài viết này, chúng ta sẽ xem cơ chế Hibernate StatementInspector hoạt động như thế nào.

2.1. Create StatementInspector

Interface StatementInspector chỉ gồm 1 phương thức duy nhất inspect(String sql). Phương thức  nhận một câu lệnh SQL mà Hibernate sắp thực hiện và cho phép bạn sửa đổi câu lệnh SQL và trả nó về Hibernate tiếp tục thực thi.

Ví dụ: tạo SqlCommentStatementInspector để remove các auto comment của Hiberate.

package com.gpcoder;

import lombok.extern.log4j.Log4j2;
import org.hibernate.resource.jdbc.spi.StatementInspector;

import java.util.regex.Pattern;

@Log4j2
public class SqlCommentStatementInspector implements StatementInspector {

private static final Pattern SQL_COMMENT_PATTERN = Pattern.compile("\\/\\*.*?\\*\\/\\s*");

@Override
public String inspect(String sql) {
log.debug("Executing SQL query: {}", sql);
String sqlAfterRemovedComment = SQL_COMMENT_PATTERN.matcher(sql).replaceAll("");
log.debug("After removed: {}", sqlAfterRemovedComment);
return sqlAfterRemovedComment;
}
}

2.2. Register StatementInspector

Để đăng ký một implment của StatementInspector, mở file hibernate.cfg.xml và thêm cấu hình sau:

<!-- Enable SQL comment --> <property name="use_sql_comments">true</property> <!-- egister an implementation of the StatementInspector interface --> <property name="session_factory.statement_inspector">com.gpcoder.SqlCommentStatementInspector</property>

Lưu ý:

  • use_sql_comments : enable option này lên để cho phép Hibernate auto generate comment để minh hoạ cho ví dụ của chúng ta. Trong ứng dụng thực tế không cần enable option này cho StatementInspector cụ thể.

Một cách khác để đăng ký là thông qua SessionFactoryBuilder:

package com.gpcoder.utils;

import com.gpcoder.LoggingInterceptor;
import com.gpcoder.SqlCommentStatementInspector;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtils {

private static final SessionFactory sessionFactory = buildSessionFactory();

private HibernateUtils() {
super();
}

private static SessionFactory buildSessionFactory() {
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() //
.configure() // Load hibernate.cfg.xml from resource folder by default
.build();
Metadata metadata = new MetadataSources(serviceRegistry).getMetadataBuilder().build();
return metadata.getSessionFactoryBuilder()
.applyStatementInspector( new SqlCommentStatementInspector() ) // Register StatementInspector
.applyInterceptor( new LoggingInterceptor() ) // Register interceptor
.build();
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}

public static void close() {
getSessionFactory().close();
}
}

2.3. Tạo lớp ứng dụng

package com.gpcoder;

import com.gpcoder.entities.Tag;
import com.gpcoder.utils.HibernateUtils;
import lombok.extern.log4j.Log4j2;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

@Log4j2
public class HibernateInterceptorExample {

public static void main(String[] args) {
try (SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session = sessionFactory.openSession();
) {

session.getTransaction().begin();

Tag tag = new Tag();
tag.setName("Hibernate Interceptor");
session.persist(tag);

session.getTransaction().commit();
}
}
}

Output:

2020-Apr-02 23:33:44 PM [main] DEBUG com.gpcoder.SqlCommentStatementInspector - Executing SQL query: select nextval ('tag_id_seq')
2020-Apr-02 23:33:44 PM [main] DEBUG com.gpcoder.SqlCommentStatementInspector - After removed: select nextval ('tag_id_seq')
2020-Apr-02 23:33:44 PM [main] DEBUG org.hibernate.SQL - select nextval ('tag_id_seq')
2020-Apr-02 23:33:44 PM [main] DEBUG com.gpcoder.LoggingInterceptor - onSave: Tag(id=50, name=Hibernate Interceptor)
2020-Apr-02 23:33:44 PM [main] DEBUG com.gpcoder.LoggingInterceptor - preFlush: Tag(id=50, name=Hibernate Interceptor)
2020-Apr-02 23:33:44 PM [main] DEBUG com.gpcoder.SqlCommentStatementInspector - Executing SQL query: /* insert com.gpcoder.entities.Tag */ insert into Tag (name, id) values (?, ?)
2020-Apr-02 23:33:44 PM [main] DEBUG com.gpcoder.SqlCommentStatementInspector - After removed: insert into Tag (name, id) values (?, ?)
2020-Apr-02 23:33:44 PM [main] DEBUG org.hibernate.SQL - insert into Tag (name, id) values (?, ?)
2020-Apr-02 23:33:44 PM [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [Hibernate Interceptor]
2020-Apr-02 23:33:44 PM [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [BIGINT] - [50]
2020-Apr-02 23:33:44 PM [main] DEBUG com.gpcoder.LoggingInterceptor - postFlush: Tag(id=50, name=Hibernate Interceptor)

Như bạn thấy, comment của hibernate /* insert com.gpcoder.entities.Tag */ đã được loại bỏ một cách tự động nhờ vào StatementInspector.

Một số trường hợp khác có thể sử dụng StatementInspector: capture tất cả câu lệnh SQL được call bởi Hibernate, quản lý số lần SQL được gọi để phục vụ cho testing, reporting, …

Tài liệu tham khảo:

Bài viết gốc được đăng tải tại gpcoder.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Những Polyfill được sử dụng nhiều

Những Polyfill được sử dụng nhiều

Bài viết được sự cho phép của tác giả Tino Phạm

Các công nghệ mới hiện nay như là: HTML5, ES6, ES7,… đã được sử dụng rất nhiều. Tuy nhiên, các công nghệ này vẫn còn bị giới hạn việc sử dung cho các trình duyệt phiên cũ không hỗ trợ.

Sau đây là một số loại Polyfill được sử dụng phổ biến nhất. Tìm hiểu Polyfill là gì ở đây

  Những cách thay đổi giá trị fill của SVG khi hover

  15 ví dụ sử dụng map, reduce và filter

01. html5shiv

html5shiv

Project URL: https://github.com/aFarkas/html5shiv

Các phiên bản IE 9 trơ về trước không hiểu được các thẻ mới trong HTML5 như là

hoặc là

. Chính vì vậy khi ứng dụng của bạn viết bằng HTML5 và chạy trên các trình duyệt cũ này sẽ không thể hiển thị nội dung hoặc làm cho giao diện web trở nên lộn xộn. Một trong những cách phổ biến là sử dụng polyfills.

html5shiv sẽ làm cho IE có thể hiểu được các thẻ mới trong HTML5 bằng cách gọi hàm document.createElement(“tagname”) mỗi khi gặp một phần tử mới của HTML5 một cách chính xác. Nó còn bao gồm các kiểu trình bày mặc định cho các thẻ HTML5.

Sử dụng:

Tải file html5shiv.js từ link trên và copy & paste và phần của trang html của bạn.

//path/to/html5shiv.js

Chú ý:

Nếu bạn đang dùng Modernizr. Đây là một plugin tương tự như html5shiv. Vì thế bạn chỉ cần dùng Modernizr hoặc là html5shiv.

Lời khuyên

Bạn nên sử dụng html5shiv nếu như bạn đang dùng HTML5 và website có thể được hoạt động tốt ngay cả với các trình duyệt cũ.

02. -prefix-free

download

Project URL: http://leaverou.github.com/prefixfree/

Mặc dù mục đích của hầu hết các polyfills là nhắm vào các trình duyệt cũ, một số tồn tại chỉ đơn giản là đưa các trình duyệt hiện tại chuyển tiếp nhiều hơn một chút. Lea Verou’s -prefix-free chính là một loại polyfill như vậy. Nó cho phép các trình duyệt hiện tại nhận ra các phiên bản không tiền tố của một số thuộc tính CSS3 thay vì yêu cầu bạn phải viết ra tất cả các tiền tố đó. Nó đọc stylesheets của website của bạn và thay thế bất kỳ thuộc tính nào chưa có tiền tố mà được các trình duyệt mới công nhận.

Sử dụng

Tải file prefixfree.min.js theo link trên. Sau đó copy & paste vào của trang html.

/path/to/prefixfree.min.js

Chú ý:

Một giới hạn lớn nhất đã được mô tả trên trang chủ của Prefix-free. Ngoài ra, bạn phải đảm bảo tải prefix-free trước khi tải các file CSS trước khi hiển thị cho người dùng xem.

Lời khuyên:

Hãy sử dụng nếu bạn đang lo lắng về kích thước file CSS hoặc là khó chịu bởi việc viết các tiền tố trong css.

03. Selectivizr

selectivizr_vlkb7l

Project URL: http://selectivizr.com/

Keith Clark’s Selectivizr là một polyfill phổ biến để giúp bạn sử dụng CSS3 với các phiên bản từ IE8 trở xuống tốt hơn. Nó đọc stylesheets của bạn và tìm những thuộc tính của CSS3, sau đó nó sẽ dùng thư việc Javascript để tao tìm các phần tử html đang được gán các thuộc tính CSS3, áp dụng styles trực tiếp đến các phần tử đó. Nó sử dụng một số thư viện Javascript, một trong số đó có thể bạn đang dùng cho trang của bạn.

Keith Clark’s Selectivizr is a popular polyfill for making many CSS3 selectors work in IE 8 and below. It reads the page’s stylesheets looking for a number of known CSS3 selectors, then uses a JavaScript selector library to query the document for elements matching those selectors, applying the styles directly to those elements. It supports several JavaScript selector libraries, one of which you’re probably already using in your page.

Sử dụng

Tải file selectivizr.min.js theo link trên. Sau đó copy & paste vào của trang html.

/path/to/jquery.min.js

/path/to/selectivizr-min.js

Chú ý

Một số lưu ý sử dụng được mô tả ở cuối trang selectivizr.com. Việc quan trọng nhất là các truy vấn được chạy ngay khi trang được load và không tự động xử lý bổ sung tới DOM mà việc đó chính là dùng với trang web động.

Lời khuyên

Hãy dùng nó với các trang web tĩnh, nhưng đi cùng các chức năng truyền  thống khác (như là các lớp đơn giản) trên các trang lớn.

04. es5-shim

 3673e9baa16eb300a2f1592a9aa4eb85

Project URL: https://github.com/kriskowal/es5-shim/

ECMAScript 5th Edition (“ES5”) mang đến cho chúng ta nhiều tính năng mới trong javascript, và trên các trình duyệt cũ thì các Javascript engines cũ không hỗ trợ các tính năng này. es5-shim sẽ giúp trình duyệt cũ có thể đọc và hiểu được code javascript được viết bằng ES5. es5-shim có 2 phần: es5-shim.js chứa các phương thức đầy đủ, và es5-sham.js chứa các phương thức chính để sử dụng.

Sử dụng

Tải es5-shim.min.js (và/hoặc es5-sham.min.js) từ link trên, sau đó nhúng vào trang html trước khi viết code javascript mà có dùng các tính năng của ES5.

/path/to/es5-shim.min.js

Chú ý

Nếu bạn chỉ cần một vài tính năng mới trong ES5 thì sử dụng es5-shim.js. Vì nó có sẵn các tính năng chính để có thể sử dụng và nó nhẹ.

Lời khuyên

Chắc chắn dùng nó nếu code Javascript củ bạn có dùng các phương thức của ES5, để các trình duyện có thể đọc và thư thi các các phương thức nhanh chóng.

dịch từ nguồn: http://www.creativebloq.com/html5/10-best-polyfills-2133015

Bài viết gốc được đăng tải tại thangphampt.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Fixed – Không Mở Được Start Menu Trên Windows 10

Fixed – Không Mở Được Start Menu Trên Windows 10

Bài viết được sự cho phép của tác giả Tino Phạm 

Nếu đã và đang sử dụng Window 10 bạn sẽ rất bực bội khi gặp phải lỗi không mở được Start Menu. Và sau đây là một số cách để khắc phục.

  10 điều bạn có thể làm với Linux mà bạn không thể làm với Windows
  40 phím tắt dành cho người dùng Windows

Bước 1: click phải chuột lên thanh Taskbar > chọn Task Manager

Bước 2: File > Run new task

Bước 3: Gõ lệnh powershell và nhớ checked ‘Create this task with administrator privileges.’ > OK

new-task

Bước 4:

Copy Mã:
Get-AppXPackage -AllUsers | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml"}

hoặc

Get-AppxPackage | % { Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppxManifest.xml" -verbose }

powershell-1

Sau đó nhấn Enter để chạy. Nếu trong quá trình chạy xuất hiện màu vàng trên nền xanh lá như trong hình thì các bạn đã thành công.

04-khong-mo-duoc-start-menu-tren-windows-10

Trong trường hợp không thực hiện được thì mình có tổng hợp một số cách khác cũng có thể được thực hiện để sửa lỗi này:

  1. Chuyển chế độ xem màn hình sang Tablet bằng cách vào Settings
  2. Chạy System file checker (sfc /scannow)
  3. Repair Windows Image (Dism /Online /Cleanup-Image /RestoreHealth)
  4. Xóa file bị hỏng trong AppLocker
    Mở Run: “ren %windir%\System32\AppLocker\Plugin. *.bak” sau đó Restart lại máy tính
  5. Chạy Application Identity Service
    Mở Run gõ: SERVICES.MSC sau đó nhấn chuột phải vào APPLICATION IDENTITY nhấn chuột phải chọn Start, rồi khởi động lại máy tính
  6. Tạo user mới trên windows 10.
  7. Vào Trouble Shooting sau đó Reset This PC
  8. Vào “%AppData%..\Local\Microsoft\Windows” đổi tên file Usrclass.dat thành Usrclass.dat.old. Sau đó sign out và sign in
  9. Vào Windows Task Manager sau đó end cái Explorer.exe rồi mở lại
  10. Vào Settings / Desktop Themes. Sau đó đổi sang High Contrast themes. Sau đó đổi lại theme cũ. Hi vọng là start menu sẽ bật lai được
  11. Chuyển vào Safemode sau đó trở lại windows 10 bình thường

Nếu thử hết mà ko được thì win7 với win 8 vẫn luôn chào đón 😀

tham khảo: http://timhieumaytinh.com/khong-mo-duoc-start-menu-tren-windows-10/

Bài viết gốc được đăng tải tại thangphampt.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Javascript check is a number – 3 cách kiểm tra

Javascript check is a number – 3 cách kiểm tra

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Làm việc với Javascript nhiều, vấn đề các bạn thường gặp là kiểm tra xem một object có phải là number hay không? (Javascript check is a number or not?).

Xin được giới thiệu 3 cách thông dụng dưới đây giúp kiểm tra isNumber trong Javascript:

  10 câu hỏi javascript để nâng cao trình độ
  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết

1. Sử dụng isNaN()

Như cái tiêu đề function, NaN (Not a number). Hàm này kiểm tra một giá trị truyền vào có phải là số hay không?.

Syntax: Number.isNaN(value)

Trường hợp parameter value là số -> isNaN() trả về false. Trường hợp parameter value không phải là số isNaN() trả về true.

Chú ý rằng sử dụng isNaN() để kiểm tra number trong Javascript sẽ có hai cách gọi:

isNaN(), this is global function, converts the tested value to a Number, then tests it.

Nếu chỉ sử dụng isNaN(), đây là function toàn cục, trước khi kiểm tra value có là number hay không?. Nó sẽ convert trước các giá trị này rồi mới kiểm tra.

// Trường hợp là string sẽ tự động convert qua number rồi mới chekc
// Không convert được -> not a number -> true
isNaN('123') //false
isNaN('Hello') //true
isNaN('2005/12/12') //true

// Chú ý khi sử dụng với ''
isNaN('') //false -> '' vẫn được hiểu là number

// NaN thì cho dù là String cũng check được
isNaN(true) //false
isNaN(undefined) //true
isNaN('NaN') //true
isNaN(NaN) //true

// Các phép toán chia cho 0 chắc chắn không là number
isNaN(0 / 0) //true

The isNaN() function is different from the Number specific Number.isNaN() method. Number.isNaN() does not convert the values to a Number, and will not return true for anyone who want use javascript check is a number or not.

Function isNaN() thì khác so với Number.isNaN(). Function Number.isNaN() không convert giá trị qua kiểu số. Cũng không trả về true cho bất kì giá trị nào khác ngoài kiểu số.

Theo ý kiến riêng của mình, trường hợp không thể sure được các giá trị truyền vào có thể là undefined hay NaN, sử dụng Number.isNaN() sẽ là cách an toàn hơn để kiểm tra

Javascript check is a number with isNaN() function

2. Sử dụng isInteger()

The Number.isInteger() method determines whether the passed value is an integer.

Hàm Number.isInteger() kiểm tra xem một được tượng truyền vào có phải là số hay không?

Syntax: Number.isInteger(value)

Function isInteger chỉ trả về True hoặc False. Trường hợp parameter value là số -> trả về trueNgược lại, trả về false (bao gồm các trường hợp NaN – Not a Number).

Ví dụ sử dụng:

// Một số ví dụ khi sử dụng isNumber()
Number.isInteger(0.1); // false
Number.isInteger(Math.PI); // false
Number.isInteger(Infinity); // false
Number.isInteger(-Infinity); // false

// Lưu ý trường hợp String number cần convert trước nha
Number.isInteger('10'); // false

// Trường hợp số âm, big int
Number.isInteger(-100000); // true
Number.isInteger(99999999999999999999999); // true

// Trường hợp có phần thập phân
Number.isInteger(5.0); // true
Number.isInteger(5.000000000000001); // false
Number.isInteger(5.0000000000000001); // true

Javascript check is a number has a many function to do it. But please take care that’s not working in Internet explorer!.

Lưu ý rằng function này không hỗ trợ trên Internet Explorer. Trường hợp đang viết Javascript core trên IE thì đừng dại dột sử dụng function này nha

Biết là thế, nhưng khó nói lắm. Nếu mà làm cho các dự án cũ của Nhật hoặc cho chính phủ thì xác định là vẫn test IE như thường
Javascript check is a number with isNaN() function

3. typeOf operator – javascript nice way check is number

Sử dụng typeOf cũng là một cách hay để check is a number đối với một object.

Using typeOf in Javascript check is a number maybe is a best way. The parameter to check in typeOf is object, function or variable.

Sử dụng typeOf cũng là một cách đáng xem xét. Ngoài kiểm tra đối tượng, typeOf còn có thể sử dụng với đối tượng, hàm và biến (object, function or variable).

// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(1) === 'boolean'; // Boolean() will convert values based on if they're truthy or falsy
typeof !!(1) === 'boolean';

typeof [5, 10, 15, 20] === 'object';
typeof 3.14 === 'number';

Anh em có thể đọc thêm các bài viết hay khác về Javascript như:

4. Tham khảo

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm javascript hấp dẫn trên TopDev

Xây dựng phương thức với thuộc tính methods trong Vue instance

Xây dựng phương thức với thuộc tính methods trong Vue instance

Bài viết được sự cho phép của tác giả Kien Dang Chung

1. Tại sao cần có phương thức trong thuộc tính method?

Trong lập trình, chúng ta thường gặp các thuật ngữ hàm (function – có trả về dữ liệu), thủ tục (procedure – chỉ thực thi một số công việc), phương thức (method là hàm hoặc thủ tục gắn với class). Các khái niệm này rất cần thiết do mấy lý do:

  • Thứ nhất nó giúp mô đun hóa trong ứng dụng, xây dựng các khối code không phải lặp đi lặp lại, giảm kích thước ứng dụng, dễ quản lý mã nguồn hơn.
  • Thứ hai, nó giúp định nghĩa cấu trúc logic của ứng dụng.
  10 kinh nghiệm khi làm việc với các dự án lớn viết bằng Vue.js
  API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth

Như vậy, với việc sử dụng các method trong Vue.js giúp tạo ra các function Javascript (trong Javascript hàm và thủ tục là một và là function). Trong Vue instance có thể khai báo nhiều các phương thức trong thuộc tính methods. Với cú pháp {{ }} cho phép một biểu thức Javascript bên trong nhưng chỉ được duy nhất một câu lệnh đơn và nếu có quá nhiều logic nằm dải rác khắp ứng dụng khiến cho việc duy trì mã nguồn là rất khó khăn. Phương thức trong thuộc tính methods của thực thể Vue có thể đưa vào các logic hoặc những công việc như lấy dữ liệu từ một nguồn ở xa… Ví dụ về việc sử dụng biểu thức Javascript

<!DOCTYPE html>
<html>
<head>
    <title>Ví dụ về phương thức trong Vue.js - allaravel.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <div class="container" id="app">
        <div class="row">
            <div class="col-md-12">
                <h1>Họ tên đầy đủ: {{ ((firstName.toUpperCase().indexOf('VĂN') != -1) ? 'ÔNG' : ((firstName.toUpperCase().indexOf('THỊ') != -1) ? 'BÀ' : 'ÔNG / BÀ')) + ' ' + firstName.toUpperCase() + ' ' + lastName.toUpperCase() }}</h1>
            </div>
        </div>
        <div class="row">
            <div class="col-md-2">
                <label>First name</label>
            </div>
            <div class="col-md-6">
                <input type="text" class="form-control" v-model="firstName">
            </div>
        </div>
        <div class="row">
            <div class="col-md-2">
                <label>Last name</label>
            </div>
            <div class="col-md-6">
                <input type="text" class="form-control" v-model="lastName">
            </div>
        </div>
    </div>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <script type="text/javascript">
        new Vue({
            el: '#app',
            data: {
                firstName: '',
                lastName: ''
            }
        });
    </script>
</body>
</html>

[jsfiddle url=”https://jsfiddle.net/6kqsn5Lm/” height=”300px” include=”result,html,js” font-color=”39464E” menu-background-color=”FFFFFF” code-background-color=”f3f5f6″ accent-color=”1C90F3″]

Logic trong ví dụ như sau, khi nhập Họ (firstName) nếu có Văn hoặc Thị thì sẽ thay Ông/Bà thành Ông hoặc Bà. Trong ứng dụng nếu hiển thị họ tên đầy đủ ở một số nơi, như vậy mỗi khi thay đổi logic chúng ta cần thay đổi ở nhiều chỗ, thay vì như thế chúng ta đưa logic trên vào phương thức trong thuộc tính methods của Vue instance như ví dụ tiếp theo.

<!DOCTYPE html>
<html>
<head>
    <title>Ví dụ về phương thức trong Vue.js - allaravel.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <div class="container" id="app">
        <div class="row">
            <div class="col-md-12">
                <h1>Họ tên đầy đủ: {{ fullName() }}</h1>
            </div>
        </div>
        <div class="row">
            <div class="col-md-2">
                <label>First name</label>
            </div>
            <div class="col-md-6">
                <input type="text" class="form-control" v-model="firstName">
            </div>
        </div>
        <div class="row">
            <div class="col-md-2">
                <label>Last name</label>
            </div>
            <div class="col-md-6">
                <input type="text" class="form-control" v-model="lastName">
            </div>
        </div>
    </div>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <script type="text/javascript">
        new Vue({
            el: '#app',
            data: {
                firstName: '',
                lastName: ''
            },
            methods: {
                fullName: function () {
                    var title = '';
                    if (this.firstName.toUpperCase().indexOf('VĂN') != -1) {
                        title = 'ÔNG';
                    } else if (this.firstName.toUpperCase().indexOf('THỊ') != -1) {
                        title = 'BÀ';
                    } else {
                        title = 'ÔNG/BÀ';
                    }
                    return title + ' ' + this.firstName.toUpperCase() + ' ' + this.lastName.toUpperCase();
                }
            }
        });
    </script>
</body>
</html>

Chuyển sang dùng method không khác gì so với ví dụ đầu, logic về xử lý họ tên đầy đủ được đưa vào fullName(), bất kỳ chỗ nào cần hiển thị họ tên đầy đủ chúng ta chỉ cần gọi đến fullName().

Để truy xuất đến một đối tượng trong thuộc tính data chúng ta sử dụng biến this và sử dụng dấu chấm để truy xuất vào các thành phần thuộc tính con. Ví dụ this.firstName, this.user.firstName…

Phương thức là các hàm, thủ tục do đó nó có thể có tham số đầu vào, ví dụ chúng ta có nhiều kiểu xử lý họ tên đầy đủ theo kiểu tiếng Anh và tiếng Việt khác nhau, ví dụ tiếp theo chúng ta sẽ thực hiện logic này trong phương thức fullName().

<!DOCTYPE html>
<html>
<head>
    <title>Ví dụ về phương thức trong Vue.js - allaravel.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <div class="container" id="app">
        <div class="row">
            <div class="col-md-12">
                <h1>Họ tên đầy đủ: {{ fullName(1) }}</h1>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <h1>Full name: {{ fullName(2) }}</h1>
            </div>
        </div>
        <div class="row">
            <div class="col-md-2">
                <label>Họ và đệm</label>
            </div>
            <div class="col-md-6">
                <input type="text" class="form-control" v-model="firstName">
            </div>
        </div>
        <div class="row">
            <div class="col-md-2">
                <label>Tên</label>
            </div>
            <div class="col-md-6">
                <input type="text" class="form-control" v-model="lastName">
            </div>
        </div>
    </div>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <script type="text/javascript">
        new Vue({
            el: '#app',
            data: {
                firstName: 'Nguyễn Văn',
                lastName: 'Tuấn'
            },
            methods: {
                fullName: function (type) {
                    var title = '';
                    var fullName = '';
                    if (type == 1 ) {
                        // Kiểu Việt Nam
                        if (this.firstName.toUpperCase().indexOf('VĂN') != -1) {
                            title = 'ÔNG';
                        } else if (this.firstName.toUpperCase().indexOf('THỊ') != -1) {
                            title = 'BÀ';
                        } else {
                            title = 'ÔNG/BÀ';
                        }
                        fullName = title + ' ' + this.firstName.toUpperCase() + ' ' + this.lastName.toUpperCase();
                    } else if (type == 2) {
                        // Kiểu Anh
                        title = 'MR/MRS';
                        fullName = title + ' ' + this.lastName.toUpperCase() + ' ' + this.firstName.toUpperCase();
                    }
                    return fullName;
                }
            }
        });
    </script>
</body>
</html>

[jsfiddle url=”https://jsfiddle.net/jcg2fymz/” height=”300px” include=”result,html,js” font-color=”39464E” menu-background-color=”FFFFFF” code-background-color=”f3f5f6″ accent-color=”1C90F3″]

2. Sử dụng arrow function trong khai báo phương thức

2.1 Arrow function là gì?

Function là khái niệm hết sức căn bản trong Javascript, đến phiên bản ECMAScript 5 xuất hiện khái niệm function expression – hàm dạng biểu thức. Đúng như tên gọi của nó, từ khóa function có thể được sử dụng để định nghĩa một hàm trong một biểu thức, bạn hãy xem ví dụ sau đây:

var getSum = function(a, b) {
    return a + b;
}
console.log(getSum(3,4));
// Trả về 7

Đến phiên bản ES 6 xuất hiện một cách viết ngắn gọn hàm dạng biểu thức ở trên dưới dạng dấu mũi tên béo => hay thuật ngữ gọi là arrow function. Ví dụ ở trên được viết lại thành:

let getSum = (a, b) => { return a + b };
console.log(getSum(3,4));
// Trả về: 7

2.2 Cú pháp arrow function

Cú pháp chung của arrow function như sau:

let func = (arg1, arg2, ...argN) => { expression }

Arrow function có chung một cú pháp, dưới đây chúng ta sẽ xem xét từng trường hợp cụ thể sử dụng arrow function. Trường hợp 1: Chỉ có một câu lệnh trong hàm thì có thể bỏ qua các dấu ngoặc:

let getSum = (a, b) => a + b;
console.log(getSum(3,4));

Trường hợp 2: Chỉ có một tham số đầu vào

let getDouble = x => x * 2;
console.log(getDouble(3));
// Kết quả 6

Trường hợp 3: Không có tham số

let alertInfo = () => alert('Không có tham số');
console.log(alertInfo());

Trường hợp 4: Trả về một đối tượng từ arrow function

// ES5
var mix = function(n) {
    return {
        double: n * 2,
        square: n * n
    };
};
// ES6
let mix = n => ({ double: n*2, square: n * n });

Trên đây là các cú pháp cơ bản, chúng ta thường dùng arrow function trong việc thao tác với các mảng, ví dụ sau cho thấy code thao tác mảng thật sự ngắn gọn: Ví dụ: Lấy danh sách ngày sinh từ một mảng chứa thông tin người dùng

const users = [
  { name:'Trần Văn A', birthday:'1982-01-01', active:false },
  { name:'Nguyễn Văn B', birthday:'1993-03-21', active:true },
  { name:'Lê Văn C', birthday:'1978-09-18', active:true }
];
// ES5
var birthdays = users.map(function(user) {
  return user.birthday;
});
// ES6
let birthdays = users.map(user => user.birthday);

Hoặc ví dụ về lọc người dùng đang hoạt động

// ES5
var activeUsers = users.filter(function(user) {
  return user.active;
});
// ES6
let activeUsers = users.filter(user => user.active);

2.3 Hạn chế arrow function

Arrow function không thể sử dụng để làm contructor giống như hàm thông thường, không sử dụng chúng để tạo ra các đối tượng, nếu bạn sử dụng từ khóa new với một arrow function, nó sẽ phát sinh lỗi. Arrow function giống như các function được xây dựng sẵn, không thể có các thuộc tính hoặc các phương thức nội tại.

Kiểu hàm arrow function cần phải khai báo ở trên trước khi gọi đến chúng. Khi đang ở phạm vi bên trong arrow function không thể tham chiếu đến các đối tượng ở ngoài nếu không truyền nó qua tham số.

2.4 Sử dụng arrow function trong thuộc tính methods của Vue instance

Như đã cảnh báo các hạn chế ở trên, arrow function không thể tham chiếu đến các đối tượng ở ngoài nếu không truyền nó qua tham số do arrow function bị ràng buộc với ngữ cảnh gốc và từ khóa this không tham chiếu đến Vue instance. Chính vì thế các thuộc tính của data và các phương thức của Vue không thể tham chiếu đến trong khai báo bằng arrow function. Một giải pháp đưa ra là sử dụng function expression ES5.

// undefined error
methods: {
    fullName: () => this.firsName + ' ' + this.lastName;
}

Với kiểu function expression ES5 như chúng ta vẫn thường viết:

methods: {
    fullName: function() {
    return this.firstName + ' ' + this.lastName;
    }
}

Với các phương thức không cần truy xuất đến các thuộc tính của data hoặc các phương thức khác trong methods thì chúng ta hoàn toàn có thể sử dụng arrow function:

methods: {
    fullName: () => 'Tôi là Vue.js'
}

Hoặc có thể truyền các thuộc tính của data dưới dạng tham số nhưng sẽ phải gõ code nhiều hơn:

<h1>{{ fullName(firstName, lastName) }}</h1>
...
methods: {
    fullName: (a, b) => a+ ' ' + b
}

3. Một số câu hỏi thường gặp

Câu hỏi 1: Truy cập đến một phương thức từ một phương thức khác trong Vue như thế nào? Gọi một phương thức trong một phương thức khác là rất hay sử dụng, trong Vue.js chúng ta sử dụng biến this để truy cập một phương thức trong một phương thức khác, bạn có thể tham khảo ví dụ sau đây:

var vm = new Vue({
  ...
  methods: {
    methodA() {
      // Phương thức A
    },
    methodB() {
      // Phương thức B

      // Gọi phương thức A bên trong phương thức B
      this.methodA()
    }
  },
  ...
});

Câu hỏi 2: Tại sao tôi sử dụng biến this nhưng không thể gọi được phương thức khác, lỗi trong console là undefined? Nếu bạn khai báo phương thức với cú pháp kiểu arrow function của ES6 thì biến this không có tác dụng do ngữ cảnh trong hàm không giống với ngữ cảnh các hàm khai báo thông thường, khi đó sử dụng biến this.phương_thức() hoặc this.thuộc_tính đều trả về undefined. Câu hỏi 3: Có thể gọi phương thức từ bên ngoài Vue instance không? Hoàn toàn có thể được, bạn tham khảo ví dụ sau đây:

var vm = new Vue({ methods: { myFunc : function(){} } } );
this.vm.myFunc();

Câu hỏi 4: Tại sao khi gọi một phương thức thì chương trình gọi tất cả các phương thức khác mặc dù chúng độc lập nhau? Trong các ứng dụng Javascript thông thường các phương thức sẽ độc lập nhau, gọi phương thức nào thì phương thức đó được thực hiện. Điều này không còn đúng 100% trong Vue.js do khi áp dụng mô hình MVVM, mọi thay đổi của một giá trị nó sẽ tự động cập nhật (hay gọi đến) tất cả các phương thức có liên quan. Chúng ta cùng xem xét ví dụ sau để minh chứng cho điều này:

<!DOCTYPE html>
<html>
<head>
    <title>Phương thức trong Vue.js - allaravel.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <p>A = {{ addA() }}</p>
        <p>B = {{ addB() }}</p>
        <button v-on:click="a++">Thêm 1 vào a</button>
        <button v-on:click="b++">Thêm 1 vào b</button>
    </div>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <script type="text/javascript">
        new Vue({
            el: '#app',
            data: {
                a: 0,
                b: 0
            },
            methods: {
                addA: function(){
                    console.log('Gọi phương thức addA');
                    return this.a;
                },
                addB: function(){
                    console.log('Gọi phương thức addB');
                    return this.b;
                }
            }
        });
    </script>
</body>
</html>

Trong ví dụ này, phương thức addA() và addB() rõ ràng là không liên quan gì đến nhau, nhưng khi bấm nút “Thêm 1 vào a” thì chúng ta lại thấy nó gọi đến cả phương thức addB().

Ví dụ Vue.js gọi tất cả các phương thức

Hai phương thức addA() và addB() độc lập với nhau, tuy nhiên trong chúng đều có sử dụng đến dữ liệu được khai báo trong thuộc tính data của Vue instance, như vậy bất kể một thuộc tính nào của data thay đổi, có thể là a hoặc b, các phương thức có sử dụng a hoặc b mà có liên quan đến render đều được gọi. Các câu hỏi thường gặp sẽ được cập nhật, nếu bạn có câu hỏi nào hãy comment cuối bài viết nhé.

4. Lời kết

Methods là một trong những thuộc tính cơ bản của Vue instance và là thuộc tính được sử dụng nhiều nhất. Bài viết khá lan man nhiều thứ nhưng nó có ích cho bạn vì các kiến thức này sẽ được dùng đến ở rất nhiều các phần tiếp theo. Arrow function tuy không phải là mục đích chính của bài viết này nhưng tôi tin chắc các cú pháp ES6 sẽ giúp bạn viết code nhanh hơn gọn đẹp hơn sau này. Hơn nữa việc diễn giải kỹ về arrow function sẽ giúp bạn hiểu tại sao trong một số tài liệu hướng dẫn Vue.js họ khuyến cáo không sử dụng arrow function trong khai báo các phương thức trong thuộc tính methods. Bài viết cũng khá dài, hy vọng dễ đọc với các bạn, nếu có góp ý gì hãy comment cuối bài viết nhé.

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Building Microservices Application – Phần 2: Xử lý “Chain of Failures” dùng Circuit Breaker Pattern với Netflix Hystrix

building

Bài viết được sự cho phép của tác giả Edward Thien Hoang

Trong bài trước, chúng ta đã làm quen với các nền tảng và công cụ để làm việc với Microservice bao gồm Spring Boot, Spring Cloud, Netflix OSS với 3 ứng viên CẦN THIẾT nhất là Netflix Eureka, Ribbon và Zuul để một hệ thống gồm nhiều Microservice có thể hoạt động trơn tru trong điều kiện “thời tiết tốt”, không có lỗi phát sinh nào.

Tuy nhiên, trong thực tế thì đâu có chuyện đơn giản như vậy. Như một tính chất quan trọng nhất mà một hệ thống microservice cần phải đáp ứng đó là khả năng chịu lỗi và phản hồi với lỗi. Đặc biệt là với các lỗi ở dạng “chain of failures”. Một hệ thống microservice, bạn hãy tưởng tượng đó là các quân cờ domino được xếp cạnh nhau, giả sử có một quân tự dưng đổ sầm ra, thì các quân còn lại, liên đới với quân bị đổ sẽ bị đổ theo.

  Building Microservices Application - Phần mở đầu: Bức tranh tổng thể
  Building Microservices Application - Phần 1: Sử dụng Netflix Eureka, Ribbon và Zuul

CIRCUIT BREAKER PATTERN

Để giải quyết vấn đề này, chúng ta có thể áp dụng Circuit Breaker Pattern. Đây là một pattern dùng để ngắt một quá trình xử lý khi hệ thống gặp sự cố, để đảm bảo số lượng message bị lỗi không tăng cao, làm cho việc khắc phục trở nên khó khăn, cũng như có thể làm cho hệ thống bị xụp đổ hàng loạt do ảnh hưởng lẫn nhau. Tư tưởng nó giống cái automat trong mạng điện, khi xảy ra chập điện, thì ngay lập tức automat sẽ ngắt mạch điện, khi nào khắc phúc xong đóng lại thì mạch điện mới thông trở lại. Các bạn có thể search thêm pattern này trên mạng để tìm hiểu chi tiết hơn. Áp dụng nó cho trường hợp microservice bị lỗi, thì ngay khi phát hiện ra sự cố thì ngay lập tức ngắt quá trình gửi/nhận message tới microservice bị lỗi và thay thế bằng các phương pháp dự phòng để tránh tình trạng nghẽn mạch.

Trong bài viết này, hãy cùng tìm hiểu về Circuit Breaker pattern và Netflix Hystrix trước đã. Mô hình của circuit breaker như sau:

1

Nhìn lại bảng nguyên liệu cần thiết để làm món Microservices

1

Netflix Hystrix – cung cấp khả năng ngắt mạch cho service consumer. Nếu một dịch vụ không đáp ứng (do timeout hoặc lỗi giao tiếp), Hystrix có thể chuyển hướng cuộc gọi đến phương thức dự phòng trong service consumer. Nếu một dịch vụ liên tục không hoạt động, Hystrix sẽ mở mạch và thực hiện fail fast (tức là gọi phương thức dự phòng mà không gọi đến service đó luôn) trên tất cả request tiếp theo cho đến khi dịch vụ “sống” trở lại. Để xác định khi nào một dịch vụ sống lại, lâu lâu nó sẽ thử bằng cách cho phép các request tới dịch vụ đó để xem nó sống lại hay chưa. Hystrix được cài đặt ở phía service consumber.

Netflix Hystrix dashboard và Netflix Turbine – được sử dụng để cung cấp tình hình tổng quan của bộ ngắt mạch và Turbine, dựa trên thông tin trong Eureka.

2

2. KIẾN TRÚC

Phần 2 này sẽ bổ Hystrix dashboard và Turbine vào Infrastructure Server. Product-composite service cũng có thêm một bộ ngắt mạch Hystrix.

3

3. SOURCE CODE

Cũng giống như Phần 1, chúng ta cần có Java SE 8, Git và Gradle.

$ git clone https://github.com/callistaenterprise/blog-microservices.git
$ cd blog-microservices
$ git checkout -b B2 M2.1
$ ./build-all.sh

Nếu đang sử dụng Windows, bạn có thể thực thi tập tin bat tương ứng build-all.bat!

Hai thành phần mã nguồn mới đã được thêm vào kể từ Phần 1 là: monitor-dashboard và turbine:

4

4. DIỄN GIẢI SOURCE CODE

4.1 GRADLE DEPENDENCIES

Do Hystrix sử dụng RabbitMQ để giao tiếp giữa các bộ phận ngắt mạch và dashboards, chúng ta cần phải thiết lập các dependencies cho nó.

Đối với một service consumer, muốn sử dụng Hystrix như một bộ ngắt mạch cần thêm:

compile("org.springframework.cloud:spring-cloud-starter-hystrix:1.0.0.RELEASE")
compile("org.springframework.cloud:spring-cloud-starter-bus-amqp:1.0.0.RELEASE")
compile("org.springframework.cloud:spring-cloud-netflix-hystrix-amqp:1.0.0.RELEASE")

Để có thể thiết lập Turbine server, hãy thêm dependency sau:

compile('org.springframework.cloud:spring-cloud-starter-turbine-amqp:1.0.0.RELEASE')

4.2. INFRASTRUCTURE SERVERS

Thiết lập Turbine server bằng cách thêm @EnableTurbineAmqp annotation vào Spring Boot application:

@SpringBootApplication
@EnableTurbineAmqp
@EnableDiscoveryClient
public class TurbineApplication {

public static void main(String[] args) {
SpringApplication.run(TurbineApplication.class, args);
}

}

Để thiết lập Hystrix Dashboard, hãy thêm @EnableHystrixDashboard annotation. Có thể xem mã nguồn hoàn chỉnh trong file HystrixDashboardApplication.java.

Với các annotations đơn giản này, bạn đã có thể tạo ra các server đỉnh, làm được việc và không lo bị cháy cầu chì 😀

4.3 BUSINESS SERVICE

Để kích hoạt Hystrix, hãy thêm @EnableCircuitBreaker annotation vào ứng dụng Spring Boot của bạn.

@SpringBootApplication
@EnableCircuitBreaker
@EnableDiscoveryClient
public class ProductCompositeServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductCompositeServiceApplication.class, args);
}
}

Thêm @HystrixCommand annotation vào các service method và thiết lập fallback method trong trường hợp có lỗi:

@Component
public class ProductCompositeIntegration {
@HystrixCommand(fallbackMethod = "defaultReviews")
public ResponseEntity getReviews(int productId) {
...
}

public ResponseEntity defaultReviews(int productId) {
...
}
}

Method dự phòng được sử dụng bởi Hystrix trong trường hợp có lỗi (gọi tới dịch vụ không thành công hoặc timeout) hoặc fail fast nếu mạch đang mở. Để xem ví dụ hoàn chỉnh, hãy xem ProductCompositeIntegration.java.

5. KHỞI CHẠY CÁC MICROSERVICES

Để có thể chạy một số lệnh được sử dụng bên dưới, cần phải cài đặt các cURL và jq .

Như đã đề cập, Hystrix sử dụng RabbitMQ cho giao tiếp nội bộ nên cần phải cài đặt và chạy nó trước khi khởi động các microservices. Làm theo hướng dẫn tại Downloading and Installing. Sau đó, start RabbitMQ bằng rabbitmq-server trong folder sbin của thư mục cài đặt.

$ ~/Applications/rabbitmq_server-3.4.3/sbin/rabbitmq-server

RabbitMQ 3.4.3. Copyright (C) 2007-2014 GoPivotal, Inc.
## ## Licensed under the MPL. See http://www.rabbitmq.com/
## ##
########## Logs: /Users/magnus/Applications/rabbitmq_server-3.4.3/sbin/../var/log/rabbitmq/rabbit@Magnus-MacBook-Pro.log
###### ## /Users/magnus/Applications/rabbitmq_server-3.4.3/sbin/../var/log/rabbitmq/rabbit@Magnus-MacBook-Pro-sasl.log
##########
Starting broker... completed with 6 plugins.

Sau đó sử dụng lệnh ./gradlew bootRun để start các services

Đầu tiên hãy start các infrastructure services

$ cd support/discovery-server; ./gradlew bootRun
$ cd support/edge-server; ./gradlew bootRun
$ cd support/monitor-dashboard; ./gradlew bootRun
$ cd support/turbine; ./gradlew bootRun

Sau đó start các business services

$ cd core/product-service; ./gradlew bootRun
$ cd core/recommendation-service; ./gradlew bootRun
$ cd core/review-service; ./gradlew bootRun
$ cd composite/product-composite-service; ./gradlew bootRun

Nếu đang sử dụng Windows, bạn có thể thực thi tập tin bat tương ứng start-all.bat!

Khi các microservices được khởi động và được đăng ký với máy chủ khám phá dịch vụ, chúng sẽ ghi các thông tin sau vào log:

DiscoveryClient … – registration status: 204

Trong ứng dụng web khám phá dịch vụ, bây giờ chúng ta có thể thấy bốn business services và một edge server (http://localhost:8761):

3

Cuối cùng đảm bảo rằng các bộ phận ngắt mạch đang hoạt động, tức là đang ở trạng thái đóng mạch (closed). Hãy thử gọi đến composite service thông qua the edge-server:

$ curl -s localhost:8765/productcomposite/product/1 | jq .
{
"name": "name",
"productId": 1,
"recommendations": [
{
"author": "Author 1",
"rate": 1,
"recommendationId": 0
},
...
],
"reviews": [
{
"author": "Author 1",
"reviewId": 1,
"subject": "Subject 1"
},
...
],
"weight": 123
}

Vào địa chỉ http://localhost:7979 trong trình duyệt web, nhập địa chỉ http://localhost:8989/turbine.stream và click vào “Monitor Stream“:

5

Chúng ta có thể thấy rằng composite service có ba bộ phận ngắt mạch hoạt động, mỗi cái tương ứng với một core service mà nó cần gọi đến. Hiện tại không có vấn đề gì, tức là bộ ngắt mạch đang đóng. Tiếp theo hãy thử nghiệm trong trường hợp có lỗi xảy ra.

6. TEST

Stop review service và thử lại lệnh trên:

$ curl -s localhost:8765/productcomposite/product/1 | jq .
{
"name": "name",
"productId": 1,
"recommendations": [
{
"author": "Author 1",
"rate": 1,
"recommendationId": 0
},
...
],
"reviews": null,
"weight": 123
}

Phần reviews trong response bị trống, nhưng những phần khác vẫn được trả về! Nhìn vào log của product-composite service sẽ thấy các warning:

2015-04-02 15:13:36.344 INFO 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : GetRecommendations...
2015-04-02 15:13:36.497 INFO 29901 --- [teIntegration-2] s.c.m.c.p.s.ProductCompositeIntegration : GetReviews...
2015-04-02 15:13:36.498 WARN 29901 --- [teIntegration-2] s.c.m.composite.product.service.Util : Failed to resolve serviceId 'review'. Fallback to URL 'http://localhost:8081/review'.
2015-04-02 15:13:36.500 WARN 29901 --- [teIntegration-2] s.c.m.c.p.s.ProductCompositeIntegration : Using fallback method for review-service

Tức là bộ ngắt mạch đã phát hiện ra sự cố với Review service và định tuyến đến phương thức dự phòng. Trong trường hợp này, chúng ta đơn giản là trả về null nhưng cung có thể, ví dụ, trả về dữ liệu từ bộ đệm local để cung cấp kết quả tốt nhất khi service review không có sẵn.

Mạch vẫn đóng vì lỗi không phải là thường xuyên:

6

Hãy tăng tần số lỗi vượt quá giới hạn mà Hystrix sẽ mở mạch và bắt đầu fail fast (sử dụng giá trị mặc định của Hystrix). Chúng ta sử dụng Apache HTTP server benchmarking tool cho việc này:

ab -n 30 -c 5 localhost:8765/productcomposite/product/1

Bây giờ mạch sẽ được mở ra:

xxx

… và các cuộc gọi tiếp theo sẽ nhanh chóng thất bại, tức là bộ ngắt mạch sẽ chuyển hướng cuộc gọi trực tiếp đến phương thức dự phòng của nó mà không cần cố gắng gọi đến service review nữa. Log lúc này sẽ không còn chứa thông báo GetReviews…:

2015-04-02 15:14:03.930 INFO 29901 --- [teIntegration-5] s.c.m.c.p.s.ProductCompositeIntegration : GetRecommendations...
2015-04-02 15:14:03.984 WARN 29901 --- [ XNIO-2 task-62] s.c.m.c.p.s.ProductCompositeIntegration : Using fallback method for review-service

Tuy nhiên, theo thời gian nó sẽ cho phép một số cuộc gọi đi qua để xem nếu chúng thành công tức là service review đã sống lại như log dưới đây:

2015-04-02 15:17:33.587 INFO 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : GetRecommendations...
2015-04-02 15:17:33.769 INFO 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : GetReviews...
2015-04-02 15:17:33.769 WARN 29901 --- [eIntegration-10] s.c.m.composite.product.service.Util : Failed to resolve serviceId 'review'. Fallback to URL 'http://localhost:8081/review'.
2015-04-02 15:17:33.770 WARN 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : Using fallback method for review-service
2015-04-02 15:17:34.431 INFO 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : GetRecommendations...
2015-04-02 15:17:34.569 WARN 29901 --- [ XNIO-2 task-18] s.c.m.c.p.s.ProductCompositeIntegration : Using fallback method for review-service
2015-04-02 15:17:35.209 INFO 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : GetRecommendations...
2015-04-02 15:17:35.402 WARN 29901 --- [ XNIO-2 task-20] s.c.m.c.p.s.ProductCompositeIntegration : Using fallback method for review-service
2015-04-02 15:17:36.043 INFO 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : GetRecommendations...
2015-04-02 15:17:36.192 WARN 29901 --- [ XNIO-2 task-21] s.c.m.c.p.s.ProductCompositeIntegration : Using fallback method for review-service
2015-04-02 15:17:36.874 INFO 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : GetRecommendations...
2015-04-02 15:17:37.031 WARN 29901 --- [ XNIO-2 task-22] s.c.m.c.p.s.ProductCompositeIntegration : Using fallback method for review-service
2015-04-02 15:17:41.148 INFO 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : GetRecommendations...
2015-04-02 15:17:41.340 INFO 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : GetReviews...
2015-04-02 15:17:41.340 WARN 29901 --- [eIntegration-10] s.c.m.composite.product.service.Util : Failed to resolve serviceId 'review'. Fallback to URL 'http://localhost:8081/review'.
2015-04-02 15:17:41.341 WARN 29901 --- [eIntegration-10] s.c.m.c.p.s.ProductCompositeIntegration : Using fallback method for review-service

Như chúng ta có thể thấy từ log, cứ mỗi 5 lần thì request được phép chuyển tới service review để kiểm tra một lần (tuy vẫn không thành công…).

Bây giờ hãy start service review lên và thử lại:
Bây giờ chúng ta có thể thấy phản hồi là ok, tức là review service đã trở lại và mạch được đóng lại:

7

7. TÓM TẮT

Bài này chúng ta đã tìm hiểu về Netflix Hystrix để sử dụng như một bộ ngắt mạch gải quyết vấn đề chain of failures như thế nào chỉ với các annotation đơn giản. Hystrix dashboard và Turbine cũng có thể giúp bạn giám sát các bộ ngắt mạch trong toàn hệ thống.

8. TIẾP THEO

Trong bài tiếp theo, chúng ta sẽ xem xét cách sử dụng OAuth 2.0 để kiểm soát quyền truy cập vào các microservice được phơi ra bên ngoài.

Series này là phần tiếp theo series Microservices: Từ Thiết Kế Đến Triển Khai, tập trung vào việc hiện thực hóa các khái niệm đã mô tả ở phần lý thuyết. Hi vọng sẽ giúp ích được cho các bạn khi làm quen với microservies. Các bạn có thể tham khảo thêm về phần Architecture căn bản ở đây nhé.

NÊN & KHÔNG NÊN Để Đàm Phán Lương Thành Công Khi Phỏng Vấn

cách đàm phán lương khi phỏng vấn
NÊN & KHÔNG NÊN Để Đàm Phán Lương Thành Công Khi Phỏng Vấn

Mục đích cuối cùng khi đi tìm việc của mọi ứng viên chính là có được mức thu nhập như mong muốn. Và để buổi phỏng vấn thành công, đừng bao giờ xem nhẹ cách đàm phán lương với nhà tuyển dụng. Mức lương cao hay thấp sẽ được quyết định dựa vào cách người phỏng vấn được công ty đánh giá được năng lực chuyên môn cũng như các kỹ năng mềm mà bạn thể hiện. Vậy phải làm thế nào để deal được mức lương như ý? Hãy nắm rõ những cách đàm phán lương khi phỏng vấn dưới đây để thương lượng thành công.

cách đàm phán lương khi phỏng vấn
Làm thế nào để deal lương thành công?

Những điều “NÊN” để đàm phán lương đạt hiệu quả

Nhiều khảo sát đã cho thấy rằng, hầu hết trong các buổi phỏng vấn, nhà tuyển dụng luôn là phía nằm ở “kèo trên” và có ưu thế hơn so với ứng viên khi deal lương. Để thật sự đạt được mức thu nhập mình mong muốn, đừng bỏ qua những lời khuyên hữu ích này.

1. Nên nghiên cứu kỹ lưỡng về thị trường và mặt bằng lương của ngành

Tùy vào mỗi ngành nghề khác nhau mà mức lương của mặt bằng chung trên thị trường sẽ có sự khác biệt. Bạn nên tìm hiểu về mức lương trung bình của ngành mình đang ứng tuyển và nếu có thể, hãy nghiên cứu về mức lương cụ thể với chuyên ngành chính của mình. Biết rõ mức lương thị trường và những yêu cầu kinh nghiệm với mỗi rank lương khác nhau sẽ giúp bạn biết được vị thế hiện tại của bản thân cũng như khả năng mà mình có thể đáp ứng trong công việc.

Có nhiều cách khác nhau để nghiên cứu về thị trường lương bổng. Bạn có thể tìm hiểu thông qua các kết quả khảo sát thị trường hoặc những người quen biết, đồng nghiệp,… Tùy thuộc vào mỗi vị trí và yêu cầu chuyên môn mà mức lương sẽ khác nhau, tốt hơn hết bạn nên cố gắng trau dồi cho bản thân những kỹ năng nâng cao và khác biệt với người khác để đạt được mức thu nhập tốt.

  4 mẹo deal lương như ý với vị trí Product Manager

2. Nên để nhà tuyển dụng đưa ra đề nghị về mức lương trước

Chọn đúng thời điểm thích hợp khi đàm phán lương cũng là nguyên tắc vàng để bạn có được mức lương như ý. Thời điểm tốt nhất là khi nhà tuyển dụng đang vui vẻ và hài lòng với những kinh nghiệm hay kỹ năng mà bạn chia sẻ. Đó cũng là một cách để ứng viên nâng tầm giá trị bản thân so với các ứng viên đối thủ khác.

Tốt nhất bạn nên để nhà tuyển dụng đưa ra đề nghị về mức lương trước. Vì điều đó đồng nghĩa với việc họ đã có sự ghi nhận với những chia sẻ của bạn và đang thật sự sẵn lòng để tuyển bạn. Ngược lại, nếu bạn đề cập đến thu nhập mong muốn trước có thể khiến nhà tuyển dụng cảm thấy rằng bạn đang tự đánh giá mình quá cao và thiếu đi sự khiêm tốn. Hãy linh hoạt theo nhịp điệu của buổi phỏng vấn để biết đâu là thời điểm hợp lí cho việc đề cập đến lương bổng, đó chính là cách đàm phán lương khi phỏng vấn hiệu quả.

Xem thêm 4 mẹo deal lương như ý với vị trí Product Manager

deal lương hiệu quả

3. Nên đề cập đến các khoản trợ cấp và phúc lợi đi kèm với lương

Hiện nay, có một số công ty bên cạnh lương cứng còn trả thêm các khoản phụ cấp và thưởng KPI cho nhân viên. Những khoản thưởng thêm này có thể tăng đến 40% thu nhập của nhân viên bên cạnh lương cứng. Chính vì thế, hãy thẳng thắn và cởi mở trao đổi thêm với nhà tuyển dụng về những khoản trợ cấp, thưởng thêm và phúc lợi để hiểu rõ hơn về những gì mình sẽ nhận được.

Đặc biệt, trong những trường hợp nhà tuyển dụng đang đưa ra mức lương cứng thấp hơn so với mong muốn thì lúc này, việc tìm hiểu về chế độ phúc lợi đi kèm là rất cần thiết. Điều này sẽ giúp bạn có cái nhìn toàn diện hơn về lương bổng và phúc lợi mà công ty cung cấp cũng như đánh giá chính xác khoản thu nhập thực nhận là như thế nào, có thể đáp ứng các yêu cầu của mình hay không.

Tính lương chuẩn với công cụ tính lương gross – net từ TopDev

4. Khéo léo và tạo không khí thân thiện để đàm phán hiệu quả hơn

Đây có thể xem là yếu tố cực kỳ quan trọng không chỉ giúp bạn đàm phán được mức lương tốt nhất mà còn thể hiện được khả năng giao tiếp và xử lý tình huống trong mắt nhà tuyển dụng. Hãy nói chuyện một cách khéo léo và trên tinh thần cùng nhau trao đổi một cách thiện chí để khiến nhà tuyển dụng cảm thấy rằng bạn thật sự có mong muốn được cống hiến cho công ty họ.

Nếu mức lương công ty đưa ra không đáp ứng được kỳ vọng của bạn, hãy cảm ơn và đưa ra những lý do để thuyết phục nhà tuyển dụng rằng bạn xứng đáng với mức thu nhập tốt hơn như thế. Hãy cho nhà tuyển dụng thấy được tinh thần hợp tác thay vì việc vội vàng tỏ thái độ hay từ chối thẳng thừng. Kiên nhẫn lắng nghe nhau và đưa ra con số hợp lý nhất so với thị trường, năng lực ứng viên cũng như tiềm lực chi trả của công ty là giải pháp hoàn hảo cho bất kỳ buổi phỏng vấn nào.

  Bí quyết deal lương giúp bạn “lật bài ngửa” với nhà tuyển dụng

Những điều “KHÔNG NÊN” để việc đàm phán lương diễn ra suôn sẻ

1. Không nên vội vàng đề xuất mức lương khi chưa được nhà tuyển dụng nhắc đến

Đây được xem là lời khuyên quan trọng với bất cứ ai sắp có một buổi phỏng vấn trong tương lai. Đừng vội vàng “ra giá” bản thân nếu chưa được nhà tuyển dụng đề cập. Điều này sẽ khiến người phỏng vấn cảm thấy rằng bạn đang quá tự tin và chỉ quan tâm đến vấn đề lương bổng, trong khi thứ họ muốn bạn thể hiện là những gì có thể đóng góp được cho sự phát triển của công ty.

Những nhà tuyển dụng chuyên nghiệp đều sẽ chủ động đưa ra câu hỏi về mức lương cho vị trí ứng tuyển. Vậy nên đừng vội vàng, lúc đó hãy lịch sự đề xuất mức lương dựa trên những gì bạn đã nghiên cứu và tìm hiểu cũng như đừng quên tìm hiểu thêm về các phúc lợi đối với người lao động của công ty ở thời điểm hiện tại.

lưu ý khi deal lương

2. Không nên tiết lộ chính xác mức lương trong quá khứ

Mức lương cũ mà bạn đã nhận được luôn là vấn đề nhạy cảm, vậy nên hãy thận trọng khi nhận được câu hỏi như thế này. Đàm phán về mức lương là vấn đề rất quan trọng của mỗi cuộc phỏng vấn, tuy nhiên, trong một số trường hợp, nếu không biết cách trả lời khéo léo và thiếu thận trọng sẽ rất dễ dẫn đến việc đàm phán đi vào bế tắc.

Do đó, nên cân nhắc mức lương cũ cũng như rank lương hiện tại mà công ty có thể chi trả để đưa ra câu trả lời về mức lương cũ cho phù hợp. Vì mức lương sẽ phản ánh năng lực làm việc của cá nhân. Quan trọng là hãy thuyết phục nhà tuyển dụng rằng bạn có thể cống hiến được cho công ty nhiều như thế nào và tại sao công ty cần bạn.

  Các Mức Level BrSE Và Mức Lương Tương Ứng

3. Không nên đồng ý ngay khi lời đề nghị được đưa ra

Thật ra bạn có thể đã hoàn toàn đồng ý với mức offer mà bên tuyển dụng đưa ra nhưng không nên quá hào hứng và nhận lời ngay lập tức. Hãy dành ra ít nhất 24 giờ để suy nghĩ thật kỹ về những gì mình sẽ nhận được khi làm việc với vị trí đó (không chỉ mỗi mức lương). Lúc này, bạn có thể cẩn thận suy xét về mọi khía cạnh cũng như nhìn nhận mức lương nhận được và công việc phải làm có tương xứng với nhau hay không. Và bên cạnh đó, cũng cho nhà tuyển dụng thấy rằng bạn đã thật sự bỏ thời gian để suy nghĩ về công việc này và có thái độ thật sự nghiêm túc.

Thu nhập chính là yếu tố cuối cùng có tác động mạnh đến việc một người có đồng ý chuyển sang vị trí mới, công ty mới hay không. Chính vì thế, nắm được những cách đàm phán lương khi phỏng vấn hiệu quả sẽ giúp bạn dễ dàng hơn trong quá trình trao đổi cũng như có được mức lương mà mình mong muốn.


Tuyển Dụng Nhân Tài IT Cùng TopDev
Đăng ký nhận ưu đãi & tư vấn về các giải pháp Tuyển dụng IT & Xây dựng Thương hiệu tuyển dụng ngay!
Hotline: 028.6273.3496 – Email: contact@topdev.vn
Dịch vụ: https://topdev.vn/page/products

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Lộ diện các công ty IT Hàn Quốc sẵn sàng nâng bước sự nghiệp cho lập trình viên Việt

Thị trường IT Việt Nam đang trên nhịp tăng trưởng mạnh và ngày càng trở nên sôi động hơn với làn sóng đầu tư từ nước ngoài, mang đến nhiều cơ hội phát triển cho các lập trình viên Việt. Tiêu biểu trong số đó, không thể không kể đến Hàn Quốc – Một trong những cường quốc về CNTT đang hướng sự chú ý đến nguồn lực IT trẻ và tài năng tại Việt Nam.

Tiếp nối thành công của dự án hợp tác 2020, KICC HCMC cùng TopDev tiếp tục mang đến chương trình hợp tác năm 2021 với thông điệp “Make Your IT Career Outstanding – Khởi sắc sự nghiệp IT của bạn”. Theo đó là những hoạt động phối hợp với mục đích kết nối các việc làm ngành CNTT tại các doanh nghiệp IT Hàn Quốc với đối tượng Lập Trình Viên Việt Nam. Từ đó hỗ trợ, hợp tác và thúc đẩy tuyển dụng việc làm công nghệ thông tin cho các công ty Hàn Quốc và tạo thêm nhiều cơ hội để các tài năng IT Việt Nam sở hữu những tấm vé gia nhập vào các doanh nghiệp công nghệ hàng đầu của Hàn Quốc hiện đang có mặt tại Việt Nam. 

Cùng khám phá xem Top 7 công ty công nghệ đến từ Hàn Quốc xuất hiện tiếp theo trong kỳ này sẽ mang đến những điều thú vị và cơ hội nào cho các tài năng IT Việt Nam nhé!

1. Shinhan DS Vietnam Company Limited

Mở màn cho danh sách kỳ này là sự xuất hiện của Shinhan DS Vietnam – thành viên của SHINHAN, một trong những tập đoàn tài chính hàng đầu với hơn 100 năm uy tín tại Hàn Quốc. Góp mặt vào thị trường IT Việt Nam từ tháng 5/2018, Shinhan DS Vietnam hứa hẹn là bước nhảy vọt ấn tượng của tập đoàn, mang đến những dịch vụ CNTT chất lượng cao, có được sự tin tưởng và ủng hộ từ khách hàng.

⇒ Nếu bạn là Experienced Software Developer (Junior/ Senior) đang tìm kiếm cơ hội trải nghiệm môi trường làm việc tuyệt vời tại một trong những tập đoàn danh tiếng, Shinhan DS Vietnam hứa hẹn là điểm đến lý tưởng cho hành trình phát triển sự nghiệp của bạn.   

2. LOTTE Data Communication Company Vietnam

LOTTE Data Communication Company Vietnam tự hào là nhà cung cấp các giải pháp và Dịch vụ IT chất lượng cho các công ty con thuộc Tập đoàn LOTTE tại Việt Nam trong hơn thập kỷ qua. Với đội ngũ chuyên gia, kỹ sư dày dặn kinh nghiệm, công ty luôn chiếm được niềm tin từ phía Đối tác và Khách hàng.

Kế thừa tất cả tinh hoa từ Công ty mẹ, LOTTE Data Communication Việt Nam kết nối và phát triển mạng lưới khách hàng thuộc mọi lĩnh vực từ Bán lẻ, Sản xuất đến Tài chính, Dịch vụ công… bằng những giải pháp bắt kịp xu hướng Công nghệ của thế giới như Triển khai hệ thống ra vào cho cao ốc, An Ninh nhận diện khuôn mặt, Smart Parking, Thu phí tự động,…

Tiếp tục góp mặt vào dự án KICCxTopDev 2021, LOTTE Data Communication Việt Nam đặc biệt mang đến cơ hội chuyển mình bứt phá dành cho các nhân tài IT tại Việt Nam với vị trí Senior System Administrator. Khám phá ngay để không bỏ lỡ những trải nghiệm nghề nghiệp thú vị bạn nhé!

3. Lecle Vietnam JSC

Lecle là công ty phần mềm toàn cầu có trụ sở chính tại Hàn Quốc cùng nhiều văn phòng đặt tại Mỹ, Singapore và Việt Nam. Với phương châm “We work and enjoy hard”, Lecle Vietnam nỗ lực đem đến môi trường làm việc đáng mơ ước, hứa hẹn là “bệ phóng” năng lực cho sự nghiệp bạn đồng thời tạo “sân chơi” lý tưởng giúp gắn kết mỗi thành viên trong công ty.

Lecle Vietnam JSC đang trên hành trình tìm kiếm tài năng IT đất Việt cho vị trí Front-end Developer (JavaScript, ReactJS) với mức lương hấp dẫn cùng loạt đặc quyền phong phú:

  • Được trang bị Macbook xịn sò
  • Chế độ nghỉ phép và thưởng xứng đáng
  • “Tấm vé” tham dự sự kiện và hoạt động thú vị
  • Cơ hội onsite Hàn Quốc

>>> Và nếu môi trường làm việc tuyệt vời tại Lecle Vietnam JSC đã đủ để kích hoạt tài năng trong bạn? Vậy đừng chần chờ thêm nữa, nắm bắt cơ hội tốt ngay hôm nay!

4. NHN VIỆT NAM

NHN Việt Nam là công ty con của NHN Corporation, phụ trách phát triển công nghệ cho các dịch vụ của NHN tại Đông Nam Á, tự hào với Comico – một trong những ứng dụng webtoon hàng đầu tại Việt Nam. Đồng thời, công ty cũng là đầu mối cung cấp nền tảng có giá trị giúp mở rộng dịch vụ trò chơi di động rộng khắp các nước Đông Nam Á.

Không dừng lại ở đó, sự xuất hiện của NHN Việt Nam trong kỳ này còn mang đến “tấm vé” khởi sắc sự nghiệp cho các lập trình viên tài năng với nhiều cơ hội bùng nổ năng lực đang chờ bạn tại 1 trong 2 vị trí:

– Manual Tester

– Senior Frontend (Javascript, HTML, CSS)

5. CAFE24 VINA

CAFE24 VINA là nền tảng thương mại điện tử toàn cầu, nơi cung cấp các dịch vụ giải pháp E-commerce tổng hợp như xây dựng cửa hàng trực tuyến, thanh toán, vận chuyển, marketing, liên kết với các sàn TMĐT.

Với kinh nghiệm 20 năm hoạt động tại Hàn Quốc với nhiều chi nhánh tại Nhật bản, Đài Loan, Mỹ,… CAFE24 VINA hướng tới việc mở rộng thị trường rộng khắp khu vực Đông Nam Á, trong đó có Việt Nam. Và để thực hiện mục tiêu đó, công ty đang ráo riết tìm kiếm Front-End Developer cùng với loạt cơ hội phát triển sự nghiệp và đặc quyền xứng đáng sẵn sàng trao tay.

6. DataStreams Asia

DataStreams Asia là doanh nghiệp Hàn Quốc hiện đang dẫn đầu thị trường về tích hợp quản lý chất lượng dữ liệu. Với công nghệ và đội ngũ chuyên môn có trình độ tốt, DataStreams Asia tự hào đã đưa ra các giải pháp với hiệu suất cao giúp xử lý và quản lý dữ liệu an toàn, hiệu quả.

Tính đến nay, Datastreams Asia đã thành lập nhiều chi nhánh ở Mỹ, Trung Quốc, Nhật Bản, Việt Nam…và đang dần mở rộng thị trường ra nước ngoài thông qua hợp tác với các đối tác toàn cầu như doanh nghiệp phát triển ứng dụng, công ty tư vấn công nghệ thông tin, đại lý…

Nếu bạn yêu thích lĩnh vực Dữ liệu hoặc đang tìm kiếm cơ hội tiếp xúc các công nghệ mới như ioT, big data,… thì DataStreams Asia chính là điểm đến phù hợp dành cho bạn. Bắt ngay “slot” gia nhập tại vị trí IT Manager và sẵn sàng chinh phục đỉnh cao sự nghiệp từ hôm nay!

7. Beyondnet VN

Beyondnet VN là nhà cung cấp dịch vụ thoại và internet cấp 2 (ISP) hỗ trợ các công ty Hàn Quốc hoạt động tại Việt Nam, Philippines và Hàn Quốc. Hiện tại Beyondnet đang tập trung vào việc cung cấp kết nối internet nhanh chóng cho khách hàng Hàn Quốc ở nước ngoài thông qua mạng đường trục toàn cầu và hỗ trợ dịch vụ viễn thông địa phương và bảo trì CNTT.

Và nếu bạn đã sẵn sàng để trở thành nhân tố quan trọng góp phần làm nên thành công của Beyondnet VN? Nhanh tay bắt ngay cơ hội tại vị trí System Engineer để không bỏ lỡ những đặc quyền hấp dẫn đang chờ bạn tại Beyondnet VN.

Với sự xuất hiện của Top 7 công ty công nghệ Hàn Quốc trong kỳ này, TopDev hi vọng bạn có thêm những thông tin hữu ích và lựa chọn được “bến đỗ” phù hợp để thỏa sức bùng nổ năng lực, phát huy thế mạnh của bản thân. Và đừng quên đón đọc những bài viết tiếp theo và chớp ngay những cơ hội mới hấp dẫn cho sự nghiệp bạn nhé!

Thông tin chi tiết về dự án vui lòng truy cập tại đây

Về KICC HCMC và NIPA

Được thành lập vào ngày 23 tháng 5 năm 2019, KICC HCMC (KICC Hồ Chí Minh) là văn phòng thứ 6 trên toàn cầu và thứ 2 tại Việt Nam. KICC là văn phòng quốc tế trực thuộc Bộ Khoa học – Công nghệ Thông tin Hàn Quốc (MSIT) và Cơ quan Xúc tiến Công nghệ Thông tin – Truyền thông (NIPA) với mục đích giúp đỡ việc kinh doanh quốc tế của những công ty về Công nghệ Thông tin (CNTT) của Hàn Quốc. KICC có 06 văn phòng ở Thung lũng Silicon (Mỹ), Tokyo (Nhật), Bắc Kinh (Trung Quốc), Singapore, Hà Nội (Việt Nam) và Hồ Chí Minh (Việt Nam).

NIPA là tổ chức phi lợi nhuận từ Chính phủ Hàn Quốc và là thành viên của Bộ Khoa học – Công nghệ Thông tin Hàn Quốc, chịu trách nhiệm trong việc hỗ trợ các công ty và các chuyên gia CNTT. NIPA hiện dẫn đầu trong kiến thức về cơ sở hạ tầng kinh tế xã hội và phát triển kinh tế quốc gia bằng việc xúc tiến khả năng cạnh tranh của toàn ngành công nghiệp thông qua sự tiến bộ kỹ thuật CNTT và công nghiệp.

Thông tin liên hệ:

  • Hotline: 84 28 35208135 (Vietnamese) | 84 28 35208136 (Korean)
  • E-mail: HCMC@nipa.kr
  • Địa chỉ: 135 Hai Bà Trưng, Phường Bến Nghé, Quận 1, Thành phố Hồ Chí Minh

Về TopDev – nền tảng tuyển dụng IT

Với hơn 300.000 profile lập trình viên đồng thời sở hữu Cộng đồng Lập trình viên lớn nhất Việt Nam, TopDev hiện là một trong những nền tảng tuyển dụng chuyên về IT hàng đầu tại Việt Nam.  Ngoài ra, TopDev là một trong những đơn vị tiên phong ở lĩnh vực IT tại Việt Nam, giúp xây dựng và phát triển thương hiệu tuyển dụng – Employer Brand cho hàng trăm công ty công nghệ trong và ngoài nước. Đây còn là đơn vị chuyên khảo sát, phân tích và phát hành các báo cáo quý, năm về thị trường và nhân lực IT tại Việt Nam. (Báo cáo thị trường IT tại đây)

Tìm việc IT lương cao, đãi ngộ tốt trên TopDev ngay!

CDN là gì? – CDN hoạt động như thế nào?

CDN là gì? – CDN hoạt động như thế nào?

Bài viết được sự cho phép của tác giả Kiên Nguyễn

CDN, viết tắt của từ Content Delivery Network (Mạng lưới phân phối nội dung) hiện nay đã trở nên vô cùng quen thuộc với chúng ta.

CDN có thể bắt gặp ở mọi nơi. Dù có chấp nhận hay không thì bản thân chúng ta vẫn tương tác với CDN hàng ngày. Từ lướt web, xem youtube hay tìm kiếm bất cứ thông tin gì. Chẳng hạn như bài viết này cũng có thể đang được lấy từ bộ đêmc của Content Delivery Network nào đó.

  CDN - Chỉ 1 giây làm đổi thay tâm trí khách hàng
  Cách làm HTTPS hoạt động trên local trong 5 phút

Vậy chính xác CDN – Content Delivery Network là gì?

1. Tại sao lại cần CDN?

Trước tiên, để hiểu tại sao chúng ta cần Content Delivery Network, ta cần hiểu từ khóa LATENCY (độ trễ).

LATENCY the annoying delay that occur. from the moment you request to load a web page to the moment its content actually appears onscreen.

Độ trễ được biết tới như là khoảng thời gian từ lúc chúng ta yêu cầu tải trang web cho tới khi thật sự nhìn thấy nội dung trên trang web đó.

Thông thường, nếu máy chủ chưa nội dung trang web ở Việt Nam và người request yêu cầu nội dung ở Việt Nam thì rất ít khi nhận ra độ trễ.

Độ trễ thường bị ảnh hưởng bởi một vài yếu tố sau:

  • Nội dung trang web
  • Khoảng cách vật lí
  • Tốc độ mạng

Tuy nhiên, yếu tố ảnh hưởng nhiều nhất vẫn là khoảng cách vật lí.

2. CDN ra đời

Để giải quyết vấn đề về độ trễ và giúp thời gian tải trang nhanh hơn, mạng lưới nội dung (Content Delivery Network) ra đời.

Có thể tìm hiểu thêm về định nghĩa qua video này

Là mạng lưới truyền tải thông tin được cache từ trước. CDN giúp tăng tốc độ tải trang, giảm bớt độ trễ do khoảng cách vật lí gây ra.

3. CDN hoạt động như thế nào?

Trong mạng lưới Content Delivery. Mỗi điểm hiện diện (location) được gọi là một PoPs.

Để tăng thời gian phản hồi giữa client và server (người dùng và trang web), các PoPs (node trong mạng lưới) sẽ lưu nội dung trang web vào bộ nhớ (cached) của mình và làm mới nó thường xuyên.

Nhờ vào mạng lưới dày đặc Content Delivery Network, người dùng sẽ chỉ kết nối với một node gần mình nhất là sẽ có thông tin. Qua đó tăng tốc độ tải trang
Nguồn ảnh / Source: hashthemes.com

Khi người dùng yêu cầu nội dung trang web, người dùng sẽ không trực tiếp truy cập tới trang web (ở bờ Tây nước Mỹ chẳng hạn) mà chỉ truy cập với một điểm CDN gần mình nhất.

4. Khi nào nên sử dụng CDN?

Tất nhiên, ai cũng muốn nội dung của mình tải nhanh, load nhanh. Nhưng chú ý rằng không phải trường hợp nào cũng cần sử dụng CDN.

Nếu content của bạn chỉ có một lượng nhỏ truy cập ở vị trí địa lí gần nơi đặt máy chủ, không cần thiết phải dùng CDN.

Ngược lại, nếu nội dung của bạn được truy cập và sử dụng ở khắp nơi trên thế giới. Đăng kí tham gia mạng lưới Content delivery network là cần thiết giúp tăng trải nghiệm người dùng. Một số dịch vụ tốt hiện nay có thể kể tới là:

cdn-la-gi-cdn-optimoleQuảng cáo về pricing của Optimole cho thấy rằng càng nhiều CDN location thì tốc độ tải nội dung càng cao
Nguồn / Source: optimole.com
cdn là gì, content delivery network là gìCDN thế hệ mới của CloudFlare tăng hai lần tốc độ tải, với mạng lưới rộng lớn ở khắp nơi trên thế giới. Cloudflare quả là lựa chọn không tồi.
Nguồn / Source: CloudFlare

5. Tham khảo

Hiểu biết về CDN tất nhiên không thể bỏ qua một khái niệm phổ biến khác là VPN. Có thể tìm hiểu về VPN qua bài viết này nha.

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Building Microservices Application – Phần 1: Sử dụng Netflix Eureka, Ribbon và Zuul

building

Bài viết được sự cho phép của tác giả Edward Thien Hoang

Đây là bài viết thứ nhất (index start từ 0 😀 ) trong series Building Microservices Application với Spring Boot. Trong bài viết mở đầu series đã giới thiệu một cách tổng quan các “viên gạch” cần có khi xây dựng ứng dụng Microservices. Trong bài viết này, hãy bắt tay vào những viên gạch đầu tiên CẦN thiết nhất bao gồm: API Gateway, Load balancer và Service Discovery.

  Building Microservices Application - Phần mở đầu: Bức tranh tổng thể
  Các thao tác cơ bản với Database SQL Server (tạo mới database, table,...)

SPRING BOOT, SPRING CLOUD VÀ NETFLIX OSS

Spring Boot là một dự án nổi bật trong hệ sinh thái Spring Framework. Nếu như trước đây, công đoạn khởi tạo một dự án Spring khá vất vả từ việc khai báo các dependency trong file pom.xml cho đến cấu hình bằng XML hoặc annotation phức tạp, thì giờ đây với Spring Boot, chúng ta có thể tạo các ứng dụng Spring một cách nhanh chóng và cấu hình cũng đơn giản hơn.

Như các bạn biết, để cấu hình, setup một project web đơn giản cũng tốn kha khá thời gian, vậy để setup, quản lý cấu hình, dependency cho một Microservices application sẽ còn phức tạp hơn nhiều. Tuy nhiên với Spring Boot, bạn sẽ thấy nó giúp ích khá nhiều cho chúng ta. Có thể coi Spring Boot như một project configuration manager của bạn, hãy cho Spring Boot biết bạn muốn tạo ứng dụng gồm những tính năng gì, ví dụ như: Web service, Web MVC, Microservices với API Gateway, Load balancer và Service Discovery, Circuit breaker,… Spring Boot sẽ tự biết làm gì để tạo ra project skeleton với đầy đủ những thứ bạn cần, và thậm chí, bạn có thể bấm Run luôn cái project mới tạo ra luôn đấy.

Spring Cloud là nền tảng khá mới mẻ trong gia đình Spring.io dùng để xây dựng microservice một cách nhanh chóng. Spring Cloud cung cấp các công cụ cho các developer để nhanh chóng xây dựng một số common patterns trong các hệ thống phân tán (e.g. configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus, one-time tokens, global locks, leadership election, distributed sessions, cluster state). Chúng sẽ hoạt động tốt trong bất kỳ môi trường phân tán nào, bao gồm máy tính xách tay của chính developer, các data center hoặc trên cloud.

Bản thân hệ sinh thái Spring không tự build hết tất cả các viên gạch cần để xây dựng ứng dụng Microservices. Thay vào đó, có một kho gạch dành cho Microservices được Netflix ban đầu phát triển trong nội bộ của họ để xây dựng dịch vụ xem phim trực tuyến nổi tiếng của họ và sau đó public ra dưới dạng open source với cái tên Netflix OSS (Open Source Software). Và Spring đơn giản chỉ làm nhiệm vụ wrap chúng lại và dùng trong hệ sinh thái của Spring (tất nhiên Spring nó còn wrap nhiều thằng khác nữa). Bằng cách kết hợp Spring Boot, Spring Cloud và Netflix OSS sẽ đủ cung cấp các công cụ và nguyên liệu cần thiết nhất để giúp bạn có thể nhanh chóng và dễ dàng xây dựng các Microservices của mình.

1. BẢNG NGUYÊN LIỆU

Nhìn vào bảng dưới đây sẽ cho thấy cách mapping giữa các viên gạch chúng ta đã nói trong phần mở đầu và các công nghệ để giải quyết

1

Trong bài viết này, hãy cùng làm việc với 3 chú: Eureka, Ribbon và Zuul

Netflix Eureka – Là một Service Discovery Server cho phép các dịch vụ microservices tự đăng ký mình vào danh sách các services hoạt động lúc khởi chạy.

Netflix Ribbon – với chức năng Dynamic Routing và Load Balancing có thể được sử dụng bởi Service client để tra cứu dịch vụ lúc runtime. Ribbon sử dụng thông tin có sẵn trong Eureka để định vị các instance thích hợp. Nếu tìm thấy nhiều hơn một instance, Ribbon sẽ áp dụng cân bằng tải để phân phối các reuqest đến các instance rảnh việc nhất. Ribbon không chạy dưới dạng một dịch vụ riêng biệt mà thay vào đó no là một thành phần được nhúng trong mỗi Service client.

Netflix Zuul – Đóng vai trò như một Edge Server hoặc gatekeeper với thế giới bên ngoài, không cho phép bất kỳ yêu cầu bên ngoài trái phép nào đi qua. Các request đi tới services đều phải qua anh chàng Zuul này để check hàng trước. Zuul sử dụng Ribbon để tra cứu các dịch vụ sẵn có và định tuyến yêu cầu bên ngoài đến instance dịch vụ thích hợp. Trong bài đăng trên blog này, tôi sẽ chỉ sử dụng Zuul như một điểm vào (entry point), các khía cạnh về bảo mật sẽ có trong các bài đăng trên blog sắp tới. Các bạn có thể tìm hiểu thêm về GateKeeper hay nói cách khác là API Gateway ở đây nhé

2. KIẾN TRÚC

2

Có 4 business services ( màu xanh lá cây ):

Ba core services chịu trách nhiệm xử lý thông tin liên quan đến sản phẩm, đề xuất và đánh giá.
Một composite service có thể tổng hợp thông tin từ ba core services và tạo ra chế độ xem thông tin sản phẩm cùng với các đánh giá và đề xuất của một sản phẩm.

Để hỗ trợ các business services, chúng ta sử dụng các infrastructure servives sau đây ( màu xanh dương ):

  • Service Discovery Server (Netflix Eureka)
  • Dynamic Routing and Load Balancer (Netflix Ribbon)
  • Edge Server (Netflix Zuul)

3. SOURCE CODE

Bạn có thể checkout source code dưới này về. Lưu ý, cần cài đặt Java SE 8 và Git.

$ git clone https://github.com/callistaenterprise/blog-microservices.git
$ cd blog-microservices
$ git checkout -b B1 M1.1

Structure của source code

2.1

Mỗi thành phần được xây dựng một cách riêng biệt (hãy nhớ rằng chúng ta không phải xây dựng các ứng dụng nguyên khối 🙂 vì vậy mỗi thành phần có build file riêng của chúng. Sử dụng Gradle làm build system, nếu bạn chưa cài đặt Gradle, build file sẽ download xuống cho bạn. Run shell script dưới đây để build.

$ ./build-all.sh

Hoặc nếu đang sử dụng Windows thì có thể run:

build-all.bat!

4. DIỄN GIẢI SOURCE CODE

Chúng ta hãy xem nhanh một số cấu trúc mã nguồn chính. Mỗi microservice được phát triển dưới dạng ứng dụng Spring Boot độc lập và sử dụng Undertow, một container Servlet 3.1 nhẹ làm máy chủ web của nó. Spring MVC được sử dụng để thực hiện các dịch vụ dựa trên REST. Spring RestTemplate được sử dụng để thực hiện các cuộc gọi đi. Nếu muốn biết thêm về các công nghệ cốt lõi này, bạn có thể xem bài đăng trên blog sau đây .

Bây giờ hãy tập trung vào cách sử dụng các chức năng trong Spring Cloud và Netflix OSS!

4.1 GRADLE DEPENDENCIES

Theo tinh thần của Spring Boot, Spring Cloud đã định nghĩa một tập hợp các dependencies mặc định. Để sử dụng Eureka và Ribbon trong microservice, cần thêm config dưới đây vào build file:

compile("org.springframework.cloud:spring-cloud-starter-eureka:1.0.0.RELEASE")

Để xem ví dụ hoàn chỉnh, hãy xem product-service/build.gradle.

Để có thể thiết lập máy chủ Eureka, hãy thêm phụ thuộc sau:

compile('org.springframework.cloud:spring-cloud-starter-eureka-server:1.0.0.RELEASE')

Để xem ví dụ hoàn chỉnh, hãy xem discovery-server/build.gradle.

Tip: các bạn có thể vào trang https://start.spring.io/ và lựa chọn thực đơn (các tính năng) cho ứng dụng microservices của mình, Spring Boot sẽ giúp bạn tìm cách dependencies cần thiết

4.2. INFRASTRUCTURE SERVERS

Thiết lập một máy chủ cơ sở hạ tầng (Infrastructure Server) dựa trên Spring Cloud và OSS Netflix thực sự dễ dàng. Ví dụ: đối với máy chủ Eureka, hãy thêm @EnableEurekaServer annotation vào ứng dụng Spring Boot chuẩn:

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}

Để xem ví dụ hoàn chỉnh, hãy xem EurekaApplication.java .

Để dựng một máy chủ Zuul, bạn có thể thêm @EnableZuulProxy. Để xem ví dụ hoàn chỉnh, hãy xem ZuulApplication.java.

Với các annotations đơn giản này, bạn đã có thể tạo ra các server đỉnh, làm được việc rồi đấy. Theo mặc định, Zuul thiết lập một route cho mọi dịch vụ mà nó có thể tìm thấy ở Eureka. Với cấu hình sau trong application.yml – chúng ta hãy giới hạn các routes để chỉ cho phép các cuộc gọi đến composite product service:

zuul:
ignoredServices: "*"
routes:
productcomposite:
path: /productcomposite/**

Để xem ví dụ hoàn chỉnh, hãy xem edge-server/application.yml.

4.3 BUSINESS SERVICE

Để tự động đăng ký microservices với Eureka, thêm một @EnableDiscoveryClient annotation vào ứng dụng Spring Boot.

@SpringBootApplication
@EnableDiscoveryClient
public class ProductServiceApplication {

public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}

Để xem ví dụ hoàn chỉnh, hãy xem ProductServiceApplication.java.

Để tìm và gọi một instance của một microservice, sử dụng Ribbon và một Spring RestTemplate như sau:

@Autowired
private LoadBalancerClient loadBalancer;
...
public ResponseEntity getReviews(int productId) {

ServiceInstance instance = loadBalancer.choose("review");
URI uri = instance.getUri();
...
response = restTemplate.getForEntity(url, String.class);

Service client chỉ cần biết tên của dịch vụ (ví dụ như review), Ribbon (tức là LoadBalancerClient ) sẽ tìm thấy một instance dịch vụ và trả về URI của nó cho Service client.

Để có một ví dụ hoàn chỉnh, hãy xem Util.java và ProductCompositeIntegration.java .

5. KHỞI CHẠY CÁC MICROSERVICES

Trong bài đăng trên blog này, chúng ta sẽ start/run các microservices như các process java độc lập trên môi trường ở máy local. Về sau, chúng ta sẽ tìm hiểu cách triển khai các microservices trên cloud và Docker containers!

Để có thể chạy một số lệnh được sử dụng bên dưới, cần phải cài đặt các cURL và jq .

Mỗi microservice được start bằng cách sử dụng lệnh ./gradlew bootRun.

Đầu tiên hãy start các infrastructure services (Eureka và Zuul)

$ cd .../blog-microservices/microservices

$ cd support/discovery-server; ./gradlew bootRun
$ cd support/edge-server; ./gradlew bootRun

Sau đó start các business services

$ cd core/product-service; ./gradlew bootRun
$ cd core/recommendation-service; ./gradlew bootRun
$ cd core/review-service; ./gradlew bootRun
$ cd composite/product-composite-service; ./gradlew bootRun

Nếu đang sử dụng Windows, bạn có thể thực thi tập tin bat tương ứng start-all.bat!

Khi các microservices được khởi động và được đăng ký với máy chủ khám phá dịch vụ, chúng sẽ ghi các thông tin sau vào log:

DiscoveryClient … – registration status: 204

Trong ứng dụng web khám phá dịch vụ, bây giờ chúng ta có thể thấy bốn business services và edge server ( http: // localhost: 8761 ):

3

5.1 TEST

Bắt đầu gọi composite service thông qua edge server ở port 8765 (xem application.yml) và như chúng ta đã thấy ở trên, chúng ta có thể sử dụng đường dẫn /productcomposite/** để tiếp cận product-composite service thông qua edge server. Kết quả trả về:

$ curl -s localhost:8765/productcomposite/product/1 | jq .

{
"name": "name",
"productId": 1,
"recommendations": [
{
"author": "Author 1",
"rate": 1,
"recommendationId": 1
},
...
],
"reviews": [
{
"author": "Author 1",
"reviewId": 1,
"subject": "Subject 1"
},
...
],
"weight": 123
}

5.2 DYNAMIC LOAD BALANCING

Để tránh lỗi hoặc sự cố mạng tạm thời, sẽ có nhiều instance dịch vụ cùng loại chạy một lúc và sử dụng bộ cân bằng tải để phân bổ các request đến các instance. Vì chúng ta đang sử dụng các port được cấp phát động và một máy chủ khám phá dịch vụ nên rất dễ dàng để thêm một instance mới. Ví dụ, chỉ cần bắt start một review service mới và nó sẽ cấp phát một port mới một cách tự động và chính nó sẽ đăng ký với máy chủ khám phá dịch vụ.

$ cd .../blog-microservices/microservices/core/review-service
$ ./gradlew bootRun

Sau một lúc, bạn có thể check lại trong Eureka server ( http: // localhost: 8761 ):

4

Nếu chạy lệnh curl trước đó ( curl -s localhost:8765/productcomposite/product/1 | jq .) một vài lần và nhìn vào log của hai service instance, bạn sẽ thấy cách bộ cân bằng tải tự động phân bổ các request tới hai instance mà không cần bất kỳ cấu hình thủ công nào:

5.png

6. TÓM TẮT

Chúng ta đã biết được sự lợi hại của bộ ba Spring Boot, Spring Cloud và Netflix OSS để đơn giản hóa việc phát triển và triển khai các microservices một cách tự động và mượt mà. Khi các service instance mới được start, chúng sẽ tự động được phát hiện bởi bộ cân bằng tải thông qua máy chủ khám phá dịch vụ và có thể bắt đầu nhận “công việc”. Sử dụng Edge server để kiểm soát các microservices nào được giao tiếp với bên ngoài.

7. TIẾP THEO LÀ GÌ

Có một số câu hỏi vẫn chưa được trả lời, ví dụ như:

  • Làm gì khi có lỗi xảy ra hoặc một hoặc thậm chí nhiều service bị down
  • Làm thế nào để ngăn chặn truy cập trái phép vào API thông qua Edger server?
  • Làm cách nào để có được bức tranh tổng hợp tốt về tình hình đang diễn ra trong toàn hệ thống microservice, ví dụ: tại sao đơn đặt hàng số 123456 chưa được giao?

Trong các bài viết sắp tới trong loạt bài về Building Microservices Application, chúng ta sẽ xem xét cách tăng khả năng phục hồi và chịu lỗi (resilience) bằng bộ ngắt mạch (circuit breaker), sử dụng OAuth 2 để hạn chế quyền truy cập bên ngoài. Chúng ta cũng sẽ xem xét cách sử dụng ELK stack để thu thập log từ tất cả các microservices theo cách tập trung và hợp nhất và more and more.

Series này là phần tiếp theo series Microservices: Từ Thiết Kế Đến Triển Khai, tập trung vào việc hiện thực hóa các khái niệm đã mô tả ở phần lý thuyết. Hi vọng sẽ giúp ích được cho các bạn khi làm quen với microservies. Các bạn có thể tham khảo thêm về phần Architecture căn bản ở đây nhé.

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Jobs for Developer hấp dẫn trên TopDev

Tăng tốc độ tối đa cho ứng dụng viết bằng Angular JS

Tăng tốc độ tối đa cho ứng dụng viết bằng Angular JS

Bài viết được sự cho phép của tác giả Tino Phạm

Gắn bó với AngularJS cũng khoảng 2 năm rồi. Thật sự nhìn lại nhưng app mình làm với nó vẫn chưa gọi là “good” về chất lượng (performance). Có thể do: code sh*t, hoặc do cách tổ chức (structure) chưa tốt, hoặc cũng có thể do dữ liệu quá lớn,… Đến lúc phải nhìn lại xem nó đang bị ảnh hưởng do yếu tố nào? Làm sao để cải thiện và làm thế nào để cải thiện.

Ở phạm vi bài viết này, mình không bàn về vấn đề code sh*t hay không và cũng không bàn về cách tổ chức code sao cho tốt. Vì đó là việc tùy vào đẳng cấp của mỗi người, tùy vào dự án, tùy vào tâm lý xã hội tình cảm,… Và việc thực hiện nó cần cả team và cần có một TechLead giỏi để giúp thực hiện tốt. Ở đây mình chỉ tập trung nói việc hiểu và sử dụng một công nghệ như thế nào cho tốt thôi. Và chủ đề của bài này là tập trung vào AngularJS.

  8 lợi thế khi sử dụng Polymer so với Angular và React

  Buils một ứng dụng thời tiết sử dụng AngularJS

Theo như ng-conf team định nghĩa thế nào là “chậm” trong ứng dụng dùng AngularJS? thì họ có nêu ra một số vấn đề như sau:

  • $apply > 25ms
  • Click handler > 100ms
  • Show a new page > 1s
  • If > 10s => User will give up
  • 200ms or less is ideal

Mình sẽ chia sẽ một số cách để có thể tăng thêm tốc độ cho ứng dụng web dùng AngularJS và Javascript mà mình đã tìm hiểu và thử nghiệm.

  1. Các file js, css nên được nén lại (minified): việc minify js (javascript) các file css (stylesheet) sẽ giúp bạn có được các file js và css nhẹ hơn, tải lên nhanh hơn và bảo mật hơn.
  2. Tắt chế độ debug của AngularJs
    Trước khi release package bạn nên tắt chế độ này để có thể tăng hiệu suất ứng dụng.Tại sao vậy? Vì, mặc định AngularJS tự động thêm các siêu dữ liệu vào trong DOM để hỗ trợ các công cụ phát triển và debug.Vậy siêu dữ liệu đó là những gì? Khi bạn debug ứng dụng bạn sẽ thấy các class như ‘ng-bind’, ‘ng-scope’, ‘ng-isolate-scope’ được gắn vào DOM.Làm sào tắt chế độ này bây giờ? Đây là cách dùng:

    
    app.config(['$compileProvider', function($compileProvider){
    $compileProvider.debugInfoEnabled(false);
    }]);
    

    Ngoài ra, khi đã tắt chế độ debug rồi bạn vẫn có thể load lại chế độ này tạm thời để debug bằng cách gọi hàm angular.reloadWithDebugInfo() bên trong console tool

  3. Sử dụng phương thức useApplyAsync() cho các đối tượng $http
    Nếu như ứng dụng của bạn có rất nhiều $http request cùng lúc để lấy dữ liệu về. Thì mỗi $http response nó sẽ gọi digest() để cập nhật lại DOM.
    Trong các ứng dụng lớn, khi khởi động ứng dụng bạn cần lấy rất nhiều dữ liệu về cùng một lúc rồi mới hiện lên giao diện. thì nên sử dụng useApplyAsync() để đồng bộ lại tất cả các response này và gọi digest() một lần thôi. Trong các ứng dụng nhỏ (có ít request cùng lúc) bạn sẽ không thấy được sự khác biệt khi dùng phương thức này.
    Vậy làm sao dùng nó trong ứng dụng đây? Xem ví dụ sau:

    
    app.config(function($httpProvider){
    $httpProvider.useApplyAsync(1000); //true
    });
    
  4. Sử dụng $templateCache
    Nếu ứng dụng của bạn có nhiều templates vậy thì server cần phải tải tất cả các templates này về trước khi hiện lên cho người dùng thấy. Sử dụng $templateCache sẽ giúp hạn chế việc tải lại các templates này. Nghĩa là template chỉ được tải 1 lần sau đó AngularJs lưu vào cache và nhưng request sau đó sẽ được gọi từ cache để load template.
    Oh, sử dụng thế nào? Có nhiều cách để chúng ta dùng template. Cách để dễ bảo trì và trực quan nhất là viết template vào 1 file html riêng rồi dùng $TemplateCache service put nó vào. Xem ví dụ sau:

    
    app.run(function($templateCache){
    $templateCache.put('templateId.html', 'This is my content');
    //Or get a template cache
    $templateCache.get('path/templateId.html');
    });
    
  5. Tránh dùng quá nhiều $watch
    Phần này khá quan trọng, nó ảnh hưởng đến performance rất nhiều. Đầu tiên chúng ta cần hiểu được $watch được tạo ra khi nào? watcher được tạo ra khi:
    – Dùng binding {{ item }}
    – Dùng biến scope: scope: { bar: ‘=’}
    – Dùng Filter {{ value | myFilter }}
    – Dùng các directive: ng-show, ng-hide, ng-repeat, ng-change, ng-model, ng-click,….
    – Dùng $http event
    – Dùng $q để resolve promise
    – Dùng $timeout, $interval
    – Dùng method $scope.$watch()Vì sao vậy? vì tất cả những thứ này sẽ gọi xuống $digest() để cập nhật lại DOM. Chính vì thể khi bạn cũng cần hạn chế việc dùng $apply() vì nó cũng sẽ gọi $digest(), hoặc khi gọi trực tiếp $digest().Bạn cần hiểu cách làm việc của AngularJs như thế này: $watch() sẽ làm thêm cái đó rồi gọi $apply(). Trong $apply có thể làm thêm việc gì đó rồi gọi $digest(). $digest sẽ kiểm tra xem đối tượng được watch có thay đổi gì không, nếu có sẽ cập nhật DOM
    Tóm lại, có nhiều watchers sẽ tạo ra nhiều digest cycle


    Ảnh từ angular.org

    Vậy làm bây giờ? ứng dụng của tôi cần  phải dùng tất cả những thứ ở trên, không lẽ không dùng.
    Ở đây chúng ta hiểu được khi nào tạo ra watcher rồi, chúng ta chỉ hạn chế tạo ra quá nhiều watcher không cần thiết. Cho nên,  tùy trường hợp, bạn cần phải xem xét để có thể áp dụng đúng.Vậy giờ làm sao để hạn chế việc tạo ra watcher?
    OK, tôi sẽ hướng dẫn cho bạn làm thế nào. Nhưng bạn cần xem xét trường hợp nào nên dùng và không nên dùng để tránh ảnh hương đến logic của ứng dụng.a) Chỉ sử dụng two-way binding (binding 2 chiều) khi nào dữ liệu của bạn cần thay đổi model. Trong AngularJs để dùng two-way binding bạn dùng ng-model. Bạn có thể sử dụng {{ item }} hoặc ng-binding nếu dữ liệu không cần thay đổi model của bạn.- Sử dụng ngModelOptions để hạn chế gọi digest() liên tục mà cần chờ một khoảng thời gian nào đó rồi mới gọi digest (trường hợp user input). Cách dùng:

    
    <span ng-model="user.username" ng-model-options="{ update: 'blur'}"></span>
    <span ng-model="search.keyword" ng-model-options="{ debounce: 500}"></span>
    <span ng-model="search.keyword" ng-model-options="{ debounce: {default: 500, blur: 0}}"></span>
    

    b) Sử dùng bind-one (binding 1 lần) nếu giá trị không cần thay đổi. Từ AngularJs 1.3 trơ đi đã hỗ trợ cho chúng ta cú pháp bind-one như sau:

    {{ :: item }}

    , chỉ cần thêm dấu :: trước tên biến. Khi dùng bind-one sẽ không tạo ra watcher.

    c) Dùng ng-if, ng-switch thay cho ng-show/ng-hide. Vì sao vậy? vì ng-if, ng-switch rẽ remove element html nếu false nên các watcher cũng sẽ bị remove theo. Còn ng-show/ng-hide element html luôn luôn tồn tại và nò dùng CSS để ẩn/ hiện trên giao diện nên watcher cho những element này vẫn tồn tại. Đây là ví dụ dùng ng-switch:

    d) Nên giảm thiểu sử dụng ng-repeat. Giảm thiểu là sao? nghĩa là nếu bạn có 1000 items cần show lên GUI bạn nên dùng paging hoặc lazy-load để show từng phần dữ liệu. Có một vấn đề là watcher được tao ra rất nhiếu khi dùng ng-repeat


    Bạn cũng có thể kết hợp bind-one với ng-repeat hạn chế việc tao ra watcher. Như sau:

    AngualrJs hỗ trợ thêm cú pháp track by khi dùng với ng-repeat như sau:

    Với việc dùng track by ng-repeat sẽ không cần $destroy và tạo lại DOM một cách không cần thiết.

  6. Sử dụng $destroy
    Nên $destroy: $timeout, $interval, $watch, $on, các events của element DOM: click, change,…

    
    var timeout = $timeout(function(){
    //do something
    }, 500);
    
    var interval = $interval(function(){
    //do something
    }, 500);
    
    var watchfunc = $scope.$watch("item", function(newVal, oldVal){
    if(newVal !== oldVal){
    //do something
    watchfunc(); //remove watch after done
    }
    });
    
    $scope.$on('$destroy', function () {
    $timeout.cancel(timeout);
    $interval.cancel(interval);
    watchfunc(); // apply the same for $scope.on
    });
    
    scope.$on('$destroy', function () {
    angular.element(window).off('click', windowClick);
    });

Hy vọng với những gì mình đã trình bày sẽ giúp các bạn có inscrease performance cho ứng dụng của mình tốt hơn khi dùng với AngularJs. Có thế bạn sẽ không thể áp dụng tất cả các cách mình đã nói. Vậy tùy trường hợp mà bạn nên xem xét dùng thế nào cho hợp lý nhé.

Bài viết gốc được đăng tải tại thangphampt.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Mức Lương Của Các Vị Trí Lập Trình Viên Trong Năm 2021 & Xu Hướng Thời Gian Tới

mức lương lập trình viên

Theo số liệu trong Báo Cáo Thị Trường IT Việt Nam 2021 – Developers Recruitment State do TopDev thực hiện, thị trường nhân lực ngành công nghệ thông tin năm 2021 sẽ tăng đến 36,5% so với năm 2020 (khoảng 117.180 lập trình viên). Nhu cầu tuyển dụng tăng lên mở ra cơ hội cho các lập trình viên tìm kiếm những công việc tốt cùng mức thu nhập hấp dẫn. Tùy theo năng lực, kỹ năng và sự tự tin của bản thân mà mức lương dành cho các vị trí lập trình viên sẽ khác nhau.

Mức lương lập trình viên dựa vào công nghệ

Hiện nay, danh sách top đầu những công nghệ được trả lương cao nhất trên thị trường chia là hai nhóm lớn, chủ yếu do ảnh hưởng từ quá trình chuyển đổi kỹ thuật số trên toàn thế giới:

  • High tech liên quan đến các xu hướng như AI/ML (Kubernetes, TensorFlows, Python)
  • Điện toán đám mây (AWS, GCP, Azure)

mức lương lập trình viên

Theo đó, mức lương lập trình viên cao nhất (với các đối tượng có khoảng 3 năm kinh nghiệm) dựa theo công nghệ hiện đang thuộc về AWS với 1.752$/tháng, TensorFlows nằm trong khoảng 1.703$/tháng

Mức lương khi làm việc với các công nghệ cơ bản về phát triển web, hệ thống và thiết bị di động hiện vẫn đang giữ ở mức khá cao, như công nghệ lập trình bằng ngôn ngữ Python khoảng 1.290$/tháng, C++ ở mức 1.196$/tháng.

Tính lương gross sang net chuẩn, trải nghiệm ngay!

Mức lương lập trình viên dựa vào trình độ

Theo thống kê Vietnam IT Market Report 2021 của TopDev, trong khoảng 5 năm làm việc đầu tiên sau khi ra trường, mức lương của lập trình viên sẽ dao động trong mức 342$/tháng (fresher) đến dưới 1.161$/tháng với vị trí Senior

Sau 5 năm làm việc, mức lương lập trình viên lúc này sẽ được chi trả dựa vào vị trí làm việc cũng như trách nhiệm đối với hoạt động kinh doanh. Mức lương tối thiểu của vị trí giám đốc hoặc các chuyên viên cấp cao thường là 2.200$/tháng. Tùy theo định hướng kinh doanh của công ty, các vị trí với trình độ chuyên môn khác nhau sẽ được trả mức lương phù hợp.

mức lương lập trình viên theo trình độ

Mức lương lập trình viên dựa vào chuyên ngành

3 ngành có mức thu nhập cao nhất thị trường IT hiện nay là Security, High Tech và Fintech. Trong đó, lĩnh vực Hightech – công nghệ cao như AI, IoT, điện toán đám mây,… được coi là xu hướng bắt buộc trong năm 2021 và thời gian tới. Nhờ đó, những lập trình viên có năng lực trong chuyên ngành này đang sở hữu lợi thế cạnh tranh mạnh hơn hẳn so với các lĩnh vực khác trong ngành IT. 

Bên cạnh đó, hầu như trong tất cả các hệ thống quản trị doanh nghiệp, đặc biệt với các ngân hàng, Fintech là yếu tố cực kỳ quan trọng và cần thiết để điều hành và quản lý công việc. Đó là lý do mức lương của lập trình viên theo chuyên ngành này đứng đầu trong top các ngành có lương cao.

Mức lương lập trình viên dựa vào vị trí

mức lương lập trình viên dựa vào vị trí

Bên cạnh những khó khăn do dịch Covid-19 gây ra, không thể phủ nhận đây cũng là chất xúc tác cho việc đổi mới và chuyển sang kỹ thuật số trong kinh doanh. Dịch vụ đám mây và DevOps chiếm vai trò quan trọng hơn rất nhiều trong việc duy trì và phát triển doanh nghiệp. Đó là lí do nhu cầu tuyển dụng các vị trí liên quan đến kỹ sư Cloud/DevOps đang tăng mạnh và mức lương cho các vị trí này cũng theo đó tăng rất cao trong khoảng 2.057$/tháng.

Các vị trí quản lý cấp cao hơn như CTO, CIO và Quản lý công nghệ đòi hỏi trách nhiệm cũng như năng lực cao hơn hẳn so với các vị trí khác, là mục tiêu nghề nghiệp của những ai theo đuổi ngành IT. Ở vai trò quản lý sẽ đòi hỏi khả năng chuyên môn tốt hơn, khả năng quản lý nhân sự trong team, quản lý hiệu suất công việc, quản trị rủi ro, quản trị an ninh mạng cũng như đảm bảo được sự ổn định tốt nhất cho team. Mức lương cho các vị trí Tech Management hiện trong khoảng 5.776$/tháng, Technical Director và Engineering Manager dao động ở mức 4.165$/tháng.

Trên đây là thống kê về mức lương của một số vị trí, ngành nghề, chuyên môn trong lĩnh vực công nghệ thông tin. Để tìm hiểu thông tin chi tiết hơn về các số liệu khác cũng như các vấn đề tuyển dụng và nhân lực của ngành IT, mời bạn tải Báo Cáo Thị Trường IT Việt Nam 2021 – Developers Recruitment State do TopDev phát hành.

Tải ngay báo cáo

Tìm việc IT lương cao, đãi ngộ tốt trên TopDev ngay!

Báo Cáo Thị Trường IT Việt Nam Năm 2021: Chuyển Mình Vào Cuộc Cạnh Tranh Tri Thức Toàn Cầu

thị trường IT
báo cáo thị trường IT năm 2021

Kể từ khi đại dịch bùng phát, ngành công nghệ thông tin cũng như mọi ngành nghề khác phải đối diện với không ít khó khăn và liên tục thay đổi để thích nghi với một hoàn cảnh mới. Trong bối cảnh các nước trên thế giới đang dần hồi phục và “đứng lên” từ chính những khó khăn, thị trường IT Việt Nam cũng đang phát triển trong bối cảnh “bình thường mới” với những câu chuyện mới về kinh doanh và công nghệ. Theo như thông tin trong Báo Cáo Thị Trường IT Việt Nam 2021 – Developers Recruitment State do TopDev thực hiện, giờ đây chính là cuộc cạnh tranh của tri thức, của sự cấp tiến trong tư duy về thị trường công nghệ. Thành công sẽ đến với những ai biết nắm bắt đúng thời cơ và tận dụng trí lực để phát triển.

DOWNLOAD

Tổng quan tình hình ngành Công nghệ thông tin

Dù chịu ảnh hưởng của nhiều làn sóng dịch Covid-19 liên tiếp, tuy nhiên kinh tế Việt Nam nói chung và ngành Công nghệ thông tin vẫn đạt được những thành tựu đáng kể. Theo công bố của Tổng cục Thống kê, Việt Nam hiện đứng thứ 2 trên thế giới về sản xuất điện thoại di động và linh kiện, đứng thứ 10 thế giới về sản xuất linh kiện điện tử. Đây cũng là hai yếu tố chính giúp lĩnh vực công nghệ thông tin và truyền thông của Việt Nam trở thành ngành xuất siêu lớn nhất trong sự tăng trưởng chung của toàn nền kinh tế.

Nhờ tình hình khả quan này mà trong Dự thảo Chiến lược quốc gia về vấn đề công ty công nghệ số Việt Nam đã nêu rõ mục tiêu, cho đến năm 2030 Việt Nam sẽ tiếp tục tập trung vào việc phát triển các công ty với 4 loại hình công nghệ số:

  1. Các công ty phát triển công nghệ cốt lõi
  2. Các công ty phát triển các sản phẩm và dịch vụ công nghệ kỹ thuật số
  3. Các công ty phát triển các giải pháp công nghệ kỹ thuật số
  4. Khởi nghiệp công nghệ số

Việt Nam đề ra mục tiêu đến năm 2030 đạt ít nhất 100.000 doanh nghiệp công nghệ số và có 1,5 triệu nhân viên trong lĩnh vực kỹ thuật số. Đây chính là cơ hội để các doanh nghiệp hoạt động trong lĩnh vực công nghệ có thể bứt phá và mở rộng hơn quy mô kinh doanh nhờ các chính sách hỗ trợ từ nhà nước. Cũng nhờ đó, dư địa việc làm trong lĩnh vực này sẽ còn dồi dào hơn.

Chính phủ Việt Nam đang tiếp tục xây dựng các chính sách để thu hút đầu tư nước ngoài vào lĩnh vực IT cũng như định hình cơ cấu chuyển đổi số quốc gia rõ ràng, hiệu quả. Việt Nam chú trọng đầu tư mạnh vào chi phí cạnh tranh, cơ sở hạ tầng với các tổ hợp công nghệ thông tin, các khu công nghệ cao để trở thành điểm đến hấp dẫn với nhà đầu tư công nghệ nước ngoài.

Nhu cầu nhân lực của thị trường IT Việt Nam 2021

nhân lực ngành IT

Theo các số liệu thống kê từ năm 2018 – 2022 được đưa ra, nhu cầu nhân lực cho ngành công nghệ thông tin tại Việt Nam vẫn đang tăng cao liên tục. Dựa trên Báo cáo về thị trường IT Việt Nam 2021 của TopDev, đến năm 2021 Việt Nam sẽ còn cần đến 450.000 nhân lực trong ngành công nghệ thông tin. Trong khi đó, số lượng lập trình viên hiện tại của Việt Nam mới chỉ đạt khoảng 430.000 người.

Thực tế là, số lượng ngành học về công nghệ thông tin ở các trường đại học đang mở rộng ngày càng nhiều cũng như số lượng cử nhân tốt nghiệp chuyên ngành này vẫn tăng cao qua mỗi năm, tại sao vẫn có sự chênh lệch này? Sự thiếu hụt này chủ yếu là do trình độ của lập trình viên và yêu cầu doanh nghiệp đặt ra vẫn chưa thực sự cân bằng với nhau. Trong số hơn 55.000 sinh viên công nghệ thông tin tốt nghiệp mỗi năm chỉ có khoảng 16.500 sinh viên (30%) đáp ứng được những kỹ năng và chuyên môn mà doanh nghiệp cần.

Cuộc cạnh tranh khó khăn hơn với nhiều yêu cầu về chuyên môn và kỹ năng

Nhu cầu tuyển dụng trong lĩnh vực IT vẫn luôn trên đà tăng trưởng nhanh và mạnh. Do sự thay đổi và ảnh hưởng của tình hình kinh tế – xã hội chung cũng như dựa trên các kỹ năng cứng và kỹ năng mềm mà lập trình viên sở hữu, mức lương cũng như trình độ sẽ được phân loại một cách rõ ràng hơn trong thời gian tới.

thị trường IT

Bên cạnh kỹ năng chuyên môn vững vàng, những kỹ năng mềm như khả năng tư duy phát triển, giao tiếp, quản lý thời gian, trình độ ngoại ngữ,… cũng là yếu tố quan trọng trong quá trình tuyển chọn và đánh giá ứng viên của nhà tuyển dụng. 

Chính sự biến động của tình hình chung do dịch bệnh gây ra cũng như sự đổi mới liên tục của công nghệ đòi hỏi ở các lập trình viên khả năng thích ứng nhanh và nhạy bén với mọi sự biến đổi. Các lập trình viên cần nâng cao kỹ năng công nghệ của bản thân với sự hiểu biết về các công nghệ mới và đột phá như Cybersecurity, DevOps, AI và Machine Learning, Cloud Computing,…

Nhìn chung, khó khăn là vấn đề chung mà mọi người phải cùng vượt qua, nhất là trong thời điểm dịch bệnh vẫn đang lan rộng hiện nay. Với tinh thần tỉnh táo và bản lĩnh trí tuệ, Việt Nam vẫn cho thấy được những tín hiệu khả quan trong sự tăng trưởng về kinh tế cũng như thu hút các nhà đầu tư chiến lược từ nước ngoài, trong đó có cả lĩnh vực công nghệ thông tin. Để tìm hiểu chi tiết hơn về thị trường IT Việt Nam trong nửa đầu năm 2021 và xu hướng trong thời gian tới, bạn có thể đón đọc Vietnam IT Market Report 2021 – Developers Recruitment State do TopDev thực hiện tại đây.