Home Blog Page 70

Chuyện biểu diễn ma trận trên máy tính

biểu diễn ma trận
Chuyện biểu diễn ma trận trên máy tính

Bài viết được sự cho phép của tác giả Huy Trần

Cách đây mấy hôm mình có share cái screenshot trên Facebook, khoe linh tinh vụ mình đang viết lại cái CHIP-8 emulator bằng Rust.

Mãi cho đến hôm nay thì vẫn viết chưa xong, chán quá nên ngồi viết mấy dòng linh tinh về quá trình này.

Phàm làm bất cứ chuyện gì, đều là cả một quá trình  viết Emulator hay code bất cứ thứ gì cũng vậy. Và trong quá trình đó thì người viết luôn phải trải qua vô số những quyết định về mặt kĩ thuật, ví dụ như nên dùng if..else hay pattern matching, viết test hay ko test , chia module hay viết 100 ngàn dòng trong 1 file,…


Một trong những quyết định đau đầu nhất của mình đó là chọn cấu trúc dữ liệu để biểu diễn ma trận hiển thị (display matrix) – tức là cái màn hình cho emulator.

Như đã đề cập ở bài Tự viết Emulator, màn hình của CHIP-8 là một ma trận 64×32. Nên cách biểu diễn thường gặp nhất đó là một mảng số nguyên (integer) hai chiều.

Tuy nhiên, việc dùng số nguyên rất là tốn kém, trong Rust, kiểu số nguyên nhỏ nhất là i8, chiếm 1 byte (8 bits), và trong JavaScript thì còn tệ hơn nữa khi một giá trị kiểu Number mặc định chiếm bà nó 8 bytes (64 bits). Nhân lên, để khai báo một mảng hai chiều cho ma trận hiển thị của CHIP-8 ta cần 64×32×8=16,384 bits trong bộ nhớ nếu dùng Rust (tương đương với 2 KB), và 131,072 bits tương đương với hơn 16 KB nếu xài JavaScript.

Con số có vẻ không lớn nếu chạy trên máy tính, nhưng nếu bạn đang implement cho các nền tảng èo ọp hơn  như là Arduino thì đây là cả một vấn đề cực kì lớn. Đơn cử, dòng Arduino phổ biến nhất là UNO R3, sử dụng vi xử lý ATmega328P và bộ nhớ SRAM (static random access memory) của nó chỉ có đúng 2 KB.

Quèo, trên thực tế thì bạn vẫn không thể chạy trực tiếp CHIP-8 emulator trên Arduino được vì tính riêng dung lượng bộ chớ chính của nó cũng đã ngốn mất 4096 bytes rồi  trong trường hợp này chúng ta cần dùng thêm một con chip khác để làm external RAM, tuy nhiên, vấn đề này nằm ngoài phạm vi bài viết, có thể mình sẽ nói tới trong một bài khác.


Dễ nhận thấy, đối với CHIP-8, màn hình hiển thị chỉ gồm 2 màu trắng đen, mỗi pixel chỉ có 2 trạng thái đó là on hoặc off, tương đương với chỉ có 2 giá trị 0 hoặc 1, vậy thì việc dùng số nguyên để biểu diễn là không cần thiết.

Kiểu dữ liệu nào chỉ có 2 trạng thái nhỉ? bool! Tuy nhiên ngay cả kiểu bool trong Rust cũng chiếm tới 1 byte (8 bits). Còn trong JavaScript thì mình chịu, không có tài liệu nào nói cụ thể, các đoạn code tính size của 1 type thì ghi nó tận 4 bytes . Mình không tin  có bằng chứng thì mới tin.

Ý định dùng bool coi như cũng không có ổn. Bỏ!

  04 Điều Cần Chú Ý Cho Người Mới Làm Automation Test
  10 nguyên tắc lập trình nền tảng mà lập trình viên nào cũng cần biết

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

1. Dùng bit array

Bản thân một bit có thể chứa được 2 giá trị (0 và 1), như vậy là đã thỏa mãn cho yêu cầu của một ma trận hiển thị.

Vậy thì có cách nào chỉ dùng đúng 64×32=2048 bits trong bộ nhớ không? Có!

Rust có hỗ trợ kiểu u64 (64-bit unsigned integer), là một kiểu số nguyên không đấu, khi khai báo một biến kiểu này tất nhiên nó sẽ chiếm 64 bits trong bộ nhớ.

Và nếu chúng ta khai báo một mảng gồm 32 số nguyên 64 bit [u64; 32] thì sao? Chúng ta sẽ có 2048 bits! Đủ để chứa toàn bộ ma trận hiển thị.

Đến đây thì vấn đề sẽ là: Làm sao để đọc/ghi vào một bit bất kì của một số u64.

Lưu ý: về thứ tự cao thấp của các bit, ở đây chúng ta theo quy ước các số đều là big endian, các bit được sắp xếp theo thứ tự từ bit cao đến bit thấp. Ví dụ trong hình sau là một số u16 gồm có 2 bytes:

Từ trái qua phải, bit đầu tiên gọi là bit cao nhất (highest bit), bit cuối cùng gọi là bit thấp nhất (lowest bit).

Vì thế, khi nói một bit thứ i, chúng ta có thể hiểu là bit thứ i tính từ bit thấp nhất (bên phải) qua .

2. Đọc một bit

Để đọc một bit thứ i của một số n, ta dịch phải số n một khoảng bằng i - 1 bits, và thực hiện phép AND kết quả thu được với 1:

(n >> (i - 1)) & 1

Ví dụ: Để đọc bit thứ 6 của số 0xA1, ta sử dụng công thức trên qua từng bước như sau:

Số 0xA1 biểu diễn dưới dạng nhị phân là 1010 0001. Để lấy được bit thứ 6, ta cần dịch phải 5 bit:

1010 0001 >> 5=0000 0101

Tiếp theo, ta thực hiện phép AND kết quả trên với số 1, thực chất có biểu diễn nhị phân là 0000 0001:

0000 0101 & 0000 0001=0000 0001=1

Kết quả thu được sẽ là 1.

3. Ghi một bit

Để ghi giá trị 1 vào bit thứ i của số n, ta dùng phép OR cho số n và kết quả của phép dịch trái số 1 một khoảng i - 1 bits:

n | (1 << (i - 1))

Ví dụ: Để ghi vào bit thứ 4 của số 0xA1, đầu tiên ta lấy số 1 dịch phải một khoảng 3 bit:

0000 0001 << 3=0000 1000

Sau đó ta thực hiện phép OR kết quả thu được với số 0xA1:

1010 0001 | 0000 1000=1010 1001=0xA9

4. Xóa một bit

Để xóa một bit thứ i (đưa bit đó về giá trị ban đầu, là 0) của một số n, ta làm như sau:

n & !(1 << (i - 1))

Ví dụ: Để chuyển giá trị 0xA9 thu được ở ví dụ trên về lại thành 0xA1, ta phải xóa bit thứ 4 cua số đó. Tương tự như ở ví dụ trước, đầu tiên ta sẽ dịch trái số 1 một khoảng 3 bit, lần này ta lấy giá trị nghịch đảo NOT của nó.

¬(0000 0001 << 3)=¬(0000 1000)=1111 0111

Sau đó thực hiện phép AND giữa kết quả thu được và giá trị nhị phân của số 0xA9:

1010 1001 & 1111 0111=1010 0001=0xA1

5. Implement

Đã thấy lợi hại chưa?

Cá nhân mình thì ko biết nữa, nhưng thấy khá là hại não  tuy nhiên hiệu quả đem lại thì rất lớn, chúng ta đã tiết kiệm được một lượng lớn bộ nhớ, từ 2KB xuống còn 2048 bits.

Bây giờ thì có thể implement thành hàm hay class để dùng lại cho tiện. Ví dụ, đây là hai hàm mình viết để sử dụng trong emulator:

// Lưu ý, code này không có chính xác :v
impl Screen {
  ...
  pub fn set_pixel(&mut self, x: usize, y: usize, on: bool) {
    if on {
      self.display[y] |= 1 << x;
    } else {
      self.display[y] &= (!(1 << x));
    }
  }

  pub fn get_pixel(&self, x: usize, y: usize) -> u64 {
    (self.display[y] >> x) & 1
  }
  ...
}

Ngoài việc dùng cho emulator (màn hình trắng đen) ra, thì cách thể hiện ma trận dùng bit array này còn có thể được dùng cho nhiều trường hợp khác như bảng đèn điện tử (tín hiệu bật/tắt), lưu các đỉnh của một đồ thị, lưu bàn cờ hoặc các thể loại map đơn giản nếu bạn làm game, hoặc có thể cải tiến để sử dụng từng byte thay vì từng bit để lưu trữ được nhiều thông tin hơn.

Hy vọng qua bài viết này, mình đã ít nhiều chia sẽ được cho các bạn chút gì đó, mặc dù cho đến thời điểm này mình vẫn chưa biết là mình đã chia sẽ được gì 

Cảm ơn các bạn đã kiên nhẫn đọc đến tận những dòng này. Nếu các bạn cảm thấy bài viết này thú vị, đừng ngại để lại comment, và nhớ subscribe vào mailing list của mình để nhận thông báo về các bài viết mới, hoặc like trang Facebook để đọc những dòng status ất ơ ngẫu nhiên của mình vào một ngày đẹp trời nào đó. Chào thân ái và quyết thắng.

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

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

Xem thêm công việc CNTT hấp dẫn trên TopDev

Công Việc & Mức Lương Chuyên Viên Phân Tích Nghiệp Vụ

lương chuyên viên phân tích nghiệp vụ
Công Việc & Mức Lương Chuyên Viên Phân Tích Nghiệp Vụ

Một trong những ngành nghề liên quan đến lĩnh vực công nghệ thông tin được nhiều người quan tâm có thể kể đến là Chuyên viên Phân tích nghiệp vụ. Công việc phù hợp với thời đại, cơ hội phát triển sự nghiệp tốt cùng với mức lương hấp dẫn chính là những yếu tố giúp công việc này thu hút được nhiều nhân tài. Vậy cụ thể công việc của chuyên viên phân tích nghiệp vụ là làm gì? Lương chuyên viên phân tích nghiệp vụ đang nằm trong khoảng nào?

lương chuyên viên phân tích nghiệp vụ
Mức lương của chuyên viên phân tích nghiệp vụ

1. Chuyên viên phân tích nghiệp vụ là làm gì?

Chuyên viên phân tích nghiệp vụ – Business Analyst được xem như một chiếc cầu nối, một kênh liên lạc giữa các doanh nghiệp và đơn vị phát triển phần mềm. Công việc của các BA sẽ không quá thiên về mảng kinh doanh hay công nghệ mà sẽ phối hợp các công việc để vận hành trơn tru quá trình làm việc giữa công ty outsource phần mềm với các doanh nghiệp cần dịch vụ.

Nhiệm vụ chính trong công việc hằng ngày của họ là thu thập các dữ liệu công việc, yêu cầu từ khách hàng, phân tích quy trình kinh doanh của công ty khách hàng để từ đó đưa ra các phương án làm việc khả thi với yêu cầu cũng như tình hình tài chính của doanh nghiệp.

Sau khi đã nắm được các vấn đề cần giải quyết trong dự án và đã có sản phẩm hoàn thành, các BA sẽ là người liên hệ với khách hàng để giới thiệu dự án. Chuyên viên phân tích nghiệp vụ cần thuyết phục khách hàng về tính khả thi và tối ưu của sản phẩm, sản phẩm mới này sẽ giúp ích gì cho công việc kinh doanh của công ty cũng như cải thiện vấn đề doanh thu như thế nào.

Xem thêm Công Việc Của Business Analyst Và Tất Tần Tật Các Thông Tin Cần Biết Về Nghề BA

Trong vai trò và công việc hàng ngày của mình, để cho ra đời được các sản phẩm đáp ứng đúng yêu cầu như trên, các chuyên viên BA còn cần làm việc và giao tiếp thường xuyên với các lập trình viên, chuyên viên quản lý phần mềm để hệ thống hóa các thông tin mà khách hàng yêu cầu cũng như cung cấp thông tin cần thiết cho lập trình viên phát triển sản phẩm. BA sẽ giúp các thành viên trong dự án gắn kết với nhau và cho ra đời những sản phẩm, những dự án tốt nhất, phù hợp nhất với khách hàng.

2. Lương chuyên viên Phân tích nghiệp vụ như thế nào?

Khi công nghệ thông tin phát triển mạnh cũng là lúc các ngành nghề liên quan đến BA không ngừng tăng lên, kéo theo nhu cầu nhân lực theo đuổi ngành cũng ngày càng lớn. Trong khoảng thời gian từ năm 2012 đến nay, có thể nói nghề BA chưa bao giờ ngừng “hot” trong thị trường việc làm lĩnh vực công nghệ thông tin.

lương BA
Mức lương của BA

Đặc biệt tại Việt Nam, nhờ chính sách mở cửa và nhiều ưu đãi cho các doanh nghiệp nước ngoài nên ngày càng có nhiều công ty nước ngoài được thành lập tại nước ta. Công ty nước ngoài luôn đòi hỏi rất cao trong các vấn đề chuyên môn cũng như các yêu cầu đặt ra trong việc hợp tác phát triển phần mềm. Hợp tác phát triển phần mềm ngày càng tăng mở ra nhiều cơ hội việc làm cho doanh nghiệp công nghệ Việt nhưng cũng đồng thời đặt ra các yêu cầu về việc đáp ứng tốt chuyên môn và kỹ năng để cho ra đời những sản phẩm mà khách hàng mong muốn.

Xem thêm Mức Lương Của Business Analyst Hiện Nay Bao Nhiêu?

Theo các thống kê được công bố trên trang Bloomberg, nghề BA là nghề có thu nhập đứng top 3 trong số 31 nghề có thu nhập cao nhất trên hợp đồng được tìm kiếm cho đến thời điểm này. Mức lương của chuyên viên phân tích nghiệp vụ hiện nay cũng được xếp hạng khá cao so với thị trường. Tùy theo mỗi dự án khác nhau cũng như tính chất công việc, mức thưởng trên mỗi dự án và chuyên môn của mỗi BA mà mức lương sẽ có sự chênh lệch nhất định.

Lương của chuyên viên phân tích nghiệp vụ mới vào nghề dưới 2 năm kinh nghiệm thường dao động trong mức từ 10 – 15 triệu đồng. Trong khi đó, mức lương của các Senior Business Analyst cao nhất có thể đạt đến khoảng 40 triệu đồng.

Kiểm tra lương thực nhận chuẩn xúc với công cụ tính tính lương gross net

3. Chuyên viên phân tích nghiệp vụ cần rèn luyện những kỹ năng nào?

Công việc của một chuyên viên phân tích nghiệp vụ sẽ phụ trách nhiều nhiệm vụ khác nhau và vì là người trung gian, đóng vai trò kết nối giữa nhóm lập trình dự án và công ty khách hàng nên kỹ năng mềm là một trong những yếu tố bắt buộc phải có của các BA. Khả năng thấu hiểu khách hàng, kỹ năng trình bày và giải quyết vấn đề cũng như tư duy logic là một trong những yêu cầu mà bất cứ BA nào cũng nên có.

Các BA cần làm tốt việc tiếp thu vấn đề mà khách hàng đưa ra, tóm tắt chúng và truyền đạt lại cho các lập trình viên trong nhóm dự án. Một sản phẩm hoàn thiện nhanh và đáp ứng đúng chất lượng dự án khi chuyên viên phân tích nghiệp vụ có thể làm tốt vai trò cầu nối của mình cũng như giải quyết các mâu thuẫn nếu có. Có những vấn đề khách hàng không thể cung cấp cho phía công ty phần mềm nhưng BA vẫn phải tìm hiểu vấn đề và đưa ra được những thông tin mà khách hàng cần.

Bên cạnh đó, khả năng giao tiếp ngoại ngữ cũng là yếu tố cần thiết với một BA giỏi. Các khách hàng làm việc cho những dự án phần mềm hiện nay có khá nhiều khách nước ngoài. Chính vì thế việc có thể giao tiếp cũng như nắm bắt văn hóa giao tiếp của nước bạn cũng là một trong những cách hay để các BA có thể dễ dàng hơn trong việc nắm bắt thông tin của đối phương.

Để có được một công việc với mức thu nhập tốt, những yêu cầu về công việc cũng như kỹ năng chuyên môn được đặt ra là rất lớn. Hiểu sớm vấn đề sẽ dễ dàng hơn với bạn trong việc trở thành một BA tương lai cũng như có được một mức lương chuyên viên phân tích nghiệp vụ đủ tốt như mong muốn của mình.

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

Xem thêm tuyển dụng việc làm IT hấp dẫn trên TopDev

Đừng giấu dốt

Đừng giấu dốt
Đừng giấu dốt

Bài viết được sự cho phép của BBT Tạp chí lập trình

Ngày mai tôi trông có vẻ ngu dốt hơn nhưng lại cảm thấy tốt hơn về điều đó. Giữ im lặng và cố đoán xem xem điều gì đang diễn ra không phải là cách làm tốt.
—Jake Scruggs in “My Apprenticeship at Object Mentor

Bối cảnh

Đối với những người trả tiền để thuê một lập trình viên như bạn, họ cần bạn cho họ biết là bạn đang làm được gì.

Vấn đề

Người quản lý và các thành viên trong nhóm cần có niềm tin là bạn làm được việc, nhưng bạn lại chưa quen thuộc với những công nghệ đang sử dụng. Điều này không chỉ xảy ra với các nhà tư vấn, nó xảy ra với tất cả mọi người. Có thể bạn đã được lựa chọn vào nhóm bởi vì bạn có hiểu biết sâu sắc về lĩnh vực kinh doanh hoặc một số khía cạnh khác trong các công việc liên quan đến kỹ thuật mà nhóm đang sử dụng.Hoặc có thể đơn giản là vì bạn là người duy nhất còn rảnh để làm việc này.

Giải pháp

Hãy thể hiện cho mọi người thấy rằng việc học tập cũng là một phần của quá trình phát triển phần mềm. Hãy chứng tỏ cho họ thấy bạn đang tiến bộ.

Theo nghiên cứu của nhà tâm lý học Carol Dweck, nhu cầu thể hiện bản thân ăn sâu vào hầu hết tất cả mọi người trong phần lớn các nền xã hội công nghiệp hóa. Xã hội này ngày càng phụ thuộc vào khả năng lập trình của bạn, vì phần mềm ngày càng gắn liền với cuộc sống hàng ngày của chúng ta. Tuy nhiên, vì bạn còn thiếu kinh nghiệm nên có nhiều thứ bạn chưa biết. Bạn đang kẹt trong một tình huống khó khăn. Những người xung quanh bạn – quản lý, khách hàng và đồng nghiệp của bạn, chưa kể chính bạn -cũng đang phải chịu áp lực rất lớn để có thể cung cấp phần mềm. Bạn có thể thấy sự kỳ vọng trong con mắt của mọi người khi họ hỏi xem bạn sẽ hoành thành tính năng X trong bao lâu. Có thể bạn sẽ nhận lấy nhiều áp lực trong việc trấn an họ và đảm bảo với họ rằng bạn biết chính xác những gì họ muốn, bạn biết lúc nào và làm cách nào để hoàn thành nó.

  10 Công cụ Go-To Tech dành riêng cho các Software Developer
  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết

Xem thêm việc làm Android lương cao trên TopDev

Các thợ gia công phần mềm xây dựng danh tiếng của họ thông qua các mối quan hệ tốt với khách hàng và đồng nghiệp. Chấp nhận những áp lực, không nói ra và chỉ nói với mọi người những gì họ muốn nghe không phải là một cách tốt để xây dựng mối quan hệ tốt. Hãy nói cho mọi người biết sự thật. Hãy cho họ biết rằng bạn đang bắt đầu hiểu những gì họ muốn và bạn đang học cách để có thể bàn giao nó cho họ. Nếu bạn trấn an họ, hãy trấn an họ bằng khả năng học hỏi của bạn chứ đừng giả vờ biết điều mình không biết. Bằng cách này, bạn sẽ xây dựng được danh tiếng dựa trên khả năng học tập của mình chứ không phải từ những gì bạn đã biết.

Cách rõ ràng nhất để thể hiện bạn chưa thật sự hiểu vấn đề là đặt câu hỏi. Điều này nói thì dễ hơn là làm, đặc biệt khi người bạn hỏi lại cho rằng bạn đã biết câu trả lời. Hãy cố gắng! Bạn hoàn toàn có thể giữ thể diện cho mình bằng cách đi đường vòng để có được những kiến thức cần thiết, nhưng hãy nhớ rằng con đường trở thành thợ lành nghề sẽ được rút ngắn nếu bạn đi theo đường thẳng. Theo thời gian cùng với sự luyện tập, bạn sẽ thấy viêc đặt câu hỏi trực tiếp cho những người có kiến thức uyên thâm nhất trong nhóm trở nên dễ dàng hơn. Song song với việc mạnh dạn bày tỏ sự thiếu hiểu biết của mình thì bạn cũng đang thể hiện với nhóm về khả năng học tập của bạn. Và đôi khi họ cũng sẽ hiểu rõ hơn về kiến thức của mình trong khi trả lời câu hỏi của bạn.

Lập trường “không biết”

Với tư cách là một nhà trị liệu gia đình, tôi đã được đào tạo để bỏ ý niệm rằng tôi có kiến thức chuyên môn về cuộc sống của người khác, qua đó tôi có thể tiếp cận với mọi người nhờ lập trường “không biết”. Đây là một việc khó có thể dễ chấp nhận cho dù bạn là một nhà trị liệu mới vào nghề hoặc một lập trình mới. Thường thì bản năng sẽ thôi thúc bạn giấu đi sự thiếu hiểu biết củacủa mình và giả vờ là có kiến thức chuyên môn về nó, nhưng điều này chỉ cản trở sự phát triển và hạn chế công việc bạn đang cố gắng đạt được mà thôi. Áp dụng bài học này đã giúp tôi rất nhiều trong các ngành nghề khác nhau. Tôi thực sự đã phát triển nhờ áp dụng sử dụng lập trường “không biết”hàng ngày; nó cho tôi thấy rằng tôi đã ở đúng nơi. Và tôi đã phát triển.

—David H. Hoover

Hãy làm quen với cách học này. Đây chính là học nghề. Có những người cảm thấy không thoải mái với việc này. Thay vì trở thành thợ gia công, những người này trở thành chuyên gia – những người đạt được kiến thức chuyên sâu trên một nền tảng hoặc trong một lĩnh vực và gắn bó với nó. Nhờ tập trung sâu, họ khả năng cao hơn người khác trong một lĩnh vực cụ thể. Các chuyên gia trong ngành là điều cần thiết và không thể tránh khỏi, nhưng đó không phải là mục tiêu của học nghề.

Các lĩnh vực chuyên môn thì phụ thuộc vào từng sản phẩm trên con đường mà chúng ta đang đi, nhưng nó không phải là đích đến của chúng ta. Trong hành trình của mình, thợ gia công sẽ làm việc với vô số công nghệ và lĩnh vực khác nhau. Nếu vì yêu cầu công việc hoặc sở thích riêng mà họ đào sâu và phát triển một hoặc một vài kỹ thuật trên thì càng tốt. Điều này là hoàn toàn bình thường, giống như việc luyện tập cho một cuộc chạy marathon thì sẽ giúp phát triển các cơ bắp chân. Cô ấy không luyện tập để có đôi chân khỏe, cô ấy luyện tập để chạy. Cũng giống như một nhà phát triển phần mềm tâm huyết đã đạt được kiến thức sâu về Python sau khi làm việc trong một dự án Python trong hai năm, các cơ bắp chân của vận động viên chạy marathon phát triển chỉ là phương tiện chứ không phải là mục tiêu cuối cùng.

Vài chuyên gia sẽ làm mọi việc có thể để duy trì gắn bó với duy nhất một lĩnh vực, thu hẹp phạm vi học tập, thực hành và các dự án. Trái lại, thợ thủ công, cần có lòng can đảm và khiêm tốn để gạt sự hiểu biết mình sang một bên và khoác lên mình chiếc đai trắng (White Belt) khi họ học một kỹ thuật hoặc miền mới.
Một trong những đặc điểm quan trọng nhất mà một thợ gia công có thể sở hữu là khả năng học hỏi, xác định một lĩnh vực mà mình còn kém và làm việc để cải thiện điều đó. Giống như những khoảng trống trong vườn, sự thiếu hiểu biết có thể được giảm đi bằng cách gieo trồng hạt giống hạt giống tri thức. Hãy tưới cho hạt giống bằng cách thử nghiệm, thực hành và đọc sách. Bạn có thể chọn cách giấu những chỗ trống, xấu hổ bởi kích thước của chúng, che đây chúng để không làm mất thể diện của bạn. Hoặc bạn có thể chọn cách phơi bày chúng, trung thực với bản thân và những người đang tin tưởng bạn, và yêu cầu được trợ giúp.

Khi kết thúc khóa học nghề, bạn sẽ có kiến thức sâu về một vài chủ đề về công nghệ. Với những chủ đề này bạn có thể tạo ra một số ít ứng dụng phần mềm mạnh mẽ trên một số nền tảng và lĩnh vực. Người thợ bậc thầy có khả năng dệt một tấm thảm từ vô số chủ đề. Không có gì đáng nghi ngờ khi họ có một vài đề tài và tổ hợp yêu thích nhưng số lượng các chủ đề sẽ lớn, cho phép họ thích ứng với một loạt các môi trường công nghệ. Đây là nơi The Long Road sẽ đưa bạn đến. Bằng cách bày tỏ và đối mặt với sự thiếu hiểu biết củamình, bạn sẽ nắm được các chủ đề còn thiếu nhanh hơn nhiều so với bạn cách giả vờ biết nó để trông có vẻ có đủ khả năng.

Hành động

Viết ra một danh sách năm thứ mà bạn thực sự không hiểu trong công việc của bạn. Đặt danh sách đó nơi người khác có thể nhìn thấy nó. Sau đó, tạo thói quen làm mới danh sách này mỗi khi công việc của bạn thay đổi.

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

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

Xem thêm công việc CNTT hấp dẫn trên TopDev

Algorithm Visualization

Algorithm Visualization
Algorithm Visualization

Bài viết được sự cho phép của tác giả Huy Trần

Algorithm Visualization là kĩ thuật hình tượng hóa quá trình hoạt động của một thuật toán, chúng ta thường thực hiện nó bằng nhiều cách khác nhau như: viết, vẽ, lập bảng giá trị,…

Tuần vừa rồi mình có làm một project nho nhỏ để giải trí, vừa để thực hành xem cách mà người ta thực hiện việc visualization nó như thế nào. Mình sử dụng phương pháp được giới thiệu bởi Chris Wellons qua bài viết Inspecting C’s qsort Through Animation.

  Algorithm in Frontend - Kỳ 3: Hashmap
  Tìm kiếm siêu nhanh sử dụng Algolia

Xem thêm tuyển dụng Designer hấp dẫn trên TopDev

Các bạn có thể tham khảo source code tại đây: https://github.com/huytd/bubble-sort-visualized

Ý tưởng cơ bản sẽ là: In trạng thái của input ra sau mỗi bước của thuật toán.

In bằng cách nào thì còn tùy thuộc vào kết quả mà bạn muốn thể hiện, ví dụ ở đây mình muốn tạo ra một ảnh GIF động, nên mỗi một bước của thuật toán, mình sẽ in ra input dưới dạng một frame của tấm ảnh GIF ấy.

Sản phẩm thu được sẽ như thế này:

Mỗi frame được in ra dưới định dạng PPM, có dạng, hàm draw_frame() dùng để thực hiện việc này.

Thuật toán sử dụng để minh họa là Bubble Sort và được implement thông qua 2 hàm swap() và bubble_sort(), trong này sẽ thấy mỗi bước chúng ta gọi hàm draw_frame().

Chỉ có một đoạn cuối hàm main() thì mình chạy một vòng for để add thêm vài frame, mục đích là để kéo dài thời gian cho dễ nhìn kết quả cuối cùng.

Cuối cùng, mình dùng lệnh convert của ImageMagick để chuyển đổi các frame định dạng PPM sang GIF.

Vì tính mình mau chán nên làm tới đây thì chán luôn rồi  đành open source để mọi người tham khảo, ai có hứng thú thì có thể nghiên cứu tiếp kĩ thuật này, đây là một hướng khá là hay ho 😀

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

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

Xem thêm công việc CNTT hấp dẫn trên TopDev

Adapter Pattern – Xoá nhoà khác biệt

adapter pattern
Adapter Pattern – Xoá nhoà khác biệt

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

Viết nhiều về Design Pattern nhưng có vẻ đang thiếu bên Structural Pattern nên nay mạnh dạn viết cho anh em về Adapter Pattern.

Theo như truyền thống ở Kieblog thì pattern luôn chú trọng vào cái mục đích, nhớ rõ hiểu sâu chứ không đi thẳng vào code. Đi thằng vào code thì muôn hình vạn trạng, bạn thì làm Golang, bạn thì PHP, bạn thì Python nếu nhớ được concept là cách học chuẩn nhất.

Bắt đầu với Adapter Pattern nha!

  18 designer hàng đầu dự đoán về xu hướng UI/ UX trong năm 2022
  5 ứng dụng Android tuyệt vời dành cho Android Developer và Designer

Xem thêm Graphic Design tuyển dụng trên TopDev

1. Adapter pattern là gì?

Lại như truyền thống. F@!k, ông truyền thống gì mà lắm vậy?. Anh em tin tôi, truyền thống đôi khi là tốt. Bắt đầu chú ý vào chứ Adapter, cái tên không tự nhiên mà có.

Search thử adapter trên mạng ta sẽ có kết quả như này.

Adapter PatternNguồn ảnh / Source: google.com

Quan sát thì thấy mỗi cái adapter có 2 đầu, 1 đầu vào là cái ổ cắm 2 chấu và đầu ra có thể cũng là 2 chấu hoặc 1 chấu (ví dụ như cái cấp nguồn hoặc là sạc đầu tiên).

Rồi, tới thẳng định nghĩa

Adapter is a structural design pattern that allows objects with incompatible interfaces to collaborate.

Adapter là pattern cấu trúc, cho phép các object khác nhau về interfaces có thể work chung với nhau được.

Đấy, như là 2 cái đầu của hình adapter, Adapter Pattenr đơn giản là để hai thằng objects có interface khác nhau có thể work được với nhau.

Adapter PatternAdapter Pattern: Nguồn ảnh/Source: Dive Into DESIGN PATTERNS

Thêm quả hình nữa thì hợp lý luôn, Adapter Pattenr giúp cái xe ô tô (4 bánh không phải loại chạy xe lửa), thông qua dăm ba cái khúc gỗ trục xoay quỷ ma gì đó thì có thể chạy trên đường ray. Hợp lí.

2. Vấn đề

Quay lại với ví dụ trong nghề ha. Anh em tưởng tượng ta đang build một stock market monitoring app. Kiểu bao gồm các chart, dữ liệu chứng khoán và các diagrams xịn xò.

Ok, sau đó app anh em mình cần bổ sung analytics library (thống kê các kiểu cho manager). Nhưng vấn đề sẽ phát sinh, thằng quỷ Statistic Library chỉ work với JSON input. Nghĩa là đầu vào của nó chỉ nhận JSON, còn cái ouput của system hiện tại lại là XML.

Adapter PatternAdapter Pattern: Nguồn ảnh/Source: Dive Into DESIGN PATTERNS

3. Giải pháp

Đấy, các ông lại không tin tôi. Pattern giờ trở nên rõ ràng dễ hiểu, còn giải pháp cho vấn đề ở trên thì.

You can create an adapter. This is a special object that converts the interface of one object so that another object can under- stand it.

Bạn có thể tạo adapter. Cái object đặc biệt này convert interface từ một object sang một object khác và nó có thể hiểu được.

Ví dụ là vậy nhưng Adapter Pattern không đơn thuần chỉ là convert data đâu nha anh em. Một số điểm dưới đây cho anh em hiểu rõ hơn Pattern này work như thế nào?

  1. The adapter gets an interface, compatible with one of the existing objects (Adapter sẽ lấy ra được interface tương thích với một trong các đối tượng đang có sẵn.
  2. Using this interface, the existing object can safely call the adapter’s methods. (Sử dụng cái interface này, object hiện tại có thể gọi được cái adapter methods)
  3. Upon receiving a call, the adapter passes the request to the second object, but in a format and order that the second object expects. (Dự vào cái kết quả nhận được, nó gửi cho object số 2, tất nhiên format thằng 2 hiểu được)
Adapter PatternAdapter Pattern: Nguồn ảnh/Source: Dive Into DESIGN PATTERNS

Về cơ bản thì giải pháp cho vấn đề ta nêu ra ở mục số 2 sẽ như hình trên.

4. Cấu trúc (Structure)

Implement Adapter Pattern sẽ theo nguyên lý composition (đóng gói lại). Adapter sẽ implement interface của một object và đóng gói lại xài cho cái object khác.

Adapter PatternAdapter Pattern: Nguồn ảnh/Source: Dive Into DESIGN PATTERNS

Giải thích 4 thành phần như sau:

  1. Client bao gồm business logic hiện tại
  2. Client Interface thì định nghĩa những protocols hoặc interface nào ta cần theo nếu muốn work với class Client
  3. Services thì bao gồm một số class, methods cần thiết
  4. Adapter là thằng quan trong nhất, work với cả Client Interface và Service. Adapter sẽ được call từ client thông qua Adapter Interface, chuyển đổi nó làm sao cho thằng Service nó hiểu được.

Còn một điểm nữa liên quan tới Adapter.

Nếu sử dụng đa kế thừa (multiple inheritance) thì thằng adapter sẽ kế thừa interface từ cả hai objects ở cùng một lúc. Tuy nhiên anh em chú ý là nó chỉ khả thi ở những ngôn ngữ cho phép đa kế thừa như C++ thôi nha.

Adapter Pattern: Nguồn ảnh/Source: Dive Into DESIGN PATTERNS

5. Ưu và nhược điểm

Về ưu điểm thì Adapter có hai ưu điểm chính:

Single Responsibility Principle. You can separate the interface or data conversion code from the primary business logic of the program.

Thứ nhất là chữ nguyên lý Single Responsibility: Ta có thể chia các interfaces hoặc code từ luồng business chính ra thành các logic nhỏ, sau đó kết nối lại với nhau bằng Adapter Pattern.

Open/Closed Principle. You can introduce new types of adapters into the program without breaking the existing client code, as long as they work with the adapters through the client interface.

Chữ O trong SOLID, với Adapter Pattern ta có thể kết nối các phần code với nhau mà không cần thêm/xoá sửa gì code cũ. Open cho Extension mà đóng cho Modification. Quá hợp lý!

Về nhược điểm thì đôi khi ta cần cân nhắc kĩ độ phức tạp hoặc tính khả thi khi áp dụng Adapter Pattern. Và nếu project đi theo một thể thống nhất thì vẫn hợp lý hơn.

6. Tham khảo

Wish you and your family all the best – Thank you so much for your time – Happy coding!

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

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

Xem thêm công việc CNTT hấp dẫn trên TopDev

Đôi điều về Elm

elm là gì
Đôi điều về Elm

Bài viết được sự cho phép của tác giả Huy Trần

Dịp cuối tuần vừa rồi thì mình cũng bắt đầu học Elm và làm thử 1 project nho nhỏ, mục đích là clone lại Trello chơi.

Trong quá trình làm thì cũng nhận thấy có nhiều thứ cần phải note lại.

Elm là một ngôn ngữ lập trình hàm (functional programming language) khá thú vị, chịu ảnh hưởng khá nhiều từ Haskell, và được biên dịch trực tiếp ra JavaScript.

Ngoài việc giống Haskell ra thì điểm nổi bật nhất của Elm chính là kiến trúc của nó (Elm Architecture) , giúp cho việc phát triển web apps với các ngôn ngữ functional programming trở nên dễ dàng hơn. Redux của hội React cũng chịu ảnh hưởng lớn từ kiến trúc này.

  Helm, Ripgrep và Emacs dùng... helm-ag
  Selenium IDE – Record and Playback

Xem thêm tuyển dụng DevOps hấp dẫn trên TopDev

1. Records

Records trong Elm là một khái niệm tương đồng với Objects trong JavaScript, tuy nhiên có vài điểm khác:

  • Không thể truy xuất một field không tồn tại: Compiler sẽ báo lỗi chứ ko trả về undefined như JS.
  • Không có field nào được mang giá trị undefined hay null cả.
  • Không được khai báo object lồng nhau với từ khóa this hoặc self

Để khai báo một record thì khá đơn giản, giống với JS:

hero : { name : String, level : Int }
hero = {
  name  = "Shadow Fiend",
  level = 1
}

Điểm khác biệt là khi chúng ta update một record, thì Elm sẽ trả về một record mới, vì một record là immutable:

hero = { hero | level = 25 }

Để tìm hiểu thêm, bạn có thể đọc tài liệu về Records của Elm.

2. Data Driven

Với Elm Architecture, chúng ta không cần phải (và không thể) tương tác trực tiếp với một DOM element nào cả, thay vào đó, chúng ta tương tác với dữ liệu (data) biểu diễn element đó. Mọi thao tác mà người dùng thực hiện trên web app của bạn, đều là việc tương tác (cập nhật) với các dữ liệu này.

Nếu bạn đã biết khái niệm data binding trong các framework khác như React hay Angular, thì đây chính là nó đó.

Ví dụ trong project của mình, các task hiển thị trên màn hình được biểu diễn bằng một List trong Model, như sau:

src/Models.elm

type alias Task = {
  name: String,
  status: String
}

type alias Model = {
  tasks: List Task,
  ...
}

Để hiển thị các task ra màn hình, việc chúng ta cần làm chỉ là hiển thị từng item có trong List đó, thông qua sự hỗ trợ của Html helper:

src/Views.elm

taskItemView : Int -> Task -> Html Msg
taskItemView index task =
  li [ class "task-item" ] [ text task.name ]

Khi user muốn thêm một task mới, việc chúng ta làm là tương tác với Model để add thêm một task:

src/Models.elm

addNewTask : Model -> ( Model, Cmd Msg )
addNewTask model =
  let
     newModel = { model | tasks = model.tasks ++ [ newTask ] }
  in
    ( newModel, Cmd.none )

Elm sẽ tự thực hiện phần việc bên dưới, bao gồm: kiểm tra sự thay đổi của Model, update lại DOM (như là thêm, xóa, update các element,…) tương ứng.

3. “Tương tác” với DOM element

Như đã nói ở phần vừa rồi, chúng ta không thể tương tác với bất kì một DOM element nào, vậy khi cần… tương tác thì phải làm sao?

Ví dụ chúng ta có một textbox và muốn lấy nội dung của nó (thuộc tính value).

Việc đầu tiên chúng ta cần làm chính là định nghĩa phần dữ liệu để biểu diễn nó, mà ở đây chúng ta tạo một trường mới trong Model:

src/Models.elm

type alias Model = {
  ...
  taskInput: String,
  ...
}

Tiếp theo, chúng ta sẽ thực hiện “binding” phần data này với textbox:

src/Models.elm

type Msg = ... | TextInput String

src/Main.elm

view : Model -> Html Msg
view model =
  ...
  input [ type_ "text", 
          placeholder "What's on your mind right now?",
          onInput TextInput,
          value model.taskInput
        ] []
  ...

Khi người dùng gõ vào textbox, sự kiện onInput được trigger, chúng ta sẽ phát đi một Message tạm gọi là TextInput kèm theo một tham số kiểu String để update giá trị của Model.textInput.

src/Main.elm

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
  case msg of
    ...
    TextInput content -> 
      ( { model | taskInput = content }, Cmd.none )

Như vậy, tại bất kì thời điểm nào, chúng ta cũng có thể lấy được nội dung của textbox thông qua giá trị Model.textInput, hoặc thay đổi nó thành một giá trị khác.

4. Side effects

Một đặc điểm của functional programming đó là việc hạn chế side effect, mỗi một hàm được viết ra đều chỉ thực hiện một việc duy nhất (pure function). Nghe qua thấy khà là mâu thuẫn đối với việc làm web, vì side effects là một phần tất yếu của các web apps (HTTP calls, Web socket,…).

Elm có một loại effect gọi là managed effects. Và cũng tương tự như khi làm việc với DOM, đối với managed effects, chúng ta khai báo data để biểu diễn thao tác mà chúng ta muốn thực hiện, Elm sẽ lo phần còn lại.

Có 2 kiểu managed effects chúng ta có thể dùng trong Commands và Subscriptions.

  • Commands là các thao tác mà chúng ta muốn thực hiện (ví dụ: HTTP call, “bắn” một message khác,…)
  • Subscriptions là thao tác listen một message hay một event nào đó, ví dụ nhận tín hiệu từ web socket,…

Trong project mà mình giới thiệu, khi muốn gọi một hàm setStorage để lưu dữ liệu vào localStorage sau khi add một task mới, ta có thể gọi nó dưới dạng một command, ở đây là setStorage:

src/Models.elm

addNewTask : Model -> ( Model, Cmd Msg )
addNewTask model =
  ( newModel, setStorage newModel )

5. Kết nối với JavaScript thông qua Ports

Để tương tác được với JavaScript (ví dụ sử dụng thư viện, sử dụng các hàm JS đã được viết trước đó,…), chúng ta có thể kết nối thông qua Ports.

Việc khai báo một port từ phía Elm khá đơn giản, ví dụ đây là đoạn code khai báo hàm setStorage, hàm này trả về một Command, và sẽ được gọi từ phía JavaScript.

src/Models.elm

port setStorage : Model -> Cmd msg

Từ khóa port đóng vai trò tương tự như extern trong C.

Ở phía JavaScript, ta viết:

main.js

app.ports.setStorage.subscribe(function(model) {
  // Do something
});

Như vậy, khi command setStorage được gọi từ phía Elm, phía JavaScript sẽ nhận được message này kèm với dữ liệu đi kèm (là Model) và thực hiện việc xử lý trong hàm callback của lệnh subscribe.

6. Pattern Matching

Pattern Matching là một phương pháp khá là hữu ích, xuất hiện trong nhiều ngôn ngữ lập trình, trong đó có cả Rust và Elm.

Việc sử dụng pattern matching trong Elm phụ thuộc nhiều vào cú pháp case .. of, ví dụ sau đây là một hàm kiểm tra một List có rỗng hay không:

isEmpty : List a -> Bool
isEmpty xs =
    case xs of
        [] ->
            True

        _ ->
            False

Nếu a là một List rỗng [] thì trả về True, ngược lại nếu nó match với một giá trị bất kì thì trả về False.

Hoặc ta có thể sử dụng pattern matching để viết hàm tính số Fibonacci:

fibo : Int -> Int
fibo n =
  case n of
    0 -> 1
    1 -> 1
    _ -> fibo (n-1) + fibo (n-2)

Đối với dân Haskell thì sẽ thấy cách viết này hơi khó chịu một tí, vì đã quen với cách viết của bên đó là:

fibo : Int -> Int
fibo 0 = 1
fibo 1 = 1
fibo n = fibo (n-1) + fibo (n-2)

Tuy như vầy có “đẹp” hơn, nhưng anh bạn tác giả của Elm lại không thích, nên anh ấy quyết định không đưa chức năng này vào .

Ngoài ra thì pattern matching còn làm được rất nhiều việc khác, rất là hữu dụng trong quá trình viết code Elm, các bạn có thể tham khảo ở gist Elm Destructuring cheatsheet.


Nhìn chung, Elm là một ngôn ngữ đáng để học, nhất là nếu bạn đã có sẵn background về lập trình (thường là imperative programming) và đang muốn dòm ngó sang functional programming thì Elm thực sự là điểm khởi đầu khá tốt.

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

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

Xem thêm công việc CNTT hấp dẫn trên TopDev

Algorithm in Frontend – Kỳ 3: Hashmap

hashmap
Algorithm in Frontend - Kỳ 3: Hashmap

Bài viết được sự cho phép của tác giả Huy Trần

Hôm nay nói về một ứng dụng của Hashmap trong việc optimize một số thuật toán thường gặp trên Frontend.

Giả sử có một mảng languages lưu danh sách các ngôn ngữ lập trình:

const languages = ["c++", "java", "javascript", "ruby", "rust", "golang"];

Và một hàm getLanguages nhận vào một mảng input, trả ra mảng gồm các phần tử vừa có trong input vừa có trong languages (nói theo kiểu tập hợp thì là phép giao hai tập input∩languages):

const normalize = text => text.trim().toLowerCase();

const getLanguages = (input) => {
  return languages.filter(searchLang => {
    return !(input.findIndex(inputLang =>
      normalize(inputLang) === normalize(searchLang)) === -1);
    });
};

Về mục đích của hàm trên, thì hãy tưởng tượng bạn đang làm một trang web về tuyển dụng, cho phép user (là ứng viên) nhập vào các ngôn ngữ mình sử dụng, có người sẽ nhập Ruby, có người nhập ruByruby,… hàm trên sẽ filter các input sai lệch đó và trả về input đúng với database nhất.

  Tìm kiếm siêu nhanh sử dụng Algolia
  Fix Lỗi "RDP Authentication Error Has Occurred – The Function Requested Is Not Supported"

Xem thêm tuyển dụng C# lương cao trên TopDev

Ví dụ:

getLanguages(["c++  ", "JavaScript", "GoLang"]);
// Output:
// [ "c++", "javascript", "golang" ]

Hàm getLanguages sẽ có độ phức tạp trong trường hợp xấu nhất là O(n∗k), hoặc nếu tập input có kích thước bằng tập languages luôn thì độ phức tạp sẽ là O(n2).

Sở dĩ tốn kém như vậy là vì chúng ta dùng array, và với array, để tìm ra tập giao nhau, hay nói cách khác, để tìm một phần tử languages[i] bất kì có cùng giá trị tương ứng với một phần tử input[j], ta không có cách nào khác là phải duyệt qua toàn bộ cả 2 mảng.

Vậy đây có thể là mấu chốt để chúng ta optimize thuật toán trên. Liệu có cách nào để từ giá trị của một phần tử input[j], ta có thể truy xuất ngay đến phần tử tương ứng nếu có của languages không? (truy xuất với độ phức tạp O(1)).

Một kiểu dữ liệu phù hợp với tính chất truy xuất trên đó là Hashmap, vậy nếu dùng hashmap để thực hiện bước lookup, ta có thể loại bỏ được một vòng lặp lồng bên trong.

Nhiều công ty tuyển dụng Frontend Developer đãi ngộ tốt, ứng tuyển ngay!

Nhưng dữ liệu cho sẵn (ở đây là mảng languages) là một mảng, ta cần phải chuyển nó thành hashmap trước:

const languagesLookup = Object.create(null);
languages.forEach(lang => { languagesLookup[normalize(lang)] = 1; });

Như vậy ta có thể dễ dàng implement lại thuật toán của getLanguages thành:

const getLanguages = (input) => {
  return input.reduce((array, lang) => {
    let key = normalize(lang);
    if (languagesLookup[key]) {
      array.push(key);
    }
    return array;
  }, []);
};

Bằng cách lợi dụng tính chất truy xuất nhanh và ít tốn kém của Hashmap, ta đã có thể loại bỏ việc phải chạy 2 vòng lặp lồng nhau, và optimize thuật toán ban đầu từ O(n∗k) về O(n+k), hay trong trường hợp k=n thì ta có thể nói là độ phức tạp giảm từ O(n2) về O(n).

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

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

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

Atomic design – Ưu nhược điểm từ kinh nghiệm thực tế

atomic design
Atomic design – Ưu nhược điểm từ kinh nghiệm thực tế

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

Bài viết này mình chia sẻ kinh nghiệm thực tế của mình khi apply Atomic Design vào project. Project nếu theo đánh giá của cá nhân mình thì cũng khá lớn (tầm 150 atom components).

Atomic designAtomic Design không còn quá xa lạ với anh em.

Những loại phổ biến như Dropdown, Button, Pagination thì không nói làm gì. Do dự án đặc biết nên cần thêm các component khác (theo requirement của khách hàng)

Kinh nghiệm này là kinh nghiệm xương móng (lộn, xương máu) muốn share cho anh em. Những anh em nào đã/ đang và sẽ sử dụng Atomic vào project có thể đọc qua, cân đo đong đếm sao cho hợp lý, tránh lặp lại một số sai lầm như mình đã bị.

Atomic designSai, sai vừa vừa thôi nha mấy sếp. LOL

1. Ưu điểm của Atomic Design

1.1 Write one time, use many time

Đây là ưu điểm rõ ràng nhất của Atomic. Viết component chỉ một lần thôi, viết cho chỉn chu thì cứ thế mà sử dụng.

Viết mà như … thì thôi xong, nhưng thôi cái đó là nhược điểm. Tui không lạc đề. Một khi đã viết atomic chuẩn, hoặc là build UI Library thì anh em cứ mặc nhiên mà sử dụng, dùng rất dễ và nhanh. Build ban đầu thì lâu nhưng đã có rồi thì atomic chấp các loại implement component khác.

Atomic designĐã có atom build hoàn chỉnh ngon lành thì implement page nhanh như chó chạy ngoài đồng.

1.2 Tuỳ biến

Rõ ràng là nguyên cái UI Libary các ông viết từng component một. Nên khả năng tuỳ biến sẽ rất cao, cần gì sửa đó. Một số công ty hay tập đoàn lớn họ build thành UI Library, vừa dễ thay đổi, vừa đáp ứng các requirement đặc biệt của công ty.

  18 designer hàng đầu dự đoán về xu hướng UI/ UX trong năm 2022
  30 tiện ích Chrome cho designer và dev

Xem thêm tuyển dụng Indesign hấp dẫn trên TopDev

Một bài viết khá hay về Atomic Design và UI Components anh em có thể tham khảo.

Một số ưu điểm khác tui list ra đây cho anh em.

  • You can mix and match components (Có thể mix các component với nhau)
  • Creating a style guide is simple (Style guidle khá đơn giản)
  • Easy to understand layout (Dễ để hiểu layout)
  • Quicker prototyping (Prototype đơn giản hơn)
Atomic designNguồn ảnh/ Source: creativebloq.com

2. Nhược điểm của Atomic Design

Ưu điểm lênh láng mênh mông nhưng Atomic Design cũng không thiếu nhược điểm. Dưới đây là một số kinh nghiệm xương máu của tôi khi sử dụng atomic design vào dự án thực tế.

Viết ra để giúp anh em đỡ phải mắc sai lầm khi apply.

2.1 Time is big problem

Atomic Design là đi build từng thứ nhỏ nhặt. Cần button, ta phải đi viết component button, cần pagination ta phải đi viết component pagination.

Tất nhiên trường hợp đi build các atoms là do dự án không sử dụng bất cứ library nào khác.

Cái gì cũng lợi kèm hại, nếu tự viết thì tuỳ biến và customize rất chi là dễ, nếu sử dụng thì nhanh nhưng hơi khó customize nếu dự án có những yêu cầu về requirement khác biệt.

Atomic designNhững dự án đặc biệt sẽ phát sinh những component đặc biệt. Nguồn ảnh/ Source: syncfusion.com

Trường hợp build component với Atomic Design ngay từ ban đầu. Thời gian sẽ là một vấn đề cần phải xem xét. Rõ ràng là viết từng component.

Với các component phức tạp, thời gian build component Atom thậm chí còn lâu hơn. Phía trên mình có dẫn nguồn từ Syncfusion, trang này chuyên bán các component phức tạp đã được viết sẵn.

Bán được chứng tỏ viết component đặc biệt không hề đơn giản, thời gian và chi phí bỏ ra để viết là không hề nhỏ. Một số dự án gấp hoặc chi phí nằm ngoài khả năng thì người sử dụng sẽ chọn mua component cho nhanh.

2.2 Đòi hỏi kĩ năng

Trong thực tế apply Atomic Design vào project, bản thân mình thấy Atomic khó đối với những component Atom. Khi viết atom, nếu người viết không đủ kinh nghiệm, props sẽ bị thiếu, cách tổ chứng props cũng sẽ bị lằng nhằng phiền hà

Người viết atomic tốt tất nhiên sẽ lường gần hết (nhấn mạnh là gần hết , chứ méo thể nào mà hết được) các trường hợp sử dụng của component đó.

Ví dụ cụ thể ta có thể xem component Pagination (Paging) phía dưới.

export default {
name: 'pagination',
props: {
maxVisibleButtons: {
type: Number,
required: false,
default: 3
},
totalPages: {
type: Number,
required: true
},
perPage: {
type: Number,
required: true
},
currentPage: {
type: Number,
required: true
}
},

Props cho paging component nhất thiết sẽ truyền:

  • Tổng số page (totalPages)
  • Page hiện tại (currentPage)
  • Số lượng page tối đa hiển thị (maxVisibleButtons)

Còn nhiều nhiều các props khác, tuy nhiên nếu kinh nghiệm sử dụng thực tế thiếu, người viết Atomic component sẽ phải sửa đổi rất nhiều lần về sau (khi component purpose thay đổi).

Nếu không có kinh nghiệm hoặc không tham khảo các trường hợp sử dụng thực tế của paging component, rất nhiều ta sẽ thiếu props. Component viết ra cũng không quá hữu dùng vì phải viết thêm quá nhiều.

Props là điều quan trọng của atom components, ngoài ta còn cả cách sử dụng và tổ chức props sao cho hiệu quả, sao cho khoa học.

Chính vì vậy, trước khi apply atomic design cho project. Hãy cẩn thận xem xét kĩ năng của các member, những component quan trọng như atom nên được giao cho những thành viên có nhiều kinh nghiệm.

Đó là kinh nghiệm xương máu của mình.

2.3 Chi phí cao và khó sửa đổi

Mới đầu nói khó sửa đổi chắc một số anh em đã sử dụng atomic bảo điên. Ông viết từng component như thế, có depend trên cái UI nào đâu. Có gì đâu mà khó sửa?

Sự thật khi đã vào project rồi mới thấy khó. Chứ tui thì không ngáo tới mức viết tầm bậy tầm bạ.

Chuyện là bọn tui viết cái component Button bị thiếu cái options link. Tức là props link khi click button thì open link mới. Cái này cơ bản, nhưng tui review thiếu, lỗi tui. LOL

Sửa thì dễ, không có gì khó. Nhưng cái khó là atomic, mà atomic thì các ông biết rồi đấy. Viết một lần, sử dụng khắp nơi.

Lên production rồi thì phải test lại tất cả. Chả ông nào dám chắc là cái props thêm vào có ảnh hưởng gì hay không. Bắt QC,QA team test lại thì quá tốt thời gian. Nhưng cuối cùng cũng phải làm.

Thêm một cái nữa là đôi khi các ông dev không phân biệt được đâu là atom, đâu là molecules. Sửa tên 1 component thôi nhưng phải đi sửa source cả mấy chục chỗ, nhức cả đầu. Sợ là còn sửa sót.

Atomic designNguồn ảnh/ Source: justinmind.com

3. Bonus thêm quả comment

Đây là cách làm khá hay khi anh em sử dụng atoms. Component ở cấp độ nào cứ comment vào cho nó dễ nhìn.

Một số anh em bảo phía dưới sẽ có import, cần thì kéo xuống xem. Nhưng một số project nuxt nó có auto import, một hai tháng sau quay lại nhìn component đảm bảo rối cmn não.

4. Tham khảo

Cảm ơn anh em đã đọc bài – Thanks for your focus – Happy coding!

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

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

Xem thêm công việc CNTT hấp dẫn trên TopDev

Quick and Dirty Stack, Queue and Deque in JavaScript

quick and dirty stack
Quick and Dirty Stack, Queue and Deque in JavaScript

Bài viết được sự cho phép của tác giả Huy Trần

Trong quá trình phỏng vấn, dùng JavaScript, nếu đề bài không yêu cầu bắt buộc phải implement Stack hoặc Queue thì chúng ta có thể tiết kiệm thời gian bằng cách sử dụng Array.

Sở dĩ tiêu đề nói Quick and Dirty là vì cách làm này có thể không bảo đảm đúng hoàn toàn về time complexity, nhưng bù lại nó đúng về mặt concept và behavior của các kiểu dữ liệu, giúp tiết kiệm thời gian khi làm bài phỏng vấn (nhưng đồng thời bạn cũng phải nói rõ vấn đề này với người phỏng vấn, nếu không thì ăn hành ngay).

Việc khai báo Array trong JavaScript khá đơn giản:

// Khai báo mảng rỗng
let array = [];
// Hoặc khai báo mảng n phần tử, fill nó bằng các giá trị 0
let array = Array.from(Array(n)).map(x => 0);

Trong JavaScript thì Array cũng được hỗ trợ một số thao tác, mà ta sẽ dùng nó để mô phỏng lại các kiểu dữ liệu đã đề cập, đó là:

  • push: thêm một phần tử vào cuối array
  • pop: lấy ra phần tử cuối cùng của array
  • unshift: thêm một phần tử vào đầu array
  • shift: lấy ra phần tử đầu tiên của array

Từ đây, ta có thể mô phỏng lại behavior của các kiểu dữ liệu thường gặp.

  Cách thức hoạt động của Javascript: Tổng quan về engine, runtime & call stack
  Ai nói làm lập trình cho Startup không thú vị?

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

1. Mô phỏng Stack

Hai thao tác chính trên stack đó là push và pop, hai hàm này có sẵn trong Array của JavaScript:

let stack = [];
stack.push(5);
stack.pop();

Một thao tác cũng thường gặp trong các implementation của stack đó là peek, giúp xem trước giá trị nằm trên cùng của stack mà không cần lấy nó ra, ta có thể thực hiện việc này bằng cách truy cập trực tiếp dùng index:

let last = stack[stack.length - 1];

2. Mô phỏng Queue

Hai thao tác thường gặp của queue là enqueue (thêm một phần tử vào queue), và dequeue (lấy một phần tử ra khỏi queue), ta có thể thực hiện việc này bằng hai cách:

let queue = [];
// Enqueue
queue.unshift(5);
// Dequeue
queue.pop();

Hoặc:

let queue = [];
// Enqueue
queue.push(5);
// Dequeue
queue.shift();

Và bạn có thể thấy hai cách trên cũng thể hiện hai hướng hoạt động của một queue (từ trái qua phải, và từ phải qua trái), và nếu gộp chung cả hai cách thì nó cũng chính là một deque (double-ended queue).

Thao tác peek cũng tương tự như với stack, đặc biệt nếu là deque, thì ta sẽ có peek_first (để xem phần tử đầu), và peek_last (để xem phần tử cuối):

let first = queue[0];
let last = queue[queue.length - 1];

3. Độ phức tạp

Như đã nói ở đầu bài, mình không chắc về độ phức tạp của các thao tác trên nếu dùng Array, nhưng chắc chắn nó sẽ không đúng với độ phức tạp của các thao tác của stack và queue.

Ví dụ như hàm shift, trên queue nó chỉ là O(1), tuy nhiên với JavaScript thì có lẽ nó sẽ chậm hơn rất nhiều.

Để hiểu rõ thêm cách mà JavaScript implement các hàm trên, bạn có thể xem qua đặc tả ECMAScript:

4. Ứng dụng

Bây giờ mình sẽ thử một bài đơn giản, là implement thuật toán BFS (breadth-first search) và DFS (depth-first search) để duyệt một cây nhị phân, bằng cách sử dụng Array để mô phỏng stack và queue cho từng trường hợp.

Một node của cây có cấu trúc như này:

function Node(val) {
    this.val = val;
    this.left = this.right = null;
}

Chúng ta sử dụng queue để implement thuật toán BFS, sau khi duyệt trả về một mảng các giá trị đã duyệt:

const BFS = (root) => {
  let queue = [root];
  let result = [];
  while (queue.length) {
    let node = queue.shift();
    if (node.left) queue.push(node.left);
    if (node.right) queue.push(node.right);
    result.push(node.val);
  }
  return result;
};

Để implement DFS thì ta dùng stack:

const DFS = (root) => {
  let stack = [root];
  let arr = [];
  while (stack.length) {
    let node = stack.pop();
    if (node.left) stack.push(node.left);
    if (node.right) stack.push(node.right);
    arr.push(node.val);
  }
  return arr;
};

Giả sử với cây input như sau:

        1
       / \
      2   3
     /   / \
    4   5   6
       /
      7

Kết quả của hai phép duyệt sẽ là:

BFS(input) = [ 1, 2, 3, 4, 5, 6, 7 ]
DFS(input) = [ 1, 3, 6, 5, 7, 2, 4 ]

Happy Coding ^^

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

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

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

Các Công Ty Tuyển Dụng Thực Tập Sinh CNTT

Các Công Ty Tuyển Dụng Thực Tập Sinh CNTT
Các Công Ty Tuyển Dụng Thực Tập Sinh CNTT

Thực tập luôn là một cơ hội tuyệt vời để các sinh viên có thể làm quen và học hỏi cách làm việc trong một môi trường chuyên nghiệp và thực tế hơn. Các sinh viên công nghệ thông tin có thể tham khảo thêm thông tin các công ty tuyển dụng thực tập sinh CNTT dưới đây để mở rộng cơ hội làm việc với tư cách là một thực tập sinh cho các ứng viên.

1. Công ty TNHH Keizu Việt Nam

Được thành lập từ năm 2013 và cho đến nay, công ty vẫn luôn nằm trong top các công ty hàng đầu trong lĩnh vực Tư vấn CRM Salesforce – phần mềm quản lý quan hệ khách hàng hàng đầu thế giới, nghiên cứu công nghệ, tư vấn CRM và chuyển đổi CNTT tại Việt Nam và Châu Á Thái Bình Dương.

Việc làm Công ty TNHH Keizu Việt Nam: tại đây

2. Công ty Cổ phần Viễn thông ASIM

ASIM TELECOM là nhà phát triển mạng di động Local. Là nhà mạng di động thứ 8 của Việt Nam với sự kết hợp giữa các dịch vụ viễn thông dựa trên hạ tầng của MobiFone và hệ sinh thái dịch vụ số trên Siêu ứng dụng myLocal.vn.

3. Bkav Corporation

Bkav là Tập đoàn công nghệ hoạt động trong các lĩnh vực an ninh mạng, phần mềm, chính phủ điện tử, nhà sản xuất smartphone, thiết bị điện tử thông minh, Smart City và AI camera. Bkav tự hào là 1 trong 10 thương hiệu Nổi tiếng nhất Việt Nam hiện nay.

Xem thêm thông tin về công ty: tại đây

4. SPLUS-SOFTWARE

SPLUS-SOFTWARE cung cấp cho khách hàng các sản phẩm sáng tạo, hấp dẫn, đồng thời đảm bảo nhanh chóng đưa sản phẩm ra thị trường. Được đánh giá là một trong những công ty đang phát triển mạnh trong lĩnh vực outsource ngành CNTT.

5. Creative Force

Creative Force là công ty cung cấp các phần mềm quản lý Photo Studio hàng đầu trong ngành quảng cáo hiện nay. Đến nay Creative Force đã hợp tác với nhiều thương hiệu lớn trên thế giới như Aldo, OTTO, Debenhams, SCOTCH & SODA,… Công ty có trụ sở tại Đan Mạch và hiện đang đặt văn phòng tại nhiều quốc gia như New York, San Francisco, Đức và Việt Nam.

Liên tục cập nhật

Các vị trí công việc và thông tin các công ty tuyển dụng thực tập sinh CNTT sẽ liên tục được cập nhật. Đón đọc các bài viết và thông tin CNTT khác tại TopDev để được tiếp cận những thông tin hay nhất một cách sớm nhất nhé!

Đừng quên tham khảo ngay các việc làm fresher react native, fresher data scientist, fresher ba mới nhất từ các công ty HOT cho các sinh viên, fresher chưa có nhiều kinh nghiệm nhé!

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

Xem thêm tuyển dụng việc làm IT hấp dẫn trên TopDev

Tuốt tuồn tuột về 4 loại Apollo Client Fetching

apollo client fetching
Tuốt tuồn tuột về 4 loại Apollo Client Fetching

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

Làm việc với Apollo Client Fetching chắc chắn anh em sẽ gặp 4 từ khoá chính là Queries, Mutation, Subscriptions và Fragment.

Bài viết này mình tham khảo từ trang document của Apollo Client GraphQL, giải thích lại một cách dễ hiểu hơn về các kiểu Fetching. Do tham khảo từ document nên một số nội dung khác ngoài định nghĩa và ví dụ tôi sẽ không đem vào.

Cảm ơn anh em và bắt đầu với Queries thôi.

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

1. Apollo Client Queries

Queries thì chắc chắn là quá familiar với anh em rồi. Query là để collect data, Apollo Client Queries cũng sinh ra với mục đích tương tự như vậy (Fetch data với useQuery hook).

Tuy nhiên Query này thì khác với Query bên SQL, nên nếu anh em nào beginner với GraphQL chắc ghé đọc qua tí rồi hãy quay lại.

Ví dụ về Queries:

import { gql, useQuery } from '@apollo/client';

const GET_DOGS = gql`
query GetDogs {
dogs {
id
breed
}
}
`;

Phía trên là câu query với GraphQl, query name là GET_DOGS. Primary API mà ta sử dụng là useQuery, argument cho nó là query string. Data trả về từ query sẽ bao gồm 3 thứ.

  • loading
  • error
  • data

Một cái hay của Apollo Client Queries là nó hỗ trợ Caching query result.

Whenever Apollo Client fetches query results from your server, it automatically caches those results locally. This makes subsequent executions of the same query extremely fast.

Khi Apollo Client fetch data từ server, nó sẽ tự động cache lại kết quả ở phía local. Điều này tăng performance do ở những lần query tiếp theo, kết quả sẽ trả về rất nhanh.

Apollo ClientNguồn ảnh: apollographql.com

Cache thì dễ, nhưng lúc update data mới thì sao?. Phải clear hoặc update cache nếu không data trả về sẽ bị sai.

1.1 Các loại Queries Cache

Với câu hỏi này thì Apollo hỗ trợ 2 chiến lược để update lại data:

  • Thứ nhất là Polling
  • Thứ hai là Refetching

Polling thì đúng như cái tên của nó, về cơ bản thì thằng này gần với realtime. Gần thôi nha anh em, vì nó sẽ fetch data theo định kì chứ không phải fetch liên tục.

Polling provides near-real-time synchronization with your server by executing your query periodically at a specified interval.

Polling cung cấp giải pháp gần với realtime data. Cách làm là query theo định kì tới server (theo khoảng thời gian thiết lập cố định)

Ông cố nội Refetching thì khác, ông này cũng update query result, nhưng chỉ lúc nào user có action nào đó. Ví dụ như khi chuyển page sẽ update lại total items chưa xem chẳng hạn.

Refetching enables you to refresh query results in response to a particular user action, as opposed to using a fixed interval.

Refetch chung cho phép “Làm tươi mới” kết quả lấy được từ query dựa trên actions của user. Cái này thì là fixed interval

Thôi viết đến đây, chi tiết cụ thể anh em có thể lên Docs của Apollo đọc ha, ta đi tiếp với Mutation.

  Giới thiệu Fetch API trong Javascript
  Hướng dẫn tắt cách tắt Superfetch (SysMain) trên Windows 10

2. Apollo Client Mutation

Khác với Queries như ở mục một, nhắc tới query là anh em biết ngay collect data từ backend. Định nghĩa về mutation trong Apollo Client đơn giản hơn nhiều.

2.1 Định nghĩa

Mutations đẻ ra để trả lời cho câu hỏi:

How to modify back-end data?

Làm thế nào để chỉnh sửa data backend?

Câu trả lời thì không thể dễ dàng hơn, mutations. Mutations đẻ ra để thực hiện các methods như REST API ta thường thực hiện (POST, PUT, UPDATE, PATCH, …)

Về mấy cái method này anh em có thể tham khảo bài Http Methods: thất tinh bắc đẩu trận.

Giờ cùng xem thử với Apollo Client Mutation thì làm sao có thể modify data:

import { gql, useMutation } from '@apollo/client';

// Define mutation
const INCREMENT_COUNTER = gql`
# Increments a back-end counter and gets its resulting value
mutation IncrementCounter {
currentValue
}
`;

function MyComponent() {
// Pass mutation to useMutation

const [mutateFunction, { data, loading, error }] = useMutation(INCREMENT_COUNTER);
}

Đầu tiên là khúc import, khúc này cần work với những API nào bên Apollo thì ta cần thảy vào.

The useMutation React hook is the primary API for executing mutations in an Apollo application.

useMutation trong React hook là API chính để thực thi mutations trong ứng dụng Apollo

Apollo Client MutationNguồn ảnh: apollographql.com

Sau khi dã khai báo thì ta cần pass câu query vào useMutation câu query cần thực thi.

const [mutateFunction, { data, loading, error }] = useMutation(INCREMENT_COUNTER);

Tiện lợi không khác gì Queries, nhưng có một điều anh em cần nhớ kĩ:

Unlike useQueryuseMutation doesn’t execute its operation automatically on render. Instead, you call this mutate function.

Không giống như useQuery, useMutation không thực thi một cách tự động khi component khi render. Thay vào đó, ta cần phải gọi mutate function

Cái này thì dễ hiểu, tại vì các actions change tới DB thường mapping tới các actions của user trên FE. Tuy nhiên, với các actions initial khi render, ta cũng thoải mái gọi các function mutation để thực thi.

2.2 Một số thứ khác

Còn data, loading thì tương tự như useQuery, cái này anh em có thể tham khảo ở mục Result bên Apollo Client

function AddTodo() {
let input;

const [addTodo, { data, loading, error }] = useMutation(ADD_TODO);

if (loading) return 'Submitting...';
if (error) return `Submission error! ${error.message}`;

return (

{
e.preventDefault();addTodo({ variables: { text: input.value } });
input.value = ”;
}}
>
{
input = node;
}}
/>
);
}

Ví dụ trên đây thì onSubmit (line 12) sẽ gọi tới mutation function. Apollo Client lúc này sẽ gọi tới Apollo Server để thực thi.

Một số các topics khác liên quan tới Mutation như Providing optionsTracking mutation status và Resetting mutation status thì anh em có thể tham khảo trên trang docs nha. Mình không viết kĩ quá ở đây.

3. Apollo Client Subscriptions

Ngoài queries và mutations, GraphQL cũng support thêm một kiểu tương tác với Apollo Server khác là Subscriptions.

3.1 Định nghĩa

Vậy Subscriptions là gì?

Về mặt bản chất thì Subscriptions cũng giống như Queries, nhưng có một điểm khác biệt chí mạng là chữ “real time”.

Unlike queries, subscriptions are long-lasting operations that can change their result over time. They can maintain an active connection to your GraphQL server (most commonly via WebSocket), enabling the server to push updates to the subscription’s result.

Không giống như queries, subscriptions là một hoạt động lâu dài có thể thay đổi kết quả của chúng trong thời gian thực. Nó cho phép ta duy trì kết nối tới GraphQL Server (thông thường thông qua WebSocket), cho phép máy chủ gửi data mới nhất về kết quả của subscriptions.

Lý thuyết lèo nhèo là thế, về cơ bản ta cứ nhớ Apollo client Subscriptions là real time data. Dựa trên cơ chế của web socket, server có thể liên tục trả về data mới cho client thông qua một connection alive. Tiện lợi mà không cần mò mẫm tới Web Socket.

Subscriptions are useful for notifying your client in real time about changes to back-end data, such as the creation of a new object or updates to an important field.

Subscription rất có lợi khi ta muốn thông báo cho user sự thay đổi data real time. Giống như khởi tạo một object mới hoặc update một field nào đó quan trọng.

3.2 Khi nào nên xài?

Khi nào ta nên sử dụng Subscriptions?

Small, incremental changes to large objects. Repeatedly polling for a large object is expensive, especially when most of the object’s fields rarely change. Instead, you can fetch the object’s initial state with a query, and your server can proactively push updates to individual fields as they occur.

Các đối tượng nhỏ, tăng dần đôi với các đối tượng bự hơn. Lặp đi lặp lại polling cho một object bự thì khá là tốn kém. Đặc biệt là field trong một object rất ít khi thay đổi. Thay vào đó, ta có thể fetch trạng thái ban đầu của một object thông qua query, sau đó server sẽ trả về các update tới các field đo khi có thay đổi.

Má, viết vậy có khi dễ hiểu hơn.

Sau đây là ví dụ cụ thể. Về phía server:

type Subscription {
commentAdded(postID: ID!): Comment
}

Subscriptions là đăng kí, ở phía server khi viết function này đồng nghĩa với việc ta đăng kí bất kì khi nào người dùng có comment mới add vào thì ta sẽ thực hiện một actions gì đó.

Ở phía client thì ta chỉ cần define subscription ta muốn Apollo Client thực thi:

const COMMENTS_SUBSCRIPTION = gql`
subscription OnCommentAdded($postID: ID!) {
commentAdded(postID: $postID) {
id
content
}
}
`;

4. Apollo Client Fragments

Fragments thì hơi confuse, nhưng anh em cứ bám vào title trên document nha.

Share fields between operations

Chia sẻ fields giữa các thao tác

GraphQL fragment is a piece of logic that can be shared between multiple queries and mutations.

GraphQL Fragment là một phần logic cho phép chia sẻ giữa các câu queries và mutations.

fragment NameParts on Person {
firstName
lastName
}

Mỗi thằng Fragment sẽ bao gồm một tập hợp con của các trường thuộc kiểu liên kết của nó. Ví dụ ở trên thì thằng Person sẽ khai báo firstName, và thằng lastName thì thuộc về thằng NameParts.

Lúc này thằng NameParts sẽ trở thành Fragments, ta có thể thêm Fragment vào bất kì cái queries và mutations nào có liên quan tới Person.

query GetPerson {
people(id: "7") {
...NameParts
avatar(size: LARGE)
}
}

Khi thêm NameParts, câu query này tương đương với:

query GetPerson {
people(id: "7") {
firstName
lastName
avatar(size: LARGE)
}
}

Ngon, vậy lúc nào thì ta cần xài tới Fragments. Cái này quan trọng, kinh nghiệm thực tế là nhiều bạn trong teams mình sử dụng Fragments theo kiểu dùng dao mổ trâu đi thịt chim sẻ.

  • Sharing fields between multiple queries, mutations or subscriptions.
  • Breaking your queries up to allow you to co-locate field access with the places they are used.

Đầu tiên là chia sẻ fields giữa các queries, mutations. Thứ hai là bẻ nhỏ queries ra, cho phép xác định chính xác field đó sẽ được sử dụng ở đâu.

Viết mệt vãi nhưng anh em yên tâm. GraphQL sẽ là một topics lớn và có bài ra thường xuyên 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 công việc CNTT hấp dẫn trên TopDev

Kiến thức cần có về System Quality Attributes

system quality attributes
Kiến thức cần có về System Quality Attributes

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

Trong quá trình thiết kế hệ thống, có rất nhiều khái niệm cần hiểu rõ để tránh việc hiểu sai yêu cầu của khách hàng, một trong những khái niệm quan trọng là Quality Attributes.

Khái niệm này thường bị nhầm lẫn bởi một số bạn có điều kiện lắng nghe trực tiếp requirement từ khách hàng. Bài viết này mình xin chia sẻ thêm về Quality Attributes và một số ví dụ cụ thể.

  Bài toán đồng thuận trong Distributed Systems
  Giải mã bí ẩn "system load" trên Linux

Xem thêm tuyển dụng Product Manager trên TopDev

1. Quality Attributes Motivation

Đối với System Design thì nỗi sợ lớn nhất là không adapt được với functional requirements. Nhưng không phải tất cả yếu tố giúp thiết kế hệ thống đều xoay quanh functional requirements.

System are frequently redesigned NOT because of the functional requirement

Qua trình thay đổi thiết kế của hệ thống đôi khi không chỉ bởi functional requirement (yêu cầu từ khách hàng, yêu cầu hệ thống)

Một số points có thể khiến hệ thống phải design đi, design lại nhiều lần bao gồm:

  • Không đủ nhanh
  • Không thể scale lên được
  • Làm chậm quá trình development
  • Khó khăn khi maintain hệ thống
  • Không đáp ứng được các tiêu chí về security
Quality Attributes

2. Quality Attributes Definition

Quality Attributes are non function requirement

Quality attributes không phải là yêu cầu về chức năng

Khái niệm này ngắn nhưng vô cùng chính xác. Trong quá trình làm việc, mình thấy một số bạn khi nhận được requirement từ khách hàng thường nhầm lẫn giữa functional requirement và Quality Attributes.

Cái này hoàn toàn dễ hiểu, bởi vì client (khách hàng), người mà mình trực tiếp làm việc đôi khi là non-technical. Tất cả những gì họ trình bày hoặc họ nói là về vấn đề hiện tại họ cần giải quyết.

Chính vì Qualiy attributes không phải là chức năng nên bản thân nó định nghĩa hai thứ sau:

  • The qualities of function requirements
  • The overrall properties of the systems

Đầu tiên là chất lượng của một function. Ví dụ:

When user click a search button after they typed in a particular search keywords, the user will be provided a list of products that closely match with search keywords within at most a 100 miliseconds

Khi người dùng click butotn search sau khi đã nhập keywords để tìm kiếm, user sẽ được cung cấp một list các sản phẩm gần khớp nhất trong khoảng thời gian 100 miliseconds.

Rõ ràng mà nói, nguyên câu có thể nhầm tưởng là requirement, nhưng thực chất không phải. Ta sẽ chia nhỏ thành hai phần.

  • Actions (hoặc có thể vẽ thành Sequence Diagram) thì khi user click search ta sẽ trả về một list product.
  • Nhưng phần còn lại, within a 100 miliseconds (cái này thì lại là QA). Thời gian khách hàng mong muốn là nhỏ hơn 100 miliseconds.
Quality Attributes

Một ví dụ khác:

The online store must be available to user a request at least 99.9% of time

Cửa hàng online phải có tính sẵn sàng cho các request từ user với mức phần trăm available khoảng 99,9%

Trong requirement này thì tính sẵn sàng là một yêu cầu, nhưng con số cụ thể 99,9% lại là Quality Attributes.

Quality Attributes

3. Quality Attributes Considerations

Nếu nắm vững và hiểu rõ về Quality Attributes và phân biệt rõ ràng được giữa Fucntional Requirements và Quality Attributes sẽ giúp quá trình thiết kế hệ thống trở nên dễ dàng hơn.

Đội development khi làm việc với PO hoặc SA cũng clear rõ ràng hơn cái nào là SRS và cái nào là QA.

3.1 Đo lường được, test được

Tuy nhiên, có 2 yếu tố chính cần quan tâm khi định nghĩa Quality Attributes.

  • Measureable
  • Testable

Thứ nhất là Measureable (đo lường), các định nghĩa về Quality Attributes cần phải đo lường được. Nếu anh muốn thời gian phản hồi nhanh (100 miliseconds).

  • Con số cụ thể đó thực hiện ở môi trường nào?
  • Server nằm ở đâu?

Yếu tố thứ hai là Testable, cái này là điểm đáng sợ nhất. Nếu không cụ thể và không test được, cả Developer và Production Owner đều sẽ không clear rõ ràng được với nhau. Dẫn tới hiểu sai về requirement và làm sai. Cái này rất tai hại.

Ví dụ:

When user click a buy button, the purchase confirmation must displayed quickly to the user

Khi người dùng ấn nút mua, cái thông tin xác nhận cần phải hiện lên rất nhanh cho user

Cái nguy hiểm chỉ nằm đúng ở một chữ (quickly). Nếu BrSe hoặc SA không clear được cụ thể cái Quality Attributes này, rất dễ là cả function requirement đều không thể xong do bất đồng về Definition Of Done của cả hai bên (client và developer)

3.2 Feasibility – Tính khả thi

Tính khả thi cũng là một yếu tố mà ở vị trí Tech Lead hoặc Solutions Architecture cần cân nhắc. Một số yêu cầu từ khách hàng (client) có thể xung đột với nhau hoặc không khả thi về mặt technical.

Ví dụ Quality Attributes của khách hàng là Login Time phải nhở hơn 1s, nhưng yêu cầu về Security phải an toàn. Với SSL, ta có thể mất nhiều hơn 1s để thực hiện đăng nhập. Các điểm này dường như xung đột với nhau và đòi hỏi người thiết kế hệ thống phải có cái nhìn đủ sâu. Kinh nghiệm cũng là một yếu tố quan trọng giúp xác định rõ các điểm QA.

4. Tham khảo

A big thanks from my side for your time to read – Happy Coding!

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

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

Xem thêm công việc CNTT hấp dẫn trên TopDev

Keyboard from Scratch: Prototype

prototype
Keyboard from Scratch: Prototype

Bài viết được sự cho phép của tác giả Huy Trần

Là một lập trình viên, bàn phím là một vật dụng bạn phải sờ vào hằng ngày, thậm chí số lần bạn sờ nó còn nhiều hơn số lần bạn sờ vào vợ hoặc bạn gái. Chính vì vậy, chúng ta phải đầu tư cho nó một cách xứng đáng, bằng 2 cách:

  1. Mua một cái bàn phím cơ
  2. Tự làm một cái

Và, với những ai tự gọi mình là kĩ sư (software engineer, backend engineer, frontend engineer, hay copy-pasta engineer, stackoverflow engineer,… nói chung là mọi thể loại engineer), chẳng có lý do gì để không tự làm một cái cho riêng mình, để tự mình quyết định bố cục (layout), màu sắc (keycaps), và tốc dộ gõ (key switches, scanning time).

  Các cách lock một property hay object của JS
  3 bài học xương máu mà mỗi Product Manager đều phải trải qua.

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

Suy cho cùng, tự mình build một cái gì đó, và tự tay giải quyết những vấn đề hóc búa trong quá trình build, học hỏi và thu lại được kinh nghiệm cho bản thân, cũng có thể gọi là cái raison d’être của một engineer . Hay nói cách khác, như vậy mới gọi là dân chơi đúng nghĩa .

Hình ảnh sẽ xuất hiện trong bài sau, không phải bài này =)))

Đó cũng là lý do mà mình quyết định tự build một cái bàn phím 40% cho riêng mình. Tuy nhiên, làm việc gì cũng có thử nghiệm, thất bại, rút kinh nghiệm,… để hạn chế những vấn đề đó, chúng ta sẽ bắt đầu với một bản prototype đơn giản nhưng đủ phức tạp để thấy được các vấn đề trong thực tế.

1. Nguyên vật liệu

Đối với bản prototype này, chúng ta cần chuẩn bị:

  • 4 x Cherry MX Brown Switches (chọn switch nào là sở thích cá nhân thôi, hè hè)
  • 4 x Keycap tùy ý
  • 4 x Diode 1N4148
  • 1 x Teensy 3.2 (hoặc Arduino Pro Micro)

Hoặc nếu máu thì các bạn có thể tự làm một con Teensy cho riêng mình 

2. Bố cục bàn phím

Đa phần các bàn phím tên tuổi thường chỉ khác nhau về bố cục (layout), và đây là phần bất biến, sau khi sản xuất, còn lại những thứ khác (case, plate, key mapping…) thì đều có thể được custom tùy ý.

Đối với bản prototype này, chúng ta sẽ thiết kế một layout vô cùng phức tạp, như thế này:

Quá phức tạp!   

Sau khi đã thiết kế xong bố cục thì chúng ta có thể move sang bước tiếp theo đó là thiết kế và cắt tấm đệm (plate).

Trong thiết kế của bàn phím cơ, có 2 cách lắp ghép (mount) swtiches, là Plate Mount và PCB Mount.

PCB Mount là cách lắp các switches trực tiếp trên board mạch. Ưu điểm của thiết kế này là bàn phím nhẹ hơn, cảm giác gõ sâu hơn, có thể cảm nhận rõ độ nẩy và lún của switch. Có khá ít bàn phím thiết kế theo dạng này, có thể kể đến Minvan, KBC Poker,… là các bàn phím như vậy.

Plate Mount là cách lắp các switches trên một tấm nền thường là bằng kim loại, plate thường có độ dày khoảng 1.5mm (rất quan trọng nếu bạn tự làm plate), trên thân của switch cũng có các khớp để “móc” vừa vào plate. Sau đó là đến PCB nằm bên dưới.

Ưu điểm của cách bố trí này là bàn phím sẽ rất cứng cáp, cảm giác gõ rất chắc chắn, nhưng độ gõ không sâu.

Hầu hết bàn phím cơ trên thị trường được thiết kế dùng plate mount.

Vì bản prototype này chúng ta tự hàn mạch bằng tay chứ chưa thiết kế PCB, nên chúng ta sẽ chọn cách plate mount. Và tùy vào độ khéo tay cũng như vật liệu mà bạn kiếm được, mình suggest dùng giấy bìa cứng =)) cắt một tấm hình vuông nhỏ nhắn xinh xinh kiểu này:

Mấy cái ô trống thì cắt hình vuông là được rồi, không cần phải phức tạp như trong hình kia đâu. Căn cứ vào kích thước của switch (ở đây là Cherry MX), mỗi ô trên plate sẽ có kích thước tầm 15mm - 15.6mm

3. Mạch điện

Tiếp đến là bước nối mạch điện. Sau khi lắp xong swtich vào plate thì lật ngửa nó ra, các bạn sẽ thấy bố trí như hình bên dưới, với mỗi switch gồm 2 chân, các chân bên trái nằm cao hơn bên phải. Nối diode vào chân bên trái, và nối lại với nhau để tạo thành một hàng, đồng thời, nối các chân bên phải lại với nhau tạo thành các cột.

Sơ đồ mạch điện trên lý thuyết

Và thực tế 

Cách mắc mạch điện như trên cũng là cách mắc phổ biến trong các loại bàn phím cơ, các switch tạo thành một mam trận nhiều hàng nhiều cột, cách mắc này có ưu điểm là tiết kiệm được số cổng kết nối trên board điều khiển, trong bản prototype này chúng ta không thể thấy rõ điều đó, nhưng giả sử với một bàn phím 60%, thường sẽ có 5 hàng và 15 cột, như vậy ta chỉ cần 20 cổng kết nối trên board điều khiển, nhưng vẫn có thể xử lý được từ 60 đến 65 phím.

Nếu các bạn thắc mắc tại sao phải lắp thêm diode vào các switch thì có thể tham khảo thêm về vấn đề Ghosting.

Sau khi hoàn tất công đoạn hàn mạch, thì chúng ta sẽ nối mạch này vào Teensy, chúng ta gọi các dây xanh là hàng (row), và dây đỏ là cột (column), mạch của chúng ta gồm có 2 hàng và 2 cột, tiến hành nối các hàng và cột này vào 4 cổng digital của Teensy, cổng nào là tùy ý các bạn chọn.

Trong hình trên, mình nối các cột vào các chân số 2 và 3. Các hàng vào các chân số 6 và 7.

4. Thiết kế Firmware

Khi mình bắt đầu phần này thì khá là nhiều người trên Reddit và Geekhack khuyên mình đừng nên tự viết firmware riêng mà hãy dùng các firmware có sẵn như TMK hoặc QMK. Tuy nhiên khi thử build hai loại firmware trên thì rất may là mình dùng Teensy 3.2, board này xài chip ARM 32-bit (Cortex-M4), chưa được support tốt lắm trên cả 2 firmware trên, nên build không chạy được . Thế nên mình quyết định là tự viết riêng cho mình một bản firmware riêng.

Để cho đơn giản, thì mình sẽ sử dụng Teensyduino để lập trình. Đây là một add-on của Arduino IDE, cho phép chúng ta lập trình trên Teensy bằng bộ thư viện của Arduino, và sử dụng cấu trúc chương trình của Arduino.

Một firmware cơ bản sẽ là một event loop thực hiện các công việc sau:

  • Scan: quét liên tục để tìm ra các phím được nhấn
  • Processing: xây dựng một buffer chứa keycode của các phím đang được nhấn xuống, dựa trên keymap mà chúng ta đã thiết lập.
  • Output: Gửi buffer này về máy tính thông qua cổng USB.

Trước khi bắt tay vào thực hiện code logic trên, chúng ta cần phải khai báo một vài thông số liên quan:

#include <Keyboard.h>

const byte ROWS = 2;
const byte COLS = 2;

char keys[ROWS][COLS] = {
  { 'A', 'B' },
  { 'C', 'D' }
};

const byte rowPins[ROWS] = { 6, 7 };
const byte colPins[COLS] = { 2, 3 };

Ở trên, chúng ta include thư viện Keyboard.h (đi kèm theo SDK của Arduino), chỉ vì chúng ta muốn sử dụng hàm Keyboard.print() có trong thư viện này để gửi phím được nhấn về cho máy tính.

Tiếp theo, chúng ta khai báo 2 hằng ROWS và COLS quy định số hàng và số cột của bàn phím, mảng keys chính là keymap, là mảng quy ước các kí tự nào thuộc về phím nào trên bàn phím của chúng ta, ở đây khi nhấn các phím 1, 2, 3, 4 thì bàn phím sẽ gửi về máy tính các kí tự A, B, C, D.

Hai mảng rowPins và colPins lưu vị trí các chân cắm trên board điều khiển, theo như cách chúng ta đã nối dây ở phần trước.

Đến đây, nếu tinh ý thì các bạn sẽ nhận ra, là ở bài viết tiếp theo khi chúng ta xây dựng firmware cho một cái bàn phím thực sự, thì chỉ cần thay đổi các thông số ở trên là xong.

Bây giờ đến phần implement event loop cho firmware của chúng ta, đầy đủ 3 bước scanprocess và output:

void loop() {
    char code = scan();
    if (code !== -1) {
        char keyCode = process(code);
        output(keyCode);
    }
    delay(50);
}

4.1. Vấn đề #1: Quét tín hiệu

Hàm scan() của chúng ta sẽ có nhiệm vụ quét tất cả các hàng và các cột của mạch điện, kiểm tra xem phím nào được nhấn xuống và trả về một giá trị kiểu byte chứa thông tin các phím được nhấn.

C không có kiểu byte nên chúng ta dùng kiểu char để thay thế.

Để cho đơn giản, thì chúng ta chỉ support việc nhấn một phím một lần, ở bài sau chúng ta sẽ cải tiến firmware để xử lý việc nhấn tổ hợp phím, macro,…

Việc quét phím được thực hiện thông qua thuật toán sau:

Nếu cảm thấy khó hiểu ở bước 3 và 4, bạn có thể đọc thêm cách hoạt động của các chân digital tại đây.

Vì mạch của chúng ta chỉ đơn giản gồm có 4 nút, mỗi hàng và mỗi cột chỉ có nhiều nhất là 2 phàn tử (index là 0 hoặc 1), vậy nên ta có thể “gói” hai giá trị hàng cột này vào cho một số kiểu byte, bằng phương pháp dịch bit.

Giả sử chúng ta đang ở hàng r = 0 và cột c = 1, chúng ta có thể chèn giá trị r vào bit thứ nhất, và c vào bit thứ 2:

n = (r << 0) | (c << 1)

Khi cần đọc ngược lại thì cũng rất đơn giản:

r = (n >> 0) & 1c = (n >> 1) & 1
char scan() {
    char code = -1;

    // Đưa tất cả các pin về trạng thái INPUT/HIGH
    for (int i = 0; i < ROWS; i++) {
        pinMode(rowPins[i], INPUT_PULLUP);
        digitalWrite(rowPins[i], HIGH);
    }
    for (int i = 0; i < COLS; i++) {
        pinMode(colPins[i], INPUT_PULLUP);
        digitalWrite(colPins[i], HIGH);
    }

    // Đưa từng hàng về trạng thái OUTPUT/LOW và quét
    for (int row = 0; row < ROWS; row++) {
        pinMode(rowPins[row], OUTPUT);
        digitalWrite(rowPins[row], LOW);
        for (int col = 0; col < COLS; col++) {
            if (!digitalRead(colPins[col])) {
                // Lưu giá trị hàng và cột thành một số int
                code = (row << 0) | (col << 1);
            }
        }
        pinMode(rowPins[row], INPUT_PULLUP);
        digitalWrite(rowPins[row], HIGH);
    }
    return code;
}

4.2. Vấn đề #2: Gửi tín hiệu về máy tính

Tiếp theo, chúng ta cần chuyển thông tin về hàng/cột nhận được thành kí tự đã được khai báo trong keymap.

Bước này khá là đơn giản, chỉ cần đọc giá trị trả về từ hàm scan() và trả về giá trị tương ứng từ mảng keys :

char process(char code) {
    return keys[(code >> 0) & 1][(code >> 1) & 1];
}

Hàm gửi tín hiệu output() sẽ sử dụng hàm Keyboard.print của bộ thư viện Keyboard.h và truyền thông tin sang máy tính:

void output(char c) {
    Keyboard.print(c);
}

Đến bước này, bạn có thể compile và upload firmware vào Teensy để test thử.

Máy tính đã nhận diện được bàn phím mới, và gõ thì có ra được nội dung thật. Tuy nhiên sẽ có một vấn đề đó là hiện tượng nhấn một nút, máy tính sẽ in ra rất nhiều lần phím được nhấn. Đây gọi là hiện tượng key chatter.

Ở bài viết tiếp theo, chúng ta sẽ tìm hiểu sâu hơn về hiện tượng này, và implement kĩ thuật debounce để giải quyết nó.

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

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

Xem thêm công việc công nghệ hấp dẫn trên TopDev

Làm IT Cho Ngân Hàng – Hướng Đi Phù Hợp Cho Lập Trình Viên?

làm IT cho ngân hàng
Làm IT Cho Ngân Hàng Có Phải Là Hướng Đi Phù Hợp Cho Lập Trình Viên?

Là ngành nghề phù hợp với xu hướng phát triển thời đại nên không khó hiểu khi nhân lực cho ngành IT cũng đang tăng lên theo cấp số nhân. Rất nhiều lập trình viên khi tốt nghiệp vẫn đang băn khoăn không biết đâu mới là lựa chọn phù hợp cho công việc của mình. Tại sao không thử cân nhắc đến việc làm IT cho ngân hàng? Đây chắc chắn sẽ là công việc hấp dẫn nếu các lập trình viên biết nắm bắt và tận dụng cơ hội của mình.

làm it cho ngân hàng
Làm IT Cho Ngân Hàng Có Phải Là Hướng Đi Phù Hợp Cho Lập Trình Viên?

Tổng quan công việc làm IT cho ngân hàng

Làm IT cho ngân hàng là gì?

Có thể hiểu một cách khái quát nhất, khi làm IT cho ngân hàng, các lập trình viên sẽ chịu trách nhiệm hoạt động các phần mềm số cũng như kỹ thuật máy tính. Lập trình viên sẽ thu thập, xử lý, chuyển đổi, truyền tải và lưu trữ thông tin toàn bộ dữ liệu của ngân hàng. Trong thời đại chuyển đổi ngân hàng số như hiện nay, hầu như tất cả các ngân hàng đang đẩy mạnh hơn nữa việc số hóa và ứng dụng công nghệ thông tin trong dịch vụ khách hàng của ngân hàng mình.

  "Cơ hội phát triển sự nghiệp AI với các ngành nghề là tương đồng" - Bảo Đại, AI Researcher tại Knorex
  10 dự đoán hàng đầu của ngành IT trên toàn thế giới

Công việc mà lập trình viên ngân hàng đảm nhận gồm những gì?

Thông thường hiện nay, công việc của các lập trình viên ngân hàng sẽ gồm 3 nhiệm vụ chính:

  • Giám sát các hoạt động của ngân hàng liên quan đến CNTT: Vì ngân hàng luôn đòi hỏi tính chính xác cao trong từng con số cũng như hạn chế thấp nhất các sự cố có thể xảy ra, ảnh hưởng đến người dùng, lập trình viên cần liên tục giám sát hoạt động của phòng IT, đảm bảo hoạt động diễn ra liên tục và hiệu quả.
  • Vận hành các phần mềm phục vụ xây dựng ngân hàng số: Do ảnh hưởng của việc chuyển đổi công nghệ thông tin, tất cả các ngân hàng hiện nay đều đầu tư rất mạnh cho việc xây dựng app, website để đáp ứng nhu cầu của người dùng. Các lập trình viên sẽ chịu trách nhiệm xây dựng và vận hành hệ thống được hoạt động tốt nhất.

Bên cạnh đó, các devs phải liên tục cập nhật thông tin, xử lý sự cố, fix bugs có thể xảy ra gây ảnh hưởng đến quá trình giao dịch của khách hàng. Ngoài ra, các devs cũng vận hành hệ thống phần mềm dành cho các bộ phận nhân viên hoạt động trong ngân hàng như POS, BO, HRM,…

  • Theo dõi, kiểm tra hạ tầng hệ thống CNTT: Ngân hàng là một trong những bộ máy hoạt động xuyên suốt, không ngừng nghỉ bất kể ngày đêm, vậy nên các devs cần giám sát hoạt động liên tục của máy chủ ứng dụng, hệ thống mạng LAN, hệ thống mạng Wifi – Internet, tổng đài nội bộ. Trong quá trình kiểm tra hệ thống cũng cần kịp thời phát hiện và tiến hành xử lý sự cố để không làm ảnh hưởng đến hoạt động của ngân hàng.
công viêc của IT ngân hàng
Lập trình viên của ngân hàng sẽ xử lý nhiều công việc khác nhau

Yêu cầu tuyển dụng với nhân viên IT ngân hàng như thế nào?

Với khối lượng công việc như thế, hiện nay yêu cầu tuyển dụng đặt ra với nhân sự ngành ngân hàng cũng liên tục được cập nhật và chú trọng nhiều hơn vào chất lượng. Về bằng cấp, thông thường ngân hàng sẽ tuyển dụng nhân sự tốt nghiệp với bằng khá trở lên và đã được đào tạo chuyên môn có liên quan đến công việc khi còn trên ghế nhà trường sẽ là một điểm cộng.

Về mặt kinh nghiệm chuyên môn, ứng viên nên có ít nhất 1 năm kinh nghiệm làm việc ở những vị trí tương tự hay ở ngân hàng. Công việc ở ngân hàng luôn có áp lực cực kỳ lớn với khối lượng công việc nhiều, liên tục nên những ứng viên có khả năng chịu áp lực tốt sẽ được đánh giá cao hơn. Ở vị trí là một lập trình viên, kiến thức và kỹ năng trong ngành IT chắc chắn là điều cần có nếu bạn muốn ứng tuyển vào ngân hàng.

Xem thêm 3PL Là Gì? Top Các Công Ty 3PL Ở Việt Nam

Ngoài ra, cũng như mọi ngành nghề khác, các kỹ năng mềm như kỹ năng làm việc nhóm, kỹ năng giao tiếp, khả năng trình bày và xử lý vấn đề,… cũng thật sự rất quan trọng trong quá trình nhà tuyển dụng đánh giá và lựa chọn ứng viên. Đầu tư thêm cho các chứng chỉ ngoại ngữ và khả năng giao tiếp ngoại ngữ cũng là điểm cộng cực lớn cho các ứng viên IT ngân hàng.

ngân hàng tuyển dụng IT
Chất lượng nhân sự IT ngân hàng ngày càng cao hơn

Mức lương của nhân viên IT ngành ngân hàng hiện đang nằm ở mức nào?

Có nhiều yếu tố khác nhau ảnh hưởng đến mức lương của nhân viên IT ngành ngân hàng. Nhìn chung trên thị trường hiện nay lương đang dao động trong khoảng từ 7 – 15 triệu đồng/tháng với những nhân viên từ 1 – 5 năm kinh nghiệm. Đối với các nhân viên đã có nhiều năm kinh nghiệm và chuyên môn cao hoặc đã ở trình độ quản lý thì mức lương hoàn toàn có thể tốt hơn như thế. Trung bình có thể nằm trong khoảng trên 25 triệu đồng/tháng.

Thu nhập hấp dẫn, công việc năng động, môi trường làm việc chất lượng chính là những lý do giúp các việc làm ngành ngân hàng thu hút rất nhiều ứng viên. Để có được cho mình công việc yêu thích, sự chuẩn bị kỹ càng và đam mê chính là yếu tố tiên quyết của sự thành công. Tìm hiểu thêm nhiều việc làm IT cho ngân hàng với cơ hội công việc đầy hứa hẹn cùng TopDev nhé!

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

Xem thêm tuyển dụng việc làm IT hấp dẫn trên TopDev

Giải thích dễ hiểu hơn về Nuxt Authentication

nuxt authentication

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

Nuxt Authentication là một module của Nuxtjs hỗ trợ Authentication. Mà bạn nào làm việc với Nuxt nhiều cũng biết rồi đấy.

Nuxtjs là framework base trên Vuejs, với Nuxt ta có thể tạo cả hai loại apps là SSR (Server Side Render) và SPA (Singple Page Application) nên Nuxt đã mạnh lại càng mạnh hơn.

Trong thực tế dự án hiện tại project mình có xài Nuxt + GraphQL, application có login/logout nên có tìm hiểu về Nuxt Authentication (auth). Mạn phép viết bài này chia sẻ anh em chút kiến thức về Nuxt Auth.

Cũng trong project mình xài JWT nên có thể có ví dụ về Nuxt auth + JWT.

  10 điều bạn có thể làm với Linux mà bạn không thể làm với Windows
  API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth

Xem thêm việc làm JavaScript lương cao trên TopDev

1. Giới thiệu về Nuxt Authentication

Authentication / Authorization thì là nhu cầu cơ bản của một applications, các application xây dựng với Nuxt cũng không phải là một ngoại lệ.

Nuxt Authentication là một modules xây dựng dựa trên Nuxtjs.

Trong vài dòng ngắn ngủi ta có một cái nhìn sơ bộ về module này như sau:

The module authenticates users using a configurable authentication scheme or by using one of the directly supported providers. It provides an API for triggering authentication and accessing resulting user information. While it takes care of storing the information on the client-side, it does NOT implement session handling or provide session based authentication on the NuxtJS server

Module xác thực người dùng sử dụng xác thực bằng scheme hoặc bởi providers. Nó cung cấp một API cho phép trigger xác thực và truy cập thông tin user sau khi đã xác thực thành công. Trong khi đó nó cũng đảm nhiệm việc lưu trữ thông tin ở phía client. Nhưng nhấn mạnh là nó không làm gì với session handling (quản lý session) hoặc cung cấp session dựa trên việc xác thực trên NuxtJS Server

Rồi, với Nuxt Authentication thì sau khi xác thực thành công, module này sẽ hỗ trợ về lưu trữ token ở phía client. Nhưng đối với việc handle session (validate token này kia đã hết hạn hay chưa) thì vẫn phải thực hiện ở phía server.

Nuxt AuthenticationNguồn ảnh / Source: https://auth.nuxtjs.org/

2. Schemes và Providers

Về setup cho Nuxt Authentication thì anh em có thể tham khảo trên trang của Nuxt ha. Bài viết này mình muốn phần tích về các khái niệm Schemes và Providers kĩ hơn.

Đôi khi xài chứ mà không hiểu thì nguy hiểm lắm. LOL

{
modules: [
'@nuxtjs/axios',
'@nuxtjs/auth-next'
],
auth: {
// Options
}
}

Authen/ Autho là common solution, nhưng những logic đằng sau đó thì không như vậy. Do đó ta cần Schemes.

2.1 Scheme Authentication

Schemes define authentication logic. Strategy is a configured instance of Scheme. You can have multiple schemes and strategies in your project.

Schemes định nghĩa logic xác thực. Object Strategy là cấu hình instance của Scheme. Ta cũng có thể có nhiều schemes và các chiến lược khác nhau trong Project

Trời má, đọc vô hiểu chết liền. Nói không điêu chứ đôi cái logic nó huyền bí cho tới khi ta thấy code.

Để dễ hiểu hơn thì ta cần quay lại khái niệm của Authentication Scheme.

An authentication scheme is a definition of what is required for an authentication process. This includes the following:

  • The login module stack used to determine whether a user is granted access to an application
  • The user interfaces used to gather the information required to authenticate a user
  • Priority, enabling authentication schemas to be ordered
Nuxt AuthenticationCách giải thích khác về Authentication Scheme. Nguồn ảnh/ Source: simpleid.org

Theo như cái định nghĩa dễ hiểu hơn ở trên thì authentication scheme là định nghĩa những thứ cần có trong quá trình xác thực người dùng. Tại phương thức xác thực đôi khi khác nhau.

Nhắc tới đây lại không thể không giới thiệu với anh em bài viết về Two-Factor Authentication (2FA) hoạt động như thế nào?.

Rồi, từ chiến lược – Strategy dễ hiểu hơn. Ta có thể có nhiều cách để xác thực người dùng, nhiều chiến lược khác nhau.

import { LocalScheme } from '~auth/runtime'

export default class CustomScheme extends LocalScheme {
// Override `fetchUser` method of `local` scheme
async fetchUser (endpoint) {
// Token is required but not available
if (!this.check().valid) {
return
}

// User endpoint is disabled.
if (!this.options.endpoints.user) {
this.$auth.setUser({})
return
}

// Try to fetch user and then set
return this.$auth.requestWith(
this.name,
endpoint,
this.options.endpoints.user
).then((response) => {
const user = getProp(response.data, this.options.user.property)

// Transform the user object
const customUser = {
...user,
fullName: user.firstName + ' ' + user.lastName,
roles: ['user']
}

// Set the custom user
// The `customUser` object will be accessible through `this.$auth.user`
// Like `this.$auth.user.fullName` or `this.$auth.user.roles`
this.$auth.setUser(customUser)

return response
}).catch((error) => {
this.$auth.callOnError(error, { method: 'fetchUser' })
})
}
}

Với fetchUser, ta có thể thoải mái custom process trong Nuxt Authentication. Do process và flow có thể can thiệp nên Nuxt auth trở nên flexible hơn bao giờ hết. Một big plus point.

this.$auth.loginWith('customStrategy', { /* ... */ })

Đơn giản là giờ xác thực với scheme nào nữa thôi.

Rồi một bé, giờ tới bé Provider

2.2 Providers

Providers là bên cung cấp (platform) mà từ đó user có thể xác thực tài khoản của mình. Nuxt Authentication cung cấp rất nhiều các providers khác nhau.

Nuxt AuthenticationList providers được cung cấp bởi Nuxt. Nguồn ảnh / Source: https://auth.nuxtjs.org/

Providers có vẻ là dễ hiểu hơn, tuy nhiên với từng loại providers ta cần đọc kỹ tài liệu. Ngoài ra Nuxt Authentication cũng hỗ trợ Extending Auth Plugin.

Đơn giản là nếu ta có một plug in nào khác, ta có thể dễ dàng sử dụng thông tin sau khi đã xác thực.

3. Tham khảo

Cảm ơn anh em đã đọc bài – Thanks for your gold time to read my article – Wish you the best of luck!

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

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

Giải thích Javascript Reactivity

Giải thích mô hình MVC thông qua … cốc trà đá

Giải thích React Component Lifecycle

Xem thêm công việc CNTT hấp dẫn trên TopDev

Chuyển số Float thành Int dùng các phép bitwise

số float
Chuyển số Float thành Int dùng các phép bitwise

Bài viết được sự cho phép của tác giả Huy Trần

Gần đây có một trick mà mình rất hay dùng, đó là sử dụng hai phép bitwise NOT ~~ để chuyển nhanh một số kiểu float thành int, thay cho việc dùng hàm Math.floor:

        ~~(5.423451) == 5 // true
Math.floor(5.423451) == 5 // true

Ngoài hiệu quả về mặt performance ra, trick này có thể được sử dụng trong các buổi phỏng vấn để… làm màu . Tuy nhiên, việc sử dụng phải đi kèm với việc hiểu và giải thích được cơ chế hoạt động của phép tính này.

Vậy vì lý do gì mà phép tính này có thể chuyển một số kiểu float thành int?

  Cách mạng 0.4 của Neovim: Floating Window
  Bitbucket là gì? Tính năng ưu, khuyết điểm so với GitHub

Xem thêm tuyển dụng Flutter hấp dẫn trên TopDev

Về mặt bản chất, tất cả các kiểu số trong JavaScript đều chiếm 64-bit trong bộ nhớ theo chuẩn IEEE 754

Để tiết kiệm bộ nhớ và hiệu năng, với đa số các JavaScript engine (như là V8, SpiderMonkey,…), nếu một biến x kiểu số có giá trị nguyên vừa đủ nhỏ (ví dụ −231≤x≤231), thì biến đó sẽ được thể hiện dưới dạng một số kiểu 32-bit intege. Chừng nào con số trên đủ lớn, hoặc hoặc không phải là số nguyên nữa thì nó sẽ được tự động chuyển về dạng 64-bit.

Theo đặc tả ECMAScript, khi thực hiện các phép toán bitwise, các toán hạng sẽ tự động bị chuyển về kiểu 32-bit integer.

Tức là khi ta thực hiện bất kỳ một phép toán bitwise nào trên một số, thì kết quả trả về luôn là kiểu 32-bit integer.

Và thường thì chúng ta sẽ sử dụng các phép bitwise vô nghĩa, để tránh làm thay đổi giá trị của số ban đầu, ví dụ:

~~(5.423451) == 5 // Double not
5.423451 | 0 == 5 // Or với 0
5.423451 << 0 == 5 // Shift 0
5.423451 >> 0 == 5 // Shift 0

Chúng ta có thể sử dụng trick này cho rất nhiều tình huống. Ví dụ như thuật toán kiểm tra một số có phải là lũy thừa của 4 hay không (Leetcode #342).

Nếu một số nguyên n∈Zn∈Z là lũy thừa bậc 4 của một số xx nào đó, thì xx cũng phải là một số nguyên (x∈Zx∈Z). Hay nói cách khác, giá trị logarithm cơ số 4 của nn cũng phải là một số nguyên (log4n∈Zlog4n∈Z).

Để tính logarithm cơ số bất kì, ta có thể sử dụng công thức chuyển đổi cơ số để đưa về cùng một dạng logarithm mà máy tính hỗ trợ sẵn, ví dụ log10:

logab=log10blog10a

Thuật toán của chúng ta sẽ được implement như sau:

var isPowerOfFour = function(num) {
    let lg4 = Math.log(num) / Math.log(4);
    return lg4 === (~~lg4);
};

Đọc thêm

  1. The Internal Representation of Numbers, Speaking JavaScript, Chapter 11
  2. Integers in JavaScript, Speaking JavaScript, Chaper 11
  3. Bitwise NOT Operator, ECMAScript 2017 Language Specification
  4. JavaScript: Bitwise Operators, MDN Web Docs
  5. 32-bit Integers via Bitwise Operators, Speaking JavaScript, Chapter 11

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

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

Xem thêm công việc CNTT hấp dẫn trên TopDev

HYBRID TECHNOLOGIES: CHÍNH THỨC IPO TẠI THỊ TRƯỜNG NHẬT BẢN – NÂNG TẦM DOANH NGHIỆP VIỆT

Trong những năm gần đây, làn sóng niêm yết cổ phiếu lần đầu (IPO) trở nên mạnh mẽ hơn bao giờ hết cho thấy dấu hiệu đáng mừng của những doanh nghiệp vừa và nhỏ đang mạnh dạn tìm kiếm cơ hội để chuyển mình. Và trong “cuộc đua” này, Hybrid Technologies chính thức được xướng tên trở thành doanh nghiệp đầu tiên do người Việt thành lập và điều hành thành công IPO trên sàn giao dịch chứng khoán Tokyo tại Nhật Bản với giá trị vốn hoá thị trường tương đương gần 1700 tỷ VNĐ.

CEO Trần Văn Minh
CEO Trần Văn Minh đại diện Hybrid Technologies nhận chứng nhận IPO tại Sở Giao dịch Chứng khoán Tokyo. (Nguồn ảnh: Hybrid Technologies)

Ngày 23/12/2021 vừa qua, vào 13 giờ (theo giờ Nhật Bản), Hybrid Technologies đã chính thức chào bán cổ phiếu ra công chúng lần đầu tại Sở giao dịch Chứng khoán Tokyo – Tokyo Stock Exchange (Nhật Bản) với mã cổ phiếu 4260. Trong số 90 doanh nghiệp thực hiện IPO thành công tại thị trường Nhật trong năm 2021, Hybrid Technologies chính là doanh nghiệp Việt Nam hiếm hoi nằm trong danh sách này. CEO Trần Văn Minh của Hybrid Technologies cũng cùng lúc trở thành người Việt đầu tiên thực hiện niêm yết chứng khoán thành công tại Nhật Bản – thị trường chứng khoán sôi động nhưng cũng khắt khe nhất từ trước đến nay. 

Nhân sự kiện này, Đại sứ Đặc mệnh toàn quyền Việt Nam tại Nhật Bản – ông Vũ Hồng Nam đã gửi lời chúc mừng tới CEO Trần Văn Minh và tập thể Hybrid Technologies. Đại sứ Vũ Hồng Nam nhấn mạnh: “Đây không chỉ là niềm vui riêng của Hybrid Technologies mà còn là niềm vui cho toàn thể các doanh nghiệp hoạt động trong lĩnh vực công nghệ tại Nhật Bản (V-Tech) nói riêng và Việt Nam nói chung. Việc Hybrid Technologies thành công IPO chính là nguồn khích lệ rất lớn cho VN-Tech tiếp tục phát triển không chỉ ở trong nước, đáp ứng kỳ vọng của chính phủ Việt Nam mà còn là động lực thúc đẩy, giúp doanh nghiệp Việt vươn tầm thế giới.” 

Đại sứ Đặc mệnh toàn quyền Việt Nam tại Nhật Bản – ông Vũ Hồng Nam đã gửi lời chúc mừng tới CEO Trần Văn Minh và tập thể Hybrid Technologies (Nguồn ảnh: Hybrid Technologies)

Để có thể IPO vào cuối năm 2021, CEO Trần Văn Minh cùng đội ngũ nhân sự đã có hơn 5 năm nuôi khát vọng và nỗ lực không ngừng nghỉ cho mục tiêu này. Ngay từ những ngày đầu thành lập, CEO của Hybrid Technologies đã định hướng công ty hoạt động theo mô hình  hybrid, mô hình uỷ thác và AI, đóng vai trò cung cấp các giải pháp toàn diện cho khách hàng. Từ chỗ chỉ vài nhân sự đến nay Hybrid Technologies đã có 500 nhân viên trong toàn hệ thống. Từ một vài khách hàng ban đầu sau 5 năm Hybrid Technologies đã có hàng trăm khách hàng, trong đó có những thương hiệu lớn mang tầm cỡ toàn cầu như: Yahoo, Docomo, Uniqlo, BMW

CEO Trần Văn Minh chia sẻ rằng: “Việt Nam hoàn toàn có thể làm chủ cuộc chơi công nghệ với thị trường giàu tiềm năng như Nhật Bản bởi đội ngũ kỹ sư Công nghệ Thông tin của chúng ta mạnh về khoa học Tự nhiên, đặc biệt là Toán học – một trong những yếu tố cốt lõi để lập trình giỏi. Tôi cũng vô cùng tự hào khi trong đội ngũ nhân sự của Hybrid Technologies có rất nhiều chuyên gia hàng đầu về công nghệ từng làm việc tại các tập đoàn công nghệ lớn tại Mỹ và Nhật Bản”. Chính vì vậy mà CEO Trần Văn Minh đã luôn tự tin khi phát triển mô hình Hybrid của mình. Vị CEO này khẳng định: “Với mô hình Hybrid chất xám của đội ngũ kỹ sư CNTT được định giá cao hơn, vị thế của công ty trong mắt đối tác cũng giữ một vai trò quan trọng hơn vì chúng ta không chỉ nhận gia công phần mềm đơn thuần theo yêu cầu của khách hàng mà với mô hình Hybrid chúng ta đóng vai trò là chuyên gia tư vấn, định hướng cho khách hàng để đưa ra các giải pháp tối ưu nhất.”

Hybrid Technologies IPO thành công tại Nhật Bản không chỉ là câu chuyện tài chính. Nhìn từ góc độ khác, Hybrid Technologies và CEO Trần Văn Minh đã khai màn cho một xu thế bước ra thế giới và tìm kiếm cơ hội. Chúng ta có quyền tự hào về một thế hệ mới của cộng đồng các doanh nghiệp hoạt động trong lĩnh vực phát triển phần mềm Việt Nam. Họ không chỉ giỏi về chuyên môn mà còn đầy khát vọng nâng tầm vị thế Việt trên bản đồ công nghệ thế giới.

Hybrid Technologies Co., Ltd. là công ty công nghệ phần mềm liên doanh Nhật – Việt, chính thức thành lập vào tháng 4/2016 với tiền thân là Evolable Asia Solutions Co., Ltd., phát triển các dịch vụ và mô hình làm việc đa dạng trong lĩnh vực công nghệ phần mềm như mô hình hybrid, mô hình ủy thác hay lĩnh vực trí tuệ nhân tạo. 

Đến nay, trải qua 5 năm phát triển không ngừng nghỉ và gặt hái được những thành tựu nhất định, Hybrid Technologies từ một Startup với 4 nhân sự, đến nay đã có 4 trụ sở văn phòng tại Việt Nam và Nhật Bản, với 500 nhân viên cùng hàng trăm các dự án, khách hàng trong nhiều lĩnh vực công nghệ khác nhau. Trong đó, Hybrid Technologies vinh hạnh nhận được sự tin tưởng hợp tác của nhiều thương hiệu lớn tầm cỡ thế giới như: Uniqlo, BMW, Doccomo, Yahoo… Đóng vai trò cung cấp các giải pháp toàn diện cho khách hàng và là đối tác đồng hành bền vững, Hybrid Technologies tự hào và tin tưởng sẽ tiếp tục phát triển song hành với sự thành công của khách hàng để cùng nhau vươn tới một tầm cao mới!

Tìm hiểu thêm về Hybrid Technologies tại: https://www.facebook.com/tuyendung.hybrid.technologies 

Two-Factor Authentication (2FA) là gì và hoạt động như thế nào?

two factor authentication
Two-Factor Authentication (2FA) 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

Bắt đầu với sự thật không thể trần trụi hơn: Đối với những giao dịch quan trọng như Internet Banking, Trading, sẽ có ngày tiền bốc hơi nếu không sử dụng Two-Factor Authentication (2FA).

Chỉ với Username và Password là không đủ để bảo vệ tài khoản cá nhân. Hiện tại có vô vàn cách để hacker đánh cắp tài khoản. Trộm tiền ngay cả khi đang ngủ mà không nỏ bất cứ thông báo nào.

Vậy Two-Factor Authentication là gì? Bằng cách nào mà Two-Factor Authentication có thể bảo vệ được tài khoản cá nhân. Anh em sử dụng nhiều application, nhiều website chắc cũng hiểu sơ sơ cách nó hoạt động, tuy nhiên viết rõ ra thì vẫn hay hơn.

Xem thêm tuyển dụng Security Engineer lương cao trên TopDev

2FA là gì?

2FA (Two-Factor Authentication) được gọi là xác minh bảo mật 2 bước hoặc xác thực hai yếu tố, là một quy trình bảo mật trong đó người dùng cung cấp hai yếu tố xác thực khác nhau để xác minh.

2FA được triển khai để bảo vệ tốt thông tin xác thực của người dùng và các tài nguyên mà người dùng có thể truy cập. Xác thực hai yếu tố cung cấp mức độ bảo mật cao hơn so với các phương pháp xác thực phụ thuộc vào xác thực một yếu tố (SFA), trong đó người dùng chỉ cung cấp một yếu tố – thường là mật khẩu hoặc mật mã.

Các phương pháp xác thực hai yếu tố dựa vào việc người dùng cung cấp mật khẩu làm yếu tố đầu tiên và yếu tố thứ hai, thường là mã thông báo bảo mật (qua địa chỉ email hoặc số điện thoại) hoặc yếu tố sinh trắc học, chẳng hạn như dấu vân tay hoặc quét khuôn mặt.

Hình ảnh đơn giản mô tả cách xác thực 2 bước (Two-Factor Authentication) hoạt động

Tôi có SMS OTP!. Một thanh niên khác mạnh mẽ tuyên bố, đáng buồn thay SMS OTP đã không còn an toàn nữa rồi.

Xác thực hai yếu tố (2FA) hoạt động như thế nào?

Việc bật xác thực hai yếu tố khác nhau tùy thuộc vào ứng dụng hoặc nhà cung cấp cụ thể. Tuy nhiên, quy trình xác thực hai yếu tố bao gồm cùng một quy trình chung, nhiều bước:

  1. Người dùng sẽ được ứng dụng hoặc trang web nhắc đăng nhập.
  2. Người dùng nhập thông tin được yêu cầu, thường là tên người dùng và mật khẩu. Sau đó, máy chủ của trang web tìm thấy sự trùng khớp và nhận dạng người dùng.
  3. Đối với các quy trình không yêu cầu mật khẩu, trang web sẽ tạo một khóa bảo mật duy nhất cho người dùng. Công cụ xác thực sẽ xử lý khóa và máy chủ của trang web sẽ xác thực khóa đó.
  4. Sau đó, trang web sẽ nhắc người dùng bắt đầu bước đăng nhập thứ hai. Mặc dù bước này có thể có nhiều hình thức, nhưng người dùng phải chứng minh rằng họ có thứ mà chỉ họ mới có, chẳng hạn như sinh trắc học, mã thông báo bảo mật, thẻ căn cước, điện thoại thông minh hoặc thiết bị di động khác.
  5. Sau đó, người dùng có thể phải nhập mã một lần được tạo ở bước bốn.
  6. Sau khi cung cấp cả hai yếu tố, người dùng sẽ được xác thực và cấp quyền truy cập vào ứng dụng hoặc trang web.
Two-Factor Authentication

Nói bổ sung một lớp bảo mật thì đơn giản, nhưng ta phải clear với nhau là 2FA chỉ là một phương pháp tiếp cận vấn đề (approach). Tức là nhắc tới Two-Factor Authentication thì hiểu nó là một cách tiếp cận vấn đề (thêm một lớp cho bảo mật)

Còn về methods (phương thức, cách thức) triển khai thì có nhiều loại. 2FA chỉ là cái chung chung chứ không phải là một phương pháp cụ thể.

Apple giải thích như thế nào về 2FA? Cùng xem video:

Các phương thức 2FA phổ biến hiện nay

Hiện nay, có nhiều loại xác thực hai yếu tố (2FA) phổ biến được sử dụng để tăng cường bảo mật cho tài khoản trực tuyến. Dưới đây là một số loại 2FA phổ biến:

Mã OTP

OTP (One Time Password) đây là một trong những phương pháp 2FA phổ biến nhất. Sau khi nhập mật khẩu, người dùng sẽ nhận được một mã xác nhận qua tin nhắn SMS hoặc cuộc gọi đến trên điện thoại di động. Mã này chỉ có thời gian hiệu lực hữu hạn, sau thời gian đó thì sẽ không còn sử dụng được.

Ứng dụng xác thực

Các ứng dụng như Google Authenticator, Authy, và Microsoft Authenticator tạo ra mã xác thực thời gian dựa trên thuật toán HMAC (Time-based One-Time Password, TOTP). Sau khi nhập mật khẩu, người dùng cần mở ứng dụng xác thực để lấy mã và nhập vào trang đăng nhập.

Điểm khác giữa Authenticate Applications và Text message là phương thức này không cần mạng viễn thông, chỉ cần internet

Email

Một mã xác thực hoặc liên kết xác nhận được gửi đến địa chỉ email đã đăng ký của người dùng. Người dùng phải nhập mã này hoặc nhấp vào liên kết để hoàn tất quá trình đăng nhập.

YubiKey và các thiết bị phần cứng khác

Đây là các thiết bị phần cứng nhỏ được cắm vào cổng USB hoặc kết nối không dây (NFC, Bluetooth) để xác thực. Người dùng chỉ cần cắm thiết bị vào máy tính hoặc chạm thiết bị vào điện thoại để hoàn tất quá trình xác thực.

Sinh trắc học

Các phương pháp xác thực sinh trắc học bao gồm nhận dạng vân tay, nhận dạng khuôn mặt, và nhận dạng giọng nói. Các thiết bị di động và máy tính hiện đại thường tích hợp sẵn các cảm biến sinh trắc học để hỗ trợ phương pháp này.

Tuy nhiên nó cũng tồn tại rủi ro nhất định. Dữ liệu sinh trắc học tuy là duy nhất nhưng theo chúng ta tới suốt đời. Không giống như mật khẩu có thể thay đổi được.

Câu hỏi bảo mật

Một số dịch vụ sử dụng câu hỏi bảo mật làm lớp xác thực thứ hai. Người dùng cần trả lời đúng các câu hỏi đã thiết lập trước đó để hoàn tất quá trình đăng nhập.

Recovery codes

Recovery codes là mã mà bạn đã tạo đầu tiên khi thiết lập tài khoản. Phần thông tin đăng nhập chỉ có chính chủ tài khoản mới biết. Cái này bao gồm một số thông tin như câu hỏi bảo mật hoặc mã pin (tự nhớ hoặc lưu trữ local). Do đó hãy lưu giữ thật kỹ mã này bạn nhé!

Một ví dụ rõ ràng dễ thấy nhất của loại này là Google Backup Codes

Two-Factor Authentication

Push Notification

Người dùng sẽ nhận được một thông báo đẩy (push notification) approve đăng nhập từ các app đã cài trước đó của chính chủ. Ví dụ cụ thể và thấy rõ nhất là Facebook. Khi đã đăng nhập trên phone thì sign in lần nữa trên web -> Gửi confirm về app chứ không cần text message hay một số phương thức OTP.

Two-Factor AuthenticationSign in approve của Facebook

Mặc dù thông báo đẩy an toàn hơn các hình thức xác thực khác, nhưng vẫn có rủi ro bảo mật. Ví dụ, người dùng có thể vô tình chấp thuận yêu cầu xác thực gian lận vì họ đã quen với việc chạm vào chấp thuận khi nhận được thông báo đẩy.

Hạn chế của 2FA

Mất yếu tố xác thực

Không có sự đảm bảo rằng các yếu tố xác thực sẽ luôn sẵn sàng khi bạn cần. Trong nhiều trường hợp, người dùng có thể bị khóa tài khoản chỉ sau một lần mắc lỗi.

Ví dụ, nếu mất điện thoại hoặc điện thoại bị hư hỏng do nước, bạn sẽ không thể nhận mã SMS làm yếu tố xác thực thứ hai. Tương tự, việc dựa vào khóa USB cũng rủi ro vì chúng có thể bị mất hoặc hư hỏng. Nếu bạn tin tưởng vào các mã PIN, luôn có khả năng bạn sẽ quên chúng. Các yếu tố sinh trắc học như dấu vân tay hay quét mắt cũng có thể bị mất trong các tai nạn.

Các nạn nhân của bão Harvey và Irma đã gặp khó khăn trong việc truy cập tài khoản vì không có cách sạc điện thoại, dẫn đến việc không thể nhận mã xác thực. Khôi phục tài khoản là có thể, nhưng thường mất thời gian và phức tạp. Nếu bạn có nhiều tài khoản được bảo vệ bằng một yếu tố duy nhất và yếu tố đó bị mất, bạn sẽ phải khôi phục tất cả các tài khoản đó.

False security

2FA cung cấp một mức độ bảo mật, nhưng thường bị phóng đại. Nếu bạn bị khóa khỏi dịch vụ vì mất yếu tố xác thực, bạn ở trong tình huống tương tự như một hacker cố gắng truy cập vào tài khoản của bạn. Nếu bạn có thể đặt lại tài khoản mà không cần yếu tố xác thực, thì hacker cũng có thể làm điều đó. Các tùy chọn khôi phục thường mâu thuẫn với mục đích của 2FA, đó là lý do tại sao các công ty như Apple đã loại bỏ chúng.

Tuy nhiên, nếu không có tùy chọn khôi phục, tài khoản của bạn có thể bị mất vĩnh viễn. Có những dịch vụ như PayPal sử dụng 2FA nhưng không thực hiện đầy đủ. Công ty này cung cấp một yếu tố thứ hai gọi là “PayPal Security Key”, nhưng vào năm 2014, nó có thể bị hoàn toàn bỏ qua một cách dễ dàng. Điều này có nghĩa là bạn có thể tuân theo 2FA và vẫn bị xâm nhập tài khoản.

Bị lợi dụng để chống lại người dùng

Mặc dù 2FA nhằm mục đích ngăn chặn hacker truy cập vào tài khoản của bạn, điều ngược lại có thể xảy ra. Hacker có thể thiết lập hoặc cấu hình lại 2FA để ngăn bạn truy cập vào chính tài khoản của mình. 2FA có thể không đủ hiệu quả để bảo vệ tài khoản của bạn nhưng cũng có thể quá hiệu quả nếu bạn không cẩn thận. Khi các dịch vụ cải tiến với các biện pháp 2FA và làm cho việc khôi phục tài khoản trở nên khó khăn hơn, điều quan trọng là thiết lập xác thực trên các tài khoản cần thiết trước khi hacker làm điều đó.

Tổng kết

  • Xác thực hai yếu tố (2FA) là hệ thống bảo mật yêu cầu hai hình thức nhận dạng riêng biệt, khác nhau để có thể truy cập vào một nội dung nào đó.
  • Yếu tố đầu tiên là mật khẩu và yếu tố thứ hai thường bao gồm tin nhắn có mã được gửi đến điện thoại thông minh của bạn hoặc thông tin sinh trắc học sử dụng dấu vân tay, khuôn mặt hoặc võng mạc của bạn.
  • Mặc dù 2FA cải thiện được tính bảo mật nhưng vẫn chưa phải là giải pháp hoàn hảo.

Tài liệu tham khảo:

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

Xem thêm công việc CNTT hấp dẫn trên TopDev

Gõ tiếng Việt trên Emacs Linux

emacs linux
Gõ tiếng Việt trên Emacs Linux

Bài viết được sự cho phép của tác giả Huy Trần

Có một vấn đề khá đau đầu với dân xài Emacs trên Linux (dù là GUI hay Termminal mode), đó là không gõ tiếng Việt với fcitx hay ibus được.

Có một cách khắc phục, nhưng cách này chỉ hoạt động nếu bạn dùng Emacs trên terminal, còn GUI mode thì vẫn bó tay.

  10 điều bạn có thể làm với Linux mà bạn không thể làm với Windows
  5 lý do lập trình viên nên sử dụng hệ điều hành Linux

Xem thêm nhiều việc làm Linux hấp dẫn trên TopDev

Đầu tiên, cần phải kiẻm tra xem máy đã enabled vi_VN.UTF-8 locale chưa:

locale -a

Nếu chưa thấy, thì có thể add thêm thông qua hướng dẫn tại Archlinux Wiki/Locale.

Tiếp theo, cài đặt biến môi trường LC_CTYPE của máy thành vi_VN.UTF-8:

export LC_CTYPE=vi_VN.UTF-8

Từ bây giờ, bạn đã có thể gõ tiếng Việt trên Emacs (chỉ trong terminal mode emacs -nw thôi nhé**.


Update Ngày 20/5/2018

Tình hình là mình vừa update lên Emacs 27, nên quyết định ngồi config lại lần nữa, quyết tâm gõ cho bằng được tiếng Việt trên Emacs =))) thế mà lại gõ được thiệt luôn  không biết từ bản 26, 27 có update gì không, nhưng khả năng là do các config mới và cài thêm gói ibus-el. Cách làm như sau:

Đầu tiên, update Emacs, hoặc cài bản mới, xóa bản cũ:

yaourt -R emacs
yaourt -S emacs-git

Tiếp theo, cài đặt các biến môi trường để Ibus hoạt động trên các môi trường như GTK, QT (Emacs mặc định xài GTK):

export GTK_IM_MODULE=ibus
export XMODIFIERS=@im=ibus
export QT_IM_MODULE=ibus
export CLUTTER_IM_MODULE=ibus
export LC_CTYPE=vi_VN.UTF-8

Tiếp, cài ibus-el, có thể tải về từ launchpad.net hoặc github, giải nén vô .emacs.d và load nó lên, tùy theo cách bạn quản lý package như nào.

Mình xài Spacemacs, nên mình giải nén nó vô thư mục ~/.emacs.d/private/local/ibus-el, và cấu hình cho Emacs load như sau:

dotspacemacs-additional-packages '(
  ...
  (ibus-el :location local)
)

Load trong user-config:

(defun dotspacemacs/user-config ()
  ...
  ;; Ibus
  (require 'ibus)
  (add-hook 'after-init-hook 'ibus-mode-on)
  (setq ibus-cursor-color '("red" "blue" "limegreen"))

  ...
)

Nếu máy bạn mặc định xài Python 3, thì phải cấu hình thêm biến ibus-python-shell-command-name về Python 2:

M-x custom-set-variable

Chọn: ibus-python-shell-command-name

Gõ: /bin/python2

Hoặc:

(custom-set-variables
 '(ibus-python-shell-command-name "/bin/python2")
)

Thế là xong.

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

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

Kinh Nghiệm Phỏng Vấn Tester Thành Công Được Áp Dụng Nhiều Nhất

kinh nghiệm phỏng vấn tester
Kinh Nghiệm Phỏng Vấn Tester Thành Công Được Áp Dụng Nhiều Nhất

Tester là công việc liên quan đến kiểm thử các phần mềm. Sự phát triển của công nghệ thông tin đã giúp ngành tester có được chỗ đứng vững chắc của riêng mình. Nhiều người lựa chọn theo đuổi công việc tester nhờ mức lương hấp dẫn và công việc thú vị. Vậy làm thế nào để ứng tuyển thành công vị trí tester khi số lượng ứng viên vẫn đang ngày một nhiều lên? Tìm hiểu thêm kinh nghiệm phỏng vấn tester hay ho với bài viết này nhé.

kinh nghiệm phỏng vấn tester
Kinh Nghiệm Phỏng Vấn Tester Thành Công Được Áp Dụng Nhiều Nhất

Công việc tester là làm gì?

Tester được biết đến là công việc liên quan đến kiểm định và thử nghiệm chất lượng phần mềm. Các hoạt động của tester nhằm bảo đảm sản phẩm cuối cùng đến tay khách hàng sẽ hoạt động suôn sẻ và không gây ra bất cứ lỗi hay kết quả không mong đợi nào. Một tester khi kiểm định phần mềm cần tìm ra những lỗi, lỗ hổng và các yêu cầu không đúng với thực tế để có cách khắc phục kịp thời cùng đội ngũ devs.

Đa phần các tester hiện nay có thể làm việc với những công cụ hỗ trợ việc test tự động. Tuy nhiên, trong nhiều trường hợp, việc kiểm tra thủ công bằng mắt cũng có thể được thực hiện để đảm bảo không có lỗi nào bị bỏ qua khi kiểm tra bằng máy. Một tester giỏi không chỉ đảm bảo thực hiện việc kiểm tra quy trình chất lượng sản phẩm, kiến thức chuyên môn mà còn có khả năng chỉnh sửa những lỗi sai mà mình phát hiện.

Những kinh nghiệm phỏng vấn tester hay ho mà các kiểm định viên phần mềm không nên bỏ qua

Để trở thành một tester chắc chắn ứng viên cần phải thông qua phỏng vấn của công ty. Một số câu hỏi phỏng vấn tester chất lượng và thường gặp dưới đây sẽ giúp bạn có thêm thông tin hữu ích cho mình.

Xem thêm nhiều việc làm Tester lương cao trên TopDev

1. Tại sao lại quyết định lựa chọn nghề tester?

Câu hỏi này được nhà tuyển dụng đặt ra nhằm mục đích xác định chính xác và cụ thể hơn định hướng của bản thân cũng như sự nghiêm túc của bạn khi lựa chọn theo đuổi công việc này. Tùy theo mong muốn và định hướng mà mỗi ứng viên mà bạn có thể đưa ra câu trả lời phù hợp. Nhưng hãy nhớ nhà tuyển dụng là những người đã dày dặn kinh nghiệm và họ biết rõ đâu là sự thật, chính vì thế nên chia sẻ một cách thẳng thắn và thật lòng để có thể trò chuyện với người phỏng vấn một cách hiệu quả nhất.

2. Một test case tốt sẽ gồm những đặc điểm gì?

Một test case chuẩn và tốt sẽ thể hiện khá rõ kết quả mà một tester sẽ đạt được trong quá trình làm việc của mình. Một test case tốt thường bao gồm các yếu tố sau: tiêu đề (nêu rõ mục đích của việc thử nghiệm), mục đích (lý do của việc thực hiện test case), mô tả đặc điểm của vấn đề, đối tượng thử nghiệm (tính năng hay mô-đun được thử nghiệm), điều kiện tiên quyết cần được thỏa mãn trong quá trình thực hiện.

phỏng vấn tester
Một số câu hỏi dành cho các tester

Ứng viên có thể dựa vào các gợi ý trên cũng như cân nhắc quá trình làm việc thực tế của mình để đưa ra câu trả lời phù hợp nhất với câu hỏi của nhà tuyển dụng.

3. Bạn hiểu thế nào về test case, use case?

Để định nghĩa thì test case là một dạng tài liệu sẽ cung cấp cho tester từng bước trong quá trình thực hiện, những gợi ý chi tiết về cách để kiểm tra được một ứng dụng. Trong một test case sẽ bao gồm hướng giải quyết, các mô tả, nhận xét, hành động cũng như kết quả, kể cả thành công và thất bại.

Trong khi đó, use case có thể hiểu một cách đơn giản là một tài liệu có thể giúp tester hiểu được hành động của người dùng. Bên cạnh đó use case cũng bao gồm một số phản ứng của hệ thống, sản phẩm khi được tìm thấy trong một chức năng cụ thể nào đó.

Xem thêm Các Phần Mềm Dành Cho Dân IT Mà Mọi Lập Trình Viên Nên Biết

4. Có những phương pháp thử nghiệm nào và các cấp độ của chúng?

Về cơ bản hiện nay có 3 phương pháp kiểm thử phần mềm được áp dụng nhiều nhất gồm:

  • Kiểm tra hộp đen: Cách kiểm tra này chủ yếu phát hiện các sai sót liên quan đến thông số kỹ thuật. Kiểm tra hộp đen không yêu cầu tester phải có kiến thức về các đường dẫn nội bộ, cấu trúc hoặc việc triển khai phần mềm đang được thử nghiệm.
  • Kiểm tra hộp trắng: Ngược lại với việc kiểm tra hộp đen, kiểm tra hộp trắng lại dựa các link nội bộ, cấu trúc code và triển khai phần mềm đang được thử nghiệm. Vậy nên kiểm tra hộp trắng cũng đòi hỏi kỹ năng lập trình chi tiết cao hơn.
  • Kiểm tra hộp xám: Với phương pháp kiểm tra này, tester sẽ không có nhiều kiến thức liên quan đến các hạn chế, các lỗi xảy ra bên trong chương trình.

Kiểm thử phần mềm nói chung, về cơ bản quy trình hoạt động sẽ diễn ra từ giai đoạn kiểm tra đơn vị đến khi các lỗi đã được sửa và chấp nhận. Trong đó gồm 4 bước chính:

  • Kiểm tra đơn vị
  • Thử nghiệm hội nhập
  • Thử nghiệm hệ thống
  • Kiểm tra chấp nhận

Để trở thành một tester, từ kỹ năng làm việc đến kiến thức chuyên môn đều là những yếu tố cần có. Hy vọng một số thông tin được cung cấp trên đây có thể giúp cho các tester tương lai có thêm thông tin và sự tự tin cho những vòng phỏng vấn tới của mình. Đón đọc thêm nhiều thông tin bổ ích khác với những bài viết hấp dẫn cùng topdev.vn/blog

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

Xem thêm tuyển dụng việc làm IT hấp dẫn trên TopDev