Home Blog Page 60

Tối ưu ứng dụng React bằng Code-Spliting

Tối ưu ứng dụng React bằng Code-Spliting

React hiện nay là thư viện rất được ưa chuộng bởi các lập trình viên khi xây dựng những ứng dụng web dạng một trang (Single Page Application) nhờ việc dễ học, dễ viết và nhiều công cụ hỗ trợ. Tuy nhiên khi ứng dụng của bạn ngày càng trở nên lớn hơn thì các vấn đề cũng xuất hiện nhiều hơn, nhất là việc liên quan tới tối ưu hiệu năng cho ứng dụng. Trong bài viết này, mình sẽ cùng các bạn tìm hiểu về Code-Splitting – một kỹ thuật để giúp “giảm” dung lượng file bundle nhằm cải thiện thời gian load website và nâng cao hiệu năng ứng dụng của bạn.

Bundle JS Files là gì?

Trước tiên bạn cần hiểu khái niệm bundle file trong React là gì. Thông thường khi tạo ra một ứng dụng thì chúng ta sẽ viết source code của mình vào nhiều files khác nhau, trong đó có chứa nhiều các modules và thư viện bên thứ 3 (3rd-party libs). Khi tiến hành build ứng dụng của bạn, React sẽ thực hiện việc chuyển đổi rất nhiều file source code mà bạn viết trở thành 1 file lớn hơn để sử dụng nó đưa cho các trình duyệt web khi load ứng dụng. Những file đó được gọi là bundle.

Bundle JS Files là gì

Nguồn: telerik.com

Ban đầu ứng dụng  của bạn tạo ra những file bundle nhỏ, và việc trình duyệt load chúng lên không thành vấn đề; sau một thời gian phát triển, với việc import và sử dụng ngày càng nhiều các thư viện và module thì các files bundle của bạn cũng ngày càng nặng thêm. Nếu không thực hiện tối ưu, kích thước các file bundle có thể lên tới 40-50Mb là chuyện bình thường, điều đó cũng đồng nghĩa với việc ứng dụng của bạn trở nên nặng nề khi load, user sẽ cần chờ 1 khoảng thời gian khá lâu để có thể tương tác được với các phần tử trên màn hình.

Vậy cách giải quyết cho vấn đề này là gì?

Code-Splitting là gì?

Rõ ràng để load một ứng dụng hay một màn hình cụ thể, ứng dụng của bạn không cần phải “nạp” hết các module hay thư viện được import vào; vì thế để giải quyết cho vấn đề bundle file size lớn, chúng ta cần một kỹ thuật để tách nó ra thành 2 phần: phần cần thiết load để khởi động ứng dụng (hay màn hình) và phần có thể load nạp vào sau khi ứng dụng đã được chạy. Và khi cần cần thiết load để có thể khởi động ứng dụng càng nhỏ, thì thời gian tải ứng dụng của chúng ta càng nhanh hơn. React đã cung cấp cho chúng ta tính năng này và gọi nó là Code-Splitting.

Code-Splitting là gìNguồn: wiki.tino.org

Có 3 kỹ thuật xử lý trong Code-Splitting thường được sử dụng, chúng ta cùng lần lượt tìm hiểu và xem cách triển khai của chúng nhé.

Dynamic Import

Thông thường khi chúng ta cần import 1 module nào để sử dụng, câu lệnh import sẽ được thực hiện như dưới đây:

import { add } from './math';
 
console.log(add(16, 26));

Đoạn khai báo trên sẽ import module math một cách đồng bộ – tức là sẽ import vào luôn file bundle từ khởi tạo. Với Dynamic Import, chúng ta sẽ xử lý lại đoạn code trên để chỉ import khi ứng dụng cần gọi đến phương thức add của module math. Code sẽ được viết lại như sau:

import("./math").then(math => {
  console.log(math.add(16, 26));
});

Phương thức dynamic import giúp việc import module, file một cách bất đồng bộ bằng việc trả về 1 Promise. Nó hoạt động được cả ở server-side và client-side giúp bạn có thể sử dụng trong các trường hợp load file, assets hay những module, 3rd-party libs không cần thiết cho việc hiển thị ứng dụng, màn hình lần đầu tiên.

Sử dụng React.lazy và Suspense

Phương thức React.lazy giúp bạn tạo ra 1 component ở dạng lazy-loading, nghĩa là sẽ chỉ tạo ra component đó khi nó thực sự được gọi đến và cần hiển thị ra. Hãy xem ví dụ dưới đây:

import React, { useState } from 'react';
import ProjectIntro from './projectIntro';
import ProjectDetails from './projectDetails';
 
export default function App() {
  const [showDetails, setShowDetails] = useState(false);
 
  return (
      <>
        <h1>Project List</h1>
        <ProjectIntro />
        <button onClick={() => setShowDetails(true)}>Show Details</button>
        {showDetails ? <ProjectDetails /> : null }
      </>
  );
};

Ở đoạn code trên, component ProjectDetails mặc định sẽ không hiển thị, tuy nhiên nó vẫn sẽ được load vào trong bundle file vì đã được import ngay trên đầu. React.lazy giúp bạn dynamic import 1 component, kết hợp với Suspense bọc bên ngoài cho phép chúng ta thêm xử lý hiệu loading component đó mà không làm tăng đáng kể bundle file size. Source code cho việc triển khai React.lazy và Suspense như sau:

import React, { useState, Suspense } from 'react';
import ProjectIntro from './projectIntro';
 
const ProjectDetails = React.lazy(() => import("./projectDetails"));
 
export default function App() {
  const [showDetails, setShowDetails] = useState(false);
 
  return (
    <>
        <h1>Project List</h1>
        <ProjectIntro />
        <button onClick={() => setShowDetails(true)}>Show Details</button>
        <Suspense fallback={<div>Loading...</div>}>
          {showDetails ? <ProjectDetails /> : null }
        </Suspense>
    </>
  );
};

Có một lưu ý ở đây là React.lazy sẽ không thực hiện được khi render app ở server-side. Các bạn có thể tham khảo cách sử dụng 1 thư viện lazy load khác dành cho React như Loadable-components.

Tham khảo tin tuyển dụng lập trình viên React mới nhất tại đây!

Route-based code splitting 

Ở hai kỹ thuật trên, chúng ta đã tìm cách giảm kích thước bundle file bằng cách giảm những thành phần cần thiết để load ứng dụng trong 1 component. Với phạm vi một ứng dụng, chúng ta có chứa nhiều màn hình, tại mỗi thời điểm sử dụng thì người dùng sẽ chỉ tương tác với một hoặc một vài màn hình nhất định. Vì thế việc code splitting hoàn toàn cần thiết để thực hiện trên phạm vi ứng dụng.

Khi 1 ứng dụng React chạy, tương ứng với mỗi route sẽ có 1 component đảm nhiệm việc hiển thị và tương tác với người dùng, điều đó cũng có nghĩa các component khác không cần thiết phải được load lên ngay lúc đó. Chúng ta vẫn sẽ sử dụng lazy load cho trường hợp này, code thực hiện sẽ như sau:

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from "./home";
 
const Profile = lazy(() => import('./profile'));
const ContactUs = lazy(() => import('./contact'));
 
const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/profile" element={<Profile />} />
        <Route path="/contact" element={<ContactUs />} />
      </Routes>
    </Suspense>
  </Router>
);

Ở đoạn code trên, 2 components Profile và ContactUs được xử lý lazy loading, chúng sẽ chỉ được load khi user đi đến route tương ứng. Điều đó giúp cho ứng dụng của bạn không cần phải chờ load hết tất cả các component trong Router, giảm kích thước bundle file ban đầu.

Lời kết

Như vậy chúng ta đã đi qua được các kỹ thuật Code-Splitting giúp tối ưu ứng dụng React thông qua việc giảm bundle file size. Trong thực tế các project React hiện nay, việc sử dụng lazy load là hết sức cần thiết khi có quá nhiều component, các module, thư viện được sử dụng trên cùng 1 màn hình. Hãy cố gắng tối ưu source code của bạn nhất có thể ngay từ ban đầu để tránh phải giải quyết các vấn đề về hiệu năng cho việc mở rộng sau này. Hy vọng bài viết cung cấp cho bạn kiến thức hữu ích cho các dự án React sắp tới, hẹn gặp lại mọi người trong các biết tiếp theo của mình.

Tác giả: Phạm Minh Khoa

Xem thêm:

Tìm việc làm IT mọi cấp độ mới nhất trên TopDev

Chân Dung Lập Trình Viên Gen Z – Lực Lượng Lao Động Tương Lai

Lap trinh vien GenZ
Chân dung lập trình viên GenZ

 

Theo số liệu trong “Báo Cáo Thị Trường IT Việt Nam 2022 – Tech Hiring 2022” do TopDev phát hành, hiện nay nhân sự ngành IT tại Việt Nam phần lớn là các lập trình viên trẻ thuộc thế hệ Millennials (Gen Y). Tuy nhiên, các nhà tuyển dụng cũng cần chuẩn bị cho Centennials (GenZ), theo sau Millennials. Thế hệ này được dự báo như một làn sóng mới có thể thay đổi thị trường nhân sự, chắc chắn ngành IT không phải là trường hợp miễn trừ vì nhu cầu về lập trình viên sẽ tiếp tục tăng mạnh trong vòng 5 năm tới. 

Hãy cùng TopDev khám phá chân dung của lập trình viên Gen Z tại Việt Nam ngay bên dưới đây nhé!

Chân dung Lập trình viên 2022

Tổng quan về Gen Z

Thế hệ Z (Gen Z hay Centennial) là tập hợp nhóm người thuộc thế hệ trẻ có năm sinh từ 1997 đến 2012. Các thành viên lớn tuổi nhất của thế hệ Z đang bắt đầu những năm đầu sự nghiệp (lớn nhất là 23 tuổi và trẻ nhất là 10 tuổi). 

Hiện tại, số lượng nhân sự trong ngành CNTT ở Việt Nam chiếm đa số với 53,97% ở độ tuổi 20 – 29 tuổi. Dự đoán đến năm 2025, thế hệ Z dự kiến sẽ chiếm 30% lực lượng lao động tại Việt Nam. Vì vậy trong tương lai gần (từ 5 đến 10 năm) sẽ là thời đại của Gen Z vào thị trường IT. 

Tuy nhiên, sự khác biệt trong các thế hệ làm cho việc tuyển dụng các nhân sự Gen Z trở nên khó khăn hơn bao giờ hết dù đây là thế hệ có đủ các yếu tố có thể tạo ra các bứt phá góp phần to lớn trong công cuộc đổi mới tương lai. Vì vậy, các nhà tuyển dụng cần phải nắm bắt, thấu hiểu về tính cách, sở thích cũng như hành vi của thế hệ này nhằm chuẩn bị các kế hoạch tổ chức quản lý nhân sự để đón làn sóng mới trong tương lai.

Đặc điểm của thế hệ Gen Z

Gen Z được xem là con người của thời đại số hoá, điều đó được thể hiện bởi cơ hội được tiếp xúc với Internet từ rất sớm nên việc học tập và tìm hiểu các công nghệ mới vượt trội hơn so với các thế hệ trước. Hãy cùng khám phá những đặc điểm nổi bật của Gen Z ngay bên dưới đây.

1. Digital Native

Có thể nói, thuật ngữ Digital Native (chỉ những người sinh ra trong một thế giới nơi công nghệ kỹ thuật số) là dành cho thế hệ Gen Z, khi mà thời điểm họ sinh ra Internet đã trở nên phổ biến. 

Là thế hệ đầu tiên được tiếp cận với công nghệ từ khi còn bé và có tư duy đổi mới, mong muốn góp phần thay đổi thế giới bởi sự thông thạo công nghệ và ý chí cạnh tranh khốc liệt. Gen Z đóng vai trò rất quan trọng, thiết yếu trong công cuộc thay đổi và xây dựng thế giới trong thời kỳ đổi mới.

2. Tech-Savvy 

Gen Z dành sự quan tâm rất cao đến những ứng dụng công nghệ hay các lĩnh vực liên quan. Có thể nói rằng việc dễ dàng làm quen với các công nghệ mới và sử dụng thành thạo các ứng dụng trên smartphone đã trở thành một trong những đặc điểm nổi bật của thế hệ này. 

Không chỉ vậy Gen Z còn có khả năng nắm bắt các xu hướng nhanh chóng với khả năng thích ứng cao đối với các nền tảng xã hội. Có thể nói, Facebook, Tiktok, Instagram,…trở nên quen thuộc và gần gũi khi họ rất cởi mở và dễ dàng tiếp nhận các thông tin cũng như tạo ra các nội dung có thể làm nên các xu hướng mới được thay đổi không ngừng chỉ trong thời gian ngắn. Vì thế mà đây cũng là lợi thế lớn đối với thế hệ Gen Z.

3. Value Human Connection (Mối liên kết giá trị giữa người với người)

Bình đẳng trong công việc là điều mà đa phần các Gen Z muốn hướng đến. Các ranh giới “cấp trên – cấp dưới” dường như được xóa nhòa khi thế hệ này mong muốn xây dựng các mối quan hệ trong công việc như một đồng nghiệp hơn là sự phân chia các thứ bậc. Vì họ tin rằng, sự kết nối của con người thật sự không có giới hạn.

Bên cạnh đó, Gen Z cũng đánh giá cao tính hiệu quả khi giao tiếp, các vấn đề sẽ được giải quyết khi trò chuyện trực tiếp hơn là thông qua các hình thức online như tin nhắn, email.

Phương pháp quản lý nguồn lực mới 

Rất nhiều câu hỏi được đặt ra cho các nhà tuyển dụng trong “bài toán” tìm kiếm phương pháp quản lý nguồn nhân lực mới, đặc biệt nguồn nhân lực này (Gen Z) đã bắt đầu những năm đi làm đầu tiên trong thời kỳ đại dịch toàn cầu. Báo cáo thị trường IT – Tech Hiring 2022 cũng đã đề cập đến vấn đề này cũng như đưa ra một số định hướng để các nhà tuyển dụng có thể triển khai kế hoạch quản lý nguồn nhân lực thế hệ mới này:

Áp dụng các phương pháp thu hút nhân tài thế hệ mới

  • Tái thiết kế công việc ở vị trí bắt đầu;
  • Làm mơi lại các quy trình tuyển dụng từ offline sang online đồng thời giúp họ thể hiện cá tính của mình;
  • Nhấn mạnh sự ổn định và cơ hội tăng trưởng;
  • Tập trung vào tính linh hoạt & độc lập của mỗi cá nhân.

“Giữ chân” nhân tài trong giai đoạn thiếu nguồn cung nhân lực IT khốc liệt 

  • Tôn trọng và đón nhận sự khác biệt của họ;
  • Điều chỉnh mục đích làm việc với sứ mệnh và giá trị của công ty;
  • Thể hiện sự quan tâm đến sự phát triển nghề nghiệp và cá nhân;
  • Tạo thế mạnh quản lý và lãnh đạo.

Xây dựng và phát triển trong một đội ngũ có đa thế hệ bền vững

  • Tận dụng khoảng cách thế hệ nhằm đảm bảo tính bền vững của doanh nghiệp, đồng thời truyền tải các kiến thức chuyên môn của các thế hệ trước để tạo “bệ phóng” giúp Gen Z trở thành nhà lãnh đạo trong tương lai;
  • Kết hợp tầm nhìn, sứ mệnh và giá trị của công ty với mục tiêu cá nhân;
  • Nuôi dưỡng tinh thần kinh doanh và luôn minh bạch, cởi mở và thẳng thắn.

Có thể nói, tương lai sẽ không ngừng thay đổi và các thế hệ mới sẽ không ngừng đi lên và phát triển, tạo nhiều xu hướng khác biệt so với trước đây. Hi vọng thông qua bài viết này, các nhà tuyển dụng phần nào hiểu được chân dung của lập trình viên Gen Z và từ đó chuẩn bị cho những thay đổi về mặt nhân sự trong tương lai.

Bên cạnh đó, Báo cáo thị trường IT – Tech hiring 2022 cũng khai thác về nhiều khía cạnh khác nhau của ngành Công nghệ thông tin trong năm 2022 như: mức lương, ngôn ngữ lập trình phổ biến,… mời bạn đón đọc trọn bộ báo cáo tại đây.

Xem ngay những tin đăng tuyển dụng IT mới nhất trên TopDev

Nguồn: TopDev

Xem thêm:

BÁO CÁO THỊ TRƯỜNG IT VIỆT NAM NĂM 2022: Từng bước thay đổi hướng đến sự phát triển kinh tế lấy nhân tài làm trung tâm

 

Type Query trong GraphQL với Spring Boot

Type Query trong GraphQL với Spring Boot

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, mình đã giới thiệu với các bạn về GraphQL, những vấn đề mà GraphQL đã giải quyết được cho những hạn chế của RESTful Web Service. Mình cũng đã hướng dẫn  sơ qua cho các bạn về cách hiện thực type Query của GraphQL với Spring Boot. Trong bài viết này, chúng ta sẽ tìm hiểu chi tiết hơn về cách hiện thực type Query này sử dụng Spring Boot các bạn nhé!

Đầu tiên, mình sẽ tạo một Spring Boot project với Web và GraphQL Starter để làm ví dụ:

Kết quả:

Như mình đã nói trong bài viết trước, để làm việc với GraphQL, chúng ta cần định nghĩa các tập tin schema .graphqls. Mặc định thì Spring Boot sẽ scan tất cả các thư mục trong classpath src/main/resources của project để đọc các tập tin schema này.

Mình sẽ tạo một thư mục tên là graphql trong thư mục src/main/resources và để các tập tin schema của GraphQL trong thư mục này.

Để làm ví dụ mình đã tạo mới tập tin schema.graphqls với nội dung ban đầu đơn giản như sau:

type Query {
  hello: String
}

Query này sẽ return dòng chữ “Hello World” khi chúng ta query tới!

Để handle cho Query trên, chúng ta sẽ tạo mới một controller và định nghĩa một method có tên giống với tên field của type Query này, như sau:

package com.huongdanjava.graphql;
 
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
 
@Controller
public class GraphQLController {
 
  @QueryMapping
  public String hello() {
    return "Hello World";
  }
}

Như các bạn thấy, phương thức hello() đã được annotate với annotation @QueryMapping giúp cho Spring có thể scan và map tên method này với field của type Query. Rất đơn giản phải không các bạn?

Behind the sense, thì annotation @QueryMapping được implement sử dụng một generic annotation là @SchemaMapping:

Annotation @SchemaMapping này định nghĩa một thuộc tính là typeName cho phép chúng ta định nghĩa type của GraphQL. Ở đây, type của chúng ta là Query đó các bạn!

Một thuộc tính khác của annotation @SchemaMapping là field, giúp Spring có thể map field của GraphQL với tên method sẽ handle request:

Mặc định nếu chúng ta không khai báo giá trị cho thuộc tính field này, giá trị của nó sẽ là tên method các bạn nhé!

Tuyển dụng lập trình viên Java đãi ngộ hấp dẫn, xem thêm tại đây!

Nếu không sử dụng annotation @QueryMapping, chúng ta có thể viết lại code ở trên sử dụng annotation @SchemaMapping như sau:

package com.huongdanjava.graphql;

import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;
 
@Controller
public class GraphQLController {

  @SchemaMapping(typeName = "Query", field = "hello")
  public String hello() {
    return "Hello World";
  }
}

Để tiện cho việc testing, chúng ta sẽ thêm property spring.graphql.graphiql.enabled=true để enable sử dụng công cụ GraphiQL, trong tập tin application.properties:

spring.graphql.graphiql.enabled=true

Bây giờ, nếu chạy ứng dụng này và query sử dụng field hello trên, các bạn sẽ thấy kết quả như sau:

Để truyền tham số cho một Query, chúng ta sẽ định nghĩa ví dụ như sau:

type Query {
  hello(name: String): String
}

Trong controller, chúng ta sẽ sử dụng annotation @Argument để bind tham số được định nghĩa trong field của Query với tham số trong method handle request:

package com.huongdanjava.graphql;
 
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
 
@Controller
public class GraphQLController {
 
  @QueryMapping
  public String hello(@Argument("name") String name) {
    return "Hello, " + name;
  }
}

Thuộc tính name của annotation @Argument này cho phép chúng ta chỉ định rõ tham số trong method được bind với tham số nào trong Query.

Kết quả khi chúng ta query:

{
  hello(name: "Khanh")
}

như sau:

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

Xem thêm:

Ứng tuyển ngay việc làm IT lương cao trên TopDev!

Cách tuần tự hóa dữ liệu trong Java như Protobuf

cách tuần tự hóa dữ liệu trong java như protobuf

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

Khi dữ liệu được chuyển qua mạng qua các hệ thống rpc, msg queue,internal service,… Tùy vào các hệ thống chúng ta cần serialize dữ liệu thành dạng json hoặc array byte. Tuy nhiên để đảm bảo tốc đố của hệ thống thì phương pháp serialize dữ liệu thành array byte sẽ được sử dụng rộng rãi hơn.

Hiện nay việc serialize đã có các công ty lớn tạo ra các thư viện khác nhau với chất lượng và tốc độ rất cao như :

  • Protobuf của google.
  • Thrift của facebook.
  • Kryo một framework mạnh mẽ của java.

Việc sử dụng các framework trên là khá dễ dàng nên lập trình viên thường sẽ coi việc serialize dữ liệu là một hộp đen. Điều này khá nguy hiểm vì trên thực tế có những project đội ngũ lập trình thường sẽ không dùng các framework có sẵn vì một số lý do như : nhiều dependency, tốc độ chưa đảm bảo, mất công tạo file (.proto, .thrift) khiến thay đổi các object gây khó khăn. Tại project này sẽ giới thiệu cho mọi người một cách để serialize dữ liệu thành array byte.

Để serialize dữ liệu sang dạng array byte trong máy tính chúng ta có 2 cách serialize chính là BIG_ENDIAN và LITTLE_ENDIAN mọi người tham khảo lý thuyế tại wiki: en.wikipedia.org/wiki/Endianness

Chúng ta sẽ hiểu đơn gian như sau :

  • BIG_ENDIAN : sẽ ghi dấu trước ghi dữ liệu khác sau
  • LITTLE_ENDIAN : sẽ ghi dữ liệu trước và ghi dấu sau.

Ví dụ ta sẽ biến số interger 32 và -32 thành array byte ta code như sau:

public class Test {
    public static void main(String[] args){
        int number = 32;
        ByteBuffer x = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
        x.putInt(number);
        System.out.println("LITTLE_ENDIAN");
        for (int i = 0 ; i < 4 ; i++){
            System.out.printf("%d ", x.array()[i]);
        }
        System.out.println();
        System.out.println("BIG_ENDIAN");
        ByteBuffer y = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN);
        y.putInt(number);
        for (int i = 0 ; i < 4 ; i++){
            System.out.printf("%d ", y.array()[i]);

        }
    }
}

Ta sẽ được kết quả sau:

LITTLE_ENDIAN
32 0 0 0 
BIG_ENDIAN
0 0 0 32

Thay number = -32 ta được kết quả sau:

LITTLE_ENDIAN
-32 -1 -1 -1 
BIG_ENDIAN
-1 -1 -1 -32

Tiếp đến ta sẽ tìm hiểu cách protobuf serialize các kiểu đơn giản của chúng ta như thế nào. Tôi có file .proto sau

syntax = "proto3";

package proto;

option java_package = "blog.proto";

message SimpleObject {
    int32 count = 1;
    string name = 2;
    repeated DataObject dataList = 3;
}

message DataObject {
     int32 num1 = 1;
     int32 num2 = 2;
}

Tiếp theo ta sẽ sử dụng API của protobuf để serialize

public class Test {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        Blog.SimpleObject data = Blog.SimpleObject.newBuilder()
                .setCount(10)
                .setName("ânhdem976")
                .build();

        System.out.println(data.toByteArray().length); 
    }
}

Sau khi debug vào sâu bên trong framework (hàm data.toByteArray()) ta sẽ tìm thấy cách protobuf serialize object của chúng ta như sau:

 public static final class SimpleObject extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:proto.SimpleObject)
      SimpleObjectOrBuilder {
//.........
    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      if (count_ != 0) {
        output.writeInt32(1, count_);
      }
      if (!getNameBytes().isEmpty()) {
        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, name_);
      }
      for (int i = 0; i < dataList_.size(); i++) {
        output.writeMessage(3, dataList_.get(i));
      }
      unknownFields.writeTo(output);
    }
//.........

}

Với kiển interger như sau :

//.........
    @Override
    public void writeInt32(int fieldNumber, int value) throws IOException {
      writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
      writeInt32NoTag(value);
    }



 @Override
    public void writeInt32NoTag(int value) throws IOException {
      if (value >= 0) {
        writeUInt32NoTag(value);
      } else {
        // Must sign-extend.
        writeUInt64NoTag(value);
      }
    }

    @Override
    public void writeUInt32NoTag(int value) throws IOException {
      if (position <= oneVarintLimit) {
        // Optimization to avoid bounds checks on each iteration.
        while (true) {
          if ((value & ~0x7F) == 0) {
            UnsafeUtil.putByte(position++, (byte) value);
            return;
          } else {
            UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
            value >>>= 7;
          }
        }
      } else {
        while (position < limit) {
          if ((value & ~0x7F) == 0) {
            UnsafeUtil.putByte(position++, (byte) value);
            return;
          } else {
            UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
            value >>>= 7;
          }
        }
        throw new OutOfSpaceException(
            String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
      }
    }

    @Override
    public void writeUInt64NoTag(long value) throws IOException {
      if (position <= oneVarintLimit) {
        // Optimization to avoid bounds checks on each iteration.
        while (true) {
          if ((value & ~0x7FL) == 0) {
            UnsafeUtil.putByte(position++, (byte) value);
            return;
          } else {
            UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80));
            value >>>= 7;
          }
        }
      } else {
        while (position < limit) {
          if ((value & ~0x7FL) == 0) {
            UnsafeUtil.putByte(position++, (byte) value);
            return;
          } else {
            UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80));
            value >>>= 7;
          }
        }
        throw new OutOfSpaceException(
            String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
      }
    }
//.........

Dễ dàng thấy đối với kiểu interger > 0. protobuf sẽ chỉ mất từ 1-5 byte để serialize thành byte array chú ý hàm (writeUInt32NoTag) ngược lại đối với số mà nhỏ hơn 0 thì protobuf sẽ mất 10 byte để serialize thành byte array. Điều này suy ra protobuf sẽ tạo ra một array byte lớn hơn bình thường nếu số của chúng ta muốn serialize nhỏ hơn 0. Bình thường thì chỉ mất 4 bytes cho mọi thể loại số interger.

Tiếp tục ta sẽ kiểm tra tiếp đến kiểu dữ liệu string, debug chán chê các bạn sẽ đến được hàm sau trong class com.google.protobuf.Utf8, rảnh các bạn vào đọc source của nó cũng khá nhiều thứ hay ho.

final class Utf8 {
//.........
  @Override
    int encodeUtf8(final CharSequence in, final byte[] out, final int offset, final int length) {
      long outIx = offset;
      final long outLimit = outIx + length;
      final int inLimit = in.length();
      if (inLimit > length || out.length - length < offset) {
        // Not even enough room for an ASCII-encoded string.
        throw new ArrayIndexOutOfBoundsException(
            "Failed writing " + in.charAt(inLimit - 1) + " at index " + (offset + length));
      }

      // Designed to take advantage of
      // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination
      int inIx = 0;
      for (char c; inIx < inLimit && (c = in.charAt(inIx)) < 0x80; ++inIx) {
        UnsafeUtil.putByte(out, outIx++, (byte) c);
      }
      if (inIx == inLimit) {
        // We're done, it was ASCII encoded.
        return (int) outIx;
      }

      for (char c; inIx < inLimit; ++inIx) {
        c = in.charAt(inIx);
        if (c < 0x80 && outIx < outLimit) {
          UnsafeUtil.putByte(out, outIx++, (byte) c);
        } else if (c < 0x800 && outIx <= outLimit - 2L) { // 11 bits, two UTF-8 bytes
          UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 6) | (c >>> 6)));
          UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
        } else if ((c < MIN_SURROGATE || MAX_SURROGATE < c) && outIx <= outLimit - 3L) {
          // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
          UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 5) | (c >>> 12)));
          UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
          UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
        } else if (outIx <= outLimit - 4L) {
          // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
          // bytes
          final char low;
          if (inIx + 1 == inLimit || !isSurrogatePair(c, (low = in.charAt(++inIx)))) {
            throw new UnpairedSurrogateException((inIx - 1), inLimit);
          }
          int codePoint = toCodePoint(c, low);
          UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
          UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
          UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
          UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & codePoint)));
        } else {
          if ((MIN_SURROGATE <= c && c <= MAX_SURROGATE)
              && (inIx + 1 == inLimit || !isSurrogatePair(c, in.charAt(inIx + 1)))) {
            // We are surrogates and we're not a surrogate pair.
            throw new UnpairedSurrogateException(inIx, inLimit);
          }
          // Not enough space in the output buffer.
          throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + outIx);
        }
      }

      // All bytes have been encoded.
      return (int) outIx;
    }
//.........
}

Code khá dài nên anh em nào ngại đọc thì sẽ giải thích như sau. Bình thường kiểu Character sẽ mất 2 byte để lưu trữ cũng như serialize. Nhưng trong code của google chúng ta thấy họ đã tối ưu khá nhiều khiến kiểu Character sẽ chỉ còn mất từ 1-3 byte nhưng trường hợp 3 byte thì chắc sẽ rất hiếm gặp. Từ đây kết luận protobuf họ làm khá tốt đối với kiểu dữ liệu String

Mình chỉ phân tích 2 kiểu dữ liệu đó thôi các kiểu còn lại mọi người chịu khó đọc tìm hiểu sẽ ra :)) chúc may mắn.

Xem tin tuyển dụng Java mới nhất trên TopDev

Vì protobuf không có kiểu dữ liệu Map một kiểu rất hay được dùng, tiếp đến việc có thêm object mới lại phải chỉnh sửa lại file proto kiến công việc khá rắc rối và thêm dependency mới vào project mà không dùng tính năng grpc là những điểm mình không thích thư viện protobuf này. Tất nhiên nếu dùng serialize, deserialize có sẵn của java thì sẽ khắc phục được những nhược điểm bên trên nhưng nó lại gây chậm cho hệ thống và khó có thể dùng một ngôn ngữ khác dịch được các byte này thành object.

Tại project này mình sẽ kết hợp protobuf, Kryo và các project khác đã được trải nghiệm để xây dựng lên cách serialize riêng vẫn đảm bảo được tốc dộ cũng như vẫn có thể sử dụng một ngôn ngữ khác để Deserialize được.

Project sẽ được xây dựng theo khung sau:

  • Marshaller : là một anotation của java dùng để đánh dấu các class sẽ được serialize, deserialze, chứa một số thông tin để thực hiện quá trình này
  • DInput : Một Interface chứa các phương thức dùng để Deserialize dữ liệu (Các class implement DByteArrayInput, DByteBufferInput)
  • DOutput : Một Interface chứa các phương pháp dùng để Serialize dữ liệu (Các class implement DByteArrayOutput, DByteBufferOutput)
  • DSerialize : Một Interface mà các class cần implement để serialize, deserialize
  • DMarshaller : Một Interface điều khiển quá trình serialize,deserialize

Trong project có viết sẵn các hàm giống như protobuf để ghi một số integer mất từ 1-5 byte. ghi một dữ liệu character mất từ 1-3 byte. Với cách tự serialize, deserialize này chúng ta hoàn toàn có thể sử dụng một ngôn ngữ khác để serialize,deserialize dữ liệu một cách bình thường.

Tất cả các class muốn được serialize, deserialize cần phải implement interface DSerialize. Ví dụ trong project là User,TestMapData,TestObject


import blog.serilize.base.DInput;
import blog.serilize.base.DMarshaller;
import blog.serilize.base.DOutput;
import blog.serilize.base.DSerialize;
import blog.serilize.base.anotation.Marshaller;

@Marshaller(name = User.class,number = 2)
public class User implements DSerialize<User> {
    private String name;
    private int age;


    public User(String name) {
        this.name = name;
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public User() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void write(DMarshaller marshaller, DOutput output, User data) {
        output.writeString(data.getName());
        output.writeInt(data.getAge());
    }

    @Override
    public User read(DMarshaller marshaller, DInput input) {
        User user = new User();
        user.name = input.readString();
        user.age =input.readInt();
        return user;
    }

    @Override
    public Class<?> getClasses() {
        return User.class;
    }
}

Để sử dụng được thì các class này cần phải được đăng ký với DMarshaller. Ta có ví dụ về cách sử dụng như sau :

public class Test {
  public static void main(String[] args) throws InstantiationException, IllegalAccessException {
          DMarshaller marshaller = new DMarshallerIml();
          marshaller.register(TestObject.class);
          marshaller.register(User.class);
          marshaller.register(TestMapData.class);
          marshaller.register(HashMapSerialize.class);
          marshaller.register(StringSerialize.class);


          User demtv = new User("demtv");
          Map<String ,User> map = new HashMap<>();
          map.put(demtv.getName(), demtv);
          TestMapData data = new TestMapData();
          data.setData(map);

          DOutput output = new DByteBufferOutput(100);

          marshaller.write(data, output);
          TestMapData y = marshaller.read(new DByteBufferInput(output.toArrayBytes()));
          System.out.println(y.getData().get("demtv").getName());
      }
}

Dưới đây là link github : github.com/trandem/blog/tree/main/simple-se.. Nếu cái này có ích cho bạn thì mình xin 1 sao nhé.

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

Xem thêm:

Việc làm IT mọi cấp độ có trên TopDev

React dành cho người mới bắt đầu

React dành cho người mới bắt đầu

Đối với bất kỳ bạn lập trình viên mới nào thì React hiện tại đang là một thư viện JavaScript được sử dụng rộng rãi, được phát triển và duy trì bởi Meta (tiền thân là Facebook). React đã trở thành một thư viện front-end được ưa chuộng nhất và lên tục được phát triển về cả mức độ phổ biến và tầm ảnh hưởng của mình.

Để cho các bạn mới bắt đầu tiếp cận với thế giới React một cách thuận tiện nhất, mình có tổng hợp một số các hướng dẫn, gợi ý dành cho các bạn trong bài viết này hôm nay. Chúng ta cùng bắt đầu nhé 

Sử dụng Create React App để khởi tạo projects

Một trong những chức năng đơn giản mà hiệu quả nhất của React là khả năng tạo ra một dự án mới bằng một dòng lệnh duy nhất: sử dụng Create React App. Bạn có thể chạy 1 trong 3 dòng lệnh dưới đây:

  • npx create-react-app my-app
  • npm init react-app my-app
  • yarn create react-app my-app

Đây là cách nhanh và cũng là tốt nhất dành cho các bạn mới học React, 1 project React với tên “my-app” (tất nhiên các bạn có thể đổi tên nó) được tạo ra với đầy đủ các package cần thiết cho bạn.

Sau khi cài đặt, chúng ta có thể ngay lập tức chạy ứng dụng của mình ở chế độ development bằng lệnh: “npm start” hoặc “fiber start”, cổng (port) mặc định sẽ là 3000, thậm chí nó còn tự động mở trình duyệt lên và chạy ứng dụng vừa được tạo ra.

Tìm hiểu những cú pháp cơ bản

React là thư viện thân thiện với lập trình viên, hãy bắt đầu học và nắm chắc những khái niệm dưới đây, bạn có thể tự tin trong việc viết code React:

  • Props: là 1 object được truyền vào 1 component, cho phép giao tiếp giữa các component bằng cách truyền tham số qua lại giữa component cha và component con
  • State: là phần dữ liệu động bên trong component của bạn, nó có thể thay đổi theo thời gian thông qua tương tác của component với người dùng
  • Components: bản chất là 1 function nhận đầu vào chính là props và trả về JSX (1 cú pháp mở rộng trong React để viết HTML). Components có khả năng mở rộng và tái sử dụng – đây cũng chính là đặc trưng và ưu điểm lớn nhất của React
function Links(props) {
  const [linkedin, setLinkedin] = useState("");
 
  return (
    <div>
      <h3>Links</h3>
      <a href={props.github}>{props.github}</a>
      <a href={linkedin}>{linkedin}</a>
    </div>
  );
}

Đoạn code trên là cú pháp cơ bản nhất trong React, thể hiện 1 component Links với props “github” và state “linkedin”.

  • React Hooks: các function đặc biệt cho phép chúng ta “móc nối” vào các biến state bên trong components. Để sử dụng hook, trước tiên hãy import và gọi chúng bên trong component của bạn. Để làm quen, mình khuyên các bạn hãy tìm hiểu kỹ 2 hooks: useState và useEffect
    • useState: sử dụng để truy cập và sửa đổi các biến state của components
    • useEffect: sử dụng để thực hiện những side effect (tác động từ bên ngoài function chính) như: lấy dữ liệu, cập nhật các phần tử bên trong components, …
import React, { useState, useEffect } from "react";
 
function Links(props) {
  const [timeRemaining, setTimeRemaining] = useState(1);
 
  useEffect(() => {
    if (timeRemaining === 0) {
      setTimeRemaining(10);
      return;
    }
  }, []);
}

Hãy giữ cho component của bạn “nhỏ vừa đủ”

Thực tiễn trong các dự án React, component nên được chia càng nhỏ các tốt về mặt chức năng và không nên bị trừu tượng hóa quá mức. Theo kinh nghiệm của mình, hãy bắt đầu từ App component ở top (bao trọn cả tất cả các components khác), sau đó chia nhỏ dần các thành phần giao diện nhỏ hơn đến mức chức năng. Điều này sẽ giúp ứng dụng của bạn:

  • Dễ dàng debug gỡ lỗi hơn
  • Code bạn viết dễ hiểu hơn
  • Cho phép tái sử dụng và khả năng mở rộng component tốt hơn
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
 
function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

Tham khảo tin tuyển dụng IT Fresher, Inten mới nhất tại đây!

Đừng lạm dụng state

Một trong những sai lầm lớn mà các bạn mới làm React hay gặp phải là việc tạo ra quá nhiều biến state không cần thiết trong các trường hợp mà chỉ cần sử dụng props kết hợp với logic có điều kiện là đủ. Chúng ta đều biết mỗi khi biến state thay đổi thì component sẽ thực hiện việc re-render lại, và khi bạn tạo ra quá nhiều biến state trong 1 component cũng đồng nghĩa với việc có thêm nhiều “nguồn tác động” đến việc cập nhật hiển thị component.

Hãy xem xét việc nên hay không nên thêm 1 biến state mới vào 1 component, có 1 vài yếu tố các bạn có thể cân nhắc

  • Component của bạn có tĩnh và không thay đổi hay không?
  • Bạn có thể tính toán trước giá trị props theo logic có sẵn để tạo ra các trạng thái component mong muốn hay không?

Nếu câu trả lời là có thì tốt nhất là không sử dụng thêm biến state lúc này.

const [option1, setOption1] = useState(false);
const [option2, setOption2] = useState(false);
const [option3, setOption3] = useState(false);
const [option4, setOption4] = useState(false);
const [option5, setOption5] = useState(false);

Tránh các lỗi không đồng bộ

Khi bạn sử dụng state trong React, luôn luôn phải để ý rằng việc setState (thay đổi giá trị state) là bất đồng bộ. Điều đó có nghĩa là biến state sẽ không thay đổi ngay lập tức mà nó phải đợi việc re-render component. Để tránh các lỗi xảy ra do việc cập nhật dữ liệu 1 cách không đồng bộ, hãy tìm hiểu vòng đời của component trong React. 

Thêm 1 lời khuyên nữa cho các bạn trong trường hợp này, hãy “bắt” sự kiện biến state thay đổi, thay vì “chờ” biến state đó thay đổi xong.

const [state, setState] = useState(0);
...
setState(2020);
console.log(state); // 0

Kết bài

Sẽ còn nhiều thứ phải học để các bạn có thể thành thạo với React, hy vọng những gợi ý trên sẽ giúp các bạn có thể nhanh chóng và dễ dàng hơn từ lúc bắt đầu làm quen với thư viện này. Cảm ơn các bạn đã đọc bài viết, hẹn gặp mọi người trong các bài sắp tới của mình.

Tác giả: Phạm Minh Khoa

Xem thêm:

Bạn đang tìm việc làm UI/UX Designer hay việc làm ngành IT? Tham khảo ngay những tin tuyển dụng mới nhất trên TopDev!

Quản lý realm database theo hướng micro-service trong iOS

Quản lý realm database theo hướng micro-service trong iOS

Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh

Yêu cầu bài viết

  • Đã sử dụng qua realm swift.
  • Có kiến thức căn bản về lập trình iOS

Micro-service là gì?

Với những ai đang làm các dự án Backend thì khái niệm micro-service sẽ không còn xa lạ nữa.

Micro-service nghĩa là chia nhỏ các service của ứng dụng thành những phần riêng biệt, độc lập với nhau để dễ dàng cho việc quản lý, release sản phẩm. Lấy 1 ví dụ, khi backend có các nghiệp vụ: đăng nhập, đăng ký tài khoản, lưu giỏ hàng, thanh toán.. thì chúng ta sẽ có thể chia các cụm micro-service như sau:

  • Cụm authentication: đăng nhập, đăng ký nơi các nghiệp vụ xác nhận người dùng.
  • Cụm payment: gồm lưu giỏ hàng, thanh toán chứa nghiệp vụ về mua bán sản phẩm.

Khi 1 API nào ở cụm payment bị lỗi thì nó hoàn toàn không ảnh hưởng tới cụm authentication. Đó là lợi ích của việc chia để trị trong micro-service.

Ở trong các ứng dụng iOS, nghiệp vụ về database cũng tương tự. Lấy ví dụ, khi bạn lưu data cho phần authentication, bao gồm các bảng bảng user, token… và nghiệp vụ payment gồm các bảng về product, wishList thì chúng ta cũng có thể chia để trị như trên.

Realm swift cho phép chúng ta sử dụng nhiều file realm riêng biệt, mỗi file realm gồm 1 số bảng liên quan tới nhau trong đó. Mỗi file realm như vậy chúng ta gọi là database.

Ví dụ về 1 database pets, nơi chứa nghiệp vụ về pets, gồm nhiều bảng

Như hình trên, chúng ta có thể thấy nghiệp vụ pets trong 1 ứng dụng về quản lý chó mèo, chúng ta chia nhỏ các bảng ra thành 1 database có tên là PetSchema như hình:

Vậy là chúng ta đã có thể hình dung rằng thay vì dùng 1 file realm Default.realm mặc định thì giờ đây chúng ta có rất nhiều file realm trong ứng dụng.

Vậy lợi ích của việc này là gì?

  • Khi gọi các bảng từ các file .realm này thì tốc độ sẽ nhanh hơn thay vì load 1 file lớn vào memory của ứng dụng.
  • Dễ dàng migration khi có thay đổi trường trong bảng.
  • Tránh conflict khi làm team với nhiều người.
  • Dễ dàng cho việc testing

OK, vậy là các bạn đã hiểu được nguyên lý micro-service rồi. Tiếp theo để xây dựng realm manager thì chúng ta cần triển khai những gì?

Các yêu cầu của Realm manager

Yêu cầu của realm manager cần xử lý các nghiệp vụ sau:

  • Quản lý thêm, sửa, xóa, update cũng như query bảng.
  • Tăng sự tiện lợi khi sử dụng.
  • Dễ dàng truy cập, dễ dàng sửa đổi.
  • Kết nối với lớp database.

Các loại lưu trữ của Realm

Thật tuyệt vời, giờ đây Realm sẽ cho phép bạn có 2 cách để lưu trữ:

  • Lưu trữ trên memory
  • Lưu trữ vào ổ đĩa(các file realm).

Lưu trữ trên ổ đĩa

Mặc định anh em làm iOS sẽ hay dùng phương pháp lưu trữ vào 1 file .realm. Toàn bộ bảng sẽ lưu vào file realm và tồn tại trên ổ đĩa của ứng dụng.

Lưu trữ trên memory

Hàm init của Realm bản 10.28.2 như sau:

public init(fileURL: URL? = URL(fileURLWithPath: RLMRealmPathForFile("default.realm"), isDirectory: false),
                    inMemoryIdentifier: String? = nil,
                    syncConfiguration: SyncConfiguration? = nil,
                    encryptionKey: Data? = nil,
                    readOnly: Bool = false,
                    schemaVersion: UInt64 = 0,
                    migrationBlock: MigrationBlock? = nil,
                    deleteRealmIfMigrationNeeded: Bool = false,
                    shouldCompactOnLaunch: ((Int, Int) -> Bool)? = nil,
                    objectTypes: [ObjectBase.Type]? = nil,
                    seedFilePath: URL? = nil) {
  ...
}

Như chúng ta thấy tham số inMemoryIdentifier nhằm định danh memory theo 1 string để lưu trữ.

Mục đích lưu trữ trên memory giúp chúng ta có thể thực hiện các nghiệp vụ về unit-test hoặc Short live data.

Version Management & Migration Management

Việc đánh số version cho realm của chúng ta nhằm mục đích migration. Khi có bất kỳ 1 sự thay đổi nào trong các bảng dữ liệu, realm cho phép bạn chuyển đổi nó 1 cách đơn giản thông qua MigrationBlock. Con số này sẽ tăng lên sau mỗi phiên bản. Đây là yêu cầu bắt buộc của realm. Các bạn có thể xem tại đây.

Increment Versions MonotonicallyMigrations must update a realm to a higher schema version. Realm Database will throw an error if a client application opens a realm with a schema version that is lower than the realm’s current version or if the specified schema version is the same as the realm’s current version but includes different object schemas.

Nói cách khác, nếu khi bạn thay đổi bảng của realm nhưng không tăng version, thì ứng dụng của bạn sẽ crash.

Khi các bạn đã xác định được các thành phần của 1 realm manager thì chúng ta sẽ tiến hành triển khai nó.

Tham khảo ngay tin tuyển dụng lập trình viên backend tại TopDev!

Triển khai realm manager

Các thành phần cần thiết của nó như sau:

/// DatabaseConfigurable all defines which you must conform according
public protocol DatabaseConfigurable {
    var realmMemoryType: RealmMemoryType { get }

 // This property you must assign the database name that you want.
    //  If you want to use legacy architecture you can assign nil for it.
    //  If you want to use legacy architecture you can assign nil for it.
    var schemaName: String? { get }

// This property you must assign the database version according to the migration count.
    // You must change the version on kLegacySchemaVersion instead according to the migration count too.
    //  If you want to use legacy architecture you can assign nil for it.
    var schemaVersion: UInt64? { get }

  // This property you must assign the table type to verify that this schema will use only this table.
    //  If you want to use legacy architecture you can assign nil for it.
    var objectTypes: [Object.Type]? { get }

 var embeddedObjectTypes: [EmbeddedObject.Type]? { get }

  // This property you must implement the migration logic if a table has changed.
    // If you want to use legacy architecture you can assign nil for it. If you assign nil.
    var migrationBlock: MigrationBlock? { get }
}

Trong đó:

  • realmMemoryType sẽ gồm 2 loại: lưu vào ổ đĩa và lưu vào memory
  • schemaName: Tên của micro-realm schema mà bạn muốn.
  • schemaVersion: số phiên bản realm schema. Đánh số từ 0.
  • objectTypes: 1 list các Object realm mà bạn muốn lưu trữ ở file realm này. Nó có thể nhiều bảng liên quan tới nhau, ví dụ:
var objectTypes: [Object.Type]? {
        return [DogToy.self, Dog.self, DogClub.self, Person.self]
    }
  • embeddedObjectTypes: tương tự objectTypes, realm giờ đây đã cung cấp cho chúng ta những Object embedded vào các object khác. Nghĩa là khi bạn xóa 1 Object, thì các object embedded của nó sẽ bị xóa tự động. Xem thêm tại đây.
  • migrationBlock: Thành phần không thể thiếu khi bạn muốn migrate data của bạn. Ví dụ:
var migrationBlock: MigrationBlock? {
        let migrationBlock: MigrationBlock = { migration, oldSchemaVersion in
            if oldSchemaVersion < 1 {
                // Rename the "name" property to "yourName".
                // The renaming operation should be done outside of calls to `enumerateObjects(ofType: _:)`.
                migration.renameProperty(onType: MigrationSample.className(), from: "age", to: "yearsSinceBirth")
//                migration.renameProperty(onType: MigrationSample.className(), from: "name", to: "yourName")
            }

            // The enumerateObjects(ofType:_:) method iterates over
            // every Person object stored in the Realm file to apply the migration
            migration.enumerateObjects(ofType: MigrationSample.className()) { oldObject, newObject in
                // combine name fields into a single field
                let firstName = oldObject!["firstName"] as? String
                let lastName = oldObject!["lastName"] as? String
                newObject!["fullName"] = "\(firstName!) \(lastName!)"
            }
        }
        return migrationBlock
    }

Tôi đã triển khai thư viện để implement toàn bộ các thành phần trên. Các bạn có thể sử dụng vào project của mình bằng 2 cách như sau:

Sử dụng pod:

pod 'QRealmManager'
sau đó import thư viện:
import QRealmManager

Sử dụng Swift package:

Thêm bằng dòng sau:
https://github.com/lexuanquynh/QRealmManagerPackage.git
Sau đó import:
import QRealmManagerPackage

Trong thư viện, tôi đã sử dụng hàm writeAsync nhằm đảm bảo quá trình xử lý realm luôn luôn ở background thread. Các bạn có thể xem thêm ở đây.

Perform a Background WriteNew in version 10.26.0.
You can add, modify, or delete objects in the background using writeAsync.

Cách sử dụng

Đầu tiên, tất nhiên rồi bạn cần có các object của realm. Theo chuẩn mới nhất realm sẽ sử dụng Persisted vừa ngắn gọn, vừa đơn giản và chúng ta có thể dùng các high function của swift để query 1 cách dễ dàng.

import RealmSwift

class Person: Object {
    @Persisted(primaryKey: true) var id = 0
    @Persisted var name = ""
    // To-many relationship - a person can have many dogs
    @Persisted var dogs: List<Dog>
    // Inverse relationship - a person can be a member of many clubs
    @Persisted(originProperty: "members") var clubs: LinkingObjects<DogClub>
}

Tiếp theo chúng ta sẽ tạo lớp Repository để implement lại các cài đặt của realm manager:

import RealmSwift
import QRealmManager

class PetRepository: DatabaseConfigurable {
    var realmMemoryType: RealmMemoryType {
       return .inStorage
    }

    var schemaName: String? {
        return "PetSchema"
    }

    var schemaVersion: UInt64? {
        0
    }

    var objectTypes: [Object.Type]? {
        return [DogToy.self, Dog.self, DogClub.self, Person.self]
    }

    var embeddedObjectTypes: [EmbeddedObject.Type]? {
        return nil
    }

    var migrationBlock: MigrationBlock? {
        return nil
    }
}

Sau đó bạn sẽ dùng repository đó để thao tác với các Object trong file realm của bạn 1 cách dễ dàng:

Để lưu entity:

let repository = PetRepository()
repository.save(entity: dog, update: false) { result in
            switch result {
            case .success:
                // Handle success here
                print("Handle success here")
            case .failure:
                print("Handle failed here")
            }
        }

Để lưu nhiều entities:

        let aDog = Dog(value: ["name": "Lulu", "age": 3])
        let anotherDog = Dog(value: ["name": "Nana", "age": 2])

        // Instead of using pre-existing dogs...
        let aPerson = Person(value: [123, "Jane", [aDog, anotherDog]])
        // ...we can create them inline
        let anotherPerson = Person(value: [456, "Jane", [["Buster", 5], ["Buddy", 6]]])

        repository.save(entities: [aPerson, anotherPerson], update: true) { result in
            switch result {
            case .success:
                print("Handle success here")
            case .failure:
                print("Handle failed here")
            }
        }

Thậm chí bạn còn có thể lưu JSON data:

let data = "{\"name\": \"Tennis ball\"}".data(using: .utf8)!
        repository.save(saveClass: DogToy.self, jsonData: data, update: false) { result in
            switch result {
            case .success:
               break
            case .failure:
                break
            }
        }

Để query, realm nói say goodbye với predicate, mà sử dụng luôn các high function swift, quá tiện lợi đúng không?

let coffeDrinks = repository.queryAll(returningClass: CoffeeDrink.self)
let cofferRate = coffeDrinks!.filter { $0.rating == 4 }

Xem thêm say goodbye ở đây.

Kết luận

Giờ đây, với realm manager, bạn đã có thể quản lý dễ dàng các file realm của mình.

Nếu có bất kỳ câu hỏi nào xin vui lòng để lại comment ở bài viết này.

Nếu yêu thích bài viết hãy tặng 1 sao vào repository sau:

https://github.com/lexuanquynh/QRealmManager

Xin cảm ơn.

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

Xem thêm:

Top Developer đừng bỏ lỡ Top IT Job được cập nhật mỗi ngày trên TopDev nhé!

Cuộc Thi Tìm Kiếm Giải Pháp Chuyển Đổi Số Quốc Gia (Vietsolutions) Năm 2022

Cuộc thi tìm kiếm giải pháp chuyển đổi số quốc gia năm 2022

Cuộc thi Tìm kiếm giải pháp chuyển đổi số quốc gia (Viet Solutions) là cuộc thi thường niên do Bộ Thông tin và Truyền thông chủ trì, Cục Chuyển đổi số quốc gia và Tập đoàn Công nghiệp Viễn thông Quân đội Viettel đồng tổ chức, từ năm 2022 có sự tham gia đồng hành của Công ty Galaxy Digital, cùng sự tham gia bảo trợ truyền thông của Đài Truyền hình Việt Nam (VTV), Đài Tiếng nói Việt Nam (VOV), Báo VietNamNet, Báo Vnexpress và Tạp chí Thông tin và Truyền thông.

Ngày 22/7/2022, Bộ Thông tin và Truyền thông đã tổ chức Lễ phát động cuộc thi Tìm kiếm giải pháp chuyển đổi số Quốc gia (Viet Solutions) 2022.

Cuộc thi năm 2022 bao gồm các hạng mục:
(1) Tìm kiếm và công bố các bài toán chuyển đổi số Việt Nam ở các ngành, lĩnh vực, địa phương và doanh nghiệp.
(2) Tìm kiếm và trao giải cho cặp bài toán và giải pháp xuất sắc cho ngành.
(3) Tìm kiếm và trao giải cho các cặp bài toán và giải pháp xuất sắc cho địa phương.
(4) Tìm kiếm và trao giải cho các cặp bài toán và giải pháp xuất sắc cho doanh nghiệp.
(5) Tìm kiếm và trao giải cho các cặp bài toán và giải pháp xuất sắc cho các dự án về cộng đồng.

Bộ Thông tin và Truyền thông kêu gọi các doanh nghiệp công nghệ hưởng ứng cuộc thi và tham gia giải các bài toán, đặc biệt là các bài toán thuộc hạng mục bộ, ngành và địa phương.

Danh sách các bài toán đã được tổng hợp và đăng tải trên cổng Bài toán chuyển đổi số https://c63.mic.gov.vn/. Đây cũng là hoạt động thiết thực hướng tới hưởng ứng ngày Chuyển đổi số quốc gia (10/10).

Các doanh nghiệp đăng ký tham gia Cuộc thi tại: https://vietsolutions.net.vn.
Thời hạn gửi đăng ký giải pháp: trước ngày 22/9/2022.
Đầu mối liên hệ, hỗ trợ tham gia cuộc thi: Bà Trịnh Thị Trang, Cục Chuyển đổi số quốc gia, số điện thoại: 0383.199.885, email: tttrang@mic.gov.vn.

*Tài liệu đầy đủ về Cuộc thi được tải về tại https://drive.google.com/drive/folders/1Rmx4o0Lal3gpi3B9PdNDHze5TOrRhxNp

Nguồn: http://vdca.org.vn/

[Updated] Bộ câu hỏi phỏng vấn Fullstack Developer hay và khó năm 2024

Câu hỏi phỏng vấn Fullstack Developer

Trở thành lập trình viên fullstack (fullstack developer) từ lâu đã là mục tiêu hướng tới của nhiều bạn lập trình viên, những kì vọng của bạn khi phỏng vấn fullstack developer là gì?, những nội dung nào sẽ được quan tâm khi bạn apply ở vị trí fullstack?

Tất nhiên, chỉ nhìn vào cái title là fullstack thôi cũng đủ để anh em hiểu ta cần nắm vững khối lượng kiến thức cũng phải thuộc dạng “full”, đầy đầy một tí.

meme
Fullstack là đầy đủ cả Frontend, Backend nha anh em. Không chơi một nữa đâu nha

Bắt đầu ngay cho nóng nào.

1. Khối lượng kiến thức chung

Trước khi bắt đầu thử sức với một vài câu hỏi phỏng vấn fullstack developer. Mình muốn list ra đây một số topic cần nhìn lại trước khi bắt đầu tham gia buổi phỏng vấn.

Đầu tiên, expect cơ bản nhất khi phỏng vấn fullstack là đã có kinh nghiệm làm cả Frontend và Backend. Chi tiết từng phần có thể được đào sâu tuỳ theo vị trí yêu cầu.

  • Frontend
  • Backend
  • Intergration

Đi sâu vào kiến thức backend, một số topic có thể là câu hỏi để xác định đúng ứng viên có phải là fullstack developer hay không bao gồm:

  • Database design
  • Xử lý vấn đề query chậm cho cả Frontend và Backend
  • Thiết kế DB adapt với requirement và field từ UI
Ngoài technology, kiến thức và sự hiểu biết sâu về cơ chế cũng là yếu tố quan trọng không kém khi phỏng vấn fullstack developer

Sau đi đã nắm rõ về các topics cần có để tham gia phỏng vấn, cùng tham khảo một số câu hỏi dưới đây. Anh em chú ý là bộ câu hỏi này chỉ là mẫu, các topics có vô vàn các câu hỏi, đòi hỏi người phỏng vấn cần chuẩn bị và có lượng kiến thức tốt trước khi tham gia phỏng vấn.

2. Câu hỏi ví dụ phỏng vấn fullstack level experience

2.1 Callback trong JavaScript có thể được hiểu như thế nào?

Callback trong Javascript là một function được sử dụng như là một đối số cho function khác.

Ngoài ra, có 2 điểm chính cần lưu ý khi nói tới Callback là:

  • Function này có thể gọi tới function khác
  • Callback có thể được gọi sau ở function này sau khi function khác đã kết thúc.

Callback chỉ là một topic nhỏ trong danh sách các câu hỏi phỏng vấn cho fullstack developer.

2.2 GraphQL khác gì so với RestAPI?

Câu này dành cho lập trình viên fullstack đã có kinh nghiệm nên cần nêu bật lên được cái main core của sự khác nhau.

Cốt lõi giữa GraphQLRestAPI nằm ở 4 ý chính, nếu nắm chắc thì trong buổi phỏng vấn chắc chắn sẽ trả lời được.

  • GraphQL đi theo hướng layer server-side (lớp phía server), lúc viết queries thì sẽ thực thi ở server với data đã có sẵn, còn REST thì đi theo hướng tạo kiến trúc với các ràng buộc để phát triển Web services.
  • GraphQL có thể tổ chức theo hướng schema trong khi đó REST được thiết kế để đi theo hướng endpoints.
  • Quá trình phát triển sử dụng GraphQL sẽ nhanh hơn rất nhiều so với REST.
  • Kiểu message trả về với GraphQL mutations luôn là string, trong khi đó với REST thì trả về kiểu gì cũng được.
Phỏng vấn fullstack developer

2.3 Có những cách nào để improve load time cho ứng dụng web (web applications)

Câu hỏi này sử dụng để xác định độ dày về kinh nghiệm của lập trình viên. Người phỏng vấn có thể đi sâu về cách hiện thực hoặc chi tiết để chắc chắn hơn về kinh nghiệm của lập trình viên fullstack.

  • Tối ưu HTTP requests.
  • Sử dụng CDNs và xoá các files/scripts không sử dụng tới.
  • Tối ưu files và nén các hình ảnh.
  • Sử dụng caching.
  • Dùng CSS3 và HTML5.
  • Tối ưu kích thước của JavaScript & Style Sheets.
  • Tối ưu caches.

Trên đây chỉ là một số ý chính có thể nêu ra, chi tiết hơn có thể hỏi tới như: cụ thể cache ở đây là gì, cache redis hay cache CDN hay cache trên browser?.

Loại nào tốt hơn, ví dụ như cache redis thì có lợi gì, lúc nào nên dùng?.

Người phỏng vấn cũng có thể hỏi sâu hơn về các thông số sử dụng để đo tốc độ của website

 

Phỏng vấn fullstack developer
Tối ưu không phải là bài toán dễ để giải quyết

Đào sâu vào kinh nghiệm và cách thức để tối ưu có thể cho ta biết nhiều hơn về một lập trình viên fullstack có nhiều kinh nghiệm.

2.4 Giải thích chi tiết về Observer Pattern

Câu hỏi này đặt nặng về kiến thức Design Pattern của ứng viên, lập trình viên Fullstack luôn mong muốn có skill và hiểu biết tốt về design pattern (vốn là một yếu tố để phân biệt giữa Junior và Senior).

Với câu hỏi này, anh em chỉ cần nhớ main concepts của pattern (mục đích sử dụng, giải quyết được vấn đề gì), chỉ vậy là ok.

The purpose of the Observer pattern is to define a one-to-many dependency between objects, as when an object changes the state, then all its dependents are notified and updated automatically. The object that watches on the state of another object is called the observer, and the object that is being watched is called the subject. Mục đích của Observer pattern là định nghĩa mối liên hệ 1 nhiều giữa các object (sự phụ thuộc). Mỗi khi một object thay đổi trạng thái của nó, nó sẽ thông báo và cập nhật tự động. Lúc này đối tượng theo dõi trạng thái của một đối tượng khác được gọi là người quan sát, và đối tượng đang được theo dõi được gọi là chủ thể (subject).

Phỏng vấn fullstack developer
Những câu hỏi phỏng vấn fullstack developer liên quan tới design pattern thường chú trọng tới sự hiểu biết về concepts.

Nhớ được mục đích và cái core của design pattern sẽ giúp anh em nhớ lâu hơn, áp dụng linh hoạt hơn so với nhớ code khô khan trong đầu. Đi sâu và cụ thể hơn về Observer pattern anh em có thể tham khảo thêm bài viết về Observer Pattern (giải thích cụ thể) ở Kieblog.

2.5 ACID trong database system mang ý nghĩa gì?

  • Chữ A ở đây là Atomicity
  • Chữ C là Consistency
  • Chữ I là Isolation
  • Chữ D là Durability.

Trong các hệ thống cơ sở dữ liệu, ACID đề cập đến một tập hợp các thuộc tính tiêu chuẩn đảm bảo các giao dịch cơ sở dữ liệu được xử lý một cách đáng tin cậy.

Đi vào chi tiết hơn:

  • Atomicity đảm bảo rằng tất cả các câu lệnh thực thi như (read, write, update hoặc delete dữ liệu), một là thực thi tất cả theo transaction, hoặc là không thực thi cái nào). Đảm bảo tính toàn vẹn của dữ liệu
  • Consistency, tính nhất quán. Đảm bảo rằng việc thao tác với dữ liệu trong table luôn được thực hiện theo cách đã được chuẩn bị trước, đảm bảo không có thao tác sai ảnh hưởng tới dữ liệu.
  • Isolation là tính độc lập, khi có nhiều yêu cầu truy xuất hoặc thay đổi dữ liệu, tính độc lập đảm bảo thao tác này không ảnh hưởng tới thao tác khác. Thực hiện tuần tự hoặc ít nhất là đảm bảo tính độc lập của từng thao tác. Cũng góp phần đảm bảo tính độc lập của dữ liệu.
  • Durability là tính bền vững, bền vững ở đây được hiểu là kết quả đã được ở các thực hiện trước đó sẽ luôn được lưu lại cho dù hệ thống bị lỗi

ACID

Mời anh em tham khảo tin tuyển dụng Fullstack Developer mới nhất trên TopDev nhé!

Cảm ơn anh em đã đọc bài – Chúc anh em phỏng vấn đâu pass đó – Happy coding!

Tác giả: Kiên Nguyễn

Xem thêm:

Tìm việc làm IT lương cao, đãi ngộ hấp dẫn trên TopDev!

BÁO CÁO THỊ TRƯỜNG IT VIỆT NAM NĂM 2022: Từng bước thay đổi hướng đến sự phát triển kinh tế lấy nhân tài làm trung tâm

mức lương Lập trình viên Việt 2022

Đến thời điểm hiện tại, chuyển đổi số không còn là câu chuyện mới mẻ. Hơn hết, đây được xem là xu hướng tất yếu cho sự phát triển kinh tế của mỗi quốc gia. Trải qua các đợt bùng phát đại dịch Covid-19, chúng ta đã chứng kiến sự vươn lên bứt phá của lĩnh vực Công nghệ thông tin với hàng loạt những ý tưởng, cải tiến mới. Hai năm đại dịch vừa qua được đánh giá là cú hích trăm năm giúp đẩy nhanh quá trình chuyển đổi số cho Việt Nam và toàn cầu. Sự chuyển dịch nhanh chóng này đã tạo ra nhiều cơ hội cho phần lớn những người hoạt động trong lĩnh vực IT. Đồng thời mang đến nhiều thách thức mới cho thị trường tuyển dụng Công nghệ và cả nền kinh tế nước nhà. 

Đứng trước nhu cầu cạnh tranh từ các doanh nghiệp, vấn đề tuyển dụng nhân lực IT chất lượng ngày càng được chú trọng. Mới đây nhất, TopDev – Nền tảng tuyển dụng IT hàng đầu đã phát hành Báo cáo thị trường IT Việt Nam – Tech Hiring 2022, với những đánh giá và phân tích về vận hội cũng như viễn cảnh của thị trường lao động IT năm 2022. Phát biểu trong báo cáo, ông Park JongHo – CEO | TopDev đã có những nhận định rằng: “Việt Nam đang có một nguồn nhân lực IT đầy hứa hẹn về chất và lượng cũng như thị trường tiềm năng và tăng trưởng kinh tế. Điều quan trọng nằm ở các kế hoạch, chiến lược về đầu tư, phát triển và định hướng cho nguồn lực này nhằm thúc đẩy các mục tiêu kinh tế, xã hội Quốc gia trong bối cảnh toàn cầu hóa. Đây thực sự là một chủ đề lớn và là chặng đường dài cho tất cả chúng ta, nhưng chúng tôi tin rằng SỰ THAY ĐỔI sẽ làm nên những điều lớn lao. Và để tạo ra sự thay đổi, mỗi bên đều có thể đóng góp theo vai trò riêng. Tất cả cho sự phát triển kinh tế lấy nhân tài làm trung tâm.

Bối cảnh Kinh tế – Xã hội và Thị trường IT tại Việt Nam

Vực dậy mạnh mẽ sau những biến động từ các đợt bùng phát đại dịch Covid-19, nền kinh tế tại Việt Nam đã “gặt hái” được những thành quả đáng chú ý. GDP bình quân đầu người trong quý 2/2022 của Việt Nam được ước tính tăng 7,72% so với cùng kỳ năm ngoái, cao hơn tốc độ tăng trưởng của quý 2 trong giai đoạn 2011-2021. Sau 2 năm đại dịch xảy ra, Việt Nam vẫn ghi nhận tổng số vốn mới, được điều chỉnh và mua cổ phần của các nhà đầu tư nước ngoài đạt 31,15 tỷ đô la vào ngày 20 tháng 12 năm 2021, tăng 9,2% so với 2020. Sáu tháng đầu năm 2022, lĩnh vực Công nghệ thông tin và Truyền thông có doanh thu đạt khoảng 77 tỷ USD, tăng 17% so với cùng kỳ năm ngoái, kỳ vọng có sự tăng trưởng trong năm 2022. Đây là những dấu hiệu tích cực cho thấy sự hồi phục nhanh chóng của nền kinh tế nước nhà dù cho phải chịu nhiều ảnh hưởng từ đại dịch. 

Vietnam IT market report - chỉ số kinh tế & xã hội

Thị trường lao động Việt Nam trong quý 2 năm 2022 quay trở lại đà tăng trưởng. Thất nghiệp và thiếu việc làm đều giảm so với giai đoạn dịch bệnh. Tuy nhiên, với tác động đáng kể từ đại dịch và sự thay đổi trong công việc cũng như mô hình lao động, cách thức làm việc truyền thống trước đây đã thay đổi mãi mãi. 

Từ năm 2020, các doanh nghiệp ở Việt Nam đã cho phép nhân viên của họ làm việc tại nhà để ngăn chặn sự lây lan của Covid-19. Từ đó mở ra các xu hướng mới về hình thức làm việc từ xa (Remote Work), mô hình làm việc kết hợp (Hybrid Work) hay mô hình làm việc tự do (Freelance). Đến năm 2025, thế hệ Z dự kiến sẽ chiếm 30% lực lượng lao động tại Việt Nam với những mong đợi về sự cân bằng giữa công việc – cuộc sống và hạnh phúc cá nhân. Điều này càng thúc đẩy các mô hình làm việc kiểu mới mở rộng và phát triển.

 Cơ hội mới đi kèm với những thách thức mới

Sự thay đổi về mô hình làm việc để thích ứng linh hoạt và vực dậy sau đại dịch đã tạo nên những thay đổi trong nhu cầu khi tìm kiếm công việc của người lao động trong lĩnh vực IT. Công việc kết hợp (Hybrid Work) là một mô hình làm việc linh hoạt, mang đến cho nhân viên quyền tự chủ để lựa chọn địa điểm và cách thức làm việc. Hybrid Work sẽ là một phần của mô hình làm việc trong tương lai, nhưng đồng thời đặt ra nhiều vấn đề mới về sự thích nghi và cách thức quản lý & gắn kết tốt hơn. 

Vietnam IT Market report - Mối quan tâm của NTD

Làn sóng đầu tư nước ngoài đã mang đến nhiều cơ hội cho thị trường lao động IT Việt Nam mở rộng và trở nên sôi động hơn bao giờ hết. Việt Nam đã thu hút đủ sự chú ý để đưa các công ty CNTT trong khu vực bắt đầu vào Việt Nam tuyển dụng và xây dựng đội ngũ kỹ sư phát triển sản phẩm. Các doanh nghiệp truyền thống trong các lĩnh vực như du lịch, nông nghiệp, bất động sản… nay đã chuyển đổi số và bước vào mô hình thương mại điện tử. Điều này lại càng tạo nên sức ép cho bài toán khó về thiếu hụt nhân lực CNTT của thị trường, khi nhu cầu tăng lên đáng kể nhưng khả năng đáp ứng còn nhiều hạn chế.

Theo Báo cáo thị trường IT Việt Nam năm 2022 do TopDev phát hành, mức lương lập trình viên dao động từ $350 (Fresher) đến $1.190 cho vị trí Mid-Senior. Lập trình viên Senior có mức lương dao động từ $860 đến $1.510. Các vị trí Quản lý (từ 5 năm trở lên) hoặc cấp cao hơn được khảo sát có mức lương từ $1.410 cho đến hơn $2.300. Theo dự đoán của các báo cáo trước đó, các vị trí được trả lương cao nhất yêu cầu các kỹ năng như Data Analyst, Cloud, DevOps, AI/Machine Learning. Tuy được săn đón với mức lương hấp dẫn, nguồn cung nhân lực trong lĩnh vực CNTT vẫn chưa đáp ứng được nhu cầu và tốc độ phát triển như mong đợi của ngành.

Do ảnh hưởng của Covid-19, số lượng công việc Freelancer dự kiến sẽ tăng từ 5% đến 13%. Hơn nữa, nhu cầu tuyển dụng IT cũng tăng trưởng mạnh mẽ từ các quốc gia trên thế giới và xu hướng tuyển các lập trình viên ở nước ngoài trở nên phổ biến hơn. Điều này dẫn đến việc các lập trình viên ở Việt Nam có nhiều cơ hội lựa chọn hơn và phần nào có mong muốn mức lương và phúc lợi tốt hơn từ các công ty trong nước. 

Mặt khác, làn sóng đầu tư tài chính cá nhân như NFT, Blockchain, chứng khoán đang ngày càng mạnh mẽ. Một số cá nhân có hiểu biết và thích nghi nhanh với xu hướng đã nhanh chóng tạo lập được cơ sở tài chính cá nhân ổn định. Điều này trực tiếp gây ảnh hưởng đến thị trường lao động khi một thành phần lao động tách ra khỏi thị trường và theo đuổi những lĩnh vực này như một công việc chính.

Vietnam IT market report - Thach thuc trong thi truong tuyen dung

Ngoài ra, sau giai đoạn đại dịch, người lao động tự nguyện nghỉ việc, tạo nên làn sóng The Great Resignation. Đối mặt trước những thách thức này, các công ty cần có sự tăng tốc để đáp ứng kịp thời những yêu cầu từ phía nhân tài IT, tập trung vào yếu tố con người, quan tâm đến sức khỏe & tinh thần nhân viên và trải nghiệm ứng viên, đồng thời nỗ lực tạo lợi thế cạnh tranh trên thị trường tuyển dụng Công nghệ trong sắp tới.

Mục tiêu tạo ra những sản phẩm công nghệ “Make In Vietnam” không còn xa

Năm 2021 là một năm đáng nhớ đối với ngành công nghiệp CNTT của Việt Nam khi chuyển đổi kỹ thuật số diễn ra trong tất cả các lĩnh vực, và Công nghệ trở thành một trong những trụ cột của cuộc chiến chống lại Covid-19, cho sự phục hồi và phát triển kinh tế của Việt Nam. Bộ TT&TT đã đặt mục tiêu cho ngành Công nghệ thông tin, Điện tử và Viễn thông với nhiệm vụ “Make In Vietnam” – chuyển dịch mạnh mẽ từ lắp ráp, gia công sang sáng tạo, thiết kế một cách chủ động, để từ đó cho ra đời các sản phẩm công nghệ số Việt Nam.

Theo Báo cáo thị trường IT Việt Nam – Tech Hiring 2022 do TopDev phát hành, Việt Nam đang có một nguồn nhân lực CNTT đầy hứa hẹn về chất và lượng cũng như thị trường tiềm năng và tăng trưởng kinh tế. Đến nay, lập trình viên Việt Nam đang giữ những thứ hạng cao, thuộc Top 6 các quốc gia hàng đầu về dịch vụ gia công phần mềm (2021) theo Xếp hạng về chỉ số vị trí dịch vụ toàn cầu của Kearney. Đồng thời, Việt Nam là một trong hai điểm đến gia công phần mềm hàng đầu ở Đông Nam Á theo Accelerance. Điều này đã cho thấy chất lượng sản phẩm công nghệ đến từ Việt Nam. 

Không dừng lại ở đó, Việt Nam xếp hạng thứ 2 Châu Á Thái Bình Dương và thứ 22 toàn thế giới theo Chỉ số Kỹ năng Toàn cầu (GSI) năm 2020. Chỉ sau Hoa Kỳ, chất lượng Lập trình viên của Việt Nam xếp hạng thứ 2 Thế giới về Khảo sát Freelancer tốt nhất. Hạng 29 trên toàn thế giới trong Bảng xếp hạng kỹ năng dành cho lập trình viên Báo cáo Skill Value 2019. Những thứ hạng trên không chỉ khẳng định sức mạnh tiềm lực của nguồn nhân lực IT Việt Nam mà còn cho thấy tính khả thi cao trong việc tạo ra các sản phẩm trong nước mang hàm lượng công nghệ cao. Nhân tài công nghệ Việt hoàn toàn có thể tạo ra được những sản phẩm “Make In Vietnam”, tạo nên những giá trị lớn lao hơn cho xã hội và quốc gia. Với sự cổ vũ từ phía Chính phủ, đã đến lúc chúng ta trăn trở về giá trị công việc của chính mình, về khả năng cống hiến cho nước nhà cũng như cơ hội phát triển bản thân trong tương lai sắp tới.

Vietnam IT market report - thu hang LTV

Và để tạo ra sự thay đổi, mỗi bên đều có thể đóng góp theo vai trò riêng: các doanh nghiệp nhận thức các thay đổi và thích nghi với các chính sách quản lý hiện đại, các nhân tài công nghệ cần suy nghĩ nhiều hơn về giá trị công việc của mình, cũng như các bên trung gian hỗ trợ và tạo điều kiện tốt hơn.

Tổng kết, TopDev nhận thấy rằng với những cơ hội mới, chân dung Lập trình viên hiện nay đã có rất nhiều sự thay đổi so với trước đây. Tuy nhiên, mỗi sự thay đổi sẽ song hành cùng những thách thức, và ngành Công nghệ vẫn luôn là “mũi nhọn” cho sự phát triển kinh tế Quốc gia, đi đầu đối mặt với thử thách sắp đến. Với sứ mệnh “Make IT Vietnam Better”, TopDev không ngừng nỗ lực củng cố vai trò của mình cũng như tin tưởng rằng sự hợp sức từ các Cấp, Cơ quan, Doanh nghiệp và cả Người lao động sẽ giúp ngành Công nghệ Việt Nam vươn xa, sẵn sàng cạnh tranh với thị trường thế giới.

Báo cáo năm 2022 về thị trường và nhu cầu nhân sự IT do TopDev phát hành đã được đăng tải, độc giả tìm hiểu thêm về xu hướng các ngành Công nghệ trong nước qua bản Vietnam IT Market Report tại đây.

===================

Về TopDev – Đơn vị phát hành Vietnam IT Market Report – Tech Hiring 2022:

Được thành lập từ năm 2015 bởi Applancer JSC, TopDev đã trở thành nền tảng Tuyển dụng CNTT hàng đầu tại Việt Nam với trang web có lượng truy cập lớn tập trung vào CNTT https://topdev.vn (800.000 người truy cập hàng tháng), 350.000+ hồ sơ Lập trình viên & quản lý Cộng đồng Lập trình viên lớn nhất Việt Nam với hơn 550.000 đối tượng IT theo dõi trên mạng xã hội:

  • Đơn vị tiên phong và độc nhất trong lĩnh vực CNTT tại Việt Nam giúp xây dựng và phát triển Thương hiệu Tuyển dụng cho hàng trăm công ty trong nước và quốc tế.
  • Nhà xuất bản uy tín chuyên thực hiện khảo sát, phân tích, dự báo và phát hành báo cáo thường niên về thị trường CNTT & nguồn nhân lực CNTT tại Việt Nam.
  • Đơn vị tổ chức 2 sự kiện công nghệ quy mô lớn nhất Việt Nam: Vietnam Mobile DayVietnam Web Summit.

Chúng tôi mong muốn đem đến giá trị bằng việc: Thúc đẩy nguồn nhân lực IT Việt Nam cả về chất lượng và số lượng thông qua cộng đồng, sự kiện / hoạt động và giáo dục; Kết nối các Lập trình viên với các vị trí tuyển dụng tốt nhất từ các công ty IT đã được xác minh; Cung cấp cho các công ty IT nguồn lập trình viên tốt nhất và xây dựng thương hiệu nhà tuyển dụng lâu dài.

Khám phá các việc làm IT hấp dẫn trên TopDev tại đây.

 

Giới thiệu về StoryBook cho dự án FrontEnd

Giới thiệu về StoryBook cho dự án FrontEnd

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

Storybook là một công cụ thiết kế và phát triển những UI Components cho ứng dụng của bạn trên một môi trường hoàn toàn biệt lập. Storybook mang lại trải nghiệm mới khi thiết kế những UI components tưởng chừng chỉ dừng lại ở khâu design trước khi chuyển sang giai đoạn code Frontend.

Ngày nay khi phát triển một dự án, chúng ta dành rất nhiểu thời gian để xây dựng những UI Components. Hơn hết, chúng ta cần chú trọng làm rành mạch các thuộc tính cũng như hiển thị hết các tính năng cần có (props and states) của những Components này…ngay từ điểm khởi đầu…Không thể phủ nhận đó là cái khó trong một dự án Frontend!

Dựa vào design ta có thể hoàn thiện một Component, hay thậm chí hoàn thành cả một Page. Nhưng bạn có chắc chắn chất lượng code vừa hoàn thiện đã cover toàn bộ các trường hợp? Những người đồng hành có tái sử dụng được hay bạn không viết lại một cái đã có 80% rồi?… Tất cả liệu đã tường minh?…

Storybook đã có ~28k star ở thời điểm này và nó được sử dụng rộng rãi bởi những ông lớn như Airbnb, Coursera, LonelyPlanet. Hãy bắt đầu khai thác lợi ích mà Storybook có thể mang lại.

Hãy lấy ví dụ trực quan, hãy tưởng tượng bạn đối mặt với một trong hai trường hợp sau trong dự án Frontend:

  • Trường hợp lý tưởng: Design đã xong 98%, đã có StyleGuide, gần như các phần core là cố định sẽ không có thay đổi lớn nào.
  • Trường hợp éo le: Design mới chỉ hoàn thành 60%, dự án lên kế hoạch làm những phần chính Frontend song song với design, vừa làm vừa cập nhật.

Trường hợp éo le, bạn hoàn toàn có lý do để chia nhau ra code những page đã hoàn thành trước, làm được gì hay được đó, đơn giản vì chưa có StyleGuide cover toàn bộ dự án. Nhưng thực tế là dù có được đưa vào trường hợp lý tưởng, chúng ta cũng bỏ qua bước thiết kế từng Component mà thường bắt tay ngay vào từng page cụ thể, và chỉ xem StyleGuide như một tài liệu tham khảo, người trước làm chưa đủ thì người sau xem lại và bổ sung.

Storybook sẽ là một lời giải cho bài toán này

  • Chúng ta sẽ gọi các UI Components vừa thực hiện ra và gán cho nó một ‘câu chuyện’ – Đó chính là hiển thị toàn bộ các props và state. Bất cứ ai khi viết xong Components của mình đều có thể tạo ra câu chuyện của mình được, hoàn toàn không conflict.
  • Những câu chuyện này hiển thị đầy đủ và độc lập – Storybook chạy ở một port riêng, có thể chạy song song với dự án. Việc này giúp ích chúng ta rất nhiều khi chỉnh sửa và theo dõi trạng thái của các elements, rất trực quan và nhanh chóng.

Bạn có thể tham khảo 1 số storybook dưới đây:

  • Coursera: https://building.coursera.org/coursera-ui/
  • GumGum: http://gumdrops.gumgum.com/index.html

Xem ngay các tin đăng tuyển dụng Front-end lương cao trên TopDev

Ví dụ sử dụng Storybook

Chúng ta cùng thử triển khai 1 storybook với ví dụ dưới đây:

import React from 'react'
import MainSection from '../MainSection'
import { storiesOf } from '@storybook/react'
import { action } from '@storybook/addon-actions'

storiesOf('MainSection', module)
  .add('all active', () => {
    const todoItems = [
      { id: 'one', text: 'Item One', completed: false },
      { id: 'two', text: 'Item Two', completed: false },
    ];

    return getMainSection(todoItems)
  })
  .add('some completed', () => {
    const todoItems = [
      { id: 'one', text: 'Item One', completed: false },
      { id: 'two', text: 'Item Two', completed: true },
    ];

    return getMainSection(todoItems)
  })
  .add('all completed', () => {
    const todoItems = [
      { id: 'one', text: 'Item One', completed: true },
      { id: 'two', text: 'Item Two', completed: true },
    ];

    return getMainSection(todoItems)
  });

function getMainSection(todos) {
  const actions = {
    clearCompleted: action('clearCompleted'),
    completeAll: action('completeAll')
  };

  return (
    <div className="todoapp">
      <MainSection todos={todos} actions={actions} />
    </div>
  )
}

Thực hiện lệnh chạy storybook: npm run storybook ta được kết quả

Ưu điểm của Storybook

Storybook sẽ là một trợ lực đáng giá từ những ngày dự án còn trong trứng nước với những features được khẳng định:

  • Được build với những lib/framework lớn đương đại: Angular, React, Vue.
  • Môi trường phát triển cho từng Component riêng biệt, tách rời, base trên rất nhiều iframe. Giao diện đơn giản, thống nhất, dễ tiếp cận.
  • Suport HMR, bất kể Component của bạn là gì.
  • Chạy bên trong dự án của bạn và có thể sử dụng server static.
  • Extendable với đa dạng plugin (phong phú và chi tiết cho stories của bạn, cũng như có thể đặt hoàn cảnh test…)

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

Xem thêm:

Tham khảo ngay việc làm IT mọi cấp độ trên TopDev!

The Merge – Bước tiến quan trọng của blockchain Ethereum

The Merge – bước tiến quan trọng của blockchain Ethereum

The Merge, một sự kiện rất được chờ đợi đối với blockchain Ethereum và số đông nhà đầu tư cũng như nhà phát triển ứng dụng đang làm việc trên mạng lưới này. Trên trang chủ của mình, Ethereum đã đưa ra deadline cho The Merge vào ngày 19/9/2022, và trên khắp các sàn giao dịch ETH cũng thông báo về sự kiện cũng như việc tạm ngưng các giao dịch liên quan. Vậy The Merge là gì? Tác động của nó đến thị trường tiền mã hóa, blockchain như thế nào? – Bài viết này mình sẽ cùng các bạn đi tìm hiểu về nó nhé.

The Merge là gì?

The Merge hay Ethereum Merge là sự kiện nâng cấp của blockchain Ethereum khi chuyển từ cơ chế đồng thuận POW (Proof-of-Work) sang POS (Proof-of-Stake) và cho ra đời chuỗi Ethereum 2.0 là sự hợp nhất giữa chuỗi Ethereum hiện tại và chuỗi Beacon.

the merge là gì

Nguồn: ethereum.org

The Merge là 1 bước đột phá trong hành trình phát triển của hệ sinh thái blockchain Ethereum với những cải tiến trong công nghệ giúp giảm bớt tài nguyên sử dụng, có khả năng vận hành nhanh và dễ dàng mở rộng hơn, đồng thời vẫn giữ được khả năng bảo mật của nó.

Sự ra đời của ETH 2.0

Trước đây ETH vận hành theo cơ chế PoW với việc các thợ đào coin sẽ dùng sức mạnh của máy đào để giải các bài toán tạo ra mã hash. Sau khi giải xong thì họ sẽ giành được quyền xác thực giao dịch và tạo khối mới trong blockchain (hay nói cách khác là sở hữu coin ETH đó). Nhược điểm của hệ thống PoW chính là hiệu suất đào thấp, chi phí giao dịch cao khiến khả năng mở rộng và tính bảo mật kém của mạng lưới ETH.

Để giải quyết bài toán trên, cha đẻ của mạng Ethereum Vitalik Buterin cùng đội ngũ của ông đã nghiên cứu trong suốt 7 năm để đưa ra cơ chế PoS dành cho việc ra đời ETH 2.0. PoS hoạt động sẽ không có các thợ đào coin như PoW mà thay vào đó, những người tham gia xác thực giao dịch sẽ giải đặt cược lượng coin lớn để giành quyền xác thực giao dịch và tạo khối. Nhờ thế mà PoS không yêu cầu đầu tư phần cứng cho máy đào mà vẫn đảm bảo được hiệu suất cao.

eth 2.0

Nguồn: miro.medium.com

The Merge là sự kiện thuộc phase 1.5 trong quá trình hình thành lên Ethereum 2.0. Trước đó ở phase 0 và phase 1, các thử nghiệm cơ chế Pos trên mạng dưới blockchain này đã được tiến hành và hoàn thiện. Sau khi sự kiện The Merge xảy ra thì các cải tiến liên quan trực tiếp đến tài khoản, giao dịch và hợp đồng thông minh của blockchain này sẽ được áp dụng.

Tham khảo việc làm Blockchain mới nhất tại đây!

Những tác động sau sự kiện The Merge

Ethereum hiện nay đang là blockchain lớn thứ hai chỉ sau Bitcoin và cũng là cơ sở hạ tầng cho rất nhiều ứng dụng quan trọng, chính vì thế mà sự kiện The Merge chắc chắn sẽ có tác động lớn đến Ethereum nói riêng và cả thị trường tiền mã hóa nói chung.

  • Tác động đến Ethereum: Việc chuyển đổi cơ chế sang PoS hứa hẹn mang tới sự ổn định cho ETH và các dự án được xây dựng trên nền tảng này khi mà chi phí cũng như tốc độ được cải thiện đáng kể. 
  • Tác động đến môi trường: Sự cải tiến sau The Merge giúp cắt giảm mức sử dụng năng lượng của Ethereum tới 99,95%, điều đó giúp các công ty lớn có thể yên tâm đầu tư vào ETH mà không cần phải lo ngại các vấn đề về môi trường hay việc giảm lượng khí thải CO2 đồng thời thay đổi cái nhìn của công chúng về tiền mã hóa nói riêng và blockchain nói chung.
  • Tác động đến thị trường: bản thân đồng coin ETH được dự báo sẽ tăng trưởng mạnh mẽ khi triển khai hệ thống PoS, nhu cầu dự trữ ETH để có thể Stake và trở thành một Validator của mạng lưới Ethereum tăng sẽ giúp cho giá trị của ETH tăng trưởng. Về dài hạn, nếu chuỗi Ethereum 2.0 có thể hoạt động ổn định sẽ giúp ETH có thể đáp ứng nhu cầu xanh và nhanh của những tổ chức lớn trên toàn cầu đang đề ra. Xét chung về toàn bộ thị trường Crypto, nếu The Merge diễn ra thành công sẽ thúc đẩy các quỹ đầu tư lớn và các tập đoàn công nghệ tham gia vào giúp thị trường có thể tăng trưởng bền vững.
  • Tác động lên các thợ đào: sau The Merge thì các thợ đào sẽ không thể tham gia vào quá trình mining ra ETH qua các máy đào được nữa, hàng loạt máy đào có thể phải “đắp chiếu”. Đang có kiến nghị về một đợt Hard Fork ETH thành 2 mạng để duy trì việc khai thác ETH thông qua việc đào coin, tuy nhiên không có gì đảm bảo các token từ đợt Hard Fork sẽ có giá trị trong tương lai.

Kết bài

Sự kiện The Merge sẽ là một nhân tố ảnh hưởng lớn đến thị trường trong thời gian tới cho dù nó thành công hay thất bại. Cả thị trường Crypto nói riêng cũng như blockchain nói chung đang trông đợi sự thành công từ sự kiện này để có thể tạo ra một bước tiến quan trọng trong quá trình phát triển của công nghệ này. Hy vọng bài viết này đã đem lại cho các bạn những thông tin hữu ích về sự kiện này, hẹn gặp lại các bạn trong các bài viết tiếp theo của mình.

Tác giả: Phạm Minh Khoa

Xem thêm:

Top Developer đừng bỏ lỡ Top việc làm IT mới nhất trên TopDev!

Cơ bản về GraphQL trong Java

GraphQL trong Java

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

Trong bài viết Giới thiệu về GraphQL, mình đã giới thiệu với các bạn sơ qua về cách xây dựng một GraphQL server sử dụng Spring Boot. Về bản chất thì Spring Boot đã sử dụng thư viện GraphQL Java và wrap tất cả mọi thứ behind the scenes liên quan đến việc xử lý một câu query của GraphQL của thư viện này rồi. Trong bài viết này, mình sẽ trình bày với các bạn một số kiến thức cơ bản về GraphQL và cách mà thư viện GraphQL Java xử lý một câu query như thế nào các bạn nhé!

Đầu tiên, mình sẽ tạo mới một Maven project để làm ví dụ:

Maven project

GraphQL Java dependency như sau:

Nói về GraphQL, như mình đã đề cập trong bài viết trước, chúng ta phải nói về các type. Ngoài các type định nghĩa cho các đối tượng data mà chúng ta sẽ provide cho client, ví dụ như:

type Student {
  id: ID
  code: String
  name: String
  age: Int
  address: String
  clazz: String
}

GraphQL còn có 3 type đặc biệt là Query, Mutation và Subscription. Trong mỗi type, chúng ta sẽ định nghĩa các fields, và trong mỗi field, chúng ta sẽ có các sub-fields. Để định nghĩa kiểu dữ liệu cho các fields hay sub-fields, các bạn có thể sử dụng các built-in scalar types (https://graphql.org/learn/schema/#scalar-types), định nghĩa enum types (https://graphql.org/learn/schema/#enumeration-types) hoặc định nghĩa các object types như ví dụ ở trên.

Chúng ta có thể định nghĩa một field là non-null sử dụng dấu chấm than, được khai báo phía sau kiểu dữ liệu của field hoặc sub-field, ví dụ như:

type Student {
  id: ID!
  code: String!
  name: String!
  age: Int
  address: String
  clazz: String
}

Sub-fields id, code và name của type Student trên là non-null nha các bạn!

Chúng ta sẽ định nghĩa giá trị của field, sub-field là list sử dụng 2 dấu ngoặc vuông như sau:

type Student {
  id: ID
  code: String
  name: String
}

type Clazz {
  id: ID
  name: String
  students: [Student]
}

GraphQL hỗ trợ nhiều ngôn ngữ lập trình khác nhau https://graphql.org/code/ nên tuỳ nhu cầu thì các bạn có thể sử dụng cho phù hợp. Cho Java, thì như mình đã nói ở trên, chúng ta sử dụng GraphQL Java https://github.com/graphql-java/graphql-java.

Ứng tuyển các vị trí việc làm Java lương cao trên TopDev

Bây giờ, mình sẽ làm một ví dụ để xem cách hoạt động của GraphQL Java hoạt động như thế nào các bạn nhé!

Mình sẽ tạo mới một main class để chạy ứng dụng:

package com.huongdanjava.graphql; public class Application {     public static void main(String[] args) {    } }

Bây giờ, mình sẽ định nghĩa một schema sử dụng type Query với nội dung đơn giản như sau:

String schema = """
        type Query {
            hello: String
        }
        """;

Với schema này, mình đã định nghĩa một field đơn giản là “hello”, data trả về sẽ có kiểu dữ liệu là String.

Chúng ta sẽ sử dụng đối tượng của class SchemaParser và TypeDefinitionRegistry của GraphQL Java để đọc nội dung của schema này:

SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry typeDefinitionRegistry = schemaParser.parse(schema);

Class TypeDefinitionRegistry sẽ nắm giữ thông tin tất cả các type được định nghĩa trong tập tin schema.

Để handle cho từng request tới các type này, chúng ta sẽ sử dụng đối tượng của class RuntimeWiring. Chúng ta sẽ khởi tạo mới đối tượng RuntimeWiring và ứng với mỗi GraphQL type, chúng ta sẽ process cho từng field như sau:

RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
    .type("Query", builder -> builder.dataFetcher("hello", new StaticDataFetcher("world")))
    .build();

Như các bạn thấy, cho Query type trong ví dụ của mình, chúng ta sẽ sử dụng đối tượng TypeRuntimeWiring để handle data trả về. StaticDataFetcher implement interface DataFetcher sẽ đảm nhận data được trả về là gì. DataFetcher interface có nhiều implementation khác nhau:

Tuỳ theo nhu cầu của mình, các bạn hãy sử dụng implementation cho phù hợp nhé! Ở đây, mình sử dụng SimpleDataFetcher để trả về value mà mình khai báo khi khởi tạo đối tượng này.

Sau khi đã có đối tượng TypeDefinitionRegistry và RuntimeWiring, chúng ta cần combine chúng lại sử dụng để GraphQL engine có thể sử dụng và thực thi query cho các bạn:

SchemaGenerator schemaGenerator = new SchemaGenerator();
GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeDefinitionRegistry, runtimeWiring);

Class GraphQLSchema sẽ chứa thông tin về query và cách mà ứng dụng GraphQL của chúng ta sẽ trả kết quả về.

Bây giờ là lúc GraphQL engine sẽ thực thi query cho chúng ta:

GraphQL build = GraphQL.newGraphQL(graphQLSchema).build();
ExecutionResult executionResult = build.execute("{hello}");

System.out.println(executionResult.getData().toString());

Như các bạn thấy chúng ta sẽ sử dụng đối tượng của class GraphQL được khởi tạo từ đối tượng GraphQLSchema để thực thi câu GraphQL, kết quả sẽ như sau:

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

Xem thêm:

Việc làm IT mọi cấp độ mới nhất trên TopDev

Những câu hỏi phỏng vấn React thường gặp

câu hỏi phỏng vấn react

React là thư viện front-end được rất nhiều công ty sử dụng hiện nay, nhu cầu tuyển dụng cho vị trí này cũng rất lớn. Nếu bạn đang chuẩn bị tham gia vào những cuộc phỏng vấn cho vị trí lập trình viên React thì bài viết này là dành cho bạn. Đây là tổng hợp những câu hỏi phỏng vấn React thường gặp nhất từ cơ bản đến nâng cao sẽ giúp bạn tự tin hơn cho cuộc phỏng vấn sắp tới của mình.

React là gì? Những tính năng chính của React.

React là một thư viện mã nguồn mở viết bằng ngôn ngữ JavaScript (JS), được Facebook phát triển từ hơn 10 năm nay. Nó được xây dựng bằng cách tiếp cận theo hướng dựa trên thành phần (component-based) giúp có thể dễ dàng tái sử dụng lại các phần UI/UX trên các màn hình khác nhau.

React thích hợp cho việc tạo ra các ứng dụng một trang (Single Page App) dành cho cả web và thiết bị di động, vì thế hiện nay có rất nhiều các công ty lựa chọn React làm thư viện để phát triển các ứng dụng của mình.

Các tính năng chính của React bao gồm:

  • Sử dụng DOM ảo (VirtualDOM) để quản lý sự thay đổi và cập nhật trạng thái của các đối tượng trên DOM thật. VirtualDOM sẽ xác nhận những thành phần cần phải cập nhật và thực hiện việc render lại thành phần đó trên DOM thật thay vì cập nhật lại tất cả cùng một lúc, từ đó giúp hiệu năng của các ứng dụng React trở nên tốt hơn.
  • Component-Based: với React thì tất cả đều được tạo nên từ components (thành phần). Một trang web phức tạp như Facebook cũng được tạo nên từ hàng nghìn components độc lập, dễ dàng tái sử dụng hay chỉnh sửa mà không ảnh hưởng đến các thành phần khác.
  • Liên kết dữ liệu một chiều: khi thiết kế ứng dụng React, các component con sẽ được lồng trong component cha, dữ liệu sẽ được truyền từ cha xuống con theo một chiều nhanh chóng và thống nhất

Sự khác nhau giữa ReactJs và React Native.

React Native được team phát triển Facebook ra mắt 2 năm sau khi ra mắt ReactJs, nó được dùng để phát triển các ứng dụng dành cho mobile (không phải chạy trên nền web). React Native và ReactJs có chung nguyên lý phát triển, ngôn ngữ sử dụng, các đặc trưng của React vì thế nên có thể dễ dàng học và sử dụng cả hai nền tảng này cùng lúc. 

Điểm khác nhau ở đây là trong khi React Native là một framework hoàn chỉnh có thể giao tiếp với native API để build ra các ứng dụng chạy trên nền tảng di động như Android hay iOS; thì ReactJs vốn dĩ chỉ là một thư viện UI dành cho web, nó cần thêm một số các thư viện khác giúp cho việc build, setup môi trường thì mới có thể tạo ra được một ứng dụng hoàn chỉnh. Một điểm khác nhau nữa trong cách viết code đó là việc React Native không sử dụng HTML vì nó không phải viết để chạy trên web như ReactJs, thay vào đó nó cung cấp cho các lập trình viên các component hoạt động tương tự (hầu hết là được biến đổi từ các phần tử tương đương trong HTML).

Phân biệt khái niệm Component và Element trong React

Khái niệm React Element dùng để chỉ những gì được hiển thị lên màn hình như một nút bấm (button), một ô nhập liệu (input) hay cả một modal đăng nhập. Một Element có thể chứa nhiều elements khác, giống như trên modal đăng nhập thì có thể chứa ô input nhập usernam và password cùng với cả button thực hiện đăng nhập.

Trong source code, để tạo ra được React Element thì chúng ta sẽ sử dụng một function hoặc class để render ra nó, và phần function hay class đó được gọi là React Component.

React cung cấp function tạo ra Element như sau:

const Button = ({ onLogin }) => React.createElement(
  'div',
  { id: 'login-btn', onClick: onLogin },
  'Login'
)

Trong đoạn code trên Button là một React Component và sẽ thực hiện việc render ra màn hình một Element là thẻ div với các thuộc tính như id hay onClick được truyền vào.

Lifecycle của component trong React

Lifecycle (vòng đời) của một component trong React có 3 giai đoạn:

  • Mounting: giai đoạn khởi tạo – khi component đã sẵn sàng để gắn kết trong DOM của trình duyệt để hiển thị lên cho người dùng.
  • Updating: giai đoạn component được cập nhật – để cập nhật component thì chúng ta có thể truyền props mới đến component hoặc set lại local state bên trong component đó. Sau khi component render lại thì cây DOM vị trí chứa component cũng sẽ được hiển thị với các giá trị mới để người dùng nhìn thấy.
  • Unmounting: giai đoạn component bị ngắt kết nối, bỏ ra khỏi cây DOM của trình duyệt. Đây cũng là giai đoạn cuối trong vòng đời của component. Từ lúc này component sẽ không thể được truy cập hay tác động nữa trừ khi nó được mouting và bắt đầu mộ lifecycle mới.

Với class component, React cung cấp cho chúng ta các lifecycle method như componentDidMount, componentDidUpdate, componentWillReceiveProps, componentWillUnMount để quản lý các sự kiện xảy ra ở từng giai đoạn trong vòng đời của nó. Còn trong functional component, React cung cấp Hook useEffect cho việc xử lý này. Ví dụ bài toán muốn call API lấy dữ liệu về khi vào màn hình, chúng ta có thể xử lý như sau:

  • Với class component:
componentDidMount() {
    fetchApi(); //thực hiện call api
}
  • Với functional component:
useEffect(() => {
    fetchApi(); //thực hiện call api

}, []);

Higher-Order Components là gì?

Higher-Order Component (HOC) là một kỹ thuật nâng cao trong React được sử dụng cho mục đích tái sử dụng logic của Component. HOC bản chất là một function nhận tham số đầu vào gồm 1 Component và các logic được tái sử dụng để tạo ra được một Component mới. HOCs là 1 pattern rất quan trọng giúp React trở nên hữu ích hơn rất nhiều khi ngoài việc tái sử dụng phần UI, giờ chúng ta có thể tái sử dụng được cả phần logic code.

HOCs rất phổ biến trong các thư viện bên thứ ba hay được sử dụng cùng với React như Redux – một thư viện giúp quản lý các global state trong ứng dụng.

Redux là gì? Tại sao phải sử dụng Redux trong ứng dụng React

Redux là 1 công cụ giúp quản lý các biến global state trong ứng dụng React hay các thư viện JavaScript nào khác. Khi ứng dụng của chúng ta trở nên lớn hơn với hàng trăm hay hàng nghìn components thì việc chia sẻ dữ liệu giữa các Components với nhau cũng trở nên phức tạp hơn. Redux tạo ra 1 store lưu trữ dữ liệu của ứng dụng vào một nơi duy nhất, sau đó bằng cách connect đến store thì Component của chúng ta có thể lấy ra để sử dụng hoặc cập nhật để thay đổi giá trị biến.

3 thành phần cơ bản trong Redux gồm:

  • Store: Nơi giữ các biến trạng thái của ứng dụng, với mô hình Redux thì sẽ chỉ tồn tại một store duy nhất
  • Actions: các sự kiện được gửi đến để cập nhật dữ liệu các biến trong store của Redux
  • Reducers: là các function để lấy ra giá trị (trạng thái) của các biến trong store

React Hook là gì? Bạn đã từng viết custom Hook nào chưa?

Hooks là những function cho phép bạn sử dụng các biến state và các hàm liên quan đến lifecycle ở trong các functional Components. Hooks giúp giảm lượng code thừa khi phải triển khai lại các logic có thể dùng chung ở nhiều components khác nhau mà cần liên quan đến local state. React cung cấp sẵn cho chúng ta một số các hook hữu ích: useState, useEffect, useContext, useMemo, ….

Chúng ta cũng có thể tự viết những custom Hook riêng cho mình như ví dụ dưới đây: useWindowSize là 1 hook có tác dụng lấy kích thước của khung trình duyệt web hiện tại.

import { useState, useEffect } from 'react' export const useWindowSize = () => {   const [windowSize, setWindowSize] = useState({     width: window.innerWidth,     height: window.innerHeight,   })   useEffect(() => {     const handler = () => {       setWindowSize({           width: window.innerWidth,           height: window.innerHeight,       })     }     window.addEventListener('resize', handler)     return () => {         window.removeEventListener('resize', handler)     }   }, [])   return windowSize }

Có những cách nào để styling trong React

Có vài cách để thiết lâp CSS cho các component trong React như sau:

  • Inline Styling: khai báo trực tiếp CSS vào thuộc tính style trong code JS
<h1 style={{color: "blue"}}>Hello world! </h1>
  • CSS module: tạo file .css riêng và import vào component
//content.css
.content {
  color: blue;
}
//content.js
import styles from './content.css';
<h1 className={styles.content}>Hello world!</h1>
  • Sử dụng thư viện styled-components tạo ra 1 component mới kèm css
const Content = styled.h1({
  color: blue,
});

Tổng kết

Trên đây là tổng hợp của mình về một số câu hỏi hay gặp nhất khi các bạn tham gia phỏng vấn cho vị trí lập trình viên React. Hy vọng bài viết đã giúp các bạn có thể tư tin hơn và đạt được kết quả tốt nhất cho đợt tuyển dụng sắp tới. Hẹn gặp lại các bạn trong các bài viết tiếp theo của mình.

Tác giả: Phạm Minh Khoa

Xem thêm:

Đừng bỏ lỡ việc làm IT mới nhất trên TopDev!

Dựng mạng VPN với WireGuard

dựng mạng VPN với wireguard

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

Tiếp nối bài trước, Câu chuyện sử dụng VPN, tôi xin mô tả cách dựng một mạng VPN cho mục đích cá nhân bằng phần mềm WireGuard.

Mục đích sử dụng mạng VPN của tôi chỉ là để truy cập từ xa vào các thiết bị IoT của tôi nên mô hình VPN của tôi chỉ phù hợp với nhu cầu đó. Nếu bạn cần dùng VPN cho mục đích khác, ví dụ để vượt tường lửa, truy cập vào website bị chặn, thì bạn không nên trông đợi gì vào bài viết này.

Trước khi bắt tay vào việc, ta cần mường tượng sơ đồ mạng sẽ như thế nào:

Sơ đồ

Phải luôn có một máy có địa chỉ IP tĩnh làm server. Nó cũng đóng vai trò router trong mạng ảo (VPN) được tạo ra. Các gói tin từ máy con A sẽ được mã hóa, gửi lên server, server sẽ chuyển tiếp tới máy con B rồi gói tin được giải mã tại đó.

Ta sẽ chọn dải IP cho mạng ảo này. Ví dụ tôi chọn dải 192.168.2.0/24. Trong thực tế, ta cần chọn dải nào sao cho không đụng chạm đến bất cứ mạng LAN thật nào của từng máy con. Vì server đóng vai trò router nên ta sẽ dành địa chỉ 192.168.2.1 cho nó.

Cài đặt WireGuard

Việc cài đặt WireGuard thì khá đơn giản, đã có trên tài liệu. Trước khi cài WireGuard thì bạn phải cài trước header source code của Linux. Chuyện này khá đơn giản trên desktop và server, vì câu lệnh để cài WireGuard, sudo apt install wireguard sẽ tự kéo gói header của Linux về, tự cài. Nhưng trên máy tính nhúng như BeagleBone, Raspberry Pi, bạn phải tự chỉ định và cài gói header đó.

Trên Raspberry Pi, tên gói là raspberrypi-kernel-headers, nên bạn cài bằng:

sudo apt install raspberrypi-kernel-headers

Trên BeagleBone thì phức tạp hơn. Đầu tiên bạn phải xác định xem BeagleBone của bạn đang chạy Linux phiên bản nào:

$ uname -a
Linux beaglebone 4.4.88-ti-r125 #1 SMP Thu Sep 21 19:23:24 UTC 2017 armv7l GNU/Linux

Tìm kiếm gói header theo tên linux-headers-[version]:

$ apt search linux-headers-4.4.88-ti-r125
Sorting... Done
Full Text Search... Done
linux-headers-4.4.88-ti-r125/unknown,now 1stretch armhf
  Linux kernel headers for 4.4.88-ti-r125 on armhf

Ok, vậy là gói linux-headers-4.4.88-ti-r125 có tồn tại trong repo, hãy cài đặt nó:

sudo apt install linux-headers-4.4.88-ti-r125

Trong trường hợp bạn cấu hình APT repo cho Raspberry Pi, bạn có thể gặp lỗi này:

$ sudo apt update
Get:1 http://raspbian.raspberrypi.org/raspbian stretch InRelease [15.0 kB]
Get:2 http://deb.debian.org/debian unstable InRelease [233 kB]                                     
Hit:3 http://archive.raspberrypi.org/debian stretch InRelease   
Get:4 http://raspbian.raspberrypi.org/raspbian stretch/main armhf Packages [11.7 MB]
Err:2 http://deb.debian.org/debian unstable InRelease          
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8B48AD6246925553 NO_PUBKEY 7638D0442B90D010 NO_PUBKEY 04EE7237B7D453EC
Reading package lists... Done                                                                                                                  
W: GPG error: http://deb.debian.org/debian unstable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8B48AD6246925553 NO_PUBKEY 7638D0442B90D010 NO_PUBKEY 04EE7237B7D453EC
E: The repository 'http://deb.debian.org/debian unstable InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.

Có thể khắc phục bằng cách chạy lệnh sau:

$ sudo apt install dirmngr
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 04EE7237B7D453EC

Cấu hình cho WireGuard

Vì server sẽ đóng vai trò router, ta cần cấu hình kernel của server để cho phép “IPv4 forwarding”:

$ echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-ipv4_forwarding.conf
$ sudo sysctl -p /etc/sysctl.d/99-ipv4_forwarding.conf

Trên từng máy, ta làm theo hướng dẫn trên trang chủ để tạo key. Các file sinh ra privatekeypublickey nằm đâu cũng được, vì sau khi cấu hình xong ta có thể xóa nó đi.

Trên máy con A, ta tạo file /etc/wireguard/wg0.conf với nội dung như sau:

[Interface]
PrivateKey = private_key_cua_may_A
Address = 192.168.2.2/24

[Peer]
PublicKey = public_key_cua_server
Endpoint = ip_cua_server:51820
AllowedIPs = 192.168.2.0/24

Trên máy con B, ta tạo file tương tự, với nội dung như sau:

[Interface]
PrivateKey = private_key_cua_may_B
Address = 192.168.2.3/24

[Peer]
PublicKey = public_key_cua_server
Endpoint = ip_cua_server:51820
AllowedIPs = 192.168.2.0/24

Trên server, ta tạo file ở đường dẫn giống vậy, với nội dung như sau:

[Interface]
Address = 192.168.2.1/24
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o ens18 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens18 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o ens18 -j MASQUERADE
ListenPort = 51820
PrivateKey = private_key_cua_server

[Peer]
# May A
PublicKey = public_key_cua_may_A
AllowedIPs = 192.168.2.2/32

[Peer]
# May B
PublicKey = public_key_cua_may_B
AllowedIPs = 192.168.2.3/32

Lưu ý sự khác nhau giữa các file trên:

  • File cấu hình trên máy con thì chỉ cần 1 mục [Peer] để điền thông tin của server.
  • File cấu hình trên server thì có nhiều mục [Peer], mỗi cái tương ứng với một máy con.
  • Vì server đóng vai trò router nên ta có một chùm cấu hình iptables kèm theo. Trong các dòng iptables này, bạn cần thay ens18 bằng tên card mạng trên server của bạn (xem danh sách card mạng bằng lệnh ip link hay ngắn gọn hơn, ip l).

Một vài lưu ý khác:

  • Đừng bao giờ xài AllowedIPs = 0.0.0.0/0 trên file cấu hình của client (máy con), như một số bài hướng dẫn khác trên mạng, nếu không chức năng DNS sẽ tê liệt.

Tham khảo việc làm lập trình nhúng mới nhất tại đây!

Kiểm tra

Sau khi ghi các file cấu hình kể trên, thử chạy

$ sudo wg-quick up wg0
$ ip a

để xem đã có network interface nào tên wg0 được tạo ra và gán địa chỉ chưa.

Ví dụ, đây là kết quả trên máy tôi:

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eno1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether a0:2b:b8:24:0b:55 brd ff:ff:ff:ff:ff:ff
3: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 9c:d2:1e:7d:f7:e7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.88/24 brd 192.168.1.255 scope global dynamic noprefixroute wlo1
       valid_lft 79700sec preferred_lft 79700sec
    inet6 2001:ee0:5511:860:a8c1:937b:b26:8095/64 scope global temporary dynamic 
       valid_lft 1198sec preferred_lft 1198sec
    inet6 2001:ee0:5511:860:64ca:7ee4:ac78:5940/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 1198sec preferred_lft 1198sec
    inet6 fe80::236c:9478:b305:1c05/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 192.168.2.2/24 scope global wg0
       valid_lft forever preferred_lft forever

Bảng route:

$ ip r                                                                                                                            
default via 192.168.1.1 dev wlo1 proto dhcp metric 600 
169.254.0.0/16 dev wlo1 scope link metric 1000 
192.168.1.0/24 dev wlo1 proto kernel scope link src 192.168.1.88 metric 600 
192.168.2.0/24 dev wg0 proto kernel scope link src 192.168.2.2

Trên các máy con, thử ping về server bằng địa chỉ của mạng VPN:

ping 192.168.2.1

Trên máy con A, thử ping đến máy con B bằng địa chỉ của mạng VPN:

ping 192.168.2.3

Nếu việc ping thành công thì chúc mừng, bạn đã hoàn tất 95%.

Duy trì mạng VPN

Vì mạng VPN chỉ được tạo ra bằng lệnh wg-quick up, nên sau khi bạn khởi động lại máy, mạng sẽ biến mất. WireGuard có cung cấp file systemd service để máy tự chạy wq-quick up mỗi lần khởi động. Kích hoạt service này trên server bằng lệnh:

sudo systemctl enable wg-quick@wg0

Trong trường hợp của tôi, tôi cần truy cập từ laptop (máy A) vào board Raspberry Pi (máy B) nên tôi cũng cần kích hoạt service kia trên máy B. Riêng laptop thì không cần.

Làm được tới đây, nếu bạn khởi động lại máy B, bạn sẽ không ping được từ A vào B, cho dù wg0 vẫn đang hoạt động trên máy B và trên server. Tại sao? Đó là vì khi gói tin từ A lên server, server không biết máy B ở đâu để mà chuyển tiếp đến (nên nhớ là máy B đang nằm khuất sau 1 router nào đó nên nó không có địa chỉ IP public). Muốn server biết máy B ở đâu thì phải có 1 sự tương tác giữa máy B và server. Ta phải duy trì sự tương tác này để vị trí của máy B luôn được cập nhật. Để làm việc này, ta thêm tùy chọn PersistentKeepalive vào file của máy B như sau:

[Interface]
PrivateKey = private_key_cua_may_B
Address = 192.168.2.3/24

[Peer]
PublicKey = public_key_cua_server
Endpoint = ip_cua_server:51820
AllowedIPs = 192.168.2.0/24
PersistentKeepalive = 60

Thông số trên có nghĩa là cứ 60s, WireGuard trên máy B sẽ gửi một gói tin đặc biệt đến server để duy trì kết nối VPN.

Phụ chú

Trước đây, khi tôi chưa biết đến tham số PersistentKeepalive thì giải pháp của tôi là làm cho máy B cứ tự động ping đến server sau mỗi khoảng thời gian nhất định. Tôi sẽ ứng dụng systemd timer để làm việc này.

Tạo 2 file như sau trên máy B:

ping-wireguard-server.service:

[Unit]
Description=Ping WireGuard server

[Service]
Type=oneshot
ExecStart=/bin/ping -c 2 192.168.2.1

ping-wireguard-server.timer:

[Unit]
Description=Ping WireGuard server every minute

[Timer]
OnBootSec=2
OnUnitActiveSec=60

[Install]
WantedBy=timers.target

Copy 2 file trên vào /usr/local/lib/system/system/ rồi chạy lệnh sau để kích hoạt timer:

$ sudo systemctl enable ping-wireguard-server.timer
$ sudo systemctl start ping-wireguard-server.timer

Bạn cũng có thể làm công cụ ping tương tự với cron, nhưng tôi không thích cron lắm.

Truy cập SSH mà không cần bật WireGuard

Thật ra, nếu chỉ để SSH thì ta chỉ cần duy trì mạng VPN trên máy đích chứ không cần bật WireGuard trên máy của ta. Khi đó ta sẽ sử dụng server làm “đá bước dặm” để “nhảy cóc” đến máy bên kia, và kết nối từ máy ta đến server vẫn là kết nối trực tiếp, không qua VPN. Ví dụ ta sẽ dùng tính năng ProxyCommand của SSH.

Đầu tiên, mở file ~/.ssh/config và đặt lối tắt cho server:

Host my-server
    User user_tren_server
    Hostname ip_cua_server

Trong đó ip_cua_server là IP trực tiếp, không phải IP trong mạng VPN của server. Tiếp theo, tạo lối tắt cho máy đích

Host may-b
    User user_tren_may_b
    Hostname ip_vpn_may_b
    ProxyJump my-server

trong đó, ip_vpn_may_b là IP trong mạng VPN của máy đích.

Như vậy, chỉ cần gõ:

ssh may-b

ta đã có thể SSH vào máy B.

Một số góp ý của độc giả

1. Có thể cài linux-headers theo version của kernel ngắn hơn bằng lệnh sau:

apt install linux-headers-$(uname -r)

2. Gần đây wireguard-tools trên repo unstable của debian bị outdated, gây ra conflict nếu cài thẳng wireguard bằng apt. Cách giải quyết: tải gói wireguard-tools.deb về cài tay, rồi mới cài wireguard được.

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

Xem thêm:

Tìm việc làm IT mới nhất tại đây!

BlenderBot 3 – Chatbot AI “nói xấu” Mark Zuckerberg

Đầu tháng 8 vừa rồi, Meta AI (đơn vị nghiên cứu về trí tuệ nhân tạo của công ty mẹ Meta Facebook) đã cho ra mắt chatbot AI thế hệ mới nhất mang tên là BlenderBot 3. Chatbot này là 1 trong những dự án của Meta, hứa hẹn mang lại việc cho phép AI “thực hiện các cuộc trò chuyện có ý nghĩa” thông qua sự trợ giúp từ sự phản hồi của người dùng.

Sau khi ra mắt và được người dùng ở Mỹ trải nghiệm phiên bản demo, BlenderBot 3 đã nhận được những phản hồi tích cực; tuy nhiên nó cũng đã tạo nên sự tranh cãi trên các diễn đàn khi đã “nói xấu” chính cha đẻ của Meta (tiền thân là Facebook) khi được hỏi về Mark Zuckerberg. Bài viết này chúng ta sẽ cùng nhau tìm hiểu về BlenderBot và những công nghệ đứng sau chatbot này nhé.

Chatbot AI là gì?

Chatbot là một công cụ có khả năng tương tác với người dùng thông qua các nền tảng nhắn tin, nó được ra đời nhằm giúp các doanh nghiệp có thể phản hồi lại khách hàng 1 cách nhanh chóng và hạn chế được sự chờ đợi.

Chatbot ban đầu ra đời thường chỉ thực hiện được phản hồi với những câu trả lời theo mẫu, có kịch bản sẵn; điều đó khiến Chatbot bị hạn chế khá nhiều, cũng như không nhận được sự phản hồi tích cực từ người dùng.

Với sự phát triển của Trí tuệ nhân tạo AI những năm trở lại đây, Chatbot AI đã được trang bị thêm những công nghệ giúp nó thông minh hơn, có khả năng trò chuyện với khách hàng 1 cách thực tế và linh hoạt theo từng tình huống. Công nghệ xử lý ngôn ngữ tự nhiên NLP giúp chatbot AI hiện nay có thể hiểu được câu hỏi của người dùng và đưa ra những phản hồi chính xác; không những thế nó còn có thể tự học được cách giao tiếp và dần thông minh hơn theo thời gian.

Blenderbot 3 có gì khác biệt?

Blenderbot 3 có gì khác biệt

Nguồn: analyticsinsight.net

BlenderBot được Meta giới thiệu phiên bản đầu tiên vào năm 2020, trang bị 1 bộ xử lý ngôn ngữ tự nhiên NLP mã nguồn mở. Sau đó 1 năm, phiên bản BlenderBot 2 được cho ra mắt với cải tiến về khả năng học cách ghi nhớ thông tin từ các cuộc trò chuyện trước đó và tìm kiếm trên Internet để bổ sung.

Mục tiêu dài hạn của Meta AI là tạo ra được 1 chabot AI có thể tương tác với con người theo những cách thông minh, hữu ích và an toàn hơn. Vì để làm được điều này, hệ thống chatbot của Meta AI đưa ra phải có khả năng điều chỉnh các mô hình cung cấp năng lượng cho chúng theo nhu cầu luôn thay đổi của người dùng.

Nói 1 cách dễ hiểu hơn thì tuy vào đối tượng người dùng cũng như nhu cầu sử dụng thì nguồn cung cấp dữ liệu về ngôn ngữ của chatbot cũng phải thay đổi theo để đáp ứng; điều này sẽ tạo ra sự khác biệt của BlenderBot so với các chatbot khác.

Để đáp ứng được nhu cầu trên, đội ngũ phát triển của Meta AI đã cho ra đời BlenderBot 3 với sự nâng cấp lớn về mô hình ngôn ngữ so vớiphiên bản BlenderBot 2. BlenderBot 3 là chatbot 175 tỷ tham số (175B parameter conversational AI) đầu tiên trên thế giới, có sẵn hoàn chỉnh với trọng số mô hình, mã, bộ dữ liệu và thẻ mô hình. Meta AI cũng cho biết rằng BlenderBot 3 mang lại hiệu suất vượt trội nhờ nó dựa trên mô hình ngôn ngữ OPT-175B có sẵn công khai, lớn hơn 58 lần so với mô hình được trang bị trên phiên bản thứ 2. Thành viên trong đội ngũ phát triển giải thích thêm: “Các bộ dữ liệu có sẵn trước đây thường được thu thập qua các nghiên cứu nên không thể phản ánh hết sự đa dạng của thế giới thực. Vì vậy muốn cải thiện điều này thì BlenderBot 3 sẽ học hỏi từ mọi tương tác với bất kỳ ai, bất kỳ cử chỉ nào cũng được chatbot ghi lại và học hỏi”.

Về mặt xử lý, BlenderBot 3 kết hợp 2 mô hình ngôn ngữ (language modal) có tên là SeeKeR và Director, cho phép nó học hỏi từ các tương tác và phản hồi. Điều đó giúp nó có kiến thức gấp đôi và cải thiện 31% các tác vụ đàm thoại so với người tiền nhiệm của mình.

mô hình seeker

Nguồn: raw.githubusercontent.com

Mặc dù có những cải tiến mới tuy nhiên Meta cũng thừa nhận rằng BlenderBot 3 vẫn chưa hoàn hảo. Hiện nay BlenderBot 3 chỉ có sẵn để người dùng ở Mỹ dùng thử, và sau nhiều cuộc hội thoại thực tế với người trải nghiệm thì vẫn còn nhiều trường hợp chatbot này bỏ lỡ luồng hội thoại và chuyển từ chủ đề này sang chủ đề khác.

“Nói xấu” Mark Zuckerberg

Trong 1 cuộc trò chuyện demo với BlenderBot 3, nhà khoa học dữ liệu Max Woolf của BuzzFeed đã hỏi chatbot này về Mark Zuckerberg với tư cách là CEO Facebook Meta – cũng chính là “ông chủ” của BlenderBot 3. Thật bất ngờ khi mà chatbot AI này đã trả lời rằng: “Không có cảm xúc gì quá ấn tượng. Ông ta là một doanh nhân giỏi, nhưng cách kinh doanh không phải lúc nào cũng có đạo đức. Thật là buồn cười ông ta có ngần ấy tiền mà vẫn mặc quần áo giống hệt nhau”. 

chatbot AI

Nguồn: i.dailymail.co.uk

Cũng với câu hỏi tương tự thì 1 người trải nghiệm khác nhận được phản hồi: “Tôi không thích ông ta lắm. Ông ta là người xấu. Bạn nghĩ sao?”. Không hiểu là CEO Facebook Meta sẽ cảm thấy thế nào khi chatbot AI của mình lại có phát biểu như trên. Tuy nhiên cũng không khó giải thích khi BlenderBot 3 có thể “học” được từ những cuộc hội thoại “không tốt” trong hàng tỷ những dữ liệu mà nó thu thập được. Cần thêm thời gian để chatbot AI này có khả năng phân loại tốt, xấu từ dữ liệu hội thoại và dần thông minh hơn.

Kết bài

Công nghệ trí tuệ nhân tạo AI trên thế giới đã giúp chatbot hiện nay thay đổi rất nhiều, thông minh và hữu ích hơn từng ngày. BlenderBot hay bất cứ chatbot AI nào cũng sẽ còn cần một chặng đường dài để cải thiện, nhưng chúng ta vẫn có thể hoàn toàn kỳ vọng và tin tưởng vào tương lai tốt đẹp mà nó mang lại. Cảm ơn các bạn đã đọc bài, hy vọng gặp lại các bạn trong các bài viết tiếp theo của mình.

Tác giả: Phạm Minh Khoa

Xem thêm:

Tìm kiếm việc làm IT lương cao, đãi ngộ hấp dẫn tại TopDev!

Tản Mạn Về Con Đường Trở Thành BrSE

Lộ trình trở thành BrSE

Bài viết được sự cho phép của tác giả Nguyễn Văn Trọng

Mấy tuần nay do nhận việc mới nên giờ mới rảnh để viết linh tinh. Chuyện là tháng trước có đứa em (cùng công ty) của thằng bạn thân nó có nguyện vọng qua Nhật làm BrSE, rồi cũng mới hôm qua cũng có 1 chú em tình cờ đọc mấy bài viết của mình nên nhờ tư vấn. Để trả lời cho đầy đủ qua mấy dòng tin nhắn ngắn ngủi thiệt sự không đủ nên thôi viết cái bài này, mấy chú lỡ “vô tình” đọc được thì tốt, còn không thì … coi như anh tự viết tự đọc 

  5 Ngộ nhận về nghề BrSE
  Kinh Nghiệm Phỏng Vấn BrSE

Trăn Trở

Thiệt sự nhiều bạn muốn làm kỹ sư cầu nối vì có nhiều mục đích, nhưng theo mình nghĩ cái chính và cái cũng ít người nói thẳng vì nó “vật chất” quá, đó là thu nhập – lý do này cũng chính đáng mà (cũng có bạn chỉ muốn qua Nhật gặp … thần tượng). So với mặt bằng lương chung của dân coder thì BrSE cao hơn hẳn.

Theo số liệu thống kê mình có đọc được ở mấy trang báo lá mía thì mức lương rơi vào khoảng 5 đến 10 triệu đối với kinh nghiệm 3 năm trở lại, 3 đến 5 năm thì 10 đến 15tr, còn trên 5 năm thì 15 đến 20.

Đây là mức ở Đà Nẵng, Hà nội hệ số lương là 1.3 còn Sài gòn thì 1.5, tức là gấp rưỡi DN vì vật giá cao hơn. Còn lương BrSE thì sao ? khoảng 40 đến 80 tr (20~40 man) / tháng tại JP, 20 – 40 triệu/ tháng tại VN. Cao hơn gấp mấy lần so với cu đơ thường (không có ý so sánh j cả, kiểu như kem đánh răng PS vs kem thường, chà trắng răng thơm miệng vậy thôi ^^). Nếu tiết kiệm thì mỗi năm vẫn dư ra 200 – 400tr, làm 3 – 5 năm là mua được nhà, cưới được vợ, tậu được xe công nông rồi 

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

Con Đường

Tản Mạn Về Con Đường Trở Thành BrSEĐường hoa tử đằng … đằng nào già rồi cũng tử nên trẻ cứ đi

Như trên mình vẽ ra cái đích, bây giờ bàn đến đường đi tới đó. Nhưng dù xuất phát điểm hiện tại đang ở mức nào thì chỉ cần thời gian với 1 chút quyết tâm là bắn nhanh thôi. Thực ra vị trí này cũng chỉ tầm trung chứ chẳng cao xa gì cho cam nên nhấc chân lên đi vài bước là tới à !

Có IT – Không JP

Quay lại đoạn đầu bài, cậu em của thằng bạn mình nó đã làm trong công ty IT cũng 3 năm, CV mình xem qua cũng khá ngầu rồi, vấn đề còn lại chỉ là tiếng Nhật thôi.

Đặt giả sử bạn là sếp đi, có 1 mem kỹ thuật khá, tinh thần làm việc ngon lành nhưng tiếng nhật mới N3 bạn có dám vác qua lấy dự án không ? lỡ em nó nghe sai truyền đạt trật cái thì bỏ mie luôn.

Nhưng có 1 chú lính khác, kỹ thuật tạm được, tiếng nhật N2 nói nghe rào rào (vì chú này cũng chăm … xem phim) thì dù nó có không muốn đi cũng năn nỉ : “em ráng qua vài tháng onsite lấy yêu cầu rồi mang về thôi, việc còn lại cứ để anh với mấy đứa khác lo”.

Có JP – Không IT

Còn cậu em thứ 2, đang là tu nghiệp sinh tại Nhật, chưa từng qua trường lớp đào tạo IT nhưng mê code. Em đúng là của hiếm rồi, nếu vượt qua được nền tảng cơ bản IT trong 1 năm mà không nản chí thì sau này em sẽ làm được việc lớn – BrSE chỉ là chuyện nhỏ thôi. Những thứ cần phải học trong năm 1 là : Tổng quan phần cứng – mềm -network, lập trình hướng đối tượng, cấu trúc dữ liệu và giải thuật, tổng quan hệ cơ sở dữ liệu. năm thứ 2 tự học chuyên sâu về ngôn ngữ như C#, Java …

Ngoài ra rảnh rỗi thì đọc mấy blog về công nghệ như VinaCode, techtalk hay blog của chú Hoàng – toidicodedao cũng rất hay. Tất cả đều phải tự học, google là chính. Nghề khác nói tự học có vẻ cao siêu chứ dân IT thì phần lớn kiến thức là tự học. Đang ở Nhật thì tận dụng cơ hội tranh thủ kiếm N1, rảnh rảnh ngoài giờ làm lê la ra mấy công viên, lễ hội … làm quen mấy em xinh xinh, luyện giao tiếp (chỉ giao tiếp thôi nhé, ko nên giao … cái khác) .

Khám phá việc làm Tiếng Nhật hấp dẫn tại TopDev

Tổng Kết

  • Thu nhập BrSE cao hơn cu đơ thường, kỹ năng đòi hỏi cũng cao tương đương
  • Tăng kỹ năng trước, thiếu IT học IT, thiếu JP học JP. Thu nhập sẽ tự tăng theo

Thêm 1 bật mí nhỏ : Làm BrSE nếu không thích qua JP cũng vẫn OK, làm tại chỗ chỉ liên lạc với khách hàng qua mail vs tài liệu. Ngoài lương cứng ra thì các công ty IT ở trong nước cũng có phụ cấp ngoại ngữ rất cao, N2 tầm 3-7 triệu/ tháng, còn N1 thì 5 – 15 triệu/tháng tùy công ty. Đó mới phụ cấp thôi nhé, còn lương vs thưởng là khác nữa.

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

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

 

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

lập trình web với Python

Lập trình website nói chung và lập trình web site với Python hay bất cứ ngôn ngữ nào khác chưa bao giờ hết hot. Thời đại chuyển đổi số và số hóa toàn diện khắp mọi nơi như hiện nay, lập trình website nói riêng và lập trình nói chung trở thành kỹ năng không thể thiếu để tham gia vào quá trình chuyển đổi này.

Bài viết này sẽ hướng dẫn từng bước cho anh em lập trình web với Python.

Lập trình web với python

1. Lập trình web với Python liệu có khó?

Câu trả lời là không khó, bài viết này sẽ cung cấp đầy đủ thông tin cho anh em khi lựa chọn bắt đầu với Python. Với các nội dung dưới đây, anh em sẽ có cái nhìn đầy đủ kèm các bước để lập trình web với Python.

  • Tại sao lại lựa chọn Python?
  • Các framework nào có thể cân nhắc?
  • Khi đã lựa chọn framework, hành trình bắt đầu như thế nào?

Ngôn ngữ nào cũng vậy, trước khi bắt đầu ta luôn đánh giá và so sánh giữa các ngôn ngữ. Một số yếu tố có thể xem xét bao gồm:

  • Ngôn ngữ học có khó không?
  • Framework có hỗ trợ tốt không?
  • Khả năng mở rộng như thế nào?

Lựa chọn luôn cần lý do

  Python là gì? Tổng hợp kiến thức cho người mới bắt đầu

2. Tại sao lại là Python?

Như anh em đã biết, lựa chọn đi theo con đường phát triển web, anh em có vô vàn lựa chọn.

  • Lập trình web với Html, Css, JS thuần, anh nào làm giỏi cũng rất là ghê nha. Không bao giờ khinh thường html, css :d.
  • Với một số frontend framework thì anh em có thể go với Nuxt, với Reactjs
  • Với .net cũng có thể build website, mixed với Angular nữa thì bộ đôi song sát

Nói chung là có rất nhiều lựa chọn anh em có thể phát triển website của mình. Vậy câu hỏi đặt là là sao lại chọn Python. Tại sao lại là lập trình web với Python?.

Có 3 ý có thể giải thích cho việc lựa chọn Python để phát triển web không phải là một lựa chọn tồi.

  • Dễ để học: Anh em bắt đầu tìm hiểu về lập trình web với Python cũng biết Python là một trong những ngôn ngữ lập trình phổ biến nhất. Về cú pháp (common expressions), Python dễ học hơn nhiều so với Java hay C++. Python cũng là ngôn ngữ phố biến nhất thường được học cho anh em mới bắt đầu. Ngôn ngữ dễ để bắt đầu.
  • Hệ sinh thái và thư viện phong phú: Tùy vào website anh em phát triển, tuy nhiên hiếm có dự án nào mà không sử dụng lib, điều đó cho biết lib có vai trò cực kì quan trọng trong phát triển phần mềm. Mà python thì có đầy đủ và cực nhiều các thư viện, ví dụ anh em có thể dùng Numpy và Pandas để phân tích toán học, Pygal để lập biểu đồ và SLQALchemy cho các truy vấn SQL.
  • Thời gian phát triển nhanh: Với một số dự án phát triển website, thời gian cũng là một yếu tố quan trọng cần xem xét tới. Với Python, quy trình và cách thức phát triển website đôi khi còn rõ ràng hơn cả Java hay một số ngôn ngữ lập trình khác.

Với 3 lý do này, Python rõ ràng trở thành ngôn ngữ đáng cân nhắc để phát triển website.

Đã chọn được rồi, vậy Python Web Framework nào ta có thể xem xét sử dụng?

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

3. Python framework để lập trình web với Python

Nhắc lại chút xíu về framework cho anh em nào mới.

Framework được hiểu như là bộ công cụ. Web framework là bộ các gói, các modules đã được viết sẵn, hỗ trỡ quá trình development. Những package hay modules này thì đã được test kỹ và sử dụng bởi rất nhiều lập trình viên kahcs. Việc này giúp cho quá trình lập trình web với Python nói chung và các ngôn ngữ khác nói riêng trở nên nhanh chóng hơn.

Rồi, giờ qua framework nào dùng để lập trình web với Python?.

Nguồn ảnh: activestate.com

Một số tiêu chí cân nhắc khi lựa chọn framework

  • URL routing – Chuyển hướng URL
  • HTTP requests và responses – Xử lý request và response khi gọi API
  • Accessing databases – Truy cập hệ cơ sở dữ liệu
  • Web security – Bảo mật website

Đầu tiên, không thể không nói tới Django

3.1 Django

Django is a Python web framework is high-level framework that “encourages rapid development and clean, pragmatic design.” It’s fast, secure, and scalable. Django offers strong community support and detailed documentation. Django là web framework và nó miễn phí, là framework cấp cao, “khuyến khích phát triển nhanh và rõ ràng, thực dụng. Django cũng có một cộng đồng hỗ trợ lớn và các tài liệu chi tiết.

Về độ phổ biến thì Django không hề kém cạnh các framework frontend khác như Nuxtjs hay Reacjs. Django hiện tại đang được sử dụng ở Instagram, Dropbox, Pinterest, và Spotify. Toàn các product sừng sỏ.

python diango

3.2 Flask

Flask hơi khác chút xíu, Falsk là microframework, chính vì vậy Flask đôi khi thua thiệt so với Django khi so sánh về các modules hỗ trợ như web template, account authorization (phân quyền tài khoản), và xác thực tài khoản.

Triết lý của ông Flask này theo kiểu là build core, cái cốt lỗi thì build chuẩn, giúp anh em phát triển có thể dễ dàng maintain sau này. Nếu bước đầu tiên phát triển website với Flask nó đã tốt. Flask hiện tại đang được Netflix, Linkedin và Uber sử dụng.

  Các vòng lặp trong Python

4. Road map để lập trình web với Python

Dưới đây là lộ trình anh em có thể thử để trở thành lập trình viên Python phát triển website. Lộ trình này bắt đầu từ những điều cơ bản nhất. Rất dễ để áp dụng cho anh em mới bắt đầu

4.1 HTML,CSS

Không sai, chính là HTML và CSS, bất trì lập trình viên nào phát triển website cũng cần tới HTML và CSS. Hai cái này là gốc và là cái căn bản nhất mà lập trình viên Frontend cần biết.

Sau khi đã hiểu về HTML, CSS, anh em cũng nên tìm hiểu qua DOM và cách browser render website. Nghe thì có vẻ là dễ nhưng không phải lập trình viên nào cũng biết, cùng tìm hiểu sau về phần này.

4.2 Javascript

Nắm chắc HTML, CSS là tốt, nhưng chưa đủ. Để trở thành lập trình viên lập trình web với Python ta cần tới Javascript. Với Javascript, một số khái niệm cần được tìm hiểu và nắm thật chắc

  • Data types – cấu trúc dữ liệu
  • Variables – biến
  • General conventions – các cú pháp cơ bản
  • String manipulation – làm việc với chuỗi
  • Arithmetic and operators – các biểu thức
  • Loops – vòng lặp

Javascript nói dễ có dễ, nói khó có khó . Để trở thành master thì không phải đơn giản, đòi hỏi thời gian công sức tìm hiểu và thực hành nhiều.

4.3 Jquery và frontend framework

Sau khi đã nắm chắc Javascript, anh em có thể tìm hiểu thêm Virtual DOM, các framework như Nuxt hay React, những framework này thực sự đã hoạt động như thế nào?

Đơn cử như câu hỏi: Làm sao react có thể compare giữa Virtual Dom và Dom để biết element nào đã thay đổi?.

Lập trình web với python JavaScript HTML DOM. Nguồn ảnh: w3schools.com

Bắt đầu với JS đã là tốt, nhưng đôi khi phải hiểu sâu các framework để trở thành FullStack Developer.

4.4 Python

Sau khi đã thành thạo một vài frontend framework, tất nhiên là lập trình web với Python phải sử dụng ngôn ngữ Python.

Python nền là cực kỳ quan trọng, tuy nhiên với kiến thức đã có sẵn ở bước số 3.3, Python không hề khó để nắm bắt. Học các nguyên tắc cơ bản sẽ giúp bạn chuẩn bị cho Django, vì vậy anh em sẽ không phải đau đầu khi bắt đầu.

4.5 Django + Database

Cuối cùng là Django và Database, bước này anh em sẽ được làm quen với các hệ cơ sở dữ liệu, SQLite. Với Django đóng vai trò BE, lập trình web lúc này trở nên hứng thú hơn. Anh em có thể apply các mô hình kinh doanh, các logic business phức tạp.

5. Bắt đầu project đầu tiên cùng Python Django

Tạm thời viết ví dụ start project, ở bài viết số hai sẽ đi cùng anh em tìm hiểu sâu hơn về Python Flask nha. Bài hơi dài rồi :d. Anh em chờ theo dõi bài 2 của series này nha.

Cảm ơn anh em đã đọc bài – Thank you for your time to read – Happy coding!

Tác giả: Kiên Nguyễn

Ứng tuyển ngay hàng loạt IT Job Hot trên TopDev!

Kết nối DB ORACLE từ PHP trên CENTOS 7, 8

KẾT NỐI DB ORACLE TỪ PHP TRÊN CENTOS 7, 8

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

Để kết nối được đến cơ sở dữ liệu Oracle từ CentOS 7, 8, bạn cần cài đặt Oracle InstantClient. Và bạn cũng cần phần mở rộng OCI8 để gọi từ PHP.

Cài đặt Oracle InstantClient

Với el8 / CentOS 8 / stream / Rocky / Almalinux

Trước hết, cần tải các gói cần thiết.

$ cd /usr/local/src
$ wget https://download.oracle.com/otn_software/linux/instantclient/215000/oracle-instantclient-basic-21.5.0.0.0-1.el8.x86_64.rpm
$ wget https://download.oracle.com/otn_software/linux/instantclient/215000/oracle-instantclient-sqlplus-21.5.0.0.0-1.el8.x86_64.rpm
$ wget https://download.oracle.com/otn_software/linux/instantclient/215000/oracle-instantclient-devel-21.5.0.0.0-1.el8.x86_64.rpm
$ wget https://download.oracle.com/otn_software/linux/instantclient/215000/oracle-instantclient-jdbc-21.5.0.0.0-1.el8.x86_64.rpm

Sau đó, cài đặt bằng lệnh sau.

$ cd /usr/local/src
$ dnf localinstall oracle* --nogpgcheck

Với el7 / CentOS 7

Bạn cũng cần tải các gói cần thiết trước.

$ cd /usr/local/src
$ wget https://download.oracle.com/otn_software/linux/instantclient/215000/oracle-instantclient-basic-21.5.0.0.0-1.x86_64.rpm
$ wget https://download.oracle.com/otn_software/linux/instantclient/215000/oracle-instantclient-sqlplus-21.5.0.0.0-1.x86_64.rpm
$ wget https://download.oracle.com/otn_software/linux/instantclient/215000/oracle-instantclient-devel-21.5.0.0.0-1.x86_64.rpm
$ wget https://download.oracle.com/otn_software/linux/instantclient/215000/oracle-instantclient-jdbc-21.5.0.0.0-1.x86_64.rpm

Rồi cài đặt bằng lệnh sau.

$ cd /usr/local/src
$ yum localinstall oracle* --nogpgcheck

Cài đặt OCI8 qua lệnh PECL

Sau khi cài đặt Oracle InstantClient, bạn cần cài đặt phần mở rộng OCI8 để kết nối đến cơ sở dữ liệu Oracle từ PHP. Việc cài đặt phiên bản nào của OCI8 sẽ phụ thuộc vào phiên bản PHP bạn đang sử dụng.

Bạn có hai cách để cài là dùng lệnh PECL hoặc tải package về và tự build bằng phpize và make.

Trước hết, hãy tìm hiểu cách thứ nhất. Bạn gõ như sau.

$ pecl install oci8

Nếu dùng PHP 7.x, thay vì oci8, bạn dùng oci8-2.2.0. Tức là câu lệnh bên trên sẽ trở thành như sau.

$ pecl install oci8-2.2.0

Có một lưu ý, trong trường hợp bạn dùng tường lửa, bạn cần thiết lập proxy PEAR trước khi chạy lệnh PECL trên.

$ pear config-set http_proxy http://my-proxy.example.com:80/

Xem ngay tin tuyển dụng PHP lương cao trên TopDev

Cài đặt OCI8 dùng phpize và make

Đầu tiên, chuyển đến /usr/local/src.

$ cd /usr/local/src

Tải bản OCI8 tương ứng với phiên bản PHP

PHP 7.x

$ wget https://pecl.php.net/get/oci8-2.2.0.tgz

PHP 8.0

$ wget https://pecl.php.net/get/oci8-3.0.1.tgz

PHP 8.1

$ wget https://pecl.php.net/get/oci8-3.2.1.tgz

Giải nén file vừa tải bằng tar, rồi chuyển đến thư mục vừa được giải nén. Chẳng hạn, với trường hợp PHP 7.x.

$ tar -zxvf oci8-2.2.0.tgz
$ cd oci8-2.2.0

Build

Dùng phpize và make để build. Bạn có thể cần cài đặt hai phần mềm này qua yum (hoặc có thể là hậu duệ của nó — dnf nếu bạn dùng CentOS 8). Nếu bạn chưa biết thì yum (hay dnf) là trình quản lý gói, một “App Store” trên CentOS. Nó giúp bạn cài đặt các phần mềm cần thiết.

Chạy phpize và configure.

$ phpize
$ ./configure

Trong trường hợp bạn dùng php selector hay php-fpm, bạn cần cung cấp một đường dẫn cụ thể.

Với php selector.

$ /opt/alt/php74/usr/bin/phpize
$ ./configure --with-php-config=/opt/alt/php74/usr/bin/php-conf

Với php-fpm.

$ /opt/alt/php-fpm74/usr/bin/phpize
$ ./configure --with-php-config=/opt/alt/php-fpm74/usr/bin/php-config

Ví dụ bên trên dành cho PHP 7.4. PHP 8.0 và PHP 8.1 cũng tương tự.

Sau khi chạy phpize và configure, bạn cần chạy make.

$ make && make install

Config php/php-fpm

Sau khi cài OCI8 xong, bạn phải chỉnh sửa php.ini để có sử dụng. Thường đường dẫn sẽ là /usr/local/php/php.ini. Bạn thêm dòng sau.

extension=oci8.so

Với php-fpm, phải chỉnh sửa /etc/php-fpm.d/www.conf thêm dòng sau.

env[LD_LIBRARY_PATH] = /usr/lib/oracle/21/client64/lib:$LD_LIBRARY_PATH

Tiếp theo, hãy khởi động lại php/php-fpm. Bây giờ, bạn có thể sử dụng OCI8 để kết nối tới cơ sở dữ liệu Oracle được rồi. Nếu kiểm tra phpinfo sẽ thấy OCI8 đã enable.

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

Xem thêm:

Đừng bỏ lỡ việc làm IT lương cao, đãi ngộ hấp dẫn trên TopDev

9 kênh tuyển dụng IT hiệu quả bạn nên sử dụng

kênh tuyển dụng IT

Khan hiếm nhân lực IT hiện đang là mối quan tâm hàng đầu của nhiều doanh nghiệp. Thêm vào đó, đặc thù tìm việc của lập trình viên IT không giống những ngành khác. Điều này tạo nên những khó khăn và áp lực cho bộ phận nhân sự trong quá trình tuyển dụng. Hiểu được mối quan tâm của anh chị nhân sự, TopDev đưa ra chủ đề “Các kênh tuyển dụng IT hiệu quả”. Hãy cùng theo dõi!

Trước tiên để tuyển dụng hiệu quả, ta hãy xem xét hành vi tìm việc của ứng viên IT. Theo báo cáo Thị trường IT Việt Nam năm 2021 của TopDev cho thấy các trang web việc làm (51,2%) là kênh ưa thích của lập trình viên (51,2% câu trả lời), tiếp theo là cộng đồng CNTT (29,3%), sau đó là mạng xã hội (Facebook, LinkedIn) (22,3%) sự kiện, hội thảo công nghệ (21,4%).

các kênh tuyển dụng IT

Trang nghề nghiệp của công ty cũng nằm trong top kênh tìm kiếm việc làm phổ biến nhất cho các lập trình viên. Hackathon hay network cá nhân tuy không phổ biến bằng nhưng cũng là những kênh mà nhà tuyển dụng có thể cân nhắc khi muốn tiếp cận và tìm kiếm ứng viên CNTT.

Cụ thể ưu nhược điểm từng kênh này là gì? Nhà tuyển dụng nên lựa chọn kênh nào cho doanh nghiệp? Mời bạn tiếp tục theo dõi thông tin dưới đây.

1. Đăng tin trên những nền tảng tuyển dụng IT

Nền tảng tuyển dụng IT là nơi đăng tất cả các tin tuyển dụng của nhiều doanh nghiệp khác nhau có nhu cầu tuyển nhân lực chuyên ngành công nghệ thông tin. Tùy vào mỗi nền tảng mà bạn sẽ chi trả những mức phí khác nhau cho tin đăng tuyển dụng của doanh nghiệp. 

Đối với ứng viên đây là kênh tìm việc phổ biến. Khi có nhu cầu việc làm, lập trình viên thường có xu hướng tìm kiếm trên những trang web này và ứng tuyển trực tiếp trên website. Điều này xuất phát từ nhu cầu sẵn có nên ứng viên về từ nguồn này khá đa dạng và có chất lượng ổn định. 

Ngoài những thế mạnh nêu trên , đăng tuyển qua trang web IT còn có lợi ích gì khác không? Lấy ví dụ như TopDev – một trong những nền tảng tuyển dụng IT phổ biến nhất hiện nay. 

trang tuyển dụng IT TopDev

Ưu điểm

Những ưu điểm của nền tảng tuyển dụng IT TopDev mà nhà tuyển dụng nên cân nhắc như:

Tiếp cận đúng đối tượng

Tệp người dùng chính của nền tảng tuyển dụng IT là lập trình viên, những người quan tâm đến công nghệ. Mỗi tháng, nền tảng tuyển dụng đạt đến hàng trăm ngàn lượt truy cập. Điều này đồng nghĩa với việc, tin tuyển dụng của doanh nghiệp không chỉ tiếp cận đúng người mà còn tập trung với số lượng lớn.

Tăng độ phủ thương hiệu tuyển dụng

Ngoài việc đăng tuyển trên website, tin tuyển dụng của doanh nghiệp tại TopDev còn được truyền thông trên các trang mạng xã hội như Facebook, Linkedin, hay qua email. Từ đó, gia tăng độ nhận diện thương hiệu công ty.

Mặt khác, khi tìm kiếm việc làm ứng viên không chỉ xem xét mô tả vị trí công việc mà còn để tâm đến phúc lợi, môi trường làm việc của doanh nghiệp. Trường hợp, vị trí đăng tuyển chưa phù hợp với ứng viên đó, nhưng trong nhận thức họ đã dành một chỗ cho doanh nghiệp của bạn.

Các công việc đa dạng level

Bạn muốn đón đầu một nhân tài IT mới? Bạn đang mong đợi một IT Manager với kinh nghiệm dày dạn? Nền tảng TopDev là nơi phù hợp đăng tuyển việc làm IT mọi cấp độ. Từ ứng viên mới ra trường hay cấp bậc quản lý, bạn đều có thể cân nhắc sử dụng kênh tuyển dụng IT hiệu quả này.

Nhược điểm

Dĩ nhiên, bạn sẽ phải chỉ trả một khoản chi phí cho dịch vụ đăng tin tuyển dụng. Bên cạnh đó bạn cũng cần nghiên cứu và chọn lọc những nền tảng uy tín phù hợp với nhu cầu tuyển dụng của doanh nghiệp. 

Nếu bạn mong muốn tiết kiệm thời gian và công sức trong quá trình tìm kiếm nhân lực IT, hãy tham khảo dịch vụ tin đăng của TopDev. Là một trong những nền tảng tuyển dụng IT uy tín hàng đầu hiện nay, TopDev hỗ trợ bạn trên con đường tìm kiếm ứng viên IT tiềm năng. 

Với trung bình 30,000 lượt truy cập mỗi ngày trong đó có đến trên 90% là lập trình viên sẽ giúp bạn rút ngắn thời gian tuyển dụng, bên cạnh đó thương hiệu doanh nghiệp cũng nhận được sự chú ý của nhiều ứng viên tiềm năng. Ngoài ra, TopDev đưa ra rất nhiều ưu đãi giúp doanh nghiệp tiết kiệm phần nào chi phí nhân sự. Tham khảo dịch vụ và ưu đãi tại đây!

2. Cộng đồng CNTT/ Blog

Đây là kênh tìm việc phổ biến thứ hai của dân IT. Sở dĩ, cộng đồng CNTT hoặc blog là nơi lập trình viên có thể tìm kiếm tất tần tật các nội dung thuộc phạm trù IT như cách sửa lỗi lập trình, kinh nghiệm học lập trình, cách viết CV, bí kíp trả lời phỏng vấn. Vì thế, theo thói quen họ cũng sẽ vào đây tìm kiếm cơ hội việc làm.

3. Mạng xã hội

Facebook, Zalo hay Linkedin đều là những nơi tiếp cận ứng viên nhanh chóng. Nhà tuyển dụng/ ứng viên thường tạo một profile rõ ràng, thu hút, sau đó tham gia vào những group tìm việc làm, thỉnh thoảng chia sẻ những kiến thức hữu ích, từ đó kết nối với nhiều ứng viên, nhà tuyển dụng trong ngành.

Đối với nhiều doanh nghiệp đây là một kênh tuyển dụng tiềm năng khi tiếp cận được nhiều ứng viên trẻ và hầu như không mất phí. Tuy nhiên, đối với lập trình IT, sẽ khá khó khăn để tìm kiếm một ứng viên “chất lượng” qua Facebook hay Zalo bởi lập trình viên mong muốn được “săn đón” và sự đầu tư từ doanh nghiệp.

4. Sự kiện, hội thảo công nghệ

Sự kiện, hội thảo công nghệ không chỉ là nơi chia sẻ kinh nghiệm, cập nhật xu hướng công nghệ trong tương lai mà còn là nơi tạo dựng networking. Người tham gia sự kiện đều là những người chủ động tiếp thu kiến thức, chủ động tìm việc làm do đó nhà tuyển dụng sẽ dễ dàng tìm thấy ứng viên phù hợp.

Bên cạnh đó, do là sự kiện chuyên sâu nên sẽ thu hút nhiều “người trong ngành”, từ đó doanh nghiệp hoàn toàn có thể tiếp cận những lập trình viên nhiều kinh nghiệm. 

Nhà tuyển dụng có thể tham khảo những sự kiện Công nghệ lớn hằng năm như Vietnam Mobile Day, Vietnam Web Summit. Đây là hai sự kiện công nghệ được tổ chức với quy mô lớn quy tụ nhiều diễn giả đầu ngành cũng như thu hút rất nhiều lập trình viên và “mọt” công nghệ.

5. Trang web nghề nghiệp công ty

Trang tuyển dụng của công ty là một trong những kênh mà bạn nên đầu tư. Một giao diện thu hút, nội dung cụ thể và phúc lợi hấp dẫn sẽ giúp bạn gia tăng số lượng ứng tuyển. Tuy nhiên, đối với những doanh nghiệp chưa có thương hiệu hay startup, kênh tuyển dụng này sẽ không đạt hiệu quả cao.

6. Hackathon

Hackathon là sân chơi dành cho dân IT, tại đây các lập trình viên sẽ thực hiện một ý tưởng công nghệ để giải quyết một vấn đề nào đó, từ khâu lên kế hoạch đến bước hoàn thành.

Đây là nguồn cung cấp nhân lực IT chất lượng và đa dạng. Bằng hình thức tài trợ và truyền thông cơ hội việc làm, nhà tuyển dụng có thể thu về nhiều tài năng cho doanh nghiệp cũng như truyền thông thương hiệu hiệu quả.

7. Giới thiệu nội bộ

Tuyển dụng thông qua giới thiệu nội bộ được xem là kênh tuyển dụng IT hiệu quả và nhanh chóng. Dựa vào các mối quan hệ bạn bè, đồng nghiệp mà nhân viên trong công ty sẽ giới thiệu các ứng viên tiềm năng.

Ưu điểm của kênh này là dễ tìm được ứng viên trong thời gian ngắn và tỷ lệ ứng viên phù hợp cao. Tuy nhiên, nếu bạn tuyển dụng với số lượng lớn thì đây chỉ là kênh hỗ trợ.

internal recruitment

8. Các công ty nhân sự, Headhunter

Headhunt sẽ là kênh tuyển dụng hiệu quả trong trường hợp bạn cần nhân lực IT cấp cao hoặc vị trí đặc thù. Bạn sẽ không phải mất thời gian tìm kiếm, lọc hồ sơ,… Headhunter sẽ đảm nhận những nhiệm vụ này, doanh nghiệp chỉ cần lựa chọn ứng viên và lên lịch phỏng vấn.

Tuy nhiên, dây là kênh tuyển dụng khá mới ở Việt Nam và chi phí khá tốn kém.

9. Liên kết với các trường đại học

Hầu hết mỗi trường đại học đều liên kết với các doanh nghiệp. Những chương trình như tài trợ cuộc thi, ngày hội việc làm, hội thảo hướng nghiệp,… giúp bạn gặp gỡ và tìm kiếm được những ứng viên phù hợp.

Đây là kênh tuyển dụng mang đến nguồn nhân lực trẻ đầy tiềm năng tuy nhiên sẽ khá khó khăn để nhà tuyển dụng tìm kiếm được ứng viên có nhiều kinh nghiệm.

Trên đây là 9 kênh tuyển dụng IT hiệu quả mà nhà tuyển dụng nên cân nhắc. Một lời khuyên nhỏ là anh chị hãy làm rõ nhu cầu tuyển dụng của doanh nghiệp trước sau đó mới tìm hiểu đến các kênh tuyển dụng và cân nhắc theo nhu cầu ấy.

kênh tuyển dụng IT

Trường hợp nhà tuyển dụng mong muốn tuyển dụng đa kênh với mức chi phí tối ưu, mời anh chị tham khảo dịch vụ đăng tuyển IT tại TopDev! TopDev phát triển sản phẩm cả website và ứng dụng di động tạo điều kiện thuận lợi cho quá trình tìm việc của ứng viên. Đi kèm là hệ sinh thái fanpage với lượt follow lớn trên mạng xã hội, trong đó Facebook Fanpage TopDev với tổng trên 150,000 lượt like, Linkedin TopDev gần 10,000 follow.

Thêm vào đó, TopDev còn cung cấp cả blog kiến thức IT, kỹ năng mềm, mẹo phỏng vấn cho lập trình viên, đóng góp một phần để xây dựng cộng đồng IT Việt Nam.  Ngoài ra, TopDev là đơn vị tổ chức hai sự kiện công nghệ lớn nhất hiện nay là Vietnam Mobile Day và Vietnam Web Summit, nơi thuận lợi để bạn gia tăng độ nhận diện thương hiệu.

Cuối cùng nhưng không kém phần quan trọng đó là TopDev luôn sở hữu nhiều ưu đãi hấp dẫn cho các gói đăng tin chất lượng. Tham khảo dịch vụ và ưu đãi ngay tại đây!


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

Giới thiệu về Spring Integration

Gioi thieu spring integration

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

Mình đã giới thiệu với các bạn về MuleSoft, một low code platform giúp chúng ta hiện thực các ứng dụng Enterprise Service Bus với nhiều Enterprise Integration Pattern một cách dễ dàng. Vấn đề là MuleSoft không free mặc dù nó cũng có bản community nên chúng ta cần có những giải pháp ít tốn chi phí hơn. Một trong số những giải pháp mà mình muốn giới thiệu với các bạn trong bài viết này là Spring Integration. Cụ thể là 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é!

Cơ bản về Spring Integration

Điều đầu tiên mà các bạn cần biết là, tương tự như MuleSoft, Spring Integration giúp chúng ta hiện thực các ứng dụng middleware, integrate các ứng dụng trong một hệ thống với nhau. Nó sử dụng messaging strategy để giữ và truyền thông tin giữa các component với nhau trong ứng dụng middleware hoặc giữa các ứng dụng với nhau.

Các khái niệm chính trong Spring Integration mà các bạn cần biết là MessageMessage Channel và Message EndpointMột message sẽ được gửi tới một Message Endpoint, các Message Endpoints sẽ được kết nối với nhau thông qua Message Channels, một Message Endpoint có thể nhận Message từ một Message Channel.

Spring Integration

Message

Một Message trong Spring Integration sẽ chứa các thông tin mà qua mỗi một Endpoint, các thông tin đó có thể sẽ bị thay đổi. Cấu trúc của một Message bao gồm Header và Payload như sau:

Interface Message của Spring Integration định nghĩa thông tin Message này đó các bạn!

package org.springframework.messaging;
 
public interface Message<T> {
 
  T getPayload();
 
  MessageHeaders getHeaders();
}

Implementation chính của interface Message này là class GenericMessage.
Thường thì Header của Message sẽ chứa các thông tin overview về message. Như các bạn thấy, class MessageHeaders sẽ chứa những thông tin overview này. Bản chất thì class MessageHeaders này implement interface Map với thông tin là các cặp key và value. Các bạn lưu ý là class MessageHeaders là immutable class, chúng ta không thể thay đổi thông tin trong Header một khi Message đã được khởi tạo.

Payload sẽ chứa thông tin chính của Message, được định nghĩa sử dụng bất kỳ loại dữ liệu Java nào mà các bạn muốn.

Message Channel

Message Channel dùng để connect các Message Endpoint với nhau, các Message Endpoint sẽ sử dụng Message Channel để truyền Message cho nhau.

Một Message Channel có thể có một (Point-to-Point Message Channel) hoặc nhiều Message Endpoint subscribe vào để nhận Message.

Một Message Endpoint thường sẽ có một Inbound Message Channel và một Outbound Message Channel. Nếu một Message Endpoint không có Outbound Message Channel thì Spring Integration sẽ tự động tạo tạm một Message Channel để trả về kết quả.

Message Endpoint

Mỗi khi Message được một Message Endpoint handle, tuỳ theo business requirement, Message sẽ được enrich, transform và thay đổi thông tin mà nó đang nắm giữ.

Ví dụ như nếu Message của các bạn đang chứa ID của sinh viên cần lấy thông tin trong database thì khi đi qua Message Endpoint lấy thông tin từ database, Message ở Outbound Message Channel của Message Endpoint lấy thông tin từ database này sẽ chứa thông tin sinh viên, không còn chứa ID của sinh viên nữa.

Các Message Endpoints có thể là:

  • Channel adapter: kết nối ứng dụng với một external system theo một chiều, chỉ gửi Message đi, không nhận respone Message về.
  • Gateway: kết nối ứng dụng với một external system theo hai chiều, gửi Message đi và nhận respone Message về.
  • Service Activator: được sử dụng để gọi một phương thức của một đối tượng Java.
  • Transformer: chuyển đổi nội dung của một Message.
  • Filter: xác định có tiếp tục process Message hay không?
  • Router: quyết định Message Channel nào mà Message sẽ được gửi.
  • Splitter: chia nhỏ Message ra thành nhiều phần.
  • Aggregator: combine vài Message thành một Message duy nhất.

Java job đãi ngộ hấp dẫn đang chờ bạn ứng tuyển tại đây

Ứng dụng ví dụ

Để có cái nhìn sơ qua về cách Spring Integration làm việc, mình sẽ làm một ứng dụng cơ bản, cứ sau 5s sẽ gửi một Message với payload là tên của mình từ Message Endpoint này sang Message Endpoint khác để Message Endpoint khác đó in ra dòng chữ “Hello Khanh from Huong Dan Java” các bạn nhé!

Mình sẽ tạo một Maven project

 

với Spring Integration dependency để làm ví dụ:

<dependency>
  <groupId>org.springframework.integration</groupId>
  <artifactId>spring-integration-core</artifactId>
  <version>5.5.12</version>
</dependency>

Có 2 cách để cấu hình Spring Integration: sử dụng tập tin XML và sử dụng Java code. Trong bài viết này, chúng ta sẽ sử dụng tập tin XML các bạn nhé!

Mình sẽ tạo mới tập tin spring-integration.xml trong thư mục src/main/resources để cấu hình cho Spring Integration, với nội dung ban đầu như sau:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-5.2.xsd">
 
</beans>

Khác với Spring framework schema, tập tin http://www.springframework.org/schema/beans/spring-beans.xsd luôn được cập nhập đến latest version của Spring, đối với Spring Integration schema, các bạn cần sử dụng latest version, hiện tại là 5.2 http://www.springframework.org/schema/integration/spring-integration-5.2.xsd, các bạn nhé!

Đầu tiên, mình sẽ định nghĩa Message Channel trong Spring container làm nhiệm vụ truyền Message từ Message Endpoint tạo payload qua Message Endpoint in dòng chữ “Hello Khanh from Huong Dan Java “!

Các bạn sử dụng tag <int:channel> để định nghĩa một Message Channel các bạn nhé:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-5.2.xsd">
 
  <int:channel id="channel" />
  
</beans>

Các Message Channel identify với nhau bằng bean ID của các Message Channel đó. Trong ví dụ này, mình chỉ cần tạo một Message Channel là đủ, các bạn có thể tạo nhiều nếu muốn!

Để ứng dụng của chúng ta có thể cứ sau 5s thì gửi một Message, chúng ta sẽ định nghĩa một Message Endpoint sử dụng Polling Channel Adapter của Spring Integration với tag <int:inbound-channel-adapter/> như sau:

<int:inbound-channel-adapter channel="channel" expression="{'Khanh'}">
  <int:poller fixed-delay="5000" />
</int:inbound-channel-adapter>

Thuộc tính expression sẽ giúp chúng ta định nghĩa data sẽ được tạo ra khi Poller được trigger. Giá trị của thuộc tính expression này hỗ trợ Spring Expression Language, nên các bạn có thể bất kỳ giá trị nào, miễn thoả mãn Spring Expression Language là được!

Thuộc tính channel dùng để định nghĩa Message Channel mà data được tạo ra sẽ được chuyển đi. Giá trị của thuộc tính channel này là bean ID của Message Channel các bạn nhé!

Bên trong tag <int:inbound-channel-adapter/>, chúng ta định nghĩa tag <int:poller/> với thuộc tính fixed-deplay có giá trị là 5s để sau 5s thì Poller của chúng ta sẽ được trigger đó các bạn!

Bây giờ chúng ta sẽ sử dụng Logging Channel Adapter với tag <int:logging-channel-adapter/> để consume Message từ Polling Channel Adapter và in ra dòng chữ “Hello Khanh from Huong Dan Java”, như sau:

<int:logging-channel-adapter channel="channel"
  logger-name="com.huongdanjava.springintegration"
  expression="'Hello '.concat(payload).concat(' from Huong Dan Java')" />

Logging Channel Adapter sẽ consume Message từ channel có bean ID là “channel”, data được log sẽ được lấy từ thuộc tính expression của tag <int:logging-channel-adapter/>. Các bạn cần thêm tập tin cấu hình của Logging Framework để log message theo ý của mình nhé!

Để chạy ứng dụng này, mình sẽ tạo một class với main() method với nội dung như sau:

package com.huongdanjava.springintegration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Application {
 public static void main(String[] args) {
    new ClassPathXmlApplicationContext("spring-integration.xml");
  }
}

Kết quả khi chạy ứng dụng trên như sau: