Home Blog Page 181

20 câu hỏi phỏng vấn Javascript dành cho Intern/Fresher

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

Câu hỏi phỏng vấn Javascript dưới đây sẽ giúp bạn vượt qua được những câu hỏi của nhà tuyển dụng.

Giới thiệu

Theo một cuộc điều tra cách mạng ẩn danh mà mình tìm hiểu được thì trong cuộc sống có 2 thứ khó hiểu nhất. Đối với nam giới thì đó là phụ nữ, còn đối với lập trình viên thì đó hẳn là javascript rồi.

Javascript là ngôn ngữ không thể thiếu trong thời đại hiện nay. Dù bạn có học ngôn ngữ gì đi chăng nữa thì bạn vẫn cần phải biết về javascript.

Hôm nay mình xin chia sẻ một chút kiến thức về javascript, cụ thể là các câu hỏi phỏng vấn JavaScript mà nhà tuyển dụng thường sẽ hỏi bạn.

Bài viết này mình viết với mục đích dành cho các bạn Intern, Fresher trong quá trình đi phỏng vấn có thể tham khảo vì đây là những câu hỏi liên quan đến javascript mà rất dễ bị “sờ gáy”.

Bắt đầu nào!

  Tôi đã phỏng vấn ở Silicon valley như thế nào (Phần 1)

Câu hỏi phỏng vấn JavaScript dành cho Intern/ Fresher

#1. Javascript là gì?

Trả lời: Javascript là một ngôn ngữ lập trình kịch bản dựa vào đối tượng phát triển có sẵn hoặc tự định nghĩa ra, javascript được sử dụng rộng rãi trong các ứng dụng Website. Nó là một ngôn ngữ thông dịch.

#2. Các kiểu dữ liệu trong Javascript?

Trả lời: Có 6 kiểu đó là StringNumberObjectUndefinedBooleanArrayNull

Ví dụ:

// String
var a = 'viblo';
// Number
var b = 3;
// Object
var c = { a: 1, b: '2' }
// Undefined
var d;
// Boolean
var e = 10 < 11;
// Array
var f = [1, 2, 3, 'z'];

#3. Hàm delete có chức năng gì?

Trả lời: Hàm delete loại bỏ một thuộc tính khỏi object; nếu không tồn tại tham chiếu tới thuộc tính, nó sẽ tự động giải phóng.

Ví dụ:

var user = { name: 'Vu', age: 18 };
delete student.age;
console.log(student)

// => { name: 'Vu' }

#4. Phân biệt var, let và const?

Trả lời: const dùng để khai báo một hằng số – là một giá trị không thay đổi được trong suốt quá trình chạy.
let tạo ra một biến chỉ có thể truy cập được trong block bao quanh nó
var – tạo ra một biến có phạm vi truy cập xuyên suốt function chứa nó.

Ví dụ:

// let
if (true) {
  let text = 'in if statement'
}
 
console.log(text) // undefinded

//const
const a = 'vu';
a = 'nguyen'; // Lỗi Identifier 'a' has already been declared

// var
var a = 'viblo';
if (true) {
  var a = 'viblo.asia';
  console.log(a); // 'viblo.asia'
}
console.log(a); // 'viblo.asia'

#5. Strict mode trong javascript là gì?

Trả lời: Strict theo nghĩa tiếng Việt là “nghiêm khắc”. Strict Mode là một quy mẫu nghiêm khắc trong Javascript. Nếu như việc viết code bình thường là Normal mode, thì Strict Mode sẽ có thêm các quy định khác so với Normal mode.

Ví dụ:

"use strict";
function foo(){
    var bar = 'viblo';
    return bar;
}

// Uncaught ReferenceError: bar is not defined
bar = 'asia';

#6. this trong javascript là gì?

Trả lời: Từ khóa this dùng để chỉ đối tượng từ nơi nó được gọi.

Ví dụ:

var data = {
  name: "vu",
  age: 18,
  getName: function(){
      return this.name; // this = data;
  }
};

console.log(data.getName()) // 'vu'

#7. Khác nhau giữa undefined và null trong javascript?

Trả lời: Khi tạo ra một biến mà không gán giá trị thì nó sẽ là undefined. Còn null là một object

Ví dụ:

var a;
console.log(typeof a) // undefined
console.log(typeof null) // object

#8. == và === khác nhau như thế nào?

Trả lời: Toán tử == kiểm tra tính bằng nhau, còn === kiểm tra cả tính bằng nhau và cả kiểu dữ liệu

Ví dụ:

var number1 = 1;
var number2 = '1';

console.log(number1 == number2) // true
console.log(number1 === number2) // false

#9. Thay đổi style/class của element?

Trả lời: Sử dụng thuộc tính document trong javascript. Có thể sử dụng với id, class hay bất cứ element nào.

Ví dụ:

document.getElementById("myId").style.backgroundColor = "red";
document.getElementById("myId").className = "newclass";
document.getElementByClass("myClass").className = "newclass";
document.getElementByTagsName("myTagsName").className = "newclass";

#10. Tại sao Math.max() nhỏ hơn Math.min()?

Trả lời: Khi chạy code Math.max() > Math.min(), giá trị trả về là False, nghe có vẻ không hợp lý. Tuy nhiên, nếu không có tham số nào được truyền vào, Math.min() trả về Infinity và Math.max() trả về -Infinity. Vậy nên Math.max() < Math.min().

Ví dụ:

var infinity = 5

var value1 = Math.min(1)
var value2 = Math.min(1, infinity)
var value3 = Math.min(1, -infinity)

console.log(value1) // 1
console.log(value2) // 1
console.log(value3) // -5

#11. Closure trong javascript là gì?

Trả lời: Closure là một hàm bên trong, truy cập đến các giá trị bên ngoài phạm vi của nó. Closure có thể truy cập vào các biến trong phạm vi của riêng nó (Variables in their own scope), trong hàm (Variables in the function’s scope), và biến toàn cục (Global variables).

Ví dụ:

const arr = [1, 2, 3, 4];

for (var i = 0; i < arr.length; i++) {
  setTimeout(function() {
    console.log(i);
  }, 10);
}

// 4 4 4 4

Lý do là bởi vì hàm setTimeout sẽ tạo ra 1 function (closure) có thể truy cập phạm vi bên ngoài nó, vòng loop sẽ chứa index i. Sau 10ms, hàm được thực thi và nó sẽ log ra giá trị của i, là giá trị cuối cùng của vòng lặp (4). Xem thêm JavaScript Closures là gì

#12. Hosting trong javascript là gì?

Trả lời: Hoisting là hành động mặc định của Javascript, nó sẽ chuyển phần khai báo lên phía trên top Trong Javascript, một biến (variable) có thể được khai báo sau khi được sử dụng.

Ví dụ:

a = 'https://viblo.asia';
console.log("My website: ", a); // My website: https://viblo.asia
var domain;
console.log("My website: ", a); //  // My website: https://viblo.asia

#13. Phân biệt giữa Function Declaration và Function Expression

Trả lời: Function declaration sẽ sử dụng từ khóa function rồi đến tên hàm. Còn Function expression sẽ được bắt đầu với từ khóa var, const, hoặc let.

Ví dụ:

// Function Declaration:
function a(x,y,z) {
    // code here
}

// Function Expression
const a = function(x,y,z) {
    // code here
}

#14. Hàm Array.splice() và hàm Array.slice() khác nhau như thế nào ?

Trả lời: Hàm Array.splice() sẽ thay thế một hoặc một số phần tử của mảng bằng một hoặc một số phần tử khác. Trong khi hàm Array.slice() sẽ trích xuất một số phần tử của mảng, vị trí bắt đầu và kết thúc việc trích xuất sẽ được xác định bởi tham số truyền vào hàm. Lưu ý hàm sẽ trích xuất không bao gồm phần tử end truyền vào.

Ví dụ:

// Array.splice()
var language = ["php", "css", "html", "js"];
language.splice(1, 1, "python", "c#", "ios");
console.log(language) // ['php', 'python', 'c#', 'ios', 'html', 'js'];
// Array.slice()
var language = ["html", "js", "php", "c#", "python", "androi", "ios"];
var slice = language.slice(1, 4);
console.log(slice); // ['js(1)', 'php(2)', 'c#(3)']

#15. Spread Operator trong javascript ?

Trả lời: Spread operator là một biểu thức mở rộng giúp gộp các phần tử vào trong một cách viết ngắn gọn hơn. Cách viết này được thể hiện bằng dấu ...

Ví dụ:

var topLane = ['zed', 'akali'];
var all = ['yasuo', 'rengar', ...topLane, 'đan trường'];
console.log(all) //  ['yasuo', 'rengar', 'zed', 'akali', 'đan trường']

#16. Anonymous function là gì ?

Trả lời: Là một hàm ẩn danh, không có tên gọi, thường được sử dụng khi xử lý các công việc có quy mô nhỏ, vì thế không cần thiết phải khởi tạo tên định danh cho hàm này. Giúp nó có tốc độ xử lý nhanh hơn hàm truyền thống phải có tên định danh.

Ví dụ:

var anonymous = function(a, b) {
    return a + b;
};
console.log(anonymous(5, 10)); // 15
//Anonymous Function không có đối số
var anonymous = function() {
    return "Hello World";
};
console.log(anonymous()); // Hello World

(function(){
    console.log('viblo');
}).call(this) // viblo

#17. Tại sao 0.1 + 0.2 không bằng 0.3 ?

Trả lời: Vấn đề này liên quan đến việc Javascript lưu trữ dữ liệu float ở dạng nhị phân chính xác tới từng con số sau dấu phẩy. Hơn nữa máy tính không thể biểu diễn chính xác số thập phân, nên gây ra sai số kiểu này. Giải pháp ở đây có thể sử dụng hàm toFixed() để đạt được kết quả đúng.

console.log(0.1 + 0.2) //0.30000000000000004

// Sử dụng toFixed()
var number = 0.1 + 0.2;
console.log(number.toFixed(2)) // 0.3

#18. Sự khác nhau giữa window.onload và onDocumentReady ?

Trả lời: Sự kiện window.onload có ý nghĩa rằng khi trình duyệt đã load xong mọi thứ (image, js, css) thì những đoạn code nằm bên trong đó mới được chạy. Với onDocumentReady, mọi thứ bên trong hàm này sẽ được load ngay khi DOM được load và trước khi toàn bộ nội dung bên ngoài được load.

#19. Kết quả của 1 + 2 + ‘3’ ?

Trả lời: 33. 1 và 2 là kiểu integer, khi cộng lại sẽ được 3, sau đó sẽ nối với string ‘3’ để được kết quả là 33.

#20. Promise trong javascript là gì ?

Trả lời: Promise là một cơ chế trong JavaScript giúp bạn thực thi các tác vụ bất đồng bộ mà không rơi vào callback hell hay pyramid of doom, là tình trạng các hàm callback lồng vào nhau ở quá nhiều tầng. Có 3 trạng thái: pendingfulfilledreject.

Hi vọng sau khi đọc xong bài này các bạn có thể nhớ thêm, học thêm một chút gì đó về javascript. Mong có thể giúp ích cho các bạn.

Đừng bỏ lỡ những bài viết hay về:

Xem thêm tuyển dụng JavaScript Developer trên TopDev

TopDev via viblo.asia

SVG là gì? Tại sao nên dùng SVG để tăng tốc cho web

Việc hiển thị hình ảnh trên nhiều độ phân giải màn hình là một vấn đề đau đầu với bất kì một ai dù là trên web hay ứng dụng di động.

Hôm nay bài này sẽ giới thiệu cho các bạn một thủ thuật. Đó là việc dùng hình ảnh dạng vector, mà cụ thể là SVG để tiết kiệm công sức, tăng tốc độ load trang, giảm dung lượng website.

SVG là gì?

SVG là viết tắt của Scalable Vector Graphics. SVG là một ngôn ngữ dạng XML, dùng để miêu tả hình ảnh đồ họa vector 2 chiều, tĩnh và hoạt hình. Bạn cũng có thể hiểu là nó một định dạng hình ảnh (tương tự như ảnh bitmap JPG, PNG…). Chỉ khác là chúng sử dụng cấu trúc XML để hiển thị hình ảnh dưới dạng vector còn ảnh bitmap sử dụng cấu trúc ma trận pixel. Tập tin có đuôi .svg được mặc định hiểu là tập tin SVG.

Tại sao nên dùng SVG?

  1. Chất lượng hình ảnh tốt: Vì là hình ảnh dạng vector nên chúng ta có thể hiển thị, co giãn (scale) thoải mái mà không làm giảm chất lượng hình ảnh.
  2. Tiết kiệm dung lượng: Vì là hình ảnh dạng vector nên dung lượng một file hình ảnh SVG rất nhỏ so với một file hình ảnh thông thường.
  3. Animation: Tất cả mọi element và thuộc tính của chúng trong file SVG đều có thể animate được. Nên chúng ta hoàn toàn có thể sử dụng một file SVG duy nhất và dùng CSS hoặc Javascript để làm animation cho từng thành phần của hình ảnh đó. Nó giúp giảm bớt lượng request và làm cho trang web của bạn load nhanh cực kỳ dù cho có animation rất nhiều.
  4. Độ tương thích tốt: Sau nhiều năm không tương thích trình duyệt, SVGs cuối cùng đã đến. Chúng được hỗ trợ trong tất cả các trình duyệt hiện đại.

Bảng so sánh:

Loại định dạng Bảng màu Công dụng
JPG Nén mất dữ liệu Hàng triệu màu sắc Ảnh tĩnh, nhiếp ảnh
PNG-8 Nén không mất dữ liệu Tối đa 256 màu Tương tự như định dạng GIF, xử lý transparency tốt hơn nhưng không có hình động, tuyệt vời khi sử dụng cho biểu tượng
PNG-24 Nén không mất dữ liệu Không giới hạn màu sắc Tương tự như định dạng PNG-8, xử lý hình ảnh tĩnh và transperency
GIF Nén không mất dữ liệu Tối đa 256 màu Hình động đơn giản, đồ họa với màu trơn, đồ họa không có gradient
SVG Vector/ Nén không mất dữ liệu Không giới hạn màu sắc Đồ họa/Logo cho web, màn hình Retina/độ phân giải dpi cao

 

Một ưu điểm của SVG là tất cả mọi element và attribute của các element đó đều có thể animate.

Ví dụ một file SVG để vẽ hình tròn:

<svg width="100" height="100">
  <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>

Hãy xem hình bên dưới, đây là 2 hình ảnh giống nhau, bên trái là hình ảnh với định dạng thông thường, tức là hình ảnh sử dụng cấu trúc từng pixel, hình bên phải là một hình ảnh vector. Và khi chúng ta phóng to hình ra, đây là kết quả:

Những thành phần cơ bản của SVG

  • <svg> là thẻ bao ngoài, định nghĩa đó là phần tử SVG.
  • <line> tạo đường thẳng đơn.
  • <rect> Tạo hình chữ nhật và hình vuông.
  • <polygon> Tạo hình đa giác, với ba hoặc nhiều cạnh.
  • <path> Tạo bất kỳ hình nào mà bạn thích bằng cách định nghĩa những điểm và đường thẳng giữa chúng.
  • <defs> Định nghĩa những tài nguyên có thể sử dụng lại. Không có gì nằm trong phần <defs> được hiển thị.
  • <g> Gom nhiều hình dạng thành một nhóm. Đặt các nhóm trong phần <defs>để cho phép chúng được sử dụng lại.
  • <use> Lấy những tài nguyên được định nghĩa bên trong phần <defs> và làm cho chúng hiển thị trong SVG.

SVG Tools

Một số tool hỗ trợ cho bạn vẽ các hình ảnh SVG như là:

Sử dụng SVG như là ảnh tĩnh

Khi bạn sử dụng thẻ HTML <img> hoặc CSS background-url thì SVG cũng hoạt động giống hệt bitmap:

<!-- HTML image -->
<img src="image.svg" alt="a vector graphic" />
/* CSS background */
.myelement {
  background-image: url('image.svg');
}

Trình duyệt sẽ disable mọi đoạn script, link hay các tính năng tương tác khác được nhúng vào file SVG. Bạn có thể thao tác SVG bằng cách sử dụng CSS giống với các loại ảnh bình thường như là filter, transform,… Kết hợp CSS với SVG thường cho kết quả tốt hơn vì ảnh SVG có thể thu nhỏ được vô hạn.

Chèn ảnh SVG vào code CSS

Một SVG có thể được viết trực tiếp trong code CSS bằng thuộc tính background. Nó phù hợp cho những icon nhỏ, tái sử dụng được và tránh việc thêm những request HTTP.

.element {
    background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600"><circle cx="400" cy="300" r="50" stroke-width="5" stroke="#f00" fill="#ff0" /></svg>') center center no-repeat;
}

ViewBox ở đây định nghĩa tọa độ không gian. Trong ví dụ trên, sẽ có 1 vòng tròn màu vàng viền đỏ, và có diện tích là 800×600 bắt đầu từ vị trí 0, 0.

Responsive với ảnh SVG

Khác với ảnh thông thường, ảnh SVG phải xác định thuộc tính width và height cho ảnh, bởi nếu ko set thì nó sẽ coi như là max-width bằng 0 và sẽ không thể nhìn thấy hình ảnh.

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300">

 

Chèn ảnh SVG vào code HTML

Ảnh SVG có thể được đặt trực tiếp vào code HTML, khi đó nó sẽ trở thành 1 phần của cây DOM và có thể thao tác với CSS và Javascript:

<p>SVG is inlined directly into the HTML:</p>

<svg id="invader" xmlns="http://www.w3.org/2000/svg" viewBox="35.4 35.4 195.8 141.8">
  <path d="M70.9 35.4v17.8h17.7V35.4H70.9zm17.7 17.8v17.7H70.9v17.7H53.2V53.2H35.4V124h17.8v17.7h17.7v17.7h17.7v-17.7h88.6v17.7h17.7v-17.7h17.7V124h17.7V53.2h-17.7v35.4h-17.7V70.9h-17.7V53.2h-17.8v17.7H106.3V53.2H88.6zm88.6 0h17.7V35.4h-17.7v17.8zm17.7 106.2v17.8h17.7v-17.8h-17.7zm-124 0H53.2v17.8h17.7v-17.8zm17.7-70.8h17.7v17.7H88.6V88.6zm70.8 0h17.8v17.7h-17.8V88.6z"/>
  <path d="M319 35.4v17.8h17.6V35.4H319zm17.6 17.8v17.7H319v17.7h-17.7v17.7h-17.7V159.4h17.7V124h17.7v35.4h17.7v-17.7H425.2v17.7h17.7V124h17.7v35.4h17.7V106.3h-17.7V88.6H443V70.9h-17.7V53.2h-17.7v17.7h-53.2V53.2h-17.7zm88.6 0h17.7V35.4h-17.7v17.8zm0 106.2h-35.5v17.8h35.5v-17.8zm-88.6 0v17.8h35.5v-17.8h-35.5zm0-70.8h17.7v17.7h-17.7V88.6zm70.9 0h17.7v17.7h-17.7V88.6z"/>
</svg>

<p>The SVG is now part of the DOM.</p>

 

Bạn có thể định nghĩa chiều rộng và chiều cao cho ảnh SVG ở trong CSS như thế này:

#invader {
  display: block;
  width: 200px;
}

#invader path {
  stroke-width: 0;
  fill: #080;
}

See the Pen
HTML-Inlined SVG by SitePoint (@SitePoint)
on CodePen.

Các phần tử SVG như là paths, circle, hay rectangles có thể chỉnh sửa được style như CSS:

/* CSS styling for all SVG circles */
circle {
  stroke-width: 20;
  stroke: #f00;
  fill: #ff0;
}

 

Khi chỉnh sửa như vậy thì nó sẽ bị ghi đè lên bất kì thuộc tính nào được xác định trong SVG vì CSS được ưu tiên cao hơn. SVG CSS có 1 số lợi ích:

  • attribute-based styling có thể được loại bỏ khỏi SVG để làm giảm dung lượng trang.
  • CSS có thể được sử dụng lại cho các ảnh SVG khác ở các trang khác nhau.
  • Có thể sử dụng các hiệu ứng của CSS lên SVG như là: :hoveranimationtransition

SVG Sprites là gì?

Thuật ngữ Sprites thực ra là kỹ thuật đưa tất cả các hình ảnh trang trí như các icon hay button đặt vào một file hình duy nhất. Sau đó dùng thuộc tính background-position của CSS để hiện ra đúng vị trí cần thiết. Lợi ích của kỹ thuật này là thay vì server bạn phải nhận rất nhiều request cho những tấm ảnh nhỏ…khiến cho web bạn load chậm đi. Lúc này bạn chỉ cần bỏ tất cả ảnh vào 1 tấm duy nhất, server chỉ nhận dc một request nhẹ nhàng, chưa kể tấm ảnh này dung lượng sẽ nhỏ hơn nhiều tấm ảnh kia cộng lại.

SVG cũng có sprites giống như ảnh thông thường. Một file SVG có thể chứa số lượng ảnh bất kì. Ví dụ file .svg này chứa folder icon được tạo bởi IcoMoon. Mỗi một icon lại được chứa trong 1 thẻ <symbol> và có 1 ID riêng biệt.

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <symbol id="icon-folder" viewBox="0 0 32 32">
      <title>folder</title>
      <path d="M14 4l4 4h14v22h-32v-26z"></path>
    </symbol>
    <symbol id="icon-folder-open" viewBox="0 0 32 32">
      <title>open</title>
      <path d="M26 30l6-16h-26l-6 16zM4 12l-4 18v-26h9l4 4h13v4z"></path>
    </symbol>
    <symbol id="icon-folder-plus" viewBox="0 0 32 32">
      <title>plus</title>
      <path d="M18 8l-4-4h-14v26h32v-22h-14zM22 22h-4v4h-4v-4h-4v-4h4v-4h4v4h4v4z"></path>
    </symbol>
    <symbol id="icon-folder-minus" viewBox="0 0 32 32">
      <title>minus</title>
      <path d="M18 8l-4-4h-14v26h32v-22h-14zM22 22h-12v-4h12v4z"></path>
    </symbol>
    <symbol id="icon-folder-download" viewBox="0 0 32 32">
      <title>download</title>
      <path d="M18 8l-4-4h-14v26h32v-22h-14zM16 27l-7-7h5v-8h4v8h5l-7 7z"></path>
    </symbol>
    <symbol id="icon-folder-upload" viewBox="0 0 32 32">
      <title>upload</title>
      <path d="M18 8l-4-4h-14v26h32v-22h-14zM16 15l7 7h-5v8h-4v-8h-5l7-7z"></path>
    </symbol>
  </defs>
</svg>

Kết luận – Khi nào thì dùng SVG?

Tất nhiên không thể dùng SVG trong 100% mọi trường hợp. Nhược điểm của SVG là giới hạn về độ chi tiết và màu sắc, tất nhiên chúng ta có thể sử dụng SVG để vẽ một hình ảnh phức tạp, hoặc thực như ảnh chụp, nhưng nếu làm vậy thì performance sẽ rất tệ.

Nhưng với xu hướng hiện nay, phong cách thiết kế phẳng đang là mốt, những website với giao diện đơn giản, sử dụng hình ảnh cũng đơn giản, ít chi tiết thì SVG hoàn toàn có thể phát huy được thế mạnh của mình.

Tìm việc làm ngành CNTT lương cao

100 Tips cho Lập trình viên siêu giỏi

tips cho lập trình viên

Giới thiệu

Lập trình là một công việc có tốc độ phát triển và đổi mới rất nhanh. Để không bị tụt lại phía sau, cập nhật kiến thức và phát triển bản thân, dưới đây là 100 tips cho lập trình viên mà có thể bạn sẽ cần.

Cùng khám phá 100 tips này nhé!

  8 tips giúp tăng hiệu suất làm việc với Github

Tips cho lập trình viên 

1. “Chơi” Google đúng cách

Là 1 lập trình viên, bạn phải biết cách search câu trả lời cho các câu hỏi của mình. Khi bạn biết cách search Google hiệu quả, bạn sẽ tiết kiệm được rất nhiều thời gian của mình và có thể code tốt hơn đó.

2. Giữ lời hứa và làm đúng deadline

Sẽ tốt hơn nếu team bạn biết task của mình và hoàn thành sản phẩm trong 3 tuần cho khách hàng hay công ty của bạn. Giữ đúng lời hứa và hoàn thành kịp deadline, bạn sẽ xây dựng được niềm tin cho mình.

3. Đối xử tốt với designer, họ là bạn không phải là kẻ thù

Designer cung cấp giải pháp, “gãi đúng chỗ ngứa” cho người dùng. Học hỏi từ họ và làm việc đoàn kết sẽ cho ra sản phẩm hiệu quả nhất.

4. Tìm một “sư phụ” cho mình

Tìm một ai đó bạn có thể học hỏi được cũng như bàn luận về các ý tưởng với họ. Coding Coach là một nơi tuyệt vời nếu bạn đang cần tìm một sư phụ cho mình đấy.

5. Hãy trở thành “sư phụ” của người khác

Sau khi tìm được sư phụ cho mình, học hỏi đủ và ở một đẳng cấp cao hơn, bạn có thể thử trở thành người chỉ dẫn cho người mới giống như bạn ngày trước. Giúp họ học hỏi và đưa ra những ý tưởng tuyệt vời nhất.

6. Viết comment có tâm

Khi viết comment, bạn nên giải thích tại sao, chứ không phải là bắt bẻ người ta đang làm cái gì.

7. Đặt tên biến và hàm thích hợp

Bạn nên đặt tên biến và hàm chính xác với mục đích của chúng.

8. Đi nghỉ mát

Chúng ta cần thời gian để xả stress. Nếu bạn muốn thì hay đi du lịch. Não của bạn và đồng nghiệp sẽ rất biết ơn nếu bạn đi chơi đấy!

9. Xoá code không hữu dụng

Không lý do gì gánh thêm bug về cho mình nhé.

10. Học cách đọc code

Đọc code mặc dù là một kỹ năng bị đánh giá thấp, nhưng lại vô cùng hữu ích cho bạn.

Xem thêm Hướng dẫn đọc code cho bạn.

11. Cân bằng giữa công việc và cuộc sống

Bạn cần thời gian để nghỉ ngơi sau 1 ngày dài làm việc. Tắt thông báo về công việc và xoá mọi ứng dụng không cần thiết ra khỏi điện thoại của bạn nhé.

12. Chỉ lên lịch nhưng cuộc gặp mặt cần thiết

Nếu chỉ cần giải quyết qua mail hay nhắn tin, thì bạn nên làm vậy và hạn chế gặp nhau. Còn nếu bắt buộc phải gặp, thì hãy sắp xếp thời gian, càng nhanh càng tốt.

13. Lập trình cặp

Lập trình cặp cho phép bạn tham gia với cả 2 vai là thầy và trò.

Tips cho Lập trình viên

14. Viết email tốt

Học cách thu hút audience trong email bằng cách cô đọng và rõ ràng. Không ai muốn đọc một cái mail dài 4 trang cả đâu.

15. Tham gia vào các cộng đồng

Gặp gỡ nhiều người cùng ngành và đam mê sẽ giúp bạn phát triển hơn.

16. Dọn dẹp branch

Dọn branch của bạn như dọn nhà trước khi có khách tới. Nếu bạn không cần cái gì, bỏ luôn chứ đừng quăng nó ở đâu đó.

17. Đừng giữ cửa

Ai cũng có thế mạnh riêng cả. Nếu người ngoại đạo muốn vào ngành, hãy ủng hộ họ. Đừng nói rằng họ không đủ giỏi để vào ngành của chúng ta.

18. Luôn học hỏi

Bạn đã chọn cái nghề mà luôn phải học rồi. Vậy nên làm quen với điều đó đi.

19. Đừng từ bỏ

Sẽ không bao giờ dễ dàng cho bạn. Nhưng chúng ta đều có xuất phát điểm như nhau mà, phải không? Bạn có thể làm được. Cố lên nhé!

20. Nhận task khó

Task dễ sẽ không bao giờ giúp bạn phát triển được.

21. Hiểu rõ yêu cầu trước khi bắt tay vào làm

Bạn nên hiểu các tiêu chí đã được chấp nhận trước khi bắt tay vào code. Bạn sẽ đỡ đau đớn và mất thời gian hơn rất nhiều sau này đó.

22. Có một bộ công cụ cho mình

Bạn hãy chuẩn bị cho mình một bộ công cụ đầy đủ. Hiểu rõ công cụ nào hỗ trợ cái gì và nó sẽ giúp ích cho bạn khi vào project rất nhiều đó.

Tips cho Lập trình viên

23. Học cách yêu những lời chỉ trích mang tính xây dựng

Hãy hỏi những người đồng nghiệp và bạn bè đáng tin cậy của bạn để cho nhận xét. Cách này sẽ giúp bạn phát triển nhanh hơn trên con đường lập trình viên.

24. Luôn mở mang đầu óc

Công nghệ luôn thay đổi nhanh chóng. Đừng phản đối những công nghệ mới mà hãy học nó rồi đưa ý kiến sau.

25. Cập nhật tin tức

Luôn cập nhật những tin tức công nghệ mới nhất bằng cách theo dõi các cộng đồng, blog, podcast, tin công nghệ,…

26. Tập trung giải quyết vấn đề

Với kỹ năng giải quyết vấn đề tốt, bạn có thể chinh phục mọi vấn đề. Tập trung vào những thứ cần thiết để giải quyết vấn đề.

27. Khiêm tốn

Không cần biết bạn làm chức gì và ở công ty nào, hãy luôn khiêm tốn nhé!

28. Học thuyết trình tốt

Học cách thu hút người nghe và có một bài thuyết trình cực hay nhé!

29. Kiểm tra tất cả những giải pháp trước khi nhảy vô làm

Đừng làm liền giải pháp đầu tiên. Hãy thử mọi phương án trước khi bắt đầu code.

30. Tìm kiếm ngách riêng cho mình

Có nhiều lĩnh vực trong ngành CNTT. Hãy tìm lĩnh vực nào bạn thích nhất và trở thành một chuyên gia về lĩnh vực đó.

31. Có thói quen lập trình tốt

Cố gắng có những thói quen nhất quán và lành mạnh cho việc code. Ví dụ như bỏ qua những thứ làm bạn phân tâm, làm task nhanh chóng, đi họp đều đặn, bắt đầu với task ưu tiên nhất,… Có thể bạn sẽ mất thời gian để làm quen, nhưng về sau này thì sẽ rất có ích cho bạn đấy.

Xem thêm 10 thói quen của một lập trình viên thành công

32. Học cách debug

Khám phá các công cụ debugger trình duyệt. Học debug I/O với IDE của bạn. Bằng cách học những phương pháp hiệu quả để debug và tìm lỗi, bạn có thể giải quyết những con bug khó nhất.

Tips cho Lập trình viên

33. Luyện kỹ năng của bạn thường xuyên

Việc bạn biết một kỹ năng nào đó rồi không có nghĩa là bạn không luyện tập nó. Các kỹ năng có thể mờ đi theo năm tháng nếu bạn không liên tục cải thiện nó, đặc biệt là trong cách ngành phát triển rất nhanh như thế này thì việc luyện tập là vô cùng quan trọng. Hãy bỏ ngay cái suy nghĩ “Mình luôn làm cách này”, mà hãy thử nghĩ là: “Liệu có cách tốt hơn không?”.

Nói đơn giản là, bạn có 6 múi rồi không có nghĩa là bạn được ăn thoải mái không tập tành gì mà vẫn giữ được 6 múi.

34. Hiểu lý do tại sao

Sẽ đến lúc bạn cần phải nói ra quan điểm của mình. Và sẽ rất quan trọng cho bạn để hiểu được lý do đằng sau vấn đề mà bạn đang tìm hiểu. Tại sao giải pháp A thì tốt hơn B? Chỉ khi nào bạn giải thích được, thì ý kiến và lời nói của bạn mới có trọng lượng.

35. Hiểu được giá trị của mình

Bạn cần nhận lại được những gì tương xứng với thứ mình bỏ ra. Luôn nắm được mức lương và thu nhập trong ngành của bạn ở khu vực bạn đang đi làm. Nếu nó thấp hơn mức trung bình, thì đã đến lúc nói chuyện với sếp và thoả thuận một mức lương tốt hơn rồi đấy.

36. Đừng sợ khi hỏi xin sự giúp đỡ

Nếu bạn đang gặp rắc rối với 1 vấn đề nào đó và đã tốn quá nhiều thời gian tìm kiểu giải pháp, đã đến lúc cầu cứu rồi đấy. Chúng ta cũng là con người với nhau mà. Con người thì cần phải hỗ trợ giúp đỡ lẫn nhau. Chẳng việc gì phải xấu hổ khi tìm đồng nghiệp để giúp mình đâu.

37. Học cách học

Người ta học theo nhiều cách khác nhau. Một vài người học qua video hướng dẫn, người khác thì đọc sách… Hãy tự tìm ra cách học tốt nhất cho bản thân và học thật siêng năng nhé các bạn.

38. Hãy tử tế với mọi người

Khi bạn nhận xét về đồng nghiệp, hãy nhẹ lời thôi. Bạn có thể nêu lên quan điểm của mình về cách làm việc của đồng nghiệp, chứ đừng chì chiết hay dùng lời lẽ quá nặng để nói với họ.

39. Biết nghỉ giải lao

Bạn không thể dành 8 tiếng đồng hồ liên tục để code được. Bạn sẽ mất sức nhanh chóng và để lại rất nhiều lỗi trong phần mềm của mình đấy. Vậy nên hãy hẹn giờ đồng hồ để nhắc bạn tạm dừng công việc và nghỉ ngơi. Đi bộ, uống cafe, tán gẫu với đồng nghiệp,… Rời mắt khỏi màn hình một chút sẽ giúp bạn lấy lại sức và chất xám, từ đó nâng cao chất lượng công việc của bạn đấy.

40. Theo dõi tiến trình

Sẽ không hay nếu bạn code một thời gian dài mà không thấy mình phát triển thêm hay đạt được gì. Bạn nên theo dõi những gì mình đạt được và tiến trình phát triển của bản thân. Dán một tờ note với list những gì bạn làm được trên máy tính của mình. Mỗi lần bạn làm được gì, hay viết lên đó, dù là việc nhỏ nhất. Những gì bạn làm được sẽ đem đến cho bạn một giá trị lớn hơn về sau.

41. Đừng dựa vào framework và thư viện

Học sâu về ngôn ngữ tốt hơn là học cách dùng framework và thư viện. Bạn không thật sự cần học về các thư viện hay framework, nhưng nếu bạn hiểu cách mà chúng hoạt động, thì sẽ giúp bạn viết code đẹp hơn và rõ hơn đấy.

42. Học cách yêu việc review code

Nhờ ai đó đọc và phân tích code cho bạn nghe có vẻ kinh khủng, nhưng có thể giúp bạn nhận được nhiều lời nhận xét giá trị để làm lập trình tốt hơn. Bạn cũng nên tập review code cho người khác nữa nhé.

43. Học những lĩnh vực khác

Bạn nên tìm hiểu thêm cơ bản về một số lĩnh vực khác có liên quan đến lập trình như thiết kế, marketing, lập trình frontend hay backend,… Điều này sẽ giúp bạn trở thành một lập trình viên toàn diện hơn.

44. Đừng chọn công nghệ dễ cho mình, hãy chọn công nghệ đúng cho mình

Mỗi project sẽ có những yêu cầu khác nhau, và chúng ta cần chọn những công cụ phù hợp cho từng công việc phải làm. Mặc dù chọn công cụ bạn đã từng làm sẽ thoải mái hơn, nhưng nếu chúng không phù hợp với yêu cầu của project, đã đến lúc bạn cần tìm cái khác để thay thế rồi.

45. Chịu trách nhiệm cho mọi lỗi sai

Đã là người thì chắc chắn phải mắc sai lầm, và bạn sẽ còn mắc nhiều lỗi sai hơn nữa trong suốt sự nghiệp của mình. Chính vì vậy, biết và nhận trách nhiệm khi mắc lỗi sai vô cùng quan trọng. Bạn sẽ xây dựng được lòng tin với team của mình cũng như sếp của mình.

46. Tự review code của chính mình

Trước khi bạn mở pull request, hãy xem lại code của mình trước. Nếu như đó là code của đồng nghiệp, thì bạn sẽ comment gì? Điều quan trọng là đoán trước được vấn đề hay lỗi sai trước khi yêu cầu review code.

47. Học từ thất bại của bản thân

Thất bại là mẹ thành công. Chúng ta sẽ gặp nhiều thất bại trên đường đời của mình. Học từ thất bại, sẽ giúp bạn biết hướng đi đúng hơn trong tương lai.

Tips cho Lập trình viên

48. Biết điểm yếu của mình

Hãy hiểu chính mình. Điểm yếu của bạn là gì? Có thể bạn sẽ luôn quên cập nhật test trước khi push, hay bạn rất tệ trong việc trả lời email,… Biết điểm yếu của bạn sẽ giúp bạn loại bỏ được chúng.

49. Luôn tò mò

Đây là ngành luôn không ngừng tiến hoá, vậy nên tò mò sẽ rất quan trọng. Nếu bạn không hiểu thứ gì, một yêu cầu của project hay một dòng code, hãy nói ra. Không ai chỉ trích bạn vì hỏi để làm rõ và bạn sẽ code tốt hơn nhiều.

50. Đừng cố học mọi thứ

Có một thế giới kiến thức khổng lồ và không thể nào học hết một cách dễ dàng được. Hãy chọn lọc và học chuyên sâu, và đừng quan tâm những thứ còn lại. Bạn có thể có kiến thức về công việc hay các lĩnh vực khác, nhưng không thể có tất cả được.

51. Chia tay

Chỉ vì bạn viết một vài dòng code không có nghĩa là bạn phải yêu thương nó. Đúng là không ai muốn quẳng công trình của mình đi, nhưng code có vòng đời của nó. Vậy nên bạn không cần phải khư khư yêu thương code cũ đâu.

52. Có team hỗ trợ

Team giỏi luôn hỗ trợ nhau. Điều này giúp bạn thấy an toàn hơn nhiều khi thử cái mới.

53. Tìm cảm hứng từ cộng đồng

Hãy tìm một ai đó trong ngành mà bạn ngưỡng mộ. Điều đó sẽ tạo cảm hứng cho bạn để tiếp tục project và thử nhiều thứ mới.

54. Hãy làm công việc của bạn trở nên giá trị

Bất kể là bạn làm vị trí nào hay công việc là gì, những gì bạn làm đều có cái giá của nó. Vì thế hãy cho nó giá trị xứng đáng nhé.

55. Bỏ qua những thứ làm phiền bạn

Tắt thông báo Slack, tin nhắn, email và các trang mạng xã hội sẽ giúp bạn tập trung tối đa cho công việc. Bạn sẽ không phải mất 30 phút trả lời tin nhắn và không làm được việc trong 30 phút đó đúng không.

56. Luôn hỗ trợ mọi người

Cố gắng hỗ trợ team của bạn trong mọi tình huống, kể cả là một buổi thuyết trình quan trọng hay đơn giản giúp họ gỡ rối tơ lòng.

57. Hay trao niềm tin đúng nơi đúng lúc

Nếu ai đó làm tốt công việc, hãy khen họ. Dùng sự tích cực để xây dựng lòng tin tới các thành viên trong team, cũng như hỗ trợ họ trong công việc. Một ngày nào đó họ cũng sẽ giúp lại bạn.

58. Kiểm tra code

Công đoạn kiểm tra rất quan trọng. Kiểm tra đơn vị, kiểm tra hồi quy, kiểm tra tích hợp, kiểm tra đầu cuối,… Kiểm tra code của bạn sẽ giúp sản phẩm của bạn ổn định hơn.

59. Lên kế hoạch tiếp cận

Khi bạn nhận được một yêu cầu về tính năng mới, hoặc là có bug, đầu tiên phải lên kế hoạch chuẩn bị. Bạn cần những gì để giải quyết vấn đề hay làm tính năng mới? Dành một vài phút để lên kế hoạch sẽ tiết kiệm hàng giờ đồng hồ hối hận của bạn sau này.

60. Học viết mã giả

Code giả là một kỹ năng tuyệt vời vì nó cho phép bạn vượt qua những vấn đề phức tạp mà không mất thời gian viết một dòng code nào. Viết lên giấy, chạy thử một vài cách test khác nhau và xem bạn gặp những lỗi gì.

61. Ghi nhớ thành tựu của mình

Nếu bạn được thưởng khi đi làm, ghi nó lại. Nếu bạn phát triển được một tính năng quan trọng, ghi nó lại. Bạn sẽ có một danh sách những thứ mình đã đạt được, dùng nó làm động lực vượt qua những thử thách khó khăn hơn.

Tips cho Lập trình viên

62. Học nền tảng lập trình

Hãy học những thuật toán sắp xếp và tìm kiếm và cấu trúc dữ liệu cơ bản. Đây là những điều bạn chưa biết về các ngôn ngữ và có thể giúp bạn giải quyết các vấn đề gặp phải.

63. Chọn công nghệ nào lâu dài và dễ maintain

Mặc dù thử nghiệm các công nghệ mới khá vui, nhưng hãy chọn những công nghệ nào dễ maintain trong ứng dụng doanh nghiệp. Team của bạn sẽ thấy biết ơn cả đời đó.

64. Học về Design Patterns

Design Patterns là những công cụ hữu ích cho việc thiết kế code của bạn. Có thể bạn không cần chúng ở nhiều project, nhưng hiểu căn bản về chúng sẽ giúp bạn làm nhiều ứng dụng lớn hơn.

Xem thêm Design Pattern là gì

65. Giảm sự mơ hồ trong code

Thay vì viết code phức tạp để thể hiện trình độ, hãy hướng đến sự dễ đọc và đơn giản. Việc này sẽ giúp thành viên team bạn dễ dàng đóng góp hơn.

66. Trả nợ kỹ thuật (Technical debt)

Technical debt có thể tác động lớn đến hiệu suất. Vậy nên nếu bạn có thể tái cấu trúc thì hãy làm đi nhé.

67. Nâng cấp thường xuyên

Thay vì nâng cấp lớn mỗi tháng, hãy nâng cấp thường xuyên hơn nhưng với các thay đổi nhỏ thôi. Bạn sẽ ít gặp bug hay phá vỡ các thay đổi trong sản phẩm của mình hơn.

68. Cam kết sớm và thường xuyên hơn

Cam kết sớm và thường xuyên là cách tốt nhất để đảm bảo công việc vẫn ổn, đồng thời cũng giảm stress khi bạn vô tình hoàn lại các thay đổi quan trọng.

69. Học cách khi nào thì hỏi trợ giúp

Không chỉ đừng ngại khi hỏi trợ giúp, mà bạn còn cần biết khi nào thì nên hỏi. Cố gắng giải quyết vấn đề trước khi hỏi ai đó. Nhưng khi bạn mắc kẹt với một vấn đề đơn giản trong 1 tiếng rồi, chi phí cao hơn lợi ích, thì hãy cầu cứu ngay nhé.

70. Hỏi những câu hỏi hiệu quả

Khi hỏi, bạn hãy cố gắng chi tiết nhất có thể.

71. Nhận feedback khi chưa xong việc

Bạn không cần phải hoàn thành hết công việc rồi mới nhận feedback. Nếu bạn chưa chắc chắn về hướng đi của mình, hãy hỏi một người đồng nghiệp đáng tin cậy để review mọi giải pháp của bạn.

72. Đọc documentation

Documentation là nguồn sự thật thuần tuý nhất về công nghệ. Vậy nên học cách đọc documentation có thể giúp bạn nhanh chóng trở thành một chuyện gia.

73. Thử mọi thứ

Không gì có thể ngăn cản bạn thử một giải pháp nào đó. Sau cùng thì, bạn có mất gì đâu nào?

74. Phát biểu ý kiến trong các cuộc họp

Ý tưởng và quan điểm của bạn đều có giá trị. Vì thế tham gia vào các cuộc họp sẽ giúp bạn phát triển mối quan hệ với team cũng như với sếp.

75. Phối hợp team chéo

Nếu bạn có cơ hội làm việc với các team khác trong công ty, đừng ngại thử.

76. Có những dự án vì đam mê

Khi bạn làm việc 40 tiếng 1 tuần, bạn cần 1 project mà bạn đam mê để làm. Những project đó sẽ giúp bạn tìm lại tình yêu với lập trình và thử những công nghệ mới mà bạn không có cơ hội để làm trên công ty.

77. Xác định mục tiêu nghề nghiệp của bạn

Nắm rõ con đường sự nghiệp lập trình của bạn rất quan trọng. Không có mục tiêu, cũng giống như bạn bắn tên mà không có bia để ngắm vậy.

78. Tham gia vào các cuộc thảo luận

Comment trên blog, tham gia trên twitter, trong các cộng đồng,… Bạn sẽ học được nhiều thứ hơn khi chủ động tranh luận.

79. Thực hiện những task ưu tiên

Học cách lên thứ tự ưu tiên cho task sẽ giúp bạn xử lý hiệu quả hơn. Luôn có một to-do list cho các công việc hàng ngày cũng như những công việc dài hạn và sắp xếp chúng khoa học.

Tips cho Lập trình viên

80. Đừng nhìn sơ qua những cái chi tiết

Những thứ chi tiết có thể tạo nên khác biệt lớn cho project của bạn.

81. Tin tưởng đồng đội

Thành viên trong team của bạn được trả lương nhờ những kỹ năng của họ. Hãy dùng chúng và tin tưởng đồng nghiệp để hoàn thành công việc.

82. Học cách phân công nhiệm vụ

Nếu bạn ở vị trí leader, hãy học cách chia công việc cho team thật hiệu quả. Bạn sẽ tiết kiệm được thời gian và không phải thất vọng, vì bạn không thể làm hết được mọi thứ.

83. Đừng so sánh mình với người khác

Người duy nhất bạn nên so sánh đó chính là bạn của ngày hôm qua.

84. Luôn có đồng minh bên cạnh

Học lập trình là một hành trình rất lâu và khó khăn. Hãy tìm kiếm người có thể giúp bạn hoàn thành hành trình của bạn nhé.

85. Đừng bắt đầu làm những thứ có quy mô lớn

Bắt đầu làm một project quy mô lớn có thể giúp bạn trở thành người giỏi trong mắt mọi người. Tuy nhiên, bạn chỉ nên giữ tư tưởng làm những thứ to lớn trong đầu, chứ đừng bắt đầu làm liền. Vì nếu vậy bạn sẽ khiến cho team khó chịu khi phải làm những thứ phức tạp không cần thiết.

86. Cân nhắc về hiệu suất làm việc

Nếu bạn muốn dùng công nghệ xịn sò, bạn nên cân nhắc hiệu suất làm việc của mình. Liệu bạn có đang làm việc với hiệu suất thấp? Nếu vậy thì bạn nên cân nhắc việc sử dụng công nghệ mới.

87. Đừng phân biệt

Đừng phân biệt công nghệ hay ý tưởng mới. Hãy luôn sẵn sàng đón nhận và học hỏi những kỹ năng mới. Và bạn cũng đừng phân biệt người khác. Ai cũng xứng đáng được đối xử tốt.

88. Mô-đun hoá code của bạn

Bạn có thể viết toàn bộ code trong một file lớn, nhưng sẽ không thể maintain tốt. Mô-đun hoá sẽ giúp code của bạn chạy ngon và dễ test hơn.

89. Đừng tin vào copy và paste

Nếu bạn định copy paste một giải pháp nào đó trên StackOverflow, bạn nên hiểu rõ nó là gì. Hãy có trách nhiệm trong việc chọn lựa code để làm việc.

90. Tạo ra một môi trường đầy cảm hứng

Bạn sẽ có nhiều động lực làm việc hơn nếu có không gian làm việc tốt.

91. Luôn nhớ về xuất phát điểm của mình

Chúng ta đều bắt đầu giống như nhau. Mặc cho những kỹ năng hay vị trí bạn làm là gì, đừng bao giờ quên mình đến từ đâu.

92. Luôn lạc quan

Nếu mọi thứ trở nên xấu đi, hãy cố gắng và lạc quan lên. Ngày mai là một ngày mới. Lạc quan sẽ giúp team bạn có sức mạnh vượt qua tất cả.

93. Liên tục xem lại quy trình làm việc của bạn

Không phải mọi thứ đang hoạt động tốt ở hiện tại thì tương lai cũng sẽ vậy. Luôn đánh giá lại workflow và điều chỉnh khi cần thiết.

94. Học cách làm việc ở nhà

Nếu bạn có thể làm việc ở nhà, hãy làm thật hiệu quả. Tìm một nơi ngoài văn phòng và tránh bị làm phiền. boneskull có viết một bài khá hay về làm việc tại nhà. Bạn có thể đọc ở đây.

Tips cho Lập trình viên

95. Mã truy cập

Khả năng truy cập không cần phải suy nghĩ quá nhiều, và cũng không nên quá khó. Mọi người cần dễ dàng sử dụng sản phẩm của bạn.

96. Tôn trọng cam kết

Nếu bạn cam kết với ai sẽ làm đúng deadline thì nên giữ lời hứa. Còn trong trường hợp có thể trễ deadline thì hãy nói ra ngay.

97. Hãy chủ động

Nếu bạn đang rảnh thì hãy giúp team bạn. Họ sẽ rất biết ơn vì bạn đã chủ động như vậy đấy.

98. Làm Portfolio đẹp

Một Portfolio đẹp sẽ làm bạn khác biết với người khác. Thể hiện mọi kỹ năng lập trình và thiết kế trong Portfolio của mình nhé.

99. Ghi nhớ lý do bạn yêu lập trình

Bạn vào ngành này vì thấy nó thú vị. Nếu bạn có thất vọng hay bực bội, hãy nghỉ ngơi một chút. Cho bạn không gian để tìm lại đam mê lập trình trong mình.

100. Chia sẻ kiến thức

Nếu bạn học được thứ gì đó hữu ích, hãy chia sẻ cho mọi người. Hãy chia sẻ trong một buổi meetup hay hội thảo. Chia sẻ cho đồng nghiệp hay nhân viên của bạn trong mỗi buổi ăn trưa. Chia sẻ kiến giúp bạn củng cố lại kiến thức của mình trong khi đem đến nhiều giá trị hơn cho người khác.

Kết

Trên đây là 100 tips cho lập trình viên để phát triển bản thân. Hy vọng các bạn sẽ cần tới. Cảm ơn các bạn đã theo dõi bài viết!

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

Truy cập ngay việc làm IT đãi ngộ tốt trên TopDev

  Những thắc mắc về nghề lập trình kinh điển thường gặp của lập trình viên

Tản mạn về cái tên “Full Stack Overflow Developer”

Full Stack Overflow Developer

Full Stack Overflow Developer, thực tế phần lớn mọi người sau khi nghe cụm từ này đều sẽ cười. Họ coi đó như một sự chế nhạo hay là một điều gì không tốt cho lắm.

Mình từng đọc được một đoạn bài viết như thế này trên một trang tạp chí công nghệ lớn:

“Một Full Stack Overflow Developer làm việc gần như 100% bằng cách sao chép và dán các đoạn code copy từ trang Stack Overflow. Thay vì nghiên cứu về vấn đề trước, họ lại đến đó ngay để đặt câu hỏi và ngồi đợi, hy vọng mọi người sẽ vào và cho họ kết quả.”

Vậy những gì ở trên là đúng hay sai? Và tại sao đúng, tại sao sai? Hôm nay mình sẽ chia sẻ những hiểu biết và chính kinh nghiệm của bản thân về vấn đề này.

Tuyển lập trình viên Full Stack lương cao trong tháng

Stack Overflow là gì?

Stack Overflow là cách gọi quen thuộc của trang web https://stackoverflow.com. Đây là nơi mà các lập trình viên trên khắp thế giới vào đặt câu hỏi về những vấn đề khó khăn, bugs mà họ chưa giải quyết được.

Những người khác có hiểu biết về vấn đề đó sẽ vào bình luận giúp đỡ. Rõ ràng là một cộng đồng lớn như vậy, Stack Overflow thực sự là một nguồn tài nguyên quý báu và đáng kinh ngạc.Full Stack Overflow Developer

Nếu có một developer nào nói với bạn rằng anh ta chưa từng vào stackoverflow bao giờ mà vẫn giỏi thì mình khuyên các bạn nên dành 99% tỏ ra nghi ngờ và 1% thì hãy tin, nhưng là tin rằng anh ta vào những trang forum tương tự khác để học hỏi.

Trở lại vấn đề, nếu Stack Overflow tốt là thế thì tại sao nhiều người lại cho rằng,việc tìm hiểu và học hỏi ở trên này là không nên? Là không tốt?

Mình sẽ không hoàn toàn phủ nhận câu nói đó. Với mình, điều trên sẽ đúng đối với những ai Không chịu đào sâu vấn đề, lúc nào cũng đi tìm code trên Stack Overflow. Copy và paste mà không hề suy nghĩ, chỉ mong code chạy được cái là dừng lại ở đó luôn. Và sai đối với những người lên đó học hỏi, tìm ra cách giải quyết vấn đề cũng như đào sâu vào nó, tại sao làm như thế này lại giải quyết được vấn đề…

Cho phép mình gọi ngắn gọn 2 nhóm người này một là “lạm dụng stackoverflow” theo nghĩa tiêu cực. Và hai là “tận dụng stackoverflow” theo nghĩa tích cực.

  StackOverflow công bố báo cáo khảo sát Lập trình viên 2019: Python là ngôn ngữ phát triển nhanh nhất
  Đừng dựa dẫm vào StackOverflow, nó sẽ chỉ khiến mọi thứ tệ hơn thôi

Lạm dụng hay tận dụng?

Nhóm người lạm dụng Stack Overflow một cách không tốt.

Đối với những người này, khi họ sao chép và dán một đoạn mã và thấy chúng chạy được, điều tuyệt vời đối với họ là họ có thể thấy được kết quả ngay lập tức mà không cần phải hiểu tại sao vấn đề lại được giải quyết như vậy.

Trước mắt, họ sẽ cảm thấy tốt hơn nhiều so với việc thất vọng nếu không làm được gì đó. Nhưng sẽ có những vấn đề như sau:

  • Khi họ không đào sâu hơn vào vấn đề, có thể chỗ code hay thư viện mà họ copy & paste đã cũ và lỗi thời, có thể chứa các lỗ hổng bảo mật… Rõ ràng là rất nguy hiểm nếu không tìm hiểu những cách giải quyết khác tốt hơn hay là cập nhật các bản sửa lỗi mới nhất của thư viện.
  • Trường hợp gỡ lỗi, nâng cấp hoặc bảo trì ứng dụng trong tương lai, với việc không hiểu biết về đoạn code mà họ copy & paste vào, thực sự sẽ trở thành một vấn đề khó khăn lớn. Không những ảnh hưởng tới chính họ, mà còn cả chất lượng sản phẩm, cả những người khác cùng trong team làm việc.
  • Về lâu dài, việc đó sẽ còn khiến giảm giá trị nghề nghiệp của bản thân họ. Họ khá giống những con robot, cứ đi đặt mọi thứ vào nhau và hy vọng có được kết quả. Những người khác sẽ không thể coi họ là chuyên gia được.

“Sinh ra là một bản thể, đừng chết như một bản sao.”

(Một câu nói và cũng là tên của một cuốn sách cực kỳ hay.)

Nhóm người biết tận dụng tốt Stack Overflow.

Với những người biết tận dụng, họ vẫn lên trang này để tìm kiếm ý tưởng giải quyết vấn đề mà họ chưa biết. Họ mong muốn hiểu vấn đề, hiểu ý tưởng giải quyết chứ không đơn thuần chỉ là copy và paste.

  • Khi tìm hiểu vấn đề, họ sẽ học được rất nhiều tips của những người giỏi hơn. Tư duy giải quyết vấn đề của họ cũng sẽ được mở rộng hơn trong cả quá trình tìm hiểu.
  • Về sau, khi gặp lại vấn đề này hoặc những vấn đề tương tự, việc giải quyết đã quá đơn giản. Họ sẽ tiết kiệm được rất nhiều thời gian.
  • Tốt hơn nữa, nếu gặp phải vấn đề mới, thì họ cũng sẽ có thói quen chủ động suy nghĩ cách giải quyết trước khi tìm kiếm ý tưởng trên mạng, vì trong họ đã hình thành tư duy này. Điều này thực sự là một tinh thần rất tốt mà tất cả mọi người cần học hỏi dù ở bất kỳ lĩnh vực nào.

Việc nghiên cứu, tận dụng tài nguyên học tập đúng cách cũng giống như bạn học kiến thức từ một người thầy vậy.

Stack overflow là nguồn tài nguyên kiến thức cực kỳ hữu ích. Hầu như những vấn đề mà chúng ta gặp phải đã có những người đi trước. Họ gặp rồi và đã có những ý tưởng giải quyết vấn đề trên đó. Chỉ cần tìm kiếm chính xác từ khóa, chịu đào sâu tư duy khám phá vấn đề, bạn sẽ càng thành công trên con đường học tập và làm việc của chính bạn.

Kết luận

Dĩ nhiên, còn rất nhiều lợi ích nữa đối với người tận dụng và nhiều vấn đề khác nữa với người lạm dụng, những điều đó chỉ có bản thân của chính mỗi chúng ta thực tế trải qua mới có thể hiểu hết được.

Hy vọng một chút chia sẻ của bản thân mình sẽ giúp được các bạn phần nào đó trong việc tìm hiểu, định hướng học tập, để biết cách tận dụng kiến thức một cách hợp lý và đúng đắn.

Cảm ơn các bạn đã dành chút thời gian xem bài viết của mình!

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

Xem thêm việc làm Full-stack Developer trên TopDev

TopDev via trungquandev.com

Quy hoạch động là gì? Nguyên lý hoạt động của Dynamic Programming

thuật toán quy hoạch động

Trong bài viết này, Topdev sẽ giới thiệu với các bạn một thuật toán thần thánh: thuật toán quy hoạch động. Nếu bạn tham gia các cuộc thi code, bạn nhất định phải biết thuật toán này.

Gần một nửa các bài thi trong các cuộc thi code cần đến quy hoạch động. Tất nhiên, có những cách khác để giải bài toán đó. Nhưng vì các cuộc thi code đều có giới hạn về thời gian, cũng như bộ nhớ của chương trình, nên một thuật toán hiệu quả là cực kỳ cần thiết. Và trong những trường hợp như vậy, quy hoạch động là một trong những thuật toán xuất hiện nhiều nhất.

Quy hoạch động là gì?

Quy hoạch động (dynamic programming) là một phương pháp được sử dụng trong toán học và khoa học máy tính để giải quyết các vấn đề phức tạp bằng cách chia chúng thành các bài toán con đơn giản hơn. Bằng cách giải mỗi bài toán con chỉ một lần và lưu trữ kết quả, nó tránh được các phép tính dư thừa, dẫn đến giải pháp hiệu quả hơn cho nhiều bài toán.

Quy hoạch động (DP) hoạt động như thế nào?

Quy hoạch động (DP) hoạt động như thế nào?
Quy hoạch động (DP) hoạt động như thế nào?

Nguyên lý hoạt động của Dynamic Programming

  1. Chia bài toán thành các bài toán con nhỏ hơn: Bài toán ban đầu được chia thành các bài toán con mà mỗi bài toán con là một phần của bài toán lớn hơn. Các bài toán con này thường có tính chất lặp lại.
  2. Lưu trữ kết quả của các bài toán con: Để tránh việc tính toán lặp lại các bài toán con nhiều lần, kết quả của chúng được lưu trữ trong một bảng (thường là mảng hoặc ma trận).
  3. Sử dụng lại kết quả đã lưu: Khi cần kết quả của một bài toán con nào đó, chương trình sẽ kiểm tra bảng lưu trữ để xem kết quả đã được tính toán trước đó chưa. Nếu đã có, nó sẽ sử dụng lại kết quả đó thay vì tính toán lại từ đầu.

Các bước thực hiện

  1. Xác định cấu trúc của bài toán con tối ưu: Hiểu rõ cách mà bài toán lớn được chia thành các bài toán con và cách mà kết quả của các bài toán con này kết hợp lại để giải quyết bài toán lớn.
  2. Định nghĩa hàm hồi quy: Xác định công thức hoặc hàm hồi quy để giải quyết bài toán dựa trên các bài toán con. Đây là bước quan trọng để hiểu cách các bài toán con liên kết với nhau.
  3. Tính giá trị của bài toán con theo thứ tự từ nhỏ đến lớn: Bắt đầu từ những bài toán con nhỏ nhất và sử dụng công thức hồi quy để tính giá trị của các bài toán con lớn hơn dựa trên các bài toán con nhỏ hơn đã được tính toán trước đó.
  4. Lưu trữ kết quả của các bài toán con: Kết quả của mỗi bài toán con được lưu trữ trong bảng để sử dụng lại sau này.
  5. Giải quyết bài toán lớn nhất: Sau khi đã tính toán và lưu trữ kết quả của tất cả các bài toán con, sử dụng chúng để giải quyết bài toán ban đầu.

Khi nào thì dùng thuật toán quy hoạch động

Khi nào thì chúng ta cần đến quy hoạch động? Đó là một câu hỏi rất khó trả lời. Không có một công thức nào cho các bài toán như vậy.

Tuy nhiên, có một số tính chất của bài toán mà bạn có thể nghĩ đến quy hoạch động. Dưới đây là hai tính chất nổi bật nhất trong số chúng:

  • Bài toán có các bài toán con gối nhau.
  • Bài toán có cấu trúc con tối ưu.

Thường thì một bài toán có đủ cả hai tính chất này, chúng ta có thể dùng quy hoạch động được. Một câu hỏi rất thú vị là không dùng quy hoạch động có được không? Câu trả lời là có, nhưng nếu bạn đi thi code, bạn trượt là cái chắc. Để hiểu rõ hơn, chúng ta sẽ tìm hiểu từng tính chất một trong những phần dưới đây

Bài toán con gối nhau

Tương tự như thuật toán chia để trị, quy hoạch động cũng chia bài toán lớn thành các bài toán con nhỏ hơn. Quy hoạch động được sử dụng khi các bài toán con này được gọi đi gọi lại. Phương pháp quy hoạch động sẽ lưu kết quả của bài toán con này, và khi được gọi, nó sẽ không cần phải tính lại, do đó làm giảm thời gian tính toán.

Quy hoạch động sẽ không thể áp dụng được (hoặc nói đúng hơn là áp dụng cũng không có tác dụng gì) khi các bài toán con không gối nhau. Ví dụ với thuật toán tìm kiếm nhị phân, quy hoạch động cũng không thể tối ưu được gì cả, bởi vì mỗi khi chia nhỏ bài toán lớn thành các bài toán con, mỗi bài toán cũng chỉ cần giải một lần mà không bao giờ được gọi lại.

Một ví dụ rất điển hình của bài toán con gối nhau là bài toán tính số Fibonacci. Bài toán quá nổi tiếng rồi, chúng ta có thể tính toán số Fibonacci theo đúng công thức như sau:

def fib(n):
    if n <= 1:
        return n
    return fib(n -1) + fib(n - 2)

Nếu tính toán như trên, chúng ta rất nhiều bài toán con sẽ được tính đi tính lại, điển hình là các số fib(0) và fib(1).

Và quy hoạch động chính là một trong số những phương pháp có thể giúp chúng ta tối ưu hóa quá trình tính toán này. Mỗi bài toán con (số fib) sẽ được lưu lại trước khi tính những bài toán con lớn hơn. Nhờ đó, mà việc tính toán giảm đi đáng kể, mỗi bài toán con chỉ cần tính đúng một lần.

Một ví dụ quy hoạch động với bài toán này như sau:

 
def fib(n):
    dp = [0] * (n + 1)
    dp[1] = 1
    for i in range(2, n + 1):
        dp[i] = dp[i - 1] + dp[i - 2]
    return dp[n]

Qua ví dụ trên, bạn đã thấy được sức mạnh vượt trội của quy hoạch động chưa? Đó cũng chính là lý do mà nó rất được ưa chuộng trong các cuộc thi lập trình, khi mà thời gian và bộ nhớ đều là hữu hạn (và thường khá nhỏ).

TÌM VIỆC LÀM NGÀNH LẬP TRÌNH

Cấu trúc con tối ưu

Cấu trúc con tối ưu là một tính chất là lời giải của bài toán lớn sẽ là tập hợp lời giải từ các bài toán nhỏ hơn.

Mình lấy một ví dụ cho dễ hiểu:

Trong bài toán tìm đường đi ngắn nhất trong đồ thị, nếu một node x nằm trên đường đi ngắn nhất giữa hai node uv thì đường đi ngắn nhất từ u đến v sẽ là tổng hợp của đường đi ngắn nhất từ u đến x và đường đi ngắn nhất từ x đến v. Môt số thuật toán tìm đường trên đồ thị (nổi tiếng nhất có lẽ là Dijkstra) đều dựa trên tính chất này, và nó cũng áp dụng quy hoạch động.

Tính chất cấu trúc con tối ưu rất quan trọng. Nó cho phép chúng ta giải bài toán lớn dựa vào các bài toán con đã giải được. Nếu không có tính chất này, chúng ta không thể áp dụng quy hoạch động được.

Không phải bài toán nào cũng có tính chất cấu trúc con tối ưu này. Ví dụ với đồ thị sau:

Thuật toán Quy hoạch động

Đường đi dài nhất từ q -> t sẽ là q -> r -> t hoặc q -> s -> t. Nhưng không giống như bài toán tìm đường đi ngắn nhất, đường đi dài nhất không phải là tổ hợp của những đường đi thành phần, do đó, bài toán này không có cấu trúc con tối ưu.

Ví dụ, đường q -> r -> t không phải là tổ hợp của đường đi dài nhất từ q -> r và đường đi dài nhất từ r -> t. Bởi vì, đường đi dài nhất q -> rphải là q -> s -> t -> r và đường đi dài nhất từ r -> t phải là r -> q -> s -> t.

Ưu và nhược điểm của Quy hoạch động

Ưu điểm của Dynamic Programming (DP)

Dynamic Programming có nhiều ưu điểm, bao gồm:

  • Giảm thời gian tính toán: Quy hoạch động lưu trữ kết quả của các bài toán con đã được tính toán trước đó, giúp giảm thiểu đáng kể số lượng phép tính cần thực hiện. Điều này đặc biệt hiệu quả trong các bài toán có tính chất lặp lại, như dãy Fibonacci hoặc bài toán tối ưu hóa.
  • Giải quyết được các bài toán phức tạp: DP cho phép giải quyết nhiều bài toán tối ưu hóa và lập lịch phức tạp mà các phương pháp khác không thể làm được hiệu quả, chẳng hạn như bài toán balo, chuỗi con chung dài nhất (LCS), và nhiều bài toán đồ thị.
  • Tránh được các tính toán lặp lại không cần thiết: Bằng cách lưu trữ kết quả của các bài toán con, DP tránh được việc tính toán lặp lại những phần đã giải quyết, giúp tiết kiệm tài nguyên và tăng hiệu suất.
  • Độ chính xác cao: Kỹ thuật DP đảm bảo tìm ra giải pháp tối ưu cho bài toán bằng cách xây dựng các giải pháp từ các bài toán con tối ưu.

Nhược điểm của Quy hoạch động

  • Tốn bộ nhớ: DP yêu cầu lưu trữ kết quả của tất cả các bài toán con, điều này có thể tốn rất nhiều bộ nhớ, đặc biệt đối với các bài toán có không gian trạng thái lớn. Điều này có thể gây ra vấn đề khi áp dụng DP cho các bài toán có quy mô lớn.
  • Phức tạp trong việc triển khai: Hiểu và triển khai một giải pháp DP đòi hỏi người lập trình phải hiểu rõ cấu trúc của bài toán và cách chia nhỏ nó thành các bài toán con. Điều này có thể phức tạp và tốn nhiều thời gian để thiết kế và debug.
  • Không phải lúc nào cũng khả thi: Không phải bài toán nào cũng có thể áp dụng được DP. Các bài toán cần có tính chất con tối ưu (optimal substructure) và tính chất lặp lại của bài toán con (overlapping subproblems). Nếu bài toán không có các tính chất này, DP sẽ không hiệu quả.
  • Tiêu tốn thời gian cho việc lưu trữ và truy xuất: Mặc dù giảm thời gian tính toán, việc lưu trữ và truy xuất kết quả từ bộ nhớ cũng tiêu tốn thời gian, đặc biệt khi kích thước của bảng lưu trữ lớn.

Một số bài toán quy hoạch động

Trong phần này, chúng ta sẽ làm quen với quy hoạch động thông qua một số ví dụ cụ thể. Chúng ta sẽ xem xét cách quy hoạch động được áp dụng vào các bài toán cụ thể như thế nào, đồng thời qua đó, chúng ta sẽ hiểu hơn về các tính chất ở phần trước.

Ví dụ 1: Bài toán kinh điển với đồng xu

Đây là một ví dụ rất kinh điển khi học về quy hoạch động. Có thể có nhiều cách phát biểu khác nhau nhưng về cơ bản, nội dung của nó sẽ tương tự như sau.

Giả sử chúng ta có n đồng xu nặng lần lượt là W1, W2, ..., Wn, và bài toán đặt ra là tìm số lượng đồng xu nhỏ nhất để tổng khối lượng của chúng là một giá trị S. Tất nhiên, số lượng đồng xu là không giới hạn.

Giả sử chúng ta có n đồng xu nặng lần lượt là W1, W2, ..., Wn, và bài toán đặt ra là tìm số lượng đồng xu nhỏ nhất để tổng khối lượng của chúng là một giá trị S. Tất nhiên, số lượng đồng xu là không giới hạn.

Với bài toán này, chúng ta cần xây dựng và giải các bài toán con gối nhau. Với ví dụ của chúng ta, mỗi bài toán con dp(P) với P <= S là bài toán tìm số đồng xu nhỏ nhất để khối lượng của chúng là P. và dp(P) = k chính là số lượng đồng xu nhỏ nhất đó.

Chúng ta sẽ áp dụng phương pháp quy hoạch động bằng cách bắt đầu từ bài toán con dp(0) sau đó tiếp tục với các bài toán con lớn hơn. Lời giải của các bài toán con sẽ được xây dựng lần lượt cho đến chúng ta xây dựng đến bài toán dp(S) và đó chính là kết quả của bài toán lớn. Một điều cần lưu ý với kỹ thuật này là bài toán con tiếp theo sẽ không thể giải được nếu chúng ta chưa giải bài toán con trước đó.

Cuối cùng là phần khó nhất của mọi bài toán quy hoạch động, đó là trả lời câu hỏi: cấu trúc con tối ưu của bài toán này ở đâu. Hay nói một cách khác, làm thế nào để từ những bài toán nhỏ hơn có thể tổ hợp ra lời giải cho bài toán lớn. Với vị dụ kinh điển này, mọi thứ sẽ tương đối đơn giản, nhưng với những bài toán phức tạp hơn, chúng ta cần suy nghĩ và tính toán nhiều hơn.

Quay trở lại với bài toán của chúng ta. Giả sử P là tổng khối lượng của các đồng xu nặng lần lượt là V1, V2, ..., Vj. Để có được khối lượng P, chúng ta cần thêm vài đúng 1 đồng xu nặng U vào khối lượng Q sao cho Q + U = P. Tất nhiên, bài toán con dp(Q) chúng ta đã có lời giải nên chúng ta sẽ biết được cần bao nhiêu đồng xu cho dp(P). Và vì có nhiều đồng xu U(nhiều nhưng hữu hạn) nên chúng ta có thể cần đến nhiều bài toán con trước đó, và dp(p) là giá trị nhỏ nhất sau khi tổng hợp những bài toán con đó.

Ví dụ với n = 3, S = 11, W = [1, 3, 5].

  • Bắt đầu với bài toán con 0 ta có dp(0) = 0
  • Với bài toán con 1, có 1 đồng xu (nặng 1) có thể thêm vào từ 0 đồng xu nào cả. Vậy dp(1) = dp(0) + 1 = 1.
  • Với bài toán con 2, cũng chỉ có 1 đồng xu (nặng 1) có thể thêm vào từ 1 đồng xu. Vậy dp(2) = dp(1) + 1 = 2.
  • Với bài toán con 3, chúng ta có thể thêm 1 đồng xu 3 vào 0 đồng xu hoặc thêm 1 đồng xu 1 vào 2 đồng xu. Rõ ràng là cách đầu tiên cho kết quả nhỏ hơn. Vậy dp(3) = min(dp(2) + 1, dp(0) + 1) = min(3, 1) = 1
  • Cứ tiếp tục như vậy cho đến bài toán S chính là đáp án chúng ta cần tìm.

Về mặt cài đặt, quy hoạch động thường lưu kết quả vào một mảng. Trong ví dụ của chúng ta, mảng dp[0..S] sẽ lưu kết quả cho từng bài toán con. Nói cách khác, dp[P] = k nghĩa là cần ít nhất k đồng xu để có khối lượng là PToàn bộ mảng này sẽ được tính bằng vòng lặp. Đoạn code sau mô tả toàn bộ quá trình này.

n, S = map(int, input().split())
w = list(map(int, input().split()))
dp = [0] * (S + 1)
dp[0] = 0

for P in range(1, S + 1):
    dp[P] = min(dp[P - x] for x in w if x <= P) + 1

print(dp)
print(dp[S])

# Nếu đầu vào như sau: n = 3, S = 11, w = [1, 3, 5]
# Thì bảng lời giải cho các bài toán con sẽ lần lượt như sau:
# P = 0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10|11
# ------+--+--+--+--+--+--+--+--+--+--+--
# k = 0 |1 |2 |1 |2 |1 |2 |3 |2 |3 |2 |3

Ví dụ 2: Xâu con chung dài nhất (LCS)

Thêm một ví dụ nữa cho dễ, cũng là một bài toán rất nổi tiếng.

Cho hai xâu ký tự. Tìm độ dài xâu con chung nhỏ nhất giữa chúng. Ví dụ với 2 xâu “quetzalcoatl” và “tezcatlipoca” thì xâu con chung dài nhất sẽ là “ezaloa” với độ dài 6.

Với bài toán này, chúng ta sẽ lần lượt giải các bài toán con như sau:

Lấy i ký tự đầu tiên từ xâu thứ nhất và j ký tự đầu tiên từ xâu thứ hai và tìm độ dài xâu chung dài nhất giữa 2 xâu con được lấy ra đó. Dễ dàng thấy được rằng, lời giải của mỗi bài toán con sẽ phụ thuộc vào i và j, dp(i, j). Và bài toán lớn sẽ được giải bằng cách lần lượt giải các bài toán con lần lượt từ dp(0, 0) và tăng dần độ dài xâu được lấy ra cho đến khi chúng ta lấy ra toàn bộ xâu của đề bài.

Chúng ta hãy bắt đầu lần lượt các bài toán con. Đương nhiên, nếu một trong hai xâu là rỗng thì xâu con chung của chúng cũng rỗng. Vậy dp(0, j) = dp(i, 0) = 0. Nếu cả i và j đều dương, chúng ta cần suy xét một vài trường hợp.

  1. Nếu ký tự cuối cùng của xâu thứ nhất không có mặt trong xâu con chung dài nhất, nó có thể bị bỏ qua mà không ảnh hưởng gì đến kết quả. Công thức ở đây sẽ là dp(i, j) = dp(i - 1, j).
  2. Tương tự như trường hợp trên, ký tự cuối cùng của xâu thứ hai không ảnh hưởng đến kết quả thì dp(i, j) = dp(i, j - 1).
  3. Trường hợp cuối cùng, nếu hai ký tự cuối cùng của hai xâu x1, x2 đều có mặt trong xâu con chung dài nhất. Dĩ nhiên là hai ký tự này phải là một thì điều này mới xảy ra, tức là x1 == x2. Trong trường hợp này, khi xoá đi bất cứ một ký tự nào trong hai ký tự đó đều khiến xâu con chung dài nhất ngắn đi 1 ký tự. Vậy rõ ràng là dp(i, j) = dp(i - 1, j - 1) + 1.

Trong cả ba trường hợp trên, chúng ta phải chọn ra trường hợp nào cho kết quả là xâu con chung dài nhất (với bài toán này thì chỉ cần đưa ra độ dài đó là đủ).

Về mặt cài đặt, dp sẽ được lưu trong mảng hai chiều. Kết quả của mảng này sẽ được tính toán thông qua vòng lặp hai lớp. Lưu ý rằng, chúng ta cần thực hiện vòng lặp sao cho chúng ta sẽ giải lần lượt từng bài toán con một, theo thứ tự từ nhỏ đến lớn. Bởi vì mỗi bài toán con dp(i, j) đều phụ thuộc vào các bài toán con trước đó dp(i - 1, j), dp(i, j - 1), dp(i - 1, j - 1).

n1, n2 = map(int, input().split())
s1, s2 = input().split()
t = [[0] * (len(s2) + 1) for _ in range(len(s1) + 1)]
for i, x1 in enumerate(s1, 1):
    for j, x2 in enumerate(s2, 1):
        if x1 == x2:
            t[i][j] = t[i - 1][j - 1] + 1
        else:
            t[i][j] = max(t[i][j - 1], t[i - 1][j])

print(t[-1][-1])

# Kết quả khi giải các bài toán con như bảng sau:
#
#    S|    t  e  z  c  a  t  l  i  p  o  c  a
# T ji| 0  1  2  3  4  5  6  7  8  9 10 11 12
# ----+--------------------------------------
#  0 | 0  0  0  0  0  0  0  0  0  0  0  0  0
# q 1 | 0  0  0  0  0  0  0  0  0  0  0  0  0
# u 2 | 0  0  0  0  0  0  0  0  0  0  0  0  0
# e 3 | 0  0  1  1  1  1  1  1  1  1  1  1  1
# t 4 | 0  1  1  1  1  1  2  2  2  2  2  2  2
# z 5 | 0  1  1  2  2  2  2  2  2  2  2  2  2
# a 6 | 0  1  1  2  2  3  3  3  3  3  3  3  3
# l 7 | 0  1  1  2  2  3  3  4  4  4  4  4  4
# c 8 | 0  1  1  2  3  3  3  4  4  4  4  5  5
# o 9 | 0  1  1  2  3  3  3  4  4  4  5  5  5
# a 10| 0  1  1  2  3  4  4  4  4  4  5  5  6
# t 11| 0  1  1  2  3  4  5  5  5  5  5  5  6
# l 12| 0  1  1  2  3  4  5  6  6  6  6  6  6

Quy hoạch động vs Memoization

Có một kỹ thuật khác gọi là “memoization” cũng có cách tiếp cận tương tự với quy hoạch động. Cả quy hoạch động và memoization đều dùng để tối ưu các vòng lặp mà có tính toán tượng tự nhau, trong đó kết quả của phép tính lớn hơn sẽ cần được tính toán dựa vào kết quả của phép tính nhỏ hơn. Memoization thường được sử dụng trong các phép tính đệ quy khi mà một tính toán bị lặp đi lặp lại nhiều lần. Nó sẽ lưu một bảng các giá trị tính được, mỗi khi có tính toán cần thực hiện, chúng ta sẽ tra bảng đó trước. Nếu bảng đã có kết quả rồi, chúng ta chỉ cần lấy ra là xong, nếu chưa, chúng ta sẽ tính toán như thường và tiếp tục lưu vào bảng.

Memoization không phải là một thuật toán theo đúng nghĩa, nó là một kỹ thuật được sử dụng trong lập trình thì đúng hơn. Để hiểu rõ hơn về kỹ thuật này, mình xin lấy ví dụ ngay với bài toán Fibonacci. Chúng ta sẽ sử dụng memoization như sau:

look_up = {0: 1, 1: 1}
def fib(n):
    if look_up.get(n) is None:
        look_up[n] = fib(n - 1) + fib(n - 2)
    return look_up[n]

Sự khác biệt chủ yếu là quy hoạch động sẽ thực hiện việc tính toán theo một thứ tự định trước, trong khi memoization duyệt theo chiều sâu. Quy hoạch động không bao giờ tính toán một bài toán con hai lần, tương đối giống với các phép tính đệ quy với memoization. Tuy nhiên memoization thì không bao giờ tính toán những phép tính thừa trong khi quy hoạch động sẽ cần tất cả mọi bài toán con. Đây là một phương pháp khá hay, nó chỉ tính toán những gì cần thiết và lưu kết quả này lại để sau này dùng lại khi nào được gọi mà không cần tính toán nữa.

Dưới đây là một số ưu, nhược điểm của memoization khi so sánh với quy hoạch động:

Ưu điểm

  • Dễ code hơn
  • Không yêu cầu thứ tự thực hiện tính toán
  • Chỉ tính toán những gì cần thiết

Nhược điểm

  • Chỉ có một kiểu duyệt duy nhất
  • Thường chậm hơn quy hoạch động.

Các dạng toán quy hoạch động

Phần lớn các bài toán quy hoạch động có thể chia làm hai loại: bài toán cần quy hoạch động để tối ưu và bài toán quy tổ hợp. Trong những phần dưới đây, chúng ta sẽ xem xét từng loại bài toán này.

Bài toán tối ưu

Bài toán tối ưu yêu cầu chúng ta phải tìm đáp án tốt nhất từ mục tiêu của bài toán. Cả hai ví dụ mình đưa ra ở trên đều thuộc loại bài toán này (một bài tìm số đồng xu ít nhất, một bài tìm xâu con dài nhất). Mối liên hệ của các bài toán con thuộc dạng này có công thức chúng là dp[s] = min(F1(dp[i], dp[j], ..., dp[k]), F2(dp[u], dp[v], ..., dp[w]), ..., Fl(dp[q], dp[p], ..., dp[z])), trong đó dp mảng lưu kết quả của các bài toán con đó.

Mỗi bài toán được giải dựa trên bài toán đã được giải trước đó. Đây chính là tính chất cấu trúc con tối ưu của mỗi bài toán. Với bài toán đồng xu, mỗi bài toán mới đều được giải bằng cách thêm đúng 1 đồng xu vào kết quả từ trước đó. Kết quả cuối cùng là kết quả tốt nhất thu được từ nhiều cách thêm đồng xu với khối lượng khác nhau.

Trước khi tính toán, mảng chứa kết quả có thể được điền đầy một giá trị trung tính nào đó. Giá trị trung tính có nghĩa là giá trị đó sẽ không bao giờ là đáp án cho bất kỳ bài toán con nào. Ví dụ khi cần tìm ra số đồng xu nhỏ nhất, chúng ta có thể điền mảng này bằng số dương lớn nhất, mọi tính toán tiếp theo sẽ cho ra một kết quả nhỏ hơn nhiều. Nếu không ra kết quả nào khác, chúng ta có thể coi như là không có một đáp án nào cho bài toán con đó.

Bài toán tổ hợp

Bài toán tổ hợp thường yêu cầu chúng ta tìm ra số cách khác nhau để thực hiện một việc gì đó. Nhiều bài thi code thường có kết quả rất lớn và họ yêu cầu chúng ta đưa đáp án dạng modulo của 10000007. Trong dạng bài toán này, công thức khi xây dựng các bài toán con sẽ là R[s] = F1(R[i], R[j], ..., R[k]) + F2(R[u], R[v], ..., R[w]) + ... + Fl(R[q], R[p], ..., R[z]). Sự khác biệt cơ bản của dạng bài toán này với dạng bài toán tối ưu là ở chỗ chúng ta cần tính tổng thay vì tìm số lớn nhất hoặc nhỏ nhất.

Trong mọi bài toán quy hoạch động, tính chất cấu trúc con tối ưu luôn là quan trọng nhất và cũng là tính chất khó đảm bảo nhất. Nếu cấu trúc con không được tối ưu, chúng ta sẽ tính toán theo một phương thức sai lầm và đương nhiên, kết quả thu được cũng không chính xác.

Với phần lớn các bài toán quy hoạch động, việc chia các bài toán con gối nhau khá dễ dàng trong khi đảm bảo cấu trúc con tối ưu thì khó hơn nhiều.

Mình sẽ đưa ra hai ví dụ tương tự nhau cho các bạn hiểu rõ hơn về những khó khăn để đảm bảo tính chất này.

Vẫn với bài toán đồng xu, chúng ta sẽ thay đổi một chút để có bài toán tổ hợp như sau:

Tìm số cách khác nhau để chọn ra các đồng xu sao cho tổng khối lượng của chúng là S.

Các bài toán con sẽ tương tự như trước: dp(P) = k là số cách khác nhau để chọn ra các đồng xu có tổng khối lượng là P. Công thức đệ quy trong trường hợp này sẽ biến đổi theo bài toán như sau:

# Công thức đệ quy cho bài toán quy hoạch động
#   {dp[0] = 1;
#   {dp[P] = sum(dp[P-Wi]);   (for Wi <= P)
#
# Với đầu vào như sau: n = 3, S = 11, W = [1, 3, 5]
# Mảng kết quả quy hoạch động sẽ là
#  P = 0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10|11
#  ------+--+--+--+--+--+--+--+--+--+--+--
#  k = 1 |1 |1 |2 |3 |5 |8 |12|19|30|47|74

Bài toán tổ hợp cũng có thể có một giá trị trung tính. Bởi vì bài toán tổ hợp thường tính tổng, giá trị trung tính sẽ là 0. Bài toán tổ hợp yêu cầu tìm số cách khác nhau để làm gì đó, do đó giá trị 0 sẽ không ảnh hưởng gì đến đáp án. Một điểm đặc biệt quan trọng trong bài toán tổ hợp này là mỗi cách chúng ta chỉ tính đúng một lần. Nói thì dễ nhưng nhiều khi trong thực hành chúng ta hay gặp sai sót ở chỗ cực kỳ quan trọng này.

Tiếp tục thay đổi thêm một chút, chúng ta sẽ có bài toán tổ hợp như sau:

Tìm số cách khác nhau để chọn ra các đồng xu sao cho tổng khối lượng của chúng là S. Với điều kiện, các cách lấy đồng xu là hoán vị của nhau không được coi là khác nhau.

Bài toán này khó hơn bài toán trước một chút. Nếu chúng vẫn chia các bài toán con như cũ thì không thể có được cấu trúc con tối ưu. Ví dụ, với các đồng xu 1, 3, 5 thì (1, 3) và (3, 1) đều cho kết quả là 4 nhưng chỉ được coi là 1 cách.

Với bài toán này, chúng ta sẽ chia bài toán lớn thành các bài toán con theo một cách tương đối khác. Chúng ta thấy rằng, kết quả (số cách chọn đồng xu) sẽ là tổng hợp của hai kết quả:

  • Số cách lấy đồng xu từ n - 1 đồng xu đầu tiên, tức là chúng ta coi như không có đồng xu nặng nhất
  • Số cách lấy đồng xu có chứa đồng xu nặng nhất.

Kết quả sẽ là tổng của hai kết quả trên. Các bạn thấy đó, với cách xây dựng bài toán con như thế này, chúng ta đã xây dựng các bài toán con gối nhau mà vẫn đảm bảo cấu trúc con tối ưu (kết quả bằng tổng của các bài toán con).

Nhân tiện, với cách chia bài toán như vậy, chúng ta có thể thu được lời giải bằng cách đệ quy đơn giản như sau:

n, S = map(int, input().split())
w = list(map(int, input().split()))


def count(arr, x):
    # Có 1 cách (lấy ra 0 đồng xu) cho tổng khối lượng bằng 0
    if x == 0:
        return 1
    # Không thể lấy được các đồng xu cho khối lượng âm
    if x < 0:
        return 0
    # Không thể lấy nếu không có đồng xu nào
    if not arr and x >= 1:
        return 0
    # Kết quả là tổ hợp các bài toán con
    return count(arr[:-1], x) + count(arr, x - arr[-1])


print(count(w, S))

Tuy nhiên, như mình đã nói ở phần trước, nếu bạn đang thi code, cách làm này sẽ không mang lại bất cứ hy vọng đạt giải nào, do nó cực kỳ mất thời gian và bộ nhớ. Tuy nhiên, chúng ta có thể áp dụng quy hoạch động cho bài toán này rất dễ dàng sau khi có được cấu trúc con tối ưu với các bài toán con gối nhau:

n, S = map(int, input().split())
w = list(map(int, input().split()))

dp = [[0 for _ in range(n)] for _ in range(S + 1)]
for i in range(n):
    dp[0][i] = 1

for i in range(1, S + 1):
    for j in range(n):
        x = dp[i - w[j]][j] if i - w[j] >= 0 else 0
        y = dp[i][j - 1] if j >= 1 else 0
        dp[i][j] = x + y


print(dp[-][n - 1])
# Kết quả tính toán với n = 3, w = [1, 3, 5] như sau:
#  S = 0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10|11
#  ------+--+--+--+--+--+--+--+--+--+--+--
#  k = 1 |1 |1 |2 |2 |3 |4 |4 |5 |6 |7 |8

Các bạn thấy đó, xây dựng các bài toán con gối nhau sao cho cấu trúc con vẫn tối ưu nhiều khi không đơn giản chút nào. Và mỗi bài toán quy hoạch động lại có những biến hóa khác nhau mà không theo một khuôn mẫu khô cứng nào. Ngay cả khi bạn có thể giải được rất nhiều bài toán quy hoạch động rồi, không gì có thể đảm bảo bạn có thể giải được các bài khác nữa. Đó cũng là một lý do khiến cho dạng bài này luôn “hot” trong các cuộc thi.

Tuyển dụng IT tại HCM, Hà Nội, Đà Nẵng

Quy hoạch động xuôi và ngược

Tất cả những ví dụ mình đã trình bày ở trên đều sử dụng quy hoạch động kiểu “ngược”. Ngược ở đây không phải là chúng ta duyệt các bài toán con từ lớn ngược về nhỏ. Mà quy trình sẽ như thế này: Duyệt qua tất cả các bài toán con (từ nhỏ đến lớn), với mỗi bài toán đó, chúng ta tính toán kết quả dựa vào bài toán con trước đó. Tất nhiên, bài toán con phía trước đã được giải theo quy trình duyệt, và với mỗi bài toán, chúng ta phải “nhìn ngược lại” bài toán trước đó, nên cách làm này gọi là quy hoạch động kiểu “ngược”.

Phương pháp quy hoạch động ngược này được sử dụng rộng rãi, vì nó khá tương ứng với suy nghĩ tự nhiên của chúng ta. Chúng ta đọc đề bài, suy nghĩ cách giải cho nó. Cách giải đó yêu cầu phải giải những bài toán nhỏ hơn, như kiểu làm toán ngày phải chứng minh các bổ đề vậy. Chúng ta tiếp tục suy nghĩ cho những bài toán con này, rồi tổng hợp để tìm ra lời giải cho bài toán lớn. Quá trình cứ tiếp tục như vậy, và quy hoạch động kiểu “ngược” này đang được xây dựng đúng như vậy.

Ngoài ra, về mặt lập trình, kiểu quy hoạch động này có mối quan hệ tương đối gần gũi với đệ quy. Một bài toán lớn được giải dựa vào các bài toán con tương tự nhau (và tương tự bài toán lớn) thì việc áp dụng đệ quy có thể là một phương pháp dễ dàng để code. Vì vậy, nhiều trường hợp, có thể coi quy hoạch động là một cách để tối ưu phương pháp đệ quy để giải một bài toán.

Ngoài kiểu quy hoạch động ngược này, có một kiểu quy hoạch động “xuôi”. Tuy không phổ biến, kiểu quy hoạch động xuôi cũng khá khó áp dụng, nhưng quy hoạch động “xuôi” mang đến cho chúng ta nhiều tiện lợi. Kiểu xuôi này cũng cần duyệt qua các bài toán con từ nhỏ đến lớn, nhưng với mỗi bài toán con, chúng ta tính toán kết quả và từ đó tìm cách thực hiện một số phép tính để giải bài toán lớn hơn. Nghĩa là, với mỗi bài toán con, chúng ta sẽ nhìn về phía trước để xem phải giải bài toán tiếp theo như thế này từ bài toán hiện tại.

Phương pháp này khó áp dụng hơn phương pháp ngược kia, và cũng không phải bài toán nào cũng áp dụng được. Với mỗi bài toán, việc xác định bước tiếp theo tương đối khó khăn, thậm chí việc kiểm tra tính đúng sai của phương pháp cũng không hề dễ dàng.

Như chúng ta đã thấy ở những phần trước, thông thường, mỗi bài toán cần phải giải bằng cách tổng hợp kết quả từ một vài bài toán con trước đó. Vì vậy, cách quy hoạch động xuôi này chỉ sử dụng một bài toán con để tính toán trước bài toán tiếp theo sẽ chỉ cho ra một phần của kết quả chứ không phải kết quả cuối cùng. Vì vậy, để thực hiện quy hoạch động xuôi, việc điền sẵn một mảng các giá trị trung tính là điều bắt buộc (sau đó chúng ta sẽ cộng dồn kết quả vào mỗi khi giải được một bài toán con mới).

Mình lấy vị với bài toán xâu con chung dài nhất. Với bài toán này, chúng ta có thể chọn giá trị trung tính là một số âm. Chúng ta sẽ tìm cách quy hoạch động xuôi như sau:

  • dp(0,0) = 0 là bài toán với hai xâu rỗng
  • Với mỗi bài toán dp(i, j) chúng ta sẽ tìm cách tính toán kết quả cho các bài toán lớn hơn. Lúc này, có 3 hướng phát triển tiếp:
    1. Lấy thêm một ký tự từ xâu thứ nhất => Kết quả không thay đổi.
    2. Lấy thêm một ký tự từ xâu thứ hai => Kết quả cũng không thay đổi.
    3. Nếu ký tự tiếp theo của cả hai xâu giống nhau => Lấy tự từ này và độ dài xâu con chung tăng lên 1.

Dưới đây là code cho bài toán này:

n1, n2 = map(int, input().split())
s1, s2 = input().split()
s1 += '\0x00'
s2 += '\0x00'

# Điền sẵn giá trị trung tính
dp = [[-1] * (n1 + 2) for _ in range(n2 + 2)]
dp[0][0] = 0

for i in range(n1 + 1):
    for j in range(n2 + 1):
        tres = dp[i][j]
        # Phát triển theo hướng thứ nhất
        if dp[i + 1][j] < tres:
            dp[i + 1][j] = tres
        # Phát triển theo hướng thứ hai
        if dp[i][j + 1] < tres:
            dp[i][j + 1] = tres
        # Phát triển theo hướng thứ ba
        if s1[i] == s2[j] and dp[i + 1][j + 1] < tres + 1:
            dp[i + 1][j + 1] = tres + 1

print(dp[n1][n2])

Kết luận

Hy vọng qua bài viết này, mình đã trình bày được phần nào về thuật toán quy hoạch động. Về cơ bản, với mọi bài toán quy hoạch động, chúng ta có thể xây dựng các bài toán con gối nhau với cấu trúc con tối ưu là 90% công việc đã hoàn thành.

Tuy nhiên, cũng cần hiểu rằng, mặc dù thuật toán quy hoạch động là một thuật toán thần thánh, nó có thể giải được rất nhiều bài toán, nhưng nó không phải là chìa khóa vạn năng. Có một điều rất hiển nhiên: phương pháp tốt nhất để giải quyết mọi bài toán trong tin học là biết sử dụng và phối hợp uyển chuyển nhiều thuật toán, chúng ta không nên phát cuồng một thuật toán và cũng không nên coi thường bất cứ một thuật toán nào.

Tác giả: Trần Ngọc Anh – manhhomienbienthuy.bitbucket.io

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

Xem thêm IT Jobs for Developer tại TopDev

Những thắc mắc về nghề lập trình kinh điển thường gặp của lập trình viên

thắc mắc về nghề lập trình

Không chỉ là “thùng rác” để các bạn lập trình viên “xả” những cảm xúc và ức chế của mình, Lập trình viên confession còn là một cầu nối giúp các bạn coder giải đáp những thắc mắc hóc búa xoay quanh công việc và học tập. Dưới đây là những thắc mắc về nghề lập trình kinh điển thường gặp của cộng đồng.

  Vì miếng ăn mà phá cả nồi cơm – Thực tại đáng lo của nghề lập trình

#C67

Mình là du học sinh vừa tốt nghiệp hè vừa rồi, vừa về nước đi làm mấy tháng lương 8 củ/tháng (mình đã có công ty ở nước ngoài tuyển cơ mà hè sang năm mới xuất ngoại đi làm). Có thể nói là mình về VN làm lấy kn vì ngồi không chả được gì. Qua việc tiếp xúc thì mình thấy mấy devs mình tiếp xúc họ rất thông thạo 1 ngôn ngữ lập trình nhưng họ thiếu những cái cơ bản như: thuật toán, cơ sở dữ liệu (chuẩn hóa,…). Mình không công nhận mình giỏi giang gì nhưng trong quá trình học mình vẫn tập trung các môn cơ sở. Ngày trước mình có phỏng vấn qua các cty bên nước ngoài, trc khi pv mình có chuẩn bị kĩ kiến thức về iava (công ty tuyển java), và ngạc nhiên là 80 – 90% họ hỏi thuật toán, chuẩn hóa csdl,… còn về ngôn ngữ lt chỉ có 10% còn lại là hỏi về kn làm việc. Mình chỉ muốn khuyên các bạn đang còn học về ngành này là hãy thông thạo các kiến thức cơ sở, ngôn ngữ lt nó cũng như ngôn ngữ bt ta nói hàng ngày. Bạn có thể giỏi tiếng Anh nhưng toán chưa chắc đã giỏi, ngôn ngữ chỉ là cái cầu để ta truyền đạt và tiếp thu. Khi bạn đã chắc chắn về kiến thức cơ sở, bạn có thể tự tin chọn ngôn ngữ bạn thích và apply cty bạn muốn.

#C116

⚠️ Bài ngắn lắm, cố gắng đọc hết nhé !

Disclaimer: Tôi cũng từng là du học sinh, cũng làm về java, và cũng từng trúng tuyển vào vị trí lập trình viên hệ thống thông tin tại một tập đoàn lớn có giá trị vốn hóa hơn 30 tỷ euro (xin phép cho tôi nổ con số này vì nó khè được khối người) nên có đôi điều muốn chia sẻ thêm về những điều bạn tác giả #C67 đã viết.

KĨ THUẬT KHÔNG PHẢI TẤT CẢ

Đầu tiên tôi muốn nói thêm về vấn đề tuyển dụng. Trong các công ty, đặc biệt là các công ty lớn, quy trình tuyển dụng thường rất lằng nhằng và phức tạp. Thông thường các bạn sẽ phải trải qua vòng hồ sơ (CV và thư), vòng này được thực hiện [chủ yếu] bởi bộ phận nhân sự và đôi khi có tham khảo ý kiến của bộ phận chuyên môn nơi ứng viên trúng tuyển sẽ làm việc. Qua được vòng này bạn sẽ bắt đầu đến với các bài test và các cuộc phỏng vấn.

Đầu tiên là phỏng vấn với nhân sự: bạn có thể được yêu cầu làm các bài kiểm tra về trình độ logic (giải đố) và ngôn ngữ (nếu vị trí yêu cầu ngoại ngữ không phải tiếng mẹ đẻ của bạn). Tiếp theo đó là một cuộc phỏng vấn khoảng 1 giờ đồng hồ, tất cả xoay quanh những gì bạn đã trình bày trong CV và Thư, chủ yếu là để nhân sự kiểm tra các thông tin về bằng cấp của bạn, vạch nên một hồ sơ khái quát về con người và tính cách của bạn và kiểm chứng các *kĩ năng mềm* và xem bạn có thật sự KHAO KHÁT công việc này hay không. Nếu trước mặt những người này bạn tỏ ra mình thờ ơ hoặc có những biểu hiện bất thường về nhân cách thì hãy coi chừng! Nghe toát mồ hôi nhỉ :’))

Sau đó mới đến các bài test và phỏng vấn về chuyên môn. Ở đây có thể có nhiều hơn 1 bài test và 1 cuộc phỏng vấn, tùy theo vị trí mà bạn ứng tuyển. Những người mà bạn sẽ gặp có thể là Lead dev, PM, Architect, thậm chí là CTO nếu bạn may mắn (hay là không may nhỉ ;D). Vì thế nên các câu hỏi đưa ra có độ khó không giống nhau và trải khá rộng trên lĩnh vực mà bạn ứng tuyển, từ những vấn đề lý thuyết cổ điển như thuật toán, độ phức tạp của thuật toán, bài toán NP-complete… cho đến các xu hướng mới [nổi] trong lập trình như functional programming, reactive programming… Kinh nghiệm của tôi cho thấy các công ty càng nhỏ thì càng có xu hướng hỏi những câu “hẹp”, tập trung vào loại kĩ thuật và công cụ mà họ đang tìm kiếm, còn ở các công ty lớn thì chủ yếu xem cách bạn giải quyết vấn đề và khả năng học kĩ năng mới để đối phó với vấn đề mới. Qua được vòng này mà nhận được những cái gật gù từ người hỏi thì 80% là bạn sẽ có được vị trí mong muốn, còn lại phụ thuộc vào kết quả test và do ..ăn ở :’))

LÝ THUYẾT HAY THỰC TẾ ? CẢ HAI!

Ở đây xin trở lại với chia sẻ #C67. Bạn OP nói rất đúng về mức độ quan trọng của các kiến thức lý thuyết đối với một kĩ sư máy tính vì nó là một tiêu chuẩn để phân biệt một kĩ sư và một lập trình viên thông thường (mặc dù tôi có chút thắc mắc, vì sao một ứng viên lập trình viên Java, là fresher, lại bị hỏi về tối ưu hóa csdl ? Vị trí bạn ứng tuyển xem ra không đơn giản). Tuy nhiên đừng vì thế mà xem nhẹ việc thành thạo một loại công nghệ hay ngôn ngữ nào đó. Lý thuyết và thực hành, nói theo kiểu Maxism (khốt ta bít), là hai thứ có quan hệ *biện chứng*, hỗ trợ qua lại với nhau. Lí do các công ty không đặt nặng phần thực tiễn khi đánh giá khả năng của bạn OP là vì (theo tôi võ đoán) bạn ứng tuyển vào vị trí lập trình viên Java nói chung, không có mission cụ thể, ngoài ra bạn không có kinh nghiệm làm việc trước đó nên họ chuyển sang đánh giá tiềm năng của bạn trước khi nhận bạn vào và tiếp tục đào tạo bạn trong quá trình làm việc.

Tôi đọc các cfs trên page này hàng ngày và có tham gia một số group lập trình trên facebook, câu hỏi (hay lời ta thán) thường gặp nhất của các bạn sinh viên là “đi học để làm gì khi mà không cần bằng vẫn có thể đi làm lương chục củ”, “tại sao ở trường chỉ toàn dạy các môn đại cương, các môn lý thuyết mà không _dạy code_”, “em đang tự học làm web, chỉ cần tốt nghiệp nữa thôi là đi làm được rồi mà sao khó [tốt nghiệp] quá”… Tôi nghĩ rằng các bạn đang nhầm lẫn về môi trường học và định hướng nghề nghiệp của mình sau này. Các chương trình đại học ở Việt Nam theo tôi biết (trừ ĐH FPT) đều là hướng nghiên cứu chứ không phải hướng chuyên nghiệp. Điều này có nghĩa là các bạn chủ yếu học lý thuyết, thiếu hoàn toàn mảng doanh nghiệp và quan trọng nhất là không biến các bạn thành các “lập trình viên web”, “lập trình viên javascript”… Bạn muốn phát triển theo hướng nào thì phải TỰ HỌC, tự trau dồi, tự tìm hiểu bằng cách sử dụng một phần những kiến thức ở trường, đó là điều bắt buộc khi bạn học về khoa học máy tính trong các chương trình hàn lâm. Còn nếu chỉ đơn giản muốn thành thục một framework, một ngôn ngữ nào đó để làm nghề thì hãy tìm đến các chương trình dạy nghề hay các khóa đào tạo ngắn hạn rồi sau đó đi làm luôn và ngay, việc học của bạn nên được thực hiện ở trường đời chứ không phải ở trường đại học.

VÀ CHUYỆN CỦA TÔI

Khi còn là sinh viên tôi cũng giống như một số bạn, trễ nải các môn lý thuyết cổ điển và các môn nghiên cứu máy tính ở bậc thấp (Unix API, OS…), và tôi đặt biệt thù ghét việc lập trình ở đây vì ngôn ngữ chính họ dạy tôi là C, sau này lên năm cuối còn “được” dạy thêm Common Lisp nữa (đừng thắc mắc về ngôn ngữ đồ đá này, nó còn nhiều tuổi hơn cả tôi với bạn mà chả thấy ai dùng). Khi đó tôi chỉ có một ước mơ duy nhất là cố gắng qua môn, tốt nghiệp để trở thành “java developer”, còn cụ thể là làm gì thì tôi mù tịt :* . Mọi chuyện chỉ thay đổi khi tôi quyết định thi OCPJP (chủ yếu là để khè HR thôi chứ sau này đi làm mới thấy các tiền bối expert có khi còn chả biết nó là cái giống gì 😀). Những kiến thức sơ sài về Data Structure đã giúp tôi qua phần Collections, những đêm ôn thi nước đến chân mới nhảy bộ môn OS thì giúp tôi qua rất nhiều phần, từ I/O, File I/O đến Threads và Concurrency. Đó là lúc tôi hiểu mình mới chỉ chạm đến bề mặt của ngôn ngữ Java, còn phần nền tảng của nó thì đã bị tôi bỏ rơi đâu đó trong suốt mấy năm sinh viên ăn chơi. Bạn thấy đấy, tất cả mọi thứ, kể cả những thứ chúng ta thù ghét nhất, đều tồn tại vì một lí do nào đó và sẽ đến lúc chúng trở nên có ích, chỉ là chúng ta có nắm bắt được hay không mà thôi.

Tôi vẫn nhớ bài test tuyển dụng đầu tiên tôi làm khi mới ra trường là phản biện một UML diagram, chỉ ra các điểm mà tôi cảm thấy bất hợp lí và đề xuất các thay đổi cho nó, sau đó generate code bằng java và viết một thuật toán *đơn giản* và *tối ưu* (giải thích lí do) để đọc/thêm/bớt dữ liệu từ cấu trúc dữ liệu đề xuất trước đó.

Chỉ bằng một bài test này thôi, họ đã đồng thời đánh giá được khả năng của tôi về OOP, Algorithm, Data structure và một chút về ngôn ngữ. Sau bài test thì tôi phải qua một lần phỏng vấn nữa, chủ yếu là về những hiểu biết của tôi về Agile, git workflow và CI/CD rồi đi về. Kết quả là tôi tạch các bạn ạ). Phải 7 – 8 lần như thế tôi mới có một lần tỏa sáng mà phần nhiều là nhờ kinh nghiệm từ các lần tạch trước đó.

Vì thế nên các bạn sinh viên hãy yên tâm, sinh viên mới ra trường ở bất kì đâu trên thế giới này cũng đều phần nào ngơ ngác như các bạn cả thôi và các nhà tuyển dụng RẤT HIỂU điều này. Tuy nhiên cần xác định rõ mong muốn cũng như khả năng của bản thân để có thể ứng tuyển một cách hợp lí. Hãy ghi nhớ, mỗi cuộc phỏng vấn là một cuộc thi và bạn thật sự cần phải ÔN THI một cách nghiêm túc.

Điểm khác biệt duy nhất ở đây chỉ là bạn có quyền và được khuyến khích học tủ. Tủ ở đây chính là thông báo tuyển dụng, nơi bạn sẽ tìm thấy tất cả các thông tin cần thiết về công ty, về vị trí tuyển dụng, về các yêu cầu (bắt buộc cũng như khuyến khích) đối với ứng viên cho vị trí đó. Hãy tìm hiểu tất cả các thông tin liên quan, mở rộng hết cỡ những vấn đề có thể được nhắc đến theo cả chiều dọc lẫn chiều ngang. Và cuối cùng, tuyệt đối không nói dối về khả năng của bản thân, vì các chuyên gia HR cũng như chuyên môn rất giỏi trong khoản bóc phốt này. Đừng dại dột!!!

Chuyên mục bốc phét đêm khuya đến đây đã dài, xin được dừng lại. Tôi hi vọng những tâm sự trên đây của tôi có thể giúp được một số các bạn trẻ đang và sắp bước vào những trận chiến đầu đời để giành lấy một công việc. Chúc tất cả các bạn may mắn và nếu có tin vui thì xin chia sẻ với tôi cũng như các bạn khác, vì một cộng đồng IT lương khởi điểm $2000

#C112

Thấy có bạn nữ lên hỏi kiểu nên theo hướng nào thì phù hợp với con gái. Và mình thấy mấy anh chị đi trước thường khuyên là nên làm tester hay đại loại là những thứ không liên quan đến code. Và mình xin kể câu chuyện của mình cho các bạn nữ còn đang đi học biết.
Mình là nữ, mình tốt nghiệp được khoảng gần 1 năm, hiện tại đang làm dev.

Hồi đó mình đỗ cả 2 trường đại học, nếu không đi theo con đường này thì năm sau có thể mình sẽ trở thành một bác sĩ. Và đương nhiên cả nhà chẳng ai muốn mình đi theo con đường trở thành một lập trình viên (mình thì thích dùng từ dev hơn). Mình đã đấu tranh rất nhiều để được học cái ngành này. Một đứa con gái trong một cái lớp có tới vài chục thậm chí cả trăm đứa con trai, dĩ nhiên mấy bạn nam rất giỏi, nhiều lúc mình cũng bị chùn chí.

Nhưng nghĩ tới cảnh ra trường không có việc làm hoặc làm một công việc không liên quan đến những thứ mình học ba mẹ sẽ thất vọng, hàng xóm dưới quê sẽ nói ra nói vào, với lại mình đã chọn con đường này mình phải có trách nhiệm với nó vì không có cơ hội để chọn lại, mình lại tiếp tục cố gắng. Lúc sắp tốt nghiệp mình đi thực tập với mức lương đủ sống. Hiện tại mức lương của mình đã gấp vài lần con số đó. Mình thấy hạnh phúc vô cùng khi được code và có thể kiếm ra tiền để lo cho gia đình bằng chính ước mơ từ hồi đi học của mình.
Mình muốn gởi tới mấy bạn nữ lời nhắn là hãy cố gắng lên, nếu đã lựa chọn con đường này thì phải đi cho tới cùng. Đừng có tư tưởng trở thành một tester nếu không thích nó. Con gái học lập trình đâu phải để làm tester, con gái cũng sẽ trở thành dev như bao đứa con trai khác, chỉ cần có ước mơ. Cố lên!

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

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

TopDev via Lập trình viên Confession

  Cơ hội nghề nghiệp về CNTT của các doanh nghiệp Nhật
  21 nghề nghiệp "đắt giá" trong tương lai, triển vọng và khó bị thay thế bởi trí tuệ nhân tạo

Hướng dẫn tạo một đối thủ AI đơn giản cho cờ vua

Tác giả: Lauri Hartikka

Chúng ta hãy cùng khám phá một số khái niệm cơ bản sẽ giúp chúng ta tạo ra một AI cờ vua đơn giản:

  • move-generation (Khởi tạo các bước di chuyển)
  • board evaluation (Khả năng tiên đoán nước cờ của đối thủ)
  • minimax (Thuật toán tính toán nước đi)
  • alpha beta pruning. (Tinh chỉnh phương thức Alpha-beta)

Ở mỗi bước, chúng tôi sẽ cải tiến thuật toán bằng một trong những kỹ thuật lập trình game cờ vua đã qua thử nghiệm. Tôi sẽ chứng minh làm thế nào để tác động đến lối chơi của thuật toán.

Bạn có thể xem thuật toán AI hoàn chỉnh trên GitHub.

Bước 1: Hiển thị các bước di chuyển và bàn cờ

Chúng tôi sẽ sử dụng thư viện chess.js để phát triển các bước di chuyển và chessboard.js để hiển thị bàn cờ. Thư viện tạo ra các bước di chuyển cơ bản tuân theo tất cả quy luật của cờ vua. Dựa vào điều này, chúng ta có thể tính toán tất cả các bước đi hợp lý cho một ván chơi nhất định.

Hình dung chức năng tạo các nước đi. Dựa vào vị trí bắt đầu để tính toán ra tất cả các nước đi có thể từ vị trí đó.

Sử dụng các thư viện này sẽ giúp chúng ta có thể dồn toàn tâm toàn ý vào công việc thú vị nhất: tạo ra thuật toán tìm nước cờ tốt nhất.

Chúng ta sẽ bắt đầu bằng cách tạo ra một chức năng chỉ trả về một nước đi ngẫu nhiên từ tất cả hướng có thể:

var calculateBestMove =function(game) {
    //generate all the moves for a given position
    var newGameMoves = game.ugly_moves();
    return newGameMoves[Math.floor(Math.random() * newGameMoves.length)];
};

Mặc dù thuật toán này không tạo nên đối thủ cứng tay, tuy nhiên đó là một khởi đầu tốt, chúng ta thực sự đã có thể chơi với nó:

Cờ đen tự di chuyển những nước đi ngẫu nhiên.
  Máy học - Machine Learning và một vài hạn chế.

Bước 2: Dự đoán các nước đi

Bây giờ chúng ta hãy cố gắng hiểu được bên nào mạnh hơn ở vị trí nào đó. Cách đơn giản nhất để đạt được điều này là tính toán sức mạnh tương đối của các quân cờ trên bàn bằng cách sử dụng bảng sau:

Với chức năng dự đoán, chúng ta có thể tạo ra một thuật toán chọn nước cờ đạt hiểu quả cao nhất:

var calculateBestMove = function (game) {

    var newGameMoves = game.ugly_moves();
    var bestMove = null;
    //use any negative large number
    var bestValue = -9999;

    for (var i = 0; i < newGameMoves.length; i++) {
        var newGameMove = newGameMoves[i];
        game.ugly_move(newGameMove);

        //take the negative as AI plays as black
        var boardValue = -evaluateBoard(game.board())
        game.undo();
        if (boardValue > bestValue) {
            bestValue = boardValue;
            bestMove = newGameMove
        }
    }

    return bestMove;

Cải tiến duy nhất đạt được là thuật toán của chúng ta sẽ nắm bắt được một phần phương thức di chuyển nếu có thể.

Cờ đen chơi với sự hỗ trợ của chức năng dự đoán đơn giản.

Bước 3: Tìm kiếm nước đi hiểu quả nhất bằng Minimax

Tiếp theo, chúng ta sẽ tạo ra các hướng đi có thể xảy ra từ đó thuật toán có thể chọn bước di chuyển tốt nhất. Điều này được thực hiện bằng cách sử dụng thuật toán Minimax.

Trong thuật toán này, hướng đi của tất cả các nước cờ có thể được tính toán kỹ trong từng tình huống nhất định, và vị trí được dự đoán cuối cùng là hiệu quả nhất.

Sau đó, chúng ta sẽ trả lại giá trị nhỏ nhất hoặc lớn nhất của child cho parent node, tùy thuộc vào việc đó là cờ trắng hoặc đen để di chuyển. (Đó là, chúng tôi cố gắng để giảm thiểu hậu quả hoặc tối đa hóa hiệu quả ở mỗi tình huống.)

 

Hình dung thuật toán minimax cho trí thông minh nhân tạo. Nước đi tốt nhất cho cờ trắng là b2-c3, bởi vì chúng tôi có thể đảm bảo rằng tại vị trí mà tính toán là -50
var minimax = function (depth, game, isMaximisingPlayer) {
    if (depth === 0) {
        return -evaluateBoard(game.board());
    }
    var newGameMoves = game.ugly_moves();
    if (isMaximisingPlayer) {
        var bestMove = -9999;
        for (var i = 0; i < newGameMoves.length; i++) {
            game.ugly_move(newGameMoves[i]);
            bestMove = Math.max(bestMove, minimax(depth - 1, game, !isMaximisingPlayer));
            game.undo();
        }
        return bestMove;
    } else {
        var bestMove = 9999;
        for (var i = 0; i < newGameMoves.length; i++) {
            game.ugly_move(newGameMoves[i]);
            bestMove = Math.min(bestMove, minimax(depth - 1, game, !isMaximisingPlayer));
            game.undo();
        }
        return bestMove;
    }

Với minimax, thuật toán của chúng tôi bắt đầu hiểu một số chiến thuật cơ bản của cờ vua:

Minimax tính toán được trước 2 nước đi.

Hiệu quả của thuật toán minimax chủ yếu dựa vào khám phá ra nước cờ tiếp theo đó mà chúng ta có thể đạt được. Đây là điều chúng tôi sẽ cải thiện trong bước tiếp theo.

  Máy học - Machine Learning và một vài hạn chế.

Bước 4: Tinh chỉnh Alpha-beta

Việc tinh chỉnh Alpha-beta là một phương pháp tối ưu hóa thuật toán minimax cho phép chúng ta bỏ qua một số hướng trong tất cả hướng đi có thể. Điều này giúp chúng tôi dự đoán hướng bằng minimax hiệu quả, trong khi sử dụng cùng một thuật toán.

Việc giảm thiểu alpha-beta dựa trên tình huống mà chúng ta có thể ngừng đưa ra hướng đi nếu chúng ta thấy hướng đi đó dẫn đến một kết quả tồi tệ hơn là bước di chuyển đã tìm ra từ trước.

Việc điều chỉnh alpha-beta không ảnh hưởng đến kết quả của thuật toán minimax, nó chỉ làm cho thuật toán nhanh hơn.

Thuật toán alpha-beta cũng hiệu quả hơn nếu chúng ta tìm ra những hướng đi dẫn tới các nước cờ tốt đầu tiên.

Các vị trí chúng ta không cần phải ngợi ý nếu việc tinh chỉnh alpha-beta được sử dụng và hướng đi tuân theo thứ tự được mô tả.

Với alpha-beta, chúng tôi đạt được sự cải thiện đáng kể cho thuật toán minimax, như thấy trong ví dụ sau:

Theo link này để thử phiên bản cải tiến alpha-beta của AI cờ vua.

Bước 5: Cải thiện chức năng dự đoán

Chức năng dự đoán ban đầu khá là đơn giản vì chúng chỉ đếm các nước đi được tìm thấy trên bàn cờ. Để cải thiện điều này, chúng tôi thêm vào dự đoán một yếu tố có tính đến vị trí của các quân cờ. Ví dụ, một con mã nằm ở giữa bàn cờ là tốt hơn (vì nó có nhiều lựa chọn hơn và vì vậy hoạt động mạnh hơn) so với một con mã trên mép của bàn cờ.

Chúng ta sẽ sử dụng các ô mà từng quân cờ có thể đi được dựa trên nguồn chess-programming-wiki nhờ vậy mà chất lượng AI được cải thiện.

Các ô minh họa để dễ hình dung. Chúng tôi có thể tính được điểm tăng hay giảm của mỗi nước đi, tùy thuộc vào vị trí của mỗi quân cờ.

Với những cải tiến sau đây, chúng tôi bắt đầu có được một thuật toán chơi cờ với những nước đi “hợp lý”, ít nhất là từ quan điểm của một kỳ thủ bình thường:

Cải thiện dự đoán và tinh chỉnh alpha-beta với khả năng tính toán trước được 3 nước đi. Có thể thử trên https://jsfiddle.net/q76uzxwe/1/

Kết luận

Sức mạnh của ngay cả một thuật toán chơi cờ vua đơn giản cũng có là không tạo ra những sai lầm ngu ngốc. Tuy nhiên, nó vẫn còn thiếu về phần lên chiến lược.

Với các phương pháp tôi giới thiệu ở đây, chúng tôi đã có thể lập trình một thuật toán chơi cờ vua có thể chơi cơ bản. Về phần “AI” (các nước đi ngẫu nhiên bị loại bỏ) của thuật toán cuối cùng chỉ có 200 dòng code, điều này khá đơn giản để thực hiện. Bạn có thể kiểm tra phiên bản hoàn chỉnh trên GitHub.

Một số cải tiến khác chúng tôi có thể thực hiện cho thuật toán như:

  • move-ordering (sắp xếp các nước đi)
  • faster move generation (tính toán các nước đi nhanh hơn)
  • và end-game specific evaluation. (dự đoán khi nào kết thúc ván cờ)

Nếu bạn muốn tìm hiểu thêm, hãy thử xem qua chess programming wiki. Đó là một nguồn thông tin hữu ích để bạn có thể khám phá vượt qua khái niệm cơ bản mà tôi giới thiệu ở bài này.

Cảm ơn bạn đã đọc bài viết này!

Đừng bỏ lỡ những bài viết hay về Machine Learning:

Xem thêm tuyển dụng kỹ sư AI hot nhất trên TopDev

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

Làm sao để nâng cao khả năng code?

nâng cao khả năng code

Làm sao để nâng cao khả năng code? Dĩ nhiên là phải code rồi, còn cách nào khác nữa. Nhưng code thì cũng có nhiều kiểu code. Có kiểu giúp bạn lên trình, cũng có kiểu giúp trình bạn lên. Dù là kiểu nào thì muốn code giỏi bạn đều phải code cả.

Tuy nhiên, lên trình nhiều hay lên trình ít lại phụ thuộc vào nhiều khía cạnh. Giả sử như bạn được code với một anh senior, code của anh ấy đẹp như đêm trăng rằm, hoặc bạn code một dự án thực tế hay ho thì trình của bạn sẽ lên rất nhanh. Còn nếu bạn cứ code đi code lại mấy bài CRUD trong trường đại học với mấy thằng bạn, hoặc làm vài task lặt vặt trong công ty thì trình sẽ khó lên hơn.

Nhưng đâu phải ai cũng có cơ hội code với senior, làm dự án thực tế đúng không? Đặc biệt là các bạn sinh viên như mình, hoặc các bạn mới ra trường. Nhưng không sao, hôm nay mình sẽ giúp bạn biết cách làm sao để nâng cao khả năng code của bạn, dễ thôi.

  Cách mà một dòng code đã thay đổi cuộc đời tôi!
  Mẹo tối ưu code ứng dụng React lập trình viên phải biết

Open source – thiên đường luyện code

Ơn trời chúng ta có internet, vô số các dự án thực tế hay ho được các developer chia sẻ đang chờ bạn.

Nếu bạn biết đến github thì chắc rằng bạn đã hiểu open source là gì. Open source đơn giản là các dự án tuyệt vời được chia sẻ lên internet, bạn có thể dễ dàng clone source code, tham gia đóng góp vào các dự án này.

Vậy open source giúp bạn lên trình code như thế nào?

Thứ nhất, bạn có thể học hỏi từ những developer giỏi trên khắp thế giới. Một đại thi hào thường đọc rất nhiều sách hay, tương tự, một developer giỏi thường đọc rất nhiều source code từ những đồng nghiệp tuyệt vời. Thông qua việc tiếp xúc, đọc hiểu những dự án open source chất lượng, bạn sẽ học được cách tổ chức code, cách viết code sạch đẹp, cách các developer khác xử lý vấn đề…

Sau khi đọc code, bạn có thể bắt đầu chọn cho mình những module nhỏ mà bạn hứng thú để bắt đầu code. Bạn có thể tự nghĩ ra các tính năng mới, hoặc cũng thể giải quyết các issues có sẵn. Dù cách nào đi chăng nữa thì bạn cũng sẽ học được vô số điều mới mẻ.

Nếu bạn có thể hoàn thành một vài tính năng mới hoặc giải quyết được các issues, đừng ngần ngại commit code của bạn, rất có thể nó sẽ được chấp nhận và tích hợp vào dự án đấy.

Ngoài lợi ích giúp bạn nâng cao khả năng code, việc đóng góp vào các dự án open source đôi khi còn là thước đo khả năng của bạn trong mắt các nhà tuyển dụng. Rất nhiều công ty, nhà tuyển dụng xem profile github là một trong những khía cạnh để đánh giá ứng viên đấy.

Pet project

Rất nhiều bạn bè của mình ở trường đại học nói với mình rằng họ đã quá chán nản với những project CRUD trong các đồ án môn học, họ muốn làm gì đó thực tế hơn. Tại sao không bắt đầu một pet project nhỉ?

Pet project là những dự án mà bạn nghĩ ra ý tưởng và làm trong thời gian rảnh. Giá trị của những project này nằm ở chỗ bạn có thể làm bất cứ thứ gì bạn thích, bất cứ công nghệ nào bạn muốn học, đặc biệt là nó giúp bạn làm ra được sản phẩm, điều mà bạn khó có thể đạt được khi đi làm.

Nhiều developer thường có ý nghĩ rằng pet project phải là thứ gì đó cao siêu, làm mấy cái nhỏ nhoi thì chẳng bõ công. Tuy nhiên, mục đích của pet project đơn giản là để bạn giải trí, rèn luyện khả năng code, khả năng làm sản phẩm chứ không phải để bán kiếm tiền hay startup. Vì vậy bạn có thể làm bất cứ thứ gì, miễn là bạn cảm thấy nó hữu ích, bạn yêu thích làm ra nó.

Những ý tưởng nhỏ nhặt có thể đến từ bất cứ đâu. Giả sử như crush của bạn thích được nhắn tin chào buổi sáng nhưng bạn lại hay ngủ đến tận trưa thì làm sao? Viết ngay một con bot tự động nhắn tin cho crush. Nhỡ crush nhắn tin lại mà con bot ngu quá không biết trả lời thì làm sao. Học ngay AI và train trình nhắn tin cho con bot. Thế là bạn có ngay một pet project.

Việc bắt đầu một pet project giúp bạn trải nghiệm được toàn bộ quy trình tạo ra một phần mềm ở giai đoạn development. Nếu như ở công ty, công việc của bạn là hoàn thành những task nhỏ trong một dự án lớn, mọi thứ đã được setup sẵn khiến bạn khó có thể nhìn thấy toàn bộ quá trình thì với pet project, bạn sẽ được làm mọi thứ từ việc setup môi trường, coding, testing, deploy…

Hy vọng mình thuyết phục được bạn rằng bạn nên bắt đầu một pet project. Nhưng chưa hết, bạn còn có thể đưa các pet project của bạn vào CV khi đi xin việc, các công ty sẽ đánh giá bạn cao hơn rất nhiều, đặc biệt nếu bạn là một người chưa có kinh nghiệm thì pet project lại càng quan trọng hơn. Bởi nó chứng minh cho phía công ty biết rằng bạn thật sự biết code, biết làm ra sản phẩm. Ngoài ra, biết đâu pet project của bạn lại được mọi người ưa chuộng thì sao? Rất nhiều dự án startup khởi đầu chỉ là một pet project, như Facebook chẳng hạn, mình tin rằng lúc code Facebook gã Mark Zuckerberg cũng chỉ xem nó như một pet project thôi.

Đọc sách về coding

Lần cuối cùng bạn đọc một cuốn sách về coding là khi nào? Mình tin rằng một số lượng kha khá developer không trả lời được câu hỏi này. Dù thế nào đi chăng nữa thì sách vẫn là một công cụ tuyệt vời giúp bạn nâng cao khả năng code, vì vậy đừng bỏ qua chúng.

Ai cũng có thể viết code, nhưng không phải ai cũng có thể viết code chất lượng. Ngoài code, bạn nên dành thời gian đọc sách, bởi sách là nơi các bậc lão thành truyền đạt kinh nghiệm lại cho hậu thế. Những kiến thức như: viết code sao cho dễ đọc, dễ hiểu, design kiến trúc sao cho dễ mở rộng, dễ bảo trì…, những kiến thức dạng này bạn khó có thể tìm thấy ở các video, các khóa học trên internet.

Hãy đứng trên vai những người khổng lồ. Bạn phải chấp nhận một điều rằng bạn không phải developer giỏi nhất trên thế giới. Vì vậy, hãy học tập từ những người giỏi nhất, những người có kinh nghiệm nhất, làm theo những chỉ dẫn của họ trong sách sẽ giúp bạn tiết kiệm được rất nhiều thời gian và công sức.

Code đã khó, đọc sách về code còn khó hơn rất nhiều, tuy nhiên, hãy tập cho bản thân thói quen này. Nếu bạn làm được, bạn sẽ nằm trong top những lập trình viên giỏi nhất.

Kết

Nâng cao khả năng code là cả một quá trình dài. Vì vậy, theo mình, bạn không nên quá quan trọng việc bạn có code giỏi hay không, trình độ của bạn đến đâu. Cái bạn cần làm là tận hưởng những gì code đem đến cho bạn, học cách tận hưởng 3 điều mình nêu ở trên, rồi sẽ đến lúc bạn không ngờ rằng bản thân code khiếp đến thế.

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

Xem thêm việc làm Software Developers tại TopDev

TopDev via thedarkknighttech.com

  Chuyện bi kịch của công ty code outsourcing

.NET core vs ASP.NET core: Phân biệt .NET Framework, .NET Core và Mono

net-core-vs-asp-net-core

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

Dù là một lập trình viên có kinh nghiệm nhưng bạn đã phân biệt được .NET core vs ASP.NET core? Một trong những điểm mạnh của hệ sinh thái .NET là sự hỗ trợ rất tốt của các công cụ như Visual Studio. Tuy nhiên đây cũng là điểm yếu vì nó ngăn cản rất nhiều lập trình viên tiếp xúc với những lý thuyết căn bản của Framework. Trong bài viết này chúng ta sẽ tìm hiểu xem .NET là gì, và các nền tảng .NET Framework, .NET core, và Mono khác nhau như thế nào.

TẠI SAO CẦN NẮM RÕ LÝ THUYẾT CĂN BẢN?

Mình đã từng gặp rất nhiều những người đã làm việc với .NET lâu năm nhưng vẫn mù mờ về những khái niệm, định nghĩa của Framework. Điều này rất nguy hiểm vì nó gây ra việc hiểu sai về nền tảng, dẫn đến việc sản sinh ra những phần mềm chất lượng không cao. Do đó hiểu rõ về framework của mình là trách nhiệm của bất cứ lập trình viên nào?

KHI NÓI VỀ .NET, NGƯỜI TA THƯỜNG HÀM Ý 3 THÀNH PHẦN:

Runtime (môi trường hoạt động)

Libraries (thư viện)

Toolings (công cụ phát triển).

Chúng ta sẽ từ từ tìm hiểu chức năng từng thành phần ở phần sau của bài viết.

Trước hết, Chúng ta cần hiểu được làm thế nào .NET có thể chạy được đoạn code C# (hay VB, F#) mà bạn viết ra. Để hiểu được điều này, chúng ta cần nắm rõ quy trình biên soạn code trong .NET

.NET core vs ASP.NET core

Trong hình trên, phần ‘Compile time’ là quá trình ‘Build’, và ‘Runtime’ là quá trình chạy (tức là tính từ khi bạn khởi động ứng dụng của mình).

Về cơ bản, khi bạn thực hiện lệnh build (trong Visual Studio, hay ‘dotnet build’ bằng dòng lệnh) thì source code của bạn được chuyển hóa thành một dạng ngôn ngữ trung gian có tên là MSIL (Microsoft Intermediate Language). Khi ứng dụng được khởi chạy, thành phần Runtime-hay tên gọi riêng biệt trong .NET là CLR(common language runtime) sẽ tiến hành dịch mã MSIL thành mã máy(Native code) để cho máy tính có thể thực thi. Quá trình này gọi là JIT (just-in-time) compilation. Cách biên soạn và vận hành của .NET khá giống với Java.

  Các thành phần trong hệ sinh thái .NET
  Google AMP là gì ? Cài đặt AMP cho website asp.net mvc

Để hiểu rõ hơn về JIT, chúng ta hãy thử làm một thí nghiệm. Copy đoạn code sau vào file Program.cs trong project của bạn:

using System;
using System.Diagnostics;

namespace ConsoleApplication
{
    public class Program
    {
        public static void DoSomeCalculation()
        {
            string input = "0";
            for (int i = 0; i < 10; i++)
            {
                var converted = Convert.ToInt32(input);
                converted++;
                input = converted.ToString();
            }
        }

        public static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();

            //first time
            sw.Start();
            DoSomeCalculation();
            sw.Stop();
            Console.WriteLine($"First calculation: {sw.ElapsedTicks} ticks");

            //second time
            sw.Restart();
            DoSomeCalculation();
            sw.Stop();
            Console.WriteLine($"Second calculation: {sw.ElapsedTicks} ticks");
        }
    }
}

Chúng ta sẽ tiến hành gọi cùng 1 hàm 2 lần và đo xem thời gian chạy của 2 lần gọi là bao nhiêu. (10000 ticks = 1 ms). Tiến hành chạy ‘dotnet run’ và xem kết quả.

.NET core vs ASP.NET core

Bạn có thể thấy rằng lần chạy đầu tiên lâu hơn lần thứ 2 rất nhiều. Tại sao vậy? Đó là do khi DoSomeCalculation() được gọi lần đầu, CLR tiến hành biên soạn (JIT) hàm này thành ngôn ngữ máy. Ở những lần chạy kế tiếp, DoSomeCalculation() không cần ‘JIT’ lại (do đã được ‘JIT’ xong), nên thời gian thực thi nhanh hơn nhiều. (Điều này cũng lý giải tại sao trong một số phần mềm, thời gian thực hiện một chức năng nào đó lần đầu tiên thường chậm hơn so với các lần kế tiếp).

Tại sao lại cần có ngôn ngữ trung gian? Ngôn ngữ trung gian trong .NET khá gần với mã máy nhưng không chứa thông tin cụ thể về CPU. Việc giúp cho đoạn code trung gian của bạn có thể hoạt động trên nhiều loại CPU (64bit, 32bit), cũng như nhiều loại kiến trúc khác nhau (ARM, Intel…)

Trên thực tế một vài ngôn ngữ (Javascript, Python…) không sử dụng đến ngôn ngữ trung gian: Source sẽ được dịch thẳng ra mã máy tại tại ‘Runtime’. Điểm lợi của việc này là quá trình build được đơn giản hóa, tuy nhiên hiệu năng sẽ bị hạn chế.

Ngoài việc biên dịch, môi trường hoạt động (Runtime) còn có những công dụng như:

– Tự động quản lý bộ nhớ. Khi làm việc với những ngôn ngữ bậc cao như C# hay Java, bạn không cần  giải phóng bộ nhớ bằng cách gọi free() như khi làm việc với C/C++. CLR bao gồm một công cụ dọn rác (Garbage collector -GC) sẽ tự động giải phóng những phần bộ nhớ không được sử dụng

– Strong typings: CLR quản lý thông tin về các kiểu dữ liệu mà bạn sử dụng. Điều này giúp cho bạn có thể phân biệt được các định dạng thông tin của từng biến khác nhau (class, structure…)

  So sánh ASP.NET và PHP? Lập trình website nên học ngôn ngữ nào?
  ASP.NET MVC5 #3: Thêm mới View

Tuyển dụng ASP.NET lương cao lên đến 3000 USD

Thế còn hệ thống thư viện (Libraries) và công cụ (Toolings) thì sao?

Khi bạn làm việc với .NET, code của bạn sẽ tương tác với rất nhiều các class khác nhau. Ví dụ: Class được sử dụng nhiều nhất trong .NET là System.String. Tất cả những class này được định nghĩa trong hệ thống thư viện cơ bản của .NET mà người ta hay gọi tắt là BCL (Base class libraries).

Mã nguồn của BCL, trái với mọi người hay nghĩ, là mã nguồn mở. Bạn có thể truy cập mã nguồn này tại sourceof.net .

Các công cụ (toolings) của .NET bao gồm compiler và Visual Studio .NET sử dụng hệ thống build của Microsoft gọi là MSBuild. Đối với nền tảng .NET core mới thì chúng ta còn có thêm công cụ dòng lệnh (dotnet cli).

Phân biệt .NET Framework, .NET Core, và Mono

Tại sao cần phải phân biệt chúng? Vì bạn cần phải hiểu rõ mình đang làm gì. VD: Nếu bạn có ý định chạy một Web server trên Linux thì tuyệt đối không nên sử dụng Mono.

Đối với những người mới làm quen với .NET hay kể cả một số người đã làm việc với .NET lâu năm, những cái tên như .NET Framework, Mono hay gần đây nhất là .NET core vẫn hay gây ra những hiểu nhầm. Tuy nhiên những khái niệm căn bản về .NET nói trên giúp chúng ta phân biệt khá dễ dàng. Về cơ bản, .NET Framework, .NET core và Mono là ba phiên bản .NET khác nhau (có nghĩa là mỗi phiên bản có Runtime, Libraries và Toolings riêng).

Vậy tại sao lại có đến 3 phiên bản khác nhau?

– .NET Framework được Microsoft đưa ra chính thức từ năm 2002. .NET Framework chỉ hoạt động trên Windows. Những nền tảng ứng dụng như WPF, Winforms, ASP.NET(1-4) hoạt động dựa trên .NET Framework.

– Mono là phiên bản cộng đồng nhằm mang .NET đến những nền tảng ngoài Windows. Mono được phát triển chủ yếu nhằm xây dựng những ứng dụng với giao diện người dùng và được sử dụng rất rộng rãi: Unity Game, Xamarin…

– Cho đến năm 2013, Microsoft định hướng đi đa nền tảng và phát triển .NET core. .NET core hiện được sử dụng trong các ứng dụng Universal Windows platform và ASP.NET Core.

.NET core vs ASP.NET core

VẬY TÔI NÊN SỬ DỤNG .NET FRAMEWORK, .NET CORE, HAY MONO?

Điều đó tùy thuộc vào ứng dụng mà bạn có ý định phát triển. Đối với các ứng dụng Windows desktop, .NET Framework sẽ là sự lựa chọn của bạn. Nếu bạn phát triển game dựa trên Unity, hay những ứng dụng di động với Xamarin, bạn sẽ sử dụng Mono. Đối với các Web server, bạn có thể sử dụng cả .NET Framework và .NET Core.

Tuyệt đối không nên dùng Mono để vận hành web server. Bộ máy dọn rác của Mono không được thiết kế để hoạt động với webserver và sẽ gây ra quá tải nhanh chóng.

Vậy nên lựa chọn .NET Framework hay .NET Core cho các web server? .NET Core chạy được đa nền tảng và có hiệu năng cao hơn. Nhược điểm duy nhất của nó là số lượng thư viện hỗ trợ vẫn còn hạn chế. .NET Framework có hệ sinh thái lớn hơn với nhiều các thư viện hỗ trợ hơn.

Series này sẽ sử dụng .NET Core. Chúng ta nên hướng đến tương lai đúng không?

Xem tình hình .NET tuyển hiện nay tại TopDev

Các bài viết liên quan:

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

Postman là gì? Hướng dẫn API Testing với Postman – API Platform

postman-la-gi

Postman là gì? Nó được các developer sử dụng để làm gì? Có thể đây là lần đầu tiên bạn nghe đến Postman, nhưng đừng lo, tất cả thông tin chi tiết nhất sẽ được TopDev chia sẻ trong bài viết dưới đây!

Postman là gì?

Đầu tiên ta cần nắm khái niệm Postman là gì?

Postman là một nền tảng API để xây dựng và sử dụng API.

Postman - API platform
Postman – API platform

Postman hiện là một trong những công cụ phổ biến nhất được sử dụng trong thử nghiệm các API.

Như ta đã biết, API chịu trách nhiệm kết nối các ứng dụng với nhau, có Postman sẽ giúp cho thao tác với API này trở nên dễ dàng hơn. Thông thường, Postman sẽ được dùng cho API kiểu REST. Với Postman, ta có thể gọi Rest API mà không cần viết dòng code nào.

Postman hỗ trợ tất cả các phương thức HTTP (GET, POST, PUT, PATCH, DELETE, …). Bên cạnh đó, nó còn cho phép lưu lại lịch sử các lần request, rất tiện cho việc sử dụng lại khi cần.

Các tính năng chính của Postman

Postman là một công cụ mạnh mẽ giúp các nhà phát triển và tester làm việc với API một cách hiệu quả. Dưới đây là một số tính năng nổi bật của Postman:

Postman Visualizer

Postman’s Visualizer cho phép bạn tăng cường việc trình bày dữ liệu phản hồi API bằng cách sử dụng HTML, CSS và JavaScript. Bạn có thể tạo các hình ảnh tùy chỉnh như biểu đồ, bảng hoặc các phần tử khác để làm cho dữ liệu phản hồi dễ đọc và hiểu hơn.

Cách sử dụng Postman Visualizer:

  1. Tạo một yêu cầu mới hoặc mở một yêu cầu hiện có trong Postman.
  2. Gửi yêu cầu để nhận phản hồi từ API.
  3. Trong bảng phản hồi, nhấp vào nút “Visualize” ở góc trên bên phải.
  4. Mở trình soạn thảo Visualizer, nơi bạn có thể viết mã HTML, CSS và JavaScript để tùy chỉnh hình ảnh phản hồi.
  5. Sử dụng các biến dữ liệu sẵn có (ví dụ: responseBody, responseHeaders, v.v.) để truy cập dữ liệu phản hồi trong mã của bạn.
  6. Viết mã HTML, CSS và JavaScript để tạo hình ảnh mong muốn.
  7. Xem trước hình ảnh bằng cách nhấp vào nút “Preview”.
  8. Lưu các thay đổi và đóng trình soạn thảo Visualizer.

Thư viện tích hợp sẵn (Built-in Libraries)

Postman cung cấp nhiều thư viện bên ngoài mà bạn có thể sử dụng trong các tab Pre-request Script và Test Script để thêm các chức năng bổ sung mà JavaScript không có sẵn.

Một số thư viện thông dụng trong Postman:

  • Moment.js: Một thư viện JavaScript phổ biến để phân tích, thao tác và định dạng ngày giờ.
  • Lodash: Thư viện tiện ích cung cấp nhiều hàm hỗ trợ xử lý mảng, đối tượng và chuỗi.
  • Faker.js: Thư viện để tạo dữ liệu giả lập thực tế như tên, địa chỉ, số điện thoại, email, v.v.

Kiểm soát luồng công việc (Workflow Control)

Postman cho phép bạn kiểm soát thứ tự thực hiện các yêu cầu trong một collection bằng phương thức postman.setNextRequest. Bằng cách sử dụng logic điều kiện trong tab Pre-request Script hoặc Tests, bạn có thể thiết lập yêu cầu tiếp theo được thực hiện dựa trên các điều kiện cụ thể.

Cách sử dụng postman.setNextRequest:

  1. Mở Collection Postman và điều hướng đến yêu cầu mong muốn.
  2. Trong tab Pre-request Script hoặc Tests, viết logic điều kiện bằng JavaScript.
  3. Sử dụng phương thức postman.setNextRequest để chỉ định yêu cầu tiếp theo được thực hiện.
  4. Lưu các thay đổi.

Hỗ trợ GraphQL tích hợp sẵn (Built-in GraphQL Support)

Postman cung cấp hỗ trợ mạnh mẽ cho GraphQL, giúp các nhà phát triển làm việc với các API GraphQL dễ dàng hơn.

Các tính năng và chức năng chính cho GraphQL trong Postman:

  • GraphQL Variables: Cho phép bạn định nghĩa và sử dụng các biến GraphQL trong các yêu cầu.
  • GraphQL Request Body: Gửi các truy vấn và mutation GraphQL dưới dạng yêu cầu POST trong phần thân yêu cầu.
  • GraphQL Autocompletion: Hỗ trợ tự động hoàn thành các trường, kiểu và tham số khi bạn gõ.
  • User-Defined GraphQL Schemas: Cho phép nhập và sử dụng các schema GraphQL của riêng bạn.
  • GraphQL Query History: Giữ lịch sử các truy vấn GraphQL, giúp dễ dàng truy cập và tái sử dụng.

Collections

Postman cung cấp tính năng “Collections” để giúp bạn tổ chức các yêu cầu API của mình. Với collections, bạn có thể nhóm các yêu cầu liên quan lại với nhau, giúp quản lý và thực hiện nhiều yêu cầu như một đơn vị đồng nhất.

Các tính năng và lợi ích của Collections trong Postman:

  • Organization: Tổ chức các yêu cầu API theo cách phân cấp.
  • Execution: Dễ dàng thực hiện tất cả các yêu cầu trong một collection chỉ với một lần nhấp.
  • Variables and Environments: Hỗ trợ sử dụng các biến và thiết lập các môi trường khác nhau.
  • Sharing and Collaboration: Chia sẻ các collections với các thành viên trong nhóm để cộng tác.
  • Documentation: Tạo tài liệu cho các collections để người khác hiểu và sử dụng API.

Kiểm thử và xác nhận (Tests and Assertions)

Postman bao gồm một khung kiểm thử mạnh mẽ, cho phép bạn viết các bài kiểm tra bằng JavaScript để xác thực các khía cạnh khác nhau của phản hồi API.

Các xác nhận phổ biến trong Postman tests:

  • Status code assertion: Xác minh mã trạng thái phản hồi khớp với giá trị mong đợi.
  • Response body assertion: Kiểm tra dữ liệu trong phần thân phản hồi.
  • Header assertion: Xác thực sự hiện diện và giá trị của các tiêu đề cụ thể trong phản hồi.
  • Response time assertion: Đảm bảo thời gian phản hồi nằm trong phạm vi chấp nhận được.

Ví dụ về kiểm thử đơn giản:

pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

pm.test("Response body contains key 'username'", function () {
    pm.response.to.have.jsonBody('username');
});

pm.test("Content-Type header is present and set to JSON", function () {
    pm.response.to.have.header("Content-Type", "application/json");
});

pm.test("Response time is within acceptable range", function () {
    pm.expect(pm.response.responseTime).to.be.below(500);
});

Postman là một công cụ không thể thiếu cho các nhà phát triển và tester làm việc với API. Với các tính năng mạnh mẽ và linh hoạt như Visualizer, thư viện tích hợp sẵn, kiểm soát luồng công việc, hỗ trợ GraphQL, collections và kiểm thử, Postman giúp đơn giản hóa và tối ưu hóa quy trình phát triển và kiểm thử API.

  Import RAML vào Postman

Hướng dẫn cài đặt Postman

Postman cho phép người dùng cài đặt dưới 2 hình thức: tool cài vào máy và Chrome Apps.

Cài Postman vào máy:

Download tại địa chỉ https://www.getpostman.com/

Postman

Cài đặt Postman như một Chrome app (UPDATE 30/10/2017): Hiện nay Chrome không còn hỗ trợ app nữa nên phần này không còn sử dụng được

Vào link https://chrome.google.com/webstore/search/postman?hl=en-US. Sau khi cài xong Postman sẽ xuất hiện ở đây

Postman Chrome

Các thành phần chính của Postman

Giao diện của Postman

Postman UI

Settings: chứa các thông tin về cài đặt chung.

  • Thông tin Account: dùng để Login, logout và sync data.
  • Settings tùy chỉnh: themes, shortcut, format…
  • Import data từ ngoài vào

Postman Settings

Collections: lưu trữ thông tin của các API theo folder hoặc theo thời gian.

Postman Collections

API content: hiển thị nội dung chi tiết API và các phần hỗ trợ giúp thực hiện test API. Đây là phần mà tester phải làm việc nhiều nhất.

Postman Content

Trong phần này gồm có 3 thành phần chính:

  • Environments: Chứa các thông tin môi trường. Ví dụ: mình làm 1 dự án nhưng có 3 môi trường khác nhau: dev, staging và product. Có phần này, mình có thể nhanh chóng đổi sang môi trường cần test mà không phải mất công đổi URL của từng request. (Cái này sẽ được nói rõ hơn ở những bài sau)
  • Request: Phần chứa các thông tin chính của API.
  • Response: Chứa các thông tin trả về sau khi Send Request.

Các thành phần khác của Postman

  1. New – tạo request, collection hoặc enviroment mới.
  2. Import – import collection hoặc environment. Có các tuỳ chọn để import từ file, folder, link hoặc paste từ text thuần.
  3. Runner – Kiểm tra tự động hóa có thể được thực hiện thông qua Runner cả collection.
  4. Open New – Mở một tab mới, cửa sổ Postman hoặc cửa sổ Runner.
  5. My Workspace – Tạo khu vực làm việc riêng hoặc cho một nhóm.
  6. Invite – Cộng tác với nhiều thành viên bằng việc mời các thành viên.
  7. History – Các request đã thực hiện mà bạn đã thực hiện sẽ được hiển thị trong History. Giúp bạn có thể lần theo các hành động bạn đã làm.
  8. Collections – Tổ chức bộ thử nghiệm của bạn bằng cách tạo collection. Mỗi collection có thể có các thư mục con và nhiều yêu cầu. Request hoặc thư mục cũng có thể được trùng lặp.
  9. Tab Request – Hiển thị tiêu đề của requet mà bạn đang làm việc. Mặc định “Untitled Request” sẽ được hiển thị cho các request không có tiêu đề.
  10. HTTP Request – Click vào đây sẽ hiển thị danh sách thả xuống với các request khác nhau như GET, POST, COPY, DELETE, v.v. Trong thử nghiệm, các yêu cầu được sử dụng phổ biến nhất là GET và POST.
  11. Request URL – Còn được gọi là điểm cuối (endpoint), đây là nơi bạn sẽ xác định liên kết đến nơi API sẽ giao tiếp.
  12. Save – Nếu có thay đổi đối với request, nhấp vào Save là bắt buộc để những thay đổi mới sẽ không bị mất hoặc bị ghi đè.
  13. Params – Đây là nơi bạn sẽ viết các tham số cần thiết cho một request, ví dụ như các cặp key – value.
  14. Authorization – Để truy cập API, cần được cấp quyền. Nó có thể ở dạng tên người dùng và mật khẩu, bearer token, v.v.
  15. Headers – Bạn có thể thiết lập các header như nội dung kiểu JSON tùy theo cách tổ chức của bạn.
  16. Body – Đây là nơi chúng ta có thể tùy chỉnh chi tiết trong request thường được sử dụng trong request POST.
  17. Pre-request Script – Đây là các tập lệnh sẽ được thực thi trước request. Thông thường, script tiền request (pre-request) cho cài đặt môi trường được sử dụng để đảm bảo các kiểm tra sẽ được chạy trong môi trường chính xác.
  18. Tests – Đây là các script được thực thi khi request. Điều quan trọng là phải có các thử nghiệm như thiết lập các điểm checkpoint để kiểm tra trạng thái là ok, dữ liêu nhận được có như mong đợi không và các thử nghiệm khác.

API Testing với Postman

API Testing là một phần quan trọng trong quá trình phát triển phần mềm, giúp đảm bảo rằng các API hoạt động đúng và hiệu quả. Dưới đây là quy trình cơ bản để thực hiện API Testing với Postman:

Gửi yêu cầu API cơ bản

  • Mở Postman và tạo một yêu cầu mới bằng cách nhấp vào New > Request.
  • Chọn phương thức HTTP (GET, POST, PUT, DELETE, v.v.) và nhập URL của API endpoint.
  • Nhấp vào Send để gửi yêu cầu và xem phản hồi từ máy chủ.

Tạo Collection và thêm yêu cầu

  • Tạo một Collection mới bằng cách nhấp vào New > Collection.
  • Đặt tên cho Collection và lưu lại.
  • Thêm các yêu cầu API vào Collection bằng cách nhấp chuột phải vào Collection và chọn Add Request.

Thiết lập biến môi trường

  • Tạo môi trường mới bằng cách nhấp vào biểu tượng Manage Environments và chọn Add.
  • Đặt tên môi trường và thêm các biến môi trường cần thiết (ví dụ: base URL, token xác thực, v.v.).
  • Sử dụng các biến môi trường trong các yêu cầu API bằng cú pháp {{variable_name}}.

Viết kịch bản kiểm thử

  • Mở yêu cầu API và chuyển đến tab Tests.
  • Viết các kịch bản kiểm thử bằng JavaScript để xác thực phản hồi từ API. Ví dụ:
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

pm.test("Response time is less than 500ms", function () {
    pm.expect(pm.response.responseTime).to.be.below(500);
});

Chạy Collection và kiểm tra kết quả

  • Chạy toàn bộ Collection bằng cách nhấp vào nút Runner trong Postman.
  • Chọn Collection và môi trường cần chạy, sau đó nhấp vào Start Test.
  • Xem kết quả kiểm thử và các báo cáo chi tiết.

Tích hợp với CI/CD

  • Sử dụng Postman CLI (Newman) để chạy các Collection trong các pipeline CI/CD.
  • Cài đặt Newman bằng lệnh NPM:

npm install -g newman

  • Chạy Collection bằng Newman:
newman run path_to_your_collection.json -e path_to_your_environment.json

 

Tóm lại, Postman là một công cụ API client không thể thiếu cho các nhà phát triển và tester, giúp họ làm việc với API một cách hiệu quả và dễ dàng. Với nhiều tính năng mạnh mẽ và khả năng tích hợp với các công cụ khác, Postman không chỉ giúp tiết kiệm thời gian và công sức mà còn đảm bảo chất lượng và tính nhất quán của các API trong suốt quá trình phát triển phần mềm.

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

Xem thêm việc làm Rest API tại TopDev

Chuyện bi kịch của công ty code outsourcing

code outsourcing

[Chú ý: bài viết sử dụng 1 vài từ ngữ thuộc *văn nói* nơi gầm bàn công sở. Sẽ không phù hợp với một số anh chị.]

Các dự án mà thiếu PM cứng, đủ tầm để dọn ngang dẹp dọc thì kiểu gì cũng đi vào thảm cảnh như bài dưới đây.

Hiện tại có rất nhiều anh chị em lập team, mở công ty, đa phần là code outsourcing (web và mobile app). Đa phần là các công ty có quy mô vừa và nhỏ, từ 30 đến 50 người là đã hoành tráng rồi.

Tuy nhiên không phải công ty nào cũng có một quy trình quản lý dự án chuẩn để đảm bảo chất lượng. Mình xin chia sẻ 1 số kinh nghiệm như bên dưới, hy vọng có thể giúp ích được cho anh chị em.

  "Dân làm Product khác hoàn toàn 180 độ với dân làm outsourcing"
  Tại sao các công ty Software Outsourcing hoạt động không giống những gì bạn nghĩ?

Câu chuyện bị kịch của công ty code outsourcing

Đầu tiên là thằng Sales nó sẽ gặp khách hàng, dụ dỗ chào mời, đưa giá làm trong 5 tháng. (project cỡ trung bình).

Xong thằng BA/PM sẽ cùng thằng Sales lấy requirements từ khách hàng. Song song HR sẽ chạy đi tuyển dev về để làm.

Khách hàng ok, ký hợp đồng và thanh toán 30%, sales hốt trước 5% của cái 30% đó, tháng này ấm rồi.

Thằng team lead / project lead sẽ cùng với thằng senior dev ngồi break down requirement, tính task, xong thằng team lead căng thời gian, với requirements này, giả tỷ như không thay đổi thêm bớt gì, thì làm 8 tháng xong.

Thằng PM gật gù, ok deadline 4 tháng, kèm lời hứa làm ngon anh share bonus dự án cho.

Thằng team lead sắp xếp nhân sự, chia task, scrum/agile các kiểu, hùng hồn: dự án này anh em mình 3 tháng xong, Thằng senior dev vừa training cho 3 đứa mới vô vừa gánh team 3 thằng dev mới vô tuần làm 5 ngày, ngày 8 tiếng, chưa kể OT buổi tối + thứ 7, CN làm ở nhà.

Sau 1 tháng 1 thằng out. HR tuyển thêm 1 thằng nữa + PM hốt 1 thằng dev từ team khác qua phụ.

1 tháng sau thì phát hiện hiểu sai một số yêu cầu từ khách hàng + khách hàng mới thấy 1 trang web nào đó có tính năng hay quá, yêu cầu làm giống vậy.

Tiếp 1 tháng nữa, về cơ bản dự án đã fail 1 cách hoàn hảo. Thằng team leader nhảy vô code phụ 2 thằng junior, do thằng senior dev đang nằm viện vì bệnh lao.

PM quyết định kéo thêm 2 thằng dev khác từ 1 dự án khác vào. 2 thằng này tốn tầm 2 tuần để ngồi đọc documents và hiểu cái mớ bùi nhùi do 2 thằng junior dev mới vào code.

Qua tháng thứ 6, thằng sales hiện đã sang làm cho công ty khác. Thằng PM vẫn liên lạc với khách hàng để kỳ kèo thời gian. Về mặt development team thì thằng senior dev đã ra viên, OT được hơn 1 tuần rồi, đám còn lại vẫn đang code + debug, thằng team lead thi thoảng xin nghỉ nửa buổi đi phỏng vấn công ty nào đó.

Qua tháng thứ 7, khách hàng đã có demo để xem.

Qua tháng thứ 8, khách hàng thanh toán 40% chi phí project để nhận 1 cục source code “có thể chạy được nếu click vào các nút theo đúng thứ tự đã chỉ dẫn” kèm theo lời tuyên bố không bao giờ quay lại.

Qua tháng thứ 9, 2 thằng junior dev bị đuổi do kỹ năng không đạt yêu cầu, năng suất làm việc kém.

Cuối quý thằng PM được bonus dự án như bình thường. Thằng team lead đã tự ra mở công ty riêng. Thằng senior dev qua Lazada làm với mức lương gấp đôi. HR lại tiếp tục tuyển thêm dev để lấp vào chỗ trống.

Sau vài tháng công ty code outsourcing chuẩn bị phá sản.

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

Xem thêm việc làm Software Developers tại TopDev

TopDev via Khuyen Le Minh

  Thị trường Outsourcing Vietnam - Thiên đường Outsourcing mới của thế giới
  “Chúng tôi không làm outsource, chúng tôi chính là source!”

Animation – dụng cụ “vàng” trong làng UX

Animation - dụng cụ “vàng” trong làng UX

Khi UX tốt không chỉ đến từ 1 thiết kế đẹp

Đến 90% người dùng sử dụng ứng dụng do hiệu suất kém, 86% người dùng xoá ứng dụng khi gặp phải vấn đề thiết kế hay chức năng. Ngược lại, có đến 86% người dùng đánh giá cao những ứng dụng có trải nghiệm đặc biệt. Từ những con số này, không khó để hiểu được lý do tại sao các công ty tập trung vào User Experience như Apple, Google, Adobe, Dropbox và Amazon vẫn luôn dẫn đầu trong lĩnh vực của họ.

UX – hay còn gọi là trải nghiệm người dùng (User experience) – là cách mà người dùng cảm nhận về một sản phẩm cụ thể, cách họ sử dụng sản phẩm đó.

Người làm về UX gọi là UX Designer. Họ là những người nghiên cứu và đánh giá về thói quen, cách mà một người khách hàng sử dụng và cảm nhận về 1 hệ thống (Sử dụng hệ thống thông qua UI). Sử dụng và cảm nhận ở đây đơn giản là những vấn đề như tính dễ sử dụng, sự tiện ích, tính hiệu quả khi sản phẩm hoạt động.

Tại Việt Nam, thói quen sử dụng UX của các nhà phát triển web hiện vẫn còn gặp rất nhiều lỗi như: quá “tham” khi đưa nhiều chức năng, nhiều tiểu tiết vào giao diện game hoặc trang web, như kết nối 3G hay dung lượng file cài đặt, hay bỏ sót các yếu tố quan trọng ảnh hưởng đến trải nghiệm người dùng, hoặc làm việc đơn lẻ thay vì tập hợp thành nhóm…

Xem thêm: Tìm việc làm designer hấp dẫn không yêu cầu kinh nghiệm

Vì sao animation đóng vai trò quan trọng hơn cả?

  • Chuyển động bằng hình ảnh sẽ nhanh hơn dạng text 60,000 lần
  • Não bộ tiếp nhận thông tin 90% từ hình ảnh
  • Não và mắt của chúng ta được “lập trình” để chú ý những chi tiết chuyển động và nhiều màu sắc

Những điều trên là lý do vì sao hình ảnh càng động thì hiệu ứng của UX cũng sẽ càng được cải thiện. Từ đó

+ Người dùng có thể thư giãn nếu App bạn đang load

+ Sự chuyển động sẽ giúp người dùng tập trung hơn vào đối tượng cần chú ý.

+ Sự kết nối mạch lạc khiến người dùng thích thú.

+ Làm nổi bật lỗi khi thông báo hoặc tác vụ hoàn thành.

◾️ Song, người dùng luôn bận rộn đồng nghĩa với việc bạn chỉ có một chút ít thời gian để thu hút họ? Vậy nên, nếu chúng ta có thể tận dụng được khoảnh khắc đó, chúng ta có thể có thêm những khách hàng tiềm năng với giá trị to lớn.

Để hiểu rõ hơn cách cải thiện UX của các marketers, businessman, developers.. trong bức tranh UX muôn hình vạn trạng, bạn có sẵn sàng đi sâu hơn về UX/UI được xem là một trong những ngành nghề “hot” nhất hiện nay cùng chúng tôi?

Buổi Meetup đặc sắc mang tên “ (UX) – Multiple Screen, Surprise and Delights Users by Animation” sẽ được diễn ra vào ngày 12/07/2019 với sự chia sẻ đầy kinh nghiệm từ các chuyên gia trong lĩnh vực mobile:

  • Anh HOÀNG NGUYỄN – Senior Product Design | Interactive Labs & Design Coach | GEEK Up
  • Anh PHAN VIẾT TRUNG – Mobile Lead | Dwarves Foundation

Điều gì đáng quan tâm và cải thiện? hay nói cách khác bạn đang mang đến giá trị gì cho người dùng? Thay vì mơ hồ tìm kiếm trên Internet thì hãy giữ ngay cho mình một slot tham dự cùng bạn bè và “mổ xẻ” những điều còn là ẩn số trong lĩnh vực UX/UI nhé!

NHẬP NGAY CODE EARLYBIRD@UX1207 GIẢM 50.000Đ/VÉ BẠN NHÉ! HẠN CHÓT ĐẾN 17:00 NGÀY MAI!

===
THÔNG TIN CHUNG
Thời gian: 17:30 ngày 12/07/2019 

Địa điểm: Saigon Innovation Hub – 273 Điện Biên Phủ, O7, Q3, HCM
===
THÔNG TIN LIÊN HỆ
Event team: event@applancer.net | 028 6681 3236

Ms. Thoa | thoa.nguyen@applancer.net | 038 5098 969

Sự khác nhau giữa AI, Machine Learning và Deep Learning

su-khac-nhau-giua-ai-machine-learning-va-deep-learning

Cách phân biệt machine learning và deep learning là bài viết đầu tiên trong series nhiều phần giải thích các nguyên tắc cơ bản của deep learnining – nhà báo Michael Copeland.

Để biết cách phân biệt machine learning và deep learning là gì đầu tiên chúng ta phải hiểu khái niệm. Trí tuệ nhân tạo (AI) là tương lai. Trí tuệ nhân không chỉ là khoa học viễn tưởng mà còn là một phần của cuộc sống hàng ngày của chúng ta. Nó phụ thuộc vào mục tiêu phát triển AI của bạn

Ví dụ: Khi AlphaGo của Google đánh bại kì thủ cờ vây quốc tế người Hàn Quốc Lee Se-Dol vào năm 2016. Thuật ngữ AI, machine learning và deep learning được giới truyền thông sử dụng để mô tả chiến thắng của DeepMind. Cả AI, machine learning và deep learning đều góp phần tạo nên chiến thắng của AlphaGo trước kì thủ Se-Dol. Nhưng chúng không giống nhau, để biết cách phân biệt machine learning và deep learning, mời bạn đọc qua khái niệm dưới đây.

Cách đơn giản nhất để hình dung về mối quan hệ của 3 khái niệm trên là dùng sơ đồ Venn. AI – ý tưởng đầu tiên – lớn nhất, sau đó là machine learning, và cuối cùng là deep learning – yếu tố thúc đẩy sự bùng nổ của AI ngày nay .

 

Từ mờ nhạt đến sự bùng nổ

AI là một phần trong trí tưởng tượng của chúng ta và là chủ đề bàn luận sôi nổi trong các phòng thí nghiệm nghiên cứu kể từ khi một nhóm các nhà khoa học máy tính sử dụng thuật ngữ này tại Hội nghị Dartmouth vào năm 1956 – lĩnh vực AI bắt đầu từ đó. Trong nhiều thập kỷ sau đó, AI được dự đoán là chìa khóa mở ra một tương lai tươi sáng nhất của nền văn minh nhân loại, khái niệm harebrained của over-reach propellerheads sẽ bị vứt bỏ. Thành thật mà nói, cho đến năm 2012, nó có một chút là sự kết hợp cả hai.

Trong vài năm trở lại đây, AI thật sự bùng nổ, đặc biệt là từ năm 2015. Phần lớn trong số đó liên quan đến những tiện ích sẵn có của GPU khiến cho việc xử lý song song nhanh, rẻ và mạnh mẽ hơn. Nó cũng liên quan đến cả vấn đề lưu trữ vô hạn trong thực tiễn và nhóm dữ liệu trên mỗi vạch (toàn bộ quá trình Big Data) – hình ảnh, văn bản, giao dịch, sơ đồ dữ liệu…

Cùng điểm qua chặng đường các nhà khoa học máy tính đã phát triển AI từ mờ nhạt để trở thành một sự bùng nổ với các ứng dụng được sử dụng bởi hàng trăm triệu người mỗi ngày giúp mọi người biết cách phân biệt machine learning và deep learning.

Trí tuệ nhân tạo – trí tuệ con người được mô phỏng bởi máy móc

 

Trở lại mùa hè năm 1956, ước mơ của những nhà tiên phong về công nghệ bấy giờ là xây dựng các máy móc phức tạp – có đặc điểm giống với trí thông minh con người, biết cách phân biệt machine learning và deep learning. Đây là khái niệm mà chúng ta nghĩ là “General AI” – những thiết bị hoàn hảo có tất cả các giác quan của con người (có thể nhiều hơn), có khả năng suy đoán, suy nghĩ như chúng ta. Có thể bạn đã nhìn thấy nó trong một loạt các bộ phim như friend —  C-3PO —  and foe —  The Terminator. Tuy nhiên, General AI vẫn còn nằm trong các bộ phim và tiểu thuyết khoa học viễn tưởng vì lý do nhân đạo. Chúng ta không thể thực tế nó, hoặc ít nhất là chưa phải lúc này.

Những gì chúng ta có thể làm, rơi vào khái niệm “Narrow AI“. Các công nghệ có khả năng thực hiện các nhiệm vụ cụ thể tương đương, hoặc tốt hơn con người có thể làm để biết cách phân biệt machine learning và deep learning. Ví dụ về Narrow AI là những thứ như phân loại hình ảnh trên một dịch vụ như Pinterest và nhận dạng khuôn mặt trên Facebook.

Đó là những ví dụ về Narrow AI trong thực tế. Những công nghệ này thể hiện một số khía cạnh của trí thông minh con người. Nhưng bằng cách nào? Trí tuệ đó ​​đến từ đâu? Điều đó đưa chúng ta tới vòng tròn tiếp theo, Machine learning.

Machine learning – Cách tiếp cận để chinh phục  trí tuệ nhân tạo

phân biệt machine learning và deep learning

Machine learning theo định nghĩa cơ bản là ứng dụng các thuật toán để phân tích cú pháp dữ liệu, học hỏi từ nó, và sau đó thực hiện một quyết định hoặc dự đoán về các vấn đề có liên quan. Vì vậy, thay vì code phần mềm bằng cách thức thủ công với một bộ hướng dẫn cụ thể để hoàn thành một nhiệm vụ cụ thể, máy được “đào tạo” bằng cách sử dụng một lượng lớn dữ liệu và các thuật toán cho phép nó học cách thực hiện các tác vụ.

Machine learning bắt nguồn từ các định nghĩa về AI ban đầu, và các phương pháp tiếp cận thuật toán qua nhiều năm bao gồm:logic programming, clustering, reinforcement learning, and Bayesian networks. Như chúng ta đã biết, không ai đạt được mục tiêu cuối cùng của General AI, và thậm chí cả Narrow AI hầu hết là ngoài tầm với những phương pháp tiếp cận Machine learning sơ khai.

Một trong những lĩnh vực ứng dụng tốt nhất cho Machine learning trong nhiều năm qua là computer vision, mặc dù nó vẫn đòi hỏi rất nhiều kỹ năng code thủ công để có thể hoàn thành công việc. Mọi người vẫn sẽ viết các lớp phân loại bằng tay như các bộ lọc để chương trình có thể xác định nơi mà một đối tượng bắt đầu và kết thúc. Phát hiện hình dạng để xác định nếu nó có tám mặt. Một phân loại để nhận dạng các chữ cái “S-T-O-P”. Từ tất cả những ứng dụng phân loại, họ sẽ phát triển các thuật toán để làm cho hình ảnh và “học” khả năng nhận diện dấu hiệu liệu nó có phải là kí hiệu stop hay không? .

Tốt, nhưng không hoàn toàn hoàn hảo. Đặc biệt vào một ngày sương mù khi tầm nhìn không thấy rõ, hoặc cây che khuất một phần. Đó là lý do khiến computer vision và image detection không gây được thiện cảm, vì nó quá nhạy cảm và dễ phát sinh lỗi.

Thời gian, và ứng dụng đúng thuật toán đã tạo ra sự phân biệt machine learning và deep learning.

Tham khảo thêm các vị trí tuyển dụng Machine Learning cho bạn 3000 USD

Deep learning – Kỹ thuật để hiện thực hóa Machine learning

phân biệt machine learning và deep learning

 Lấy hình ảnh mèo ra khỏi video trên YouTube là một trong những đột phá đầu tiên của deep learning

Một phương pháp tiếp cận thuật toán khác từ cộng đồng machine-learning, Artificial Neural Networks, được nhắc đến nhiều thập kỷ qua. Neural Networks được lấy cảm hứng từ sự hiểu biết về sinh học của bộ não loài người – sự liên kết giữa các nơ-ron. Tuy nhiên, không giống như một bộ não sinh học nơi mà bất kỳ nơ-ron nào cũng có thể liên kết với các nơ-ron khác trong một khoảng cách vật lý nhất định, các mạng thần kinh nhân tạo này có các lớp rời rạc, các kết nối, và các hướng truyền dữ liệu.

Chẳng hạn, bạn có thể lấy một hình ảnh, cắt nó thành một nhóm được đặt vào lớp đầu tiên của mạng thần kinh nhân tạo. Trong lớp đầu tiên các nơ-ron cá nhân truyền dữ liệu đến lớp thứ hai. Lớp thứ hai của nơ-ron làm nhiệm vụ của nó, và như vậy, cho đến khi lớp cuối cùng và cho ra sản phẩm cuối cùng.

Mỗi nơ-ron đảm nhiệm một chức năng – làm thế nào để biết chính xác liệu rằng nó có liên quan đến nhiệm vụ đang được thực hiện. Vì vậy, suy nghĩ về điểm dừng là một dấu hiệu. Các thuộc tính của một hình ảnh dấu hiệu “dừng” được cắt nhỏ và được “kiểm tra” bởi các nơ-ron – dạng hình trụ, màu đỏ của các động cơ cháy, các chữ cái đặc trưng, ​​kích thước biển báo giao thông, và sự chuyển động hoặc sự thiếu hụt của nó. Nhiệm vụ của mạng thần kinh là để kết luận liệu đây có phải là dấu hiệu dừng hay không. Nó đi kèm với một “vector xác suất”. Trong ví dụ của chúng ta, hệ thống có thể xác định chắc chắn đến 86% một dấu hiệu dừng, 7% rằng đó là một dấu hiệu giới hạn tốc độ, và 5% còn lại là một con diều bị mắc kẹt trong cây,( hoặc cái gì đó tương tự)  vv … và kiến ​​trúc mạng sau đó sẽ thông báo đến mạng nơron cho dù đó là đúng hay sai.

Thậm chí ví dụ này cũng là một sự tiến bộ, bởi vì mạng lưới thần kinh đã có thể làm được tất cả nhưng bị xa lánh bởi cộng đồng nghiên cứu về AI. Nó đã có mặt từ những ngày đầu tiên của AI, và tạo ra rất ít sản phẩm “trí tuệ”. Vấn đề là ngay cả những mạng nơ-ron cơ bản nhất cũng có tính toán rất cao, nó không phải là cách tiếp cận thực tiễn. Tuy nhiên, một nhóm nghiên cứu nhỏ do Geoffrey Hinton thuộc trường đại học Toronto đứng đầu, cuối cùng đã parallelizing các thuật toán cho siêu máy tính để chạy và chứng minh khái niệm, nhưng nó không chính xác cho đến khi GPU được triển khai.

  Top những thuật toán machine learning mà bất cứ Data Scientist nào cũng cần phải biết (Phần 1)

Nếu chúng ta quay trở lại ví dụ “ký hiệu dừng”, rất có thể là khi mạng đang được điều chỉnh hoặc được “đào tạo” thì sẽ có câu trả lời sai – rất nhiều. Những gì nó cần là luyện tập. Nó cần phải nhìn thấy hàng trăm ngàn, thậm chí hàng triệu hình ảnh, cho đến khi trọng lượng của đầu vào nơ-ron được điều chỉnh chính xác đến mức nó có được câu trả lời ngay trong thực tế mọi lúc – sương mù hoặc không có sương mù, nắng hoặc mưa. Vào thời điểm đó mạng thần kinh đã tự dạy cho nó một dấu hiệu dừng như thế nào; Hoặc khuôn mặt của mẹ bạn trong trường hợp của Facebook. Hay một con mèo, đó là điều mà Andrew Ng đã làm trong năm 2012 tại Google.

Sự đột phá của Ng là đưa các mạng thần kinh này, và làm cho chúng trở nên to lớn, tăng số layer và các nơ-ron, sau đó chạy một khối lượng lớn dữ liệu thông qua hệ thống để huấn luyện nó. Trong trường hợp của Ng, đó là hình ảnh từ 10 triệu video trên YouTube. Ng đặt “deep” vào deep learning, mô tả tất cả các lớp trong các mạng nơron này.

Ngày nay, khả năng nhận dạng hình ảnh của máy móc được luyện tập thông qua deep learning trong một số tình huống tốt hơn so với con người. AlphaGo của Google đã được huấn luyện chơi cờ vay – nó điều chỉnh mạng lưới thần kinh của mình bằng cách tự mình chống lại chính mình.

Nhờ Deep learning, AI có một tương lai tươi sáng

Deep Learning đã cho phép ứng dụng nhiếu vấn đề thực tế của máy học và bằng cách mở rộng lĩnh vực tổng thể của AI. Deep learning phá vỡ các cách thức con người làm việc bằng cách làm cho tất cả các loại máy móc trợ giúp có thể thực hiện được, gần hoặc giống hệt con người.

Ô tô không người lài, chăm sóc sức khoẻ tốt hơn, thậm chí cả đề xuất về bộ phim tốt hơn, tất cả đều hiện thực trong thời đại ngày nay. AI là hiện tại và tương lai. Với sự trợ giúp của Deep Learning, AI có thể hiện thức hóa ước mơ khoa học giả tưởng mà chúng ta đã tưởng tượng từ rất lâu. Bạn có một C-3PO, tôi sẽ lấy nó. Bạn có thể giữ Terminator của bạn.

Có thể bạn muốn xem thêm:

Xem thêm tuyển dụng it mới nhất tại TopDev

                 TopDev via Blogs Nvidia

Mô hình 3 lớp (three-layer) có gì hay?

“Biết địch biết ta, trăm trận trăm thắng “. Vậy muốn biết có gì hay thì phải hiểu rõ về nó. Được rồi, nhân dịp đang học nhập môn công nghệ phần mềm ở trường, kiến thức còn nóng hổi nên mình sẽ phân tích về mô hình 3 lớp (3-layer).

Trước tiên, cần phân biệt 2 khái niệm tầng (tier) và lớp (layer)

3 lớp (three-layer) là gì?

3-tiers là một kiến trúc kiểu client/server mà trong đó giao diện người dùng (UI-user interface), các quy tắc xử lý (BR-business rule hay BL-business logic), và việc lưu trữ dữ liệu được phát triển như những module độc lập, và hầu hết là được duy trì trên các nền tảng độc lập, và mô hình 3 tầng (3-tiers) được coi là một kiến trúc phần mềm và là một mẫu thiết kế.” (dịch lại từ wikipedia tiếng Anh).

Đây là kiến trúc triển khai ứng dụng ở mức vật lý. Kiến trúc gồm 3 module chính và riêng biệt:

  • Tầng Presentation: hiển thị các thành phần giao diện để tương tác với người dùng như tiếp nhận thông tin, thông báo lỗi, …
  • Tầng Business Logic: thực hiện các hành động nghiệp vụ của phần mềm như tính toán, đánh giá tính hợp lệ của thông tin, … Tầng này còn di chuyển, xử lí thông tin giữa 2 tầng trên dưới.
  • Tầng Data: nơi lưu trữ và trích xuất dữ liệu từ các hệ quản trị CSDL hay các file trong hệ thống. Cho phép tầng Business logic thực hiện các truy vấn dữ liệu .

Mọi người vẫn hay nhầm lẫn giữa tier và layer vì cấu trúc phân chia giống nhau (presentation, bussiness , data). Tuy nhiên, thực tế chúng hoàn toàn khác nhau. Nếu 3 tiers có tính vật lí thì 3 layer có tính logic. Nghĩa là ta phân chia ứng dụng thành các phần (các lớp) theo chức năng hoặc vai trò một cách logic. Các layer khác nhau được thực thi trong 1 phân vùng bộ nhớ của process. Vì thế nên một tier có thể có nhiều layer.

TÌM VIỆC LÀM NGÀNH IT LƯƠNG CAO

Giới thiệu mô hình 3-layer ( 3 lớp)

Mô hình 3-layer gồm có 3 phần chính:

Presentation Layer (GUI) : Lớp này có nhiệm vụ chính giao tiếp với người dùng. Nó gồm các thành phần giao diện ( win form, web form,…) và thực hiện các công việc như nhập liệu, hiển thị dữ liêu, kiểm tra tính đúng đắn dữ liệu trước khi gọi lớp Business Logic Layer (BLL).

Business Logic Layer (BLL) : Layer này phân ra 2 thành nhiệm vụ :

  • Đây là nơi đáp ứng các yêu cầu thao tác dữ liệu của GUI layer, xử lý chính nguồn dữ liệu từ Presentation Layer trước khi truyền xuống Data Access Layer và lưu xuống hệ quản trị CSDL.
  • Đây còn là nơi kiểm tra các ràng buộc, tính toàn vẹn và hợp lệ dữ liệu, thực hiện tính toán và xử lý các yêu cầu nghiệp vụ, trước khi trả kết quả về Presentation Layer.

Data Access Layer (DAL) : Lớp này có chức năng giao tiếp với hệ quản trị CSDL như thực hiện các công việc liên quan đến lưu trữ và truy vấn dữ liệu ( tìm kiếm, thêm, xóa, sửa,…).

Ưu điểm

  • Việc phân chia thành từng lớp giúp cho code được tường minh hơn. Nhờ vào việc chia ra từng lớp đảm nhận các chức năng khác nhau và riêng biệt như giao diện, xử lý, truy vấn thay vì để tất cả lại một chỗ. Nhằm giảm sự kết dính.
  • Dễ bảo trì khi được phân chia, thì một thành phần của hệ thống sẽ dễ thay đổi. Việc thay đổi này có thể được cô lập trong 1 lớp, hoặc ảnh hưởng đến lớp gần nhất mà không ảnh hưởng đến cả chương trình.
  • Dễ phát triển, tái sử dụng: khi chúng ta muốn thêm một chức năng nào đó thì việc lập trình theo một mô hình sẽ dễ dàng hơn vì chúng ta đã có chuẩn để tuân theo. Và việc sử dụng lại  khi có sự thay đổi giữa hai môi trường ( Winform sang Webfrom ) thì chỉ việc thay đổi lại lớp GUI.
  • Dễ bàn giao. Nếu mọi người đều theo một quy chuẩn đã được định sẵn, thì công việc bàn giao, tương tác với nhau sẽ dễ dàng hơn và tiết kiệm được nhiều thời gian.
  • Dễ phân phối khối lượng công việc. Mỗi một nhóm, một bộ phận sẽ nhận một nhiệm vụ trong mô hình 3 lớp. Việc phân chia rõ ràng như thế sẽ giúp các lập trình viên kiểm soát được khối lượng công việc của mình.

Phân tích chi tiết từng layer trong mô hình 3 lớp. 

1. Presentation Layer (GUI):

Có hai thành phần chính sau đây với những tác vụ cụ thể :

  • UI Components : gồm các thành phần tạo nên giao diện của ứng dụng (GUI). Chúng chịu trách nhiệm thu nhận và hiển thị dữ liệu cho người dùng… Ví dụ : textbox, button, combobox, …
  • UI Process Components : là thành phần chịu trách nhiệm quản lý các quá trình chuyển đổi giữa các UI… Ví dụ : Sắp xếp quá trình kiểm tra thông tin khách hàng:

1.Hiển thị màn hình tra cứu ID

2.Hiển thị màn hình thông tin chi tiết khách hàng tương ứng

3.Hiển thị màn hình liên lạc với khách hàng.

2. Bussiness Layer (BLL) :

Lớp này gồm 4 thành phần:

  • Service Interface : là thành phần giao diện lập trình mà lớp này cung cấp cho lớp Presentation sử dụng.
  • Bussiness Workflows : chịu trách nhiệm xác định và điều phối các quy trình nghiệp vụ gồm nhiều bước và kéo dài. Những quy trình này phải được sắp xếp và thực hiện theo một thứ tự chính xác.
  • Ví dụ : Thực hiện mua một đơn hàng trên tiki qua nhiều bước : kiểm tra gói hàng còn không?, tính tổng chi phí, cho phép giao dịch và sắp xếp việc giao hàng.
  • Bussiness Components : chịu trách nhiệm kiểm tra các quy tắc nghiệp vụ, ràng buộc logic và thực hiện các công việc . Các thành phần này cũng thực hiện các dịch vụ mà Service Interface cung cấp và Business Workflows sẽ sử dụng nó.
  • Ví dụ : Tiếp tục ví dụ ở trên. Bạn sẽ cần một Bussiness Component để kiểm tra gói hàng có khả dụng không ? hay một component để tính tổng chi phí,…
  • Bussiness Entities : thường được sử dụng như Data Transfer Objects ( DTO ) . Bạn có thể sử dụng để truyền dữ liệu giữa các lớp (Presentation và Data Layer). Chúng thường là cấu trúc dữ liệu ( DataSets, XML,… ) hay các lớp đối tượng đã được tùy chỉnh.
  • Ví dụ : tạo 1 class Student lưu trữ các dữ liệu về tên, ngày sinh, ID, lớp.

 3. Data Layer (DAL) :

  • Data Access Logic Components : chịu trách nhiệm chính lưu trữ và truy xuất dữ liệu từ các nguồn dữ liệu (Data Sources) như XML, file system,… Hơn nữa còn tạo thuận lợi cho việc dễ cấu hình và bảo trì.
  •  Service Agents: giúp bạn gọi và tương tác với các dịch vụ từ bên ngoài một cách dễ dàng và đơn giản.

Cấu trúc mô hình 3 lớp

Để hiểu rõ hơn về cấu trúc và cách xây dựng của mô hình 3 lớp, chúng ta cùng tham khảo một ví dụ về mô hình quản lí công nhân gồm các lớp BUS, DAO, GUI. (Các đoạn code sẽ bị lược bỏ bớt )

Đầu tiên là GUI gồm các button insert, update, reset ,delete ,exit .Người dùng sẽ giao tiếp với màn hình giao diện này

Lớp DTO, đây không phải là layer, đây chỉ là 1 gói dữ liệu đươc trao đổi giữa các lớp. Gói dữ liệu này được xây dựng dưới dạng lớp đối tượng. Mỗi một công nhân sẽ mang những thuộc tính sau:

namespace DTO
{
    public class EmployeeDTO
    {
        #region Atrributes
        private String _employeeID;
        private String _name;
        private String _email;
        private float _salary;
        private int _employeeStyle;
        #endregion
        //.....

Các nghiệp vụ xử lý chính sẽ được đặt ở lớp BUS (hay là BLL)  gồm các nghiệp vụ insert, update, delete, retrieve

namespace BUS
{
    public class EmployeeBUS
    {
        #region 1. Inserting
        public static bool InsertEmployee(EmployeeDTO emp)
        {
            if (EmployeeDAO.CheckEmployeeByID(emp.EmployeeID)==true
                &amp;&amp;EmployeeStyleDAO.CheckEmployeeStyleByID(emp.EmployeeStyle)==false)
            {
                return false;               
            }
            return EmployeeDAO.InsertEmployee(emp);
        }
        #endregionhttps://techtalk.vn/wp-admin/post-new.php#
        //2. Updating
        //3. Deleting
        //4. Retrieving
    }
}

Và cuối cùng là lớp DAO ( hay là DAL ). Truy  vấn đến cơ sở dữ liệu

{
    public class EmployeeDAO
    {
        #region 1. Inserting
        public static bool InsertEmployee(EmployeeDTO emp)
        {
            bool result=false;
            try
            {
                // Create List Sql Parameter
                List sqlParams = new List();
                sqlParams.Add(new SqlParameter("@EmployeeID", emp.EmployeeID));
                sqlParams.Add(new SqlParameter("@Name", emp.Name));
                sqlParams.Add(new SqlParameter("@Email", emp.Email));
                sqlParams.Add(new SqlParameter("@Salary", emp.Salary));
                sqlParams.Add(new SqlParameter("@EmployeeStyle", emp.EmployeeStyle));
                // Call Store Procedure
                int n = SqlDataAccessHelper.ExecuteNoneQuery("spInsertEmployee", sqlParams);
                if (n == 1)
                    result = true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }
#endregion
        // 2. Updating
        // 3. Deleting
        // 4. Retrieving

Vì đây là ví dụ mô phỏng nên tôi chỉ chú trọng đến cách cấu trúc một chương trình sử dụng mô hình 3 lớp. Cảm ơn đã đọc hết.

Đừng bỏ lỡ những bài viết hay về lập trình hướng đối tượng:

Xem thêm việc làm Web Developer mới nhất tại TopDev

  List các thuật ngữ căn bản .NET- Bách khoa toàn thư

Xây dựng ứng dụng realtime messaging bằng Firebase như TikTok, Bigo…

Xây dựng ứng dụng realtime messaging bằng Firebase

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

Hiện nay các ứng dụng live stream mọc lên như nấm, một trong số đó có thể được kể đến như Bigo, Facebook live, Tiktok, Youtube …

Trong khi live stream thì người dùng có thể thả tim, like, comment … Và tất cả những chức năng đó hoàn toàn là realtime.

Vậy làm thế nào có thể làm được tính năng realtime như thế? Và có thể xử lí được hàng triệu, hàng tỉ request/s như vậy chắc cũng nhiều người quan tâm, và bản thân mình cũng thế. Cũng muốn vọc vạch xem công nghệ đằng sau những ứng dụng đó như thế nào.

Trong lúc tìm hiểu thì đọc thấy 1 bài rất hay mà kĩ sư Mercari đã chia sẻ. Và bên họ sử dụng Firebase Realtime Database để giải quyết bài toán này.

Cùng nhau tìm hiểu xem cụ thể sẽ làm như thế nào để có thể xây dựng được ứng dụng realtime messaging xử lí được hàng tỉ request/s như vậy.

Phạm vi bài toán

Xây dựng ứng dụng realtime messaging bằng Firebase xử lí 100k request/s

Hình ảnh bên trên mình chụp được thông qua ứng dụng Bigo (thi thoảng ngắm gái :D).

Ai dùng Bigo hay Facebook live rồi cũng đều biết ngoài tính năng live stream ra thì còn 1 vài tính năng khác nữa như gửi comment, like, gửi tim, tặng coin … Và tất cả những thứ này đều realtime.

Nên hôm nay mình chỉ tập trung vào những tính năng realtime như comment, like, gửi tim …

Firebase Realtime Database là gì?

  • Là sản phẩm của Google (chính xác là được Google mua lại)
  • Là cơ sở dữ liệu NoSQL được lưu trữ và quản lí trên đám mây.
  • Dữ liệu được lưu đưới dạng JSON.
  • Client có thể subscribe dữ liệu 1 cách realtime.
  • Tại thời điểm hiện tại (2019/07/06) thì firebase realtime database xử lí được 1 triệu request đồng thời và 10k write/s. Tương lai số lượng này có thể tăng lên. Số liệu tham khảo ở đây.

Ngoài tính năng của 1 database ra thì nó còn có 1 số tính năng khác nữa như:

  • Tính năng Authentication thông qua Facebook, Google, Twitter …
  • Có thể cài đặt rule để phân quyền xem ai được read, write đến resource của database. Ví dụ như ai login mới có quyền read, write chẳng hạn.
  • Bởi vì Firebase được dùng ở phía client (web, mobile) nên việc decode để lấy ra key của firebase là điều hoàn toàn dễ dàng. Do đó nếu không cài đặt rule 1 cách cẩn thận thì có thể sẽ bị bên thứ 3 read, write tài nguyên 1 cách dễ dàng.

Kiến trúc hệ thống

Xây dựng ứng dụng realtime messaging bằng Firebase xử lí 100k request/s

Kiến trúc khá là simple phải không nào. Bây giờ mình sẽ đi giải thích từng bộ phận trong kiến trúc này.

Đầu tiên khi người dùng thực hiện comment, like thì khi đó sẽ gửi request đến API Server để xử lí. Tại sao ở bước này không gửi trực tiếp đến Firebase mà phải thông qua API Server để làm gì? Bởi vì ngoài mục đích insert data đến firebase database còn có 1 số nhiệm vụ khá quan trọng khác nữa như authentication người dùng, detect tấn công xâm nhập … Nên việc xử lí những logic phức tạp đó bắt buộc phải thông qua API Server.

Sau khi API Server nhận được request từ phía người dùng. Khi đó nó sẽ thực hiện việc chuyển data đó vào queue để xử lí thông qua worker.

Worker sẽ lấy dữ liệu từ queue ra và thực hiện insert data đến Firebase thông qua REST API của Firebase.

Tại sao từ API Server không gửi data trực tiếp đến Firebase?

Chúng ta hãy luôn luôn nhớ 1 điều là ngoài mình ra không bao giờ được tin tưởng bất kì thằng nào cả (Don’t trust each other).

Nếu API Server gửi request trực tiếp đến Firebase thì có vấn đề gì xảy ra ở đây? Chẳng may lúc này firebase database bị down. Khi đó API Server sẽ không thể gửi request được nữa và có thể gây ra lỗi. Khi đó phía client cũng bị lỗi theo. Và làm cho trải nghiệm người dùng bị gián đoạn.

Do đó mới thông qua queue để xử lí. Nếu mà Firebase Database có bị down đi chăng nữa thì job đó sẽ bị failed và sẽ được retries lại ngay sau đó. Hơn nữa nhờ cơ chế work-queue này giúp chúng ta scalable khá tốt ở chỗ này.

Về Queue thì hiện nay có rất nhiều như KafkaQ4M … Về cá nhân mình thích nhất thằng Kafka vì nó luôn luôn đảm bảo đúng thứ tự xử lí. Và hơn nữa nó lại phân tán nữa nên tính mở rộng của nó khá là cao.

Và cuối cùng phía Client chỉ cần Subscribe event từ Firebase Realtime Database là có thể nhận dữ liệu 1 cách realtime rồi.

Ở bước này chúng ta sẽ không xử lí gì cả và chỉ cho hiển thị dữ liệu thôi. Như thế tốc độ sẽ khá là nhanh.

Về tính mở rộng của Firebase Realtime Database

Đầu tiên mình muốn nhấn mạnh 1 điều là Firebase Realtime Database không thể scale up với scale out được nhé.

Do đó trước khi đưa nó vào hệ thống thì chúng ta cần test tải kĩ càng trước xem cần bao nhiêu con database thì hợp lí, dựa vào tuỳ tình hình mà sẽ tiến hành sharding để đáp ứng được số lượng request đề ra.

Như phần trên mình có nói, firebase realtime database hiện tại chỉ cho phép 1 triệu request đồng thời và 10k write/s. Do đó để không vượt quá ngưỡng này thì sharding là điều hoàn toàn cần thiết.

Xây dựng ứng dụng realtime messaging bằng Firebase xử lí 100k request/s

Chúng ta sẽ sharding database theo liveID. Như trong ví dụ trên thì với liveid=1 và 4 sẽ cho trong db1, liveid = 2 và 5 sẽ cho trong db2, và live_id=3 và 6 sẽ cho trong db3

Nếu chia như thế thì chúng ta có thể xử lí được 3 triệu request đồng thời và 30k write/s.

Ở đây có 1 điểm chắc nhiều người cũng đang thắc mắc. Ví dụ live_id=1 (của 1 em gái xinh xắn nào đó) có tới hàng triệu anh vào xem live và comment. Nếu số lượng request đó vượt quá 1 triệu thì sẽ bị block lại và không gửi đc nữa. Ví dụ như ai đó thả tim liên tục chăng hạn …

Vậy ở chỗ này nên làm thế nào để có thể hạn chế được điều đó?

Có 1 solution khá đơn giản. Ví dụ như chức năng like chẳng hạn. Khi ấn like chúng ta sẽ không send ngay đến firebase mà sẽ đợi khoảng 10s sau đó mới send chẳng hạn. (Cứ miễn làm sao mà không làm giảm trải nghiệm của người dùng là được).

Để thực hiện được logic này chúng ta có thể sử dụng Redis hoặc memcached để lưu lại live_id với timestamp tương ứng. Sau khoảng 10s từ lúc insert vào redis thì sẽ không làm gì cả, sau 10s thì sẽ insert data đến firebase.

<code><?php
$memcachd = new \Sample\MemcachedClient();
$firebase_client = new \Sample\FirebaseClient();
$like_counter = new \Sample\LikeCounter();
$live_id = \HttpParameter::get('live_id');

$like_count = $like_counter->increment($live_id);

if ($memcached->get('key-prefix-like-' . $live_id)) {
    // Skip
} else {
    $firebase_client->updateLikeCount($like_count);
    $memcached->add('key-prefix-like-' . $live_id, true, 10); // 10s
}</code>

Ngoài ra mình nhấn mạnh 1 điều là do Firebase được dùng phía client (như web, mobile) nên việc lộ key của firebase là điều không thể tránh khỏi. Do đó việc cài đặt rule để phân quyền người dùng access đến resource là điều vô cùng cần thiết và ở bài này mình sẽ không đi sâu vào nữa. Mọi người có thể tìm hiểu thêm về Firebase Realtime Database Rule ở đây nhé.

Xây dựng ứng dụng realtime messaging bằng Firebase xử lí 100k request/s

Như hình ảnh bên trên là 1 ví dụ về lộ key firebase ở phía javascript.

Kết luận

Theo như các anh Mercari chia sẻ thì sau khi release tính năng live stream đó thì đến bây giờ cũng được 2 năm rồi mà chưa lần nào Firebase bị down cả.

Firebase quả thực rất mạnh. Nếu ai muốn dev thật nhanh hoặc muốn làm bản prototype thì có lẽ Firebase là 1 sự lựa chọn đúng đắn.

Với loại truyền thống thì chúng ta sẽ cần phải có DB, và chuẩn bị API phía backend để thao tác với dữ liệu trong DB. Nhưng Firebase thì khác, nó cung cấp cho ta DB và API để thao tác đến DB rồi. Do đó không cần phải dev API làm gì cho mệt. Cứ dùng Firebase SDK là xong.

Ngoài ra mình nhấn mạnh 1 điều là do Firebase được dùng phía client (như web, mobile) nên việc lộ key của firebase là điều không thể tránh khỏi. Do đó việc cài đặt rule để phân quyền người dùng access đến resource là điều vô cùng cần thiết và ở bài này mình sẽ không đi sâu vào nữa. Mọi người có thể tìm hiểu thêm về Firebase Realtime Database Rule ở đây nhé.

Hiện tại sắp tới công ty mình cũng đang chuẩn bị làm 1 service mới và sếp yêu cầu 2 tháng phải xong. Team mình cũng quyết định chọn Firebase cho giải pháp lần này.

Xem thêm việc làm Software Developers tại TopDev

Bài viết gốc được đăng tải tại Nghệ thuật coding

  Sharding là gì? - Cách Instagram tạo ID trong database của họ bằng Sharding
  Các kĩ sư Grab thiết kế hệ thống "đàn hồi" sử dụng kĩ thuật Circuit Breaker như thế nào?

Cách mà một dòng code đã thay đổi cuộc đời tôi!

chuyện nghề lập trình

Năm 2012 là giai đoạn mà sự nghiệp của tôi không đi đến đâu cả. Một ngày đẹp trời, đồng nghiệp của tôi – Otto Lombardo, đã cho tôi xem một dòng code mà đã thay đổi cuộc đời tôi mãi mãi, và đây là câu chuyện nghề lập trình của tôi.

Tôi làm quen với máy tính nhờ vào người anh họ của mình qua con game Street Road vào năm 1992. Như là yêu chỉ bằng cái nhìn đầu tiên, tôi còn nhớ đã xin mẹ tôi đến nhà anh họ chơi hết lần này đến lần khác.

Không lâu sau, mẹ tôi đăng ký cho tôi học một khoá về máy tính, DOS, Windows 3.1, Lotus…, DBase! Tôi háo hức như một đứa trẻ 10 tuổi! Tôi đi học về máy tính sớm để tôi có thể có nhiều thời gian “vọc” máy tính hơn. Tôi còn nhớ chuỗi ngày không bao giờ kết thúc chơi con game Carmen San Diego khi ba mẹ có đủ khả năng mua cho tôi một chiếc.

Một vài năm sau đó, tôi chuyển từ Argentina đến US khi tôi 15 tuổi, và phải mãi một năm sau đó bố mẹ tôi mới cho tôi chiếc máy tính đầu tiên, một chiếc PC Sony màu đen, thật tuyệt vời! Năm 1999, khi Internet bắt đầu xuất hiện, tôi đã dành hàng đêm để làm web bằng Notepad và upload lên hosting AngelFire. Tôi còn được nhận một chiếc đĩa vàng (24k) do Bill Gates và Steve Ballmer ký tặng vì đã làm testing MSN. Đó là những tháng ngày hacking rất vui và tuyệt vời.

chuyện nghề lập trình

Vài năm sau, tôi quyết định đi sửa cái máy tính của mình, và tôi học được một ít thủ thuật và bất ngờ tôi có một buổi phỏng vấn với một công ty máy tính ở New York. Wow! Khi bước vào đó và thấy những cái thùng chứa đầy linh kiện máy tính, tôi biết mình đã đến thiên đường. Tôi trở thành một network engineer và phải nói là tôi có thể sửa mọi lỗi về máy tính và network, và mặc dù tôi giỏi việc đó nhưng tôi lại không thật sự hạnh phúc. Tôi luôn luôn thích những công việc liên quan đến sáng tạo, và giờ tôi nhận ra công việc 8 năm qua của tôi chỉ là về sửa chữa, không hề có sự sáng tạo.

Và đó là khi mọi thứ bắt đầu. Một đồng nghiệp của tôi cho tôi xem một dòng code ở Delphi, nó có thể tạo ra một tin nhắn “Hello Ricardo”. Thật kỳ diệu! Nó dành cho tôi, ngay lập tức tôi biết rằng mình muốn trở thành một lập trình viên. Tôi trở về nhà, download delphi và chỉ trong 1 tuần tôi đã tạo được một giao diện phần mềm tương tự mà chúng tôi có khi làm việc và bắt đầu chạy. Thậm chí tôi còn lừa đồng nghiệp và người lập trình cái phần mềm đó nghĩ rằng là tôi đã hack vào phần mềm và thay đổi menu. Thật sự rất vui! Nhưng giờ thì sao? Tôi có nên tiếp tục học Delphi?

Sau đó nếu tôi muốn bán thứ gì mà tôi lập trình được, tôi có thể ghi nó trong …? Thật may mắn khi một người bạn của tôi gợi ý cho tôi học code iOS. Tôi có thể build cái gì đó và đăng lên App Store.

Tôi mất gần một năm trời để học căn bản, nhớ là tôi không hề có background về lập trình. Tôi dành hàng giờ đồng hồ để đọc, xem video, viết stuff. Bạn của tôi và tôi bắt đầu sáng thứ 7 vào lúc 9h00 và làm việc không ngừng nghỉ đến 2h30 sáng Chủ Nhật (hoặc chỉ khi vợ tôi nói dừng lại!). Tôi build được một prototype cho một ứng dụng, và nó giúp tôi tìm được công việc đầu tiên cách nhà 3 tiếng di chuyển.

Trong khoảng 6 tháng đó tôi chỉ dành từ 5 đến 6 tiếng để đi lại. Tôi sống ở Queens, NY và công việc đầu tiên làm lập trình iOS thì ở Summit, NJ. Rất xứng đáng! Tôi dành một nửa thời gian để đọc về lập trình và nửa còn lại để cố gắng ngủ một chút. Tôi phải thừa nhận là nó rất mệt nhưng công việc đó lại giúp tôi tìm được một việc khác gần nhà tôi hơn, chỉ mất khoảng 40 phút đi từ Manhattan, NY. Trong khoảng thời gian đó tôi đã chiến thắng một cuộc thi về lập trình với giải thưởng không thể đòi hỏi thêm: $20,000 (Link)

Tôi nhận được chứng chỉ từ Đại học New York và sau đó được mời về làm diễn giả cũng như được thuê làm một số công việc về lập trình. Tôi đến các hội thảo và được nói chuyện với một vài người. Đây chính là cuộc sống mà tôi mơ ước, và tôi đang sống trong giấc mơ Mỹ của mình!

chuyện nghề lập trình

Hiện tôi đang làm việc tại MediPortal, chúng tôi đang cố gắng cải thiện ngành chăm sóc sức khoẻ. Tôi phụ trách mọi giải pháp mobile. Giờ đây không kể bao nhiêu giờ, tôi làm việc cả ngày lẫn đêm và cả vào cuối tuần. Khi bạn thực sự yêu thích công việc mà bạn đang làm, bạn sẽ không còn nhìn vào đồng hồ và nghĩ về việc về nhà nữa. Không dễ dàng để đến được thời điểm hiện tại nhưng mọi thứ đều xứng đáng.

Và bạn thấy đó, bí quyết chính là việc bạn đã sẵn sàng chưa? Mọi người đều có thể làm được! Tôi luôn nghĩ về câu mà Steve Jobs đã nói: “Cuộc sống sẽ mở rộng hơn chỉ khi bạn khám phá ra một sự thật đơn giản là: Mọi thứ xung quanh mà bạn gọi là cuộc sống được tạo nên bởi những người không hề thông minh hơn bạn và bạn có thể thay đổi điều đó, bạn có thể tác động đến nó, bạn có thể tự tạo nên những thứ mà người khác có thể dùng được. Và chỉ khi bạn học được điều đó, bạn sẽ không còn giống họ nữa.”

Nếu có điều gì tôi muốn đạt được, thì đó là tạo động lực cho mọi người như cách mà Otto đã tạo động lực cho tôi. Ra ngoài đó và bắt đầu sống với ước mơ của bạn đi. Không gì là không thể và chỉ có bạn là người cản trở bạn mà thôi. Hãy điên rồ và táo bạo lên. Và biến nó thành hiện thực!

Xin cảm ơn các bạn đã theo dõi bài viết!

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

Xem thêm việc làm Software Developers hot nhất tại TopDev

  5G & IoT hứa hẹn điều gì trong tương lai?
  Học lập trình thế nào để không thất nghiệp?

Vượt qua 7 sai lầm này để học JavaScript dễ thở hơn

7-sai-lam-trong-hoc-javascript

Giới thiệu

Đối với một số người, học JavaScript có vẻ không hứng thú lắm, đặc biệt là những ai thiếu kiên nhẫn. Thỉnh thoảng, bạn sẽ lại tự hỏi bản thân liệu mình đã chọn đúng con đường cho tương lai chưa…

JavaScript chưa bao giờ dễ dàng như đi dạo hồ con rùa cả!

Tin tốt là bạn có thể cải thiện quá trình học của mình bằng những lựa chọn và cách tiếp cận khác. Còn đợi gì nữa mà không tự thay đổi chính bản thân bạn?

Bài viết này sẽ chỉ ra 7 lỗi sai mà các lập trình viên học JavaScript thường mắc phải. Và cũng chính những lỗi này mà họ bị thụt lại phía sau so với người khác khi học JavaScript

Cùng tìm hiểu đó là 7 lỗi sai nào nhé!

Tuyển dụng Javascript lương cao cho SV mới ra trường

7 sai lầm trong học JavaScript lập trình viên cần tránh

Học cho qua với các khái niệm

học JavaScript

Khi bạn bắt đầu hiểu các khái niệm cơ bản như closures là gì hay các hàm bậc cao, đừng bao giờ chuyển sang các bài học tiếp theo mà bỏ qua các bài tập thực hành ở đầu.

Nhưng đã số với mọi người, chuyển sang học cái tiếp theo có vẻ hấp dẫn hơn nhiều. Tuy nhiên, nếu bạn dành thời gian luyện code sau khi học xong một kiến thức, chỉ cần 5 phút thôi, cũng đủ giúp bạn dễ thở hơn rất nhiều với các project trong tương lai. Luôn luyện code sau khi học một khái niệm sẽ giúp bạn nhớ lâu hơn.

Nếu bạn chỉ học cho qua các khái niệm cơ bản, một lúc nào đó khi gặp phải nó trong lúc đang code, bạn sẽ tốn nhiều thời gian tìm kiếm lại nó trên mạng. Và sẽ thật tệ khi phải mất đi những giây phút quý báu, chỉ để tìm lại cái mình đã học rồi. Tới lúc đó bạn sẽ còn stress hơn rất nhiều.

Và thực tế là có nhiều lập trình viên rời project chỉ vì lý do không đủ thời gian.

Vậy nên, đừng bao giờ bỏ qua một kiến thức nào, dù chỉ là đơn giản nhất nhé!

Không tự viết code

học JavaScript

Vấn đề gần đây xảy ra với rất nhiều lập trình viên, đó là họ phụ thuộc quá nhiều vào code của người khác, như việc copy file của người khác trên các bài hướng dẫn, hay dùng thư viện Lodash trong mọi tình huống…

Xem thêm Lodash là gì.

Mặc dù không có gì sai khi dùng thư viện Lodash, nhưng bạn có thể bị thụt lại phía sau, nếu cứ lạm dụng nó trong thời gian dài. Lâu dần, bạn sẽ không nắm được khái niệm cơ bản về tools, frameworks, ngôn ngữ,… đều là những thứ giúp bạn tư duy lập trình.

Đó cũng là lý do vì sao nhiều cuộc phỏng vấn có thử thách code. Họ muốn xem cách bạn tư duy và cách bạn vận dụng kiến thức để giải quyết tình huống khi lập trình. Bạn có thể dùng các thư viện component để làm UI tốt hơn và xử lý Lodash với các thuật toán. Nhưng khi có vấn đề xảy ra, họ sẽ cần bạn vận dụng kiến thức, khái niệm để giải quyết. Họ không cần một người cài đặt npm vào thư viện khác để giải quyết vấn đề. Họ chỉ cần bạn.

Bạn sẽ không muốn kết thúc cuộc đời với những tình huống mà bạn đã từng dành thời gian ra học cực khổ. Vậy nên hãy luyện tập tự viết code của bạn thường xuyên nhé.

Làm quá một việc gì đó

học JavaScript

Với tất cả thông tin bạn kiếm được trên mạng, bạn cần bình tĩnh ngồi xuống, thu thập và chọn lọc các tài nguyên bạn cần trước khi học topic mới trong JavaScript.

Nhưng hiếm ai biết được đó là cách học tốt hơn rất nhiều.

Nhiều bạn thường nghĩ rằng nếu chúng ta chỉ cần có tất cả thông tin cần thiết, mọi thứ sẽ dễ dàng hơn. Nhưng đó chỉ là bạn nghĩ mà thôi.

Đừng cố gắng kiếm 80 cái tutorial, 6 cái ebook, một bộ 50 bookmark về nguồn, và cố gắng bắt đầu giải quyết đống đó một lúc như thể bạn là “Master of Lập trình web”.

Nếu bạn đang học JavaScript, thì hãy nhớ học đi đôi với hành. Cứ thế mà viết mọi thứ thôi. Dùng bất cứ thứ gì bạn học được trong quá khứ, tổng hợp chúng lại để làm những ví dụ nhỏ. Việc này sẽ giúp bạn nhớ lâu hơn thay vì đọc toàn bộ tài liệu mà bạn kiếm được trong cùng một lúc.

Choáng ngợp bởi quá nhiều thông tin

học JavaScript

Nếu bạn dành nhiều thời gian kiếm thông tin thay vì tự code, bạn sẽ rất nhanh quên và lại phải đi tìm kiếm tư liệu sau này.

Sẽ thật đáng sợ nếu bạn dành nhiều thời gian để học vì bạn nghĩ mình thích. Nhưng điều gì sẽ xảy ra khi bạn quên hết mọi thứ sau vài tháng? Bạn sẽ nhận ra được một vài lý do tại sao mình không thể dùng những kiến thức và tài liệu đã học lúc trước nữa.

Nếu bạn cần lời khuyên, hãy dành ít nhất 15 phút mỗi giờ bạn tìm kiếm thông tin để code.

So sánh bản thân với người khác

học JavaScript

Khi bạn so sánh bản thân với người khác, bạn sẽ không bao giờ biết cách họ làm, mà chỉ biết thứ họ đạt được.

Khi người ta nhìn vào những lập trình viên thành công, họ sẽ tự động cho rằng quá trình học của họ bắt đầu viết clean code.

Chỉ tập trung vào những gì bạn học ở hiện tại và tiếp tục đi lên khi bạn sẵn sàng. Rồi bạn sẽ sớm đạt được những thứ mà người ta đang ao ước.

Học các công cụ và Framework được xây dựng dựa trên JavaScript

học javascript

Bạn cho là học JavaScript bằng cách học React/jQuery/Angular/Vue đúng không? Điều gì sẽ xảy ra nếu có một công cụ mới xuất hiện và bạn phải thay đổi? Cuối cùng, bạn sẽ phải trông đợi người khác bày cách tốt hơn và chia sẻ cho cộng đồng, vì họ đã học JavaScript còn bạn thì không.

Nếu bạn chưa học Vanilla JavaScript, bạn nên bắt đầu học nó đi. Vì nó sẽ giúp bạn hiểu cách các tool được xây dựng như thế nào, tại sao chúng được build và vấn đề chúng giải quyết là gì. Bằng cách học các lý do trong JavaScript, bạn sẽ tránh được việc code xấu sau này.

Xem thêm lý do học Vanilla JavaScript

Trong các công cụ hay framework JavaScript, rất nhiều bits quan trọng được ẩn đi mà bạn cần phải biết. 

Không chia nhỏ kiến thức ra để học

học JavaScript

Học JavaScript cũng như học môn toán lúc trước vậy. Khi bạn học căn bản về phép cộng, nhân, chia… bạn sẽ chuyển sang học so sánh lớn hơn, nhỏ hơn, phép chia nhiều chữ số, đại số cơ bản,… Bạn thường gặp khó khăn trong việc học là vì bạn nhảy cóc quá xa, mà không đi những bước ngắn. Tất nhiên học thẳng vào đại số mà không học cơ bản là điều không thể rồi.

Bằng cách đi từng bước nhỏ, khi gặp những khái niệm bạn không biết, sẽ dễ dàng hơn rất nhiều để tìm kiếm trợ giúp vì bạn đã thu hẹp chủ đề lại.

Kết luận

Trên đây là 7 sai lầm sẽ làm bạn thụt lại phía sau khi học JavaScript. Hy vọng các bạn có thể tránh được và phát triển hơn trong việc học JavaScript. Cảm ơn các bạn đã theo dõi bài viết!

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

Xem thêm việc làm JavaScript Developer hot nhất tại TopDev

Kỹ thuật phần mềm vs Khoa học máy tính – Nên chọn ngành nào/

chọn chuyên ngành IT nào

Xin chào mọi người! Tên tôi là YK, hiện đang quản lí CS Dojo, một kênh YouTube giáo dục lập trình với hơn 200.000 người đăng ký. Tôi cũng từng là một nhà phát triển phần mềm tại Google.

Trong quá trình làm ra các video, tôi thường được hỏi hai câu hỏi phổ biến:

   “Sự khác biệt giữa khoa học máy tính và phần mềm kỹ thuật phần mềm là gì?”

Và …

   “Tôi có nên chọn khoa học máy tính hay kỹ thuật phần mềm để trở thành một kỹ sư phần mềm?”

Trong bài viết này, tôi sẽ trả lời các câu hỏi trên và đưa cho bạn phân tích nhanh về những chuyên ngành này.

Tổng quan nhanh về hai chuyên ngành này

Khoa học máy tính là nghiên cứu về cách các máy tính hoạt động, chủ yếu từ quan điểm lý thuyết và toán học.

Bạn nên chọn Khoa học máy tính nếu bạn thích toán học, logic hoặc nếu bạn muốn tham gia vào một lĩnh vực chuyên biệt trong CS chẳng hạn như trí tuệ nhân tạo, học máy, an ninh, hoặc đồ họa.

Kỹ thuật phần mềm là nghiên cứu về cách thức các hệ thống phần mềm được xây dựng, bao gồm các chủ đề như quản lý dự án, đảm bảo chất lượng và kiểm tra phần mềm.

Bạn nên chọn kỹ thuật phần mềm nếu bạn quan tâm nhiều hơn đến cách thực hành và nếu bạn muốn tìm hiểu chu kỳ sống chung của phần mềm được xây dựng và duy trì như thế nào.

Cả Khoa học máy tính và kỹ thuật phần mềm đều dạy các nguyên tắc cơ bản của lập trình và khoa học máy tính, vì vậy bạn vẫn có thể chọn một trong hai để trở thành một nhà phát triển phần mềm.

Để hiểu được sự khác biệt giữa khoa học máy tính và kỹ thuật phần mềm, chúng ta hãy cùng xem chương trình giảng dạy của họ tại Đại học Waterloo ở Canada.

Tôi đã chọn Đại học Waterloo vì nó có một trong những chương trình khoa học máy tính tốt nhất ở Bắc Mỹ

  Cách tiếp cận công nghệ và ngôn ngữ mới cho những lập trình viên non trẻ

Triển vọng nghề nghiệp

Đầu tiên chúng ta hãy so sánh các loại công việc và thực tập mà bạn có thể có được thông qua mỗi chương trình.

Rất may, trang web của Đại học Waterloo có cung cấp một số ví dụ cụ thể.

Khoa học máy tính

  • Nhà phát triển Web / Kiến trúc sư Desinger
  • Lập trình viên
  • Nhà phát triển điện thoại di động Moblie / đám mây Cloud
  • Kỹ thuật Phần mềm
  • Kỹ thuật phát triển phần mềm
  • Kỹ sư Agile
  • Chuyên viên Phân tích Kinh doanh
  • Quản lý sản phẩm
  • Hỗ trợ công nghệ IT Support
  • Nhà phát triển phần mềm
  • Quản lý Phần mềm
  • Kỹ sư phần mềm
  • Quản lý Sản phẩm Kỹ thuật
  • Tư vấn, Giải pháp Tài chính
  • Tư vấn thực hiện

Như bạn thấy, không có sự khác biệt lớn giữa các loại công việc mà bạn có thể có được.

Đa phần các sinh viên sau khi tốt nghiệp đều làm Software Developer hoặc Software Engineer

Cũng có những lựa chọn liên quan khác như quản lý sản phẩm, nhà phân tích QA và tư vấn công nghệ. Nó hoàn toàn tùy thuộc vào khả năng của bạn.

Các khóa học năm thứ nhất:

Bây giờ, chúng ta hãy xem các khóa học bắt buộc của mỗi chương trình. Trước tiên chúng ta hãy so sánh một số các khóa học bạn cần phải thực hiện trong năm đầu tiên của bạn.

  • Khoa học máy tính

   CS 135 – Thiết kế các chương trình chức năng

   CS 136 – Thuật toán và khai thác dữ liệu

   MATH 135 – Đại số

   MATH 136 – Đại số tuyến tính 1

   MATH 137 – Calculus 1

   MATH 138 – Calculus 2

   Cộng thêm một vài môn phụ

  • Kỹ thuật phần mềm

   CS 137 – Nguyên tắc lập trình

   CS 138 – Thu thập và thực hiện dữ liệu

   MATH 115 – Đại số tuyến tính cho kỹ thuật

   MATH 117 – Calculus 1 cho Kỹ thuật

   MATH 119 – Calculus 2 cho Kỹ thuật

   ECE 105 – Vật lý Kỹ thuật Điện 1

   ECE 106 – Điện và Từ

   ECE 124 – Các mạch và hệ thống số

   ECE 140 – Mạch tuyến tính

   SE 101 – Phương pháp kỹ thuật Phần mềm

Như bạn thấy, các khóa học năm đầu cũng tương tự như vậy. Cả hai đều bao gồm một vài khóa học về khoa học máy tính cơ bản, và một vài môn toán trong đại số tuyến tính và tính toán.

Sự khác biệt lớn duy nhất là phần mềm Kỹ thuật có thêm vật lý và các thành phần kỹ thuật điện, trong khi Khoa học Máy tính có thêm một số môn tự chọn.

Các khoá học sau năm đầu tiên:

Các khóa học bắt buộc và tự chọn sau năm đầu tiên như thế nào? Chúng ta hãy xem xét một số ví dụ ở đây:

  • Khoa học máy tính:

   MATH 239 Giới thiệu tổng hợp

   STAT 230 Xác suất

   STAT 231 Thống kê

   CS 240 Cấu trúc dữ liệu và Quản lý dữ liệu

   CS 241 Các cơ sở của các chương trình tuần tự

   CS 245 Logic và Tính toán

   CS 246 Phát triển phần mềm hướng đối tượng <- không bắt buộc đối với các chuyên ngành Kỹ thuật phần mềm

   CS 251 Tổ chức và thiết kế Máy tính

   Thuật toán CS 341

   CS 350 Hệ điều hành

   Thêm vào đó, một số môn Khoa học máy tính

  • Kỹ thuật phần mềm:

   CHE 102 Hóa học cho kỹ sư

   ECE 222 Máy vi tính số (bao gồm ngôn ngữ lắp ráp)

   ECE 358 Mạng máy tính

   MATH 213 Toán cao cấp cho kỹ sư phần mềm

   MATH 239 Giới thiệu tổng hợp

   STAT 206 Thống kê cho Kỹ thuật Phần mềm

   MSCI 261 Kinh tế Kỹ thuật: Quản lý Tài chính cho Kỹ sư

   CS 241 Các cơ sở của các chương trình tuần tự

   CS 240 Cấu trúc dữ liệu và Quản lý dữ liệu

   CS 247 Nguyên tắc Kỹ thuật Phần mềm <- không bắt buộc đối với các chuyên ngành Khoa học máy tính

   Thuật toán CS 341

   Giao diện Người dùng CS 349 <- không bắt buộc đối với các chuyên ngành Khoa học máy tính

   CS 343 Lập trình song song và song song <- không bắt buộc đối với các chuyên ngành Khoa học máy tính

   CS 348 Giới thiệu về Quản lý Cơ sở dữ liệu

   SE 212 Logic và Tính toán

   SE 350 Hệ điều hành

   SE 465 Kiểm thử phần mềm và đảm bảo chất lượng

   SE 464 Thiết kế và Kiến trúc phần mềm

   SE 463 Yêu cầu phần mềm Yêu cầu kỹ thuật và phân tích

   Dự án Thiết kế SE 490

   Thêm vào đó, một vài môn khoa học máy tính và các môn kỹ thuật điện

Tôi đã cung cấp cho bạn rất nhiều thông tin để tiêu hóa ở đây. Nhưng ngắn gọn thì:

Khi nói đến các yêu cầu trong toán học và thống kê, Khoa học máy tính và Kỹ thuật phần mềm gần như giống hệt nhau. Chúng bao gồm tổ hợp, xác suất và thống kê.

Các yêu cầu về khoa học máy tính cốt lõi cũng tương tự nhau, bao gồm các thuật toán, cấu trúc dữ liệu và các hệ điều hành.

Sự khác biệt chính là:

  • Kỹ thuật phần mềm có nhiều yêu cầu hơn về kỹ thuật điện và các nguyên tắc cơ bản về phần mềm, chẳng hạn như kiểm tra phần mềm, thiết kế và yêu cầu phần mềm.
  • Khoa học Máy tính cho phép nhiều môn tự chọn trong các khóa học khoa học máy tính cấp cao hơn. Bạn có thể chọn từ một loạt các chủ đề như an ninh, nguyên tắc cơ bản về công nghệ phần mềm, tầm nhìn máy tính, học máy và quản lý cơ sở dữ liệu.

Vậy, bạn nên chọn chuyên ngành IT nào nào?

Tôi nghĩ rằng nó chủ yếu phụ thuộc vào sở thích của bạn. Nói ngắn gọn:

Bạn nên chọn Khoa học máy tính nếu bạn thích toán học, logic, hoặc nếu bạn muốn tham gia vào một lĩnh vực chuyên biệt trong CS chẳng hạn như trí tuệ nhân tạo, học máy, an ninh hoặc đồ họa.

Bạn nên chọn Kỹ thuật phần mềm nếu bạn quan tâm nhiều hơn đến cách tiếp cận thực hành và nếu bạn muốn tìm hiểu chu kỳ sống chung của phần mềm được xây dựng và duy trì như thế nào.

  Cách tiếp cận công nghệ và ngôn ngữ mới cho những lập trình viên non trẻ

Nhưng ngành nào thì thích hợp cho software engineer?

Thông thường, các công ty thường tìm kiếm trong một ứng cử viên kỹ sư phần mềm là khả năng viết code tốt và xây dựng các dự án thú vị, cũng như những nguyên tắc cơ bản về khoa học máy tính bao gồm các cấu trúc dữ liệu và thuật toán.

Tôi nghĩ cách tốt nhất để trau dồi kỹ năng này là nhanh chóng học thật vững về nguyên tắc cơ bản về máy tính, và dành thời gian riêng của mình để thực hành viết code.

Dựa trên chương trình học cho kỹ thuật phần mềm và mức độ bận rộn của sinh viên, tôi nghĩ rằng sẽ khó thực hiện việc này nếu bạn theo học kỹ thuật phần mềm hơn là khoa học máy tính.

Một lợi ích khác của chương trình khoa học máy tính này là nó cho phép nhiều môn tự chọn hơn. Điều này khá tuyệt vời vì tùy thuộc vào nhu cầu thị trường lao động, bạn có thể điều chỉnh các khóa học của mình. Ví dụ: nếu phát triển ứng dụng di động, bạn có thể tìm hiểu điều đó. Và nếu tính toán song song là nhu cầu, bạn có thể tập trung vào nó thay cho những khóa khác.

Tôi chắc chắn rằng có một số lợi ích để học các nguyên tắc cơ bản về công nghệ phần mềm (quản lý dự án, thiết kế, thử nghiệm, v.v.). Nhưng tôi cá nhân sẽ linh hoạt hơn đối với các kỹ năng được xác định trước. Đó là lý do tại sao tôi nghĩ rằng khoa học máy tính là một lựa chọn tốt hơn để trở thành một kỹ sư phần mềm.

Tất nhiên, đó chỉ là ý kiến ​​của tôi, và đây nó dựa trên chương trình từ một trường đại học cụ thể. Tôi rất muốn nghe ý kiến ​​của bạn và kinh nghiệm của bạn về hướng chọn chuyên ngành này.

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

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

Xem thêm tuyển dụng ngành cntt hot nhất trên TopDev

Những ngày đen tối nhất của Vue

RFC

Vừa qua cộng đồng VueJS đã có khoảng thời gian khá dậy sóng. Mới đây, người tạo ra Vue, Evan You đã phát hành RFC (Request for Comment) để viết component dựa trên chức năng trong phiên bản Vue 3.0 sắp tới.

Trên Reddit Thread và cả Hacker News xuất hiện rất nhiều bình luận phê bình và chỉ trích, hàng loạt các developer đổ xô vào RFC và bày tỏ sự phẫn nộ của họ, một số còn đi quá giới hạn với nhiều lời bình luận gay gắt.

  Unit testing các component Vue.js bằng các tool Vue testing và Jest (P2): Test Vue.js Components deep render trong Jest
  API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth

Cộng đồng Vue dậy sóng với nhiều comment như:

  • Toàn bộ code Vue phải được biết lại theo cách hoàn toàn mới vì cách viết hiện tại đã bị xoá và thay thế bằng một cái gì đó mới;
  • Thời gian người ta dành ra để học Vue đã thành tro bụi vì mọi thứ sắp thay đổi;
  • Cách viết mới tệ hơn cách cũ, không thực thi cấu trúc, và sẽ dẫn đến spaghetti code;
  • Team Vue Core đã bất ngờ thực hiện một thay đổi lớn mà không hề có tham vấn;
  • Vue đang biến thành React!
  • Không, Vue đang biến thành AngularJS/Angular!
  • Giờ thì HTML phải được viết dưới dạng một string khổng lồ rồi!

Mặc dù có nhiều comment tiêu cực trên Reddit Thread, tỉ lệ reaction tích cực và tiêu cực cho RFC của You rất cao trên trang RFC, và đa phần ý kiến ban đầu khá tích cực.

Và thực tế, phiên bản RFC mới có rất nhiều ưu điểm. Nhưng trước tiên, cùng phân tích và giải quyết những lời chỉ trích tiêu cực trước đã.

Có khá nhiều người đã vội vàng bình luận tiêu cực và gay gắt trên Hacker News hoặc Reddit Thread mà không đọc kĩ các đề xuất ban đầu. Evan You cũng đã có đăng Q&A nhằm giải đáp nhiều vấn đề mọi người gặp phải:

  • Bạn không cần viết lại code nếu bạn không muốn. Cách viết mới chỉ là “thêm mắm thêm muối”, cách viết cũ vẫn có thể được sử dụng trong Vue 3.0 và miễn là còn nhiều người sử dụng cách cũ đó. Thậm chí nếu nó có bị gỡ ra khỏi Core code, các plugin có thể dễ dàng cho phép cách viết cũ còn hiệu lực 100%.
  • Thời gian học Vue của bạn không hề lãng phí. Cú pháp component mới sử dụng chung hình thức mà bạn học, và những hình thức khác như Component single file, template, và phạm vi hoạt động cũng như nhau.
  • Sự thay đổi này không phải là không có tham vấn. RFC là tham vấn. Cú pháp mới vẫn còn lâu mới được phát hành.
  • Và chắc chắn không, HTML không cần viết theo kiểu string khổng lồ rồi.

Một nhận định khá chủ quan là cách viết mới sẽ kém hơn cách viết cũ, và ít code cấu trúc hơn. Cùng xem 1 ví dụ tại saoRFC mới lại tuyệt vời hơn và có cấu trúc code tốt hơn nhé.

Ví dụ component vui, cho phép người dùng nhập thông tin về thú cưng của họ.

Lưu ý:

  • Một thông báo sẽ hiện ra khi người dùng nhập xong tên thú cưng của họ;
  • Sẽ có thông báo khác hiện lên sau khi họ chọn kích cỡ của thú cưng;

VÍ dụ RFC

Ví dụ RFC

Bạn có thể thử demo của component này tại đây và có thể xem toàn bộ code dùng Vue 2.x tại đây. (see components/Vue2.vue)

Một chút JavaScript nào:

export default {
  data() {
    return {
      petName: "",
      petNameTouched: false,
      petSize: "",
      petSizeTouched: false
    };
  },
  computed: {
    petNameComment: function() {
      if (this.petNameTouched) {
        return "Hello " + this.petName;
      }
      return null;
    },
    petSizeComment: function() {
      if (this.petSizeTouched) {
        switch (this.petSize) {
          case "Small":
            return "I can barely see your pet!";
          case "Medium":
            return "Your pet is pretty average.";
          case "Large":
            return "Wow, your pet is huge!";
          default:
            return null;
        }
      }
      return null;
    }
  },
  methods: {
    onPetNameBlur: function() {
      this.petNameTouched = true;
    },
    onPetSizeChange: function() {
      this.petSizeTouched = true;
    }
  }
};

Về cơ bản, chúng ta có một số dữ liệu, các thuộc tính được tính toán từ các dữ liệu đó và các phương thức sẽ thao túng dữ liệu đó. Chú ý là Vue 2.x không có cách nào để giữ những thứ liên quan lại với nhau. Chúng ta không thể để petName khai báo dữ liệu cạnh petNameComment hay phương thức onPetNamBlur được vì trong Vue 2.x nhóm theo loại.

Tất nhiên là điều này không quá quan trọng đối với một ví dụ nhỏ như vậy. Nhưng bạn hãy tưởng tượng với những ví dụ lớn hơn, có nhiều chức năng cần data, computed, methods và thậm chí một hoặc hai watcher. Hiện tại không có cách nào khả quan để giữ những thứ liên quan cùng một chỗ.

Bạn có thể sử dụng một vài thứ như Mixins hay Higher Order Components nhưng có một vấn đề là, rất khó để thấy các thuộc tính đến từ đâu và có những vấn đề gì với xung đột namespace. (Và chắc chắn rồi, trong trường hợp này chúng ta có thể chia ra nhiều component, nhưng hãy xem một ví dụ tương tự không làm cách đó.)

Thay vì sắp xếp các component theo từng loại, đề xuất mới cho phép ta sắp xếp component theo chức năng thực tế. Cũng tương tự cách bạn sắp xếp file cá nhân trên máy tính của mình vậy. Bạn không cần có folder “spreadsheets” hay folder “word documents”, thay vào đó bạn có một folder “work” và một folder “kế hoạch đi chơi”.

Hãy xem component ở trên được viết theo cách mới:

import { state, computed } from "vue";
export default {
  setup() {
    // Pet name
    const petNameState = state({ name: "", touched: false });
    const petNameComment = computed(() => {
      if (petNameState.touched) {
        return "Hello " + petNameState.name;
      }
      return null;
    });
    const onPetNameBlur = () => {
      petNameState.touched = true;
    };

    // Pet size
    const petSizeState = state({ size: "", touched: false });
    const petSizeComment = computed(() => {
      if (petSizeState.touched) {
        switch (this.petSize) {
          case "Small":
            return "I can barely see your pet!";
          case "Medium":
            return "Your pet is pretty average.";
          case "Large":
            return "Wow, your pet is huge!";
          default:
            return null;
        }
      }
      return null;
    });
    const onPetSizeChange = () => {
      petSizeState.touched = true;
    };

    // All properties we can bind to in our template
    return {
      petName: petNameState.name,
      petNameComment,
      onPetNameBlur,
      petSize: petSizeState.size,
      petSizeComment,
      onPetSizeChange
    };
  }
};

Lưu ý là:

  • Rất dễ để nhóm mấy thứ liên quan lại với nhau;
  • Bằng cách xem những gì được trả về bởi chức năng thiết lập, chúng ta có thể dễ dàng thấy những gì được quyền truy cập trong template của mình;
  • Thậm chí ta có thể tránh lộ state nội bộ (“touched”) mà template không cần truy cập;

Trên hết là cách mới dễ dàng cho phép hỗ trợ đầy đủ TypeScript, điều mà khó có thể làm được trong cách cũ ở Vue 2.x. Giờ chúng ta có thể dễ dàng trích xuất logic tái sử dụng thành các chức năng tái sử dụng.

Ví dụ:

import { state, computed } from "vue";

function usePetName() {
  const petNameState = state({ name: "", touched: false });
  const petNameComment = computed(() => {
    if (petNameState.touched) {
      return "Hello " + petNameState.name;
    }
    return null;
  });
  const onPetNameBlur = () => {
    petNameState.touched = true;
  };
  return {
    petName: petNameState.name,
    petNameComment,
    onPetNameBlur
  };
}

function usePetSize() {
  const petSizeState = state({ size: "", touched: false });
  const petSizeComment = computed(() => {
    if (petSizeState.touched) {
      switch (this.petSize) {
        case "Small":
          return "I can barely see your pet!";
        case "Medium":
          return "Your pet is pretty average.";
        case "Large":
          return "Wow, your pet is huge!";
        default:
          return null;
      }
    }
    return null;
  });
  const onPetSizeChange = () => {
    petSizeState.touched = true;
  };
  return {
    petSize: petSizeState.size,
    petSizeComment,
    onPetSizeChange
  };
}

export default {
  setup() {
    const { petName, petNameComment, onPetNameBlur } = usePetName();
    const { petSize, petSizeComment, onPetSizeChange } = usePetSize();
    return {
      petName,
      petNameComment,
      onPetNameBlur,
      petSize,
      petSizeComment,
      onPetSizeChange
    };
  }
};

Trong Vue 2.x, component thường rất khó để chia thành nhiều phần nhỏ. Không thể phân tách thành các component khác vì sẽ có rất nhiều thứ xảy ra trên một lượng nhỏ state.

Tuy nhiên sử dụng phương pháp mới sẽ dễ dàng để thấy cách các component lớn được chia tách thành các phần nhỏ hơn, chuyển chúng vào các file riêng biệt nếu cần thiết, và cho bạn những chức năng cũng như component nhỏ và dễ hiểu hơn.

Liệu đây có phải là ngày đen tối nhất của Vue? Có vẻ đúng vậy đấy. Đến bây giờ, cả một cộng đồng đã hiểu sai định hướng của project mới này. Hy vọng người ta sẽ có cái nhìn khác về phiên bản mới.

RFC mới vẫn cho phép họ nhóm mọi thứ theo loại tuỳ chọn nếu họ thích, nhưng nó còn cho phép nhiều hơn thế nữa. Code clear hơn, clean hơn, thư viện có nhiều khả năng thú vị hơn, và hỗ trợ TypeScript đầy đủ.

Cuối cùng, khi bạn dùng phần mềm mã nguồn mở, bạn nên biết ơn những người maintain đang nỗ lực rất nhiều vào một thứ gì đó cho bạn sử dụng free. Một số lời chỉ trích gay gắt thật sự không có lý. Rất may là những comment tiêu cực đó vẫn còn ít và đã có nhiều người thể hiện ý kiến tích cực và tôn trọng hơn cho tác giả và cả phiên bản mới này.

Cảm ơn các bạn đã theo dõi bài viết!

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

Xem thêm việc làm Software Developers hot nhất trên TopDev

  Unit testing các component Vue.js bằng các tool Vue testing và Jest (P3): Test các Style and cấu trúc của các Vue.js Component trong Jest
  Call API trong VueJS theo cách thông minh nhất

Lập trình viên và hội chứng Tự kỷ

Khi tôi đọc bài viết của Wesner Moise về hội chứng Asperger (một dạng tự kỷ nhẹ), tôi đã không cảm thấy ngạc nhiên. Nhiều người trong số các nhà phát triển phần mềm giỏi nhất mà tôi từng biết đều có một vài đặc điểm đi kèm với hội chứng tự kỷ (Asperger):

1. Khiếm khuyết về mặt xã hội

Điều đáng chú ý bởi vì nó được phân loại là một dạng rối loạn, một số người bị hội chứng tự kỷ (Asperger) gần như bình thường trong khả năng đọc và sử dụng nét mặt cũng như các hình thức tinh tế khác của giao tiếp. Tuy nhiên, khả năng này không tự nhiên đến với hầu hết những người có hội chứng tự kỷ. Những người như vậy thường bị chậm phát triển các kỹ năng xã hội và phải học để có thể phát triển được những kỹ năng đó.

  Tự học một cách chủ động từ dự án và đồng nghiệp

  Con đường sự nghiệp của một Lập trình viên!

2. Có những mối quan tâm trong phạm vi hẹp và mãnh liệt

Hội chứng tự kỷ có thể liên quan đến một mức độ ám ảnh tập trung dữ dội vào những mối quan tâm. [.. ] Những mối quan tâm đặc biệt phổ biến là phương tiện vận tải (như tàu hỏa), máy tính, toán học (đặc biệt là các khía cạnh cụ thể, chẳng hạn như số pi), wikipedia, và khủng long. Lưu ý rằng một số trong những điều kể trên là mối quan tâm thông thường ở những trẻ em bình thường; sự khác biệt ở trẻ em tự kỷ đó là là cường độ bất thường trong mối quan tâm của chúng.

3. Lời nói và ngôn ngữ khá lập dị

Việc giải thích ngữ nghĩa là một dấu hiệu phổ biến khác nhưng không hoàn toàn xác định cho hội chứng này. Attwood đưa ra ví dụ về một cô gái bị hội chứng tự kỷ, một ngày nọ cô trả lời điện thoại gọi đến từ một người lạ hỏi là “Có Paul đó không?”. Mặc dù Paul trong câu hỏi là người có mặt ở trong nhà, nhưng anh ta không ở cùng phòng với cô, vì vậy sau khi nhìn xung quanh để khẳng định điều này, cô ta chỉ đơn giản nói “không” và dập máy. Người ở đầu bên kia đã gọi trở lại và giải thích với cô rằng ông muốn nhờ cô tìm Paul và chuyển điện thoại cho anh ta.

Tôi thường nói đùa rằng bạn phải có một chút ám ảnh mới có thể trở thành một lập trình viên giỏi được. Phát triển phần mềm thì ..

  • chủ yếu là nam giới
  • luôn gắn chặt với thứ tự, cú pháp, và giải thích chính xác
  • cho phép bạn giao tiếp với máy tính chứ không phải con người
  • đòi hỏi sự tập trung gần như ám ảnh

.. cũng giống như hội chứng tự kỷ.

Đây không phải là một ý tưởng mới; có một bài báo kinh điển trên tạp chí Wired về mối liên quan đáng lo ngại giữa lập trình và hội chứng tự kỷ:

Đó là một câu chuyện đùa vui quen thuộc trong ngành công nghiệp này, khi mà rất nhiều các lập trình viên lão làng trong các công ty lớn như Intel, Adobe, và Silicon Graphics – đến làm việc rất sớm, và về nhà rất muộn, luôn uống những chai nước ngọt Big Gulp loại lớn trong ô làm việc của họ trong khi ngồi viết code liên tục trong nhiều giờ liền – họ cũng thuộc diện nào đó trong hội chứng tự kỷ. Kathryn Stewart, giám đốc Học viện Orion, một trường trung học dành cho trẻ em bị bệnh tăng động ở California, đã gọi hội chứng tự kỷ là bệnh “rối loạn của các kỹ sư”. Bill Gates cũng thường xuyên được chẩn đoán trên báo chí là: luôn tập trung đầu óc của ông duy nhất vào các chi tiết kỹ thuật nhỏ nhất. Nhiều đồng nghiệp trong Thung lũng Silicon “có thể được chẩn đoán bị hội chứng ODD (Hội chứng rối loạn chống đối và thách thức) – họ là những kẻ lập dị”. Trong tác phẩm Microserfs, tiểu thuyết gia Douglas Coupland cũng nhận xét, “Tôi nghĩ rằng tất cả mọi người làm việc liên quan đến công nghệ đều mắc chứng tự kỷ ở dạng nhẹ.”

Mặc dù không có ai cố gắng thuyết phục những bộ óc thông minh và giỏi nhất của Thung lũng Silicon đăng ký tham gia vào các bài test về căn bệnh này, văn hóa của khu vực này đã phát triển một cách tinh tế để đáp ứng nhu cầu xã hội của những người trưởng thành bị mắc chứng tự kỷ nhẹ. Trong cộng đồng những kỹ sư và nhà nghiên cứu R&D, thái độ xã hội bị gạt sang một bên. Bạn có thể lập dị như bạn muốn, nhưng nếu code của bạn là quan trọng, thì không ai sẽ chỉ ra rằng bạn đã được mặc một chiếc áo sơ-mi liên tục trong 2 tuần liền. Những người tự kỷ gặp khó khăn trong việc làm nhiều nhiệm vụ cùng một lúc (đa nhiệm) – đặc biệt là khi một trong các kênh giao tiếp là kiểu mặt đối mặt. Thay thế sự huyên náo của các văn phòng kiểu truyền thống bằng một màn hình máy tính và một địa chỉ email, chèn vào một giao diện điều khiển được giữa một lập trình viên và sự hỗn loạn của cuộc sống hàng ngày. Việc làm phẳng sự phân cấp thứ bậc ở nơi làm việc sẽ tạo ra sự thoải mái hơn cho những ai thấy khó khăn trong việc giao tiếp xã hội. Trong một thế giới WYSIWYG (What You See Is What You Get), nơi sự tôn trọng và phần thưởng được dựa hoàn toàn vào công sức họ bỏ ra, thì đó là giấc mơ của một người mắc hội chứng tự kỷ.

Có một yếu tố di truyền đã được ghi nhận trong hội chứng rối loạn phát triển này, nhưng điều không may là nó có nhắm đến khu vực mà các kỹ sư phần mềm tập trung sinh sống:

Những điểm nóng công nghệ cao như Thung lũng Silicon, và vành đai Route 128 bao quanh Boston, là một nghịch lý gây tò mò: Chúng là nơi tập hợp của những người cô đơn. Ở những nơi này, nếu bạn là một người đam mê công nghệ (geek) và mắc hội chứng tự kỷ nhẹ, thì nhiều khả năng bạn sẽ gặp một ai đó có cùng nỗi ám ảnh dai dẳng giống như bạn (ví dụ về Linux hay Star Trek). Khi mà ngày càng nhiều phụ nữ bước chân vào lĩnh vực IT, thì những gã trước đây chưa bao giờ có một lời cầu nguyện để tìm kiếm một người bạn đời đồng cảm đột nhiên phát hiện ra rằng cô ấy đang ngôi viết code ngay trong ô làm việc bên cạnh.

Các nhà di truyền học đã suy đoán về một giả thuyết hấp dẫn có thể giải thích cho sự gia tăng của các rối loạn trong cộng đồng kỹ sư lão luyện ở Thung lũng Silicon, đó là sự gia tăng về sự phối ngẫu giữa những cá thể trong cộng đồng này. Bình thường các quý ông tóc vàng sẽ thích các cô gái tóc vàng; người trí thức thường gặp bạn đời của mình trong phòng chờ của bác sĩ chuyên khoa. Có những áp lực bổ sung và các biện pháp khuyến khích cho những người tự kỷ tìm thấy bạn tâm giao – nếu họ muốn làm như vậy – với một người nào đó cũng có hội chứng tự kỷ. Grandin viết, “Hôn nhân diễn ra tốt nhất khi hai người tự kỷ kết hôn hoặc khi một người tự kỷ kết hôn với một người bạn đời tàn tật hoặc lập dị…. Họ bị hấp dẫn nhau bởi vì trí tuệ của họ làm việc trên cùng một bước sóng giống nhau.”

Tại các trạm y tế và trường học trong Thung lũng Silicon, người ta quan sát thấy rằng hầu hết các bậc cha mẹ của những đứa trẻ mắc chứng tự kỷ là những kỹ sư và lập trình viên có biểu hiện mắc hội chứng tự kỷ dạng nhẹ. Và đó có thể không phải là tin tức gì mới mẻ đối với cộng đồng này. Tháng Giêng vừa rồi, Microsoft đã trở thành công ty lớn của Mỹ đầu tiên cung cấp quyền lợi bảo hiểm cho nhân viên của mình để trang trải chi phí đào tạo hành vi cho những đứa con mắc chứng tự kỷ của họ. Một bà mẹ ở khu vực Bay Area nói với tôi rằng khi bà đang có kế hoạch chuyển tới Minnesota với con trai mình, người có hội chứng tự kỷ, bà đã hỏi trường học ở quận xem liệu họ có thể đáp ứng được nhu cầu của con trai bà. “Họ nói với tôi rằng góc phần tư phía Tây Bắc của Rochester, nơi các nhân viên hãng IBM tụ tập sinh sống, có một số lượng lớn các trẻ em mắc chứng tự kỷ,” bà nhớ lại. “Đó cũng là lời đề xuất để tôi chuyển nhà đến khu vực này sinh sống.”

Nhưng cuối cùng một câu hỏi quan trọng là về mức độ; điều gì sẽ quyết định xem đâu là người tự kỷ và đâu là người bình thường? Hans Asperger, vị bác sĩ tâm thần người Áo lần đầu tiên xác định các điều kiện để xác định đâu là người mắc bệnh tự kỷ, đã từng viết rằng để thành công trong khoa học và nghệ thuật, một chút tự kỷ là điều cần thiết.

TopDev via Vinacode

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