Home Blog Page 124

System Design Cơ Bản: REST, GraphQL, gRPC và Webhooks

system design cơ bản

Bài viết được sự cho phép của Edward Thiên Hoàng

Để giúp các API developer hiểu được nên sử dụng phong cách thiết kế API nào, trong ngữ cảnh nào. Hãy cùng xem xét REST, GraphQL, gRPC và Webhooks, phân tích điểm mạnh và điểm yếu của chúng để ap dụng cho đúng vào từng trường hợp.

  Bài toán đồng thuận trong Distributed Systems
  System Admin là gì? Mô tả công việc vị trí System Administrator

REST

18-1

Có thể nói nguyên lí REST và cấu trúc dữ liệu RESTful được biết đến rộng rãi trong giới lập trình web nói chung và lập trình ứng dụng nói riêng.

Bản thân REST không phải là một loại công nghệ. Nó là phương thức tạo API với nguyên lý tổ chức nhất định. Những nguyên lý này nhằm hướng dẫn lập trình viên tạo môi trường xử lý API request được toàn diện.

REST (REpresentational State Transfer) là một dạng chuyển đổi cấu trúc dữ liệu, một kiểu kiến trúc để viết API. Nó sử dụng phương thức HTTP đơn giản để tạo cho giao tiếp giữa các máy. Vì vậy, thay vì sử dụng một URL cho việc xử lý một số thông tin người dùng, REST gửi một yêu cầu HTTP như GET, POST, DELETE, vv đến một URL để xử lý dữ liệu.

RESTful API là một tiêu chuẩn dùng trong việc thiết kế các API cho các ứng dụng web để quản lý các resource. RESTful là một trong những kiểu thiết kế API được sử dụng phổ biến ngày nay để cho các ứng dụng (web, mobile…) khác nhau giao tiếp với nhau.

Chức năng quan trọng nhất của REST là quy định cách sử dụng các HTTP method (như GET, POST, PUT, DELETE…) và cách định dạng các URL cho ứng dụng web để quản các resource. RESTful không quy định logic code ứng dụng và không giới hạn bởi ngôn ngữ lập trình ứng dụng, bất kỳ ngôn ngữ hoặc framework nào cũng có thể sử dụng để thiết kế một RESTful API.

Đọc thêm:

GRPC

18-2

Hiện tại với API thì quá phổ biến cho các ứng dụng từ giao tiếp client tới server hay từ instance tới instance. Tuy nhiên ngày nay công nghệ càng ngày càng phát triển với http2 ra đời đã kéo theo 1 loạt những thay đổi để cải thiện performance, gRPC là sự kết hợp của Protocol Buffers và http2, Protocol Buffers được phát triển bởi google nó nhẹ hơn, nhanh hơn và cung cấp hiệu năng tốt hơn so với sử dụng XML hoặc Json

gRPC là một RPC platform được phát triển bởi Google nhằm tối ưu hoá và tăng tốc việc giao tiếp giữa các service với nhau trong kiến trúc microservice. gRPC cũng cho phép định nghĩa cấu trúc của data dưới dạng file protoc và nó tự động generate ra file sử dụng để giao tiếp với ngôn ngữ mà bạn sử dụng. gRPC hiện tại cũng đã hỗ trợ khá đầy đủ các ngôn ngữ như C++, Java, Python, Go, … các bạn có thể tham khảo thêm ở đây https://grpc.io/docs/

gRPC dùng Protocal Buffer giảm kích thước request và response data, RPC để đơn giản hoá trong việc tạo ra các giao tiếp giữa các service với nhau, HTTP/2 để tăng tốc gửi/nhận HTTP request.

RPC

RPC là từ viết tắc của Remote Procedure Call, nó được xây dựng với ý tưởng là đơn giản hoá việc giao tiếp giữa những service với nhau, thay vì những service giao tiếp với nhau theo kiểu RESTful API thì giờ đơn giản là gọi hàm như những object nói chuyện với nhau thôi, còn việc phân tán các service là chuyện của tương lai không dính liếu đến việc code.

PROTOCAL BUFFER

Protocal Buffer là một ngôn ngữ trung lập để serializing structured data sử dụng cho việc giao tiếp giữa các service với nhau. Protocal Buffer được tạo ra với ý tưởng là làm nhỏ kích thước data truyền đi trong giao tiếp và chỉ cần định nghĩa một lần và sử dụng cho các service với các ngôn ngữ lập trình khác nhau.

HTTP/2

HTTP/2 là một phiên bản nâng cấp của HTTP/1.1, HTTP/2 sinh với với mục đích cải thiện tốc độ giao tiếp giữa client/server trên nền tảng Web.

Vậy những ưu điểm rất lớn của RPC, Protocal Buffer, HTTP/2 sẽ gói trong gRPC

Đọc thêm:

GRAPHQL

18-3

GraphQL là một Graph Query Language được dành cho API. GraphQL bắt đầu từ ông lớn Facebook, thế nhưng ngay cả những app đơn giản đôi khi vẫn gặp phải trường hợp “nghẽn cổ chai” do sự hạn chế của REST APIs. Và hiện tại nó được duy trì bởi rất nhiều công ty lớn, và mọi cá nhân trên khắp thế giới. GraphQL từ khi ra đời đã gần như thay thế hoàn toàn REST bởi sự hiệu quả, mạnh mẽ và linh hoạt hơn rất nhiều. Thường được dùng để load data từ một server cho client. GraphQL bao gồm 3 điểm đặc trưng bao gồm cho phép client xác định chính xác những gì dữ liệu họ cần, làm cho việc tổng hợp dữ liệu từ nhiều nguồn dễ dàng hơn và nó sử dụng một type system để mô tả dữ liệu.

Vấn đề mà REST đang gặp phải là nó việc phản hồi dữ liệu của REST trả về quá nhiều hoặc là quá ít. Trong cả 2 trường hợp thì hiệu suất của ứng dụng đều bị ảnh hưởng khá nhiều. Giải pháp mà GraphQL đưa ra là cho phép khai báo dữ liệu nơi mà một client có thể xác định chính xác dữ liệu mà mình cần từ một API.

GraphQL có 1 hệ thống riêng dành cho nó được sử dụng để xác định schema của một api. Tất cả type được liệt kê trong một API thì được viết trong schema thì sử dụng GraphQL Schema Definition Language (SDL). Schema này được dùng như là một bản giao dịch giữa client và server để xác định client có thể truy cập dữ liệu như thế nào. Sau đó team frontend có thể mock data để kiểm tra các component, song song đó team back-end cũng chuẩn bị công việc cần thiết cho phía server.

GraphQL sử dụng việc nạp dữ liệu khác với REST. Nó chí có duy nhất 1 single endpont và hoàn toàn phụ thuộc vào client để xác định những dữ liệu cần thiết. Vì thế client phải chỉ ra các trường cần thiết

Trong GraphQL viêc gửi các queries được gọi là mutations. Các mutation này có 3 loại là CREATE, UPDATE và DELETE. Mutation cũng có cú pháp giống như Fetching Data(Query). Nhưng mutation luôn bắt đầu với một từ khóa.

Một yêu cầu quan trọng khác đối với nhiều ứng dụng đó chính là realtime, để có thể kết nối đến máy chủ để có được thông tin về các event ngay lập tức. Trong trường hợp này, GraphQL cung cấp các khái niệm gọi là subscriptions. Khi 1 client subscriptions một event, nó cũng bắt đầu và giữ các kết nối đến server. Bất cứ khi nào sự kiện đó xảy ra, server sẽ đẩy dữ liệu tương ứng đến client.

Đọc thêm:

WEBHOOKS

18-4

Web hook là một cách cực kỳ hữu ích và tương đối dễ dàng, gọn nhẹ trong việc triển khai các phản ứng sự kiện. Các web hook cung cấp một cơ chế trong đó một ứng dụng server-side có thể thông báo cho một ứng dụng phía client-side khi một sự kiện mới (mà ứng dụng client-side có thể quan tâm) đã xảy ra trên máy chủ.

Webhooks đôi khi còn được gọi là “Reverse APIs”. Trong các API, ứng dụng client-side sẽ gọi (tiêu thụ) ứng dụng server-side. Trong khi đó, khi có web hook, phía server-side sẽ gọi web hook (end-point URL được cung cấp bởi ứng dụng client-side), ví dụ: ứng dụng server-side gọi ứng dụng client-side.

Webhooks hoạt động dựa trên khái niệm về phản ứng sự kiện- “event reaction” (đừng gọi cho tôi, tôi sẽ gọi bạn nếu tôi có tin gì mới). Nhờ vậy, ứng dụng client-side sẽ không cần phải liên tục hỏi ứng dụng server-side.

Do đó, thay vì ứng dụng client-side phải liên tục thăm dò ứng dụng server-side để kiểm tra các sự kiện mới, ứng dụng server-side sẽ gọi ứng dụng client-side (bằng cách gọi URL webhook từ client cung cấp) bất cứ khi nào server-side có thông tin gì mới để báo cáo cho client.

SO SÁNH REST, GRAPHQL, WEBHOOKS, AND GRPC

Đối với ứng dụng thì internal bên trong có thể xài gRPC, 1 vài cái integration với hệ thống cũ cùng sử dụng nó nếu được

Public API mình vẫn qua REST vì đa phần nếu các hệ thống bên ngoài và frontend thì Rest vẫn tốt nhất.

Về performance thì theo mấy ngôn ngữ đo được gRPC sẽ tốt hơn khoảng +-20% so với Rest về mặt tốc độ và size payload (message).

Ngoài ra có thể consider dùng Rest + message pack nếu không có nhu cầu chuyển qua gRPC

Restful và gRPC về bản chát là giống nhau, đều là công cụ RPC (remote procedure call).
Chỉ khác nhau cách cài đặt (implement): gRPC sử dụng binary trong đóng gói dữ liệu để truyền thông (protobuf), còn Restf thì tự do, có thể chọn (thường là text-based: xml hoặc json).

Nhờ đó mà gRPC thường có tốc độ cao và độ trễ thấp hơn. Chỉ nên chuyển qua gRPC nếu ứng dụng cần một số yếu tố như tốc độ truyển thông cao và độ trễ thấp, truyển dữ liệu kiểm stream.

Cái giá phải trả là độ phức tạp tăng lên, khó cài đặt (system) và bảo trì hơn nhiều

Còn với GraphQL, hãy xem xét một số tình huống sau:

  • Ở trường đại học có các sinh viên thuộc về các chuyên ngành khác nhau. Giả sử chúng ta cần lấy chi tiết thông tin sinh viên cùng với chi tiết chuyên ngành. Để làm được điều đó phải gọi nhiều request đến server nếu dùng REST.
  • Trong một usecase khác khi client muốn hiển chi tiết khoá học của sinh viên theo mục đích sử dụng khi đó cần phải custom REST api endpoint, với GraphQL ko cần phải custom lại endpoint, client chỉ cần định nghĩa model ở dạng graph.

Vậy GraphQL giúp cho ứng dụng Web API sáng sủa hơn, dễ mở rộng và dễ dàng tương thích ngược mà ko cần phải thay đổi Web API có sẵn.

Và với Webhooks, hãy tưởng tượng một ứng dụng server-side thông báo cho ứng dụng client-side bất cứ khi nào một bình luận mới cho một message cụ thể được đăng lên. Trong trường hợp này, bất cứ khi nào một bình luận mới được đăng lên cơ sở dữ liệu phía server-side, ứng dụng server-side sẽ (sau khi đăng bình luận lên cơ sở dữ liệu) gọi URL webhook ở trên, để client biết vừa có một bình luận mới. Do đó, với việc sử dụng webhooks, server-side có thể thông báo cho client-side về một sự kiện có liên quan (hay một bình luận mới đã được đăng).

Bài viết được tổng hợp từ nhiều nguồn trên internet

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

Xem thêm IT Jobs Developer hấp dẫn trên TopDev

Kỹ năng giao tiếp? Làm thế nào để cải thiện giao tiếp hiệu quả?

kỹ năng giao tiếp
kỹ năng giao tiếp

Kỹ năng giao tiếp là một trong những kỹ năng quan trọng trong xã hội hiện đại. Dù là một sai lầm nhỏ cũng dễ làm bạn bị mất điểm. Đồng thời, khi có sự tương tác tốt sẽ là lợi thế lớn trong việc xây dựng các mối quan hệ. Kỹ năng giao tiếp ngày nay được hầu hết các nhà tuyển dụng đánh giá cao. Vì vậy, bên cạnh kiến thức chuyên môn, kỹ năng giao tiếp đóng một vai trò quan trọng giúp bạn chính phục các nhà tuyển dụng khó tính.

Vậy thế nào là kỹ năng giao tiếp? Nó có những khía cạnh nào nổi bật? Đâu sẽ là những nhân tố trực tiếp cảnh hưởng đến việc phát triển kỹ năng này? Những chia sẻ TopDev dưới bài viết sau đây sẽ giúp bạn cải thiện kỹ năng giao tiếp của mình một cách hiệu quả nhất.

Kỹ năng giao tiếp là gì?

Hiểu một cách đơn giản, kỹ năng giao tiếp là khả năng truyền đạt thông điệp, các tín hiệu có cơ sở, lắng nghe; gửi đi và nhận lại các phản hồi là các thông tin được tri nhận thông qua nền tảng kiến thức riêng của mỗi người.

Quá trình này mô tả sự trao đổi thông tin qua lại giữa chủ thể giao tiếp (người nói)đối tượng giao tiếp (người nghe) nhằm tạo ra sự liên kết chặt chẽ với định hướng mang lại một mục đích giao tiếp nhất định.

Có rất nhiêu yếu tố ảnh hưởng đến cách thức và hiệu quả giao tiếp. Đó có thể là yếu tố tâm lý, những rối loạn về xúc cảm, sự mất bình tĩnh, ngôn từ, các âm thanh nhiễu xung quanh môi trường giao tiếp,… Do vậy, có thể nói kỹ năng giao tiếp có mối liên hệ mật thiết với năng lực nghe-nói, năng lực tiếp nhận; đánh giá phản hồi và cả các khía cạnh cảm xúc cũa người giao tiếp lẫn người tiếp nhận giao tiếp.

Nếu xét dưới góc độ hình thức giao tiếp thì sẽ rất đa dạng. Ví dụ như giao tiếp thông qua ngôn ngữ – lời nói, giao tiếp qua ngôn ngữ viết, giao tiếp qua ánh mắt hay ngôn ngữ hình thể,… Mỗi hình thức giao tiếp được sử dụng ứng với từng đối tượng giao tiếp phù hợp.

Tầm quan trọng của kỹ năng giao tiếp

Kỹ năng giao tiếp là một kỹ năng mềm cực quan trọng trong thời kỳ phát triển mới

kỹ năng giao tiếp
Kỹ năng giao tiếp có vai trò rất quan trọng.

Và có lẽ hiện tại, giao tiếp không gì đơn giản là nói và lắng nghe. Mà nó là cả một nghệ thuật. Bởi lẽ, nó được thiết lập trên nền tảng những quy tắc, nghệ thuật và phong cách ứng xử, cách sự dụng ngôn từ và giọng điệu, cách ứng phó và trình bày kết hợp các quan điểm, ý kiến, góc nhìn,…

Rất nhiều thứ làm nên kỹ năng giao tiếp. Và để phát triển kỹ năng giao tiếp, không còn cách nào khác chính là rèn luyện và trau dồi các kinh nghiệm thông qua trải nghiệm giao tiếp thực tế.

Bạn phải thực sự hiểu rằng giao tiếp là một mắc xích quan trọng giúp xây dựng và nuôi dưỡng các mối quan hệ. Hãy dành thời gian để học hỏi, tăng cường tập luyện để kỹ năng của bạn ngày càng được hoàn thiện. Từ đó, kết quả tương tác và giá trị giao tiếp bạn nhận lại sẽ thật sự có ích.

1. Giao tiếp thúc đẩy hiệu suất công việc và phát triển tiềm năng nhân sự

Môi trường văn hóa công sở nếu thiếu đi kỹ năng giao tiếp sẽ khó có thể phát triển. Sự thăng tiến là điều mà mỗi cá nhân đều mong muốn đạt được. Khi giao tiếp bị giới hạn thì con đường thăng tiến, sự phát triển sẽ gặp những trở ngại. Và đôi khi, bạn sẽ ngã gục trước những khó khăn ấy. 

Ngược lại, nếu sở hữu một năng lực tư duy ngôn ngữ tốt, linh hoạt trong giao tiếp sẽ giúp bạn thành công hơn. Cụ thể giao tiếp hiệu quả giúp bạn khai thác thông tin một cách chuyên sâu, nhanh chóng. Những gì bạn truyền đến các đối tác, khách hàng cũng trở nên thuận lợi và suôn sẻ hơn.  Đồng thời, hiệu suất công việc cũng được gia tăng.

Hơn thế nữa, giao tiếp giúp bạn kết nối tốt hơn với mọi người. Bạn sẽ trở thành một cá nhân truyền tải quan điểm tốt trong một nhóm. Bạn biết cách giúp đỡ cũng như đẩy cho cuộc thảo luận của hội nhóm đi đến trọng tâm, đảm bảo tính khả thi cho định hướng nhiệm vụ.

Chính giao tiếp giúp bạn có sự tương tác tốt hơn với các đồng đội. Từ đó, nhóm của bạn sẽ ngày một hiểu nhau hơn. Và rất có thể sẽ trở thành một hội nhóm tiểm năng trong việc triển khai thực hiện các kế hoạch của tổ chức/doanh nghiệp. Bởi lẽ, kỹ năng giao tiếp cũng là yếu tố giúp gia tăng tính đoàn kết của mỗi cá nhân trong team. Các bạn sẽ hiểu điểm mạnh, điểm yếu để cùng nhau thảo luận đưa ra các chiến lược thực sự phù hợp.

2. Kỹ năng giao tiếp tạo ra nhiều cơ hội thăng tiến 

Để thăng tiến trong sự nghiệp, tất nhiên cần có những chiến lược. Và ngoài các kỹ năng chuyên môn thì kỹ năng giao tiếp là một kỹ năng không thể thiếu. Nếu bạn muốn thăng tiến nhanh, bạn phải là người giao tiếp tốt.

  Những lý do làm kìm hãm sự thăng tiến của bạn

Đơn giản vì bạn là người có tiếng nói. Bạn cần tham gia vào nhiều cuộc trao đổi, các cuộc họp với các đối tác trong và ngoài nước.

kỹ năng giao tiếp
kỹ năng giao tiếp

Đặc biệt kỹ năng giao tiếp không chỉ tác động riêng về phía bạn. Nó còn có ảnh hưởng tích cực đến các đồng nghiệp, cấp dưới,… của bạn. 

Nhờ có kỹ năng giao tiếp, Leader mới thật sự biết cách khai thác thông tin ở nhân viên. Họ biết nắm bắt tâm lý, tùy cá tính đối tượng nhân viên mà có cách ứng xử phù hợp. Từ cơ sở đó, họ đưa ra các phân tích, suy luận về kế hoạch phát triển riêng cho từng nhân viên. Vì giao tiếp là chiếc chìa khóa giúp họ khai thác các thế mạnh và điều một người lãnh đạo cần làm là hiểu họ. Đồng thời, tạo cơ hội để họ phát triển năng lực của riêng mình thông qua các nhiệm vụ ứng với năng lực thật sự của họ.

Kỹ năng giao tiếp là một trong những kỹ năng quan trọng trong xã hội hiện đại. Dù là một sai lầm nhỏ cũng dễ làm bạn bị mất điểm. Những chia sẻ TopDev dưới bài viết sau đây sẽ giúp bạn cải thiện kỹ năng giao tiếp của mình một cách hiệu quả nhất.

Giao tiếp đúng đối tượng – Bước đi đầu trong việc phát triển kỹ năng giao tiếp

Giao tiếp trong môi trường làm việc chịu ảnh hưởng bởi nhiều rào cản như: ngôn ngữ, tuổi tác, giới tính, kinh nghiệm làm việc, thứ bậc xã hội,…

Mỗi rào cản ứng với từng đối tượng khác nhau. Do đó, buộc chúng ta phải có những cách thức khác nhau. 

Đây là điều rất quan trọng . Vì nó giúp xác định những cách ứng xử phù hợp; giúp làm tăng hiệu quả giao tiếp. Hãy nhớ rằng để có một sự phản hồi tốt thì trước hết, bạn phải là một người giao tiếp đúng đối tượng.

Để giúp xác định đối tượng bạn muốn giao tiếp, bạn có thể đặt ra những câu hỏi như sau:

–         Người đó là ai? (Là sếp, là nhân viên hay đồng nghiệp của bạn?)

–         Người đó đến từ đâu/như thế nào?

–         Điều gì mà người đó đang gặp phải?

1. Giao tiếp với cấp trên của bạn

Đối với sếp để tạo cuộc thoại hiệu quả, bạn nên giải thích; trình bày thông tin một cách rõ ràng để nhận được sự đồng ý, chấp nhận về một vấn đề nào đó. Không nên trình bày quá dài dòng. Sếp thường không thích sự dàn trải. Họ sẽ ấn tượng với những nhân viên nói ít mà hiểu nhiều. 

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

2. Giao tiếp với cấp dưới của bạn

Đối với cấp dưới, bản thân họ sẽ cảm thấy ngại và có khoảng cách với bạn. Họ thường ít khi bày tỏ những suy nghĩ của mình. Do tính chất công việc mà bạn cần phải phân công nhiệm vụ cho các thành viên một cách nhanh chóng vì thế tạo ra những ngõ cụt. Thậm chí là đứt đoạn trong giao tiếp. 

Họ chỉ dừng lại ở mức thụ động. Họ chỉ nghe theo và làm mà thiếu tính tương tác, đó là nguy cơ tạo ra những sai sót. Vì vậy, đối với cấp dưới thì bạn phải kiên nhẫn, chịu khó giao tiếp với họ. Từng câu chữ cần truyền tải một cách rõ ràng, task cụ thể phù hợp với khả năng.

3. Giao tiếp với đồng nghiệp cùng cấp bậc với bạn

Việc giao tiếp với đồng nghiệp sẽ rất thuận lợi nếu cả hai có sự tương tác và chia sẻ về tương đồng sở thích hoặc cùng lĩnh vực chuyên môn. Ví dụ là đối với một ông senior về code, và một ông senior về BA. Lúc này, giao tiếp sẽ hiệu quả vì cả hai có cùng kiến thức nền nên sẽ dễ dàng thảo luận và đề ra phương án mới cho việc tuyen dung it hay freelancer it. Tuy nhiên xung đột giao tiếp vẫn có thể xảy ra nếu cái tôi của một trong hai quá lớn.

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

Nắm bắt được “cái bẫy” giao tiếp

“Bẫy” giao tiếp được hiểu là những tình huống bạn có thể mắc phải do sự giới hạn về kiến thức và nội dung giao tiếp. Hiểu và nhận biết những bẫy giao tiếp sẽ giúp bạn giao tiếp hiệu quả hơn.

kỹ năng giao tiếp
kỹ năng giao tiếp

Không với biết: Đây là cách nói được xem là chém gió hay múa rìu qua mắt thợ, nói như kiểu bạn thật sự am hiểu về một vấn đề nào đó quá tinh tường trong khi bạn rỗng tuếch.

Biết với không: Trường hợp này bị lạm dụng khá nhiều. Đây là trường hợp bạn cảm thấy mệt mỏi khi phải giải thích cho người chưa hiểu vấn đề. Vì vậy bạn chọn cách chia sẻ với người đã biết vấn đề đó như mình; hoặc cố tình hiểu sang một vấn đề khác. 

Không với không: Đúng thật như kiểu là thầy bói xem voi. Đây cũng là trường hợp đẩy quá trình giao tiếp vào ngõ cụt. Người nói và người nghe đều không biết vấn đề mình đang trao đổi.

Biết với biết: Đây được xem là hình thức giao tiếp hiệu quả nhất vì cả người truyền tải lẫn người tiếp nhận thông điệp đều hiểu vấn đề đang được đề cập đến. Từ đó, họ có thể trao đổi, thỏa hiệp và đi đến những thống nhất chung. Tuy nhiên, tại sao vẫn xếp nó vào “bẫy giao tiếp’. Điều này là điểm hạn chế, Bởi nếu một cá nhân quá phô trương kiến thức của mình, xem mình là ”bác học” để giải lý với người khác thì điều này lại tạo ra tác dụng ngược. Và tất nhiên, dễ khiến hiệu quả giao tiếp bị giảm xuống hoặc thậm chí là mất đi.

Những lưu ý giúp giao tiếp đạt hiệu quả cao

Giao tiếp hiệu quả không hề đơn giản. Và có nhiều người phải thực hiện nhiều phương pháp để thay đổi khả năng giao tiếp của mình. Vậy phải làm gì để giao tiếp hiệu quả?

  5 lưu ý để viết đánh giá hiệu suất của bạn

1. Truyền tải đầy đủ, dễ hiểu và tránh dài dòng

Cách diễn đạt, trình bày với quá nhiều thuật ngữ chuyên ngành khó hiểu tạo ra sự khó nắm bắt. Bạn nên cố gắng giao tiếp ngắn gọn, trình bày cụ thể, rõ ràng. 

Mặc khác, có thể bạn đang gặp vấn khác như là nói quá ít vì thiếu từ ngữ để diễn đạt; hoặc quá lộn xộn, dài dòng do thiếu sự chuẩn bị; hoặc là sử dụng từ ngữ không phù hợp, lạm dụng quá nhiều từ có tính “thô tục” – vì cho rằng nó gây cười hoặc tạo điểm nhấn.

Lời khuyên nào cho vấn đề này: Chuẩn bị trước những gì bạn cần nói; luyện tập ngữ điệu và cách nói sao cho phù hợp. Bạn cần phải nói rõ ràng, chính xác trước khi luyện tập cách giao tiếp hay và chuyên nghiệp.

2. Học cách lắng nghe

Việc lắng nghe đôi rất khó nắm bắt, lắng nghe không dừng lại ở việc nghe đơn thuần. Mà nó đi kèm với sự tri nhận về thông tin và bắt đầu phân tích nó. Và việc lắng nghe một ai đó lại càng trở nên khó khăn hơn. Bởi lẽ, nhiều đồng nghiệp, thậm chí sếp của chúng ta đôi khi lúc diễn đạt vấn đề không rõ ràng, dẫn đến chúng ta hiểu không đầy đủ, hoặc hiểu sai lệch vấn đề.

Xem thêm các việc làm

Khả năng lắng nghe còn chịu sự chi phối về thời lượng sử dụng. Vì vậy, nếu một trong hai hoặc một vài người trong một nhóm người bị xao nhãng thì hiệu quả giao tiếp bị ảnh hưởng đáng kể và không đạt hiệu quả cao như mong đợi ban đầu. 

Vậy làm thế nào để lắng nghe tốt? Đúng là câu hỏi không dễ trả lời. Trước tiên là bạn phải bỏ thời gian tìm hiểu chủ đề, nội dung mình được nghe. Ngoài ra, trong các buổi nói chuyện đông người, hãy chịu khó tập trung. Tránh xa các yếu tố có thể chi phối bạn như: điện thoại, tin nhắn, email, hoặc là nói chuyện riêng với người khác.

3. Khả năng tương tác trực tiếp thông qua sự phản hồi

Điều mấu chốt của một quá trình giao tiếp được đánh giá là hiệu quả tức là khả năng tương tác thông qua các phản hồi trực tiếp. Sự phản hồi có thể là những suy nghĩ, góc nhìn của người nghe về cách người nói trình bày; chia sẻ thông tin hay thậm chí là đánh giá về nội dung thông tin mà người nói đang truyền tải. 

Một biểu hiện khác của sự phản hồi chính là việc đặt câu hỏi. nó thể hiện người nghe thật sự lắng nghe và đã theo dõi; tiếp nhận thông điệp và có những phân tích riêng từ đó có những thắc mắc cần được thảo luận, làm rõ. 

Hãy nhớ rằng nếu ở vai trò là người nghe, khi bạn không nghe rõ, thì hãy hỏi để làm rõ. Đừng xấu hổ và giả vờ hiểu về một vấn đề nào đó. Còn ngược lại, nếu bạn ở vai trò của người nói, nếu bạn có câu hỏi, chưa trả lời được, thì hãy khéo léo trả lời là: “Tôi sẽ tìm hiểu, và trả lời lại sau, vào ngày nào đó.” Đừng mãi loay hoay, suy đoán và nói lung tung, những điều mà bạn không biết.

Nghệ thuật giao tiếp từ kỹ năng giao tiếp chuyên nghiệp

TopDev sẽ chia sẻ với các bạn về những tips cụ thể giúp bạn thiết lập một nghệ thuật giao tiếp cho riêng mình. Tất nhiên, nghệ thuật giao tiếp sẽ được thiết lập trên nền tảng phát triển kỹ năng giao tiếp chuyên nghiệp.

1. Tính rõ ràng, dễ hiểu

Không một cuộc giao tiếp nào hiệu quả nếu cách diễn đạt lủng củng, không rõ ràng. Nó thể hiện bạn chưa đủ bản lĩnh và tự tin trong cuộc giao tiếp; vừa cho thấy sự non nớt trong cách phát ngôn. Hãy cố gắng luyện tập giao tiếp rõ ràng. Có thể bạn không cần nói quá nhanh, hãy nói từ tốn và chậm rãi. Từng bước nâng trình bằng những từ/ngữ có số lượng ký tự dài hơn kết hợp với việc kết hợp làn hơi và nối chữ. 

Hạn chế tối đa các từ ngữ như “à, ừm” vì nó thể hiện sự lúng túng, không nhất quán trong lời nói. Khi thực hiện cuộc giao tiếp, hãy nói dứt khoác, ngắt nhịp hợp lý để kiểm soát tốt ý nghĩa của câu nói; không vội vàng cũng không quá chậm rãi. Có thể, người nghe sẽ thấy thoải mái khi lắng nghe những điều mà bạn chia sẻ. 

Ngôn từ, giọng nói khác nhau, tông giọng và cách dẫn dắt câu chuyện giao tiếp sao cho nội dung không bị gò bó mà phải đảm bảo tính mạch lạc, logic và dễ hiểu nhất. Đôi khi, không nên sử dụng các ngôn từ quá khoa học chuyên ngành hay có tính chất quá trang trọng trong các tình huống bình thường. Điều này sẽ khiến giá trị của việc ứng biến giao tiếp bị đánh giá thấp hơn.

Tùy trường hợp mà kỹ năng giao tiếp của bạn được bộc lô. Phân tích mới thấy, cả ngôn ngữ, âm sắc lời nói, ngữ pháp trong câu phát ngôn và cách lựa chọn cảm xúc để truyền tại đã đủ mô tà một nghệ thuật giao tiếp hiệu quả rồi.

2. Không “thùng rỗng kêu to”

Giao tiếp chi phối cuộc thoại và giúp nó duy trì một giới hạn nhất định. Tuy nhiên, bạn không nên dùng giao tiếp để nói khoác cho những kiến thức của mình. Đừng nói quá nhiều. “Thao thao bất tuyệt” không khiến cuộc giao tiếp trở nên sôi nổi hơn. Chính điều đó sẽ khiến cho chất lượng cuộc giao tiếp ngày càng đi xuống. 

Nghệ thuật giao tiếp giúp nâng chất lượng cuộc giao tiếp. Và việc của bạn cần làm là kéo dài cuộc giao tiếp. Sự tương tác qua lại giữa 2 người hoặc một cá nhân với nhiều đối tượng. Giao tiếp phát triển ở một mức cao hơn khi những kiến thức được chia sẻ qua lại. Họ cùng có một mối quan tâm chung cần giải quyết. Nếu bạn chỉ mãi “thùng rỗng kêu to” với các phát ngôn của mình, cuộc giao tiếp ấy sẽ sớm đi vào ngõ cụt; thậm chí bạn đang thể hiện mình là người thiếu tinh tế trong vấn đề giao tiếp.

3. Tương đồng về nền tảng kiến thức 

Như đã đề cập từ trước, mục đích của cuộc giao tiếp chính là truyền tải thông tin, trao đổi, chia sẻ các tín hiệu về dự liệu trên cơ sở chung một nền tảng kiến thức nền. Sẽ khó khăn biết bao nhiêu nếu như bạn đang giao tiếp với một đối tượng không “match” về thông tin. Do vậy, nếu là một người hiểu về nghệ thuật giao tiếp, bạn hãy chủ động khai thác các yếu tố thông tin tương đồng với người tiếp nhận giao tiếp của bạn.

Nếu bạn tìm được một đối tượng biết lắng nghe, chia sẻ các suy nghĩ chung về giá trị kiến thức, thì đó quả là một sự may mắn. Giao tiếp hiệu quả phải đến từ hai phía, bạn và người đối diện cần có sự lắng nghe và tôn trọng lẫn nhau để cuộc giao tiếp trở nên thú vị.

4. Sự lắng nghe

Ai cũng tranh giành các quyền lợi về phát ngôn, ít ai biết lắng nghe thấu hiểu. Dường như đó trở thành xu hướng chung của nhiều người, đặc biệt là người trẻ. Sự hấp tấp trong giao tiếp, khiến mọi thứ trở nên vội vàng. Họ chỉ quan tâm đến việc phô bày qua lời nói; chứ chưa tôn trọng ý kiến hoặc lắng nghe suy nghĩ, quan điểm của người khác. Họ quên rằng cuộc hội thoại này không thể hiệu quả nếu chỉ mỗi mình họ tự độc thoại nội tâm. Thật sự, việc lắng nghe và chia sẻ là cách bạn đang tôn trong đối phương; tạo cơ hội cho cuộc giao tiếp trở nên lâu dài và hấp dẫn.

Tại sao bạn không dừng lại đôi chút để lắng nghe đối phương họ nói gì. Biết đâu, ở họ có một chút cảm xúc tích cực, lời nói, ngôn từ, giọng điệu; cách họ dẫn dắt câu chuyện là thứ bạn nên học tập.

Giao tiếp không phải cuộc tranh luận mà cứ tranh giành quyền nói. Bạn sẽ nhận ra các bài học, các giá trị hay nếu bạn thật sự quan tâm đến những gì đối phương chia sẻ. Có lắng nghe, bạn mới biết phản hồi phù hợp, đúng chủ đề.

Nếu gặp phải một vấn để nào đó, việc lắng nghe giúp bạn mô hình hóa được quá trình và bạn sẽ biết đâu là điểm mấu chốt. Từ đó, bạn biết cách góp ý và giúp đỡ đối phương thông qua các giải pháp cụ thể. Kỹ năng giao tiếp tuy dễ mà khó. Và nếu không biết lắng nghe, bạn chỉ đang làm tốn thời gian cho việc phát ngôn vô ích mà thôi.

5. Kết hợp ngôn ngữ hình thể 

Một điều bạn đáng lưu tâm để đạt hiệu quả nghệ thuật giao tiếp chính là tính trung thực khi giao tiếp.

Hãy nói đúng suy nghĩ của mình, cuộc hội thoại sẽ cởi mở hơn; được duy trì và phát triển xa hơn. Nếu cảm xúc trong bạn đang không ổn, hãy cho đối phương biết điều đó. Nếu không muốn tiếp tục chia sẻ, bạn nên nói với họ để dừng lại cuộc thoại. Không nên duy trì khi trạng thái có sự ảnh hưởng tiêu cực. Vì nó là mấu chốt tạo ra những cuộc tranh luận dữ dội. Và quả thật, điều này thật tệ. Đồng thời, khi chia sẻ điều gì, bạn phải thật khéo léo để không làm phật ý đối phương. Tất cả đều biểu hiện cho nghệ thuật giao tiếp hiệu quả nhất.

Ngoài ra, một nghệ thuật giao tiếp khác bạn cần biết chính là ngôn ngữ cơ thể. Không nhất thiết thông qua lời nói. Những cử chỉ nhỏ qua ánh mắt, dáng đứng, nụ cười,… đều có những ý nghia giao tiếp nhất định. Đôi khi có còn hiệu quả truyền thông điệp cao hơn cả lời nói trong nhiều trường hợp. Âm sắc, tông giọng của bạn có thể thay đổi theo cách bạn cảm nhận về một khía cạnh vấn đề. Tất cả những biểu hiện ấy đều bộc lộ ra các tín hiệu về thông điệp. Ngôn ngữ cơ thể rất đa dạng và nó cho thấy sự thú vị hơn, tương tác đa chiều hơn. Đồng thời, nó cũng giúp cuộc hội thoại giao tiếp của bạn không bị nhàm chán nữa.

Lời kết

Kỹ năng giao tiếp thật sự là một kỹ năng quan trọng. Dù ở trong bất cứ lịnh vực, ngành nghề nào, bạn cũng cần kỹ năng giao tiếp. Hãy rèn luyện và phát triển kỹ năng của bản thân để gia tăng các cơ hội phát triển cao hơn trong nghề nghiệp. TopDev hi vọng với bài viết này, các bạn sẽ biết được những thông tin bổ ích; giúp cho việc cải thiện giao tiếp tốt hơn, tự tin và hiệu quả hơn.                                    

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

Xem thêm việc làm developer trên TopDev

Hướng dẫn xử lý lỗi 502 Bad Gateway Nginx

nginx là gì

NGINX Error 502 Bad Gateway là một lỗi phổ biến ở người dùng trang web. Nguyên nhân nào khiến website của bạn gặp lỗi 502 Bad Gateway Nginx? Cùng chúng tôi theo dõi bài viết dưới đây để tìm hiểu nguyên nhân và cách fix nhanh lỗi này bạn nhé!

Lỗi 502 Bad Gateway Nginx là gì?

Lỗi 502 Bad Gateway Nginx là thông báo lỗi cho biết máy chủ đang nhận lỗi từ máy chủ khác và không thể kết nối với PHP-FPM hoặc PHP-FPM không phản hồi.

Để đi sâu vào nguyên nhân và cách xử lý lỗi 502 Bad Gateway Nginx, bạn cần hiểu 502 Bad Gateway là gì? Click vào bài viết để tìm hiểu từ A-Z về lỗi phổ biến này nhé!

Nguyên nhân gây lỗi 502 Bad Gateway Nginx

1. PHP-FPM không chạy

Nếu PHP-FPM không chạy, NGINX sẽ trả về lỗi 502 cho bất kỳ yêu cầu nào nhằm truy cập ứng dụng PHP. Nếu bạn nhìn thấy 502s, trước tiên hãy kiểm tra để xác nhận rằng PHP-FPM đang chạy. Ví dụ: trên máy chủ Linux, bạn có thể sử dụng lệnh ps như lệnh này để tìm kiếm các quy trình PHP-FPM đang chạy:

sudo ps aux | grep 'php'

2. PHP-FPM đã hết thời gian chờ

Nếu ứng dụng của bạn mất quá nhiều thời gian để phản hồi, người dùng của bạn sẽ gặp phải lỗi hết thời gian chờ. Nếu thời gian chờ của PHP-FPM — request_termina_timeout của config (và mặc định là 20 giây) – ít hơn thời gian chờ của NGINX (mặc định là 60 giây), NGINX sẽ phản hồi với lỗi 502. Error log của NGINX hiển thị bên dưới chỉ ra rằng upstream process — là PHP-FPM — đã đóng kết nối trước khi gửi phản hồi hợp lệ. Nói cách khác, đây là error logs mà chúng tôi thấy khi PHP-FPM hết thời gian:

2020/02/20 17:17:12 [error] 3059#3059: *29 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php/mypool.sock:", host: "localhost"

Bạn có thể tăng cài đặt thời gian chờ của PHP-FPM bằng cách chỉnh sửa tệp cấu hình (file config), nhưng điều này có thể gây ra một vấn đề khác: NGINX có thể hết thời gian trước khi nhận được phản hồi từ PHP-FPM. Thời gian chờ NGINX mặc định là 60 giây; nếu bạn đã tăng thời gian chờ PHP-FPM của mình trên 60 giây, NGINX sẽ trả về lỗi 504 Gateway Timeout nếu ứng dụng PHP của bạn không phản hồi kịp thời. Bạn có thể ngăn chặn điều này bằng cách tăng thời gian chờ NGINX của mình. Trong ví dụ bên dưới, chúng tôi đã tăng giá trị thời gian chờ lên 90 giây bằng cách thêm mục fastcgi_read_timeout vào block http của /etc/nginx/nginx.conf:

http { 
...
    fastcgi_buffers 8 16k;
    fastcgi_buffer_size 32k;
    fastcgi_connect_timeout 90;
    fastcgi_send_timeout 90;
    fastcgi_read_timeout 90;
}

3. NGINX không thể giao tiếp với PHP-FPM

Nếu NGINX không thể giao tiếp với PHP-FPM vì bất kỳ lý do nào trong số này, nó sẽ phản hồi với lỗi 502, lưu ý điều này trong nhật ký truy cập của nó (/var/log/nginx/access.log):

127.0.0.1 - - [31/Jan/2020:18:30:55 +0000] "GET / HTTP/1.1" 502 182 "-" "curl/7.58.0"

NGINX’s access log không giải thích nguyên nhân gây ra lỗi 502, nhưng bạn có thể tham khảo error log của nó (/var/log/nginx/error.log) để tìm hiểu thêm. Ví dụ: đây là một mục nhập tương ứng trong nhật ký lỗi NGINX cho thấy rằng nguyên nhân của lỗi 502 là do socket không tồn tại, có thể do PHP-FPM không chạy.

2020/01/31 18:30:55 [crit] 13617#13617: *557 connect() to unix:/run/php/php7.2-fpm.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.2-fpm.sock:", host: "localhost"

Cách fix nhanh lỗi 502 Bad Gateway Nginx

  1. Mở file cấu hình Nginx:
nano /etc/nginx/nginx.conf

2. Thêm đoạn cấu hình sau vào trong block http { }

http {
    ...
    fastcgi_buffers         8 16k;
    fastcgi_buffer_size     32k;
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout    300;
    fastcgi_read_timeout    300;

    include /etc/nginx/conf.d/*.conf;
}

Nếu muốn tìm hiểu chuyên sâu hơn về các cấu hình trên, các bạn có về vào trang docs của Nginx với các thông số của module ngx_http_fastcgi_module rất cụ thể.

3. Khởi động lại nginx, php-fpm:

service nginx restart
service php-fpm restart

Trên đây là hướng dẫn cách khắc phục 502 Bad Gateway Nginx dễ dàng mà ai cũng áp dụng được, hi vọng bài viết của đội ngũ Top Dev đã giúp bạn fix thành công lỗi này. Theo dõi chúng tôi để cập nhật nhiều hơn kiến thức về công nghệ mỗi ngày.

3 tips làm việc với JavaScript giúp bạn tiết kiệm thời gian

javascript tip
3 tips làm việc với JavaScript giúp bạn tiết kiệm thời gian

Tác giả: Gaël Thomas

Để làm việc hiệu quả hơn cũng như tối ưu được thời gian làm việc cho một task, biết thêm một số tips hay ho sẽ giúp ích rất nhiều cho bạn. Dưới đây tôi sẽ giới thiệu với các dev một số JavaScript tip khi làm việc bằng ngôn ngữ JavaScript để tiết kiệm thời gian và công sức.

làm việc với javascript
JavaScript tip giúp công việc trở nên nhẹ nhàng hơn

1. Cấu trúc đối tượng

Đây là một JavaScript tip phổ biến hiện tại. Destructuring là một tính năng đã được giới thiệu trong ES6. Đó là một trong những tính năng bạn sẽ sử dụng hàng ngày khi bạn biết cách. Nó giúp bạn giải quyết ba vấn đề chính:

Lặp lại: Mỗi khi bạn muốn trích xuất một thuộc tính đối tượng và tạo một biến mới, bạn sẽ tạo một dòng mới.

const user = {
  firstName: "John",
  lastName: "Doe",
  password: "123",
};

// Wow... should we display
// John's password like that?

const firstName = user.firstName;
const lastName = user.lastName;
const password = user.password;

Accessibility – Khả năng tiếp cận: Mỗi lần bạn muốn truy cập một thuộc tính đối tượng, bạn nên viết đường dẫn đến nó (ví dụ: user.firstName, user.family.sister)

  10 câu hỏi javascript để nâng cao trình độ
  12 tips hay cho JavaScript

Usage – Sử dụng. Ví dụ như khi bạn tạo một hàm mới và bạn chỉ đang làm việc với một thuộc tính của một đối tượng.

Xem thêm các việc làm tuyển dụng javascript tại TopDev

Bây giờ bạn đã thấy ba vấn đề này với các đối tượng là gì, bạn nghĩ bạn có thể giải quyết chúng như thế nào? Hãy sử dụng các JavaScript tip dưới đây:

1.1. Cách giải quyết vấn đề lặp lại

const user = {
  firstName: "John",
  lastName: "Doe",
  password: "123",
};

const { firstName, lastName, password } = user;

console.log(firstName, lastName, password);
// Output: 'John', 'Doe', '123'

Destructuring là quá trình trích xuất một thuộc tính từ một đối tượng bằng key của nó. Bằng cách lấy một key hiện có trong đối tượng, sau đó đặt nó giữa hai dấu ngoặc ( { firstName })

Nếu bạn muốn hủy cấu trúc một đối tượng, bạn phải luôn sử dụng một khóa hiện có. Nếu không, nó sẽ không hoạt động.

Xem thêm các việc làm KMS Technology tuyển dụng hấp dẫn tại TopDev

1.2. Cách giải quyết Accessibility

const user = {
  firstName: "John",
  lastName: "Doe",
  password: "123",
  family: {
    sister: {
      firstName: "Maria",
    },
  },
};

// We access to the nested object `sister`
// and we extract the `firstName` property
const { firstName } = user.family.sister;

console.log(firstName);
// Output: 'Maria'

Khi làm việc với các đối tượng lồng ghép vào nhau, nó có thể bị lặp lại và lãng phí nhiều thời gian khi truy cập cùng một thuộc tính nhiều lần.

Sử dụng cấu trúc destructuring, chỉ trong một dòng, bạn có thể giảm đường dẫn thuộc tính thành một biến.

Xem thêm các việc làm KMS tuyển dụng

1.3. Cách giải quyết Usage

Nếu bạn biết React, có lẽ bạn đã quen thuộc với vấn đề này.

function getUserFirstName({ firstName }) {
  return firstName;
}

const user = {
  firstName: "John",
  lastName: "Doe",
  password: "123",
};

console.log(getUserFirstName(user));
// Output: 'John'

Trong ví dụ trên, chúng ta có một getUserFirstName hàm và biết rằng nó sẽ chỉ sử dụng một thuộc tính của đối tượng là firstName.

Thay vì truyền toàn bộ đối tượng hoặc tạo một biến mới, chúng ta có thể destructure các tham số hàm của đối tượng.

>>> Xem thêm Vượt qua các bài phỏng vấn Javascript

2. Cách hợp nhất các đối tượng trong ES6

Trong lập trình, bạn thường phải giải quyết các vấn đề với cấu trúc dữ liệu. Nhờ toán tử spread được giới thiệu trong ES6, các thao tác đối tượng và mảng đơn giản hơn.

const user = {
  firstName: "John",
  lastName: "Doe",
  password: "123",
};

const userJob = {
  jobName: "Developer",
  jobCountry: "France",
  jobTimePerWeekInHour: "35",
};

Hãy tưởng tượng rằng chúng ta có hai đối tượng:

  • User: Một đối tượng xác định thông tin chung về người dùng.
  • UserJob: Một đối tượng xác định thông tin công việc của người dùng.

Chúng ta muốn tạo một đối tượng chỉ chứa các thuộc tính của hai đối tượng này.

const user = {
  firstName: "John",
  lastName: "Doe",
  password: "123",
};

const userJob = {
  jobName: "Developer",
  jobCountry: "France",
  jobTimePerWeekInHour: "35",
};

const myNewUserObject = {
  ...user,
  ...userJob,
};

console.log(myNewUserObject);
// Output:
//{
//  firstName: 'John',
//  lastName: 'Doe',
//  password: '123',
//  jobName: 'Developer',
//  jobCountry: 'France',
//  jobTimePerWeekInHour: '35'
//}

Sử dụng toán tử spread ( ...), chúng ta có thể trích xuất tất cả các thuộc tính của đối tượng này sang đối tượng khác.

const user = {
  firstName: "John",
  lastName: "Doe",
  password: "123",
};

const myNewUserObject = {
  ...user,
  // We extract:
  // - firstName
  // - lastName
  // - password
  // and send them to
  // a new object `{}`
};

2.1. Cách Merge Arrays – hợp nhất mảng

const girlNames = ["Jessica", "Emma", "Amandine"];
const boyNames = ["John", "Terry", "Alexandre"];

const namesWithSpreadSyntax = [...girlNames, ...boyNames];

console.log(namesWithSpreadSyntax);
// Output: ['Jessica', 'Emma', 'Amandine', 'John', 'Terry', 'Alexandre']

Giống như các đối tượng, toán tử spread ( ...) trích xuất tất cả các phần tử từ mảng này sang mảng khác.

const girlNames = ["Jessica", "Emma", "Amandine"];

const newNewArray = [
  ...girlNames,
  // We extract:
  // - 'Jessica'
  // - 'Emma'
  // - 'Amandine'
  // and send them to
  // a new array `[]`
];

2.2. Cách loại bỏ Array Duplicates

Vì mảng là danh sách nên có thể có nhiều mục cùng giá trị. Nếu bạn muốn loại bỏ các bản sao trong mảng của mình, bạn có thể làm theo một trong các ví dụ dưới đây.

Một trong số đó sẽ chỉ có một dòng nhờ ES6, nhưng tôi để ví dụ “cũ” trong đó để bạn có thể so sánh.

tip for javascript
Tìm hiểu thêm các tip JavaScript thông qua bài viết này

Xem thêm các việc làm tuyển dụng Tester HCM hấp dẫn tại TopDev

2.2.1. Cách loại bỏ các bản sao mảng “theo cách cũ”

const animals = ["owl", "frog", "canary", "duck", "duck", "goose", "owl"];

const uniqueAnimalsWithFilter = animals.filter(
  // Parameters example: 'owl', 0, ['owl', 'frog', 'canary', 'duck', 'duck', 'goose', 'owl']
  (animal, index, array) => array.indexOf(animal) == index
);

console.log(uniqueAnimalsWithSet);
// Output: ['owl', 'frog', 'canary', 'duck', 'goose']

Trong ví dụ trên, tôi muốn clean mảng animals bằng cách loại bỏ tất cả các bản sao.

Chúng ta có thể làm điều đó bằng cách sử dụng hàm filter với indexOf bên trong nó.

Các filter chức năng sẽ đưa tất cả các yếu tố của mảng animalsanimals.filter). Sau đó, đối với mỗi lần xuất hiện, nó cung cấp:

  • giá trị hiện tại ( ví dụ duck 🙂
  • chỉ mục ( ví dụ: 0)
  • mảng ban đầu ( ví dụ: các animalsmảng => ['owl', 'frog', 'canary', 'duck', 'duck', 'goose', 'owl'])

Tôi sẽ áp dụng indexOf trên mảng ban đầu cho mỗi lần xuất hiện và đưa ra dưới dạng một tham số là biến animal (giá trị hiện tại).

indexOf sẽ trả về chỉ mục đầu tiên của giá trị hiện tại (ví dụ: đối với ‘cú’, chỉ mục là 0).

Sau đó, bên trong bộ lọc, tôi so sánh giá trị của indexOf với chỉ mục hiện tại. Nếu nó giống nhau, chúng tôi trả lại true khác false.

filter sẽ tạo một mảng mới chỉ với các phần tử có giá trị trả về true.

Vì vậy, trong trường hợp của chúng tôi: ['owl', 'frog', 'canary', 'duck', 'goose'].

2.2.2. Cách loại bỏ các bản sao mảng “theo cách mới”

Cách cũ cũng thú vị nhưng nó dài và hơi khó. Nếu muốn bạn có thể thực hiện bằng cách mới như sau:

const animals = ["owl", "frog", "canary", "duck", "duck", "goose", "owl"];

const uniqueAnimalsWithSet = [...new Set(animals)];

console.log(uniqueAnimalsWithSet);
// Output: ['owl', 'frog', 'canary', 'duck', 'goose']

Hãy tách các bước khác nhau ra:

// 1
const animals = ["owl", "frog", "canary", "duck", "duck", "goose", "owl"];

// 2
const animalsSet = new Set(animals);

console.log(animalsSet);
// Output: Set { 'owl', 'frog', 'canary', 'duck', 'goose' }

// 3
const uniqueAnimalsWithSet = [...animalsSet];

console.log(uniqueAnimalsWithSet);
// Output: ['owl', 'frog', 'canary', 'duck', 'goose']

Tôi có một mảng animal và muốn chuyển đổi nó thành một Set, là một loại đối tượng đặc biệt trong ES6.

Điều khác biệt ở nó là nó cho phép bạn tạo ra một bộ sưu tập các giá trị độc đáo.

Lưu ý: Set là một tập hợp các giá trị duy nhất, nhưng nó không phải là một Array.

Khi chúng ta có Set đối tượng của mình với các giá trị duy nhất, chúng ta cần chuyển đổi nó trở lại một mảng.

Để làm điều đó, tôi sử dụng các toán tử spread để phá hủy nó và gửi tất cả các thuộc tính sang một thuộc tính mới Array.

Vì Set đối tượng có các thuộc tính duy nhất nên mảng mới của chúng ta cũng sẽ chỉ có các giá trị duy nhất.

  3 lỗi javascript thường mắc phải làm ảnh hưởng perfomance

3. Cách sử dụng toán tử bậc ba

Bạn đã nghe nói về cách viết các điều kiện nhỏ chỉ trong một dòng chưa? Hãy làm quen với cách này bằng một JavaScript tip.

Nếu không, đã đến lúc loại bỏ nhiều khối if và else chuyển chúng thành các phép toán bậc ba nhỏ.

Hãy xem một ví dụ với console.log để bắt đầu. Ý tưởng là kiểm tra giá trị của một biến và hiển thị có điều kiện một đầu ra.

const colour = "blue";

if (colour === "blue") {
  console.log(`It's blue!`);
} else {
  console.log(`It's not blue!`);
}

Ví dụ này là một trường hợp điển hình trong đó bạn có thể sử dụng toán tử bậc ba để giảm 5 if và else các dòng này xuống chỉ còn một!

Một dòng để tổng hợp tất cả!

const colour = "blue";

colour === "blue" ? console.log(`It's blue!`) : console.log(`It's not blue!`);
// [condition] ? [if] : [else]

Toán tử bậc ba thay thế if và else cho các điều kiện nhỏ.

Lưu ý: Không nên tạo điều kiện phức tạp với toán tử bậc ba vì nó có thể làm giảm khả năng đọc.

Dưới đây là một ví dụ khác sử dụng toán tử bậc ba, nhưng lần này là return trong một hàm.

function sayHelloToAnne(name) {
  return name === "Anne" ? "Hello, Anne!" : "It's not Anne!";
}

console.log(sayHelloToAnne("Anne"));
// Output: 'Hello, Anne!'

console.log(sayHelloToAnne("Gael"));
// Output: "It's not Anne!"

Hi vọng một số tip hay ho trên đây có thể giúp bạn coding hiệu quả hơn với ngôn ngữ JavaScript. Happy Coding!

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

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

Xem thêm việc làm tuyển dụng lập trình viên hấp dẫn tại TopDev

Framework và Library khác nhau thế nào?

Framework và Library khác nhau thế nào?

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

Để trả lời cho câu hỏi này, chúng ta cùng tìm hiểu qua một số khái niệm về Framework và Library được nhiều người thống nhất ý kiến.

1. Library là gì?

Là một tập hợp các chức năng (functions), các lớp (class) được viết sẳn để có thể tái sử dụng. Mỗi function hoặc class phục vụ cho một công việc cụ thể nào đó.
Ví dụ:
– JQuery là một library, nó cung cấp các chức năng giúp chúng ta thao tác với DOM.
– LinqJS là một library, nó cung cấp các chức năng giúp chúng ta truy vấn (query) dữ liệu dễ dàng, đơn giản và nhanh hơn.

2. Framework là gì?

Là một tập hợp các Library đã được đóng gói để hỗ trợ phát triển ứng dụng dựa trên framework đó. Đồng thời, Framework cung cấp các nguyên tắc, cấu trúc của ứng dụng mà chúng ta phải tuân thủ theo nó.

Ví dụ 1:
 Angular là một framework. Mục đích Angular framework là giúp cho người dùng xây dựng được các ứng dụng website dạng single page một cách dễ dàng và nhanh chóng. Nó tập trung vào việc phát triển font-end cho ứng dụng web. Angular cung cấp sẵn cho bạn các directives, services, data-biding, filters,… Để sử dụng Angular, chúng ta phải tuân thủ theo mô hình và cách hoạt động của nó. Chẳng hạn, một page sẽ có phần html gọi là template, phần xử lý gọi là controller, các quy định về việc sử dụng $scope, isolate-scope, cách để trao đổi dữ liệu giữa các page như thế nào. Nghĩa là Angular team đã viết sẵn các thư viện ( Libraries ) để bạn sử dụng lại, cùng với một khuôn mẫu (design parttern) mà bạn phải tuân theo nó để có thể xây dựng được ứng dụng.

3. Những điểm khác nhau giữa Framework và Library là gì?

– Framework và Library đều cung cấp các tính năng (functions) được viết sẵn để chúng ta có thể tái sử dụng.
– Framework lớn hơn và phức tạp hơn Library.
– Sử dụng Framework bạn phải thay đổi cấu trúc code của dự án (project’s structure) theo các quy tắc của framework đó để có thể sử dụng được các functions mà framework đó cung cấp.
– Chúng ta có thể sử dụng các functions của Library một cách trực tiếp mà không cần thay đổi cấu trúc code của dự án.
– Framework có thể hiểu là một khung chương trình, người dùng bổ sung code và tuân theo quy tắc để tạo ra ứng dụng. Còn Library chỉ cung cấp các chức năng tiện ích hay các class để sử dụng trong quá trình xây dựng ứng dụng.
– Framework hoạt động chủ động. Nghĩa là nó có thể đưa ra các quyết định gọi hoặc bị gọi bởi các Library hay ứng dụng nào đó.
– Library hoạt động bị động. Nghĩa là nó chỉ được gọi khi nào chúng ta cần dùng nó.

Tới đây, mình nghĩ các  bạn đã hiểu được Framework và Library là gì, chúng khác nhau thế nào rồi đúng không. Để giúp các bạn hiểu rõ hơn, mình lấy một ví dụ đời thực để so sanh Framework với Library thế này:

  • Chúng ta lấy cấu trúc máy tính để làm ví dụ nhe.
  • Framework: là mô hình để có một cái máy tính hoạt động được. Nghĩa là, một cái máy tính sử dụng được phải bao gồm: màn hình, CPU, bàn phím, chuột, … Và bạn phải lắp đặt các linh kiện này theo tuần tự và quy tắc như: màn hình phải được gắn vào case CPU qua card đồ họa, bàn phím phải được gắn vào case CPU qua cổng COM/USB,… và bản thân case CPU để nó hoạt động phải có đủ các thành phần: chíp CPU, nguồn, dây điện,… và chúng phải được gắn kết với nhau theo quy tắt và vị trí của nó.
  • Library: có thể xem các cổng COM/USB được chia thành nhiều loại phục vụ cho từng chức năng của nó. Dây điện với các giắc cấm điện (loại 3 đầu, 2 đầu), óc vít dùng để liên kết các thành phần máy tính lại,…

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

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

Giải phóng lòng nhiệt huyết

Giải phóng lòng nhiệt huyết

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

Các thợ lành nghề trong lĩnh vực phát triển phần mềm chỉ quan tâm nhiều đến những thợ học việc mà có ham muốn thực sự với nghề.

Những người thợ học việc là một phần thiết yếu đối với nghề thủ công phần mềm bởi vì họ mang đến lòng nhiệt huyết và định hướng học tập có ảnh hưởng nhiều đến những người xung quanh.
—Pete McBreen, Software Craftmanship

Bối cảnh

Bạn đang rất phấn khích và tò mò về việc tạo ra các sản phẩm phần mềm thủ công.

  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết
  10 tips để trở thành Java Developer xịn hơn

Vấn đề

Bạn tự cảm thấy mình đang bị thụt lùi, ý thức được rằng lòng nhiệt huyết của mình cao hơn so với những đồng nghiệp xung quanh.

Giải pháp

Cho dù đang còn thiếu kinh ngiệm, bạn vẫn có những đóng góp nhất định cho nhóm của mình, bao gồm cả việc lan truyền sự nhiệt huyết. Đừng để ai đó làm giảm hứng thú với nghề của mình- đó là một yếu tố rất quý giá và sẽ đẩy nhanh tốc độ học của bạn.

Là một nhà phát triển, bạn sẽ không tránh khỏi việc phải làm theo nhóm. Trong một nhóm, mọi người thường có xu hướng thích nghi với những tiêu chuẩn chung, nhất là với người mới. Phần lớn các nhóm đều không quá đam mê hoặc nhiệt huyết về công nghệ. Ta có thể dễ đoán được là họ thường chỉ tập trung vào việc hoàn thành xong dự án hoặc cải thiện các phương diện trong quá trình phát triển đang gặp phải khó khăn. Vì vậy, những người tập sự nhiệt tình thường sẽ phải cố gắng chịu đựng để không bị soi xét. Họ sẽ cố kìm nén cảm xúc của mình lại, hoặc  chỉ biểu hiện ra ngoài trong các  công việc hàng ngày của họ. Sẽ có một số rắc rối xảy ra nếu bạn cứ để cảm xúc của mình tuôn trào khi  làm việc với một nhóm đã được gây dựng ổn định. Nếu tinh thần xuống thấp hoặc nhóm không chào đón người mới, thì bạn sẽ dễ bị soi xét. Bạn sẽ để lại ấn tượng không tốt với những người hay coi trọng năng lực hơn là khả năng học hỏi, đặc biệt là khi bạn thể hiện sự thiếu hiểu biết của mình. Tương tự như những yếu tố khác, không nên áp dụng phương pháp này một cách mù quáng. Tạo động lực trong nhóm cũng nên được cân nhắc. Nếu bạn thấy mình đang ở trong một nhóm không chấp nhận sự nhiệt tình của bạn, bạn nên tìm cách để nuôi dưỡng đam mê của mình.

Tuy nhiên, trong một nhóm chào đón sự hào hứng và tinh thần đóng góp của một người học việc, bạn nên thể hiện những khả năng đặc biệt mà lập trình viên kinh nghiệm hơn tin vào, chẳng hạn như trí tưởng và sự nhiệt tình.  Đây là thời gian có ý nghĩa nhất trong sự nghiệp, cho phép bạn chấp nhận rủi ro và nói lên suy nghĩ của mình. Bạn không có gì nhiều để sợ mất. Những ý tưởng và niềm đam mê của bạn sẽ tăng sự thông minh và tính đa dạng cho nhóm. Trong  cuốn The Wisdom of Crowds (Trí khôn của đám đông) của Jam Surowiecki, ông  đã nhiều lần chỉ ra rằng sự đa dạng  trong suy nghĩ là một thành phần chính của trí tuệ tập thể (collective intelligence – CI).

Một nghiên cứu thú vị về trí tuệ tập thể của các phi hành đoàn máy bay hàng không mẫu hạng cho thấy những người mới đến đóng một vai trò quan trọng trong các hoạt động nhóm phức tạp và đòi hỏi sự phối hợp của nhiều thao tác để vận hành an toàn một cỗ máy lớn với các những chiếc máy bay chiến đấu liên tục đến và đi. Các nhà nghiên cứu nhận thấy một nhóm bao gồm các thành viên có  kinh nghiệm ở các trình độ khác nhau góp phần tạo nên một nhóm vững mạnh hơn.

Sự hiểu biết có thể được tăng lên nếu có nhiều người với nhiều trình độ khác nhau kết nối với nhau, như khi những người mới đến, vì những người mới thường không coi điều gì là nghiễm nhiên mà có cả và sẽ thường kết hợp chặt chẽ hơn với những nhân viên kỳ cựu luôn nghĩ rằng họ đã chứng kiến mọi thứ rồi.

-Karl Weick và Karlene Roberts, ” Collective Mind in Organizations “, tr. 366

Cuối cùng, giải phóng lòng nhiệt tình là một trong số khá ít các trách nhiệm của người học việc. Bạn không thể mang lại kiến ​​thức sâu rộng hoặc tăng năng suất, nhưng bạn lại có thể khơi gợi sự hứng thú cho nhóm và đặt câu hỏi về mọi thứ. Bạn đang là người duy nhất (và tạm thời) có một quan điểm mới cho phép mình đưa ra một số gợi ý hữu ích để cải tiến.

Những người thợ lành nghề có thể học hỏi người lại từ những người học việc, ngay cả khi những người đó học hỏi từ họ. Người mới bắt đầu với sự nhiệt tình không chỉ làm mới  những người lành nghề mà còn thách thức họ bằng cách đưa những ý tưởng mới từ bên ngoài. Một người học việc được lựa chọn tốt thậm chí có thể làm cho một nghệ nhân làm việc năng suất hơn.

-Pete McBreen, Software Craftsmanship, p. 75

Hành  động

Hãy suy nghĩ về lần cuối cùng bạn có ý tưởng nhưng không đề xuất nó. Tìm một người mà đáng lẽ ra bạn đã giới thiệu nó cho họ và mô tả ý tưởng của bạn với người đó. Nếu  người đó chỉ ra những sai sót của nó hãy cố gắng thuyết phục người đó giúp bạn cải thiện nó.

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

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

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

Inversion of Control và Dependency Injection

Inversion of Control và Dependency Injection

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

Trong bài viết trước chúng ta đã cùng tìm hiểu thế nào là Dependency Injection rồi, do đó trong bài viết này mình sẽ đi sâu về Inversion of Control (IoC) hơn, và tìm hiểu xem mối liên hệ giữa hai khái niệm này là như thế nào các bạn nhé!

Như mình đã nói, với Dependency Injection thì một đối tượng sẽ không phụ thuộc vào đối tượng khác và đối tượng khác cũng vậy. Khi cần đối tượng này sẽ gọi tới đối tượng kia và ngược lại. Và mình đã hỏi các bạn, các đối tượng sẽ được tạo ra và nằm ở đâu để khi cần chúng có thể gọi lẫn nhau. Câu trả lời là chúng ta phải có một khung chứa, và khung chứa đó chính là một phần của IoC.

  Hiểu về Dependency Injection
  SQL Injection là gì? Cách giảm thiểu và phòng ngừa SQL Injection

IoC có mục đích là cung cấp một cơ chế đơn giản để chứa các đối tượng phụ thuộc và quản lý các đối tượng phụ thuộc đó thông qua chu trình sống của chúng. Một đối tượng bị phụ thuộc sẽ yêu cầu một số lượng nhất định các đối tượng phụ thuộc được quản lý bởi IoCIoC sẽ cung cấp những cách để các đối tượng bị phụ thuộc có thể truy cập và tương tác được các đối tượng phụ thuộc.

IoC được phân chia thành hai loại khác nhau, đó là:

  • Dependency Lookup
  • Dependency Injection

và chúng sẽ có hai kiểu hiện thực khác nhau.

Dependency Lookup sẽ tìm kiếm đối tượng phụ thuộc trong khung chứa IoC và sau đó các bạn có thể dùng code để đưa đối tượng phụ thuộc vào trong đối tượng bị phụ thuộc trong khi đó Dependency Injection sẽ đưa luôn đối tượng phụ thuộc vào đối tượng bị phụ thuộc.

Đến đây chắc các bạn cũng có thể phân biệt được sự khác biệt giữa IoC và Dependency Injection rồi phải không? Bây giờ chúng ta sẽ cùng tìm hiểu thêm về các loại của IoC các bạn nhé!

Dependency Lookup

Dependency Lookup được chia thành hai kiểu khác nhau đó là:

  • Dependency Pull
  • Contextualized Dependency Lookup (CDL)

Với Dependency Pull, các đối tượng phụ thuộc sẽ được lấy ra từ một nơi mà các đối tượng phụ thuộc đã được đăng ký chứ không phải lấy trực tiếp từ khung chứa. Nếu các bạn đã làm việc qua với EJB thì các bạn đã làm quen với Dependency Pull vì để lấy các đối tượng phụ thuộc các bạn phải thông qua JNDI API.

Inversion of Control và Dependency Injection

Còn Contextualized Dependency Lookup thì việc lấy đối tượng phụ thuộc xảy ra trực tiếp với khung chứa luôn chứ không thông qua nơi mà đối tượng phụ thuộc đã đăng ký.

Inversion of Control và Dependency Injection

Dependency Injection

Dependency Injection cho chúng ta hai cách phổ biến để đưa đối tượng phụ thuộc vào đối tượng bị phụ thuộc đó là: Constructor Injection và Setter Injection.

Với Constructor Injection, việc đưa đối tượng phụ thuộc vào đối tượng bị phụ thuộc sẽ thông qua các constructor của đối tượng bị phụ thuộc. Khi đó đối tượng phụ thuộc sẽ là một tham số trong những constructor đó.

Ví dụ:

Còn với Setter Injection thì việc đưa đối tượng phụ thuộc sẽ thông qua một phương thức setter bên trong đối tượng bị phụ thuộc.

Ví dụ

package com.huongdanjava;
public class SetterInjection {
private Dependency dependency;
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
}

Cấu hình định dạng ngày tháng, thời gian trên Windows cho ứng dụng Winform

Cấu hình định dạng ngày tháng, thời gian trên Windows cho ứng dụng Winform

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

Xin chào các bạn, bài viết hôm nay mình sẽ hướng dẫn các bạn cách định dạng Ngày tháng và Thời gian trên Windows và Ứng dụng trong lập trình C#, Winform.

  10 điều bạn có thể làm với Linux mà bạn không thể làm với Windows
  Cách mạng 0.4 của Neovim: Floating Window

[C#] Set config shortDate and Short Time Windows

Khi các bạn viết ứng dụng winform hay ứng dụng nào của windows, thì mặc định các control ngày tháng hay thời gian, sẽ mặc định sẽ lấy format cấu hình của máy tính.

Cấu hình định dạng ngày tháng, thời gian trên Windows cho ứng dụng Winform

Cấu hình DateTime Format ở Windows của mình:

Cấu hình định dạng ngày tháng, thời gian trên Windows cho ứng dụng Winform

Theo hình trên, thì người sử dụng cài đặt mặc định Short Date Format là: MM/dd/yyyy

Thì khi chúng ta chạy ứng dụng của mình thì các control cũng format theo định dạng đó, như hình bên dưới đây:

Cấu hình định dạng ngày tháng, thời gian trên Windows cho ứng dụng Winform

Các bạn xem hình ảnh trên sẽ thấy thay vì hiển thị ngày 03/12/2020 => nó lại đi hiển thị là 12/03/2020.

Nếu mặc định người dùng biết chỉnh định dạng format ngày tháng lại thì đơn giản không sao.

Nhưng mong muốn của mình là khi chạy ứng dụng của mình sẽ luôn thể hiện ở định dạng format chuẩn Việt Nam dd/MM/yyyy.

Dưới đây mình sẽ có ba cách thực hiện như sau:

Cách 1: Chỉnh Regedit của Windows về định dạng mong muốn của mình

private void button1_Click(object sender, EventArgs e)
{
    RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Control Panel\International", true);
    rk.SetValue("sTimeFormat", "HH:mm:ss"); // HH for 24hrs, hh for 12 hrs
}

private void button2_Click(object sender, EventArgs e)
{
    RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Control Panel\International", true);
    rk.SetValue("sTimeFormat", "dd/MM/yyyy"); 
}
C#

Cấu hình định dạng ngày tháng, thời gian trên Windows cho ứng dụng Winform

Tuy nhiên, khi các bạn set theo Regedit bằng cách này, thì ngày tháng dưới Thanh Taskbar sẽ không thay đổi liền.

Mà nó chỉ thay đổi như số phút thời gian nhảy nó mới cập nhật lại định dạng.

Cấu hình định dạng ngày tháng, thời gian trên Windows cho ứng dụng Winform

Dưới đây là kính thưa các loại định dạng ngày tháng.

1) MM/dd/yyyy 08/22/2006
2) dddd, dd MMMM yyyy Tuesday, 22 August 2006
3) dddd, dd MMMM yyyy HH:mm Tuesday, 22 August 2006 06:30
4) dddd, dd MMMM yyyy hh:mm tt Tuesday, 22 August 2006 06:30 AM
5) dddd, dd MMMM yyyy H:mm Tuesday, 22 August 2006 6:30
6) dddd, dd MMMM yyyy h:mm tt Tuesday, 22 August 2006 6:30 AM
7) dddd, dd MMMM yyyy HH:mm:ss Tuesday, 22 August 2006 06:30:07
8) MM/dd/yyyy HH:mm 08/22/2006 06:30
9) MM/dd/yyyy hh:mm tt 08/22/2006 06:30 AM
10) MM/dd/yyyy H:mm 08/22/2006 6:30
11) MM/dd/yyyy HH:mm:ss 08/22/2006 06:30:07
12) MMMM dd August 22
13) yyyy’-‘MM’-‘dd’T’HH’:’mm’:’ss.fffffffK 2006-08-22T06:30:07.7199222-04:00
14) ddd, dd MMM yyyy HH’:’mm’:’ss ‘GMT’ Tue, 22 Aug 2006 06:30:07 GMT
15) yyyy’-‘MM’-‘dd’T’HH’:’mm’:’ss 2006-08-22T06:30:07
16) HH:mm 06:30
17) hh:mm tt 06:30 AM
18) H:mm 6:30
19) h:mm tt 6:30 AM
20) HH:mm:ss 06:30:07
21) yyyy’-‘MM’-‘dd HH’:’mm’:’ss’Z’ 2006-08-22 06:30:07Z
22) dddd, dd MMMM yyyy HH:mm:ss Tuesday, 22 August 2006 06:30:07
23) yyyy MMMM 2006 August

Cách 2: Mình sẽ sử dụng hàm API 32 Windows để thực hiện thay đổi định dạng ngày tháng và thời gian.

Cách này khi các bạn thay đổi thì định dạng ngày tháng thời gian trong Windows sẽ thay đổi ngay lập tức.

public const int LOCALE_USER_DEFAULT = 0x00000400;
public const int LOCALE_SSHORTDATE = 0x0000001F;
public const int LOCALE_STIMEFORMAT = 0x1003;
public const int LOCALE_SSHORTTIME = 0x0079;

public const int BSF_QUERY = 0x00000001;
public const int BSF_IGNORECURRENTTASK = 0x00000002;
public const int BSF_FLUSHDISK = 0x00000004;
public const int BSF_NOHANG = 0x00000008;
public const int BSF_POSTMESSAGE = 0x00000010;
public const int BSF_FORCEIFHUNG = 0x00000020;
public const int BSF_NOTIMEOUTIFNOTHUNG = 0x00000040;
public const int BSF_MSGSRV32ISOK = unchecked((int)0x80000000);
public const int BSF_MSGSRV32ISOK_BIT = 31;

public const int BSM_ALLCOMPONENTS = 0x00000000;
public const int BSM_VXDS = 0x00000001;
public const int BSM_NETDRIVER = 0x00000002;
public const int BSM_INSTALLABLEDRIVERS = 0x00000004;
public const int BSM_APPLICATIONS = 0x00000008;
public const int BSM_ALLDESKTOPS = 0x00000010;

public const int WM_WININICHANGE = 0x001A;

[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean SetLocaleInfo(int Locale, int LCType, string lpLCData);

[DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int BroadcastSystemMessage(int flags, ref int lpInfo, uint Msg, uint wParam, IntPtr lParam);
C#

+ Cấu hình ShortDate ta viết như sau:

if (SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, "dd/MM/yyyy"))
{
    int dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
    string sString = "intl";
    GCHandle GCH = GCHandle.Alloc(sString, GCHandleType.Pinned);
    IntPtr pString = GCH.AddrOfPinnedObject();
    BroadcastSystemMessage(BSF_FORCEIFHUNG | BSF_IGNORECURRENTTASK | BSF_NOHANG | BSF_NOTIMEOUTIFNOTHUNG, ref dwRecipients, WM_WININICHANGE, 0, pString);
}
C#

+ Cấu hình cho ShortTime:

if (SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTTIME, "HH:mm:ss"))
{
    int dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
    string sString = "intl";
    GCHandle GCH = GCHandle.Alloc(sString, GCHandleType.Pinned);
    IntPtr pString = GCH.AddrOfPinnedObject();
    BroadcastSystemMessage(BSF_FORCEIFHUNG | BSF_IGNORECURRENTTASK | BSF_NOHANG | BSF_NOTIMEOUTIFNOTHUNG, ref dwRecipients, WM_WININICHANGE, 0, pString);
}
C#

Cái này là mình định dạng theo chuẩn format về 24h.

Kết quả chạy như hình ảnh bên dưới đây:

Cấu hình định dạng ngày tháng, thời gian trên Windows cho ứng dụng Winform

Tuy nhiên trong ứng dụng, chúng ta nên thực hiện theo cách thứ 3 ở bên dưới đây:

Cách 3: Cài đặt ngày tháng và thời gian mặc định của ứng dụng khi chạy Current Thread

Thay vì chúng ta đi chỉnh định dạng ngày của người sử dụng, thì không hay, nhiều lúc người dùng vẫn mong muốn định dạng máy tính của họ là MM/dd/yyyy.

Hay bất kỳ định dạng nào. Tuy nhiên, chúng ta làm sao để khi mở ứng dụng của mình lên chạy đều thể hiện ở định dạng dd/MM/yyyy thì chúng ta sẽ sử dụng cách dưới đây nhé.

Các bạn cấu hình trực tiếp ở file Program.cs nhé như code bên dưới đây.

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        initCulturalFormattingChanges();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    private static void initCulturalFormattingChanges()
    {
        CultureInfo cultureDefinition = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
        cultureDefinition.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
        cultureDefinition.DateTimeFormat.ShortTimePattern = "HH:mm:ss";
        Thread.CurrentThread.CurrentCulture = cultureDefinition;
    }
}
C#

Thanks for watching!

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

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

Xem thêm Tuyển dụng Winform hấp dẫn trên TopDev

Đơn xin nghỉ việc là gì? Mẫu đơn xin nghỉ việc chuẩn nhất

đơn xin nghỉ việc
đơn xin nghỉ việc

Mẫu Đơn xin việc có những điều gì đáng lưu ý? Đâu là những điểm đáng lưu ý cho một mẫu đơn xin nghỉ việc đúng chuẩn theo yêu cầu? Cách viết một đơn xin nghỉ việc như thế nào?

Như chúng ta đều biết, nhu cầu nghỉ việc, thôi việc là nhu cầu thiết yếu của người lao động. Tùy vào quy mô tổ chức, vận hành mà chế độ và hình thức nghỉ phép sẽ có điểm khác nhau. Do vậy mà đơn xin nghỉ việc thật sự rất quan trọng. Đồng thời, một lý do xin nghỉ việc chính đáng cũng rất quan trọng! Cùng TopDev tìm hiểu và giải đáp các thắc mắc xoay quanh mẫu đơn xin thôi việc nhé!

Đơn xin nghỉ việc là gì?

Đơn xin nghỉ việc là một loại giấy tờ có hiệu lực và giá trị pháp lý, đảm bảo yếu tố hiện hành về yêu cầu thôi việc của một cá nhân trong một lĩnh vực hoạt động cụ thể nào đó. Loại văn bản này là quyền lợi của mỗi nhân viên. Văn bản này giúp nhân viên trực tiếp hoặc gián tiếp phản ánh sự vắng mặt của bản thân trong một khoảng thời gian được xác định và có giới hạn.

Không khác nhiều so với CV IT hay sơ yếu lý lịch dành cho IT, mẫu đơn xin nghỉ việc cũng có những đặc điểm riêng biệt.

Chúng ta có thể xem xét nó như một loại văn bản cần có trong quy trình quản lý và phát triển tổ chức nhân sự ở mỗi cấp doanh nghiệp. Đơn xin nghỉ việc cần được thể hiện giá trị của nó đúng thời điểm. Điều này phản ánh cho tính trách nhiệm mà mỗi nhân viên thể hiện thông qua sự chuyên cần.

Tại sao cần phải viết đơn xin nghỉ việc?

Chắc hẳn khi muốn nghỉ việc, ai cũng mong muốn “đẹp lòng” cả đôi bên. Do vậy, một đơn xin nghỉ việc với đầy đủ thông tin, nội dung hợp chuẩn; được viết với thái độ chuyên nghiệp và thể hiện sự tôn trọng cần có với tổ chức sẽ giúp lưu giữ những giá trị tốt đẹp hơn. 

đơn xin nghỉ việc
Lý do xin nghỉ việc rất quan trọng

Mẫu đơn xin thôi việc thể hiện bạn là người có tính trách nhiệm với vị trí, sự tín nhiệm mà tổ chức dành cho bạn trong thời gian vừa qua.

Nó cũng là cơ sở quan trọng giúp cho quá trình nghỉ việc được thuận lợi và có tính chuẩn mực hơn. Vì thế, trong bất kỳ hoàn cảnh nào và bất cứ lý do nào, bạn cũng cần phải viết đơn xin nghỉ việc.

Phân loại mẫu đơn xin nghỉ việc

Thực tế trong tổ chức quản lý nhân sự, có rất nhiều mẫu đơn xin việc. Vậy bạn đã bao giờ biết rõ về chúng? Cùng điểm qua 3 loại mẫu đơn xin nghỉ việc, thôi việc chuẩn nhất.

  Tất tần tật về mẫu đơn xin nghỉ phép dành cho IT 

1. Đơn xin nghỉ việc thông dụng nhất

Khi cá nhân người lao động có ý định nhảy việc, muốn chấm dứt hợp đồng thì nhu cầu viết đơn thôi việc là tất yếu diễn ra.

Mục đích của đơn này là trình bày chi tiết lý do và thông báo cho công ty về việc thay đổi nhân sự. Từ cơ sở đó, họ có kế hoạch tuyển dụng kịp thời cho các vị trí còn trống.

Đồng thời, đơn xin nghỉ việc củng có ý nghĩa lớn khi là văn bản giải trình; hỗ trợ quá trình thiết lập sự minh bạch về quy chế nhân sự, tránh tình trạng vi phạm hợp đồng hay những phát sinh tiêu cực ngoài ý muốn.

Tất nhiên, để được phê duyệt và xử lý theo quy trình, đơn nghỉ việc và lý do xin nghỉ việc của cá nhân phải đảm bảo tính thuyết phục, chuyên nghiệp. 

2. Đơn xin thôi việc, nghỉ phép không lương

Nếu bạn là cá nhân thuộc các trường hợp như: ốm đau, có việc riêng cần giải quyết; hoặc không có thời gian để bàn giao các nhiệm vụ;… Đây là lúc thích hợp để bạn nêu rõ các lý do của mình.

  Top lý do xin nghỉ việc sếp không thể từ chối

Một điểm cần lưu tâm là bạn cần có thiện chí nghỉ việc không lương để có thể nhận được sự thông cảm từ nhà quản lý/tổ chức nhân sự. Đừng khiến bản thân rơi vào các tình trạng vi phạm hợp đồng!

3. Đơn xin thôi việc tạm thời (thời gian ngắn)

Đã là một nhân sự chính thức, bạn cần tuân thủ mọi điều luật và chế độ quản lý được đặt ra. Vì vậy, dù là tạm nghỉ có thời hạn và quay trở lại, bạn cũng cần viết đơn xin nghỉ việc. Điều này thể hiện bạn là người có trách nhiệm với tổ chức. 

Các bạn lưu ý, cách viết cho loại đơn xin nghỉ việc này là thông báo tới công ty về: lý do, thời gian trở lại làm việc,… Không khó để nhận được sự chấp thuận nếu ban có cách trình bày lý do chính đáng và một thái độ chuyên nghiệp.

Những lý do viết đơn xin nghỉ việc

Tùy vào từng trường hợp cụ thể mà mỗi cá nhân có lý do xin nghỉ việc tương ứng. Cùng điểm qua các lý do viết đơn thôi việc hợp lý, chính đáng và ngược lại.

1. Các do xin nghỉ việc chính đáng

Mong muốn đổi môi trường làm việc phù hợp hơn.

Những định hướng phát triển hiện tại không đúng với kỳ vọng.

Các vấn đề về di chuyển cá nhân.

Chế độ đãi ngộ không tương xứng với sự nỗ lực cá nhân.

Sự thăng tiến chậm hoặc nhận thấy không có cơ hội nào để tiếp tục phát triển trong sự nghiệp.

Những “nội chiến” từ các mâu thuẫn, bất đồng công sở.

Ảnh hưởng đa chiều từ các công việc bên ngoài.

Các lý do cá nhân: tâm lý, tình cảm.

Văn hóa công ty chưa thực sự phù hợp với cá tính.

Có những môi trường làm việc lý tưởng hơn.

2. Các lý do xin nghỉ việc không chính đáng

đơn xin nghỉ việc
Có nhiều lý do nghỉ việc được đặt ra trong lá đơn trình bày.

Hoàn cảnh gia đình không cho phép.

Bất khả khàng trong việc kết nối mọi người.

Xu hướng tâm lý và cảm xúc cá nhân chi phối.

Chưa hài lòng với lịch trình làm việc và các quy tắc của công ty.

Công việc nhàm chán, thiếu tính bức phá và các cơ hội sáng tạo.

Với những lý do chính đáng trên, chắc chắn là bạn không nên sử dụng.

Đơn giản vì nó không được nhà quản lý đánh giá cao bạn. Mọi cố gắng của bạn có thể bị mất đi. Trong việc viết đơn, bạn nên thành thật chia sẻ những lý do của bản thân. Đừng nói dối trong mọi trường hợp. Một khi sự thật được phát hiện, bạn mất đi uy tín lẫn cả những tình cảm của cấp trên, các đồng nghiệp đối với bạn. Vậy nên, hãy chân thật khi viết đơn xin thôi việc.

Nếu đã xác định rõ lý do nghĩ việc, bạn cũng nên lập ra kế hoạch trở lại; hoặc sự chuẩn bị tốt nhất cho thời gian mà bạn vắng mặt. Đồng thời, bạn hãy tìm kiếm cho bản thân những mẫu đơn xin nghỉ việc hợp lý, đúng chuẩn để có thể thuận lợi chuyển sang một môi trường làm việc thích hợp hơn. Ra đi hay ở lại thì bạn đều phải để lại ấn tượng đẹp với tổ chức/doanh nghiệp của mình.

  Top lý do xin nghỉ việc sếp không thể từ chối

Tìm hiểu về quy trình xin nghỉ việc đúng hiệu lực

1. Bước đầu tiên – Thông báo nghỉ việc

Việc cần làm đầu tiên là bạn cần thông báo cho người quản lý, ngưới giám sát hoặc các cấp cao hơn. Tùy vào mỗi công ty, bạn phải thực hiện thông báo về Team Leader hay phòng nhân sự khoảng 15-30 ngày trước khi chính thức thôi việc. Đây là khoảng thời gian tương ứng với phụ lục pháp lý được trích trong hợp đồng lao động.

Và việc bạn cần làm là tuân thủ chúng. Đây cũng là thời gian công ty có thể sắp xếp và tuyển chọn nguồn nhân sự mới cho vị trí bạn nghỉ việc. Việc báo trước cho nhân sự phản ánh bạn là một cá nhân có thái độ tốt và tính trách nhiệm cao.

2. Bàn giao công việc và những thứ có liên quan

Khi lá đơn xin thôi việc của bạn được duyệt, kế tiếp chính là bước bàn giao công việc. Trong thời gian đó, nhiệm vụ của bạn là phải hoàn tất các công việc dang dở trong thời gian quy định còn lại. Tiếp đó là hệ thống các nội dung công việc, lưu trữ và bàn giao lại cho nhân sự mới (nếu có).

Những thứ có liên quan như tài sản, giấy tờ cũng được sắp xếp theo quy trình. Đặc biệt, chính bạn là người chia sẻ, hướng dẫn lại công việc cho người mới; trao đổi và trình bày với họ nắm rõ quy chế và cách xử lý công việc trong thời gian tới.

3. Tuân thủ hiệu lực hợp đồng lao động 

Nếu rời đi không bao trước, không có đơn xin thôi việc và không nhận được sự đồng ý của công ty, bạn sẽ phải chịu trách nhiệm cho hành động của mình. Việc đơn phương chấm dứt hợp đồng mà chưa có sự chấp thuận, bạn sẽ phải thực hiện các nghĩa vụ như sau:

Không nhận được trợ cấp thôi việc.

Bạn phải bồi thường cho người sử dụng lao động từ ½ đến một tháng tiền lương.

Tùy theo từng loại hợp đồng bổ sung hay quy chế riêng từng doanh nghiệp, bạn có thể được yêu cầu hoàn trả toàn bộ chi phi đào tạo ban đầu.

Việc đơn phương chấm dứt hợp đồng khiến bạn có một “chấm đen” trong hồ sơ xin việc. Và đó là rào cản khiến bạn khó khăn trong việc tìm kiếm công việc mới.

Từ những phân tích trên cho thấy, mọi thứ đều phải tuân thủ các quy trình. Bạn cần thực hiện đầy đủ việc viết đơn xin nghỉ việc để để đảm bảo quyền lợi cũng như trách nhiệm của bản thân mình. Tất nhiên vẫn phải lưu tâm về một lý do xin nghỉ việc hợp lý.

Mẹo ứng xử “khôn khéo” khi viết đơn xin nghỉ việc

Như bạn đã biết, viết mẫu đơn xin thôi việc không phải chỉ dừng lại ở quy trình gửi đơn, chấp thuận rồi nghỉ một mạch. Mà nó cần quy trình và đôi khi là cả một nghệ thuật.

Việc khéo léo và tinh tế trong các thủ thuật viết đơn xin nghỉ việc sẽ cho thấy bạn là một nhân viên chuyên nghiệp. Hãy quan tâm và bỏ túi những cách thức dưới đây.

1. Suy nghĩ thận trọng trước khi quyết định gửi đơn

đơn xin nghỉ việc
đơn xin nghỉ việc

Đây thật sự là một bước quan trọng. Bạn không thể thích thì nghỉ. Việc tùy hứng thể hiện bạn là người thiếu trách nhiệm. Hãy đặt ra các câu hỏi, sau đó cân nhắc trước khi đi đến quyết định viết đơn xin thôi việc.

Sau đây là một vài suy nghĩ và phán đoán bạn nên tham khảo:

Liệu bạn đã giải quyết hết những công việc còn lại chưa?

Bạn có chắc chắn tìm được việc mới sau khi nghỉ việc?

Lý do xin việc ấy liệu là nhất thời? Nó có tương xứng với những công sức bạn cống hiến hay không?

Ở môi trường làm việc mới, các chế độ phúc lợi, các kỹ năng, kiến thức mới bạn học được có giúp bạn nhanh chóng thăng tiến như kỳ vọng?

Rất nhiều thứ cần bạn suy nghĩ kỹ lưỡng. Do đó, bạn không thể đưa ra các quyết định một cách vội vàng. Hãy thật sự thận trọng khi đi quyết định rời đi. Khi đã thật sự lựa chọn được hướng đi, hãy dành tâm sức đầu tư cho lá đơn xin nghỉ việc một cách hoàn hảo. Nó không đơn giản chỉ là một tờ trình, mà đó còn là sự tôn trọng với chính tổ chức nhân sự của bạn.

2. Thời điểm rời đi rất quan trọng

Sau khi đã cân nhắc và có những quyết định, bạn nên quan tâm đến tình thế hiện tại của công ty.

Ví dụ như: công ty có đang thật sự ổn về nhân lực? Các chiến lược phát triển sản phẩm, dự án hoạt động, sự kiện thường niên có đang vào thời điểm nóng hay không? Nếu là một nhân viên thật sự có tâm, bạn phải nhìn nhận rõ vấn đề này. Bạn không nên rời đi nếu công ty rơi vào khủng hoảng khó khăn. Hãy nghĩ đến công ty dù đó chỉ là vài tháng tới!

Trước khi rời đi, đây có phải thời gian thích hợp để bạn bỏ đi những mâu thuẫn vốn có với sếp, đồng nghiệp? Thật sự đó là một suy nghĩ đúng đắn! Bạn nên cởi mở, tìm kiếm cơ hội để tháo gở những nút thắt bất đồng nảy sinh. Có thế như thế, khi “tốt nghiệp” môi trường làm việc cũ, bạn sẽ cảm thấy thoải mái hơn.

Đồng thời, đó cũng là cơ sở giúp nuôi dưỡng các mối qun hệ đẹp của bạn. Từ suy nghĩ đó, bạn có thể tự tin tìm kiếm công việc mới cũng như mong đợi về một chặng đường tươi đẹp, suôn sẻ hơn.

Cách viết mẫu đơn xin nghỉ việc chuẩn nhất

1. Phần mở đầu

  • Quốc hiệu, tiêu ngữ

Bạn cần phải triển khai viết quốc hiệu, tiêu ngữ trước khi đi vào chi tiết. Cụ thể như sau:

CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM

Độc lập – Tự do – Hạnh phúc

  • Tên đơn: Đon xin nghỉ việc, đơn xin thôi việc,… (Đơn nghỉ phép sẽ gắn với mục đích cụ thể tùy trường hợp thực tế).
  • Kính gửi: Đơn xin phép được gửi cho ai? Người viết đơn cần xác định rõ đối tượng cần gửi đơn. Đó có thể là cấp trên, người quản lý, Team Lead, trưởng nhóm,…

2. Phần nội dung trọng tâm mẫu đơn xin nghỉ việc

  • Phần này rất quan trọng và cần đảm bảo đầy đủ các nội dung như sau gồm:

–  Các thông tin liên quan đến người viết đơn

–  Mục đích của việc viết đơn xin nghỉ việc

–  Lý do xin nghỉ phép: Các lý do phải thật sự chính đáng và hợp lý trong hoàn cảnh hiện thời của tổ chức/doanh nghiệp.

–  Lời cam kết về sự thật và lởi cảm ơn

– Xác nhận minh chứng thông qua chữ ký (ký và ghi rõ họ tên)

  • Đặc biệt, một phần đáng lưu tâm nữa, bạn nên trình bày thêm những nội dung sau:

– Những kinh nghiệm, các giá trị bạn có được trong thời gian làm việc tại công ty

– Chia sẻ về quá trình trưởng thành của bạn

– Gửi lời cảm ơn và sự trân trọng với những ai đã giúp đỡ bạn

– Nhắc lại những ấn tượng về các cột mốc/dấu ấn khó quên của bạn

– Trình bày lý do rời đi một cách chân thật, có chiều sâu

– Nếu có thể, hãy đề cử các ứng viên thay thế phù hợp

Những lưu ý khi viết đơn xin nghỉ việc

Sau đây là những lưu ý sẽ thật sự giúp bạn có một lá đơn xin thôi việc thật sự thuyết phục.

đơn xin nghỉ việc
Những tips cần quan tâm khi viết đơn xin thôi việc rất cần thiết.

1. Văn phong lịch sự 

Thái độ quyết định tất cả. Điều này không bao giờ là sai. Khi viết mẫu đơn xin nghỉ việc, bạn cần có một thái độ tôn trọng, lịch sự. Điều đó được thể hiện qua văn phong trình bày, ngôn ngữ bạn sử dụng. Đừng quá phô trương các cảm xúc vào lá đơn mà hãy kiếm soát tốt nó.

2. Nội dung mô tả về lý do phải chi tiết

Lý do nghỉ việc. thôi việc là nội dung trọng tâm mà bạn muốn truyền tải đến cấp trên. Và dù là loại văn bản, giấy tờ dưới hình thức nào, nội dung đều phải được chú trọng. 

Bên cạnh lý do hợp lý, cách trình bày rõ ràng, chân thật, bạn nên chia sẻ với người quản lý về thời gian mà bạn sẽ trở lại với công việc (trường hợp bạn tạm thời nghỉ việc). Đó được hiểu là lời cam kết mang dấu ấn uy tín; và trách nhiệm của bạn với công việc. Trong trường hợp đó, hãy linh hoạt để lại thông tin cá nhân, đề phòng những vấn đề phát sinh liên quan đến quyền lợi.

Tương tự, nếu bạn là cá nhân chịu trách nhiệm quản lý trực tiếp các dự án lớn, hãy nhanh chóng bàn giao. Công tác bàn giao cần được tiến hành lập tức và trong khoảng thời gian ngắn. Bạn phải đảm bảo cho dù thế nào, khi bạn rời đi, mọi quy trình vẫn được tiếp diễn. Đồng thời, chắc chắn không tạo ra sự thay đổi và ảnh hướng tiêu cực đến mọi người xung quanh bạn.

Làm gì để nghỉ việc chuyên nghiệp?

Chắc chắn rằng sau khi rời đi, việc bạn làm đầu tiên là tìm việc mới. Hãy cố gắng hoàn thiện một bộ hồ sơ xin việc để đảm bảo quá trình ấy diễn ra thuận lợi. Nếu là một cá nhân nghỉ việc chuyên nghiệp, bạn cần quan tâm đến những yếu tố xung quanh.

Cùng TopDev xem qua các thông tin dưới đây! Chúng đều là những khía cạnh nhỏ. Song, chúng có ích trong mối quan hệ với cách thức tổ chức/quản lý nhân sự.

1. Rời đi bí mật

Bí mật ở đây không phải bạn tự ý rời đi không viết mẫu đơn thôi việc. Mà nó hiểu là bạn không nên chia sẻ chúng cho những người bạn thân thiết.

Đặc biệt, trước khi tìm được công việc phù hợp mới, bạn lại không nên chia sẻ. Bởi đơn giản, việc bạn nghỉ việc có thể làm ảnh hưởng đến tâm trạng, suy nghĩ của những người xung quanh. Hệ quả tiêu cực hơn là khiến cho hiệu suất công việc của họ bị thụt lùi.

2. Hệ thống hóa và lưu lại những thứ bạn đã làm

Mọi bài học dù ở môi trường nào đều có giá trị. Nó đều có ích cho sự nghiệp phát triển riêng của bạn sau này. Vì thế, dù nghỉ việc, bạn vẫn phải có trách nhiệm lưu trữ hồ sợ, thông tin về các dự án bạn thực hiện.

Điều này vừa có lợi cho việc thiết lập tài liệu bàn giao cho nhân sự mới; vừa giúp bạn nhìn nhận lại những nỗ lực và thành quả thực tế trong hành trình dài vừa qua.

Mẫu đơn xin thôi việc chuẩn nhất

đơn xin nghỉ việc
1-đơn xin nghỉ việc
đơn xin nghỉ việc
2-đơn xin nghỉ việc
đơn xin nghỉ việc
3-đơn xin nghỉ việc
đơn xin nghỉ việc
4-đơn xin nghỉ việc

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

Xem thêm việc làm Developers hàng đầu tại TopDev

Những tựa sách nổi tiếng dành cho Software Developer – Phần 3

sách cho software developer
Những tựa sách nổi tiếng dành cho Software Developer – Phần 1

Tác giả: Andrew

Giới thiệu

Với hai bài viết được chia sẻ ở các phần trước, các Software Developer đã phần nào tìm được cho mình những nội dung tham khảo tốt nhất. Phần này sẽ chia sẻ với các dev phần còn lại của chuỗi các tựa sách nổi tiếng về phát triển phần mềm.

software developer
Chuỗi các tựa sách về kỹ năng Software Developer cho công việc build phần mềm
  Những tựa sách nổi tiếng dành cho Software Developer - Phần 1
  Những tựa sách nổi tiếng dành cho Software Developer – Phần 2

Những cuốn sách cho Software Developer được lựa chọn nhiều nhất

15. Introduction to Algorithms – Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein

Một số sách về thuật toán hiện có trên thị trường dù khá chặt chẽ nhưng không đầy đủ. Cuốn sách về các thuật toán này là sự kết hợp độc đáo giữa tính chặt chẽ và tính toàn diện. Nó bao gồm một loạt các thuật toán chuyên sâu, nhưng vẫn làm cho thiết kế và phân tích của chúng có thể tiếp cận với mọi cấp độ độc giả. Mỗi chương tương đối khép kín và có thể được sử dụng như một chủ đề nghiên cứu khá hiệu quả. Những nội dung được chia sẻ trong đó đã được giữ nguyên bản mà không làm mất đi độ sâu của nội dung hoặc tính chặt chẽ của toán học.

Xem thêm các việc làm hấp dẫn KMS Technology tuyển dụng 2020

16. Agile Software Development: Principles, Patterns, and Practices – Robert C. “Uncle Bob” Martin

Agile Software Development được viết bởi một Software Developer nên toàn bộ nội dung của cuốn sách cũng chủ yếu liên quan đến vấn đề Software Developing. Nội dung cuốn sách bao gồm các phương pháp OOD, UML, Design Patterns, Agile và XP với mô tả chi tiết về một thiết kế phần mềm hoàn chỉnh cho các chương trình có thể tái sử dụng trong C++ và Java. Sử dụng cách tiếp cận thực tế, giải quyết vấn đề, nó chỉ ra cách phát triển một ứng dụng hướng đối tượng – từ giai đoạn đầu của phân tích, thông qua thiết kế cấp thấp và triển khai.

Xem thêm Tiếng Anh dành cho lập trình viên

Cuốn sách bao gồm các phần: Tin học và Động lực học, Nguyên tắc thiết kế lớp học, Quản lý sự phức tạp, Nguyên tắc thiết kế bao bì, Phân tích và Thiết kế, Các mẫu và Giao cắt Mô hình. Giải thích các nguyên tắc của OOD, từng cái một, và sau đó tác giả chứng minh nội dung được giải thích với nhiều ví dụ, thiết kế hoàn toàn được làm việc kỹ lưỡng và nghiên cứu điển hình. Thảo luận chi tiết các phương pháp thiết kế và phát triển phần mềm lớn.

Tham khảo tuyển dụng software engineer lương cao trên TopDev

17. CODE: The Hidden Language of Computer Hardware and Software – Charles Petzold

Trong CODE các tác giả cho chúng ta thấy những cách khéo léo mà các lập trình viên có thể vận dụng ngôn ngữ và phát minh ra các phương tiện giao tiếp mới với nhau. Và thông qua CODE, chúng ta cũng sẽ nhận thấy sự khéo léo này và sự bắt buộc giao tiếp của chính con người chúng ta đã thúc đẩy những đổi mới công nghệ trong hai thế kỷ qua như thế nào.

Sử dụng các vật dụng hàng ngày và các hệ thống ngôn ngữ quen thuộc như chữ nổi Braille và mã Morse, tác giả Charles Petzold đã tạo nên một câu chuyện sáng tạo cho bất kỳ ai từng thắc mắc về cách hoạt động đầy khó hiểu bên trong máy tính và các loại máy thông minh khác.

sách cho software developer
Tham khảo thêm nhiều đầu sách kỹ năng giúp dev nâng cao tay nghề

18. Sách cho Software Developer “The Art of Computer Programming” – Donald Knuth

Đây là cuốn sách kinh điển đã được xuất bản cách đây vài thập kỷ nhưng đến thời điểm hiện tại, tác phẩm vẫn giữ được tính hiệu quả của mình với các nội dung đầy chất lượng. Một trong những điểm mạnh nhất của cuốn sách là bộ sưu tập các bài toán cực kỳ ấn tượng đi kèm với mỗi chương. Tác giả đã chọn các vấn đề một cách cẩn thận và lập chỉ mục toàn bộ nội dung theo độ khó. Giải quyết một số lượng đáng kể các vấn đề này sẽ giúp bạn có được sự hiểu biết vững chắc về các vấn đề xung quanh chủ đề đã cho. Hơn nữa, các bài tập có một loạt các bài toán kinh điển.

Xem thêm các việc làm KMS tuyển dụng Intern

19. Clean Architecture: A Craftsman’s Guide to Software Structure and Design – Robert C. “Uncle Bob” Martin

Cuốn sách này sẽ giúp bạn tìm hiểu công việc mà kiến ​​trúc sư phần mềm cần đạt được là những gì, và các nguyên tắc cũng như cách thực hiện cốt lõi để đạt được điều đó. Người viết cần nắm vững các nguyên tắc thiết kế phần mềm cần thiết để giải quyết chức năng, tách thành phần và quản lý dữ liệu. Xem cách các mô hình lập trình áp đặt kỷ luật bằng cách hạn chế những gì nhà phát triển có thể làm cũng như hiểu điều gì cực kỳ quan trọng và điều gì chỉ đơn thuần là “chi tiết”.

  Làm thế nào để sắp xếp Clean Architecture theo Modular Patterns trong 10 phút?

Ngoài ra, với Clean Architecture, các tác giả sẽ triển khai các cấu trúc cấp cao, tối ưu cho web, cơ sở dữ liệu, máy khách dày, bảng điều khiển và các ứng dụng nhúng, xác định ranh giới và lớp thích hợp, đồng thời tổ chức các thành phần và dịch vụ. Dựa vào đó, bạn sẽ xem được lý do tại sao thiết kế và kiến ​​trúc gặp lỗi và cách ngăn chặn (hoặc sửa chữa) những lỗi này như thế nào.

Xem thêm các việc làm KMS Technology tuyển dụng hấp dẫn tại TopDev

20.Sách cho Software Developer “Patterns of Enterprise Application Architecture” – Martin Fowler

Cuốn sách này thực sự được nhiều người dùng đánh giá là cuốn sách có nội dung hai trong một. Phần đầu tiên của Patterns of Enterprise Application Architecture là một hướng dẫn ngắn về phát triển ứng dụng doanh nghiệp, bạn có thể đọc từ đầu đến cuối để hiểu phạm vi bài học của cuốn sách. Phần tiếp theo, cũng là phần chính trong toàn bộ nội dung của cuốn sách, là tài liệu tham khảo chi tiết về bản thân các mẫu. Mỗi mẫu cung cấp thông tin sử dụng và triển khai, cũng như các ví dụ mã chi tiết trong Java hoặc C#. Toàn bộ cuốn sách cũng được minh họa phong phú bằng các sơ đồ UML để giải thích thêm về các khái niệm.

Khi tìm hiểu về những thông tin được cung cấp trong cuốn sách này, bạn sẽ có kiến ​​thức cần thiết để đưa ra các quyết định quan trọng trong việc xây dựng một ứng dụng doanh nghiệp và các mô hình đã được chứng minh để sử dụng khi xây dựng chúng.

Xem thêm việc làm tester đãi ngộ tốt trên TopDev

Kết luận

Chuỗi bài viết này là thông tin tổng hợp gần như đầy đủ như cuốn sách về Software Developer phổ biến và hiệu quả nhất ở thời điểm hiện tại. Tìm đọc các nguồn này chắc chắn sẽ mang đến cho bạn những kỹ năng làm việc hiệu quả hơn trong thời gian tới.

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

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

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

Seminar môn Cấu trúc dữ liệu và giải thuật

Seminar môn Cấu trúc dữ liệu và giải thuật

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

Giới thiệu

Mình vừa làm seminar kết thúc môn học Cấu trúc dữ liệu và giải thuật, mình sẽ chia sẻ với các bạn về seminar của mình. Đề tài của mình: Đánh giá hiệu suất các thuật toán tìm kiếm và so sánh.

Bình thường khi học, độ phức tạp về thời gian của các thuật toán mà các bạn được giới thiệu đều là Big O notation, nhìn vào đó các bạn có thể biết được thuật toán nhanh hay chậm. Tuy nhiên, các bạn lại không biết được thuật toán nhanh hay chậm hơn như thế nào. Do đó mình muốn tạo ra chương trình thực hiện các thuật toán và đo thời gian thực hiện, từ đó các bạn có thể dễ dàng so sánh và thấy được hiệu suất của thuật toán.

  Crawl dữ liệu bằng JavaScript ngay trên trình duyệt
  Tìm hiểu về giải thuật: Một số phương pháp sắp xếp cơ bản

Dù mỗi máy có tốc độ xử lý khác nhau, hiệu suất thuật toán phụ thuộc vào rất nhiều yếu tố, tuy nhiên, các thuật toán cùng thực hiện trên cùng một máy, tức là cùng 1 điều kiện, vậy nên chúng ta vẫn có thể thấy được sự chênh lệch hiệu suất của các thuật toán.

Mình quyết định sử dụng WPF để có thể dễ dàng custom giao diện đẹp hơn.

Tính năng

Một số tính năng của phần mềm mình viết:

  • Tạo dãy số ngẫu nhiên
  • Lưu vào file
  • Load dãy số từ file
  • Tìm kiếm theo 3 thuật toán
  • Sắp xếp theo 7 thuật toán
  • Xem kết quả thời gian thực hiện thuật toán
  • Xem kết quả dãy sau khi sắp xếp
  • Xem code thuật toán bằng C++

Demo

Một số screenshot Seminar của mình:

Seminar môn Cấu trúc dữ liệu và giải thuật
Seminar môn Cấu trúc dữ liệu và giải thuật
Seminar môn Cấu trúc dữ liệu và giải thuật

Source code

Các bạn có thể xem code seminar của mình trên Github. Có một lưu ý nhỏ là thư mục ViewCode phải được đặt cùng cấp với file exe thì tính năng View code mới có thể lấy code ra được.

Tổng kết

Seminar này mình chỉ làm sơ sài thôi, code cũng không clean, tổ chức chưa tốt lắm, các bạn tham khảo cho vui thôi nha!

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

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

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

Một ví dụ đơn giản giải thích hàm đệ quy

Một ví dụ đơn giản giải thích hàm đệ quy

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

Làm sao để in ra từ 1 đến 10 bằng hàm đệ quy?

I. Hàm đệ quy

Recursive function (hàm đệ quy) là function mà nó tự gọi chính nó. Phần định nghĩa function trông như thế này:

def foo():
    dosomething()
    foo() # gọi chính nó
    maybedosomething()
    return otherthing

Recursion là một lối suy nghĩ, một cách lập trình rất phổ biến trong functional programming (lập trình hàm) nhưng ở thế giới còn lại, nó không thực sự phổ biến hay có vẻ quen thuộc. Quan điểm về viết recursive function cũng khác nhau, có người bảo dễ, có người mãi không hiểu gì. Và nếu bạn thuộc nhóm không hiểu gì, thì không phải do bạn dốt, chỉ là chưa quen thôi.

  10 Bí quyết tuyển dụng giúp bạn tăng tỉ lệ nhận offer tức thì!
  3 chỉ số quan trọng đánh giá quy trình tuyển dụng

II. Recursive print

Đề bài: Cho số nguyên dương N, viết function in ra màn hình từ 1 đến N.

Lời giải:

Cách bình thường:

def lprint(n):
    '''
    Prints from 1 to n the loop way
    '''
    for i in range(1, n+1):
        print(i)
lprint(3)

Còn đây cách đệ quy:

def rprint(n):
    '''
    Prints from 1 to n recursive way
    '''
    if n == 0:
        return
    else:
        rprint(n-1)
        print(n)
rprint(3)

Output:

1
2
3

Nếu bạn không hiểu đoạn code trên thực sự làm gì qua từng bước, hãy xem phiên bản chỉnh sửa một chút để in ra giải thích sau:

INPUT = 10
def rprint2(n):
    pad = 3 * ' ' * (INPUT - n)
    print('%sInside function with %d' % (pad, n))
    if n == 0:
        return
    else:
        print('%s calling rprint2(%d)' % (pad + '|' + '_', n-1))
        rprint2(n-1)
        print('%s| printing %d' % (pad, n))
        print(n)
        return
rprint2(INPUT)

Output:

Inside function with 10
|_ calling rprint2(9)
   Inside function with 9
   |_ calling rprint2(8)
      Inside function with 8
      |_ calling rprint2(7)
         Inside function with 7
         |_ calling rprint2(6)
            Inside function with 6
            |_ calling rprint2(5)
               Inside function with 5
               |_ calling rprint2(4)
                  Inside function with 4
                  |_ calling rprint2(3)
                     Inside function with 3
                     |_ calling rprint2(2)
                        Inside function with 2
                        |_ calling rprint2(1)
                           Inside function with 1
                           |_ calling rprint2(0)
                              Inside function with 0
                           | printing 1
1
                        | printing 2
2
                     | printing 3
3
                  | printing 4
4
               | printing 5
5
            | printing 6
6
         | printing 7
7
      | printing 8
8
   | printing 9
9
| printing 10
10

Hãy đọc từ trên xuống dưới, chậm rãi, để hiểu chuyện gì đã xảy ra. Nếu vẫn chưa hiểu?

Hãy đọc lại từ đầu!

Ví dụ trên chỉ nhằm minh hoạ recursive function làm việc như thế nào, chứ không có lợi ích gì khi viết hàm recursive trong trường hợp này.

Recursive function sẽ trở nên rất hữu dụng nếu vấn đề được định nghĩa theo cách đệ quy (các hàm toán học), giải bài toán Tháp Hà Nội, hay chỉ đơn giản là muốn tiến gần hơn một bước đến Functional programming.

Link Jupyter notebook

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

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

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

Phân quyền người dùng với Laravel Authorization

Phân quyền người dùng với Laravel Authorization

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

Bất kể hệ thống website nào cũng có người dùng và đi kèm với nó là việc xác thực (authentication) và phân quyền (authorization) với từng người dùng. Xác thực trong Laravel là khá đơn giản với Laravel Authentication, chúng ta cũng có thể tận dụng các hệ thống khác như mạng xã hội để xác thực, ví dụ xác thực người dùng bằng FacebookGoogleTwitter…  Bên cạnh đó, chúng ta cũng rất cần phân quyền cho người dùng để đảm bảo các vấn đề về bảo mật và tuân thủ các chính sách từng hệ thống. Ví dụ như có những người dùng được phép chỉnh sửa hoặc xóa một tài nguyên nhưng cũng có những người dùng chỉ được phép đọc thông tin. Từ phiên bản Laravel 5.1 trở về trước, công việc này phải thực hiện thông qua các gói ACL (Access Control List) như Entrust, Sentinel hay Laravel-ACL thì hiện nay Laravel đã có hỗ trợ trực tiếp trong core của framework. Với việc sử dụng các gói ACL ở ngoài, các quyền cho người dùng chỉ là các cờ, nếu muốn các nghiệp vụ phức tạp trong phân quyền, bạn sẽ rất khó khăn và phải đưa vào Controller. Sử dụng Laravel Gate tránh được một số các nhược điểm của việc sử dụng các gói ACL ngoài như sau:

  • Sử dụng Laravel Gate cho bạn sự tự do, bạn có thể sử dụng cho các trường hợp cực phức tạp tùy ý do nó không bắt buộc phải implement trong các model.
  • Bạn có hoàn toàn tự chủ về các chính sách phân quyền, với Laravel Gate các xử lý truy cập có thể tách biệt với các xử lý về nghiệp vụ, loại bỏ sự phụ thuộc và code trong các controller dễ đọc hơn.

Gate và Policy giống như Route với Controller, Gate cũng cấp một giải pháp dựa trên Closure để phân quyền trong khi các policy giống với controller nhóm các logic nghiệp vụ liên quan đến Model hoặc các tài nguyên. Chúng ta cùng tìm hiểu về Gate trước khi tìm hiểu về Policy. Phần lớn các ứng dụng sẽ sử dụng cả Gate và Policy, Gate được áp dụng cho các hành động không liên quan đến Model hoặc các tài nguyên như việc truy nhập vào trang quản trị dashboard. Ngược lại, policy được sử dụng khi bạn muốn cho phép một hành động truy nhập vào một model hoặc nguồn tài nguyên.

  API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth
  Các Laravel route tips giúp bạn cải thiện routing

Laravel Gate

Gate là các Closure được xác định nếu một người dùng được xác thực để thực hiện một hành động, nó được định nghĩa trong App\Providers\AuthServiceProvider sử dụng facade Gate. Gate luôn nhận một thực thể user là tham số thứ nhất và có thể có các tham số tùy chọn khác như Eloquent Model:

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Gate::define('update-post', function ($user, $post) {
        return $user->id == $post->user_id;
    });
}

Gate cũng có thể định nghĩa sử dụng dạng callback string giống như Controller:

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Gate::define('update-post', 'PostPolicy@update');
}

Resource Gates Bạn có thể định nghĩa nhiều Gate sử dụng phương thức resource

Gate::resource('posts', 'PostPolicy');

Với phương thức resource nó tương tự như định nghĩa thủ công các phương thức sau:

Gate::define('posts.view', 'PostPolicy@view');
Gate::define('posts.create', 'PostPolicy@create');
Gate::define('posts.update', 'PostPolicy@update');
Gate::define('posts.delete', 'PostPolicy@delete');

Mặc định view, create, update và delete được định nghĩa. Bạn có thể override các khả năng này bằng cách truyền vào một mảng như là tham số thứ 3 cho phương thức resource. Key của mảng này định nghĩa tên khả năng trong khi giá trị định nghĩa tên phương thức.

Gate::resource('posts', 'PostPolicy', [
    'photo' => 'updatePhoto',
    'image' => 'updateImage',
]);

Phân quyền Để phân quyền thực hiện một hành động, bạn có thể sử dụng các phương thức allows và denies, chú ý rằng bạn không cần truyền người dùng đã được xác thực vào các phương thức này. Laravel sẽ tự động xử lý việc đó trong các gate Closure:

if (Gate::allows('update-post', $post)) {
    // The current user can update the post...
}

if (Gate::denies('update-post', $post)) {
    // The current user can't update the post...
}

Nếu bạn muốn xác định một người dùng nào đó có được phân quyền để thực hiện một hành động hay không, bạn có thể sử dụng phương thức forUser trên facade Gate:

if (Gate::forUser($user)->allows('update-post', $post)) {
    // The user can update the post...
}

if (Gate::forUser($user)->denies('update-post', $post)) {
    // The user can't update the post...
}

Policy

Tạo policy

Policy là các class quản lý logic trong phân quyền liên quan đến một Model hoặc tài nguyên nào đó. Ví dụ, nếu ứng dụng của bạn là một blog, bạn có thể có một model Post và một policy là PostPolicy để phân quyền các hành động người dùng như tạo hay cập nhật các bài viết. Bạn có thể tạo ra một policy bằng cách sử dụng câu lệnh Artisan make:policy, các policy được tạo ra sẽ được đặt trong thư mục app\Policies. Nếu thư mục này không tồn tại trong project, Laravel sẽ tự động tạo nó cho bạn:

php artisan make:policy PostPolicy

Câu lệnh make:policy sẽ sinh ra một class policy rỗng, nếu bạn muốn sinh ra một CRUD policy bạn cần thêm tham số –model khi thực thi câu lệnh artisan:

php artisan make:policy PostPolicy --model=Post

Đăng ký Policy

Một policy muốn sử dụng cần được đăng ký, AuthServiceProvider được đưa vào trong project Laravel chứa một thuộc tính policies để map Eloquent model với các policy tương ứng. Đăng ký một policy sẽ chỉ dẫn cho Laravel policy nào sẽ được sử dụng để phân quyền hành động cho model nào:

<?php

namespace App\Providers;

use App\Post;
use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        Post::class => PostPolicy::class,
    ];

    /**
     * Register any application authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        //
    }
}

Logic nghiệp vụ trong Policy

Phương thức Policy Khi Policy được đăng ký, bạn có thể thêm các phương thức cho mỗi hành động cần cấp quyền. Ví dụ, định nghĩa phương thức update trên PostPolicy để xác định một user có thể cập nhật một thực thể Post. Phương thức update sẽ nhận được một User và Post như là tham số và nó trả về true hoặc false để nhận diện xem người dùng này có được phân quyền để cập nhật Post không? Trong ví dụ dưới đây, chỉ có người dùng đã viết bài mới có quyền cập nhật bài viết

<?php

namespace App\Policies;

use App\User;
use App\Post;

class PostPolicy
{
    /**
     * Determine if the given post can be updated by the user.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return bool
     */
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

Bạn có thể tiếp tục định nghĩa các phương thức khác trên policy này nếu cần phân quyền cho các hành động. Ví dụ, bạn có thể định nghĩa phương thức view hoặc delete để phân quyền các hành động Post khác và nhớ rằng tên các phương thức trong policy là hoàn toàn bạn có thể đặt thoải mái nếu thích.

Route Model Binding

Có những phương thức policy chỉ nhận người dùng được xác thực hiện tại và không cần một thực thể của một Model. Tình huống này dùng khi phân quyền một hành động create. Ví dụ, nếu bạn tạo một blog, bạn có thể muốn kiểm tra nếu một người dùng có được phân quyền để tạo một post bất kỳ không. Khi định nghĩa phương thức trong policy nó sẽ không nhận một thực thể của Model, như phương thức create, nó sẽ không nhận một thực thể của model. Thay vào đó, bạn nên định nghĩa phương thức chỉ với người dùng đã được xác thực.

/**
 * Determine if the given user can create posts.
 *
 * @param  \App\User  $user
 * @return bool
 */
public function create(User $user)
{
    //
}

Policy Filter

Với người dùng hiện tại, bạn muốn cấp quyền thực hiện các hành động trong một chính sách, để thực hiện bạn định nghĩa phương thức before trong policy. Phương thức before sẽ thực thi trước bất kỳ phương thức nào trong policy, nó cho bạn cơ hội để cho phép thực hiện hành động trước khi phương thức của policy mong muốn được gọi. Tính năng này rất thông dụng để cho phép các administrator có thể thực hiện bất kỳ hành động nào:

public function before($user, $ability)
{
    if ($user->isSuperAdmin()) {
        return true;
    }
}

Nếu bạn muốn một user không được phép thực hiện bất kỳ gì bạn chỉ cần trả về false trong phương thức before. Nếu null được trả về, việc cấp quyền sẽ được tiếp tục trong phương thức policy.

3. Cho phép thực hiện hành động sử dụng Policy

Thông qua User Model Model User được tạo sẵn trong project Laravel chứa hai phương thức có sẵn là can và cant. Phương thức can nhận hành động bạn muốn cấp phép và model liên quan. Ví dụ, để xác định một người dùng được phép cập nhật model Post không?

if ($user->can('update', $post)) {
    //
}

Thực hành Laravel Authorization

Chúng ta cùng xem xét một ví dụ về phân quyền trong một tờ báo điện tử bao gồm hai chức danh là phóng viên và biên tập viên.

  • Phóng viên có thể viết một bài báo mới
  • Phóng viên có thể cập nhật nội dung bài báo của họ.
  • Biên tập viên có thể cập nhật nội dung bài báo.
  • Biên tập viên có thể phát hành bài báo.

Như vậy phóng viên không thể tự phát hành bài báo và biên tập viên không thể tạo ra bài báo mới mà chỉ có quyền cập nhật và xuất bản. Chúng ta sẽ từng bước thiết kế và phát triển ứng dụng web này, nó sẽ giúp bạn hiểu cạn kẽ về Laravel Authorization.

Cài đặt môi trường Laravel

Cài đặt môi trường Laravel rất đơn giản, bạn tham khảo bài Cài đặt Laravel dễ dàng với Laragon (trong bài này sẽ lấy tên project là allaravel nhé). Tiếp theo, chúng ta thực hiện cài đặt xác thực với Laravel Authentication. Đây là những phần rất cơ bản của Laravel, bạn nên làm quen vì hầu hết các dự án mới sẽ bắt đầu bằng bước này. Kiểm tra xem môi trường hoạt động tốt chưa, mở đường dẫn http://allaravel.dev.

Tạo database, dữ liệu test với Laravel Migrate và Laravel Seeding

Việc đầu tiên của dự án báo điện tử là thiết kế database, chúng ta sẽ có 4 bảng như sau:

  • Posts: chứa các bài báo
  • Users: chứa thông tin người dùng hệ thống, được tạo khi sử dụng Laravel Authentication.
  • Roles: chứa các chức danh và quyền hạn của từng chức danh
  • Role_users: gán từng người dùng với chức danh.

Thiết kế cơ sở dữ liệu

Bạn nên tham khảo về Laravel Migrate và Laravel Seeding nếu chưa làm quen các khái niệm này.

Tạo file migrate cho cơ sở dữ liệu

Đầu tiên, chúng ta sử dụng câu lệnh artisan để tạo ra model Post kèm theo với controller PostController và file migrate bằng cách sử dụng các tùy chọn -m và -c.

php artisan make:model Post -m -c

Với câu lệnh này chúng ta có:

  • Model Post trong file app\Post.php.
  • Post Controller trong file app\Http\Controllers\PostController.php.
  • File migrate nằm trong databases\migrations\yyyy_mm_dd_xxxxxx_create_post_table.php.

Xử lý file migrate để tạo bảng post trong cơ sở dữ liệu, thiết lập các trường của bảng post như sau:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->string('slug')->unique();
            $table->text('body');
            $table->boolean('published')->default(false);
            $table->unsignedInteger('user_id');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

Tiếp đến chúng ta tạo model Role kèm theo controller và file migrate:

php artisan make:model Role -m -c

Tạo các trường cho bảng roles với file migrate databases\migrations\yyyy_mm_dd_xxxxxx_create_roles_table.php:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateRolesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('slug')->unique();
            $table->jsonb('permissions')->default('{}');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('roles');
    }
}

Chú ý: trường permission chúng ta sẽ chứa một dữ liệu json thay vì tách ra thành một bảng riêng. Tiếp theo là bảng role_users chỉ cần tạo bảng do đó sử dụng câu lệnh artisan make:migrate

php artisan make:migration create_role_users_table

và định nghĩa các trường của bảng role_users trong file migrate databases\migrations\yyyy_mm_dd_xxxxxx_create_role_users_table

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateRoleUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('role_users', function (Blueprint $table) {
            $table->unsignedInteger('user_id');
            $table->unsignedInteger('role_id');
            $table->timestamps();

            $table->unique(['user_id','role_id']);
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('role_users');
    }
}

Thiết kế model map từ database sang class

Trong phần 4.1 chúng ta đã cài đặt phần xác thực cho Laravel, nó tạo ra bảng user, model User tuy nhiên model này chưa có phần phân quyền. Chúng ta sẽ thêm hai phương thức cho model User:

  • hasAccess(): kiểm tra xem người dùng có quyền thực hiện một hành động nào đó không.
  • inRole(): kiểm tra xem một người dùng có thuộc về một chức danh nào đó không.
<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    public function roles()
    {
        return $this->belongsToMany(Role::class, 'role_users');
    }

    /**
     * Checks if User has access to $permissions.
     */
    public function hasAccess(array $permissions) : bool
    {
        // check if the permission is available in any role
        foreach ($this->roles as $role) {
            if($role->hasAccess($permissions)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Checks if the user belongs to role.
     */
    public function inRole(string $roleSlug)
    {
        return $this->roles()->where('slug', $roleSlug)->count() == 1;
    }
}

Model User có quan hệ nhiều – nhiều với model Role thông qua bảng role_users (Xem bài xử lý quan hệ trong database với Laravel ORM Eloquent). Tiếp theo, chúng ta thay đổi model Role

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    protected $fillable = [
        'name', 'slug', 'permissions',
    ];
    protected $casts = [
        'permissions' => 'array',
    ];

    public function users()
    {
        return $this->belongsToMany(User::class, 'role_users');
    }

    public function hasAccess(array $permissions) : bool
    {
        foreach ($permissions as $permission) {
            if ($this->hasPermission($permission))
                return true;
        }
        return false;
    }

    private function hasPermission(string $permission) : bool
    {
        return $this->permissions[$permission] ?? false;
    }
}

và cuối cùng là model Post

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = [
        'title', 'slug', 'body', 'user_id'
    ];

    public function owner()
    {
        return $this->belongsTo(User::class);
    }

    public function scopePublished($query)
    {
        return $query->where('published', true);
    }

    public function scopeUnpublished($query)
    {
        return $query->where('published', false);
    }
}

Trong model Post sử dụng hai local scope là published và unpublished để tiện cho các truy vấn sau này.

Tạo dữ liệu test

Chúng ta đã tạo xong các file migrate, chúng ta thêm dữ liệu kiểm thử vào bằng Laravel Seeding. Tạo các file seeder cho Role, User và Post như sau:

php artisan make:seeder RolesSeeder
php artisan make:seeder UsersSeeder
php artisan make:seeder PostsSeeder

Chúng ta sẽ tạo dữ liệu kiểm thử trong file vừa tạo ra databases\seeds\RolesSeeder.php như sau:

<?php

use Illuminate\Database\Seeder;
use App\Role;

class RolesSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $author = Role::create([
            'name' => 'Phóng viên', 
            'slug' => 'author',
            'permissions' => [
                'post.create' => true,
            ]
        ]);
        $editor = Role::create([
            'name' => 'Biên tập viên', 
            'slug' => 'editor',
            'permissions' => [
                'post.update' => true,
                'post.publish' => true,
            ]
        ]);
    }
}

Role author sẽ sử dụng cho phóng viên còn role editor sẽ sử dụng cho biên tập viên. Tiếp đến là databases\seeds\UsersSeeder.php:

<?php

use Illuminate\Database\Seeder;
use App\User;
use App\Role;

class UsersSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $author = Role::where('slug', 'author')->first();
        $editor = Role::where('slug', 'editor')->first();

        $user1 = User::create([
            'name' => 'Phóng viên 1', 
            'email' => 'pv1@allaravel.dev',
            'password' => bcrypt('123456')
        ]);
        $user1->roles()->attach($author);

        $user2 = User::create([
            'name' => 'Phóng viên 2', 
            'email' => 'pv2@allaravel.dev',
            'password' => bcrypt('123456')
        ]);
        $user2->roles()->attach($author);

        $user3 = User::create([
            'name' => 'Biên tập viên 1', 
            'email' => 'btv1@allaravel.dev',
            'password' => bcrypt('123456')
        ]);
        $user2->roles()->attach($editor);
    }
}

và databases\seeds\PostsSeeder.php:

<?php

use Illuminate\Database\Seeder;
use App\User;
use App\Post;

class PostsSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $author1 = User::where('email', 'pv1@allaravel.dev')->first();
        $author2 = User::where('email', 'pv2@allaravel.dev')->first();
        $faker = Faker\Factory::create();
        for ($i=0; $i < 10; $i++) { 
          $title = $faker->sentence($nbWords = 6, $variableNbWords = true);
          $post = Post::create([
              'title' => $title, 
              'body' => $faker->text($maxNbChars = 1000),
              'slug' => str_slug($title),
              'published' => rand(0,1),
              'user_id' => $author1->id
          ]);
          $title = $faker->sentence($nbWords = 6, $variableNbWords = true);
          $post = Post::create([
              'title' => $title, 
              'body' => $faker->text($maxNbChars = 1000),
              'slug' => str_slug($title),
              'published' => rand(0,1),
              'user_id' => $author2->id
          ]);
        }
    }
}

Chú ý, gọi đến các Seeder này trong databases\seeds\DatabaseSeeder.php:

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->call(\RolesSeeder::class);
        $this->call(\UsersSeeder::class);
        $this->call(\PostsSeeder::class);
    }
}

Ok, vậy là phần chuẩn bị khung cho cơ sở dữ liệu và đưa vào dữ liệu kiểm thử đã xong, để thực hiện các công việc này trên database sử dụng lệnh artisan migrate với tùy chọn –seed

php artisan migrate --seed

Thiết lập chính sách phân quyền

Câu lệnh make:policy giúp tạo ra một class policy để chứa các logic về phân quyền. Trong ví dụ hiện tại, chúng ta có model Post tương ứng với class PostPolicy để phân quyền các hành động của người dùng như tạo mới bài viết, cập nhật bài viết.

php artisan make:policy PostPolicy --model=Post
Policy created successfully.

Thiết lập các chính sách truy cập trong file app\Policies\PostPolicy.php

<?php

namespace App\Policies;

use App\User;
use App\Post;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
    use HandlesAuthorization;

    public function view(User $user, Post $post)
    {
        //
    }

    public function create(User $user)
    {
        return $user->hasAccess(['post.create']);
    }

    public function update(User $user, Post $post)
    {
        return $user->hasAccess(['post.update']) or $user->id == $post->user_id;
    }

    public function delete(User $user, Post $post)
    {
        //
    }

    public function publish(User $user)
    {
        return $user->hasAccess(['post.publish']);
    }

    public function draft(User $user)
    {
        return $user->inRole('editor');
    }
}

Đăng ký chính sách với hệ thống trong app\Providers\AuthServiceProvider.php:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Policies\PostPolicy;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Gate::resource('post', PostPolicy::class);
        Gate::define('post.publish', PostPolicy::class . '@publish');
        Gate::define('post.draft', PostPolicy::class . '@draft');
    }
}

Định nghĩa các route liên quan đến post và có kiểm tra quyền truy xuất trong routes\web.php

Route::get('/', 'PostController@index');
Route::get('/posts', 'PostController@index')->name('list_posts');
Route::group(['prefix' => 'posts'], function () {
    Route::get('/drafts', 'PostController@drafts')
        ->name('list_drafts')
        ->middleware('auth');
    Route::get('/show/{id}', 'PostController@show')
        ->name('show_post');
    Route::get('/create', 'PostController@create')
        ->name('create_post')
        ->middleware('can:post.create');
    Route::post('/create', 'PostController@store')
        ->name('store_post')
        ->middleware('can:post.create');
    Route::get('/edit/{post}', 'PostController@edit')
        ->name('edit_post')
        ->middleware('can:post.update,post');
    Route::post('/edit/{post}', 'PostController@update')
        ->name('update_post')
        ->middleware('can:post.update,post');
    Route::get('/publish/{post}', 'PostController@publish')
        ->name('publish_post')
        ->middleware('can:post.publish');
});

Các phần phát triển ứng dụng khác

Trong phần này, chúng ta sẽ xử lý các công việc còn lại là tạo ra các view và chuẩn bị dữ liệu cho các view này thông qua controller. Trong phần 4.2 khi tạo ra model Post chúng ta cũng đã tạo ra PostController, thực hiện xử lý logic cho từng route trước khi định tuyến đến view.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;
use App\Http\Requests\StorePost as StorePostRequest;
use App\Http\Requests\UpdatePost as UpdatePostRequest;
use Auth;
use Gate;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::published()->paginate();
        return view('posts.index', compact('posts'));
    }

    public function create()
    {
        return view('posts.create');
    }

    public function store(StorePostRequest $request)
    {
        $data = $request->only('title', 'body');
        $data['slug'] = str_slug($data['title']);
        $data['user_id'] = Auth::user()->id;
        $post = Post::create($data);
        return redirect()->route('edit_post', ['id' => $post->id]);
    }

    public function edit(Post $post)
    {
        return view('posts.edit', compact('post'));
    }

    public function update(Post $post, UpdatePostRequest $request)
    {
        $data = $request->only('title', 'body');
        $data['slug'] = str_slug($data['title']);
        $post->fill($data)->save();
        return back();
    }

    public function show($id)
    {
        $post = Post::published()->findOrFail($id);
        return view('posts.show', compact('post'));
    }

    public function publish(Post $post)
    {
        $post->published = true;
        $post->save();
        return back();
    }

    public function drafts()
    {
        $postsQuery = Post::unpublished();
        if(Gate::denies('post.draft')) {
            $postsQuery = $postsQuery->where('user_id', Auth::user()->id);
        }
        $posts = $postsQuery->paginate();
        return view('posts.drafts', compact('posts'));
    }
}

Tiếp theo, thực hiện tạo master layout và các view phục vụ cho các route liên quan. Tạo file app\resources\views\layouts\app.blade.php:

<!DOCTYPE html>
<html lang="vi">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="Ví dụ phân quyền trong báo điện tử sử dụng Laravel Authorization">
        <meta name="author" content="FB [allaravel.com]">
        <title>Ví dụ Laravel Authorization - Allaravel.com</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
        <link href="https://getbootstrap.com/docs/3.3/examples/jumbotron/jumbotron.css" rel="stylesheet">
    </head>
    <body>
        <nav class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="">Allaravel</a>
                </div>
                <div class="collapse navbar-collapse" id="app-navbar-collapse">
                    <ul class="nav navbar-nav navbar-right">
                        @if (Auth::guest())
                            <li><a href="{{ route('login') }}">Đăng nhập</a></li>
                            <li><a href="{{ route('register') }}">Đăng ký</a></li>
                        @else
                            <li class="dropdown">
                                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
                                    {{ Auth::user()->name }} <span class="caret"></span>
                                </a>

                                <ul class="dropdown-menu" role="menu">
                                    <li>
                                        <a href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> Đăng xuất </a>
                                        <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
                                            {{ csrf_field() }}
                                        </form>
                                    </li>
                                    <li>
                                        <a href="{{ route('list_drafts') }}">Bài chưa đăng</a>
                                    </li>
                                </ul>
                            </li>
                        @endif
                    </ul>
                </div>
            </div>
        </nav>
        <div class="container" style="margin-top: 50px;">
            @yield('content')
            <hr>
            <footer>
                <p>© 2017 <a href="https://allaravel.com">Allaravel.com</a>.</p>
            </footer>
        </div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    </body>
</html>

Các view cho các hành động với user như đăng nhập, đăng ký. app\resources\views\auth\login.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Đăng nhập</div>
                <div class="panel-body">
                    <form class="form-horizontal" method="POST" action="{{ route('login') }}">
                        {{ csrf_field() }}

                        <div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
                            <label for="email" class="col-md-4 control-label">Địa chỉ email</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" required autofocus>

                                @if ($errors->has('email'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('email') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
                            <label for="password" class="col-md-4 control-label">Mật khẩu</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control" name="password" required>

                                @if ($errors->has('password'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                <div class="checkbox">
                                    <label>
                                        <input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}> Ghi nhớ
                                    </label>
                                </div>
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-8 col-md-offset-4">
                                <button type="submit" class="btn btn-primary">
                                    Đăng nhập
                                </button>

                                <a class="btn btn-link" href="{{ route('password.request') }}">
                                    Quên mật khẩu?
                                </a>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

app\resources\views\auth\register.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Đăng ký tài khoản</div>
                <div class="panel-body">
                    <form class="form-horizontal" method="POST" action="{{ route('register') }}">
                        {{ csrf_field() }}

                        <div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
                            <label for="name" class="col-md-4 control-label">Họ và tên</label>

                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control" name="name" value="{{ old('name') }}" required autofocus>

                                @if ($errors->has('name'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('name') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
                            <label for="email" class="col-md-4 control-label">Địa chỉ Email</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" required>

                                @if ($errors->has('email'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('email') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
                            <label for="password" class="col-md-4 control-label">Mật khẩu</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control" name="password" required>

                                @if ($errors->has('password'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group">
                            <label for="password-confirm" class="col-md-4 control-label">Nhập lại mật khẩu</label>

                            <div class="col-md-6">
                                <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
                            </div>
                        </div>

                        <div class="form-group{{ $errors->has('role') ? ' has-error' : '' }}">
                            <label for="role" class="col-md-4 control-label">Chức danh</label>

                            <div class="col-md-6">
                                <select id="role" class="form-control" name="role" required>
                                @foreach($roles as $id => $role)
                                    <option value="{{$id}}">{{$role}}</option>
                                @endforeach
                                </select>

                                @if ($errors->has('role'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('role') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                <button type="submit" class="btn btn-primary">
                                    Đăng ký
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Các view cho việc tạo, cập nhật bài viết và các hành động khác như danh sách bài viết chưa đăng, hiển thị chi tiết app\resources\views\posts\index.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        @foreach($posts as $post)
        <div class="col-md-4">
            <h2>{{ $post->title }}</h2>
            <p>{{ str_limit($post->body, 100) }}</p>
            <p><a class="btn btn-default" href="{{ route('show_post', ['id' => $post->id]) }}" role="button">Chi tiết »</a></p>
        </div>
        @endforeach
    </div>
</div>
@endsection

app\resources\views\posts\create.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-12">
            <div class="panel panel-default">
                <div class="panel-heading">Bài viết mới</div>
                <div class="panel-body">
                    <form class="form-horizontal" role="form" method="POST" action="{{ route('store_post') }}">
                        {{ csrf_field() }}
                        <div class="form-group{{ $errors->has('title') ? ' has-error' : '' }}">
                            <label for="title" class="col-md-3 control-label">Tiêu đề</label>
                            <div class="col-md-9">
                                <input id="title" type="text" class="form-control" name="title" value="{{ old('title') }}" required autofocus>
                                @if ($errors->has('title'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('title') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group{{ $errors->has('body') ? ' has-error' : '' }}">
                            <label for="body" class="col-md-3 control-label">Nội dung</label>
                            <div class="col-md-9">
                                <textarea name="body" id="body" cols="30" rows="8" class="form-control" required>{{ old('body') }}</textarea>
                                @if ($errors->has('body'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('body') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-md-9 col-md-offset-3">
                                <button type="submit" class="btn btn-success">
                                    Tạo bài viết mới
                                </button>
                                <a href="{{ route('list_posts') }}" class="btn btn-success">
                                    Hủy bỏ
                                </a>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

app\resources\views\posts\edit.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-12">
            <div class="panel panel-default">
                <div class="panel-heading">Cập nhật bài viết</div>
                <div class="panel-body">
                    <form class="form-horizontal" role="form" method="POST" action="{{ route('update_post', ['post' => $post->id]) }}">
                        {{ csrf_field() }}
                        <div class="form-group{{ $errors->has('title') ? ' has-error' : '' }}">
                            <label for="title" class="col-md-3 control-label">Tiêu đề</label>
                            <div class="col-md-9">
                                <input id="title" type="text" class="form-control" name="title" value="{{ old('title', $post->title) }}" required autofocus>
                                @if ($errors->has('title'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('title') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group{{ $errors->has('body') ? ' has-error' : '' }}">
                            <label for="body" class="col-md-3 control-label">Nội dung</label>
                            <div class="col-md-9">
                                <textarea name="body" id="body" cols="30" rows="8" class="form-control" required>{{ old('body', $post->body) }}</textarea>
                                @if ($errors->has('body'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('body') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-md-9 col-md-offset-3">
                                <button type="submit" class="btn btn-success">
                                    Cập nhật
                                </button>
                                @can('post.publish')
                                <a href="{{ route('publish_post', ['post' => $post->id]) }}" class="btn btn-success">
                                    Xuất bản
                                </a>
                                @endcan
                                <a href="{{ route('list_posts') }}" class="btn btn-default">
                                    Hủy bỏ
                                </a>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

app\resources\views\posts\drafts.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        @foreach($posts as $post)
        <div class="col-md-4">
            <h2>{{ $post->title }}</h2>
            <p>{{ str_limit($post->body, 100) }}</p>
            <p>
                <a class="btn btn-success" href="{{ route('edit_post', ['id' => $post->id]) }}" role="button">Chỉnh sửa</a>
                @can('post.publish')
                    <a class="btn btn-success" href="{{ route('publish_post', ['id' => $post->id]) }}" role="button">Xuất bản</a>
                @endcan
            </p>
        </div>
        @endforeach
    </div>
</div>
@endsection

app\resources\views\posts\show.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-12">
            <h2>{{ $post->title }}</h2>

            <p>{{ $post->body }}</p>
        </div>
    </div>
</div>
@endsection

app\resources\views\errors\403.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-12">
            <h2>Bạn không có quyền truy nhập đường dẫn này.</h2>
        </div>
    </div>
</div>
@endsection

Chạy thử ứng dụng

Khi vào màn hình trang chủ http://allaravel.dev, chúng ta sẽ thấy một số các bài viết đã được xuất bản

Phân quyền người dùng với Laravel Authorization

Khi đăng nhập vào bằng user pv1@allaravel.dev và pv2@allaravel.dev chúng ta thấy các tài khoản này chỉ được tạo mới và cập nhật bài viết.

Phân quyền người dùng với Laravel Authorization

Phóng viên 1 có thể chỉnh sửa bài viết có id 32 và sửa đường dẫn thành http://allaravel.dev/posts/publish/32 để xuất bản bài viết nhưng do Phóng viên 1 không có quyền xuất bản do đó sẽ gặp thông báo lỗi “Bạn không có quyền truy nhập đường dẫn này”.

Phân quyền người dùng với Laravel Authorization

Đăng nhập vào user Biên tập viên 1, chúng ta thấy user này không có quyền tạo bài viết mới.

Phân quyền người dùng với Laravel Authorization


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

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

Xem thêm Việc làm lập trình Laravel hấp dẫn trên TopDev

Thực thi kiểm thử tự động Selenium với Selenium-Grid

Thực thi kiểm thử tự động Selenium với Selenium-Grid

Bài viết được sự cho phép của vntesters.com

Selenium-Grid là một chế độ thực thi kiểm thử của Selenium mà ban đầu chỉ hỗ trợ cho Selenium RC như mình có nói ở bài trước. Tuy nhiên, sau này, đội ngũ phát triển của Selenium đã phát triển công cụ này cho cả Selenium WebDriver (Selenium 2).

Selenium-Grid cho phép người dùng thực thi kiểm thử trên nhiều máy khác nhau với nhiều trình duyệt khác nhau. Đặc biệt hơn nữa là, Selenium-Grid còn cho phép chúng ta thực thi kiểm thử với chế độ phân tán.

  Selenium là gì? Một số kinh nghiệm làm việc với Selenium
  Selenium – Xác Định Đối Tượng UI

Thiết lập môi trường cho Selenium-Grid

Để thiết lập môi trường cho Selenium-Grid, đâu tiên chúng ta cần cài đặt Java. Để kiểm tra PC có Java hay không, chúng ta có thể chạy câu lệnh này ở Command Line:

java –version

Thực thi kiểm thử tự động Selenium với Selenium-Grid

Nếu máy các bạn có Java thì version hiện tại của Java sẽ được trả về. Các bạn cố gắng lấy version mới nhất của Java nha.

Selenium Server

Kế tiếp là chúng ta cần có Selenium Server. Các bạn có thể download phiên bản mới nhất của Selenium Server ở đây.

Sau khi download Selenium Server về máy, chúng ta cần kiểm tra để chắc chắn rằng chương trình này có thể được sử dụng trên PC của chúng ta.

java –jar selenium-server-standalone-*.jar

Thực thi kiểm thử tự động Selenium với Selenium-Grid

Nếu mọi chuyện OK, INFO: Launching a standalone server sẽ được trả về.

Hub và Node

Hub

  • Hub là trung tâm phân phối nơi mà chúng ta gửi lệnh đến.
  • Chúng ta chỉ có một và chỉ một Hub trong một Selenium-Grid
  • Hub chỉ có thể được thiết lập trên một máy
  • Máy được thiết lập cho Hub là nơi kịch bản kiểm thử được thực thi, nhưng mà chúng ta sẽ thất trình duyện chạy ở trên Node

Node

  • Node là nơi các trình duyện chạy các kịch bản kiểm thử mà chúng ta đưa vào hub
  • Có thể có nhiều node trong một Grid
  • Node có thể được thiết lập trên nhiều máy với nhiều trình duyệt khác nhau

Thiết lập Hub và Node

Khởi động Hub với câu lệnh:

java –jar selenium-server-standalone-*.jar -role hub

Thực thi kiểm thử tự động Selenium với Selenium-Grid

Sau khi thực thi câu lệnh khởi tạo Hub, chúng ta có thể vào http://localhost:4444/grid/console để kiểm tra Hub được khởi tạo thành công.

Thực thi kiểm thử tự động Selenium với Selenium-Grid

Thiết lập Node với câu lệnh

java -jar selenium-server-standalone-*.jar -role node  -hub [Hub URL]/register

Thực thi kiểm thử tự động Selenium với Selenium-Grid

Như vậy là chúng ta đã thiết lập được một node trên một hub và sẵn sàng để sử dụng Selenium-Grid thực thi các kịch bản kiểm thử Selenium.

Mã nguồn để sử dụng Selenium-Grid

URL hubUrl = new URL(“http://[Hub URL]:4444/wd/hub”);
DesiredCapabilities capabilities = DesiredCapabilities.Firefox();
driver = new RemoteWebDriver(hubUrl, capabilities);

Như vậy, chúng ta đã có thể sử dụng Selenium-Grid cho việc thực thi kiểm thử tự động.

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

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

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

Khám phá phong cách hợp tác của bạn

phong cách hợp tác

Bạn đã bao giờ tìm hiểu về phong cách hợp tác cá nhân chưa? Nó thật sự là một điều quan trọng đấy. Tại sao? Vì hiệu quả của sự kết nối, tương tác trực tiếp, làm việc nhóm đều chịu sự chi phối của phong các hợp tác.

Phong cách hợp tác là yếu tố cần khai thác trước khi bạn tiến hành thực hiện công việc, đặc biệt là giải quyết nhiệm vụ với tư cách là một nhóm. Mỗi phong cách hợp tác sẽ thể hiện các đặc trưng dấu ấn về cá tính của từng cá nhân. Đó là cơ sở để bạn có thể lựa chọn ra những người cộng sự phù hợp nhất.

Cùng TopDev tìm ra phong cách của riêng bạn thông qua bài viết sau nhé.

Người “độc tài”

Nếu thuộc nhóm này, bạn sẽ dễ dàng nhận ra các lợi ích tốt nhất cho dự án của bạn. Và tất nhiên, bạn rất chủ động trong việc lập kế hoạch; muốn chia sẻ và trình bày cụ thể chúng với những cộng sự của bạn.

phong cách hợp tác

Bạn là người có một sự tập trung cực kỳ cao, luôn theo sát các thông số báo cáo mô tả tiến trình hoạt đồng. Đồng thời, bạn chủ động tìm kiếm các thông tin cập nhật từ nhóm. Do có sự kỳ vọng quá lớn, đôi lúc bạn cảm thấy một dự án nào đó có thể bị ảnh hưởng nếu thiếu đi sự cảnh giác của bạn. Một freelancer IT là người biết vận dụng nhiều kỹ năng. Và tất nhiên, năng lực tập trung tuyệt đối là rất quan trọng.

Xem thêm các việc làm về tuyển dụng Data Scientist 

Đồng ý rằng việc giám sát và quản lý chặt chẽ các đầu công việc là một điều tốt. Đó cũng là cách để hạn chế những sai sót có thể xảy ra. Và bạn cũng cho thấy được, bạn thật sự là một cá nhân có trách nhiệm với nhóm của mình. Tuy nhiên, bạn nên thảo luận, đánh giá và tạo cơ hội cho các thành viên trong nhóm phản hồi.

Có như vậy, một chiến dịch sẽ được theo dõi chặt chẽ và hiệu quả hơn do được đảm bảo về tính minh bạch, tính thống nhất về quan điểm thiết lập quy trình giải quyết công việc. 

Người “tích trữ”

Với phong cách cộng tác này, bạn thuộc tuýp người thích ghi chú lại một cách chi tiết, lưu trữ và thống kê thông tin về từng giai đoạn, tiến độ phát triển. Để tối ưu hóa, bạn đã có thể lưu tất cả các email, tạo liên kết. Ngoài ra, bạn có thể cập nhập, chỉnh sửa – bổ sung các nội dung có liên quan đến dự án.

phong cách hợp tác

Đặc biệt, với cách phân bổ hợp lý, không quá khó để bạn tra cứu các thông tin. Chính điều này đã giúp nhóm của bạn sở hữu nguồn tư liệu đa dạng hơn. Thế nhưng, bạn không nên  quá tập trung vào việc quản lý dữ liệu của riêng bạn. Hãy quan tâm đến các đồng đội vì các bạn là một team.

Người “phân tích”

Với khả năng tư duy nhanh nhạy và nhiều đa dạng về góc nhìn, bạn tự thúc đẩy bản thân muốn tìm hiểu và thực hiện khai thác, phân tích dự án một cách chi tiết. Vì là phân tích nên bạn thường sử dụng những kiến thức được minh chứng cụ thể về số liệu. Do vậy, hầu như trong mọi trường hợp, bạn đều nhận được sự tin tưởng từ mọi người. Ngược lại, bạn cũng sẽ phản bác các quan điểm thiếu xác thực, chưa đảm bảo về những minh chứng. 

phong cách hợp tác

Xem thêm các việc làm NTQ Solution tuyển dụng

Nếu bạn phát hiện ra một vấn đề nào đó, đừng ngần ngại mà trao đổi mối quan tâm của bạn với các đồng đội của mình. Đừng tự ý xử lý một mình! Bình tĩnh thảo luận và nhận ý kiến để tránh tình trạng làm nổ tung do sự mất kiểm soát bất ngờ từ các số liệu đáng báo động.

Người “nuôi dưỡng”

Bạn là một người luôn tìm kiếm các tài liệu hữu ích cho các thành viên. Đồng thời, bạn cũng là người đầu tiên nhận phản hồi và chia sẻ các cập nhật. Là một freelancer it, bạn cũng thường xuyên hợp tác và giúp đỡ tra cứu tài liệu cùng các cộng sự. Chính việc quá “chăm sóc” cho nhu cầu đồng đội mà đôi khi, bạn lọt thõm trong chính nhiệm vụ của cá nhân mình.

phong cách cộng tác

Bạn là kiểu người hữu ích và quá nhiệt tình. Tuy vây, hãy chú ý đến bất kỳ nguyên tắc giao tiếp nào mà nhóm của bạn có thể chia sẻ một cách hiệu quả nhất. Cách tốt nhất chính là loại bỏ các đồng nghiệp không phản hồi các đề xuất ra khỏi dự án của bạn. 

Thực tập sinh/hướng đạo sinh

Nếu thuộc phong cách này, bạn là kiểu người ham học hỏi. Bạn sẵn sàng giúp đỡ các đồng nghiệp khi họ khó khăn. Quan trọng, bạn thật sự yêu thích làm việc trong một nhóm. Đối với bạn, việc nhận được những phản hồi, đánh giá của người khác về bản thân mình là một điều rất tuyệt vời.

Bạn có thể kiểm tra đặc điểm tính cách của bản thân để lựa chọn công việc phù hợp thông qua công cụ trắc nghiệm tính cách tại TopDev

Nếu bạn là người thuộc kiểu phong cách cộng tác này, hãy thật sự cởi mở với những ý tưởng nghe có vẻ như chúng hoàn toàn bất hòa với chính bạn. Và đừng quá ôm đồm nhiều thứ nếu giới hạn khả năng không cho phép. 

Xem ngay các tin tuyển dụng thực tập sinh IT mới nhất

Lời kết

Phong cách cộng tác không áp định bất cứ ai. Chính bạn thể hiện phong cách bản thân. Cá tính bạn ra sao, xu hướng hợp tác của bạn thế nào? Tất cả đều tạo nên giá trị con người trong bạn. Để hòa nhập với một môi trường làm việc hiện đại, bạn nên cân bằng tận dụng tốt; biết phát huy những phong cách cá nhân một cách phù hợp để đạt hiệu quả tốt trong công việc. TopDev hi vọng bạn sẽ vận dụng tốt phong cách hợp tác của bản thân và có những người cộng sự tuyệt vời.

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

Xem thêm tuyển dụng it lương cao hàng đầu tại TopDev

Functors trong JavaScript là gì?

functors là gì

Functors là gì? Đôi khi, logic chính xác sẽ là bất khả thi bởi sự phức tạp của data trong thế giới lập trình. Do đó, data trừu tượng (data abstraction) là một tool rất hữu ích giúp ta tạo một đại diện đơn giản cho data.

Để có thể đạt được điều này, chúng ta tạo ra ‘Containers’, những container này sẽ chỉ chứa data và không làm gì khác. Ta cũng không cung cấp cho chúng những properties hoặc methods như trong lập trình hướng đối tượng OOP.

Tìm hiểu 4 thuộc tính cơ bản của OOP là gì?

Khi cho một giá trị vào container thì nó sẽ giúp giữ giá trị đó được an toàn, trong khi được pass qua functional logic. Và ta chỉ lấy nó khi rất cần thiết. Như vậy, container có 2 task chính:

  • Chứa giá trị bên trong chính nó
  • Trả giá trị lại khi chúng ta cần

Và nó cũng không làm biến đổi giá trị.

Thật ra, những container này cũng không có gì mới, chúng ta đã sử dụng chúng kể từ khi bắt đầu JavaScripting.

Khi làm về functional programming, những containers này cực kì quyền năng, bởi chúng góp phần vào nền tảng cho cấu trúc của functional, và giúp chúng ta với những kĩ thuật như Pure Functional Error Handling và Asynchronous Actions (cùng nhiều cái khác nữa).

>>> Xem thêm về tính trừu tượng đuợc nhắc đến trong Bí thuật đơn giản hóa code của bạn

functors là gì

Trước khi đi sâu vào những container này thì mình sẽ nói về một loại container đặc biệt là Functors.

Functors là gì? Functors chính là container có thể được dùng với ‘map’ function.

Trước khi chúng ta tạo ra container cho riêng mình, hãy nhìn lại những loại container mà ta thường dùng trước đây:

Các loại container thường dùng

Arrays

functor là gì
Array

Arrays là loại container phổ biến nhất mà chúng ta thường dùng trong lập trình hàng ngày, thay vì chỉ chứa duy nhất một giá trị thì chúng chứa được nhiều hơn. Array là dạng đơn giản nhất của Data trừu tượng nhưng lại vô cùng mạnh mẽ.

const arr = [ 8, 10, 23, 35, 54 ];

Vậy giá trị ta có thể lấy ra giá trị trong như như sau

const b = a[1];

Giờ, nếu bạn hứa là chỉ dùng những operation này trong array, thì nó sẽ trở thành trợ thủ trung thành nhất của bạn.

Đừng bao giờ modify array như thế này:

arr.push(45) 
or
arr[1] = 45

Nhưng bạn có thể dùng nó để tạo ra các array mới

const arr2 = [ ...arr, 38, 52 ]
or
const even = filter(x => x%2 === 0, arr)

Chúng ta không thay đổi bất cứ giá trị nào trong array, mà chỉ đơn giản là tạo ra array hoặc lấy giá trị ra từ nó.

Và Array cũng chính là một Functor.

  9+ cách để xóa một phần tử ra khỏi JavaScript Array
  Các phương thức trên array cần nhớ

Một Functor là một container mà có thể được map lên bởi một Unary function.

Nói cách khác, container có thể sử dụng với những function đặc biệt (fmap hoặc map) và nó cũng áp dụng lên mọi unary function cho đến các nội dung trong container này.

functor là gì
Xe tải này là functor

Với array, function đặc biệt được gọi đơn giản là map function.

Map Function

Functor là gì
Tất nhiên không phải map này nha

Map function lấy một array và áp dụng một vài function cụ thể lên toàn bộ yếu tố của nó từng cái một và trả về một array khác.

[1,2,3,4].map(multiplyBy2) 
//=> [2,4,6,8]
or
map(multiplyBy2, [1,2,3,4]) 
//=> [2,4,6,8]
where multiplyBy2 = x => x * 2 and map = (fn, arr) => arr.map(fn)

Từ đó, chúng ta sẽ luôn có một array mới từ map, ta cũng có thể map nó để tạo ra một chain của array.

[1,2,3].map(x => x * 3).map(x => x * 2).map(x => x / 6)

Map function không chỉ đơn thuần là một iterator function, nên nhớ rằng, với giá trị trong một container ta không thể cứ trực tiếp áp dụng một function lên nó và chờ đợi giá trị thay đổi. Ví dụ:

const a = [1, 2, 3]
String(a) = ‘[1 ,2, 3]’ and not [‘1’, ‘2’, ‘3’]

Một map function sẽ cho function truy cập vào nội dung của content

map(String, [1, 2, 3]) = [‘1’, ‘2’, ‘3’]

Ngoài ra, map function không bao giờ thay đổi container, thay vào đó nó chỉ hành động dựa trên nội dung của container..

functor là gì

Một map sẽ không thay đổi loại của container nhưng nó sẽ thay đổi loại content bên trong.

Type của content có thể thay đổi, và chúng ta có thể xem từ type definition của map function.

map :: a -> b -> [a] -> [b]
or
fmap :: a -> b -> F a -> F b

Với  a và b có thể cùng hoặc khác loại.

Nếu bạn để ý kỹ thì map function đang lấy một function từ  a -> b  trả lại một function từ  Fa -> Fb

Tại đây, a -> b  có nghĩa là bất cứ unary function nào lấy a và trả lại b  như

multiplyBy2(3) = 6 // is a -> b as 3 -> 6

và Fa -> Fb ám chỉ bất kì unary function nào lấy một Container với a bên trong và trả lại một Container  với b bên trong.

multiplyArrBy2([1]) = [2] // is Fa -> Fb as [1] -> [2], F is []

Giờ map function đã thay đổi từ multiplyBy2 to multiplyArrBy2

const multiplyBy2 = no => no * 2

// We need to partially apply our map function to explain this

const map = mappingFn => arr => arr.map(mappingFn) 

// Now we create our new Function now that can act upon arrays

const multiplyArrBy2 = map(multiplyBy2)

Kể từ giờ, function multiplyBy2, vốn được dùng cho integer, sẽ hành động với array của integer. Nói cách khác, map function đã promote hoặc nâng function lên để nó có thể hành động trên containers hoặc arrays trong trường hợp này.

Ta thường áp dụng một phần map function khi có thể để tạo ra các function mới hoặc dùng nó với compose function, và khi có trường hợp cực kỳ khẩn cấp của Data thì ta sẽ dùng map function bình thường.

Vậy sao lại áp dụng một phần map function?

Trước khi đi xa hơn, hẳn bạn cũng đã hiểu là ta dùng container để chứa giá trị. Ta cũng biết về Functor, vốn là những container đặc biệt mà ta có thể dùng map operation lên nó. Mặt khác, ta cũng biết cách thức map function được dùng trên Arrays, ngoài bạn cũng đã biết cách tạo ra một Container và Functor từ những ví dụ trên.

Bây giờ, Tôi xin giới thiệu container tiếp theo vốn cũng là một functor. Container đã đi cùng chúng ta ngay từ khi cuộc phiêu lưu vừa mới băt đầu.

Functions

Thế nào mà Functions lại là container?

Container chứa data, nhưng function rõ ràng là chứa logic, thế thì làm sao function có thể là container?

Đó là bởi function, khi được called sẽ trả lại một giá trị. Thế nên ta có thể hiểu là nó chứa giá trị nhưng chỉ là giá trị đó được dynamically computed.

aFunction(45) // => 90
So aFunction gives the value 90, when it is passed 45

Hãy nghĩ chúng là những arrays chứa vô hạn các value và khi bạn muốn một giá trị nào đó thì phải call function như sao:

functor trong js
Funtion là array với value vô hạn

Vậy Function cũng chính là container như Array?

Đúng vậy! Như array đưa giá trị khi index được pass, function đưa kết quả khi một argument được pass

const a = [ 8, 10, 23, 35, 54 ]
const f = z => z * 2 
a[1] = 10
f(2) = 4

Chỉ có điều là Array yếu hơn khi nó chỉ cho kết quả khi các số nguyên là index. Còn function thì có thể lấy bất cứ type nào của arguments bởi không hề có một giới hạn nào. Thậm chí nó còn lấy những function khác làm arguments luôn.

Vậy nếu chúng là Functors thì hẳn cũng có map luôn đúng không?

Chính xác, nó là như thế này:

const fnMap = (f, mappingFn) => (x => f(mappingFn(x)))

Cũng như map function lấy array, áp dụng function vào content và trả lại array. Tương tự, fnMap lấy một function, áp dụng một function vào kết quả của nó và return lại function, theo cách mà nó kết hợp 2 function sao cho kết quả của một function là  argument của function thứ hai.

Được rồi hãy dùng thử cái này

const multiplyBy6 = fnMap(multiplyBy2, multiplyBy3)

Nhìn quen đúng không, đó là vì nó chính là Compose function.

Vậy function cũng có một map function và nếu ta mapping một function tới function khác, ta sẽ như đang kết hợp chúng lại và cho ra Compose function.

  • Ví dụ ta có một function là  multiplyBy2 
  • Trước khi lấy giá trị hay làm gì khác thì ta sẽ map nó với multiplyBy3
  • Vậy là toàn bộ giá trị trong  multiplyBy2 sẽ được nhân 3.
  • Do đó, khi ta call multiplyBy2  với giá trị  x thì kêt quả thu được sẽ là  x * 3 * 2

Như vầy thì hẳn bạn sẽ dễ hiểu hơn

const fnMap = (f, mappingFn) => (x => f(mappingFn(x)))

Functions cũng là arrays, một dạng data trừu tượng. Chỉ có function tính toán data theo yêu cầu của ta.

Nói cách khác, Array giống như function nhưng chỉ đưa giá trị ngay lập tức khi ta dùng ‘[]’ lên chúng.

Chỉ cần nhớ một điều rằng giá trị chỉ có ý nghĩa khi nó nằm trong một container. Do đó trong lập trình, đừng bao giờ sử dụng Data một cách thô sơ, hãy luôn cho nó vào trong container.

Vậy đấy! Tôi hi vọng bạn đã học được thêm nhiều điều từ bài viết này!

Tham khảo bài viết gốc tại hackernoon

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

Tham khảo việc làm javascript lương cao tại TopDev

System Design Cơ Bản: Message Broker

Message Broker

Bài viết được sự cho phép của tác giả Edward Thiên Hoàng

Trong kiến trúc cloud (hay microservices), các ứng dụng được chia thành những khối độc lập nhỏ hơn để có thể dễ dàng develop, deploy và maintain. Hãy thử tưởng tượng bạn có một kiến trúc cloud có nhiều service và nhiều request mỗi giây, bạn phải đảm bảo rằng không có bất cứ một request nào bị mất và web service của bạn luôn luôn sẵn sàng tiếp nhận request mới thay vì locked bởi đang xử lí request trước đó cũng như phải đảm bảo rằng các service giao tiếp với nhau một cách trơn tru và hiệu quả.

  Discord đã lưu trữ hàng tỉ messages mỗi ngày như thế nào
  Xây dựng ứng dụng realtime messaging bằng Firebase như TikTok, Bigo...

Vậy bạn làm thế nào? Câu trả lời đó chính là Message Broker!

MESSAGE BROKER LÀ GÌ?

Message broker (hay còn gọi là integration broker hoặc interface engine) là một module trung gian trung chuyển message từ người gửi đến người nhận. Nó là một mô hình kiến trúc (architentural pattern) để kiểm tra, trung chuyển và điều hướng message; làm trung gian giữa các ứng dụng với nhau, tối giản hóa giao tiếp giữa các ứng dụng đó và để tăng hiệu quả tối đa cho việc tách ra các khối nhỏ hơn. Nhiệm vụ chính của một Message broker là tiếp nhận những message từ các ứng dụng và thực hiện một thao tác nào đó.

Hiện tại có rất nhiều các message broker software có thể kể đến như: Amazon Web Services (AWS) Simple Queue Service (SQS), Apache Kafka, Apache ActiveMQ. Nhưng phổ biến nhất trong số những cái tên kể trên đó là RabbitMQ!

PHÂN LOẠI GIỮA CÁC HỆ THỐNG MESSAGE QUEUE

Nếu bạn là một backend-developer chắc hẳn bạn không còn xa lạ gì với những hệ thống message-queue. Hầu như project nào của mình cũng có sự xuất hiện của message-queue và việc khó khăn nhất là lựa chọn nên dùng cái nào và không nên dùng cái nào.

Thử tưởng tượng một ngày sếp của bạn muốn tích hợp một hệ thống message queue hoặc bạn cảm thấy nên sử dụng một hệ thống message queue để giải quyết bài toán mà team đang gặp phải. Bạn bắt đầu tìm kiếm và nhận ra rằng có quá nhiều hệ thống message queue tồn tại. Mình có thể liệt kê một số loạt mà mình biết dưới đây :

  • RabitMQ
  • ActiveMQ
  • Kafka
  • SQS
  • ZeroMQ
  • MSMQ
  • IronMQ
  • Kinesis
  • RocketMQ
  • Redis Pub/sub

Trong quá khứ mình đã có không ít lần lựa trọn sai và mọi sai lầm đều phải trả giá không ít thì nhiều.

Sau những sai lầm đó thì mình nhận ra một điều, đó là mặc dù cùng là message queue nhưng lại được chia làm 2 loại có mục đich sử dụng và những tính năng liên quan hoàn toàn khác nhau.

Mình tạm chia thành 2 loại như sau:

Message Base Data Pipeline
RabitMQ Kafka
ActiveMQ Kinesis
SQS RocketMQ
ZeroMQ
MSMQ
IronMQ
Redis Pub/sub

SO SÁNH CÁCH HOẠT ĐỘNG CỦA 2 LOẠI:

System Design Cơ Bản: Message Broker

Dựa vào bảng trên, ta có thể thấy được sự khác nhau cơ bản giữa 2 loại, cũng như cách sử dụng trong tưng bài toán cụ thể.

Đối với loại “message base”: là những loại message queue truyền thống, thích hợp làm hệ thống trao đổi message giữa các service. Việc đảm bảo mỗi consumer đều nhận được message và duy nhất một lần là quan trọng nhất.

Đối với loại “data-pipeline”, có cách lưu trữ message cũng như truyền tải message đến consumer hoàn toán khác với hệ thống message queue truyền thống. Việc đảm bảo mỗi consumer đều phải nhận được message và duy nhất một lần không phải là ưu tiên số một, mà thay vào đó là khả năng lưu trũ message vả tốc độ truyền tải message. Khi có message mới, consumer sẽ lựa chọn số lượng message mà mình muốn lấy, chính vì thế mà cùng một message consumer có thể nhận đi nhận lại nhiều lần. Những hệ thống sử dụng message queue loại này thường là hệ thống Event Sourcing, hoặc hệ thống đồng bộ dữ liệu từ những database khác nhau như Debezium.

Khi các bạn lựa chọn message queue cho hệ thống của mình, các bạn nên xác định rõ mục địch của hệ thống messague queue để xem mình cần loại trong hai loại trên. Việc xác định được loại message queue nào mình cần sẽ giúp các bạn giảm bớt thời gian tìm hiểu cũng như tìm được chính sác cái mà mình cần.

Đôi khi chúng ta cũng thấy một số hệ thống sẽ sử dụng nhiều loại message queue, thường sẽ là 1 của “message base” và 1 của “data pipeline” để tận dụng tối đa ưu điểm của từng loại vào giải quyết bài toán cụ thể.

MỘT SỐ MESSAGE BROKER PHỔ BIẾN

RABBITMQ

RabbitMQ là một message broker ( message-oriented middleware) sử dụng giao thức AMQP(Advanced Message Queue Protocol — Giao thức giao nhận tin nhắn sử dụng hàng đợi). Đây là chương trình đóng vai trò trung gian lưu trữ cũng như điều phối các yêu cầu (message) giữa người nhận(consumer) và người gửi(producer).

KAFKA

Kafka là nền tảng streaming phân tán, có thể mở rộng và là sản phẩm mã nguồn mở. Dự án Kafka ban đầu được phát triển bởi Linkedin sau đó trở thành dự án Apache mã nguồn mở vào năm 2011. Kafka được viết bằng ngôn ngữ Scala và Java. Nó được viết ra nhằm mục đích cung cấp một nền tảng mà có độ trễ thấp và thông lượng cao cho việc xử lý các nguồn cấp dữ liệu theo thời gian thực.

Kafka là gì? Tìm hiểu và ứng dụng Kafka cho hệ thống message tối ưu

REDIS PUB/SUB

Redis hỗ trợ Transaction, hỗ trợ Pub/Sub vì vậy nó cũng được sử dụng làm hệ thống Message Broker, kinh điển là RabbitMQ sử dụng Redis là core của hệ thống.

READ MORE:

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

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

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

Cách gỡ bỏ Adobe Flash. Tại sao Flash bị Adobe khai tử?

Cách gỡ bỏ Adobe Flash. Tại sao Flash bị Adobe khai tử?

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

Adobe Flash Player (hay còn gọi tắt là Flash) là một chương trình điện toán được cung cấp bởi Adobe System, công ty này cũng rất có tiếng nhờ làm ra phần mềm Photoshop và hàng loạt các phần mềm nổi tiếng khác nữa.

Cách gỡ bỏ Adobe Flash. Tại sao Flash bị Adobe khai tử?

Quay trở lại với Flash thì nó dùng kỹ thuật đồ họa Vector và đồ họa điểm với ngôn ngữ ActionScript để truyền tải các luồng âm thanh và hình ảnh trên trang web.

  12 plugin nên dùng trong Adobe XD
  Hadoop là gì? Kiến trúc của Hadoop

Khi sử dụng Flash các tập tin đồ họa, ảnh động có kích thước khá nhỏ nên nó rất phù hợp với thời kỳ Internet tốc độ chậm mà lại có nhiều người sử dụng. Nhờ vậy mà Flash đã phát triển vượt bậc trong khoảng thời gian từ năm 2000 đến năm 2010.

Hơi khó hiểu khi tên Flash được dùng để chỉ chương trình tạo ra các tập tin Flash (*.swf) và cũng được dùng để chỉ ứng dụng có nhiệm vụ thi hành hay hiển thị các tập tin Flash đó.

Tuy Flash có nhiều chức năng như vậy nhưng cuộc chơi nào cũng đến lúc tàn, Adobe Flash Player giờ đã hết đất sống. Và…

Sau ngày 31 tháng 12 năm 2020 thì Adobe sẽ không còn hỗ trợ Flash Player nữa, chính vì thế Adobe cũng sẽ chặn nội dung Flash chạy trong Flash Player kể từ ngày 12 tháng 1 năm 2021.

=> Vậy nên Adobe khuyên tất cả người dùng ngay lập tức gỡ cài đặt Flash Player để giúp bảo vệ hệ thống. Tránh bị hacker lợi dụng khai thác.

Cách gỡ bỏ Adobe Flash. Tại sao Flash bị Adobe khai tử?

Để tìm hiểu kỹ hơn về Adobe Flash Player thì bạn có thể đọc chi tiết hơn trong bài viết này nhé !

#1. Lý do Adobe khai tử Flash?

Về lý do khai tử Flash thì có khá nhiều lý do, nhưng chủ yếu là do bảo mật kém nên các trình duyệt web phổ biến hiện tại đều không còn hỗ trợ Flash nữa, cộng với sự phát triển quá tốt của HTML5, WebGL và WebAssembly đã đủ để thay thế cho Flash với nhiều cơ chế bảo mật tốt hơn.

Mặt khác, tốc độ Internet ngày càng nhanh nên lợi thế tiêu tốn ít băng thông của Flash dần dần không còn quá nhiều ý nghĩa nữa.

Những điểm mạnh của Flash đều được thay thế bởi những công nghệ mới như HTML5 dùng để thiết kế website, thẻ <video> trong HTML5 cùng với tốc độ Internet nhanh hơn đã giúp việc phát video có chất lượng cao hơn.

Thẻ <canvas> trong HTML5 giúp trình duyệt web vẽ và tạo hiệu ứng hoạt hình cho đồ họa bằng JavaScript.

WebGL giúp trình duyệt web hiển thị đồ họa 2D và 3D. ActionScript thì có JavaScript thay thế. Hầu như chẳng còn lý do nào để Flash nên tiếp tục tồn tại cả.

Việc khai tử Flash sẽ ảnh hưởng tới những trang web cũ đã lâu không cập nhật, vì Adobe đã ra thông báo từ năm 2017 để nhiều trang web có thời gian chuyển đổi nội dung từ Flash sang các tiêu chuẩn mới.

Còn lại thì hầu như những website lớn hiện nay đều đã loại bỏ Flash khỏi mã nguồn của trang web và thay vào đó là HTML5. Điển hình như Youtube đã thay thế Flash bằng HTML5 từ năm 2015.

Cách gỡ bỏ Adobe Flash. Tại sao Flash bị Adobe khai tử?

Thật ra thì tương lai của Flash đã được Apple dự đoán trước, khi vào năm 2007, Apple ra mắt iPhone nhưng lại không hỗ trợ Flash trên nền tảng này, mặc dù vào thời điểm đấy Flash vẫn còn rất phổ biến.

Sau vài đời iPhone tiếp theo, vì sự phổ biến của iPhone và nhiều nhà phát triển web muốn website của họ có thể hoạt động tốt trên mọi nền tảng nên dẫn đến Flash đã có dấu hiệu suy giảm.

Vào năm 2012, Flash được coi là một rủi ro bảo mật khiến Google phải cô lập Flash với Google Chrome bằng Sandbox. Cách này khá hiệu quả khi đặt nội dung flash trong một không gian ảo của riêng mình và cô lập nó với phần còn lại của hệ thống.

Nhưng vì phải tạo ra sandbox nên đã ảnh hưởng đến hiệu năng khi sử dụng Chrome, điều này khiến cho nhiều người khó chịu và về lâu dài thì trải nghiệm người dùng Chrome sẽ bị ảnh hưởng.

Vậy nên tốt nhất vẫn là để các trang web loại bỏ Flash thì mọi thứ sẽ ổn thỏa hơn.

Cách gỡ bỏ Adobe Flash. Tại sao Flash bị Adobe khai tử?

#2. Làm thế nào để gỡ bỏ hoàn toàn Adobe Flash Player?

Microsoft đã lên tiếng sẽ có một bản cập nhật để loại bỏ hoàn toàn Adobe Flash Player ra khỏi hệ điều hành Windows 10.

Trên Windows 10 thì Flash được Microsoft tích hợp sẵn vào hệ thống, chính vì thế bạn sẽ không thể tìm thấy phần gỡ cài đặt Flash trong phần Uninstall của Windows được. Mà nó nằm tại đường dẫn này:

C:\Windows\System32\Macromed\Flash

Đương nhiên là bạn không nên gỡ Flash bằng cách truy cập vào đường dẫn trên và xóa các file trong đó đi. Điều này có thể gây ra lỗi hệ thống. Vậy nếu bạn muốn thực hiện gỡ bỏ ngay bây giờ thì phải làm thế nào?

Cách 1: Sử dụng Adobe Flash Uninstaller

Phương pháp này là do Adobe cung cấp (hàng chính chủ). Bạn chỉ cần truy cập vào đây để tải về (link dự phòng)

Cách gỡ bỏ Adobe Flash. Tại sao Flash bị Adobe khai tử?

Vâng, sau khi bạn tải về => chạy file => và nhấn vào UNINSTALL để thực hiện gỡ bỏ Adobe Flash Player thôi.

Cách gỡ bỏ Adobe Flash. Tại sao Flash bị Adobe khai tử?

Cách 2: Sử dụng bản vá Windows KB4577586

Đây là bản vá do Microsoft cung cấp, tác dụng duy nhất của bản vá này là loại bỏ hoàn toàn Adobe Flash khỏi hệ thống.

Hiện tại thì bản vá KB4577586 (link truy cập bản vá tại đây) vẫn chưa được hỗ trợ thông qua Windows Update. Tuy nhiên bạn có thể tải xuống và cài đặt thủ công theo hướng dẫn chi tiết trong bài viết này:

NOTE: Bạn hãy chọn bản vá tương ứng với hệ điều hành Windows mà bạn đang sử dụng nhé. Rất đơn giản thôi !

#3. Lời kết

Okay, như vậy là trong bài viết này mình đã hướng dẫn rất chi tiết với các bạn cách gỡ bỏ Adobe Flash khỏi Windows một cách sạch sẽ và an toàn rồi nhé.

Mặc dù Flash còn nhiều hạn chế, nhưng nó đã là một phần không thể thiếu trong tuổi thơ của nhiều người.

Mình biết, từng có một thời các webgame, web xem video đều yêu cầu các trình duyệt web phải có Flash thì mới chơi hoặc xem được nội dung, vậy nên có thể nói Flash là một huyền thoại.

Adobe Flash Player trước đây có thể nói là một  phần mềm/ tiện ích mặc định phải có trên bất kỳ một máy tính nào. Nhưng giờ đây nó đã bị khai tử !

Kể từ bây giờ, tuy không còn Flash nữa nhưng những tính tăng mà nó đem lại đã khởi nguồn cho một thế giới Internet với đa dạng các nội dung và tràn đầy sức sống như hiện nay.

Cách gỡ bỏ Adobe Flash. Tại sao Flash bị Adobe khai tử?

Tạm biệt Flash !

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

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

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

Thay đổi tư duy về kiểm thử theo Nguyên lý Agile

Thay đổi tư duy về kiểm thử theo Nguyên lý Agile

Bài viết được sự cho phép của vntesters.com

Nguyên lý Agile – QA ngày nay đã phát triển từ “Tim lỗi” đến “Ngăn ngừa lỗi”. Những kỹ sư kiểm thử cần thêm nhiều kỹ năng khác như kiểm thử tự động, TDD, BDD và kiểm thử hộp trắng (không chỉ làm duy nhất kiểm thử hộp đen). Kỹ sư kiểm thử cần hướng đến hướng-giải-pháp, cộng tác nhiều hơn với nhóm phát triển và các bên nghiệp vụ.

  Agile là gì? Scrum là gì? Các công cụ quản lý dự án theo Agile mà bạn nên biết
  Quản lý dự án theo Agile và Scrum cho người mới bắt đầu

Thay đổi tư duy kỹ sư kiểm thử với Nguyên lý Agile

Agile nghĩa là “Linh động”, “khả năng thay đổi nhanh chóng”.

Kiểm thử trong Agile không có nghĩa là một kỹ thuật kiểm thử mới, mà đi theo Agile nghĩa là phát triển một khả năng thay đổi trong tư duy để triển khai/tiến hành những gì có thể kiểm thử.

Trước khi bàn luận về kiểm thử trong Agile, hãy nhìn lại và xem xét nguồn gốc và nguyên lý bên trong Agile.

Câu chuyện xưa cũ

Trước khi thế giới làm việc với Agile, Thác nước (Waterfall) là một phương pháp có ưu thế trong công nghiệp phần mềm. Ở đây, chúng ta không giải thích mô hình Thác nước, nhưng có ghi chú vài điểm đáng chú ý trong làm việc thực tế.

Những điểm này là dựa vào kinh nghiệm của cá nhân. Có thể có khác biệt đôi chút với mọi người.

  • Kỹ sư phát triển (dev) và QA làm việc như những nhóm riêng lẻ (Đôi khi còn là đối thủ)
  • Các tài liệu liên quan được cả kỹ sư phát triển và QA xem xét cùng một lúc. Kỹ sư phát triển thiết kế và viết mã trong khi QA làm các kịch bản kiểm thử cho các tài liệu đó. Kế hoạch và việc thực thi được làm tuần tự.
  • Việc xem xét các kịch bản kiểm thử được tiến hành bởi trưởng nhóm QA. Việc chia sẻ các kịch bản kiểm thử cho kỹ sư phát triển không phải là một việc được khuyến khích. (Lý do: kỹ sư phát triển sẽ viết mã dựa trên các kịch bản kiểm thử và nhóm QA sẽ không thể tìm thấy lỗi).
  • Việc kiểm thử được xem như là công việc cuối cùng trong vòng lặp phát triển phần mềm. Hầu hết mọi lúc, QA nhận phiên bản phần mềm ở giai đoạn cuối và được mong đợi sẽ hoàn thành việc kiểm thử trong một khoảng thời gian giới hạn. (Và tất nhiên, QA đã làm được việc đó).
  • Mục tiêu duy nhất của QA là tìm lỗi và các khuyết điểm. Đồng thời, việc đánh giá hiệu suất làm việc của QA cũng dựa vào số lượng lỗi/khuyết điểm hợp lý mà QA tìm ra.
  • Chu trình kiểm thử phần mềm (STLC) và vòng đời của lỗi (Bug lifecycle) được đi theo trong quá trình thực thi. Giao tiếp qua email được khuyến kích.
  • Kiểm thử tự động được xem như là công việc cuối cùng và tập trung chủ yếu ở phần giao diện. Bộ kiểm thử qui hồi được xem như là ứng viên tốt nhất cho kiểm thử tự động.

Những điều trên cũng có những khuyến điểm của riêng nó

  • Vì kỹ sư phát triển và QA làm việc độc lập nên việc giao tiếp giữa hai bên chỉ là lỗi và khuyết điểm.
  • Phạm vi làm việc của QA bao gồm viết và thực thi các kịch bản kiểm thử trên sản phẩm hoàn chỉnh.
  • Có rất ít (hoặc không có) cơ hội cho QA xem mã nguồn hay tương tác với kỹ sư phát triển hay nhóm nghiệp vụ.
  • Bởi vì toàn bộ sản phẩm được đưa đến QA một lúc, trách nhiệm của QA là cực kỳ to lớn trên vòng đời của sản phẩm. QA thường được xem như “người gác đền”, và bất kể trên sản phẩm có vấn đề gì, mọi chỉ trích đều chỉ vào QA.
  • Như một phần của kiểm thử chức năng, kiểm thử qui hồi trên toàn bộ sản phẩm cũng là một trách nhiệm của QA, nơi mà có một lượng khổng lồ kịch bản kiểm thử cần thực thi.
  • Ngoài những khuyết điểm ở trên, vấn đề lớn nhất chính là “Thiếu sự tập trung vào việc cung cấp một sản phẩn với chất lượng tốt với một tốc độ hợp lý”.

Mục tiêu cuối cùng của nhóm

(cả kỹ sư phát triển và kỹ sư kiểm thử) là đưa ra một sản phẩm với chất lượng tốt, đáp ứng các yêu cầu nghiệp vụ của khách hàng và dễ sử dụng. Nhưng bởi vì những khoảng thời gian giữa những giai đoạn bị tăng lên khi đưa sản phẩm ra thị trường, trọng tâm đã bị xao lãng, mục tiêu duy nhất được duy trì là hoàn thành việc viết mã và chuyên giao cho nhóm kiểm thử để tiến hành UAT (User Acceptance Testing).

Khi đó, QA chỉ tập trung vào việc thực thi các kịch bản kiểm thử (đánh dấu vào một bảng kiểm tra), đảm bảo mọi lỗi/khuyết điểm đã được chỉnh sửa, và chuyển qua kiểm thử các chức năng khác trong hệ thống. Vậy nên, trên quan điểm của QA, trọng tâm không ở vấn đề tốc dộ và chất lượng của sản phẩm, mà là hoàn thành việc thực thi các kịch bản kiểm thử (và, tất nhiên là bao gồm cả các kiểm thử tự động, nếu có).

Nguyên lý Agile

Bắt đầu từ năm 2001, khi một nhóm gồm 17 chuyên gia gặp gỡ ở Utah (Mỹ) để trượt tuyết, ăn uống, nghĩ ngơi và có một thảo luận về chất lượng; kết quả chính là Nguyên lý Agile.

Là một chuyên gia về chất lượng, chúng ta cũng nên hiểu về bản chất của các Nguyên lý Agile và định hình lại cách suy nghĩ của chúng ta cho phù hợp với mô hình mới này.

Trước khi định hình lại cách suy nghĩ của chúng ta trong việc kiểm thử phần mềm với các nguyên lý Agile, hãy cùng làm rõ một việc: trong Agile, nhóm làm việc cần đa nhiệm và mỗi một thành viên trong nhóm đều đóng góp để phát triển sản phẩm/chức năng.

Do đó, nhóm thường được gọi là “Nhóm phát triển”, bao gồm cả lập trình viên, kỹ sư kiểm thử và phân tích nghiệp vụ. Và, các thuật ngữ lập trình viên và kỹ sư kiểm thử được dùng thay cho kỹ sư phát triển và QA.

Phần mềm hoạt động quan trọng hơn các tài liệu toàn diện về sản phẩm

Mục tiêu cuối cùng của nhóm phát triển Agile là chuyển giao ứng dụng/bản nâng cấp có khả năng sử dụng trong khoảng thời gian nhanh nhất, nghĩa là, thời gian là nhân tố chính. Nói vậy, không có nghĩa chất lượng không quan trọng. Bởi vì thời gian để đưa sản phẩm ra thị trường là giới hạn, điều quan trọng chính là một chiến lược và kế hoạch thực thi kiểm thử cần tập trung nhiều hơn vào chất lượng tổng quát của ứng dụng.

Kiểm thử là một công việc không có điểm dừng, nó có thể tiếp tục và tiếp tục, kỹ sư kiểm thử cần xác định các thông số chính mà họ có thể bật đèn xanh để sản phẩm có thể đưa ra thị trường. Để làm được điều đó, điều quan trọng là kỹ sư kiểm thử cảm thấy phù hợp khi quyết định các khái niệm “định nghĩa sự sẵn sàng” (Definition of Ready) và “định nghĩa sự hoàn thành” (Definition of Done – DoD), và cũng không nên bỏ qua “Tiêu chuẩn chấp nhận cho một tình huống/chức năng” (Acceptance Criteria of the story – AC).

Các chiến lược và kịch bản kiểm thử nên xoay quanh DoD và AC. Thay vì cố gắng viết đầy đủ các kịch bản cũng như bao gồm các thông tin mà hiếm khi được sử dụng, hãy tập trung hơn vào sự rõ ràng và các điểm chính yếu.

Điểm quan trọng ở đây là, chỉ bao gồm những thông tin mà kịch bản kiểm thử cần và có giá trị đối với kịch bản đó.

Cộng tác với khách hàng quan trọng hơn đàm phán hợp đồng

Nên có những cuộc tiếp xúc trực tiếp với khách hàng về cách tiếp cận kiểm thử và cố gắng minh bạch trong việc chia sẽ các kịch bản kiểm thử, dữ liệu kiểm thử và kết quả.

Cũng nên có những buổi họp mặt để lấy phản hồi từ khách hàng và chia sẽ kết quả kiểm thử. Hỏi khách hàng nếu họ đánh giá tốt các kết quả kiểm thử hay họ muốn có thêm những kịch bản đặc biệt. Đừng tự giới hạn bản thân trong việc đặt câu hỏi và tìm kiếm sự xác nhận từ khách hàng/nhóm nghiệp vụ để hiểu hơn về chức năng cũng như nghiệp vụ.

Càng hiểu sâu về chức năng, kỹ sư kiểm thử càng rõ ràng hơn trong việc kiểm thử.

Phản hồi với sự thay đổi quan trọng hơn bám theo kế hoạch

Thứ bất biến duy nhất chính là sự thay đổi.

Chúng ta không thể kiểm soát sự thay đổi và chúng ta hiểu và chấp nhận sự thật là, luôn luôn có sự thay đổi trong chức năng cũng như các yêu cầu; chúng ta phải thích ứng và thực hiện nó.

Tốc độ thay đổi yêu cầu được nhấn mạnh trong Agile, giống với thời trang, như một kỹ sư kiểm thử, chúng ta cần giữ cho kế hoạch kiểm thử và các kịch bản linh động đủ để thích ứng với sự thay đổi.

Theo truyền thống, chúng ta tạo kế hoạch kiểm thử và mọi thứ đi theo vòng đời của dự án. Ngược lại, trong Agile, kế hoạch cần linh động với từng yêu cầu. Một lần nữa, hãy tập trung vào DoD và AC.

Không cần thiết phải tạo ra kế hoạch kiểm thử cho từng tình huống/chức năng; thay vào đó, có thể tạo các kế hoạch kiểm thử ở mức độ Epic. Khi một Epic được thiết lập và tiến hành, có thể đồng thời tiến hành tạo ra kế hoạch kiểm thử cùng lúc. Quan trọng là, kỹ sư kiểm thử cần bao phủ chất lượng của toàn bộ Epic với kế hoạch kiểm thử đó.

Có thể sử dụng PI (Product Increment) để xác định các kịch bản kiểm thử tổng quát cho từng tình huống dựa vào DoD và AC.

Truyền thông giao tiếp và sự tương hỗ quan trọng hơn quy trình và công cụ

Kỹ sư kiểm thử thường có xu hướng nghiên về quá trình (process-oriented), nhưng chúng ta cần nhớ rằng, thay vì đi theo chu trình, thời gian đáp ứng không nên bị ảnh hưởng.

Với trường hợp nhóm làm việc cùng địa điểm, bất kỳ vấn đề nào cũng có thể giải quyển thông qua đối thoại trực tiếp. Có lẽ việc họp mặt hằng ngày (daily stand-ups) cung cấp một giải pháp tốt để giải quyết các vấn đề. Việc ghi nhận/tài liệu hóa lỗi/khuyết điểm là quan trong, nhưng nó chỉ nên được làm cho mục đích ghi dấu (tracking) mà thôi.

Tester nên làm việc chung với Dev và hợp tác để giải quyết các khuyết điểm. Nếu cần, khách hàng cũng nên tham gia chung. Kỹ sư kiểm thử nên chủ động tham gia vào quá trình TDD và cũng nên cộng tác với lập trình viên để chia sẽ các kịch bản và cố gắng xác định lỗi ở ngay mức độ đơn vị.

Kết luận

Kiểm thử trong Agile không phải là kỹ thuật mới. Nó là sự thay đổi trong suy nghĩ, và sự thay đổi diển ra một cách liên tục. Nó yêu cầu các kiến thức, kỹ năng và sự hướng dẫn đúng đắn.

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

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

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

Những tính năng Load Balancer

Những tính năng Load Balancer

Bài viết được sự cho phép của tác giả Lê Chí Dũng

Quá nhiều người dùng truy cập sẽ dẫn đến lượng request khổng lồ, server trở nên quá tải, ảnh hưởng không hề nhỏ đến công suất hoạt động của website, ứng dụng nói riêng và kết quả kinh doanh nói chung. Trong các tình huống như vậy, áp dụng load balancer để cân bằng tải cho server sẽ là giải pháp tối ưu.

  9 mã nguồn mở cho file upload field
  Giải mã bí ẩn "system load" trên Linux

1. Sticky session

Những tính năng Load Balancer

Khái niệm

Một router hay hoặc load balancer hỗ trợ sticky session có thể gán một máy chủ đơn lẻ cho một người dùng cụ thể, dựa trên HTTP session hoặc địa chỉ IP của họ. Máy chủ được chỉ định sẽ được router ghi nhớ trong một khoảng thời gian nhất định, đảm bảo rằng tất cả các yêu cầu trong tương lai cho cùng một session sẽ được gửi đến cùng một máy chủ.

Sticky session là một trong các tính năng cơ bản của nhiều giải pháp load balancer nhằm cân bằng tải cho các website. Tính năng này route các yêu cầu cho một session cụ thể đến cùng một máy tính vật lý, và máy tính này phục vụ yêu cầu đầu tiên cho session đó. Tính năng này chủ yếu được sử dụng để đảm bảo một in-proc session nào đó sẽ không bị mất bởi các yêu cầu cho session được route đến các máy chủ khác nhau. Vì yêu cầu từ 1 người dùng luôn được route đến cùng một máy đã phản hồi yêu cầu lần đầu cho session đó, các sticky session có thể gây ra phân phối tải không đồng đều trên các máy chủ.

Ngoài ra, load balancer cũng có thể duy trì các sticky session thay vì phải nhớ địa chỉ ip của máy khách và máy chủ backend mà máy khách đã gửi đến lúc đầu.

Lợi ích

– Không quá phức tạp để triển khai đối với quản trị viên mạng có kinh nghiệm.

– Giảm nhu cầu triển khai chuyển đổi dự phòng, vì yêu cầu người dùng sẽ chỉ được gửi tới các máy chủ khác nếu một máy chủ offline.

– Load balancer/router thường chịu trách nhiệm phát hiện các máy chủ offline, cung cấp yêu cầu chuyển đổi dự phòng nhanh hơn so với round robin của load balancing dựa trên DNS.

2. Tính năng Health check backend

Server Load Balancer sẽ kiểm tra tính khả dụng dịch vụ của các backend server bằng cách thực hiện health check. Chức năng health check giúp cải thiện tính sẵn sàng cho toàn bộ dịch vụ và tránh tác động xấu từ các lỗi trên server backend.

Sau khi kích hoạt health check, Server Load Balancer sẽ ngừng phân phối các request đến các phiên bản được xác minh là không đạt yêu cầu hoặc lỗi và chỉ khởi động lại việc chuyển tiếp request đến phiên bản đó khi nó được khai báo là đã đạt yêu cầu.

Tính năng này giúp kiểm tra trạng thái máy chủ ở backend để đẩy request vào các server group không bị lỗi.

Quy trình hoạt động của health check

Server Load Balancer thường được triển khai theo cụm/cluster. Chuyển tiếp dữ liệu và health check sẽ được xử lý đồng thời bởi các node servers trong LVS cluster và Tengine cluster.

Các node servers trong cluster độc lập sẽ thực hiện health check song song, theo cấu hình của health check. Nếu một node server phát hiện ra một khu vực nào đó bị lỗi, node server sẽ ngừng phân phối request tới khu vực đó. Thao tác này sẽ được đồng bộ hóa trên tất cả các node server như trong sơ đồ dưới đây.

Những tính năng Load Balancer

3. Tính năng theo dõi giám sát hoạt động (Operational Monitoring)

Một số các thông số trong Load balancer cần theo dõi, giám sát:

Healthy host count: Số lượng các trường hợp không bị lỗi trong load balancer. Một trường hợp được coi là “healthy” – đạt tiêu chuẩn nếu nó đáp ứng ngưỡng tiêu chuẩn được cấu hình cho health check.

Unhealthy host count: Số lượng các trường hợp lỗi trong load balancer. Một trường hợp được coi là lỗi nếu nó vượt quá ngưỡng tiêu chuẩn lỗi được cấu hình cho health check. Số này không được lớn hơn 0 trừ khi máy chủ đang trong thời gian bảo trì.

Request Count: Số lượng request trọn vẹn được nhận và chuyển đến các phiên bản đăng ký. (The number of completed requests that were received and routed to the registered instances.)

Latency: Thời gian tính từ sau khi request rời khỏi load balancer cho tới lúc nhận được phản hồi (được tính bằng giây và không được lớn hơn 0 trừ khi máy chủ đang được bảo trì).

Lỗi kết nối Backend: Số lượng kết nối không thành công giữa load balancer và phiên bản đăng ký. Số này không được lớn hơn 0 trừ khi máy chủ đang trong thời gian bảo trì.

Độ dài Surge Queue Length: Tổng số request đang chờ gửi đến phiên bản đăng ký. Số này không được lớn hơn 0 trừ khi máy chủ đang trong thời gian bảo trì.

Spillover Count: Tổng số request bị từ chối khi quêu đã full. Số này không được lớn hơn 0 trừ khi máy chủ đang trong thời gian bảo trì.

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

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

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