Việc cài đặt Rust trên môi trường Arch Linux khá là đơn giản. pacman có sẵn gói rust và cargo, bạn có thể chọn cách cài đặt trực tiếp 2 packages này.
Tuy nhiên ở bước cài đặt công cụ hỗ trợ cho các IDE, chúng ta thường dùng racer và engine này yêu cầu chúng ta phải có source code của Rust nằm sẵn trong máy. Nếu chọn cách cài đặt từng gói, thì chúng ta có thể cài đặt Rust source code thông qua yaourt với gói rust-srcAUR, rồi phải set biến môi trường RUST_SRC_PATH khá là phiền phức.
Cho nên, cách cài đặt đơn giản nhất đó là dùng rustup. Package này gồm có: rustup, rustc và cargo. Và bước cài đặt Rust source cũng đơn giản hơn.
Cài rustup thông qua pacman sau đó chọn phiên bản Rust cần dùng, ví dụ ở đây dùng bản stable.
$ sudo pacman -S rustup$ rustup default stable
Sau khi cài xong thì chúng ta có toàn bộ các công cụ cần thiết để làm việc với rust. Có thể kiểm tra thông qua các lệnh:
$ rustc -V$ cargo -V
2. Cài đặt công cụ hỗ trợ cho các IDE
Việc đầu tiên cần làm trước khi cài đặt các gói hỗ trợ cho IDE là add Rust source code vào máy, thực hiện việc này thông qua rustup như sau:
$ rustup component add rust-src
Sau khi đã có source code của Rust trong máy, các bạn có thể bắt đầu đọc source để hiểu những gì Rust làm bên dưới, từ đó sẽ nắm được toàn bộ kiến thức và không cần dùng bất cứ trình hỗ trợ nào cho IDE khi code Rust nữa… à nhầm, không phải =)))) bước tiếp theo là cài đặt racer.
$ cargo install racer
Cuối cùng, tùy theo IDE/editor mà bạn sử dụng, bạn có thể cài các plugin khác nhau cho việc support Rust. Nếu bạn xài Vim thì cài plugin rust.vim:
Plug'rust-lang/rust.vim'
3. Cài đặt Syntastic trong Vim
Phần này chỉ là phụ, dành cho bạn nào xài Vim và muốn có chức năng kiểm tra lỗi trực tiếp trong lúc code bằng Syntastic.
Cài thêm plugin Syntastic như sau:
Plug'vim-syntastic/syntastic'
Cấu hình cho Syntastic trong .vimrc theo như recommend trên trang chủ dự án của họ:
set statusline+=\ %#warningmsg#
set statusline+=\ %{SyntasticStatuslineFlag()}
set statusline+=\ %*
letg:syntastic_always_populate_loc_list = 1letg:syntastic_auto_loc_list = 1letg:syntastic_check_on_open = 1letg:syntastic_check_on_wq = 0
Tuy nhiên nếu chỉ đến đây, khả năng là chức năng kiểm tra lỗi vẫn chưa hoạt động được, cần thêm vào dòng sau để chỉ định Syntastic checker dành cho Rust:
letg:syntastic_rust_checkers = ['rustc']
Khởi động lại Vim và thưởng thức thành quả 😀
Đến đây thì việc cài đặt hoàn tất. Bạn có thể tham khảo thêm wiki của Arch Linux để biết thêm chi tiết về cách cài đặt Rust và các chức năng cần thiết khác.
UPDATE: Sau khi làm việc với Rust theo như setup ở trên vài ngày thì mình có gặp hai vấn đề liên quan đến cargo, đó là:
Syntastic không thể nhận biết được project dạng library, nên sẽ luôn xuất hiện thông báo kiểu như missing main function
Khi sử dụng các crate bên ngoài thì Syntastic sẽ báo lỗi ngay dòng extern crate ..., nói là không tìm thấy crate này
Hai vấn đề trên buộc lòng chúng ta phải sử dụng cargo làm checker cho Syntastic thay vì rustc, hiện tại thì cargo check đã được merge vào master của cargo nhưng việc support này vẫn chưa được merge vào plugin rust.vim (xem pull request rust.vim#132).
Cách giải quyết tạm thời là cài rust.vim trực tiếp từ repo của tác giả jlevesy thay vì từ repo của rust-lang:
Vì không còn màu sắc nên bạn phải chú ý hơn tới việc trình bày code cho gọn gàng sạch đẹp
Bạn sẽ bớt code ẩu hơn
Khiến bạn trông ngầu hơn khi code
Thực ra nếu để ý kĩ thì giao diện mình đang xài không hoàn toàn là không màu. Nó vẫn có 2 màu chủ đạo là trắng và ít trắng hơn :))) bên cạnh đó còn có 2 kiểu hiển thị là in đậm và in không đậm nữa.
Đây là kết quả sau quá trình sử dụng và “optimize” cái giao diện để làm việc thoải mái nhất có thể.
Và mình cũng không phải là người duy nhất làm cái trò này :v
Tất nhiên khi mới bắt đầu thì không dễ dàng gì vì gần như ngay từ lần đầu tiên bắt đầu học lập trình thì mình đã sử dụng syntax highlighting rồi. Tuy nhiên điều khá bất ngờ là mình trở nên quen với việc code không màu này rất nhanh (chưa đầy nửa ngày).
Nếu bạn nào có hứng thú thì có thể xài thử color scheme do mình modify lại từ bộ màu base16-ocean tại đây:
Một Bộ Hồ Sơ Xin Việc Gồm Những Gì Khi Gửi Qua Email?
Ngày nay, hơn 80% nhà tuyển dụng đã sử dụng các kênh online để tìm kiếm ứng viên. Do đó, việc tạo một hồ sơ xin việc online ấn tượng sẽ giúp bạn nổi bật giữa hàng ngàn ứng viên khác và tăng cơ hội nhận được lời mời phỏng vấn. Hãy cùng theo dõi bài viết này để tìm hiểu cách tạo hồ sơ xin việc qua email chuẩn chỉnh và tăng cơ hội lọt vào “mắt xanh” nhà tuyển dụng
Hồ sơ xin việc online qua email là gì?
Hồ sơ xin việc online qua email là cách ứng viên nộp hồ sơ xin việc của mình bằng hình thức online thông qua địa chỉ email. Email xin việc thường được gửi trực tiếp đến địa chỉ email của nhà tuyển dụng hoặc phòng nhân sự của công ty. Đây là cách thức phổ biến trong thời đại kỹ thuật số, giúp ứng viên tiếp cận nhanh chóng và hiệu quả với nhà tuyển dụng mà không phải đến trực tiếp công ty để nộp hồ sơ như trước kia.
Email xin việc thường bao gồm một lời giới thiệu ngắn gọn về bản thân, vị trí ứng tuyển. Email xin việc thường ngắn gọn, tập trung vào việc dẫn dắt nhà tuyển dụng đến phần hồ sơ đính kèm.
Cần phân biệt email xin việc và cover letter, Thư xin việc (Cover Letter) là một tài liệu chi tiết hơn, thường được đính kèm cùng CV trong email xin việc. Thư xin việc cung cấp một cái nhìn sâu hơn về kinh nghiệm, kỹ năng và lý do ứng viên muốn ứng tuyển vào vị trí cụ thể. Thư xin việc thường dài hơn email xin việc và có cấu trúc rõ ràng, bao gồm phần mở đầu, nội dung chính và phần kết thúc.
Hồ sơ xin việc online sẽ bao gồm những gì?
CV – Công cụ tiếp thị cá nhân không thể thiếu
CV là một thứ rất quan trọng, bắt buộc phải có. Dù cho mọi thứ được “marketing hóa”, CV vẫn là công cụ giúp bạn ghi điểm hiệu quả với nhà tuyển dụng.
Ứng viên cần thể hiện rõ các khía cạnh về kỹ năng chuyên môn của mình trong CV.
Tăng hiệu quả ứng tuyển bằng cách tạo CV Online hiệu quả trên TopDev
Gửi CV qua email gồm những gì? Các thành phần cơ bản trong CV thường gồm có:
Thông tin cá nhân
Trình độ học vấn
Kinh nghiệm làm việc
Kỹ năng
Thành tích
Hãy thật sự đầu tư cho chiếc CV của bản thân mình chuẩn format và đủ nội dung. Nội dung CV cần truyền tải đúng trọng tâm, đầy đủ. Trong khi đó, visual của CV cũng là yếu tố thu hút nhà tuyển dụng. Hãy đảm bảo CV đầy đủ sự chân thật và tính trực quan cần có.
Một số tip đáng lưu ý:
Bạn nên ưu tiên sử dụng các font chữ chuyên nghiệp; phù hợp với tiêu chuẩn chung như: Time New Roman, Arial, Century Gothic,…
CV nên được định dạng bằng file PDF thay vì phiên bản Word hay PowerPoint. Điều này giúp hạn chế tình trạng font chữ bị lỗi hoặc các bố cục trong CV bị dịch chuyển.
Cover Letter – Thư xin việc
Cover Letter thường được mô tả dưới dạng nội dung trong email nên bạn không cần phải đính kèm. Dù bạn ứng tuyển vị trí nào như freelancer it hay Senior Developer đều phải đảm bảo những yếu tố cần thiết của một Cover Letter.
Một số nhà tuyển dụng, họ có hoặc không yêu cầu về Cover Letter. Tuy nhiên, bạn có thể đính kèm nếu bản thân muốn thể hiện sự nghiêm túc với công việc.
Khi viết cover letter bạn cần xác định rõ vị trí bạn ứng tuyển và mục tiêu của bạn khi ứng tuyển vào vị trí này. Hãy nêu bật những điểm mạnh, kỹ năng và kinh nghiệm của bạn phù hợp với vị trí ứng tuyển. Và hãy nhớ check lại thật kỹ lỗi ngữ pháp và chính tả trước khi gửi nó đến nhà tuyển dụng.
Nội dung thông tin có thể gửi thường chỉ được giới hạn từ 300 – 500 chữ. Vì thế, bạn nên cân nhắc việc lựa chọn các thông tin nào quan trọng và cần thiết để gửi đến nhà tuyển dụng.
Portfolio là phần không bắt buộc phải có trong bộ hồ sơ xin việc qua email vì nó còn phụ thuộc vào ngành nghề mà bạn ứng tuyển. Portfolio là một tập hợp các công việc, dự án hoặc sản phẩm mà bạn đã thực hiện trong quá khứ. Đây là cách tốt nhất để bạn có thể giới thiệu và thể hiện khả năng và kỹ năng của mình cho nhà tuyển dụng.
Nếu bạn là ứng viên ứng tuyển các nhóm ngành thuộc lĩnh vực sáng tạo như: thiết kế, truyền thông marketing, quảng cáo, báo chí,… thì Portfolio rất quan trọng.
Portfolio có thể bao gồm nhiều loại tài liệu khác nhau như hình ảnh, video, bài viết, thiết kế,… Bạn cần lưu ý chọn lọc những sản phẩm tốt nhất, phù hợp nhất với vị trí bạn ứng tuyển để đưa vào portfolio và thường xuyên cập nhật những sản phẩm mới mà bạn đã thực hiện.
Lưu ý quan trọng, các file sản phẩm định dạng phù hợp là file dưới dạng hình ảnh JPG, PNG hay PDF.
Hình ảnh cá nhân
Một bức ảnh cá nhân là điều cần thiết giúp cho hồ sơ xin việc của bạn thêm chuyên nghiệp. Vì thế, hãy chuẩn bị ngay cho mình những bức hình đẹp nhất để đính kèm trong email nhé!
Những lưu ý về một bức ảnh phù hợp:
Bức ảnh phải rõ mặt, thể hiện sự tự tin, không nên có sự xuất hiện của người khác.
Ảnh cần thể hiện sự nghiêm túc, tránh gửi hình tự sướng, ảnh đời thường hay ảnh với chất lượng kém.
Ảnh chuẩn là ảnh sắc nét, không dùng các phần mềm chỉnh sửa quá đà.
Các tài liệu đính kèm khác
Một số nhà tuyển dụng muốn đánh giá toàn diện hơn về các khả năng khác của ứng viên. Và vì thế, họ có thể yêu cầu thêm một số tài liệu có liên quan.
Đó có thể là những minh chứng về thành tích học thuật, ngoại khóa; các chứng chỉ khóa học, ngoại ngữ hay thậm chí là bảng điểm của bạn. Yêu cầu thêm thông tin là cách họ khai thác nhiều hơn ở bạn.
Quan trọng là, bạn hãy thật thông minh trong việc lựa chọn các minh chứng. Nên chọn lọc các thành tích khoa học, phát triển kỹ năng, ngoại khóa có liên quan đến vị trí mà bạn đang ứng tuyển để gia tăng cơ hội trúng tuyển.
Cách viết một email xin việc chuyên nghiệp
Viết một email xin việc đúng chuẩn là một bước quan trọng trong việc làm hồ sơ xin việc online để tạo ấn tượng tốt đầu tiên với nhà tuyển dụng. Dưới đây là hướng dẫn chi tiết về cách viết email xin việc đúng chuẩn:
Tạo một địa chỉ email chuyên nghiệp
Địa chỉ email của bạn cũng vô cùng quan trọng vì nó cũng giúp hồ sơ của bạn vì nó là thứ giúp bạn gây ấn tượng ban đầu với nhà tuyển dụng.
Đừng đặt một địa chỉ email quá trẻ con. Điều này hiển nhiển trở thành một điểm trừ lớn. Nhà tuyển dụng sẽ đánh giá bạn là một người thiếu chuyên nghiệp. Hoặc đơn giản họ nghĩ, bạn chưa đủ trải nghiệm do sự am hiểu về “diện mạo” của địa chỉ email – kiến thức căn bản chưa hoàn thiện. Và do đó, hồ sơ của bạn bị loại bỏ khi họ chưa kịp xem đến CV của bạn.
Tiêu đề Email xin việc
Dù chỉ là những khía cạnh về mặt hình thức song, nó rất quan trọng. Thường các nhà tuyển dụng sẽ có đề cập về cách thức đặt tiêu đề trong thông tin tuyển dụng. Bạn nên lưu ý để đảm bảo không sai hình thức.
Nếu không có format sẵn từ doanh nghiệp, bạn có thể đảm bảo tính chuyên nghiệp thông qua cách đặt tiêu đề gợi ý như sau:
Vị trí ứng tuyển – Họ Tên – Năm kinh nghiệm
Tên Doanh nghiệp – Vị trí ứng tuyển – Họ tên
Họ Tên – Vị trí ứng tuyển
Lời chào
Lời chào cần lịch sự và chính xác. Nếu biết tên của nhà tuyển dụng hoặc người phụ trách tuyển dụng, hãy sử dụng tên của họ. Nếu không biết tên, bạn có thể sử dụng chung chung như:
Kính gửi Ông/Bà [Tên người nhận],
Kính gửi Bộ phận Tuyển dụng công ty…,
Phần mở đầu
Phần mở đầu của email nên giới thiệu ngắn gọn về bản thân và lý do bạn viết email này. Bạn nên nêu rõ vị trí mình đang ứng tuyển và lý do tại sao bạn quan tâm đến công việc này.
Ví dụ: “Tôi là Nguyễn Văn A, hiện đang tìm kiếm cơ hội làm việc trong lĩnh vực [lĩnh vực của bạn]. Tôi rất hứng thú với vị trí [Tên vị trí] mà quý công ty đang tuyển dụng và tin rằng với kinh nghiệm và kỹ năng của mình, tôi sẽ đóng góp tích cực cho công ty.”
Phần nội dung chính
Trong phần này, bạn nên tóm tắt ngắn gọn về kinh nghiệm, kỹ năng và lý do bạn phù hợp với vị trí ứng tuyển. Bạn có thể nhấn mạnh những thành tựu nổi bật hoặc kỹ năng đặc biệt của mình.
Nội dung trình bày trong Email là những thông tin cơ bản. Nó như một phần níu kéo nhà tuyển dụng ở lại lâu hơn. Hình thức font chữ, màu sắc cần đồng nhất. Bạn không nên trình bày quá rườm rà, hãy nghĩ đơn giản nhưng chuyên nghiệp.
Ví dụ: “Với hơn 3 năm kinh nghiệm trong lĩnh vực [lĩnh vực của bạn], tôi đã phát triển được các kỹ năng như [kỹ năng chính], giúp tôi hoàn thành xuất sắc các dự án tại công ty cũ. Tôi tin rằng những kinh nghiệm này sẽ giúp tôi thực hiện tốt các nhiệm vụ của vị trí [Tên vị trí].”
Phần kết luận
Kết thúc email bằng việc cảm ơn nhà tuyển dụng đã dành thời gian đọc email của bạn và bày tỏ mong muốn được gặp trực tiếp để trao đổi thêm về cơ hội này.
Ví dụ: “Tôi rất mong được có cơ hội trao đổi thêm về cách mà tôi có thể đóng góp cho công ty. Xin cảm ơn quý công ty đã dành thời gian xem xét hồ sơ của tôi. Tôi rất hy vọng sẽ nhận được phản hồi từ quý công ty.”
Lời chào kết
Kết thúc email bằng một lời chào lịch sự, chẳng hạn:
Trân trọng,
Chân thành cảm ơn,
Chữ ký email
Cuối email, bạn nên để lại thông tin liên lạc chi tiết bao gồm tên, số điện thoại và địa chỉ email của bạn để thể hiện sự chuyên nghiệp và có đầu tư.
Đừng quên đính kèm các tài liệu như đã liệt kê ở trên như CV và các tài liệu liên quan như thư xin việc, chứng chỉ, bảng điểm,… Kiểm tra lại lần cuối trước khi gửi để đảm bảo các file đã được đính kèm đúng cách.
Đây là phần rất nhiều ứng viên mắc lỗi, họ thường quên đính kèm CV mà gửi một email trơ trọi đến nhà tuyển dụng.
Mẫu email xin việc online tham khảo
Dưới đây là một số mẫu email xin việc ấn tượng mà bạn có thể tham khảo và tùy chỉnh để phù hợp với vị trí và công ty mà bạn đang ứng tuyển:
Mẫu 1: Email xin việc cho vị trí Marketing Specialist
Tiêu đề email: Ứng tuyển vị trí Marketing Specialist – [Họ tên]
Nội dung email:
Kính gửi Anh/Chị [Tên Nhà Tuyển Dụng] và Phòng Nhân Sự Công ty [Tên Công Ty],
Tôi tên là [Họ tên], và tôi rất hào hứng được ứng tuyển vào vị trí Marketing Specialist tại [Tên Công Ty] mà Quý công ty đã đăng tuyển trên [nơi đăng tin tuyển dụng] ngày [ngày tháng]. Với kinh nghiệm [X năm] trong lĩnh vực marketing, đặc biệt là trong việc phát triển chiến lược marketing kỹ thuật số và quản lý các chiến dịch quảng cáo, tôi tin rằng mình có thể đóng góp tích cực cho đội ngũ Marketing của công ty.
Trong vai trò trước đây tại [Tên Công Ty Trước], tôi đã [tóm tắt một số thành tích nổi bật, ví dụ: “tăng 25% lượng khách hàng tiềm năng thông qua các chiến dịch email marketing và tối ưu hóa nội dung trên các kênh truyền thông xã hội”]. Tôi tin rằng với kỹ năng phân tích dữ liệu mạnh mẽ và khả năng sáng tạo trong việc triển khai các chiến dịch tiếp thị, tôi sẽ giúp [Tên Công Ty] đạt được mục tiêu kinh doanh trong thời gian tới.
Tôi đã đính kèm CV của mình trong email này và rất mong có cơ hội trao đổi trực tiếp để chia sẻ thêm về kinh nghiệm và những giá trị mà tôi có thể mang lại cho [Tên Công Ty].
Chân thành cảm ơn Anh/Chị đã dành thời gian xem xét hồ sơ của tôi. Tôi rất mong nhận được phản hồi từ Anh/Chị.
Trân trọng,
[Chữ ký mail]
Mẫu 2: Email xin việc cho vị trí Nhân viên Kinh Doanh
Tiêu đề email: Ứng tuyển vị trí Nhân viên Kinh Doanh – [Họ tên]
Nội dung email:
Kính gửi Anh/Chị [Tên Nhà Tuyển Dụng],
Tôi tên là [Họ tên], và tôi rất mong muốn được ứng tuyển vào vị trí Nhân viên Kinh Doanh tại [Tên Công Ty] mà Quý công ty đã đăng tuyển. Với hơn [X năm] kinh nghiệm làm việc trong lĩnh vực bán hàng và phát triển kinh doanh, tôi tự tin rằng mình có thể đóng góp tích cực vào việc mở rộng thị trường và nâng cao doanh số của công ty.
Trong quá trình làm việc tại [Tên Công Ty Trước], tôi đã thành công trong việc [tóm tắt một số thành tích đáng chú ý, ví dụ: “tăng 30% doanh số bán hàng trong khu vực miền Trung trong năm vừa qua nhờ vào việc phát triển mối quan hệ với các khách hàng chiến lược và mở rộng mạng lưới phân phối”]. Tôi cũng có kỹ năng đàm phán và thuyết phục tốt, giúp tôi đạt được các mục tiêu bán hàng một cách hiệu quả.
Tôi tin rằng với những kinh nghiệm và kỹ năng đã tích lũy, tôi sẽ là một thành viên hữu ích trong đội ngũ Kinh doanh của [Tên Công Ty]. Tôi rất mong có cơ hội trao đổi thêm về vị trí này cũng như đóng góp vào sự phát triển của công ty.
Tôi đã đính kèm CV chi tiết của mình trong email này. Rất mong nhận được phản hồi từ Anh/Chị.
Trân trọng,
[Chữ ký mail]
Mẫu 3: Email xin việc cho vị trí Lập trình viên
Tiêu đề email: Ứng tuyển vị trí Lập trình viên – [Họ tên]
Nội dung email:
Kính gửi Anh/Chị [Tên Nhà Tuyển Dụng] và Bộ phận Tuyển Dụng Công ty [Tên Công Ty],
Tôi tên là [Họ tên], và tôi viết email này để bày tỏ nguyện vọng được ứng tuyển vào vị trí Lập trình viên tại [Tên Công Ty]. Tôi đã tốt nghiệp ngành [Tên Ngành] tại [Tên Trường] và có [X năm] kinh nghiệm làm việc với các ngôn ngữ lập trình như [liệt kê các ngôn ngữ lập trình bạn thành thạo].
Trong quá trình làm việc tại [Tên Công Ty Trước], tôi đã tham gia phát triển nhiều dự án phần mềm, trong đó có [tên dự án hoặc sản phẩm nổi bật]. Tôi đã có cơ hội áp dụng các kỹ năng của mình vào việc [tóm tắt công việc đã làm, ví dụ: “phát triển các tính năng mới cho ứng dụng quản lý dự án, giúp cải thiện hiệu suất làm việc của người dùng lên 20%”]. Tôi luôn hướng đến việc tạo ra những sản phẩm chất lượng cao, đáp ứng tốt nhu cầu của khách hàng.
Tôi tin rằng với niềm đam mê công nghệ và khả năng học hỏi nhanh, tôi sẽ đóng góp hiệu quả cho đội ngũ phát triển phần mềm của [Tên Công Ty]. Tôi rất mong có cơ hội được gặp gỡ và trao đổi thêm về vị trí này.
CV của tôi đã được đính kèm trong email này. Rất mong nhận được sự phản hồi từ Anh/Chị.
Trân trọng,
[Chữ ký mail]
Hy vọng những mẫu email này sẽ giúp bạn tạo ấn tượng tốt với nhà tuyển dụng và tăng cơ hội thành công khi ứng tuyển.
Lời kết
Hồ sơ xin việc là một phần không thể thiếu để khi bạn muốn ứng tuyển một vị trí công việc nào. Mỗi yếu tố trong hồ sơ đều có những vai trò khác nhau. Hãy chuẩn bị cho bản thân một hồ sơ xin việc. Đồng thời, hoàn thiện nó để bạn có đủ tự tin gửi nó đến với nhà tuyển dụng. TopDev mến chúc các bạn sẽ thành công trong việc chinh phục nhà tuyển dụng nhé!
Message Brokers là gì?. Mesage Brokers trong design system
Bài viết được sự cho phép của tác giả Kiên Nguyễn
Tiếp theo chuỗi về System Design và System Architecture, bài viết này giới thiệu với anh em về khái niệm Message Brokers. Khái niệm này cũng nằm trong nhóm bài viết về Large Scale Systems Architectural Building Blocks.
Applications ngày nay càng ngày càng lớn, càng ngày càng phức tạp. Thời gian và cách thức để giao tiếp giữa các Services lớn đã trở thành một bài toán lớn. Rất may ta đã có một solutions khá tốt tên Message Brokers.
Luôn bắt đầu với khái niệm loằng ngoằng lèo nghèo
A message broker is a piece of software, which enables services and applications to communicate with each other using messages. The message structure is formally defined and independent from the services that send them.
Message broker là một phần của phần mềm, cho phép services và applicaiton giao tiếp với nhau thông qua messages. Cấu trúc message thông thường được định nghĩa sẵn và nó động lập hoàn toàn khỏi services gửi nó.
Thêm nữa
This allows applications to share information with one another, even if they’re written in different programming languages!
Message Brokers còn cho phép ứng dụng chia sẻ thông tin với một cái khác, kể cả là 2 con services viết trên 2 ngôn ngữ lập trình khác nhau!
Rồi kèm thêm quả 3 khái niệm chất chơi Producer, Consumer và Queue/topic nữa. Loạn hết đầu, khó hiểu nhân đôi.
May thay ở Kieblog luôn có ví dụ cụ thể tận tình cho anh em.
Thật sự phân vân – LOL
2. Message Brokers Motivation
Trước khi bắt đầu với Message Brokers thì ta điểm xuyết qua tí về Load Balancer. Anh em nào chưa biết về Load Balancer có thể tham khảo bài này.
Rồi, bắt đầu với ví dụ, đầu tiên là
2.1 Synchronous Communication
Synchoronous là đồng bộ. Synchronous Communication nghĩa là giao tiếp đồng bộ. Sender và Receiver sẽ giao tiếp với nhau thông qua Direct Communication (kết nối trực tiếp).
Ngoài kết nối trực tiếp (Direct Communication), cũng có thể thông qua Load Balancer như hình dưới
Giao tiếp kiểu này thường yêu cầu cả Sender và Receiver đều phải work (healthy). Trường hợp một trong hai ngủm thì tính là ngủm.
2.2 Drawbacks
Trường hợp giao tiếp trực tiếp (Direct Communication), sẽ có yêu cầu cho cả 2 services
Both application instances have to remain healthy and maintain this connection to complete transaction
Cả hai application đều phải đảm bảo ổn và duy trì connection để có thể hoàn thành một transaction.
Cũng không có vấn đề gì phát sinh để ta phải dùng Message Brokers nếu cả hai services đều nhỏ, ít xử lí và cho thời gian phản hồi nhanh.
Nhưng đời không như là mơ, trường hợp receiver services xử lí cồng kềnh và tốn nhiều thời gian thì sao?
Nói là làm, ví dụ ngay và luôn cho anh em. Giả sử ta đang build một hệ thống xử lí vé (ticket), đã là vé thì có mua bán, có thanh toán online, có xử lí đặt chỗ.
Fullfilment Services sẽ thực thi nhiều actions, kiểm tra thẻ, thanh toán và gửi email thông báo thành công cho user. Nếu cả 3 thứ này đều tốn thời gian?
Bài toán đặt ra lúc này là user cần có response nhanh nhất?. Không thể chờ tới khi tất cả các services hoàn thành (giảm performance). Chính lúc này là lúc Message Brokers ra tay.
À tí quên, chưa kể là trường hợp có nhiều user truy cập cùng lúc và Services xử lí lần lượt từng request.
2.3 Message Brokers là gì?
Lý thuyết, không thể không đọc.
A software architectural building block that uses the queue data structure to store messages between sender and receiver
Kiến trúc phần mềm theo các khối sử dụng queue để lưu trữ message giữa người gửi là người nhận là Message Brokers
Tới đây đã rõ, Brokers có nghĩa là môi giới và siêu đúng trong trường hợp này. Đứng giữa sender và receicer để nhận messages, đem nó vào queue. Ngon
Đứng giữa hai thằng là ông Brokers, sender lúc này gửi request tới ông trung gian và có ngay kết quả. Đôi khi là ngay lập tức. Đặt hàng phát là có thông báo đặt hàng thành công luôn. Quá đã.
Sau khi đã done và Broker trả về cho Sender, lúc này Message Brokers mới giao tiếp thật sự với Receiver. Đi thực hiện nốt cho xong các công việc.
Với kiến trúc này, ta cũng có thể chia nhỏ các services với nhiều brokers
Tới đây là anh em hiểu hết rồi đúng không?. Giờ chuyển qua phần hấp dẫn không kém. Benefits
3. Message Brokers Benefits
Chính vì cơ chế đứng trung gian giữa Sender và Receiver nên:
Most message brokers implemetation offer the publish/subscrible pattern
Hầu hết các message brokers đều implement dựa trên publish/subscrible pattern.
Publish messages to a particular channel (gửi tin nhắn tới một kênh cụ thể)
Subscrible to that channel (đăng kí một kênh)
Get notified when a new event is published (nhận thông báo khi có event mới được publish)
4. Message Capabalities
Về những thứ Message Brokers có thể làm, hoặc gọi chung là benefit đi. Bao gồm một số điểm sau:
Storing/temporarily buffering the messages
Message routing
Transformation validation
Với message brokers, ta cũng có thể đăng kí với các services khác, thông báo tới end user khi một event nào đó đã hoàn thành.
4.1 Fault Tolerance
Khả năng chịu lỗi là điểm đáng ghờm mà Mesage Brokers đem lại.
It allows different services to communicate with each other white some of them maybe unavailable temporarily
Nó cho phép các services khác nhau giao tiếp với nhau trong khi một trong số chúng đã ngủm củ tỏi
Thua, vậy lại chả tăng tính chịu lỗi, hàng không có nhưng anh brokers môi giới đã cho đặt luôn rồi.
4.2 Availability và Scalabality
Tính sẵn sàng (availability) và tính mở rộng (scalabality) cũng là 2 điểm mà Mesage Brokers đem tới. Trường hợp có rất nhiều traffic, thanh niên môi giới này có thể trả về kết quả nhanh chóng, sau đó đi xử lí từ từ.
We pay a little in performance when it comes to latency
Tăng performance và giảm độ trễ của hệ thống
Tới đây mong anh em đã hiểu rõ về Message Brokers. Một số bài viết hay để ở tham khảo nha.
Có rất nhiều phương pháp để làm web dùng Rust, ví dụ như là, compile Rust code ra thành client-side JavaScript code dùng WebAssembly, viết RESTful API, hoặc xây dựng ứng dụng web được render từ phía server, giống như những năm 2012 vậy :v
Chúng ta sẽ đi vào từng phương pháp một.
1. Client-side JavaScript trong Rust
Cách đầu tiên, hoàn toàn là frontend, mà mình nghiên cứu đó là dùng Rust để viết web theo dạng component-based như là React vậy. Điều này có nghĩa là chúng ta phải tìm ra cách nào đó để chạy Rust ngay trên trình duyệt.
Và tất nhiên không phải tìm lâu, chúng ta có thể dễ dàng biên dịch code Rust ra thành JavaScript để chạy trên trình duyệt, nhờ vào các dự án như ASM.js và WebAssembly.
Rồi, giờ quay lại vụ component-based. Mình có viết một macro đơn giản để wrap các API của crate stdweb, và render các HTML elements thông qua DOM API của trình duyệt:
Nếu mà nhìn vào đoạn code trên bạn cảm thấy mông lung không hiểu gì, thì thôi cũng đừng hoảng. Cú pháp macro của Rust vốn không được đẹp cho lắm. Mà thực ra giờ mình đọc lại cũng không hiểu mình đang viết gì nữa, tự thấy nể bản thân mình ghê gớm =)))
Chi tiết về đoạn macro trên, component! làm nhiệm vụ định nghĩa ra một HTML element mới, mount_component! làm nhiệm vụ chèn (append) cái element đó vào document, và html! làm nhiệm vụ tạo ra một element từ một chuỗi HTML bất kỳ.
Cách dùng như sau:
component!(AppComponent => {
init: {
let e: Element = html!("
<div>
<p>
<span>Hello</span>
<span>World</span>
</p>
<GreenButton />
</div>
");
letmut button = GreenButton::new();
mount_component!(e, "GreenButton", button);
e
},
render: |this: &Element| {
}
});
component!(GreenButton => {
init: {
let button = document().create_element("button");
button.add_event_listener(move |_: ClickEvent| {
js! {
alert("Yo! This is the Green Button!");
}
});
button
},
render: |this: &Element| {
this.set_text_content("This is a button");
}
});
fnmain() {
stdweb::initialize();
letmut app = AppComponent::new();
mount_component!(document(), "#root", app);
stdweb::event_loop();
}
Đấy, như thế thì ai cần xài React làm gì nữa nào? =))) (đùa tí thôi)
Các bạn có thể tham khảo mã nguồn đầy đủ để xem cách sử dụng stdweb với các macro trên để minh họa cho phương pháp biên dịch Rust sang JavaScript.
2. Dùng Rust viết RESTful API
Phương pháp thứ 2 tập trung vào backend. Đó là dùng Rust để viết một API server và kết nối nó với frontend có sẵn của bạn.
Hiện tại có một lượng kha khá framework để bạn chọn, có thể tham khảo tại AreWeWebYet.
Với những ai thích xài các framework nhỏ gọn tiny_http là sự lựa chọn hoàn hảo.
Xét về mặt đơn giản, dễ dùng thì nickel.rs, là một trong những framework tinh gọn nhất trong Rust, và lấy cảm hứng từ Express framework bên Node.js
Nếu bạn muốn hỗ trợ HTTP/2, thì solicit là sự lựa chọn duy nhất tính tới thời điểm này.
Cá nhân mình thích xài rocket.rs vì nó là một framework rất mạnh và có rất nhiều tính năng, nhưng vẫn giữ cho code của bạn đơn giản tới mức tối đa. Gần đây thì rocket.rs đã hỗ trợ luôn TLS built-in. Điểm trừ duy nhất của framework này đó là cần sử dụng phiên bản Rust Nightly.
Đây là đoạn code ví dụ việc handle một endpoint dùng GET method với rocket.rs:
Từ đây thì mình có thể đưa hết toàn bộ code frontend vào một thư mục, ví dụ như là www, và gọi tới RESTful API từ Rust. Để rõ hơn thì đây là ví dụ minh họa về cấu trúc của mộ project mà mình thường làm:
Để kết nối với database, chúng ta có thể sử dụng các ORM như Diesel.
Nếu bạn muốn tham khảo ví dụ thực tế về 1 project sử dụng rocket.rs + Diesel (cho backend) và React (cho frontend), thì đây là mã nguồn của Kipalog Links – website đọc/tổng hợp tin bài từ các blogger công nghệ tiếng Việt mình làm cho Kipalog.
Gửi mail cho mình link RSS blog của bạn nếu bạn muốn bài viết của mình được list trên Kipalog Links 😛
Phương pháp cuối cùng, là phương pháp mình thích nhất, giống với thời kì nằm 2012, khi mình mới bắt đầu sự nghiệp lập trình với một chân code thuê PHP. :))
Không còn những khái niệm Single Page Application, client-side rendering. Không còn những trang web bể tè le hột me khi người dùng disable JavaScript nữa.
Fun fact: Hầu hết các website lớn đều hoạt động ngay cả khi bạn tắt JavaScript của trình duyệt
Cũng như nhiều framework đến từ các ngôn ngữ khác (như Rails, CakePHP, ASP.NET…), rocket.rs hỗ trợ bạn render một HTML template sau khi đã bind dữ liệu vào đó từ phía server, trình duyệt chỉ cần nhận về và hiển thị lên màn hình.
#[get("/")]fnindex() -> Template {
let news = fetch_from(RSS_URL).ok().expect("Could not read RSS");
Template::render("index", &news)
}
Ở bài viết trước, mình hướng dẫn cách build một ứng dụng đọc tin Hacker News dùng rocket.rs và Handlebars template, chính là áp dụng phương pháp này.
Các bạn có thể tham khảo mã nguồn đầy đủ của project để nắm rõ hơn. Phiên bản code trong mã nguồn này có áp dụng một vài kĩ thuật mới chưa được đề cập trong bài trước để giải quyết vấn đề load nội dung qua giao thức HTTPS.
Vậy là chúng ta đã điểm qua hết các phương pháp sử dụng Rust vào cho một project Web. Mỗi một phương pháp trên đều có những ưu nhược điểm khác nhau, có thể sử dụng tùy theo từng yêu cầu khác nhau của mỗi dự án, và bạn cũng hoàn toàn có thể kết hợp các phương pháp này lại với nhau trong cùng một dự án.
Hy vọng qua bài viết này, các bạn có được cái nhìn toàn cảnh về việc lập trình Web với Rust, và có được câu trả lời của riêng mình cho câu hỏi: “Rust có làm được Web không?”.
Và chúc các bạn may mắn nếu quyết định sử dụng Rust vào cho project của mình.
Bài viết được dịch lại từ bản gốc “Rust for the Web” đăng tại phiên bản blog tiếng Anh của mình.
Algorithm in Frontend - Kỳ 1: Xử lý dữ liệu trên Frontend
Bài viết được sự cho phép của tác giả Huy Trần
Đối với lĩnh vực Frontend nói riêng, chuyện học hay luyện các kĩ năng phân tích thiết kế thuật toán là một kĩ năng bị xem nhẹ nhất. Vì lý do đơn giản, chúng ta không thấy nhiều về tính ứng dụng của nó vào công việc thực tế.
Nhưng đây là sai lầm lớn nhất của đại đa số Frontend Developers.
Trên thực tế, chúng ta phải đối mặt với các vấn đề cần phải sử dụng thuật toán, và cần phải vận dụng các kĩ năng phân tích thiết kế thuật toán gần như là hằng ngày. Nhưng rất ít khi chúng ta nhận ra.
Đây cũng là lý do mà mình viết sê-ri Algorithm in Frontend này, xoay quanh những kinh nghiệm thực tế mà mình đã gặp phải trong thời gian làm việc, phần lớn là trong hai lĩnh vực sản phẩm mình đã/đang làm là Realtime Infrastructure Monitoring (theo dõi hạ tầng CNTT thời gian thực) và Health Care (chăm sóc sức khỏe).
Bài đầu tiên nói về vấn đề Xử lý dữ liệu trên Frontend.
1. Đặt vấn đề
Nếu các bạn có đọc bài phỏng vấn của mình trên blog Tôi Đi Code Dạo, thì có lẽ các bạn đã biết, công việc chính của mình hiện nay ngoài việc fix bug cũ ra thì còn phải phối hợp với các team khác nhau để tạo ra bug mới xây dựng feature mới cho sản phẩm của công ty.
Một trong những chức năng mới nhất mà team mình vừa ship thành công đó là cung cấp khả năng thống kê tình trạng sức khỏe của bệnh nhân cho các bác sĩ.
Dạng đơn giản nhất của chức năng này, thì các bạn có thể hình dung thông qua hình minh họa sau (lấy từ bảng thống kê của Fitbit, không phải sản phẩm công ty mình, NDA đã ký, up bậy lên là thành homeless ngay, cũng xin các bạn đừng phán xét về mức độ siêng năng đi bộ của mình :v).
Đây là tính năng thống kê dữ liệu theo từng khoản nn ngày tính từ ngày hiện tại (ở đây n=7n=7). Lưu ý là không phải thống kê theo tuần nhé.
Như vậy, nếu hôm nay là thứ 5 bác sĩ muốn xem tình trạng sức khỏe trong 7 ngày gần đây của bênh nhân thì phía Frontend phải hiển thị được dữ liệu trong khung thời gian như hình sau:
Từ phía frontend, một request có dạng như sau sẽ được gửi lên để lấy dữ liệu:
GET /api/v0/tracker?from=14-09-2017&to=08-09-2017
Bất kỳ ngày nào có dữ liệu thì sẽ được gửi trả về, không có dữ liệu thì không xuất hiện luôn:
Date
Steps
Fri 08-09-2017
5123
Mon 11-09-2017
1734
Tue 12-10-2017
5000
Wed 13-10-2017
4985
Thu 14-10-2017
3220
Và để vẽ được biểu đồ lên màn hình theo đúng nn ngày thì nội dung đầu vào phải đúng nn records. Thiếu hay thừa 1 record đều sẽ dẫn đến kết quả hiển thị bị sai.
Phía frontend phải làm công việc xử lý dữ liệu để với mỗi record bị thiếu, chèn vào một record mới với một giá trị mặc định, đảm bảo tính đúng đắn này.
Ví dụ với bảng dữ liệu trên, sẽ phải chèn thêm 2 record mới là:
Date
Steps
Sat 09-09-2017
0
Sun 10-09-2017
0
2. Bài toán cần giải quyết
Để dễ hình dung hơn, ta có thể đơn giản hóa bài toán cần giải quyết cho vấn đề trên là:
Cho một mảng II gồm mm phần tử (m>0m>0), với mỗi phần tử là một ngày trong tuần, không liên tục, và một số nn (với m⩽nm⩽n), implement thuật toán trả về mảng OO gồm nn ngày liên tục, tính từ phần tử đầu tiên của II, và vẫn giữ được thứ tự xuất hiện trong mảng.
Có thể thấy đây là một bài toán hết sức đơn giản, việc cần làm chỉ là tạo ra một mảng nn phần tử và lần lượt đưa vào mảng này các ngày tương ứng, tính từ ngày đầu tiên trong mảng II. Nếu một phần tử đã tồn tại ở mảng II thì chúng ta sẽ đưa phần tử đó vào mảng kết quả.
Ta cũng chú ý đến tính chất xoay vòng của các ngày trong tuần, nếu cho ii là một giá trị tăng dần, với i=0i=0 là thứ hai (Monday), i=1i=1 là thứ ba (Tuesday), tiếp tục tăng, đến i=6i=6 sẽ là Chủ nhật (Sunday). Tương đương với một mảng có 7 phần tử, như sau:
const DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
Ta có thể viết một hàm day_to_num() để chuyển đổi giữa giá trị ngày sang số để tiện cho việc tính toán:
const day_to_num = day => DAYS.findIndex(i => i === day);
Nếu ii tiếp tục tăng, thì với việc đối chiếu thông thường, i=7i=7 tương ứng với DAYS[7]DAYS[7], là một giá trị không tồn tại. Để ii tiếp tục tăng nhưng giá trị tham chiếu phải xoay vòng, ta có thể thay ii bằng một giá trị i2i2 với:
i2=imod7i2=imod7
Ví dụ, với i=12i=12 ta có i2=12mod7=5i2=12mod7=5 tương đương với DAYS[5]=SatDAYS[5]=Sat.
Dựa vào đây ta có thể viết hàm num_to_day() để chuyển một giá trị số thành ngày tương ứng:
const num_to_day = num => DAYS[num % DAYS.length];
Thuật toán xử lý dữ liệu của chúng ta có thể được mô tả thông qua các bước như sau:
Bước 1: Tạo ra mảng result có nn phần tử, với phần tử đầu tiên cũng là giá trị đầu của mảng II.
Bước 2: Tạo một vòng lặp với i=1→ni=1→n.
Bước 2a: Ở mỗi lần lặp, tìm ngày tiếp theo tương ứng với vị trí ii.
Bước 2b: Duyệt qua mảng II để tìm giá trị tương đương với giá trị vừa tính được ở bước 2a.
Bước 2c: Nếu tìm được giá trị ở bước 2b thì đưa giá trị này vào mảng result, nếu không thì đưa giá trị ở bước 2a vào.
Bước 3: Trả về kết quả của mảng result.
Implement thuật toán trên bằng JavaScript:
const fill_days = (input, n) => {
let result = [input[0]];
for (let i = 1; i < n; i++) {
let previous_day = day_to_num(result[i - 1]);
let current_day = num_to_day(previous_day + 1);
let day_from_input = null;
for (let j = 0; j < input.length; j++) {
if (current_day == input[j]) {
day_from_input = input[j];
break;
}
}
if (day_from_input) {
result.push(day_from_input);
} else {
result.push(current_day);
}
}
return result;
};
Đừng quên test lại để đảm bảo thuật toán của chúng ta chạy đúng:
Vậy là hàm fill_days() của chúng ta đã hoạt động và trả về đúng giá trị cần tìm, tuy nhiên chúng ta không thể dừng ở bước này được vì thuật toán trên vẫn còn rất nhiều điểm cần phải cải thiện.
Cụ thể, chúng ta sẽ thực hiện các thay đổi như là cache lại những chỗ tính toán bị lặp đi lặp lại, tận dụng lại biến current_day để bỏ bớt một khối lệnh if không cần thiết,…
Hàm day_to_num() cũng có thể được tối ưu bằng cách không dùng hàm findIndex() có sẵn nữa mà tự viết vòng lặp for riêng.
const day_to_num = day => {
for (let i = 0, len = DAYS.length; i < len; i++) {
if (DAYS[i] == day) return i;
}
return-1;
};
const fill_days = (input, n) => {
let result = [input[0]];
for (let i = 1; i < n; i++) {
let previous_day = day_to_num(result[i - 1]);
let current_day = num_to_day(previous_day + 1);
for (let j = 0, len = input.length; j < len; j++) {
if (current_day == input[j]) {
current_day = input[j];
break;
}
}
result.push(current_day);
}
return result;
};
Chúng ta có thể chạy test lại, kết quả vẫn chính xác.
Vậy là chúng ta đã xây dựng thành công thuật toán xử lý lấp đầy dữ liệu cho trước bằng những ngày bị thiếu và vẫn đảm bảo được số lượng record, và thứ tự xuất hiện của các record.
Việc tiếp theo là ứng dụng thuật toán này vào với dữ liệu thực tế.
Qua bài viết này, chúng ta đã cùng đi qua các bước: Tiếp cận vấn đề thực tế, phân tích bài toán, xây dựng thuật toán, cải thiện thuật toán để chạy tốt hơn, và cuối cùng là ứng dụng thuật toán đó để giải quyết các yêu cầu kĩ thuật từ phía frontend.
Mình biết cảm giác bây giờ của các bạn là gì, các bạn đang nghĩ là cái quần què này thì có gì đâu, đây vẫn là thứ mà các bạn vẫn làm mỗi ngày mà. Đúng là như vậy, chúng ta đã và đang áp dụng thuật toán vào cho công việc frontend mỗi ngày.
Có thể thấy, việc áp dụng, xây dựng, sử dụng thuật toán là một vấn đề chung không chỉ giới hạn trong bất kì một lĩnh vực nào của lập trình. Hy vọng bài viết này có thể giúp bạn nhận ra tầm quan trọng của thuật toán, nhất là đối với các bạn frontend developers.
Cảm ơn các bạn đã kiên nhẫn đọc đến tận đây. Hẹn gặp lại các bạn ở các phần sau của sê-ri Algorithm in Frontend.
Viết Đơn Xin Việc Như Thế Nào Để Gây Ấn Tượng Với Nhà Tuyển Dụng?
Ngày nay việc gửi CV xin việc qua email đã trở nên quá quen thuộc, nhưng chỉ một bộ CV với thông tin cá nhân cũng như kinh nghiệm làm việc ấn tượng, bạn nghĩ đã đủ để gây ấn tượng với nhà tuyển dụng? Thực tế thì khi gửi đơn xin việc qua email, điều quan trọng và đầu tiên được các nhà tuyển dụng xem qua chính là nội dung đơn xin việc của ứng viên. Vậy nên viết đơn xin việc – cover letter như thế nào để vừa ngắn gọn lại vừa gây ấn tượng tốt trong mắt nhà tuyển dụng?
Viết Đơn Xin Việc Như Thế Nào Để Gây Ấn Tượng Với Nhà Tuyển Dụng?
1. Tiêu đề thư – Subject
Tiêu đề chính là một trong những yếu tố khá quan trọng để nhà tuyển dụng quyết định có nên xem thư xin việc của ứng viên hay không. Vậy nhưng có không ít ứng viên hiện nay lại chưa chú tâm đến việc viết email có tiêu đề thư cung cấp được thông tin chính xác. Thậm chí có không ít ứng viên còn gửi mail mà không hề có tiêu đề. Đây là một sai lầm chắc chắn không nên lặp lại.
Thông thường tiêu đề thư sẽ là tóm tắt nội dung mà bạn muốn đề cập đến trong email. Theo đó, với nội dung của đơn xin việc, ứng viên nên đặt tiêu đề gồm Họ & tên – Vị trí ứng tuyển. Tùy theo một số công ty, có thể trong JD công việc có yêu cầu chi tiết về việc ứng viên nên đặt tiêu đề thư như thế nào cùng với mã số vị trí công việc.
2. Lời chào đầu thư
Trước khi bắt đầu đề cập đến nội dung chính của đơn xin việc, lời chào đầu tư cần được nhắc đến trước tiên. Việc viết lời chào đầu thư như thế nào sẽ phụ thuộc vào những thông tin bạn có về vị trí tuyển dụng đó.
Nếu ứng viên đã biết cụ thể mình nên gửi mail cho ai và chắc chắn về thông tin thì nên viết lời chào theo công thức Dear Mr/Ms + tên nhà tuyển dụng,
Trong trường hợp bạn không biết rõ người mình cần nộp đơn xin việc cụ thể là ai thì có thể viết theo cách gọi chung như Dear HR Team, Dear Công ty…, To whom it may concern,… Hãy cân nhắc các thông tin bạn có để có thể đưa ra lời chào đầu thư phù hợp nhất với tình huống của bản thân.
Trước tiên, ứng viên cần nhớ rằng, đơn xin việc – cover letter chỉ thể hiện thành ý của bạn đang mong muốn ứng tuyển vào vị trí này, còn những vấn đề cụ thể như kinh nghiệm làm việc sẽ được đề cập chi tiết trong CV. Chính vì thế đừng nên viết quá dài dòng sẽ khiến người đọc khó chịu. Nội dung chính của một cover letter chỉ nên kéo dài trong 1 – 2 đoạn cơ bản mà thôi.
Với đoạn đầu tiên, ứng viên nên đề cập đến mong muốn và vị trí bạn đang quyết định ứng tuyển “I’m writing to you with regards to the position within your company for Marketing Executive” – “Tôi viết thư này với mong muốn được ứng tuyển vào vị trí chuyên viên Marketing tại công ty”.
Các nội dung tiếp theo, người viết cover letter nên cố gắng làm rõ những nội dung như Tại sao bạn lại ứng tuyển vào vị trí này? Bạn đã có những kinh nghiệm làm việc nào? Mong muốn của bạn khi muốn làm việc tại công ty?…
Tất cả đều nên được trình bày một cách ngắn gọn, xúc tích mà vẫn đủ ý. Đừng viết quá dài dòng vì nhà tuyển dụng sẽ không có đủ thời gian để đọc hết những gì bạn trình bày. Những nội dung chi tiết có thể được trình bày khi ứng viên đến với buổi phỏng vấn trực tiếp tại công ty.
Có một mẹo nhỏ được nhiều người áp dụng, đó là để có thể viết ngắn nhưng vẫn gây ấn tượng với người đọc thư, ứng viên nên diễn tả kinh nghiệm của mình bằng những con số. Nó vừa dễ nhìn, vừa cho thấy được những con số bạn đã trải qua trong quá trình học tập và làm việc của mình.
4. Cách kết thúc trong đơn xin việc
Trong phần kết thúc, hãy cố gắng nhấn mạnh lại một lần nữa rằng với những kinh nghiệm mà bạn đã có, bạn hoàn toàn có thể làm tốt những nhiệm vụ mà công ty đang đặt ra. Cũng như bày tỏ mong muốn rằng, bạn muốn được thông qua vòng sơ loại hồ sơ để có cơ hội được phỏng vấn và trao đổi thêm với công ty.
Bên cạnh đó, hãy nhớ đề cập với nhà tuyển dụng rằng bạn đã đính kèm thông tin CV hay portfolio cá nhân có thông tin chi tiết về quá trình làm việc của bạn. Và đừng quên dành đến nhà tuyển dụng lời cảm ơn vì đã dành thời gian đọc đơn xin việc của bạn.
Ngoài ra, có một phần cuối ở bức thư mà bạn không nên bỏ qua đó là chữ ký. Để thể hiện sự chuyên nghiệp cũng như nhà tuyển dụng có thêm thông tin liên lạc với bạn khi cần thiết, hãy đề cập đầy đủ về họ tên và thông tin như số điện thoại cá nhân của mình.
Đơn xin việc – cover letter là một trong những thông tin quan trọng bạn không nên bỏ qua khi gửi email ứng tuyển với nhà tuyển dụng. Biết cách viết cover letter chuyên nghiệp chính là bước đầu tiên để bạn có thể ghi điểm với công ty tuyển dụng. Hy vọng bài viết trên đã giúp bạn có thêm thông tin cho hành trình tìm việc của mình.
Tuyển Dụng Nhân Tài IT Cùng TopDev Đăng ký nhận ưu đãi & tư vấn về các giải pháp Tuyển dụng IT & Xây dựng Thương hiệu tuyển dụng ngay!
Hotline: 028.6273.3496 – Email: contact@topdev.vn
Dịch vụ: https://topdev.vn/page/products
Một số khái niệm cần biết trong Kubernetes Architecture
Bài viết được sự cho phép của tác giả Kiên Nguyễn
Làm việc với các topics thì đã từ lâu nhưng từ nay Kieblog sẽ mở thêm chuyên mục mới viết các bài viết về Devops, bắt đầu với bài viết về Kubernetes Architecture nha anh em.
Cảm ơn anh em đã dành thời gian đọc bài. Do bên mảng Devops tui vẫn là amateur nên có gì sai sót nhờ anh em chỉ giao chó.
Nhầm, chỉ giáo cho.
1. Kubernetes là gì?
Bắt đầu luôn là khái niệm. Riết nó chán nhưng thôi ráng đọc.
Kubernetes architecture components or K8s components include the Kubernetes control plane and the nodes in the cluster. The control plane or master machine components include the Kubernetes API server, Kubernetes scheduler, Kubernetes controller manager, and etcd. Kubernetes node components include a container runtime engine or docker, a Kubelet service, and a Kubernetes proxy service.
Kiến trúc Kubernetes hoặc K8s components bao gồm phần điều khiển của Kubernetes và các nodes ở trong một cluster. Phần điều khiển của Kubernetes bao gồm Kubernetes API Server, Kubernetest scheduler, controller manager và nhiều thứ khác nữa. Trong node components thì bao gồm engine và docker, Kubelet service và Kubernetes proxy service.
Dưới đây là một số khái niệm trong Kubernestes Architecture anh em cần nắm rõ.
Trời má, chưa biết gì mà nhìn cái Architecture muốn nhức cả đầu.
Thôi thì ta đi step by step. Tìm hiểu từng thứ một anh em ạ.
2. Container
Anh em nào đã tìm hiểu hoặc làm việc với Docker chắc không còn xa lạ gì khái niệm về Container. Container không được liệt kê là một thành phần chính trong Kubernetes Architecture. Tuy nhiên bài viết này vẫn nhắc tới vì nếu không hiểu về Container, ta sẽ không thể đi tiếp các Components khác.
Containers are a solution to the problem of how to get software to run reliably when moved from one computing environment to another
Containers là giải pháp giải quyết vấn đề làm sao phần mêm có thể chạy tốt khi thay đổi computing environment từ cái này qua cái kia
Đại thể có thể tưởng tượng Container như cái thùng sau xe container mà ta biết, thảy lên tàu thuỷ cỡ nào cũng chở được, cũng chạy được.
Trong Container bao gồm tất cả mọi thứ mà ta cần để chạy Software hoặc Application.
Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings.
Docker container image nhẹ, độc lập, bao gồm các gọi thực thi của phần mềm. Trong đó bao gồm tất cả những gì cần thiết để ta khởi chạy application: code, runtime, system tools, system libraries và cả settings (các thiết lập).
Docker Container bao gồm mọi thứ cần thiết để chạy software hoặc applications của chúng ta. Nguồn ảnh/ Source: docker.com
Container là một item nhỏ trong Kubenetes Architecture, tiếp theo đây ta sẽ nói về Pods, thằng bự hơn bao gồm một hoặc nhiều Container trong đó.
3. Pod
Pod là khái niệm quan trọng trong Kubernetes Architecture. Lý thuyết thì luôn lèo nhèo khó hiểu nhưng vẫn phải đọc để hiểu.
Một Pod là một khái niệm trừu tượng của Kubernetes, đại diện cho một nhóm gồm một hoặc nhiều ứng dụng containers (ví dụ như Docker hoặc rkt) và một số tài nguyên được chia sẻ cho các containers đó.
Vậy sau khi đã có Container với Docker thì Pods là thằng lớn hơn (có thể có một hoặc nhiều Container trên pod). Nhưng không chỉ có mỗi Container, trên Pod còn bao gồm nhiều thành phần khác như:
Lưu trữ được chia sẻ, dưới dạng Volumes
Kết nối mạng, như một cluster IP duy nhất
Thông tin về cách chạy từng container, chẳng hạn như phiên bản container image hoặc các ports cụ thể để sử dụng
Ngoài container, pod còn bao gồm IP address, và version của container image. Nguồn ảnh/ Source: docker.com
4. Nodes
Sau khi đã hiểu về Pod và những thứ bao gồm trong Pod, tiếp đến ta sẽ tìm hiểu về khái niệm Nodes.
Trong Kubernetes Architecture, Nodes là khái niệm bắt buộc hiểu và nắm thật rõ.
Cluster nodes are machines that run containers and are managed by the master nodes. The Kubelet is the primary and most important controller in Kubernetes
Cluster nodes là máy mà chúng ta sử dụng để chạy containers và quản lý bởi master nodes. Kubelet là thành phần chính và quan trọng trong Kubernetes.
Má, khái niệm loằng ngoằng, nhưng anh em nhớ giúp Nodes là thằng chịu trách nhiệm để điều khiển lớp thực thi (execution layer), là nơi mà ta push cái Docker lên
It’s responsible for driving the container execution layer, typically Docker.
Ngoài ra, nodes có thể la virtual hoặc physical, phụ thuộc và cái cluster.
A Node is a worker machine in Kubernetes and may be either a virtual or a physical machine, depending on the cluster
Node là worker machine (máy ảo hoặc máy thật), cái này phụ thuộc vào cluster.
Nodes cũng được chia thành 2 loại là master node và worker node. Có điều kiện sẽ viết rõ thêm cho anh em về hai loại này.
5. Cluster
Sau khi đã biết về Nodes thì xin mời anh em đi tiếp tới Cluster, thằng mà bự hơn Nodes. Bài viết này viết về khái niệm từng thành phần trong Kubernetes Architecture nên mình sẽ đi tuần tự từ bé tới lớn.
A Kubernetes cluster is a set of nodes that run containerized applications. Containerizing applications packages an app with its dependences and some necessary services. They are more lightweight and flexible than virtual machines. In this way, Kubernetes clusters allow for applications to be more easily developed, moved and managed.
Kubernetes cluster là một tập hợp các nodes để chạy ứng dụng trong vùng chứa. Bao gồm một ứng dụng và các thành phần liên quan. Chúng nhẹ và linh hoạt hơn so với máy ảo. Bằng cách này, các cụm Kubernetes cho phép các ứng dụng được phát triển, di chuyển và quản lý dễ dàng hơn.
Rồi, hiểu Cluster thì bao gồm các Nodes trong đó + một số thành phần liên quan. Có một cái nữa:
Every cluster has at least one worker node.
Mỗi cluster bắt buộc phải có ít nhất một worker node trong đó.
Trong thực tế (production) thì thông thường một cluster sẽ có nhiều nodes. Điều này đảm bảo tính ổn định (availability) và fault-tolerance.
The control plane usually runs across multiple computers and a cluster usually runs multiple nodes, providing fault-tolerance and high availability.
Control plane của Kubernetes thường chạy thông qua nhiều máy và cluster thông thường chạy nhiều nodes khác nhau.
Generate API contract sử dụng Spring MVC-RAML Plugin
Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh
Sau khi định nghĩa API specs với RAML, chúng ta sẽ tiến hành implement API specs này. Nếu ứng dụng của các bạn đang sử dụng Spring framework thì các bạn có thể sử dụng Spring MVC-RAML Plugin để generate API contract với Spring framework và chỉ cần thêm code implementation. Cụ thể như thế nào? Chúng ta hãy cùng nhau tìm hiểu trong bài viết này các bạn nhé!
Đầu tiên, mình sẽ tạo mới một Spring Boot project với Web dependency như sau:
Kết quả:
Để làm ví dụ, mình sẽ sử dụng API specs được định nghĩa với RAML trong bài viết về API fragments với RAML. Các bạn có thể lấy nội dung của API specs này ở đây, copy tất cả các tập tin, folder vào thư muc src/main/resources/api của project của chúng ta:
Để bắt đầu, chúng ta sẽ khai báo Spring MVC-RAML Plugin trong project của chúng ta như sau:
Chúng ta sẽ thêm phần cấu hình để plugin này có thể làm việc được. Cấu hình này bao gồm đường dẫn tới tập tin RAML chúng ta sẽ sử dụng để generate các request URI, đường dẫn thư mục của class Controller sẽ được generate, … Các bạn có thể cấu hình plugin này cơ bản như sau:
<ramlPath> cho phép chúng ta cấu hình đường dẫn đến tập tin RAML định nghĩa API specs.
<outputRelativePath> sẽ là đường dẫn đến thư mục sẽ chứa API contract được generate. Ở đây, các bạn cũng thấy, chúng ta còn có <basePackage> để định nghĩa package cho generated Java classes.
<baseUri> sẽ override lại định nghĩa baseUri mà chúng ta định nghĩa trong tập tin RAML. Khi generate thì giá trị của baseUri sẽ được sử dụng để định nghĩa request URI ở đầu mỗi Controller class đó các bạn!
<rule> cho phép chúng ta định nghĩa cách mà các Controller classes sẽ được generated. Spring MVC-RAML Plugin định nghĩa một số rule như sau:
Spring4ControllerInterfaceRule sẽ generate các Controller class là những interface. Chúng ta sẽ cần tạo các class implementation cho những interface Controller này.
Spring4RestTemplateClientRule thì sẽ generate các class giúp chúng ta consume các request URI mà chúng ta định nghĩa trong API specs.
Spring4ControllerDecoratorRule sẽ generate code dựa vào decorator design pattern.
Spring4ControllerStubRule sẽ generate các Controller class và chúng ta sẽ modify những class này để thêm phần implementation.
Mình thì như các bạn thấy, sử dụng Spring4ControllerInterfaceRule để tách bạch định nghĩa API specs với phần implementation. Sau này có thay đổi gì đến API specs, chúng ta chỉ thay đổi code implementation khi cần thiết mà thôi.
Còn một số các cấu hình khác mà các bạn có thể tìm hiểu thêm ở đây. Trong bài viết này, mình chỉ giới thiệu với các bạn một số cấu hình cơ bản.
Sau khi cấu hình xong, chúng ta có thể cấu hình phần execution để mỗi khi chúng ta compile, build source code, Spring MVC-RAML Plugin có thể chạy để generate code cho chúng ta, ví dụ như sau:
Goal “generate-springmvc-endpoints” của Spring MVC-RAML Plugin sẽ giúp chúng ta generate code lúc compile.
Bây giờ thì nếu các bạn chạy “mvn clean install”, kiểm tra project, các bạn sẽ thấy code được generate như sau:
2 class Controller tương ứng với 2 root request URIs mà chúng ta đã định nghĩa trong tập tin RAML. Kiểm tra nội dung của các class Controller này, các bạn sẽ thấy chúng là những interface:
Nhiệm vụ của chúng ta là tạo mới các class khác để implement các interface này.
Khi generate các class Controller này, một số thư viện đã được sử dụng để adapt với định nghĩa trong tập tin RAML. Trong trường hợp của mình, có 2 thư viện mà Spring MVC-RAML Plugin đã sử dụng là Common Lang và Java Bean Validator, chúng ta cần phải khai báo sử dụng các dependencies này để project không bị lỗi như sau:
Bài viết được sự cho phép của tác giả Trần Anh Tuấn
Sau series HTML cơ bản dành cho người mới thì bây giờ mình lại tiếp tục tới một series cơ bản khác đó chính là CSS cơ bản. Sau khi học HTML cơ bản thì các bạn đã biết dùng tới các thẻ như thế nào rồi, mỗi thẻ được tạo ra với mục đích là gì, khác nhau giữa inline và block như thế nào…
Sau khi chúng ta tạo được sườn của trang web với HTML thì việc tiếp theo là làm sao cho nó đẹp lên, trang trí cho nó như thế nào, tùy biến các kiểu ra sao… thì đây chính là công việc của CSS. Vậy trong CSS có những thuộc tính gì và nó hoạt động ra sao thì hãy cùng mình tìm hiểu dưới đây nha
Để viết được CSS thì việc đầu tiên các bạn cần làm là tạo một file có đuôi mở rộng là .css là được ví dụ như mình ở đây sẽ là main.css, sau đó chúng ta sẽ chèn nó vào HTML như thế này. Việc tạo file HTML rất là đơn giản nhé, tạo file main.html rồi gõ ! thì vscode emmet sẽ gợi ý ra cấu trúc chuẩn cho các bạn
Chèn file main.css vào file main.html
Sau khi chèn CSS vào được file HTML rồi thì việc tiếp theo chúng ta cần làm đó chính là tìm hiểu về cấu trúc của một đoạn code CSS cơ bản là như thế nào nhé
Như hình thì các bạn sẽ thấy cấu trúc mình ghi rõ ràng. Trong đó:
Selectors: Là các thẻ HTML đã học như div, h2, body, span, a, hoặc là class(bắt đầu với dấu chấm như .heading, .item, .header), hoặc là id(bắt đầu với dấu # như là #header, #container…)
Property: Là những thuộc tính CSS mà chúng ta sẽ học sắp tới đây
Value: Là giá trị tương ứng của Property
Cấu trúc đoạn code CSS cơ bản
Thuộc tính Color
Thuộc tính này dùng để đổi màu chữ cho trang web, chỗ nào các bạn dùng chữ thì có thể đổi màu được, và giá trị của nó là các mã màu, mã màu ở đây có thể là name(red, orange, blue…), hexa(#ffa400), rgb(255,255,255), hsl(39, 100%, 50%) tùy vào mục đích mà chúng ta sử dụng sao đó cho nó hợp lý
Nếu các bạn muốn có màu chữ trong suốt thì nên dùng rgb hoặc hsl. Ví dụ với rgb thì các bạn có thể viết như thế này rgba(rgb-color, alpha) trong đó alpha là độ trong suốt chạy từ 0 cho đến 1 tương ứng từ không thấy gì cho đến rõ dần, còn rgb-color thì sẽ là mã màu ví dụ màu đen sẽ là 0, 0, 0. Ở hình này mình đang dùng màu đen nhưng độ trong suốt của nó giảm đi một nửa nên mình truyền vào là 0.5 nè
Thay đổi màu chữ của class heading
Thuộc tính background-color
Cái này thì tương tự cho cái trên nên mình không có giải thích lại, chỉ khác cái là background-color thì sẽ áp dụng cho màu nền của một khối nào đó, ví dụ các bạn sơn tường thì đó là background-color, còn viết chữ lên đó thì sẽ là color. Giải thích vậy thì chắc các bạn sẽ dễ hiểu hơn đúng không nào?
Thay đổi màu nền trang web với background-color
Thuộc tính text-align
Thuộc tính này thì có 4 giá trị hay dùng, trong đó giá trị mặc định là left. Nếu các bạn có dùng word để soạn thảo thì không còn xa lạ gì về việc căn chữ hiển thị trái, phải, giữa, và đều 2 bên. Tương tự như vậy ở trong CSS thì thuộc tính này có 4 giá trị như sau, lưu ý là ở đây mình đang liệt kê nhen, khi dùng thì tùy vào thiết kế mà các bạn dùng 1 trong 4 cái nhé.
Thuộc tính line-height
Thuộc tính này sẽ làm tăng hoặc giảm chiều cao của dòng chữ, ví dụ các bạn có đoạn chữ có font-size là 20px thì nếu là một dòng nó sẽ có chiều cao là 20px, nhưng nếu là 2 dòng thì chiều cao sẽ là 40px. Lúc này các bạn muốn tạo khoảng trống giữa các dòng cho nó thoáng hơn chẳng hạn thì các bạn sẽ dùng line-height
Giá trị line-height càng lớn thì khoảng cách dòng càng xa, nên các bạn lưu ý điều đó. Ở đây mình ví dụ là 2 dòng sẽ có chiều cao là 40px, tuy nhiên khi mình thêm line-height: 2 vào thì nó sẽ ảnh hưởng, chúng ta sẽ lấy chiều cao nhân cho line height là 2 thì kết quả chiều cao của 2 dòng sẽ là 80px đấy nhé.
Thuộc tính letter-spacing
Ở trên thì là khoảng cách giữa các dòng, vậy thì khoảng cách giữa các kí tự trong chữ thì sao nhỉ ? Chúng ta sẽ dùng letter-spacing nhé, số càng lớn thì các kí tự càng thưa và ngược lại, số càng nhỏ thì nó càng sát lại
Thuộc tính word-spacing
Nếu có khoảng cách giữa các kí tự thì cũng sẽ có khoảng cách giữa các từ, tương tự như trên nhưng là thuộc tính khác word-spacing
Thuộc tính work-break
Sau này khi các bạn đã có kiến thức và đi làm, đôi khi các bạn sẽ làm với những giao diện mà nội dung được người dùng nhập vào, và họ cố ý nhập các chữ dính nhau và làm giao diện chúng ta bị bể, như dưới này, cái khối màu xám mình chỉ cho độ rộng là 300px và các bạn thấy là các chữ nó bị tràn ra ngoài luôn
Để giải quyết nó thì chúng ta sẽ dùng thuộc tính work-break và giá trị là break-all hoặc là `break-word` tùy vào mục đích của giao diện chúng ta
Xử lý chữ dính nhau với work-break
Thuộc tính text-overflow
Tuy nhiên có một vài trường hợp theo giao diện thiết kế thì chữ nó phải nằm trên một hàng, và nếu dài quá cho phép thì ẩn đi và hiển thị dấu 3 chấm thì phải làm sao ? Đừng lo lắng việc đầu tiên chúng ta cần làm đó chính là làm sao để hiển thị một hàng cái đã.
Để hiển thị chữ trên một hàng thì chúng ta sẽ dùng thuộc tính white-space: nowrap lúc này ta sẽ được như này
Chữ bị tràn ra ngoài khi dùng nowrap
Tuy nhiên nó lại quay lại vấn đề khi trước là chữ bị tràn ra ngoài khối làm giao diện bị bể, để giải quyết nó chúng ta sẽ kết hợp thêm 2 thuộc tính là overflow: hidden(nghĩa là nếu bị tràn ra ngoài thì sẽ ẩn đi) và text-overflow: ellipsis( để hiển thị dấu 3 chấm)
Tạm kết phần 1
Mình tạm kết phần 1 ở đây, ở phần này thì các bạn cũng đã có hiểu biết chút chút về CSS là gì rồi cũng như biết cách chèn vào file HTML như thế nào, các selectors ra sao, cấu trúc của CSS, và học được khá nhiều thuộc tính cơ bản liên quan tới chữ. Hi vọng những kiến thức mình chia sẻ sẽ có ích cho các bạn khi bắt đầu học CSS nhen. Hẹn gặp lại các bạn ở phần 2.
Đối với nghề lập trình nói chung và công việc Frontend nói riêng, theo mình, cái khoảnh khắc tự mình đọc hiểu hoặc viết ra được một đoạn Regex (biểu thức chính quy – reqular expression) có thể coi là một trong những khoảnh khắc đáng nhớ nhất (well…).
Thực ra cũng như nhiều người khác, mình được tiếp xúc với Regex từ khá sớm – từ những ngày đầu tiên bắt đầu nghề mần web, với PHP. Xuất hiện thường xuyên nhất chắc là khi phải viết các route handler, rồi thì kiểm tra độ chính xác của email,… Và trong một thời gian rất dài, mình cũng chỉ đi copy paste. Nhưng rồi mình quyết định phải học để hiểu được thứ cú pháp ngoài hành tinh này. Và cũng trong một thời gian dài mình vỗ ngực tự khen là đã học được Regex, xong rồi muối mặt khi nhận ra bất cứ ai nghiêm túc theo nghề lập trình đều biết Regex hết :)) và nhất là cái bọn xài vim.
Khoan hãy bàn đến tính hiệu quả của Regex, bài viết này mình muốn nói đến một thực trạng của rất đông đảo các lập trình viên, tech blogger, mentor, giảng-bài-viên ở các trung tâm,…
Đó là việc chia sẻ và copy về sử dụng các đoạn Regex một cách mù quáng.
Không quá khó để có thể tìm thấy trên Google các kết quả như: n đoạn biểu thức chính quy cần biết cho tất cả mọi thể loại lập trình viên. Mình không hiểu viết ra những bài này thì đem lại lợi ích gì cho người đọc?
Đồng ý là vì Regex có cú pháp không hề đẹp mắt, dẫn đến khó đọc và khó hiểu (nhưng không hề khó học), đa số chúng ta có xu hướng thích copy những đoạn được viết sẵn về để sử dụng. Và đa số sẽ bỏ ra hơn 10 giờ đồng hồ chỉ để tìm được một đoạn Regex nào đó được post sẵn trên mạng mà chạy gần đúng nhất đối với một cái requirement ất ơ nào đó của dự án mà chúng ta đang làm. Đó là chưa kể nếu dự án có ra những yêu cầu trên trời rơi xuống thì biết Google ở đâu cho ra đây?
Và việc này hoàn toàn không đáng nếu bạn có thể bỏ ra 30 phút để học cú pháp của Regex và tự sửa nó cho đúng chính xác với cái requirement ất ơ kia.
Nói chung là còn rất nhiều những ví dụ và những trường hợp mà chúng ta buộc phải học cách sử dụng Regex một cách linh động, và việc học để hiểu được cú pháp của nó là giải pháp duy nhất. Nếu bạn vẫn còn đang đi tìm một đoạn Regex ăn sẵn nào đó trên mạng, thì thôi hãy dừng lại và bắt đầu học Regex ngay và luôn đi.
Và đôi lời cho bạn nào vẫn có ý định viết về Regex: Thay vì copy dán các đoạn Regex vào bài viết của bạn một cách vô trách nhiệm, hãy bớt chút thời gian tìm hiểu cú pháp của nó và giải thích cặn kẽ từng phần của mỗi biểu thức. Việc bạn muốn chia sẻ kiến thức thì rất đáng hoan nghênh, nhưng xin đừng chia sẻ sự lười biếng và ngu dốt.
IT Helpdesk Cần Học Gì Để Làm Tốt Chuyên Môn Của Mình?
IT Helpdesk là một trong những vị trí quan trọng liên quan đến các công việc của ngành công nghệ thông tin. Vị trí này phụ trách hỗ trợ và kết nối thông tin giữa người dùng với bên cung cấp dịch vụ công nghệ, nhằm đảm bảo mọi hoạt động được diễn ra thông suốt. Vậy IT Helpdesk cần học gì để trở thành một nhân viên có chuyên môn tốt và đảm bảo hoàn thành các công việc của mình?
IT Helpdesk Cần Học Gì Để Làm Tốt Chuyên Môn Của Mình?
1. Tổng quan về vị trí IT Helpdesk
IT Helpdesk là nhân viên làm việc tại bộ phận hỗ trợ các dịch vụ chăm sóc khách hàng ngành công nghệ thông tin. Các IT Helpdesk chính là người có vai trò kết nối người dùng dịch vụ với bên cung ứng dịch vụ để đảm bảo các hoạt động sử dụng được thông suốt.
Công việc chính của IT Helpdesk là tiếp nhận các thông tin về khó khăn hoặc các yêu cầu hỗ trợ của người dùng và tư vấn thông tin, hướng dẫn cách khắc phục cho họ. Các vấn đề người sử dụng thường gặp phải như việc cài đặt, sử dụng máy tính, app, hỗ trợ xử lý các sự cố liên quan đến phần mềm, phần cứng,… IT Helpdesk sẽ tiếp nhận thông tin và hỗ trợ trong khả năng của mình, vấn đề khó hơn sẽ được chuyển đến bộ phận kỹ thuật chuyên môn để xử lý.
Bên cạnh đó, còn có các công việc nội bộ dành cho IT Helpdesk liên quan đến việc giải quyết các vấn đề kỹ thuật trong công ty. Vị trí này chủ yếu hoạt động ở các công ty chuyên về công nghệ thông tin nhằm giúp xử lý các tình huống như đường truyền internet, phần cứng máy tính,…
Vị trí IT Helpdesk yêu cầu người làm việc cần được trang bị những kiến thức chuyên môn đầy đủ cũng như phải rèn luyện cho bản thân những kỹ năng mềm thích hợp.
2.1. Yêu cầu về chuyên môn
Vì đây là công việc sẽ hỗ trợ khá nhiều các vấn đề liên quan đến CNTT nên việc người làm việc ở vị trí cần có những kiến thức từ cơ bản đến chuyên sâu về công nghệ máy tính, phần cứng, phần mềm,… là cần thiết.
Am hiểu quy trình làm việc gồm tiếp nhận, hỗ trợ xử lý sự cố và cung ứng dịch vụ IT cho người dùng.
Nắm vững các thông tin liên quan đến việc vận hành hệ thống của công ty. Đây là một trong những yếu tố quan trọng để các nhân viên IT Helpdesk có thể hỗ trợ, tư vấn cũng như giải đáp thắc mắc cho người dùng một cách nhanh nhất, phù hợp nhất.
Cũng như các vị trí khác trong ngành CNTT, IT Helpdesk cũng nên có khả năng đọc hiểu tiếng Anh để dễ dàng hơn cho bản thân trong quá trình đọc và xử lý tài liệu nước ngoài.
Đây đều là những thông tin cần thiết cho việc tiếp nhận và đón nhận nhanh nhất các thông tin công nghệ mới nhất.
2.2. Các yêu cầu về kỹ năng mềm
Kỹ năng giao tiếp: Đây có thể xem là kỹ năng cực kỳ quan trọng ở công việc này vì IT Helpdesk sẽ phải giao tiếp một cách thường xuyên và liên tục với nhiều khách hàng để tiếp nhận phản ánh của họ. Biết cách nói chuyện rõ ràng và giải thích dễ hiểu sẽ giúp công việc của bạn trở nên trôi chảy hơn rất nhiều.
Khả năng tiếp nhận và xử lý sự cố: Do vị trí công việc, các IT Helpdesk bắt buộc phải có khả năng phát hiện ra vấn đề cũng như nhanh chóng đưa ra hướng giải quyết theo mô tả của khách hàng. Có những người dùng lớn tuổi hay quá nhỏ tuổi và họ không thể diễn tả chính xác vấn đề mà họ đang gặp phải thì IT Helpdesk cần thể hiện rõ hơn nữa vai trò của mình trong vấn đề này.
Khả năng giao tiếp ngoại ngữ: Như đã đề cập ở bên trên, kỹ năng đọc hiểu cũng như giao tiếp bằng ngoại ngữ khá quan trọng với các IT Helpdesk. Do đó, ngay từ bây giờ, nếu đang nuôi dưỡng mong muốn trở thành một IT Helpdesk, bạn hãy chú trọng dành thời gian cho việc cải thiện kỹ năng ngoại ngữ của mình.
Kỹ năng làm việc nhóm: Vì công việc của IT Helpdesk cần có sự phối hợp giữa nhiều phòng ban liên quan nên không có kỹ năng teamwork sẽ rất khó để bạn làm việc được với nhiều người. Khả năng lắng nghe và hợp tác trong quá trình làm việc sẽ giúp công việc diễn ra suôn sẻ hơn. Và hãy dám chịu trách nhiệm cho những lỗi sai của mình nếu có vấn đề xảy ra.
Kỹ năng chăm sóc khách hàng: Giữ thái độ tích cực, thể hiện sự thông cảm và quan tâm đến khách hàng chắc chắn sẽ giúp bạn dễ dàng hơn trong việc xử lý vấn đề. Nhất là trong trường hợp tư vấn cho những khách hàng còn nhỏ tuổi hay những người lớn tuổi không hiểu nhiều về công nghệ, sự giúp đỡ của bạn là rất cần thiết với họ.
Để trở thành một IT Helpdesk, việc trau dồi và học hỏi thêm nhiều kỹ năng liên quan để làm tốt công việc hơn là rất cần thiết. Hy vọng các thông tin được cung cấp trong bài đã phần nào giúp người đọc có thêm định hướng về việc nên học gì, lựa chọn hướng đi nghề nghiệp nào là phù hợp với mình. Đón đọc thêm nhiều bài viết hấp dẫn trong lĩnh vực IT và nhân sự tại TopDev nhé!
Chuyện là cái ông owner của Kieblog nhận được yêu cầu build UI Library cho một dự án lớn. Build thì được nhưng gặp phải một số điểm khó nhắn.
Khó nhằn thì cũng xử xong, nhưng muốn viết ra đây cho anh em nào tương lai muốn build UI Library có vài điểm để lưu ý.
Tránh đi vào vết xe hơi sâu chứ méo đổ nha =)))
Rồi bắt đầu, bài viết này viết theo ý kiến cá nhân nên có cái nào chưa đủ nhờ anh em comment thêm nha.
1. Có depend trên UI Library nào khác không?
Hiện tại có rất nhiều UI Library, với Vuejs ta có Vuetify, Bootstrap Vue và Element UI. Nói chung là rất rất nhiều UI Library khác, nhưng trước khi build UI Lib ta cần ra quyết định.
Câu hỏi như cái title, có cần dựa vào một UI Library nào khác không?. Dựa vào thì có cái lợi là thời gian implement sẽ bớt đi, còn bỏ qua tất cả để tự viết mới thì cần rất nhiều thời gian.
Đơn cử như vấn đề về CSS, nếu ta chọn Buefy thì đã có sẵn nền là Bulma Css. Còn nếu không thì phải tự build bộ variable scss và sass cho riêng mình.
Có hai yếu tố chính để anh em cân nhắc:
Thứ nhất là quỹ thời gian có hay không?
Thứ hai là độ custom của UI Library có yêu cầu nhiều không?
Ở nội dung bài viết và theo quan điểm cá nhân thì tôi không đánh giá cái nào ngon cái nào dở. Tất cả phụ thuộc vào requirement của anh em lúc build UI Library.
Đã depend thì hơi khó custom, nên tuỳ vào tính chất UI Library anh em muốn build mà cân nhắc nha
2. Tổ chức source code như thế nào?
Bản thân build UI Library không hề khó. Tại sao vậy?, vì ta có nhiều nguồn để tham khảo. Hầu hết đều có source sẵn trên github cho anh em tham khảo. Tuy nhiên anh em cần tìm đúng cái cần cho UI Library của riêng mình.
Ông Buefy thì viết kiểu Vue components
Ông Vuetify thì Typescript thuần + mixins
Ông Bootstrap Vue thì viết js thuần
Tất nhiên là đều render ra component với props, directives và một số thứ khác nữa, nhưng khi tiến hành quyết định build UI Library anh em nên tham khảo ý kiến của từng thành viên trong team.
Một số bạn có thể thoải mái với Typescript, nhưng một số thì lại thích Javascript thuần. Tuỳ vào tình hình cụ thể trong team mà ta phải ra quyết định cho phù hợp.
3. Visualization sao cho tốt?
Cái UI Library build ra bản thân dành cho developer xài. Không chỉ mỗi người implement component đó xài mà các developer khác. Chính vì vậy vấn đề Trực Quan quá trở nên cực kì quan trọng.
Cái này tuỳ theo nhu cầu, thời gian và cách mà team dev muốn làm. Anh em có thể có vài lựa chọn.
Có mấy cái có thể suggest anh em:
Thứ nhất là dùng StoryBook (cách này ít tốn effort và dễ làm) vì Storybook hỗ trợ visualization.
Thứ hai là tự viết và deploy docs như cách mà các UI Library khác đang làm (cách này tốn effort)
Tất nhiên là cái nào cũng có điểm mạnh riêng của nó. Nếu nhanh thì khó custom và nếu dễ custom thì lại tốn effort.
Tự viết docs theo kiểu Vuetify
Hoặc sử dụng Storybook
4. Tổ chức component như thế nào?
Đây cũng là một vấn đề cần lưu ý. Nếu khách hàng hoặc project đã quyết chí build UI Library riêng, chứng tỏ style component và component business có gì đó khác biệt so với các UI Library đang có trên thị trường.
Các component phổ biến như Dropdown, Input, Radio, Checkbox anh em có thể gom vào 1 phần.
Những component đặc biệt phụ thuộc vào business và đặc thù dự án thì gom vào một chỗ. Các component phổ biến mình có thể tham khảo props và cách viết.
Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh
Trait trong RAML được sử dụng để định nghĩa những thành phần giống nhau trong các request URI khác nhau để có thể sử dụng lại được. Nó giống như common class, method trong Java đó các bạn!
Trong 2 request này, request parameter “name” được định nghĩa giống nhau. Do đó, chúng ta có thể sử dụng Trait để định nghĩa cho request parameter này và sử dụng lại trong 2 request. Khi thay đổi định nghĩa cho request parameter “name”, chúng ta không cần phải sửa nhiều chỗ nữa.
Chúng ta định nghĩa Trait cho request parameter “name” với tên gọi là “hasNameParam” như sau:
LÀM THẾ NÀO ĐỂ HỢP TÁC TRONG CÔNG VIỆC VỚI NGƯỜI BẠN KHÔNG THÍCH?
Bài viết được sự cho phép của tác giả Ánh Nguyệt
1. Tự chiêm nghiệm lại nguyên nhân
Việc bạn không thích người đó, và cách bạn đã phản ứng với các tình huống gây căng thẳng giữa hai người.
Bạn phải hiểu rằng: Bạn sẽ không hòa đồng với tất cả mọi người. Hãy nhìn nhận một cách trung thực điều gì đang gây ra căng thẳng và vai trò của bạn trong việc tạo ra nó. Có thể phản ứng của bạn với tình huống là cốt lõi của vấn đề (và bạn không thể kiểm soát bất cứ điều gì khác ngoài phản ứng của mình).
2. Tìm nhiều cách để hiểu quan điểm của người đó
Hãy dành thời gian để suy nghĩ về quan điểm của người kia, đặc biệt nếu người đó là yếu tố cần thiết cho sự thành công của bạn
– Tại sao người này lại phản ứng theo cách đó?
– Điều gì là động lực của họ?
– Người đó đang nhìn mình như thế nào?
– Điều gì họ muốn & cần ở mình?
3. Đứng ở vị trí là người giải quyết vấn đề hơn là người đánh giá hay người cạnh tranh
Để làm việc cùng nhau tốt hơn, điều quan trọng là phải chuyển từ quan điểm cạnh tranh sang quan điểm hợp tác . Một chiến thuật là “đưa ra” vấn đề cho người khác. Thay vì cố gắng làm việc thông qua hoặc xung quanh người khác, hãy thu hút họ trực tiếp.
Có thể mời người đó ăn trưa hoặc cafe rồi mở lòng với họ: mình không cảm thấy chúng ta đang làm việc với nhau tốt như chúng ta có thể. Bạn nghĩ sao về điều này? Bạn có ý tưởng gì để chúng ta có thể làm việc tốt hơn không?
4. Hỏi nhiều hơn
Trong những tình huống căng thẳng, nhiều người trong chúng ta cố gắng “nói” theo cách của mình điều này thường làm cho tình hình trở nên tồi tệ hơn. Thay vào đó, hãy thử đặt câu hỏi mở nhằm tạo ra cuộc trò chuyện.
Sử dụng những câu hỏi với mục đích xây dựng và thật lòng kiên nhẫn lắng nghe câu trả lời
5. Nâng cao nhận thức về bản thân
Trong những mối quan hệ với những loại tính cách khác nhau
Thật dễ dàng làm cho xung đột trở thành “phản ứng hóa học kém”Với một người khác nhưng mọi người đều có phong cách khác nhau và thường xuyên nhận thức được những khác biệt đó có thể giúp ích
Ví dụ bạn là người mới vào, người đó đã làm việc ở tổ chức lâu hơn bạn:Mình cảm thấy đã bắt đầu hiểu về tổ chức, tuy nhiên mình cần thêm sự trợ giúp của bạn: Điều gì mình nên làm nhiều hơn hoặc ít đi? Mình đã bỏ qua điều gì hay mình nên kết nối với ai? Bạn đã từng ước ai đó nói cho bạn điều gì khi bạn bắt đầu công việc ở đây?
Tiếp tục với sê ri Algorithm in Frontend, kì này nói về một loại cấu trúc dữ liệu được dùng thường xuyên trên frontend, đó là Kiểu dữ liệu dạng cây (tree).
Nhắc đến cây thì hẳn chúng ta nghĩ ngay đến DOM và các thao tác trên đó, ví dụ như tìm kiếm một element trên DOM, thêm/xóa element,… tuy nhiên các thao tác này chúng ta thường sử dụng DOM API có sẵn của trình duyệt và bài này cũng không có ý định nói đến phần đó
Thực ra đây là một câu hỏi phỏng vấn cho vị trí Frontend Engineer tại công ty G cũng khá là có tiếng tăm (vì họ bắt mình ký NDA không được tiết lộ nội dung buôi phỏng vấn, nhưng mà để viết bài này thì phải lộ đề rồi, nên thôi mình không tiết lộ tên công ty đó vậy hình như đây là lần thứ 2 mình nhắc đến NDA rồi, mấy cái công ty cứ thích dùng cái này để bịt miệng người ta quài).
Câu hỏi này gây ấn tượng mạnh với mình vì lúc đó là lần đầu tiên mình gặp một câu hỏi phỏng vấn núp bóng dưới dạng một ứng dụng thực tiễn rõ ràng như thế này.
Mặc dù đề bài yêu cầu xây dựng một component in ra một menu đa cấp, nhưng bản chất bài toán vẫn là xây dựng thuật toán chuyển cục JSON kia về dạng cây.
Nói thì dễ, đến lúc vào phỏng vấn thì mặt mình tái mét, dành hết 40 phút để implement cái cơ chế tạo và mount một custom component theo kiểu Angular Directive, trong khi không đả động gì đến cái đề bài, kết quả là fail dập mặt
Nhìn vào dữ liệu input (tạm gọi là II) ta có thể thấy đây là một mảng “phẳng” (flat array), và mỗi phần tử của mảng này có thể có hoặc không có mối liên hệ nào với nhau. Nếu một phần tử IjIj là “con” của IiIi thì tên Ij.nameIj.name sẽ có mặt trong mảng Ii.itemsIi.items.
Nhiệm vụ của chúng ta sẽ biến mảng phẳng này thành một cây dữ liệu, dựa trên mối quan hệ vừa đề cập.
3. Cấu trúc dữ liệu
OK, vậy thì đầu tiên ta phải nghĩ về cấu trúc dữ liệu của một Node trên cây, sẽ có dạng như sau:
pseudo code
struct Node {
name: String,
items: Array<Node>
}
Với cấu trúc trên, một Node cha sẽ có các Node con nằm trong trường items, và với một Node lá, không có Node con nào, thì trường items chỉ là một mảng rỗng.
Như vậy, nếu ThinkpadThinkpad là một Node lá, và cũng là con của LaptopLaptop thì cây của chúng ta sẽ có dạng:
Ý tưởng của thuật toán sẽ gồm 2 công đoạn, giống như chơi xếp hình vậy:
Màn dạo đầu: để thống nhất về kiểu dữ liệu, ta đưa mảng input II thành một mảng có mỗi phần tử là một cây riêng biệt, có gốc (root) chính là phần tử IiIi đang xét, và các node lá là các phần tử của Ii.itemsIi.items.
Xếp hình: gọi là lắp ráp thì đúng hơn, ở bước này ta sẽ ráp nối các cây lại với nhau theo kiểu, cây nào con cây nào thì cắm vào cây đó. Kết thúc việc lắp ráp thì chúng ta sẽ có một cây hoàn chỉnh như đề bài yêu cầu.
Thuật toán đầy đủ được mô tả như sau:
Bước 1: Duyệt qua tất cả các phần tử của mảng II
Bước 2: Với mỗi phần tử IiIi (còn gọi là một cây IiIi), duyệt qua tất cả các phần tử của mảng Ii.itemsIi.items (các cây con của IiIi).
Bước 3: Gọi nodenode là phần tử Ii.itemsjIi.itemsj đang xét. Tìm trong mảng II một phần tử ItIt sao cho It.name==nodeIt.name==node.
Bước 3a: Nếu tìm thấy một phần tử ItIt thỏa điều kiện trên thì thay thế nodenode thành ItIt. Đánh dấu ItIt thành một cây cần xóa.
Bước 3b: Nếu không thì biến nodenode thành một lá của cây IiIi
Bước 4: Xóa tất cả các cây IiIi đã được đánh dấu trong mảng II. Mảng thu được chính là mảng kết quả.
Khác với các ngôn ngữ lập trình khác, vì JavaScript là dynamic typing, ta có thể dễ dàng thay đổi giữa nhiều kiểu dữ liệu cho một biến, chính vì thế, rất có khả năng bạn sẽ bị confuse khi đọc đến bước 3 và 3a
Ở bước 3, một giá trị node=Ii.itemsjnode=Ii.itemsj sẽ mang kiểu string, đến bước 3a ta lại gán nodenode thành một giá trị ItIt (là một cây).
Nếu ngôn ngữ mà các bạn sử dụng không phải JavaScript mà là một ngôn ngữ strong typing nào đó ví dụ như Go hay Rust hay C/C++, thì thuật toán ở trên cần phải được sửa lại.
Còn bây giờ thì implement thôi:
const buildTree = (nodes) => {
for (let i = 0; i < nodes.length; i++) {
for (let j = 0; j < nodes[i].items.length; j++) {
let node = nodes[i].items[j];
let found = nodes.find(n => n.name == node);
if (found) {
nodes[i].items[j] = Object.assign({}, found);
found.removed = true;
} else {
nodes[i].items[j] = {
name: node,
items: []
};
}
}
}
return nodes.reduce((arr, item) => {
if (!item.removed) {
arr.push(item);
}
return arr;
}, []);
}
Chúng ta chạy thử và in kết quả dưới dạng một chuỗi JSON để thấy rõ cấu trúc dạng cây:
let list = require('./menu.json');
let result = buildTree(list);
console.log(JSON.stringify(result, null, ' '));
Nội dung JSON của kết quả thu được
5. Phức tạp quá, làm vậy chi cho cực?
Đọc đến đây hẳn có bạn sẽ đặt ra câu hỏi: Tại sao ngay từ ban đầu lại dùng kiểu dữ liệu dạng như thế này trên frontend? Chẳng phải đây là việc của backend hay sao? Trên thực tế có ai làm vậy không?
Câu trả lời nằm ở tính tiện lợi khi cần mở rộng menu dạng cây như thế này, ví dụ, với mảng II đã cho ở trên, khi chúng ta cần mở rộng, ví dụ thêm vào một loại laptop khác bên cạnh dòng Thinkpad, hoặc thêm vào một hãng xe ô tô mới, ta có thể thêm trực tiếp một hoặc nhiều item mới vào mảng II, ví dụ:
Nếu lưu dữ liệu trực tiếp dạng cây thì việc cả việc lưu trữ lẫn việc thêm/bớt này quả thực là một vấn đề không đơn giản. Hay nói cách khác thì giải pháp đó không scalable.
6. Bài viết này có giúp tôi được tăng lương không?
Lưu ý: Bản quyền câu nói trên thuộc về blog Quần Cam, để đưa câu nói này vào bài viết, mình đã phải trả một khoản “tiền” khá lớn, mong các bạn đừng bắt chước.
Chân thành mà nói thì việc tăng lương hay không phụ thuộc vào… sếp của bạn
Tuy nhiên, là một frontend developer, bạn cũng là một phần rất quan trọng trong team, nếu phải lựa chọn giữa một giải pháp tiện lợi cho cá nhân mình nhưng sẽ tạo ra gánh nặng cho phần còn lại của team, và một giải pháp tạo ra vài thách thức nhỏ cho bản thân nhưng đem lại hiệu quả cho toàn bộ hệ thống, thì có lẽ hy sinh một chút thời gian và sự thoải mái của bản thân sẽ tốt hơn so với việc ngồi câu nệ xem việc này là của ai và ai phải làm gì.
Rất cảm ơn các bạn đã đọc đến tận dòng này, hy vọng các bạn thích sê ri này, đừng ngại để lại comment nếu các bạn có bất kỳ góp ý hay gợi ý gì. Hẹn gặp lại các bạn trong các bài viết sắp tới.
Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh
Khi định nghĩa API specs với RAML, việc chúng ta định nghĩa tất cả các thông tin chỉ trong một tập tin RAML sẽ gây khó khăn trong việc maintain và sẽ có những phần, những data types được sử dụng đi, sử dụng lại trong nhiều request URI khác nhau, nếu định nghĩa như vậy thì không phải là best practice. Việc chia nhỏ định nghĩa những phần được sử dụng đi sử dụng lại này thành những fragments trong những tập tin RAML khác, sẽ giúp chúng ta quản lý cách định nghĩa API specs tốt hơn, tránh lặp đi lại những thứ không cần thiết. Trong bài viết này, mình sẽ hướng dẫn các bạn cách định nghĩa API specs với các fragments trong RAML các bạn nhé!
Như các bạn thấy là, tất cả các thông tin về Student object, các example đều được khai báo trong cùng một tập tin RAML. Giả sử sau này ứng dụng của mình được mở rộng để thêm các request URI thêm xoá sửa lớp học, lấy thông tin student của một lớp học:
thì như các bạn thấy: nội dung của tập tin RAML này sẽ phình ra nhiều hơn gây khó khăn trong việc chỉnh sửa, các example không được reusable, … Sử dụng các fragments sẽ giúp chúng ta giải quyết những bất cập này.
Để sử dụng các fragments, điều các bạn cần phải làm đó là chia nhỏ tập tin RAML của chúng ta (mình sẽ gọi tập tin RAML này là tập tin root RAML các bạn nhé!) bằng cách định nghĩa fragment cho các data types, các thông tin chung giữa các request URI sử dụng các tập tin RAML khác và khai báo để sử dụng những tập tin RAML này trong tập tin root RAML sử dụng từ khoá “!include”.
Trong ví dụ của mình ở trên thì việc đầu tiên chúng ta có thể làm là định nghĩa fragment cho các data type object trong các tập tin RAML khác.
Mình sẽ tạo mới 2 tập tin student.raml và class.raml nằm trong thư mục data-types/objects:
để định nghĩa data type cho các object Student, Class.
Để định nghĩa fragment cho các data type, chúng ta cần khai báo dòng “#%RAML 1.0 DataType” ở đầu của mỗi tập tin .raml. Ví dụ nội dung của tập tin student.raml sẽ như sau:
Tổng Hợp Những Câu Hỏi Phỏng Vấn Front End Thường Xuyên Xuất Hiện Trong Các Buổi Phỏng Vấn
Front-end và Back-end là một trong những vị trí quan trọng trong các dự án công nghệ thông tin, triển khai phần mềm. Để vượt qua vòng phỏng vấn, ứng viên nên có sự chuẩn bị kỹ càng ngay từ việc trang bị kiến thức, kỹ năng trả lời cũng như tham khảo một số mẫu câu phỏng vấn thường xuyên xuất hiện để làm quen trước. Bài viết dưới đây sẽ tổng hợp một số câu hỏi phỏng vấn Front End Developer mang tính chuyên môn được hỏi nhiều nhất.
Tổng Hợp Những Câu Hỏi Phỏng Vấn Front End Thường Xuyên Xuất Hiện Trong Các Buổi Phỏng Vấn
API Gateway, một thanh niên điều đào chính hiệu trong làng Micro Services và Architecture. Tui không hề nói điêu, đúng nghĩa điều đào. Không tin anh em cứ đọc bài thử là sẽ biết.
Như kiểu tú ông, nhưng có lợi cũng đi kèm hại và một số điểm ta cần consideration nha.
1. API Gateway Movitation
Nói tới Movitation thì nói với ví dụ là dễ để mà hiểu nhất. Đây, giả sử ta có requirement build Video Streaming System + Sharing System.
Những tính năng chính mà ta cần implement bao gồm:
Upload Videos
Watch Videos
Comment on Videos
Từ những tính năng chính nay, tiến hành bẻ nhỏ ta sẽ có:
Một đống các feature nho nhỏ ta cần quan tâm
Một list các features cần implement, nhưng do ta đã biết về Micro Services và build Scalable System nên ta sẽ tách các nhóm feature này thành các services. Một điểm yếu nữa với kiến trúc ở hình trên, ta sẽ gặp rất nhiều khó khăn khi maintain.
Làm về lâu về dài rất dễ dẫn tới out of control source code.
Anh em nào muốn tìm hiểu về Scalable có thể đọc chuỗi bài này nha:
Chính vì vậy, ta sẽ split thành các service nhỏ như sau:
Với nhóm tính năng trên, ta split thành 4 nhóm services chính là Frontend Service, Users Service, Video Service và Comments Services.
Vấn đề là mỗi services này cần phải implement Authentication, Authorization và xử lí các Business Logic riêng. Việc xử lí riêng rẽ ở từng Service không những gây tốn kém về effort mà còn gây ra vấn đề về Performance.
Đây rồi, lúc này API Gateway solutions ra đời (anh em đọc tiếp phần 2)
Thay vì để user gọi từng service riêng rẽ, API Gateway sẽ đứng ra “điều đào” là API Management Services, đứng giữa End User và các Services
Thanh niên “Điều đào” API Gateway
Tính search hình “Điều đào” gửi cho anh em có khí thế đọc bài mà nó ra hình quả điều. Clm. Thôi tới định nghĩa API Gateway
The API Gateway follows a software architecture pattern called API Composition
API Gateway được sinh ra dựa trên một pattern của kiến trúc phần mềm là Composition
Ở pattern này, ta sẽ gom toàn bộ các API ở phía services thành 1 API Services, end user chỉ cần giao tiếp với một API services duy nhất.
Gom lại hết có lợi nha, chính vì có lợi nên mới để nó thành một pattern. Chi tiết anh em mình tiếp tục tới mục số 3
3. Benefit và Quality Attributes
3.1 Seamless internal modification/refactoring
Cái này nếu nói đúng thì là điểm mạnh của micro services. Tuy nhiên nhờ có anh API Gateway đừng mũi chịu sào nên ta có thể sửa đổi (modification) hoặc sửa code (refactoring) một cách dễ dàng hơn.
Ví dụ, nếu hệ thống Video Streaming của ta chia thành 2 services cho 2 loại Mobile và Desktop. Ta có thể dễ dàng tạo ra 2 services để handle từng loại devices.
Tách riêng thành 2 services handle cho Mobile và Desktop
Một ví dụ khác cũng khá hợp lí là xử lí chất lượng cho từng loại device (high quality và low quality)
Tách thành 2 services cho High Resolution và Low Resolution
3.2 Consolidating all security, authorization, authentication
Cái này thì là benefits nhìn thấy rõ của API Gateway. Gom toàn bộ phần Authorization, Authentication về một mối. Thay vì không có API Gateway, từng services phải handle Autho, Authen riêng nó. Các vấn đề về Security cũng handle riêng.
Giờ tất cả trong một mối, handle ở API Gateway. Nếu không có vấn đề gì thì request sẽ được chuyển tiếp tới các Services con.
Cũng với Authorization, ta có thể phân quyền cho từng user, mỗi loại user sẽ được access tới một số lượng nhất định các services.
Ta cũng có thể implement rate-limiting nhằm phòng chống các cuộc tấn công DDos. Lợi nhiều vô kể.
3.3 Request routing
Request routing cũng là một điểm cộng lớn của API Gateway. Như đã nói ở trên, thay vì từng services phải thực hiện Authen Autho thì giờ chỉ API Gateway làm việc đó. Giảm tải, tăng performance.
Thứ hai nữa là mỗi user bây giờ chỉ cần gửi một request duy nhất tới API Gateway, nhân về một response duy nhất. Còn việc gọi những services con nào thì để API Gateway lo
Như ví dụ ở trên đây, trường hợp user muốn xem một video thì sẽ cần request tới 3 Services. Nếu không có Gateway thì gọi 3 lần nha.
Đầu tiên là Frontend Services để thấy layout trang xem video
Video service để thấy video cần xem
Comments Service để load ra toàn bộ comment của video đó
3.4 Static content và response cache
Trường hợp ta có sử dụng cache để cache lại content ở API Gateway, ta có thể trả về nội dung nhanh chóng hơn cho người dùng.
Điều này cũng làm tăng performance thấy rõ cho application
3.5 Protocols Translation
Với API Gateway, giờ đây sự khác biệt giữa các Service cũng có thể đem thành một thể thống nhất.
Gateway luôn trả về JSON format cho người dùng, nhưng các services có thể được define ở các kiểu khác nhau. Frontend Service có thể là gRPC và PROTO BUFFER.
Comments Service có thể là HTTP 1.0 REST API và XML. Nhưng với API Gateway thì tất cả được gom về một mối, end user hoặc phía Frontend client chỉ cần làm việc với REST API và JSON
4. Consideration
Tuy là API Gateway tiện lợi như vậy, trung gian đầu mối của tất cả các server trong hệ thống. Nhưng nó cũng tồn tại những điểm yếu chết người.
Chính vì là trung gian nên có một số thứ ta cần cẩn trọng khi áp dựng API Gateway.
4.1 Bussiness Logic
Đầu tiên là cách implement
API Gateway should not contain any business logic
API Gateway không nên bao gồm bất cứ logic nào về business
Do mục đích chính của Gateway sinh ra chỉ bao gồm 2 thứ sau:
Thứ nhất là API Composition
Thứ hai là Routing request tới các services khác
Nếu chính trong bản thân Gateway có business logic, nó sẽ làm mất đi tính năng điều phối. Nếu lạm dụng đưa logic hoặc business vào đây, ta sẽ trượt xa khỏi micro services architecture. Gom toàn bộ lại vào API Gateway, biến nó thành một bộ code khổng lồ.
Thứ hai:
API Gateway may become a Single Point of Failure
API Gateway có thể trở thành điểm chết duy nhất
Chính vì API Gateway là thanh niên điều đào cho các Service, nên nếu thằng cha này mà ngủm thì cả đường dây chết. Mà nguyên nhân nó ngủm thì đôi khi tới từ những lí do ngớ ngẩn nhất.
Cũng không trách được, vì nếu có tác động của Human thì make a mistake là chuyện bình thường. Nhưng anh em nhớ là nếu nó ngủm thì tất cả đều ngủm.
Cách đây mấy hôm mình có share cái screenshot trên Facebook, khoe linh tinh vụ mình đang viết lại cái CHIP-8 emulator bằng Rust.
Mãi cho đến hôm nay thì vẫn viết chưa xong, chán quá nên ngồi viết mấy dòng linh tinh về quá trình này.
Phàm làm bất cứ chuyện gì, đều là cả một quá trình viết Emulator hay code bất cứ thứ gì cũng vậy. Và trong quá trình đó thì người viết luôn phải trải qua vô số những quyết định về mặt kĩ thuật, ví dụ như nên dùng if..else hay pattern matching, viết test hay ko test , chia module hay viết 100 ngàn dòng trong 1 file,…
Một trong những quyết định đau đầu nhất của mình đó là chọn cấu trúc dữ liệu để biểu diễn ma trận hiển thị (display matrix) – tức là cái màn hình cho emulator.
Như đã đề cập ở bài Tự viết Emulator, màn hình của CHIP-8 là một ma trận 64×3264×32. Nên cách biểu diễn thường gặp nhất đó là một mảng số nguyên (integer) hai chiều.
Tuy nhiên, việc dùng số nguyên rất là tốn kém, trong Rust, kiểu số nguyên nhỏ nhất là i8, chiếm 1 byte (8 bits), và trong JavaScript thì còn tệ hơn nữa khi một giá trị kiểu Number mặc định chiếm bà nó 8 bytes (64 bits). Nhân lên, để khai báo một mảng hai chiều cho ma trận hiển thị của CHIP-8 ta cần 64×32×8=16,38464×32×8=16,384 bits trong bộ nhớ nếu dùng Rust (tương đương với 2 KB), và 131,072 bits tương đương với hơn 16 KB nếu xài JavaScript.
Con số có vẻ không lớn nếu chạy trên máy tính, nhưng nếu bạn đang implement cho các nền tảng èo ọp hơn như là Arduino thì đây là cả một vấn đề cực kì lớn. Đơn cử, dòng Arduino phổ biến nhất là UNO R3, sử dụng vi xử lý ATmega328P và bộ nhớ SRAM (static random access memory) của nó chỉ có đúng 2 KB.
Quèo, trên thực tế thì bạn vẫn không thể chạy trực tiếp CHIP-8 emulator trên Arduino được vì tính riêng dung lượng bộ chớ chính của nó cũng đã ngốn mất 4096 bytes rồi trong trường hợp này chúng ta cần dùng thêm một con chip khác để làm external RAM, tuy nhiên, vấn đề này nằm ngoài phạm vi bài viết, có thể mình sẽ nói tới trong một bài khác.
Dễ nhận thấy, đối với CHIP-8, màn hình hiển thị chỉ gồm 2 màu trắng đen, mỗi pixel chỉ có 2 trạng thái đó là on hoặc off, tương đương với chỉ có 2 giá trị 0 hoặc 1, vậy thì việc dùng số nguyên để biểu diễn là không cần thiết.
Kiểu dữ liệu nào chỉ có 2 trạng thái nhỉ? bool! Tuy nhiên ngay cả kiểu bool trong Rust cũng chiếm tới 1 byte (8 bits). Còn trong JavaScript thì mình chịu, không có tài liệu nào nói cụ thể, các đoạn code tính size của 1 type thì ghi nó tận 4 bytes . Mình không tin có bằng chứng thì mới tin.
Bản thân một bit có thể chứa được 2 giá trị (0 và 1), như vậy là đã thỏa mãn cho yêu cầu của một ma trận hiển thị.
Vậy thì có cách nào chỉ dùng đúng 64×32=204864×32=2048 bits trong bộ nhớ không? Có!
Rust có hỗ trợ kiểu u64 (64-bit unsigned integer), là một kiểu số nguyên không đấu, khi khai báo một biến kiểu này tất nhiên nó sẽ chiếm 64 bits trong bộ nhớ.
Và nếu chúng ta khai báo một mảng gồm 32 số nguyên 64 bit[u64; 32] thì sao? Chúng ta sẽ có 2048 bits! Đủ để chứa toàn bộ ma trận hiển thị.
Đến đây thì vấn đề sẽ là: Làm sao để đọc/ghi vào một bit bất kì của một số u64.
Lưu ý: về thứ tự cao thấp của các bit, ở đây chúng ta theo quy ước các số đều là big endian, các bit được sắp xếp theo thứ tự từ bit cao đến bit thấp. Ví dụ trong hình sau là một số u16 gồm có 2 bytes:
Từ trái qua phải, bit đầu tiên gọi là bit cao nhất (highest bit), bit cuối cùng gọi là bit thấp nhất (lowest bit).
Vì thế, khi nói một bit thứ i, chúng ta có thể hiểu là bit thứ i tính từ bit thấp nhất (bên phải) qua .
2. Đọc một bit
Để đọc một bit thứ i của một số n, ta dịch phải số n một khoảng bằng i - 1 bits, và thực hiện phép AND kết quả thu được với 1:
(n >> (i - 1)) & 1(n >> (i - 1)) & 1
Ví dụ: Để đọc bit thứ 6 của số 0xA1, ta sử dụng công thức trên qua từng bước như sau:
Số 0xA1 biểu diễn dưới dạng nhị phân là 1010 0001. Để lấy được bit thứ 6, ta cần dịch phải 5 bit:
1010 0001 >> 5=0000 01011010 0001 >> 5=0000 0101
Tiếp theo, ta thực hiện phép AND kết quả trên với số 1, thực chất có biểu diễn nhị phân là 0000 0001:
Để xóa một bit thứ i (đưa bit đó về giá trị ban đầu, là 0) của một số n, ta làm như sau:
n & !(1 << (i - 1))n & !(1 << (i - 1))
Ví dụ: Để chuyển giá trị 0xA9 thu được ở ví dụ trên về lại thành 0xA1, ta phải xóa bit thứ 4 cua số đó. Tương tự như ở ví dụ trước, đầu tiên ta sẽ dịch trái số 1 một khoảng 3 bit, lần này ta lấy giá trị nghịch đảo NOT của nó.
Cá nhân mình thì ko biết nữa, nhưng thấy khá là hại não tuy nhiên hiệu quả đem lại thì rất lớn, chúng ta đã tiết kiệm được một lượng lớn bộ nhớ, từ 2KB xuống còn 2048 bits.
Bây giờ thì có thể implement thành hàm hay class để dùng lại cho tiện. Ví dụ, đây là hai hàm mình viết để sử dụng trong emulator:
// Lưu ý, code này không có chính xác :vimpl Screen {
...
pubfnset_pixel(&mutself, x: usize, y: usize, on: bool) {
if on {
self.display[y] |= 1 << x;
} else {
self.display[y] &= (!(1 << x));
}
}
pubfnget_pixel(&self, x: usize, y: usize) -> u64 {
(self.display[y] >> x) & 1
}
...
}
Ngoài việc dùng cho emulator (màn hình trắng đen) ra, thì cách thể hiện ma trận dùng bit array này còn có thể được dùng cho nhiều trường hợp khác như bảng đèn điện tử (tín hiệu bật/tắt), lưu các đỉnh của một đồ thị, lưu bàn cờ hoặc các thể loại map đơn giản nếu bạn làm game, hoặc có thể cải tiến để sử dụng từng byte thay vì từng bit để lưu trữ được nhiều thông tin hơn.
Hy vọng qua bài viết này, mình đã ít nhiều chia sẽ được cho các bạn chút gì đó, mặc dù cho đến thời điểm này mình vẫn chưa biết là mình đã chia sẽ được gì
Cảm ơn các bạn đã kiên nhẫn đọc đến tận những dòng này. Nếu các bạn cảm thấy bài viết này thú vị, đừng ngại để lại comment, và nhớ subscribe vào mailing list của mình để nhận thông báo về các bài viết mới, hoặc like trang Facebook để đọc những dòng status ất ơ ngẫu nhiên của mình vào một ngày đẹp trời nào đó. Chào thân ái và quyết thắng.