Home Blog Page 144

Vì sao IT Fresher không thể bỏ lỡ Vòng Loại cuối cùng của TopDev Challenge?

TopDev Challenge lần đầu tiên khởi động vào tháng 10/2020 kết hợp cùng nền tảng Hackerrank hứa hẹn một sân chơi chuyên nghiệp, công bằng, trực quan không cảm tính hay thiên vị dành riêng cho lập trình viên sẵn sàng đương đầu thử thách!

Nếu đây từng là nơi “luyện code” nay đã trở thành một đấu trường cạnh tranh năng lực cùng những món quà hấp dẫn “dân công nghệ” không tài nào bỏ qua!

Hiện tại cuộc thi đã đi đến được Round 2 – Vòng Loại cuối cùng của TopDev Challenge 2020 trước khi bước vào Final Round và tìm ra người thắng chung cuộc! 

HackerRank là một nền tảng hiện đang được nhắc đến rất nhiều trong cộng đồng lập trình viên. Nếu bạn đã từng nghe thoáng qua cái tên này hoặc nếu bạn đã biết đến HackerRank nhưng vẫn chưa có “đủ động lực” để thử sức với một nền tảng mà sẽ giúp năng cao kỹ năng lập trình của mình thì hãy cùng TopDev tìm hiểu 4 lý do vì sao bạn nên tạo một tài khoản HackerRank ngay bây giờ nhé!


HackerRank là nơi bạn có thể học và rèn luyện kỹ năng lập trình, đặc biệt về thuật toán, Machine learning & AI, với độ khó từ mức cơ bản cho đến cực kỳ “hack não”.

Trên HackerRank, người tham gia được yêu cầu đưa ra lời giải cho các challenge (những bài toán/câu đố do HackerRank cung cấp). Kết quả và tốc độ giải đề của bạn sẽ những yếu tố để đánh giá và xếp hạng các lập trình viên tham gia trên toàn thế giới!

Hiện tại nhiều công ty công nghệ trên thế giới đang sử dụng HackerRank như một công cụ để đánh giá ứng viên trong quy trình tuyển dụng IT. Riêng Việt Nam cũng sẽ không ngoại lệ, làn sóng sử dụng HackerRank như một bài test ứng viên IT sẽ trở nên phổ biến trong thời gian tới!

Một nơi để bạn khẳng định bản thân và giành lấy những phần quà hấp dẫn thông qua các cuộc thi! Nếu bạn là người “mới vào nghề” (fresher hoặc sinh viên CNTT), việc luyện tập & tham gia một cuộc thi trên HackerRank sẽ là một cơ hội giúp bạn khẳng định bản thân trước nhà tuyển dụng và trong cộng đồng lập trình, đồng thời rinh về những phần quà giá trị!

  HackerRank là gì? Lời khuyên khi tham gia HackerRank

  Ra mắt Nền tảng kết hợp tuyển dụng và đánh giá ứng viên IT chuẩn quốc tế đầu tiên tại Việt Nam TopDev x HackerRank

Không những thế, ciệc lộ diện danh tính các ‘Problem Setter’ có giúp bạn đoán được phần nào chủ đề bài thi:

TopDev Challenge là một “sân chơi chuẩn quốc tế” dành riêng cho IT freshers Việt Nam. Cuộc thi vừa là một nơi “luyện code”, đồng thời cũng là nơi “đọ code” giữa các fresher để bạn có thể khẳng định bản thân trước nhà tuyển dụng nói riêng và trong cộng đồng lập trình viên Việt Nam nói chung. Người chiến thắng còn có cơ hội nhận được những phần thưởng lên đến hàng chục triệu đồng, ngại gì mà không thử sức?!

Tìm hiểu & đăng ký tham gia cuộc thi ngay nào coders ơi!     

Xây dựng REST API cơ bản trong Golang

Xây dựng REST API cơ bản trong Golang

Bài viết được sự cho phép của tác giả Võ Xuân Phong

Để tiếp cận với Golang một cách nhanh chóng hơn, chúng ta sẽ xây dựng một REST API cơ bản với Golang nhé.

Cấu trúc project

Chúng ta hãy tạo cấu trúc thư mục như hình bên dưới, project này có tên GolangRestApi các bạn có thể clone về với đường link sau: Github

  Chiến trường sinh tử phiên bản lập trình : Python vs Ruby vs Golang
  Channel trong Golang là gì? So sánh Callback function và mutex lock với channel

Sau khi clone về các bạn nhớ đổi tên project thành GolangRestApi và vào GOPATH rồi copy vào thư mục src, cách cài đặt và setup dự án Golang các bạn có thể tham khảo chi tiết tại bài viết này của mình:

https://anhlamweb.com/bai-viet-64/hoc-golang-tu-con-so-0-phan-1-cai-dat-golang-tren-linux-va-windows.html

Xây dựng REST API cơ bản trong Golang

Code Rest Api Golang

entities/user.go

Khai báo cấu trúc của một thực thể User. User sẽ có hàm ToString để xuất thông tin chi tiết của User đó ra.

package entities

import (
"fmt"
)

type User struct {
Id string `json:"id"`
Name string `json:"name"`
Password string `json:"password"`
}

func (user User) ToString() string {
return fmt.Sprintf("id: %s\nName: %s\nPassword: %s\n", user.Id, user.Name, user.Password)
}

models/userModel.go

Định nghĩa các hàm cơ bản như CreateUser, UpdateUser, FindUser, DeleteUser và GetAllUser. listUser dùng để chưa thông tin của các User, thay vì để khai báo listUser như vậy chúng ta có thể connect tới  database và thực hiện các thao tác như trên, nhưng để dễ hiểu và rõ ràng hơn thì ở bài viết này chúng ta sẽ thực hiện theo cách đơn giản này trước.

package models

import (
"GolangRestApi/entities"
"errors"
)

var (
listUser = make([]*entities.User, 0)
)

func CreateUser(user *entities.User) bool {
if user.Id != "" && user.Name != "" && user.Password != "" {
if userF, _ := FindUser(user.Id); userF == nil {
listUser = append(listUser, user)
return true
}
}
return false
}

func UpdateUser(eUser *entities.User) bool {
for index, user := range listUser {
if user.Id == eUser.Id {
listUser[index] = eUser
return true
}
}
return false
}

func FindUser(id string) (*entities.User, error) {
for _, user := range listUser {
if user.Id == id {
return user, nil
}
}
return nil, errors.New("User does not exist")
}

func DeleteUser(id string) bool {
for index, user := range listUser {
if user.Id == id {
copy(listUser[index:], listUser[index+1:])
listUser[len(listUser)-1] = &entities.User{}
listUser = listUser[:len(listUser)-1]
return true
}
}
return false
}

func GetAllUser() []*entities.User {
return listUser
}

apis/userapi/userApi.go

Ở file này là các hàm xử lý các http request và chịu trách nhiệm trả về kết quả cho người dùng bằng http response.

package userapi

import (
"GolangRestApi/entities"
"GolangRestApi/models"
"encoding/json"
"net/http"
)

func FindUser(response http.ResponseWriter, request *http.Request) {
ids, ok := request.URL.Query()["id"]
if !ok || len(ids) < 1 {
responseWithError(response, http.StatusBadRequest, "Url Param id is missing")
return
}
user, err := models.FindUser(ids[0])
if err != nil {
responseWithError(response, http.StatusBadRequest, err.Error())
return
}
responseWithJSON(response, http.StatusOK, user)
}

func GetAll(response http.ResponseWriter, request *http.Request) {
users := models.GetAllUser()
responseWithJSON(response, http.StatusOK, users)
}

func CreateUser(response http.ResponseWriter, request *http.Request) {
var user entities.User
err := json.NewDecoder(request.Body).Decode(&user)
if err != nil {
responseWithError(response, http.StatusBadRequest, err.Error())
} else {
result := models.CreateUser(&user)
if !result {
responseWithError(response, http.StatusBadRequest, "Could not create user")
return
}
responseWithJSON(response, http.StatusOK, user)
}
}

func UpdateUser(response http.ResponseWriter, request *http.Request) {
var user entities.User
err := json.NewDecoder(request.Body).Decode(&user)
if err != nil {
responseWithError(response, http.StatusBadRequest, err.Error())
} else {
result := models.UpdateUser(&user)
if !result {
responseWithError(response, http.StatusBadRequest, "Could not update user")
return
}
responseWithJSON(response, http.StatusOK, "Update user successfully")
}
}

func Delete(response http.ResponseWriter, request *http.Request) {
ids, ok := request.URL.Query()["id"]
if !ok || len(ids) < 1 {
responseWithError(response, http.StatusBadRequest, "Url Param id is missing")
return
}
result := models.DeleteUser(ids[0])
if !result {
responseWithError(response, http.StatusBadRequest, "Could not delete user")
return
}
responseWithJSON(response, http.StatusOK, "Delete user successfully")
}

func responseWithError(response http.ResponseWriter, statusCode int, msg string) {
responseWithJSON(response, statusCode, map[string]string{
"error": msg,
})
}

func responseWithJSON(response http.ResponseWriter, statusCode int, data interface{}) {
result, _ := json.Marshal(data)
response.Header().Set("Content-Type", "application/json")
response.WriteHeader(statusCode)
response.Write(result)
}

Main.go

Để xây dựng một REST Api Server thì ở đây chúng ta sử dụng mux và tạo một router để nó thực hiện việc handle request như sau.

Server sẽ lắng nghe ở port 5000.

package main

import (
"GolangRestApi/apis/userapi"
"net/http"

"github.com/gorilla/mux"
)

func main() {
router := mux.NewRouter()

router.HandleFunc("/api/v1/user/find", userapi.FindUser).Methods("GET")
router.HandleFunc("/api/v1/user/getall", userapi.GetAll).Methods("GET")
router.HandleFunc("/api/v1/user/create", userapi.CreateUser).Methods("POST")
router.HandleFunc("/api/v1/user/update", userapi.UpdateUser).Methods("PUT")
router.HandleFunc("/api/v1/user/delete", userapi.Delete).Methods("DELETE")

err := http.ListenAndServe(":5000", router)
if err != nil {
panic(err)
}
}

Chạy chương trình bằng lệnh

go run main.go

Kiểm Tra Kết Quả

Để kiểm tra kết quả chúng ta sẽ sử dụng Postman nhé, bạn có thể vào thư mục assets và import file GolangRestApi.postman_collection.json vào để test cho nhanh.

Tạo mới User.

Xây dựng REST API cơ bản trong Golang

Lấy danh sách các User

Xây dựng REST API cơ bản trong Golang

Tìm kiếm một User

Xây dựng REST API cơ bản trong Golang

Cập nhật User

Xây dựng REST API cơ bản trong Golang

Sau khi update user chúng ta hãy kiểm tra lại thông tin vừa được update.

Xây dựng REST API cơ bản trong Golang

Xóa một User

Xây dựng REST API cơ bản trong Golang

Sau khi delete user chúng ta hãy kiểm tra lại danh sách, như hình bên dưới sau khi delete user đi thì danh sách là rỗng.

Xây dựng REST API cơ bản trong Golang

Tổng kết:

Chúng ta đã tập làm quen với Golang và Rest Api trong Golang, ở bài tiếp theo chúng ta sẽ tìm hiểu tiếp về xác thực Rest Api sử dụng Json Web Token nhé.

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

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

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

Viết chương trình Xoá các File trùng lặp bằng Python

Viết chương trình Xoá các File trùng lặp bằng Python

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

Bạn quá lo âu vì có nhiều file bị trùng lặp trên ổ đĩa khiến chiếm dung lượng bộ nhớ? Nhưng khi tìm kiếm và xoá chúng theo cách thủ công lại quá tẻ nhạt. Tiếp tục Seri python, hôm nay, mình sẽ tiếp tục hướng dẫn các bạn cách xoá các File trùng lặp và giải phóng dung lượng ổ đĩa bằng python.

Giải pháp

Thay vì tìm kiếm khắp ổ đĩa để xoá các File trùng lặp, bạn có thể tự động hóa quy trình này bằng cách sử dụng script, bằng cách viết một chương trình để tìm kiếm đệ quy trong ổ đĩa và loại bỏ tất cả các File trùng lặp được tìm thấy.

Nguyên lý hoạt động

Nếu chúng ta đọc toàn bộ File và sau đó so sánh nó với các File còn lại bằng đệ quy thì sẽ mất rất nhiều thời gian, vậy chúng ta phải làm thế nào mới được?

Câu trả lời là hashing (băm), với hashing chúng ta có thể tạo ra một chuỗi các chữ cái và số nhất định đóng vai trò là danh tính của một File nhất định và nếu chúng ta tìm thấy bất kỳ File nào khác có cùng danh tính, chúng ta sẽ xóa nó.

Viết chương trình Xoá các File trùng lặp bằng Python

Có rất nhiều thuật toán hashing khác nhau như:

  • md5
  • sha1
  • sha224, sha256, sha384 và sha512
  Tại sao phải chọn giữa R hay Python trong khi bạn có thể chọn cả 2?

Code xoá các File trùng lặp bằng Python

Hashing trong Python khá đơn giản, chúng ta sẽ sử dụng thư viện hashlib được mặc định với thư viện chuẩn của Python.

Dưới đây là một ví dụ về cách chúng ta hashing nội dung bằng cách sử dụng hashlib, chúng ta sẽ băm một chuỗi trong Python bằng cách sử dụng thuật toán băm md5.

Ví dụ

>>> import hashlib
>>> example_text = "Duplython is amazing".encode('utf-8')
>>> hashlib.md5(example_text).hexdigest()
'73a14f46eadcc04f4e04bec8eb66f2ab'

Giải thích chút, bạn chỉ cần import hashlib và sau đó sử dụng phương thức md5 để tạo hash và cuối cùng sử dụng hexdigest để tạo chuỗi hash.

Ví dụ trên đã cho chúng ta thấy cách băm một chuỗi nhưng khi xem xét mối việc này với dự án sắp thực hiện, thì chúng ta phải quan tâm đến các File hơn là chuỗi đúng không? Một câu hỏi khác đã được đặt ra.

Chúng ta Hash file như thế nào?

Các File hash (băm) tương tự như chuỗi băm nhưng lại có một sự khác biệt nhỏ, trong quá trình băm File, trước tiên chúng ta cần mở File ở dạng nhị phân và sau đó băm giá trị nhị phân của File.

Băm file

Giả sử bạn có tài liệu văn bản đơn giản trên thư mục dự án của mình với tên learn.txt. Đây là cách mà chúng ta sẽ thực hiện.

>>> import hashlib
>>> file = open('learn.txt', 'rb').read()
>>> hashlib.md5(file).hexdigest()
'0534cf6d5816c4f1ace48fff75f616c9'

Hàm này sẽ trả ra các giá trị băm giống nhau nếu các file đó có nội dung giống nhau khi đó dễ dàng tìm và Xoá các File trùng lặp bằng Python. Lưu ý: khác tên nhưng giống nội dung thì vẫn trả ra giá trị băm giống nhau nhé.

Thách thức nảy sinh khi chúng ta cố gắng đọc một File khá lớn sẽ mất một lúc để tải nó. Do đó, thay vì đợi toàn bộ File vào bộ nhớ, chúng ta có thể tiếp tục tính toán hàm băm khi đọc File.

Việc tính toán hàm băm trong khi đọc File yêu cầu chúng ta đọc File theo các khối có kích thước nhất định và liên tục cập nhật các hàm băm khi chúng ta tiếp tục đọc File cho đến khi băm hoàn chỉnh toàn bộ File. Nói đơn giản là chia file làm nhiều phần, sau đó đọc từng phần, từng phần đó sẽ được hash, sau khi hash sẽ được update vào biến khác.

Làm theo cách này có thể giúp chúng ta tiết kiệm rất nhiều thời gian chờ đợi mà chúng ta có thể sử dụng để đợi toàn bộ File sẵn sàng.

Ví dụ

>>> import hashlib
>>> block_size = 1024
>>> hash = hashlib.md5()
>>> with open('learn.txt', 'rb') as file:
... block = file.read(block_size)
... while len(block)>0:
... hash.update(block)
... block = file.read(block_size)
... print(hash)
...
0534cf6d5816c4f1ace48fff75f616c9

Nhưng băm chỉ là một bước chúng ta cần để thực sự loại bỏ các bản sao, do đó chúng ta sẽ sử dụng module OS để xóa các bản sao.

Chúng ta sẽ sử dụng hàm remove() trong module OS để xoá các File trùng lặp.

Sử dụng module OS để xoá file learn.txt

Ví dụ:

>>> import os
>>> os.listdir()
['Desktop-File-cleaner', '.git', 'learn.txt', 'app.py', 'README.md']
>>> os.remove('learn.txt')
>>> os.listdir()
['Desktop-File-cleaner', '.git', 'app.py', 'README.md']

Sau khi đã xoá được file với hàm remove(), chúng ta sẽ bắt đầu xây dựng ứng dụng.

  Top 15 câu hỏi phỏng vấn Python lý thuyết + thực hành

Cách tạo ứng dụng xoá các File trùng lặp

Những thư viện cần thiết:

import time
import os
from hashlib import sha256

Mình là một người rất thích lập trình hướng đối tượng nên trong bài viết này, mình sẽ xây dựng tool dưới dạng một class duy nhất, code bên dưới chỉ là khung sườn của chương trình.

import time
import os
from hashlib import sha256

class Duplython:
def __init__(self):
self.home_dir = os.getcwd(); self.File_hashes = []
self.Cleaned_dirs = []; self.Total_bytes_saved = 0
self.block_size = 65536; self.count_cleaned = 0

def welcome(self)->None:
print('******************************************************************')
print('**************** DUPLYTHON ****************************')
print('********************************************************************\n\n')
print('---------------- WELCOME ----------------------------')
time.sleep(3)
print('\nCleaning .................')

def main(self)->None:
self.welcome()

if __name__ == '__main__':
App = Duplython()
App.main()

Đó chỉ là giao diện của chương trình, khi bạn chạy nó sẽ chỉ in lời chào mừng ra màn hình.

$ python3 app.py
******************************************************************
**************** DUPLYTHON ****************************
********************************************************************

---------------- WELCOME ----------------------------
​
Cleaning .................

Bây giờ chúng ta sẽ tạo một hàm đơn giản dùng để băm một File với đường dẫn nhất định bằng cách sử dụng kiến ​​thức băm mà chúng ta đã học ở trên.

import time
import os
from hashlib import sha256

class Duplython:
def __init__(self):
self.home_dir = os.getcwd(); self.File_hashes = []
self.Cleaned_dirs = []; self.Total_bytes_saved = 0
self.block_size = 65536; self.count_cleaned = 0

def welcome(self)->None:
print('******************************************************************')
print('**************** DUPLYTHON ****************************')
print('********************************************************************\n\n')
print('---------------- WELCOME ----------------------------')
time.sleep(3)
print('\nCleaning .................')

def generate_hash(self, Filename:str)->str:
Filehash = sha256()
try:
with open(Filename, 'rb') as File:
fileblock = File.read(self.block_size)
while len(fileblock)>0:
Filehash.update(fileblock)
fileblock = File.read(self.block_size)
Filehash = Filehash.hexdigest()
return Filehash
except:
return False

def main(self)->None:
self.welcome()

if __name__ == '__main__':
App = Duplython()
App.main()

Triển khai logic cho chương trình

Sau khi tạo hàm băm File, chúng ta phải triển khai ở nơi sẽ so sánh các chuỗi băm đó và loại bỏ bất kỳ bản sao nào được tìm thấy.

Tôi sẽ tạo một hàm đơn giản được gọi là clean () như hình bên dưới.

import time
import os
from hashlib import sha256
​
class Duplython:
def __init__(self):
self.home_dir = os.getcwd(); self.File_hashes = []
self.Cleaned_dirs = []; self.Total_bytes_saved = 0
self.block_size = 65536; self.count_cleaned = 0
​
def welcome(self)->None:
print('******************************************************************')
print('**************** DUPLYTHON ****************************')
print('********************************************************************\n\n')
print('---------------- WELCOME ----------------------------')
time.sleep(3)
print('\nCleaning .................')

def generate_hash(self, Filename:str)->str:
Filehash = sha256()
try:
with open(Filename, 'rb') as File:
fileblock = File.read(self.block_size)
while len(fileblock)>0:
Filehash.update(fileblock)
fileblock = File.read(self.block_size)
Filehash = Filehash.hexdigest()
return Filehash
except:
return False
​
def clean(self)->None:
all_dirs = [path[0] for path in os.walk('.')]
for path in all_dirs:
os.chdir(path)
All_Files =[file for file in os.listdir() if os.path.isfile(file)]
for file in All_Files:
filehash = self.generate_hash(file)
if not filehash in self.File_hashes:
if filehash:
self.File_hashes.append(filehash)
#print(file)
else:
byte_saved = os.path.getsize(file); self.count_cleaned+=1
self.Total_bytes_saved+=byte_saved
os.remove(file); filename = file.split('/')[-1]
print(filename, '.. cleaned ')
os.chdir(self.home_dir)

def main(self)->None:
self.welcome();self.clean()
​
if __name__ == '__main__':
App = Duplython()
App.main()

Bây giờ chương trình của chúng ta đã gần hoàn tất, việc cuối cùng là phải hiển thị kết quả của quá trình dọn dẹp cho người dùng xem.

Xem thêm:  Javascript Hoa mai đào rơi trang trí Tết cho Website

Mình đã tạo ra hàm Cleaning_summary() chỉ để làm việc đó. In kết quả của quá trình dọn dẹp ra màn hình để hoàn thành chương trình.

import time
import os
import shutil
from hashlib import sha256

class Duplython:
def __init__(self):
self.home_dir = os.getcwd(); self.File_hashes = []
self.Cleaned_dirs = []; self.Total_bytes_saved = 0
self.block_size = 65536; self.count_cleaned = 0

def welcome(self)->None:
print('******************************************************************')
print('**************** DUPLYTHON ****************************')
print('********************************************************************\n\n')
print('---------------- WELCOME ----------------------------')
time.sleep(3)
print('\nCleaning .................')

def generate_hash(self, Filename:str)->str:
Filehash = sha256()
try:
with open(Filename, 'rb') as File:
fileblock = File.read(self.block_size)
while len(fileblock)>0:
Filehash.update(fileblock)
fileblock = File.read(self.block_size)
Filehash = Filehash.hexdigest()
return Filehash
except:
return False

def clean(self)->None:
all_dirs = [path[0] for path in os.walk('.')]
for path in all_dirs:
os.chdir(path)
All_Files =[file for file in os.listdir() if os.path.isfile(file)]
for file in All_Files:
filehash = self.generate_hash(file)
if not filehash in self.File_hashes:
if filehash:
self.File_hashes.append(filehash)
#print(file)
else:
byte_saved = os.path.getsize(file); self.count_cleaned+=1
self.Total_bytes_saved+=byte_saved
os.remove(file); filename = file.split('/')[-1]
print(filename, '.. cleaned ')
os.chdir(self.home_dir)

def cleaning_summary(self)->None:
mb_saved = self.Total_bytes_saved/1048576
mb_saved = round(mb_saved, 2)
print('\n\n--------------FINISHED CLEANING ------------')
print('File cleaned : ', self.count_cleaned)
print('Total Space saved : ', mb_saved, 'MB')
print('-----------------------------------------------')

def main(self)->None:
self.welcome();self.clean();self.cleaning_summary()

if __name__ == '__main__':
App = Duplython()
App.main()

Ứng dụng Xoá các File trùng lặp bằng Python của chúng ta đã hoàn tất, bây giờ để chạy ứng dụng, hãy chạy nó trong thư mục cụ thể mà bạn muốn dọn dẹp và nó sẽ đệ quy qua một thư mục nhất định để tìm tất cả các File và xóa File trùng lặp.

Kết quả

$ python3 app.py
******************************************************************
**************** DUPLYTHON ****************************
********************************************************************
​
​
---------------- WELCOME ----------------------------
​
Cleaning .................
0(copy).jpeg .. cleaned
0 (1)(copy).jpeg .. cleaned
0 (2)(copy).jpeg .. cleaned

​
--------------FINISHED CLEANING ------------
File cleaned : 3
Total Space saved : 0.38 MB

Sử dụng flat state trong Vue Store

Sử dụng flat state trong Vue Store

Bài viết được sự cho phép của tác giả Lưu Bình An

Đầu tiên chúng ta cần trả lời câu hỏi global state có phải là phương thuốc chữa bá bệnh cho các vấn đề liên quan tới state? Mình chỉ đưa dữ liệu vào Vuex store như là lựa chọn cuối cùng và có một lý do cụ thế để phải sử dụng. Điều thứ 2, luôn giữ global state ở dạng cây một cấp, nghĩa là chúng ta không lồng dữ liệu liệu vào nhau như bên dưới

  3 phút làm quen với Vue.js
  Autosaving cùng Vuex

Đọc thêm https://markus.oberlehner.net/blog/should-i-store-this-data-in-vuex/ để có khái niệm khi nào cần dữ liệu trong store và khi nào không.

Quan điểm về flat state (không lưu dữ liệu lồng nhau trong store) được lấy cảm hứng từ chú Matt Biilmann chia sẽ về quan điểm về Redux sau khi làm cái dashboard cho Netlify trong bài phỏng vấn Architecting the Netlify Dashboard with React and Redux

cap_1: {
    cap_2: {
        cap_3: {
        }
    }
}

Rất khó để sync dữ liệu ở dạng lồng ghép như vậy.

Ví dụ, có danh sách bài viết, mỗi bài viết được nhét thông tin tác giả bên trong, có nhiều bài viết có cùng một tác giả, rồi ngày đẹp trời tác giả này đổi tên, thì chúng ta phải đi sync lại toàn bộ tất cả bài viết của ổng.

const articles = [
  // bài viết này được load trước
  {
    author: {
      avatar: 'https://picsum.photos/id/1011/25',
      id: 1,
      name: 'Jane Doe',
    },
    id: 1,
    intro: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr.',
    title: 'Lorem Ipsum',
  },
  // tác giả đó ổng vô đổi avatar,
  // rồi chúng ta load thêm bài viết
  // avatar của ổng đã không còn như xưa
  {
    author: {
      avatar: 'https://picsum.photos/id/2000/25',
      id: 1,
      name: 'Jane Doe',
    },
    id: 2,
    intro: 'Stet clita kasd gubergren, no sea takimata sanctus est.',
    title: 'Dolor sit',
  },
];

Cách mà chúng ta nên lưu, tách riêng 2 thằng

const articles = {
  1: {
    author: 1,
    id: 1,
    intro: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr.',
    title: 'Lorem Ipsum',
  },
  2: {
    author: 1,
    id: 2,
    intro: 'Stet clita kasd gubergren, no sea takimata sanctus est.',
    title: 'Dolor sit',
  },
};

const authors = {
  1: {
    avatar: 'https://picsum.photos/id/2000/25',
    id: 1,
    name: 'Jane Doe',
  },
};

Những kiểu thực thể khác nhau, chúng ta tách ra thành các module riêng biệt, dùng khái niệm foreign key (khóa ngoại) như trong database

// src/store/modules/article.js
import Vue from 'vue';

import { normalizeRelations, resolveRelations } from '../helpers';
import articleService from '../../services/article';

const state = {
  byId: {},
  allIds: [],
};

const getters = {
  // trả về một article với giá trị id được truyền vào
  find: (state, _, __, rootGetters) => id => {
    // dùng ID để lấy thông tin tác giả
    return resolveRelations(state.byId[id], ['author'], rootGetters);
  },
  // trả về danh sách articles
  list: (state, getters) => {
    return state.allIds.map(id => getters.find(id));
  },
};

const actions = {
  load: async ({ commit }) => {
    const articles = await articleService.list();
    articles.forEach((item) => {
      commit('add', normalizeRelations(item, ['author']));
      // thêm hoặc update order
      commit('author/add', item.author, {
        root: true,
      });
    });
  },
};

const mutations = {
  add: (state, item) => {
    Vue.set(state.byId, item.id, item);
    if (state.allIds.includes(item.id)) return;
    state.allIds.push(item.id);
  },
};

export default {
  actions,
  getters,
  mutations,
  namespaced: true,
  state,
};
// src/store/helpers.js
export function normalizeRelations(data, fields) {
  return {
    ...data,
    ...fields.reduce((prev, field) => ({
      ...prev,
      [field]: Array.isArray(data[field])
        ? data[field].map(x => x.id)
        : data[field].id,
    }), {}),
  };
}

export function resolveRelations(data, fields, rootGetters) {
  return {
    ...data,
    ...fields.reduce((prev, field) => ({
      ...prev,
      [field]: Array.isArray(data[field])
        ? data[field].map(x => rootGetters[`${field}/find`](x))
        : rootGetters[`${field}/find`](data[field]),
    }), {}),
  };
}

Sử dụng

<template>
  <div id="app">
    <ArticleList :articles="articles"/>
  </div>
</template>

<script>
// src/App.vue
import { mapActions, mapGetters } from 'vuex';

import ArticleList from './components/ArticleList';

export default {
  name: 'App',
  components: {
    ArticleList,
  },
  computed: {
    ...mapGetters('article', { articles: 'list' }),
  },
  created() {
    this.loadArticles();
  },
  methods: {
    ...mapActions('article', { loadArticles: 'load' }),
  },
};
</script>

Trong component App.vue chúng ta lấy các getter và action trong article module, khi vừa khởi tạo component, gọi action loadArticle để lấy dữ liệu

<template>
  <ul class="ArticleList">
    <li
      v-for="article in articles"
      :key="article.id"
    >
      <h2>{{ article.title }}</h2>
      <p>{{ article.intro }}</p>
      <div class="ArticleList__author">
        <img class="ArticleList__avatar" :src="article.author.avatar" :alt="article.author.name">
        {{ article.author.name }}
      </div>
    </li>
  </ul>
</template>

<script>
export default {
  name: 'ArticleList',
  props: {
    articles: {
      required: true,
      type: Array,
    },
  },
};
</script>

Nhờ vào các hàm getter và resolveRelations(), chúng ta có thể dễ dàng truy cập author của từng article

📜 Make your Vuex State Flat: State Normalization with Vuex

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

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

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

Software Developer và 5 bài học kinh nghiệm quan trọng

5 bài học kinh nghiệm quan trọng được đúc kết bởi một Software Developer

Dịch từ bài viết của tác giả Stephen McLean

Với 4 năm làm việc ở vị trí Software Developer tôi đã rút ra được nhiều bài học lớn cho bản thân và hy vọng bài viết này sẽ giúp các dev học hỏi thêm những điều mình chưa biết.

  10 Công cụ Go-To Tech dành riêng cho các Software Developer
  Biến Git và GitHub trở thành công cụ đắc lực cho Software Engineer

Những bài học kinh nghiệm của Software Developer

1. Đừng cho rằng mọi thứ luôn hoạt động trơn tru

Ở job đầu tiên của mình sau khi ra trường, tôi được giao một task nhỏ trong chuỗi dự án dài hạn. Dự án này có sự tham gia của rất nhiều dev và phải chạy nước rút nhiều lần để hoàn thành. Nó có lượng codebase cực kỳ lớn, phức tạp và tích hợp với nhiều dịch vụ outsource.

Xem thêm Thị trường Outsourcing Vietnam 2019 – Thiên đường Outsourcing mới của thế giới

Công việc của tôi là fix một số unit tests không thể chạy liên tục, code của unit tests này tương đối cũ và được viết bởi một Senior Developer. Vì chúng hoạt động tốt trên UI và đã thông qua bài kiểm tra QA nên tôi nghĩ rằng sai sót có thể nằm ở kỹ năng kiểm thử của mình.

topdev

Tôi dành gần 3 ngày để fix những tests không có vấn đề gì như thế nên thời gian lâu hơn. Khi trình bày với sếp, anh ấy nói với tôi rằng đừng bao giờ cho rằng code của người khác thì luôn đúng. Lời khuyên này dường như không chỉ đúng với việc viết code:

  • Đừng nghĩ rằng khi bạn giao việc gì thì người thực hiện đều làm đúng theo như vậy mà thay vào đó, hãy có một thỏa thuận rõ ràng và theo dõi kỹ càng các task đã giao để đạt được kết quả tốt.
  • Đừng cho rằng đối phương đã hiểu những gì bạn nói kể cả khi họ nói đã hiểu và có thể làm được. Tôi rút ra bài học này sau khi là mentor của nhiều Junior Developer. Để chắc chắn bạn nên yêu cầu họ trình bày lại những gì bạn đã hướng dẫn theo cách họ hiểu.
  • Đừng nghĩ rằng đối phương luôn sai. Nhiều người quá tin tưởng vào code của mình và đổ lỗi cho người khác khi code không chạy được. Bạn sẽ được đánh giá cao hơn nếu biết nhìn nhận và test lại code của mình để đảm bảo sự chính xác hơn là chỉ chối lỗi.

Xem thêm Junior developer là gì? Những quy tắc bất biến dành cho Junior developer

2. Hãy suy nghĩ trước khi code

Sự thật là đa phần các dev đều thích automation, họ luôn tìm cách tự động hóa mọi thứ để cải thiện vấn đề. Tuy nhiên, đừng vội vàng viết code để làm điều đó, nhất là khi coding để sửa lỗi sai. Hãy nghiên cứu kỹ nguyên nhân vấn đề chứ đừng vội vàng tìm giải pháp. Trao đổi với nhiều người khác nhau không chỉ các dev để xem đây là lỗi kỹ thuật hay do quy trình, sau đấy hãy tìm giải pháp thực hiện. Vì nếu không hiểu được ngọn nguồn vấn đề, các dev và team của mình sẽ tiếp tục phạm phải nhiều sai lầm hơn khi làm việc mà thôi. 

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

3. Kết quả quan trọng hơn cách tạo ra kết quả

Sau 4 năm là Software Developer tôi nhận ra rằng, tools được sử dụng để xây dựng phần mềm là gì không quan trọng, miễn là nó có thể giúp tôi hoàn thành tốt nhiệm vụ là được. Khách hàng cũng chỉ quan tâm đến sản phẩm cuối cùng và hoạt động của nó có hiệu quả hay không, họ không để ý đến việc làm sao để nó hoạt động được như vậy.

topdev

4. Những vấn đề không do lỗi kỹ thuật mới là vấn đề khó giải quyết nhất

Khi ở giảng đường, mọi sai sót đều do kỹ thuật và bạn dễ dàng tìm được cách để đoạn code mình viết chạy được. Nhưng trong công việc thì không đơn giản như vậy. Bạn sẽ gặp rất nhiều chuyện phát sinh khi chạy một dự án: Làm sao để đảm bảo sự kết nối giữa các bên liên quan với nhau tốt nhất dù khác múi giờ làm việc, làm sao đảm bảo quy trình hoạt động và document được lưu trữ đầy đủ, giúp đỡ các dev mới trong team, giới thiệu cách hoạt động dự án cho khách hàng một cách dễ hiểu nhất,… Đó chỉ là một trong rất nhiều các vấn đề bạn phải giải quyết khi là Software Developer.

  Liệu Software Engineer có phải là nghề dễ ăn?
  20 trường hợp sử dụng lệnh Docker cho developer

5. Mọi vai trò trong team đều quan trọng như nhau

Một dự án sẽ không thể diễn ra suôn sẻ nếu không có sự kết hợp giữa các team liên quan và mỗi thành viên trong một team với nhau. Mỗi người sẽ đóng một vai trò nhất định từ BA, QA, quản lý dự án, quản lý các bên liên quan khác đến các dev. Code sẽ vô nghĩa nếu không có các stakeholder cùng nhau xây dựng dự án.

Kết luận

Hy vọng rằng những chia sẻ trong bài viết này có thể giúp bạn có thêm kinh nghiệm để hoạt động hiệu quả hơn với tư cách là một Software Developer.

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

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

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

QUnit — Những bước chân TDD đầu tiên trên JavaScript

QUnit — Những bước chân TDD đầu tiên trên JavaScript

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

TDD là gì?

TDD (Test Driven Development) là một phương thức làm việc, hay một quy trình viết mã hiện đại. Lập trình viên sẽ thực hiện thông qua các bước nhỏ (BabyStep) và tiến độ được đảm bảo liên tục bằng cách viết và chạy các bài test tự động (automated tests). Quá trình lập trình trong TDD cực kỳ chú trọng vào các bước liên tục sau:

  1. Viết 1 test case cho hàm mới. Đảm bảo rằng test sẽ fail.
  2. Chuyển qua viết code sơ khai nhất cho hàm đó để test có thể pass.
  3. Tối ưu hóa đoạn code của hàm vừa viết sao cho đảm bảo test vẫn pass và tối ưu nhất cho việc lập trình kế tiếp
  4. Lặp lại cho các hàm khác từ bước 1

Phát triển hướng kiểm thử TDD (Test-Driven Development) là một phương pháp phát triển phần mềm trong đó kết hợp phương pháp Phát triển kiểm thử trước (Test First Development) và điều chỉnh lại mã nguồn (Refactoring).

Mục tiêu quan trọng nhất của TDD là hãy nghĩ về kết qủa của bạn trước khi viết mã nguồn cho chức năng. Nhìn chung, mục tiêu của TDD là viết mã nguồn sáng sủa, rõ ràng và hạn chế lỗi, dễ dàng mở rộng.

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

QUnit là gì?

QUnit là một framework mạnh, miễn phí và dễ sử dụng để triển khai Kiểm thử Đơn vị (Unit Testing) trong JavaScript. Framework này đã được dùng cho các dự án jQuery, jQuery UI và jQuery Mobile cũng như có thể dùng cho tất cả các mã nguồn JavaScript nói chung.

Cài đặt QUnit

QUnit là một thư viện độc lập, chỉ cần một tệp JavaScript (qunit.js) và một tệp CSS (qunit.css). Bạn có thể tải chúng xuống từ trang QUnit hoặc sao chép chúng từ kho lưu trữ QUnit GitHub, như sau:

 git clone git://github.com/jquery/qunit.git

Hoặc đơn giản hơn, chúng ta có thể nhúng CDN của QUnit vào trang HTML của chúng ta:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>QUnit Example</title>
    <link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.10.0.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="https://code.jquery.com/qunit/qunit-2.10.0.js"></script>
<script src="tests.js"></script>
</body>
</html>

Sau đó, chúng ta tạo 1 file js là “tests.js” và viết những dòng test case đầu tiên vào đó:

QUnit.test( "hello test", function( assert ) {
    assert.ok( 1 == "1", "Passed!" );
});

Cuối cùng, hãy chạy thử file HTML của bạn và xem kết quả nhé:

QUnit — Những bước chân TDD đầu tiên trên JavaScript

Yeah, bạn đã chạy thành công 1 test case đơn giản đầu tiên, bây giờ hãy thử nâng cấp 1 chút, viết test cho 1 hàm của bạn nhé. Bạn tạo file “app.js” chứa các hàm mà bạn muốn test, và tạo sẵn vào đó hàm sayHello() như sau:

 function sayHello(yourName) {    return yourName; }

Tiếp đó, Viết một test case trong file tests.js dành cho hàm sayHello()

Qunit.test( "test sayHello", function(assert) {
  let expected = "Hello World";
  let result =  sayHello("World");
  assert.ok(expected == result,"Passed!");
});

Chạy thử HTML của bạn sẽ có kết quả như sau:

QUnit — Những bước chân TDD đầu tiên trên JavaScript

Vậy là bạn đã thành công với bước đầu có được test case “fail” với QUnit, công việc của bạn là hoàn chỉnh hàm sayHello() để “pass” được cái test này.

 function sayHello(yourName) {    return "Hello " + yourName; }

Xong rồi chạy lại trang HTML của bạn, nếu hiển thị như này:

Xanh tức là bạn đã “pass” trường hợp đó rồi. Nếu báo đỏ thì bạn hãy kiểm tra lại hàm sayHello() xem có vấn đề gì không nhé. Sau khi pass rồi thì chúng ta viết tiếp những test case mới.

Đến đây tôi đã hoàn tất việc giới thiệu với các bạn về QUnit và một hướng dẫn nho nhỏ để bạn có thể bắt đầu làm Unit Test hay xa hơn nữa là TDD với JavaScript. Bạn có thể tìm hiểu sâu hơn về QUnit tại trang web http://qunitjs.com.

Chúc bạn thành công và có những mã nguồn JavaScript chất lượng!

Author: Dư Thanh Hoàng

Bài viết gốc được đăng tải tại Tạp chí Lập trình

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

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

Một số tool hữu ích dành cho Web Developer có thể bạn chưa biết (Phần 1)

tool cho web developer

Bài viết được sự cho phép của BQT Kinh nghiệm lập trình

Ngày nay lĩnh vực công nghệ phát triển một cách vượt bậc, bên cạnh đó sự trải nghiệm người dùng cũng được theo đó mà tăng lên đáng kể. Đằng sau những giao diện bắt mắt là những ý tưởng mới mẻ, tốn rất nhiều công sức của Developer. Dưới đây mình tổng hợp một số công cụ hữu ích cho một Frontend developer/Designer được chọn lọc qua nhiều nguồn khác nhau.

Font

Trong một layout website thường sẽ có những Icon giúp website đẹp và thân thiện hơn, ngoài ra còn có tác dụng điều hướng người dùng. Trước đây để tạo các Icon đó ta phải thực hiện cắt chúng ra từ file PSD và dùng CSS để gán background hoặc dùng thẻ img để đưa Icon đó vào. Tuy nhiên hiện nay chúng ta đã có giải pháp khác đó là sử dụng Symboy Font (font chữ kiểu ký hiệu). Hiện nay có nhiều thư viện Symboy Font nhưng mạnh nhất và hay sử dụng nhất là Font Awesome, Material icon… vì nó đơn giản và dễ sử dụng.

1. Awesome Font

Font Awesome là một trong những icon font phổ biến nhất hiện nay. Với phiên bản mới nhất hiện tại 5.5.0, Font Awesome hỗ trợ trên 1400 icon free.

Một số tool hữu ích dành cho Web Developer có thể bạn chưa biết (Phần 1)

2. IcoMoon Font

IcoMoon thực chất là một ứng dụng cho phép bạn tuỳ chỉnh icon font, import SVG để tạo ra font riêng, convert font sang SVG, PDF, XAML, CSH… Và IcoMoon cung cấp hơn 5000 icon free bằng cách tối ưu từ nhiều thư viện miễn phí khác nhau

Một số tool hữu ích dành cho Web Developer có thể bạn chưa biết (Phần 1)

CSS Generator

1. CSS tool

Một số tool hữu ích dành cho Web Developer có thể bạn chưa biết (Phần 1)

Đây là công cụ tổng hợp không thể thiếu của một CSS Developer. Có rất nhiều tool dùng để tạo box-shadow, background gradient, text effect, transform…

2. Image Sprites

Với một Frontend developer chắc không xa lạ với kỹ thuật image sprites. Đây là phương pháp giúp tối ưu website, tuy nhiên để xác định tọa độ (background-position) thật là một điều khó khăn. Sau đây làm một công cụ tuyệt vời để giải quyết vấn đề trên với thao tác đơn giản.

Một số tool hữu ích dành cho Web Developer có thể bạn chưa biết (Phần 1)

Tổng kết

Trên đây là một số công cụ cần thiết của một Frontend/Design developer. Hy vọng những công cụ này có thể hỗ trợ phần nào cho công việc lên ý tưởng, hoàn thiện thiết kế UI và phát triển phần code Frontend cho các dự án của các bạn.

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

  Một số tool hữu ích dành cho Web Developer có thể bạn đã biết (Phần 2)

Xem thêm vị trí tuyển dụng web Developer hấp dẫn tại TopDev

Senior là gì? Phân biệt Senior và Junior thật chi tiết

senior là gì
senior là gì

Thị trường tuyển dụng đang phát triển, có rất nhiều thuật ngữ ra đời. Thuật ngữ Senior là một trong số đó. Vậy Senior là gì? Senior không chỉ đơn giản là một người có nhiều năm kinh nghiệm hơn, mà còn là một người đã đạt được một trình độ chuyên môn cao, có khả năng dẫn dắt đội nhóm và đưa ra các quyết định quan trọng. Bài viết này sẽ đi sâu vào khái niệm Senior là gì, những kỹ năng cần có để trở thành một Senior thực thụ, và làm thế nào để liên tục nâng cao trình độ của mình.

Senior là gì?

Senior là thuật ngữ chỉ một người đã có nhiều năm kinh nghiệm (thường là từ 3 năm trở lên), có sự hiểu biết và trải nghiệm dày dặn trong lĩnh vực của mình. Khả năng chuyên môn của họ đã được nâng cao thông qua các thách thức từ những giai đoạn Intern, Fresher, Junior trước đó.

Senior có khả năng làm việc độc lập và đảm nhận các nhiệm vụ phức tạp mà không cần sự giám sát liên tục. Senior không chỉ có kiến thức chuyên môn sâu rộng mà còn có kỹ năng quản lý thời gian, làm việc nhóm và ra quyết định dựa trên kinh nghiệm thực tế.

Senior là gì?
senior là gì

Nhiều người thường nghĩ rằng một Senior sẽ được tôi luyện từ 4 đến 5 năm. Tuy nhiên, đó là cách nghĩ sai lầm. Bạn khó có thể trở thành “tiền bối” nếu chỉ đơn thuần đảm nhận các công việc lặt vặt, dự án với quy mô nhỏ. Không có sự rèn luyện, tiếp thu cái mới về năng lực – kỹ năng, tư duy nghề nghiệp thì bạn phải chấp nhận một sự thật rằng: Bạn vẫn không khác Junior là bao.

Điều đó cho thấy việc tự tích lũy kiến thức theo quá trình mới thật sự quan trọng. Do vậy, không thể đánh giá, phân loại Senior chỉ dựa vào số năm kinh nghiệm. Và tùy thuộc vào từng loại hình công ty, việc phân chia cấp bậc Senior lại có những tiêu chí khác nhau.

Vai trò và công việc của Senior

Trong một tổ chức, vai trò của Senior rất quan trọng. Họ thường là những người dẫn dắt dự án, định hướng kỹ thuật, và đôi khi còn đóng vai trò cố vấn cho các thành viên trẻ hơn trong nhóm. Senior không chỉ đảm bảo rằng công việc được hoàn thành đúng hạn và đạt chất lượng cao mà còn đóng góp vào việc xây dựng văn hóa làm việc tích cực và hiệu quả.

Senior cũng thường là người chịu trách nhiệm trong việc đưa ra các quyết định kỹ thuật quan trọng, đảm bảo rằng các dự án phát triển theo đúng hướng và đáp ứng các yêu cầu kinh doanh. Họ cũng có trách nhiệm đào tạo và hướng dẫn những thành viên mới, giúp họ nhanh chóng nắm bắt công việc và hòa nhập với đội ngũ.

Ngoài ra, Senior cần cung cấp các báo cáo tiến độ thường xuyên cho cấp trên hoặc khách hàng, đảm bảo rằng mọi người đều cập nhật về tình trạng hiện tại của dự án. Đánh giá hiệu suất làm việc của bản thân và các thành viên trong nhóm, đưa ra các phản hồi và đề xuất cải tiến khi cần thiết.

>> Xem thêm: Senior developer là gì? Vai trò và kĩ năng cần có

Những kỹ năng giúp Senior lên “trình” hiệu quả

Kỹ năng về chuyên môn

Kỹ năng chuyên môn phản ánh sự am hiểu các kiến thức nền tảng cần phải có trước khi bạn bước vào giai đoạn phát triển năng lực

Nâng cao không ngừng kiến thức chuyên môn

Một trong những yếu tố quan trọng nhất để một Senior có thể nâng cao trình độ là không ngừng trau dồi và cập nhật kiến thức chuyên môn của mình. Ở cấp độ Senior, bạn cần có sự hiểu biết sâu rộng về lĩnh vực mà mình đang làm việc, từ các công cụ, framework đến các xu hướng công nghệ mới nhất. Việc cập nhật kiến thức liên tục giúp bạn không chỉ giữ vững vị thế mà còn trở thành người dẫn đầu trong việc áp dụng các giải pháp công nghệ tiên tiến.

Để phát triển kỹ năng chuyên môn, bạn có thể:

  • Tham gia các khóa học nâng cao, hội thảo và seminar liên quan đến lĩnh vực của mình.
  • Tham gia vào các cộng đồng chuyên môn để trao đổi và học hỏi từ các chuyên gia khác.
  • Đọc sách chuyên ngành, bài viết và nghiên cứu để nắm bắt các xu hướng mới.

Khả năng phân tích và giải quyết vấn đề

Một Senior không chỉ cần biết cách làm việc mà còn phải hiểu rõ lý do và nguyên nhân sâu xa của các vấn đề trong công việc. Kỹ năng phân tích và giải quyết vấn đề là rất cần thiết, đặc biệt trong những tình huống phức tạp, yêu cầu tư duy logic và sự sáng tạo để tìm ra giải pháp hiệu quả.

Để cải thiện kỹ năng này, bạn có thể:

  • Thực hành phân tích các vấn đề thực tế và đề xuất giải pháp.
  • Thảo luận với đồng nghiệp hoặc nhóm để lắng nghe các góc nhìn khác nhau và tìm ra phương pháp tốt nhất.
  • Tham gia các dự án thử thách để rèn luyện khả năng xử lý tình huống phức tạp.

Kỹ năng làm việc nhóm

Kỹ năng làm việc nhóm là một trong những kỹ năng cốt lõi mà mọi Senior cần phải nắm vững. Ở vị trí này, bạn không chỉ làm việc cá nhân mà còn phối hợp với các thành viên khác trong nhóm để đạt được mục tiêu chung. Hiểu rõ vai trò của mình và của các thành viên khác trong nhóm giúp bạn phối hợp hiệu quả hơn, đảm bảo rằng mọi người đều đóng góp tối đa vào thành công của dự án.

Một Senior thường được kỳ vọng có thể dẫn dắt nhóm, đặc biệt trong các dự án lớn hoặc khi đối mặt với những thách thức khó khăn. Khả năng lãnh đạo không chỉ bao gồm việc đưa ra chỉ đạo mà còn là khả năng truyền cảm hứng, thúc đẩy tinh thần đồng đội và tạo ra một môi trường làm việc tích cực.

Để phát triển kỹ năng lãnh đạo nhóm:

  • Hãy thể hiện tinh thần trách nhiệm và cam kết với công việc của nhóm.
  • Lắng nghe và hỗ trợ các thành viên trong nhóm khi họ gặp khó khăn.
  • Đưa ra các giải pháp và hướng dẫn rõ ràng để nhóm có thể thực hiện công việc một cách hiệu quả.

Làm việc Client

Làm việc với Client/User là một kỹ năng quan trọng đối với một Senior, đặc biệt trong các lĩnh vực yêu cầu sự tương tác trực tiếp với khách hàng như công nghệ thông tin, thiết kế, hay marketing. Hiểu rõ nhu cầu và mong muốn của khách hàng giúp bạn đưa ra các giải pháp phù hợp và đáp ứng được kỳ vọng của họ.

Quản lý kỳ vọng của khách hàng là một trong những thách thức lớn mà mọi Senior đều phải đối mặt. Việc này không chỉ đòi hỏi khả năng giao tiếp tốt mà còn yêu cầu sự nhạy bén trong việc xử lý các tình huống khó khăn, chẳng hạn như khi có sự khác biệt giữa mong đợi của khách hàng và khả năng thực hiện của đội ngũ.

Chuẩn bị các phương án dự phòng và kế hoạch rõ ràng để giải quyết khi có tình huống phát sinh.

Kỹ năng đàm phán

Một Senior không chỉ cần giao tiếp mà còn phải biết đàm phán và thuyết phục, đặc biệt trong các tình huống cần thương lượng về ngân sách, thời gian hoàn thành, hoặc các yêu cầu kỹ thuật. Kỹ năng này giúp bạn đạt được các thỏa thuận có lợi và duy trì mối quan hệ tốt đẹp với các bên liên quan.

Để cải thiện kỹ năng đàm phán:

  • Hãy chuẩn bị kỹ lưỡng trước mỗi cuộc đàm phán, nắm vững thông tin và dữ liệu cần thiết.
  • Hiểu rõ lợi ích của cả hai bên và tìm kiếm giải pháp win-win.
  • Giữ thái độ linh hoạt và sẵn sàng thương lượng để đạt được mục tiêu chung.

So sánh Senior và Junior

Dưới đây là bảng so sánh giữa Senior và Junior để giúp bạn dễ dàng so sánh các yếu tố quan trọng:

Tiêu Chí Junior Senior
Kinh Nghiệm Ít kinh nghiệm hoặc mới bắt đầu sự nghiệp Nhiều năm kinh nghiệm (thường từ 5-10 năm trở lên)
Kiến Thức Chuyên Môn Đang học hỏi và phát triển kỹ năng cơ bản Kiến thức chuyên môn sâu rộng, cập nhật liên tục
Giải Quyết Vấn Đề Cần sự hướng dẫn khi gặp vấn đề Có khả năng phân tích và giải quyết vấn đề phức tạp
Mức Độ Độc Lập Cần sự giám sát và hỗ trợ từ cấp trên Làm việc độc lập mà không cần sự giám sát liên tục
Vai Trò Trong Nhóm Hỗ trợ và thực hiện các nhiệm vụ dưới sự hướng dẫn Lãnh đạo nhóm, đào tạo Junior, chịu trách nhiệm dự án
Giao Tiếp Đang phát triển kỹ năng giao tiếp Giao tiếp hiệu quả, có khả năng thuyết phục và đàm phán
Lãnh Đạo Chủ yếu là người thực hiện nhiệm vụ Định hướng, lãnh đạo và truyền cảm hứng cho đội nhóm
Đóng Góp Vào Tổ Chức Đóng góp ở mức độ công việc cá nhân Tham gia vào chiến lược, cải tiến quy trình, nâng cao hiệu quả tổ chức
Mức thu nhập Mức lương trung bình cho Junior thường từ 8-15 triệu VND/tháng tại Việt Nam. Mức lương trung bình cho Senior có thể từ 25-50 triệu VND/tháng, hoặc hơn tùy vào ngành nghề và công ty.

Khi bạn đang làm việc với chức danh Junior nhưng cảm thấy mình đã đạt được trình độ của Senior, đừng ngần ngại apply vào vị trí Senior bạn nhé, đây chính là thử thách đầu tiên trên con đường phát triển của bạn.

Việc trở thành Senior không phải là điểm dừng mà là một bước tiến mới, đòi hỏi sự tiếp tục học hỏi và phát triển để duy trì và nâng cao năng lực chuyên môn.

>> Xem thêm: So sánh chi tiết Fresher, Junior và Senior

Lời kết

Senior là vị trí đòi hỏi nhiều kỹ năng khác nhau tương ứng với từng ngành nghề nhất định. Hãy đầu tư nhiều vào sự trải nghiệm thay vì mãi loay hoay một nhiệm vụ. Sự đào thải và tính cạnh tranh luôn tồn tại trong môi trường làm việc của các Senior. Đừng để bản thân rơi vào áp lực! Không ngừng nỗ lực, nâng cao trình độ chuyên môn là điều các Senior cần ghi nhớ. TopDev hy vọng, bài viết đã có những chia sẻ bổ ích giúp các bạn có cái nhìn rõ hơn về senior là gì; các kỹ năng cần thiết của một Senior. Chúc các bạn có sự chuẩn bị tốt nhất cho mục tiêu của chính mình.

Tuyển dụng lập trình viên đãi ngộ tốt, tham khảo ngay

Một số đoạn code Python phổ biến bạn nên thuộc lòng

Một số đoạn code Python phổ biến bạn nên thuộc lòng

Bài viết được sự cho phép của tác giả Nguyen Chi Thuc

Đảo ngược chuỗi trong Python

Đoạn mã sau đảo ngược một chuỗi bằng cách sử dụng thao tác cắt (slicing) trong Python.

# Đảo ngược chuỗi sử dụng slicing

my_string = "ABCDE"
reversed_string = my_string[::-1]

print(reversed_string)

# Kết quả
# EDCBA

Viết Hoa ký tự đầu tiên của mỗi từ

Đoạn code sau có thể được sử dụng để chuyển đổi một chuỗi thành trường chuỗi mới được viết HOA ký tự đầu tiên của mỗi từ.

Điều này được thực hiện bằng cách sử dụng phương thức title() của string class.

my_string = "đây là một chuỗi"

# Sử dụng hàm title() của lớp string
new_string = my_string.title()

print(new_string)

# kết quả
# Đây Là Một Chuỗi

Tìm việc python các công ty tập đoàn

Tìm các phần tử duy nhất trong một chuỗi

Đoạn code sau có thể được sử dụng để tìm tất cả các phần tử duy nhất trong một chuỗi.

Chúng ta sử dụng tính chất của kiểu dữ liệu set: Tất cả các phần tử trong set là duy nhất.

my_string = "aavvccccddddeee"

# Chuyển chuỗi thành một set
temp_set = set(my_string)

# Chuyển set thành một chuỗi sử dụng join
new_string = ''.join(temp_set)

print(new_string)

# Kết quả
# acdve

# Vì set không có thứ tự
# nên thứ tự chuỗi mới nhận được là ngẫu nhiên

In một Chuỗi hoặc một List n lần

Bạn có thể sử dụng phép nhân (*) với chuỗi hoặc List. Điều này cho phép chúng ta nhân chúng bao nhiêu lần tùy thích.

n = 3 # Số lần lặp lại

my_string = "abcd"
my_list = [1,2,3]

print(my_string*n)
# abcdabcdabcd

print(my_list*n)
# [1,2,3,1,2,3,1,2,3]

Một trường hợp sử dụng thú vị của điều này có thể là để xác định một list với các giá trị không đổi – hãy thử xem:

n = 4
my_list = [0]*n # n Độ dài của list
# [0, 0, 0, 0]
  Quy tắc đặt tên biến trong Python đúng chuẩn 2024

List comprehension

List comprehension cung cấp cho chúng ta một cách đơn giản, thanh lịch để tạo list dựa trên các list khác.

Đoạn code sau tạo một list mới bằng cách nhân từng phần tử của list cũ với 2.

# Nhân mỗi phần tử của list với 2

original_list = [1,2,3,4]

new_list = [2*x for x in original_list]

print(new_list)
# [2,4,6,8]

Hoán đổi giá trị giữa hai biến trong Python

Python làm cho việc hoán đổi giá trị giữa 2 biến khá đơn giản mà không cần sử dụng một biến trung gian khác.

a = 1
b = 2

a, b = b, a

print(a) # 2
print(b) # 1

Tuyển dụng python Hà Nội lương cao, tham khảo ngay!

Tách một chuỗi thành một list

Chúng ta có thể tách một chuỗi thành một list chứa các chuỗi con bằng phương thức .split().

Bạn cũng có thể truyền một đối số (dấu phân cách) để hướng dẫn tách chuỗi theo chỉ định của bạn.

string_1 = "Tên tôi là NIIT Hà Nội"
string_2 = "chuỗi 1/ chuỗi 2"

# Tách chuỗi mặc định sẽ tách từ khoảng trắng ' '
print(string_1.split())
# ['Tên', 'tôi', 'là', 'NIIT', 'Hà', 'Nội']

# Tách chuỗi từ ký tự '/'
print(string_2.split('/'))
# ['chuỗi 1', ' chuỗi 2']

Kết hợp một danh sách các chuỗi thành một chuỗi

Ngược lại ở ví dụ trên, chúng ta có danh sách các chuỗi. Bây giờ ghép chúng lại thành một chuỗi duy nhất.

Chúng ta sẽ sử dụng phương thức join().

Trong trường hợp này, chúng ta truyền đối số (dấu phân tách) để hướng dẫn ghép chuỗi. (Mình sẽ sử dụng dấu phảy)

list_of_strings = ['Tên', 'tôi', 'là', 'NIIT', 'Hà', 'Nội']

# Sử dụng join và phân tách bằng dấu phảy
print(','.join(list_of_strings))

# Output
# Tên,tôi,là,NIIT,Hà,Nội
  Python: Cách in mà không cần dòng mới

Kiểm tra một chuỗi có phải chuỗi đối xứng

Vì chúng ta đã biết cách đảo ngược chuỗi nên việc kiểm tra một chuỗi có phải chuỗi đối xứng hay không sẽ rất đơn giản.

my_string = "abcba"

if my_string == my_string[::-1]:
    print("Chuỗi đối xứng")
else:
    print("Chuỗi không đối xứng")

# Kết quả
# Chuỗi đối xứng

Tình số lần xuất hiện của các phần tử trong một List

Có nhiều cách để làm điều này, nhưng mình thích sử dụng Counter của Python.

Bộ đếm Python theo dõi tần suất của từng phần tử trong container.

Counter() trả về một dictionary với các phần tử là key và số lần xuất hiện là value.

Chúng tôi cũng sử dụng hàm most_common() để lấy phần tử most_frequent (xuất hiện nhiều nhất) trong List.

# Tìm số lần xuất hiện của mỗi phần từ trong List

# import Counter
from collections import Counter

my_list = ['a','a','b','b','b','c','d','d','d','d','d']
count = Counter(my_list) # Xác định đối tượng counter

print(count) # In thông tin tất cả
# Counter({'d': 5, 'b': 3, 'a': 2, 'c': 1})

print(count['b']) # Số lần xuất hiện của phần tử cụ thể
# 3

print(count.most_common(1)) # Phần tử xuất hiện nhiều nhất
# [('d', 5)]

Tìm xem hai chuỗi có đảo chữ không

Một ứng dụng thú vị của Counter là tìm chuỗi đảo chữ.

Đảo chữ là một từ hoặc cụm từ được hình thành bằng cách sắp xếp lại các chữ cái của một từ hoặc cụm từ khác nhau.

Nếu các đối tượng Counter của hai chuỗi bằng nhau, thì chúng là đảo chữ cái.

# import Counter
from collections import Counter

str_1, str_2, str_3 = "acbde", "abced", "abcda"
cnt_1, cnt_2, cnt_3  = Counter(str_1), Counter(str_2), Counter(str_3)

if cnt_1 == cnt_2:
    print('1 và 2 Đảo chữ')
if cnt_1 == cnt_3:
    print('1 và 3 Đảo chữ')

Sử dụng Khối try-except-else

Xử lý lỗi trong Python có thể được thực hiện dễ dàng bằng cách sử dụng khối try / except.

Thêm một câu lệnh else vào khối này rất hữu ích. Nó sẽ chạy khi không có ngoại lệ xảy ra trong khối try.

Nếu bạn cần chạy một cái gì đó không phân biệt ngoại lệ, hãy sử dụng finaly.

a, b = 1,0

try:
    print(a/b)
    # Ngoại lệ xảy ra khi b == 0
except ZeroDivisionError:
    print("Chia cho số 0")
else:
    print("Không có ngoại lệ xảy ra")
finally:
    print("Luôn luôn chạy lệnh này!")

Việc làm python Đà Nẵng đãi ngộ tốt

Sử dụng liệt kê (Enumerate) để nhận các cặp index / value

Kịch bản sau đây sử dụng phép liệt kê (enumerate) để lặp qua các giá trị trong list cùng với các chỉ mục (index) của chúng.

my_list = ['a', 'b', 'c', 'd', 'e']

for index, value in enumerate(my_list):
    print('{0}: {1}'.format(index, value))

# 0: a
# 1: b
# 2: c
# 3: d
# 4: e

Kiểm tra mức sử dụng bộ nhớ của một đối tượng

Đoạn code sau đây có thể được sử dụng để kiểm tra mức sử dụng bộ nhớ của một đối tượng.

import sys

num = 21

print(sys.getsizeof(num))

# Kết quả trong Python 2 là: 24
# Kết quả trong Python 3 là: 28

Hợp nhất hai từ điển

Trong khi ở Python 2, chúng ta đã sử dụng phương thức update() để hợp nhất hai Dictionaries.

Nhưng Python 3.5 làm cho quá trình này đơn giản hơn nhiều.

Trong đoạn code được đưa ra dưới đây, hai Dictionaries được hợp nhất.

Lưu ý: Các value của Dictionaries thứ hai sẽ được sử dụng nếu key bị trùng với key trong Dictionaries thứ nhất.

dict_1 = {'apple': 9, 'banana': 6}
dict_2 = {'banana': 4, 'orange': 8}

combined_dict = {**dict_1, **dict_2}

print(combined_dict)
# Output
# {'apple': 9, 'banana': 4, 'orange': 8}

Nếu bạn muốn giữ các giá trị của chúng, bạn có thể làm như sau:

def mergeDict(dict1, dict2):
   ''' Hợp nhất dictionaries và giữ giá trị của key phổ biến trong list'''
   dict3 = {**dict1, **dict2}
   for key, value in dict3.items():
       if key in dict1 and key in dict2:
               dict3[key] = [value , dict1[key]]
 
   return dict3

# Hợp nhất dictionaries và thêm giá trị của key phổ biến trong list
dict3 = mergeDict(dict1, dict2)
 
print('Dictionary 3 :')
print(dict3)

Tính thời gian thực hiện để thực thi một đoạn code trong Python

Đoạn code sau sử dụng thư viện time để dễ dàng giúp chúng ta tính thời gian thực để thực thi một đoạn code trong Python.

# import thư viện time
import time

# Kiểm tra thời gian bắt đầu
start_time = time.time()

# Code cần kiểm tra
a, b = 1,2
c = a+ b

# Kiểm tra thời gian kết thúc
end_time = time.time()

# Tính thời gian chênh lệch
time_taken_in_micro = (end_time- start_time)*(10**6)

# In kết quả
print(" Thời gian thực thi micro_seconds: {0} ms").format(time_taken_in_micro)

Trải phẳng list trong list

Đôi khi bạn không chắc chắn về mức độ lồng trong list của mình và bạn chỉ muốn trải phẳng tất cả các phần tử trong đó thành một list duy nhất.

Đây là cách bạn có thể thực hiện:

from iteration_utilities import deepflatten

# Nếu bạn chỉ có một lồng 1 cấp, sử dụng cái này
def flatten(l):
  return [item for sublist in l for item in sublist]

l = [[1,2,3],[3]]
print(flatten(l))
# [1, 2, 3, 3]

# Nếu bạn không biết list lồng sâu thế nào
l = [[1,2,3],[4,[5],[6,7]],[8,[9,[10]]]]

print(list(deepflatten(l, depth=3)))
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Lấy mẫu từ một List

Đoạn mã sau tạo ra n số mẫu ngẫu nhiên từ một list nhất định bằng thư viện random.

# import thư viện
import random

my_list = ['a', 'b', 'c', 'd', 'e']
num_samples = 2

samples = random.sample(my_list,num_samples)
print(samples)

# Kết quả nhận được là ngẫu nhiên:
# [ 'a', 'e']

Bạn cũng có thể sử dụng thư viện secrets để tạo các mẫu ngẫu nhiên để mã hóa.

Đoạn code sau sẽ chỉ hoạt động trên Python 3.

import secrets                              # imports secure module.
secure_random = secrets.SystemRandom()      # Tạo một đối tượng secure ngẫu nghiên.

my_list = ['a','b','c','d','e']
num_samples = 2

samples = secure_random.sample(my_list, num_samples)

print(samples)

# Kết quả nhận được là ngẫu nhiên:
# [ 'e', 'd']

Chuyển đổi một số thành danh sách các chữ số trong Python

Đoạn code sau sẽ chuyển đổi một số nguyên thành một danh sách các chữ số.

num = 123456

# Sử dụng map
list_of_digits = list(map(int, str(num)))

print(list_of_digits)
# [1, 2, 3, 4, 5, 6]

# Sử dụng kỹ thuật list comprehension
list_of_digits = [int(x) for x in str(num)]

print(list_of_digits)
# [1, 2, 3, 4, 5, 6]

Kiểm tra tính duy nhất

Hàm trong ví dụ sau sẽ kiểm tra xem tất cả các phần tử trong list có phải là duy nhất hay không.

def unique(l):
    if len(l) == len(set(l)):
        print("Tất cả phần tử là duy nhất")
    else:
        print("List có phần tử trùng lặp")

unique([1,2,3,4])
# Tất cả phần tử là duy nhất

unique([1,1,2,3])
# List có phần tử trùng lặp

Tổng kết

Đây là một số Đoạn code Python ngắn mình thấy cực kỳ hữu ích trong công việc hàng ngày của mình.

Nếu bạn chưa hiểu lắm, Khóa học Python trên ucode.vn sẽ dạy bạn đầy đủ và chi tiết nhất để bạn hoàn toàn làm chủ Ngôn ngữ Python.

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

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

5 kỹ năng quan trọng cho ngành Nhân sự

ngành nhân sự

Ngành nhân sự ngày nay đòi hỏi nhiều kỹ năng. Đó cũng là thách thức lớn đối với những ai lựa chọn theo đuổi ngành nghề này. Khi thế giới nhân sự phát triển, việc tìm kiếm những người có kỹ năng tốt để đáp ứng sự vận hành hiện đại là ưu tiên hàng đầu. Liệu các kỹ năng nào sẽ giúp bạn có đủ cạnh tranh trong thị trường này? Cùng TopDev điểm qua những kỹ năng mà một HR cần phải.

Giao tiếp

Vấn đề giao tiếp được đánh giá là quan trọng. Vì nó được xem là chiếc chìa khóa giúp bạn thành công. Những người làm nhân sự cần có một khả năng giao tiếp tốt. 

ngành nhân sự

Không chỉ đơn thuần là trao đổi thông tin, bạn còn phải nắm bắt được cảm xúc, suy nghĩ của người tiếp nhân thông tin. Đồng thời, nhận biết những biểu hiện của giao tiếp phi ngôn ngữ: cử chỉ, hành vi,… Chằng hạn trong công tác quản trị nhân sự, mỗi lời nói của các lãnh đạo/nhà quản lý  đều thể hiện một thông điệp nào đó. Và phát ngôn đó đủ sức tạo ra sự ảnh hưởng đến nhân viên.

Tuyển dụng

Sẽ là một thiếu sót lớn nếu bỏ qua kỹ năng này. Vì thực tế, nó chính là một phần công việc mà người người thuộc lĩnh vực nhân sự cần phải thực hiện.

  Những sai lầm phổ biến trong Tuyển dụng Nhân sự

ngành nhân sự

Các thách thức trong việc tìm kiếm, thu hút ứng viên tài năng; và làm thế nào để quản trị nguồn nhân lực hiệu quả đang là mối quan tâm lớn của nhà tuyển dụng. Đó là lý do tại sao họ cần những HR giàu kinh nghiệm và kỹ năng. Điều này mở ra một cuộc chiến tuyển dụng lớn. Và nếu bạn là người có kỹ năng tốt, bạn sẽ có lợi thế nhiều hơn trong cuộc chơi tuyển dụng. 

Công nghệ nhân sự và phân tích dữ liệu

Công nghệ nhân sự là kỹ năng gia tăng các cơ hội tuyển dụng. Những lợi thế mà nó mang lại rất lớn do HR và công nghệ đang ngày càng gắn kết chặt chẽ với nhau.

Việc quản trị nguồn nhân lực đang đi vào thời đại kỹ thuật số. Ngày càng nhiều quá trình được tự động hóa và tăng cường bởi công nghệ. Vì thế, nếu có những hiểu biết cơ bản về công nghệ, bạn sẽ chạm gần hơn với sự thành công.

ngành nhân sự

Đồng thời, nhiều người nghĩ rằng phân tích dữ liệu là một kỹ năng không quá quan trọng. Và họ bỏ qua chúng, điều này thật sai lầm!

Với sự phát triển nguồn dữ liệu đa dạng, nhà tuyển dụng cần những người có khả năng đọc được dữ liệu tốt. Điều này giúp cho công tác nhân sự trở nên chặt chẽ hơn. Từ đó, việc tiếp cận và khai thác nguồn thông tin nhiều hơn.

Trí tuệ cảm xúc – EI

Trí tuệ cảm xúc là tiêu chí quan trọng để đánh giá bạn có thể trở thành một lãnh đạo nhân sự giỏi.

Đối với ngành Nhân sự, trí tuệ cảm xúc đã trở thành một chiến lược quan trọng. Tại sao? Vì nó là một trong những yếu tố quyết định liệu bạn có đủ sự phù hợp với vai trò ứng tuyển hay không. Ngoài ra, sự hiểu biết từ EI có thể giúp bạn xác định xu hướng hành vi của tổ chức/doanh nghiệp. 

  Trí tuệ cảm xúc là gì và áp dụng như thế nào trong ngành Nhân sự

ngành nhân sự

Với EI, bạn có thể khám phá cảm xúcnhững tác động đa chiều xung quanh. Đồng thời, EI còn giúp hình thành nên một môi trường làm việc thân thiện, vui vẻ. Từ đó thúc đẩy việc gia tăng hiệu suất công việc của toàn tổ chức. Chính vì điều này, bạn nên học cách nhận biết những cảm xúc. Hãy rèn luyện để bạn có thể điều khiển được tích cách, suy nghĩ và hành động của mình một cách hiệu quả.

Khả năng thích ứng và sự nhanh nhẹn

Ngành nghề nhân sự cần những ứng viên có khả năng thích nghi tốt. Đồng thời, họ phải nhanh nhẹn để đáp ứng đủ các tiêu chí.

Những nhà lãnh đạo luôn tìm kiếm những người có thể nắm bắt nhanh tình hình. Họ cũng được trao quyền khi đưa ra các đánh giá, những biện pháp, lập kế hoạch xử lý phù hợp. Điều này giúp giảm thiểu tối đa những ảnh hưởng xấu trong công tác quản trị doanh nghiệp.

ngành nhân sự

Đặc biệt, theo một khía cạnh khác các nhà quản lý nhân sự còn đòi hỏi nhân viên của họ có sự bản lĩnh. Và hơn hết, chính sự thích ứng là chiếc chìa khóa tạo ra sự bản lĩnh cho bạn. Một câu hỏi đặt ra là “Bạn sẽ tiếp tục làm công việc cũ hay bức phá khỏi“vùng an toàn?” Với những tố chất sẵn có từ ngành nhân sự cùng khả năng thích ứng tốt, bạn sẽ có những lựa chọn đúng đắn nhất.

Lời kết

Bối cảnh ngành nhân sự đang phát triển theo xu thế chung của thời đại. Vì thế, các doanh nghiệp rất cần những người đa kỹ năng đáp ứng kịp thời sự phát triển đó. Song, đó là một quá trình tích lũy và rèn luyện lâu dài. TopDev hi vọng các bạn sẽ biết đâu là điều mình cần làm. Từ đó, lập kế hoạch theo đuổi mục tiêu thông quq những hành động cụ thể nhất.


Tuyển Dụng Nhân Tài IT Cùng TopDev
Đăng ký nhận ưu đãi & tư vấn về các giải pháp Tuyển dụng IT & Xây dựng Thương hiệu tuyển dụng ngay!
Hotline: 028.6273.3496 – Email: contact@topdev.vn
Dịch vụ: https://topdev.vn/page/products

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

Xem thêm Top Việc làm Developer trên TopDev

Kiểm thử đơn vị trong C# với Nunit và .Net Core

Kiểm thử đơn vị trong C# với Nunit và .Net Core

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

Bài viết sẽ hướng dẫn từng bước xây dựng giải pháp kiểm thử đơn vị. Bài viết này đề cập tới việc kiểm thử một dự án .NET Core.

  So sánh tốc độ List collection và HashSet collection trong C#
  Namespace trong C#

Tạo dự án

Tạo một thư mục có tên là “unit-tests-using-nunit” để lưu trữ solution. Trong thư mục này, hãy chạy lệnh sau để tạo solution mới cho class library và test project:

>> dotnet new sln

Tiếp theo, tạo thư mục PrimeService. Các phác thảo sau đây cho thấy cấu trúc thư mục và tập tin:

Đi đến thư mục PrimeService và chạy lệnh sau để tạo dự án nguồn:

>> dotnet new classlib

Đổi tên Class1.cs thành PrimeService.cs. Tạo ra một triển khai fail của lớp PrimeService:

using System;
namespace Prime.Services
{
    public class PrimeService
    {
        public bool IsPrime(int candidate)
        {
            throw new NotImplementedException("Please create a test first.");
        }
    }
}

Đi đến thư mục “unit-tests-using-nunit”. Chạy lệnh sau để thêm dự án class library vào solution:

>> dotnet sln add PrimeService/PrimeService.csproj

Tạo dự án test

Tiếp theo, tạo thư mục “PrimeService.Tests”. Các phác thảo sau đây cho thấy cấu trúc thư mục:

Đi đến thư mục “PrimeService.Tests” và tạo dự án mới bằng lệnh sau:

>> dotnet new nunit

Lệnh “dotnet new” tạo ra một dự án test sử dụng NUnit làm thư viện test. Xem file cấu hình PrimeService:

using System;
namespace Prime.Services
{
    public class PrimeService
    {
        public bool IsPrime(int candidate)
        {
            throw new NotImplementedException("Please create a test first.");
        }
    }
}

Dự án test yêu cầu các gói khác để tạo và chạy kiểm thử đơn vị. Lệnh “dotnet new” trong bước trước đã thêm SDK test của Microsoft, NUnit test framework và bộ điều hợp thử nghiệm NUnit. Bây giờ, thêm class library PrimeService như một phụ thuộc khác vào dự án. Sử dụng lệnh “dotnet add reference”:

>> dotnet add reference ../PrimeService/PrimeService.csproj

Các phác thảo sau đây cho thấy cấu trúc của solution:

Thực hiện lệnh sau trong thư mục “unit-tests-using-nunit”:

>> dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj

Tạo test

Bạn viết một test fail, làm cho nó pass, sau đó lặp lại quá trình. Trong thư mục “PrimeService.Tests”, đổi tên tệp UnitTest1.cs thành PrimeService_IsPrimeShould.cs và thay thế toàn bộ nội dung của nó bằng mã sau:

using NUnit.Framework;
using Prime.Services;

namespace Prime.UnitTests.Services
{
    [TestFixture]
    public class PrimeService_IsPrimeShould
    {
        private PrimeService _primeService;

        [SetUp]
        public void SetUp()
        {
            _primeService = new PrimeService();
        }

        [Test]
        public void IsPrime_InputIs1_ReturnFalse()
        {
            var result = _primeService.IsPrime(1);

            Assert.IsFalse(result, "1 should not be prime");
        }
    }        
}

Thuộc tính [TestFixture] biểu thị một lớp có chứa các phương thức kiểm thử đơn vị. Thuộc tính [Test] chỉ ra một phương thức là một phương thức kiểm thử.

Lưu tệp này và thực hiện lệnh “dotnet test” để build các kiểm thử và class library và sau đó chạy các kiểm thử. NUnit chứa Entry Point (điểm bắt đầu của chương trình)  để chạy các kiểm thử. “dotnet test” bắt đầu trình chạy thử bằng cách sử dụng dự án kiểm thử đơn vị đã tạo.

Kiểm thử sẽ thất bại. Thực hiện kiểm thử này bằng cách viết mã đơn giản nhất trong lớp PrimeService:

public bool IsPrime(int candidate)
{
    if (candidate == 1)
    {
        return false;
    }
    throw new NotImplementedException("Please create a test first.");
}

Trong thư mục “unit-testing-using-nunit”, chạy lại lệnh “dotnet test”. Lệnh “dotnet test” build dự án PrimeService và sau đó là dự án PrimeService.Tests. Sau khi build cả hai dự án, nó chạy test này, kết quả là pass.

Thêm tính năng

Có một vài trường hợp đơn giản khác cho các số nguyên tố: 0, -1. Có thể thêm các test mới với thuộc tính [Test]. Tuy nhiên, có các thuộc tính NUnit khác cho phép viết một bộ các test tương tự.

Thuộc tính [TestCase] ​​được sử dụng để tạo một bộ các test thực thi cùng một mã nhưng có các đối số đầu vào khác nhau. Bạn có thể sử dụng thuộc tính [TestCase] ​​để chỉ định các giá trị cho các đầu vào đó.

Thay vì tạo các test mới, hãy áp dụng thuộc tính này để tạo một test theo hướng dữ liệu. Test hướng dữ liệu là phương pháp test một vài giá trị nhỏ hơn hai, là số nguyên tố thấp nhất:



public bool IsPrime(int candidate)
{
    if (candidate == 1)
    {
        return false;
    }
    throw new NotImplementedException("Please create a test first.");
}

Chạy lệnh “dotnet test” và hai trong số các test này thất bại. Để thực hiện tất cả các test, hãy thay đổi mệnh đề if ở đầu phương thức Main trong file PrimeService.cs:

public bool IsPrime(int candidate)
{
    if (candidate == 1)
    {
        return false;
    }
    throw new NotImplementedException("Please create a test first.");
}

Bài viết đã hoàn thành xây dựng một thư viện nhỏ và một bộ các kiểm thử đơn vị cho thư viện đó.

Author: Nguyễn Khánh Tùng

Bài viết gốc được đăng tải tại Tạp chí Lập trình

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

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

Các kiểu dữ liệu trong lập trình C/C++ (Data type)

Các kiểu dữ liệu trong lập trình C/C++ (Data type)

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Kiểu dữ liệu trong C – Data type là gì?

Trong lập trình C/C++ (hoặc các ngôn ngữ khác), kiểu dữ liệu chính là phần xác định các giá trị mà một biến có thể nhận hay giá trị mà một hàm có thể trả về. Các kiểu dữ liệu này đã được lưu trữ trong chương trình C.

Dễ hiểu là, nếu xem biến là một vật và kiểu dữ liệu sẽ là vùng để chứa vật đó, thì chúng ta phải lựa chọn kiểu dữ liệu phù hợp cho biến, giống như việc lựa chọn vật đựng phù hợp để chứa vật. Ví dụ một biến cần nhập một giá trị là số nguyên thì không thể khai báo kiểu dữ liệu String được.

Nhiều vị trí tuyển dụng C++ đãi ngộ tốt trên TopDev

Kiểu dữ liệu của một biến, xác định kích thước (số byte) của biến đó. Có 4 kiểu dữ liệu trong lập trình C/C++ là: Kiểu dữ liệu cơ bản, kiểu dữ liệu enum, kiểu void và kiểu dữ liệu nâng cao.

Tổng hợp các kiểu dữ liệu trong C/C++

Kiểu dữ liệu cơ bản

Kiểu dữ liệu cơ bản là kiểu dữ liệu số học, có thể là số nguyên (integer) hoặc số thực (float).

Kiểu số nguyên (integer)

Với kiểu dữ liệu số nguyên (integer) ta có các loại sau:

Kiểu Kích thước Vùng giá trị
char 1 byte -128 tới 127 hoặc 0 tới 255
unsigned char 1 byte 0 tới 255
signed char 1 byte -128 tới 127
int 2 hoặc 4 bytes -32,768 tới 32,767 hoặc -2,147,483,648 tới 2,147,483,647
unsigned int 2 hoặc 4 bytes 0 tới 65,535 hoặc 0 tới 4,294,967,295
short 2 bytes -32,768 tới 32,767
unsigned short 2 bytes 0 tới 65,535
long 4 bytes -2,147,483,648 tới 2,147,483,647
unsigned long 4 bytes 0 tới 4,294,967,295

Cùng là dữ liệu kiểu số học nhưng ta lại có nhiều kiểu khác nhau. Việc này giúp tiết kiệm bộ nhớ là linh động hơn trong việc lưu dữ liệu.

Ví dụ khi lưu tuổi một người ta chỉ cần dùng kiểu char hoặc unsigned char. Vừa tiết kiệm bộ nhớ nhưng vẫn đảm bảo có thể lưu tất cả các tuổi có thể xảy ra.

Nhưng với trường hợp dữ liệu lớn hơn, như số người trong một quốc gia thì lên tới con số hàng triệu. Do đó ta phải sử dụng loại dữ liệu khác như int

Kiểu số thực (float)

Tương tự với kiểu dữ liệu số thực (dấu phẩy động) ta cũng có các loại sau:

Kiểu Kích thước Vùng giá trị Độ chính xác
float 4 byte 1.2E-38 tới 3.4E+38 6 vị trí thập phân
double 8 byte 2.3E-308 tới 1.7E+308 15 vị trí thập phân
long double 10 byte 3.4E-4932 tới 1.1E+4932 19 vị trí thập phân

Code ví dụ:

#include <stdio.h>
#include <limits.h>

int main() {
int age = 25;
int population = 85000000; // 85 triệu

printf("Age: %d - Population: %d \n", age, population);

float pi = 3.14; // giá trị số pi
printf("pi: %f \n", pi);

printf("Storage size for int : %d \n", sizeof(int)); // kích thước kiểu int
printf("Storage size for float : %d \n", sizeof(float)); // kích thước kiểu float

return 0;
}

Kết quả:

Các kiểu dữ liệu trong lập trình C/C++ (Data type)

Kiểu dữ liệu Enum

Kiểu dữ liệu Enum trong ngôn ngữ C hay còn gọi là kiểu dữ liệu cố định, kiểu liệt kê. Giá trị của một Enum chỉ có thể nhận giá trị là một số các số nguyên cho trước.

Kiểu Enum này khá giống với kiểu Enum trong Java, Node.js hay Python…

Kiểu dữ liệu Void

Kiểu void dùng xác định không có giá trị nào (không phải là null).

Nó được sử dụng trong các trường hợp sau đây:

  • Kiểu trả về của một hàm: khi một không trả về dữ liệu gì thì hàm đó có kiểu void

Ví dụ:

void hello() {
printf("hello world");
}
  • Hàm với tham số void (tức là hàm không có tham số đầu vào)

Ví dụ: 2 cách viết dưới đây tương đương nhau:

void hello() {
printf("hello world");
}
// tương đương với
void hello(void) {
printf("hello world");
}
  • Con trỏ kiểu void void * được dùng để tham chiếu thới địa chỉ của một đối tượng (chứ không phải là một kiểu dữ liệu mới. Phần này hơi khó hiểu mình sẽ có bài riêng)

Kiểu dữ liệu nâng cao

Các kiểu dữ liệu nâng cao của C gồm:

  • Con trỏ (pointer)
  • Kiểu mảng (array)
  • Kiểu cấu trúc (structure)
  • Kiểu union
  • Kiểu hàm (function)

Kiểu dữ liệu boolean

Kiểu dữ liệu Boolean là một kiểu dữ liệu có chỉ có thể nhận một trong hai giá trị như đúng/sai (true/false, yes/no, 1/0) nhằm đại diện cho hai giá trị thật (truth value).

Trong lập trình C kiểu boolean sẽ được gọi là bool (trong Java thì gọi là boolean, trong Python thì gọi là bool… tùy theo ngôn ngữ)

Ban đầu, ngôn ngữ C không hỗ trợ kiểu bool, mà nó dùng số integer để biểu thị true/false (0 tức là false, khác 0 tức là true). Bắt đầu từ phiên bản C99 standard for C language thì mới bắt đầu hỗ trợ kiểu bool.

Lưu ý

Kiểu String

C/C++ không có loại dữ liệu string (text) dùng để hiển thị văn bản. Để hiển thị các giá trị kiểu text/string, ta dùng kiểu char. Thực chất char vẫn là kiểu số, nhưng tùy theo giá trị mà nó được hiểu thành các ký tự trong bảng mã ASCII. Một đoạn text/string trong C/C++ sẽ là một mảng char

Ví dụ số 32 tương ứng với dấu cách, 48 tương ứng với ký tự '0', 65 tương ứng với ký tự 'A'.

Để hiển thị đoạn text ‘hello’ thì ta cần mảng char tương ứng là [104, 101, 108, 108, 111]

Kiểu bool

Trong lập trình C, thực chất bool chính là kiểu integer (0 tức là false, khác 0 tức là true)

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

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

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

Tìm hiểu before và after trong CSS

Tìm hiểu before và after trong CSS

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

Hey ya. Tình hình là mới đi du lịch Đà Nẵng zìa hôm kia nên hôm nay tranh thủ viết bài chia sẻ tiếp kiến thức cho anh em. Và chủ đề hôm nay đó là một trong những pseudo class mà nhiều bạn học và làm vẫn chưa hiểu rõ cũng như áp dụng hết sự hiệu quả của nó mang lại đó chính là :before và :after.

Hiểu đơn giản thì before thì thêm vào trước và after là thêm vào sau thế thôi nhưng để hiểu sâu và làm được với nó thì cách tốt nhất đó là làm ví dụ thì mới mau hiểu được. Nào cùng chiến thôi.

  3 điều bạn có thể không biết về biến trong CSS
  9 CSS animation mới "mãn nhãn" cho các project

Đừng quên tham khảo khoá học HTML CSS cực chất mới ra mắt của mình tại đây: https://evondev.com/khoa-hoc-html-css

# Cách sử dụng

Để sử dụng :before hay :after thì đơn giản các bạn chỉ cần dùng theo cú pháp element:before hoặc element:after. Như .home:before{} chẳng hạn. Và để before hay after hoạt động thì bắt buộc phải có thuộc tính content nha.

Thường thường các bạn hay thấy content: "" người ta để rỗng thế này là vì người ta muốn làm một cái gì đó khác mà không có nội dung bên trong. Còn bạn muốn thêm vào content: "noidung" thì vẫn được không sao cả. Ví dụ một thẻ p nào đó

<p>toi ten la</p>

Mình muốn thêm tên của mình vào phía sau thẻ p này thì mình sẽ sử dụng :after

p:after {
content: " Tuan";
}

Còn nếu mình muốn thêm vào trước thì dùng :before

p:before {
content: "Xin chao ";
}

Ta được kết quả như hình

Tìm hiểu before và after trong CSS

Hoặc các bạn có thể thấy rõ khi các bạn sử dụng fontawesome, họ xài before hay after để hiển thị icon với thuộc tính content: "\ec06" gì đó để nó hiển thị icon tương ứng mà họ đã định dạng trong code của họ.

Còn nếu mà để trống content: "" như này thì các bạn cũng có thể làm nhiều kiểu style khác như làm background phủ toàn bộ layer nè, hiệu ứng background chạy qua chạy lại rồi animation các kiểu, tạo những kiểu phức tạp…. nhiều lắm.

Thường thường khi sử dụng before hoặc after thì phần tử mà chúng ta đang làm nên sử dụng position: relative hoặc position: absolute. Sau đó trong :before hay :after các bạn dùng position: absolute và các thuộc tính toprightbottomleft để căn chỉnh vị trí cùng với các thuộc tính CSS khác để style theo ý muốn của bạn.

Nếu bạn không hiểu cách dùng position trong CSS như thế nào thì đừng quên quay lại bài trước mình có viết về tìm hiểu thuộc tính position trong CSS rất rõ ràng chi tiết luôn ấy. Các bạn có thể xem tại đây nha.

Giờ mình sẽ làm vài ví dụ kèm theo giải thích cho các bạn dễ hiểu và hình dung hơn. Chớ đọc chữ nãy giờ chắc chưa thông não đâu.

# Hiệu ứng background

Giả sử bây giờ mình có HTML như thế này

<h2>Animation background</h2>

và CSS như này

h2 {
  display: block;
  margin: 50px;
  padding: 10px;
  color: black;
  font-weight: bold;
  position: relative;
}
h2:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 100%;
  background-color: #e74c3c;
  transition: .25s;
}

Giờ mình muốn khi rê chuột vào thì cái background-color nó sẽ chạy từ trái qua phải rồi sau khi đưa chuột ra thì background-color nó thu về lại. Mình sẽ code như sau

h2:hover:before {
  width: 100%;
}

Lúc đầu mình cho :before có thuộc tính content: "" rỗng, position: absolute để chạy theo phần tử cha(ở đây là thẻ h2 chính nó) và  top: 0left: 0 thì nó sẽ nằm góc bên trái trên cùng

Kèm theo là height: 100% nghĩa là nó sẽ chiếm chiều cao 100% của phần tử mà chúng ta đang làm là thẻ h2 và set độ rộng(width) là 0 để nó chưa có gì hết. Và kèm thêm transition để làm hiệu ứng nó mượt hơn khi :hover vào.

Sau đó mình dùng :hover để khi chúng ta rê chuột vào thì mình cho độ rộng(width: 100%) để cho cái background-color nó chạy ra từ trái qua phải. Bạn có thể xem demo Codepen này

Tuy nhiên các bạn sẽ thấy khi rê chuột vào background-color nó chạy đè lên chữ luôn. Như vậy là sai rồi. Vì thế đừng quên dùng thuộc tính z-index vào nhé. Ở trong Codepen các bạn check code CSS sẽ thấy mình có comment cái z-index: -1 lại đó.

Mình để số âm là vì muốn nó nằm dưới, z-index hoạt động như các lớp đè lên nhau lớp nào có z-index cao hơn sẽ nằm lên trên và ngược lại lớp nào có z-index thấp hơn sẽ nằm ở dưới.

Mặc định giá trị của z-index là auto và z-index chỉ hoạt động khi đi kèm với thuộc tính position nhé. Cho nên mình set cho thẻ h2:before là -1 cho nó nằm dưới text. Các bạn nhớ bỏ comment để nó hiển thị ra kết quả như mong đợi nè.

Giờ mình muốn cải thiện hiệu ứng độc đáo hơn một chút với các thuộc tính left right các bạn có thể xem tham khảo nà. Mình muốn khi rê chuột vào background-color nó sẽ chạy từ trái qua phải(như lúc đầu) và sau khi bỏ chuột ra thay vì co background-color lại bên trái thì mình muốn nó chạy qua bên phải luôn.

Chỉ một chút thay đổi code CSS với thuộc tính left và right như thế này

h2:before {
  content: "";
  position: absolute;
  top: 0;
  left: auto; /*change here*/
  right: 0;/*change here*/
  width: 0;
  height: 100%;
  background-color: #e74c3c;
  transition: .25s;
  z-index: -1;
}
h2:hover:before {
  width: 100%;
  left: 0;/*change here*/
  right: auto;/*change here*/
}

Và ta được kết quả như mong đợi

# Lưu ý : và ::

Nhiều bạn khi code sẽ thấy có người dùng :before hoặc ::before thì mình note phát là hầu hết các trình duyệt đều hỗ trợ 2 dấu 2 chấm :: hay 1 dấu 2 chấm : cho cú pháp của CSS3 tuy nhiên trên một số trình duyệt cũ như IE8 chẳng hạn thì lại không hỗ trợ 2 dấu 2 chấm ::.

Cho nên nếu dự án bạn code không cần tới tận IE8 thì thoải mái dùng ::before hay ::after ok nhé. Còn làm việc với IE8 thì dùng :before hay :after cho an toàn.

# Tạo ribbon hình tam giác

Tìm hiểu before và after trong CSS

Các bạn nhìn quen không? Chắc hẳn khi làm sẽ gặp nhiều trường hợp như thế này rồi. Và cách tốt nhất đó là dùng :before hoặc :after để làm nó. Để tạo hình tam giác bằng CSS hay hình gì khác thì các bạn có thể tham khảo code tại đây.

Và chúng ta sẽ code HTML và CSS như thế này

<div class="quote"></div>

Ta được kết quả như mong đợi

Việc tạo hình tam giác thì mình đã để link ở trên, còn ở đây mình có set bottom: -10px để nó nằm dưới cùng vì nó có độ cao là 10px của border và mình cho thêm left: 50px để nó cách ra so với bên trái 1 chút cho đẹp và màu border nó sẽ trùng với màu nền của thẻ div mà chúng ta đang làm cho đồng bộ.

# Lời kết

Bài viết đến đây là kết thúc. Hi vọng sẽ giúp được cho các bạn hiểu hơn được đôi chút. Vì mấy cái này cần làm nhiều thì mới biết nhiều, áp dụng được nhiều chứ không thể chỉ hết được vì nó còn rất nhiều cái mới mà trong khi làm chúng ta sẽ gặp phải.

Nếu có gì thắc mắc góp ý thì cứ bình luận bên dưới mình sẽ ráng giải đáp với kiến thức chuyên môn của mình nà. Chúc các bạn một ngày tốt lành.

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

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

Xem thêm các việc làm lập trình CSS hấp dẫn tại TopDev

Import lodash như thế nào mới đúng

Import lodash như thế nào mới đúng

Bài viết được sự cho phép của tác giả Lưu Bình An

Mình đã từng nghe một bạn Principle FE trong công ty phát biểu là

Đã 2020 rồi mà còn xài lodash là sao, lodash đã tối cổ, chả ai xài nữa đâu

Khoan bàn chuyện đúng sai trong phát biểu này, nếu bạn cũng như mình, vẫn đang dùng lodash thì bạn cần biết import nó như thế nào cho đúng

Tại sao cần làm đúng? Vì nếu làm sao vô tình bạn sẽ làm phình cục bundle lên gấp mấy chục lần

  PHPExcel - Import và Export xử lý Excel
  20 trường hợp sử dụng lệnh Docker cho developer

Giờ so sánh 3 cách import

Cách 1

import _ from 'lodash';

Tại sao lại chọn kiểu này? Không cần quan tâm đến user, cảm giác rất quyền lực như có găng tay vô cực, chỉ với _. chúng ta có tất cả mọi thứ.

Điểm yếu, đây là cách tuyệt đối nghiêm cấm, vì gần như là load nguyên cái thư viện

Import lodash như thế nào mới đúng

Tổng 190 KB, Lodash ngốn hết 72.5kb

Cách 2

import { map, each, get, set } from lodash;

Kiểu này ổn, dễ đọc, rất rõ ràng để thấy được những hàm nào cần sử dụng.

Tuy nhiên, nó lại không khác gì với cách 1. Tổng vẫn là 190kb

Cách 3

import map from 'lodash/map';
import each from 'lodash/each';
import get from 'lodash/get';
import set from 'lodash/set';

Kết quả cho thấy đây là cách tiết kiệm nhất, mặc dù thực tế sử dụng cho thấy cách này hơi tốn công anh em dev của chúng ta và nhìn đoạn import có vẻ dài.

Import lodash như thế nào mới đúng

Một số ý kiến cho là dùng lodash-es, một phiên bản theo kiểu ES module sẽ tiết kiệm hơn, đây là kết quả đo được

  1. Cách 1: 256.4 KB
  2. Cách 1: 256.54 KB
  3. Cách 1: 142.39 KB

Như vậy việc dùng lodash-es có vẻ là vô dụng

Dùng lodash babel plugin

Sử dụng lodash babel plugin chúng ta có kết quả 140kb trên tất cả các cách import

Import lodash như thế nào mới đúng

Dùng Lodash webpack plugin

Lodash webpack plugin không biết đã bùa chú kiểu gì mà kết quả cuối cùng rất ngon 121kb cho cách 1, các cách khác sẽ còn bé hơn nữa

Kết luận

Nếu ko siêng bạn nên dùng cách 3, còn nếu siêng bạn setup với babel-plugin-lodash và lodash-webpack-plugin để đạt hiệu quả cao nhất.

Lodash-es thì nên dẹp luôn đừng xài vì nó ko thay đổi gì tích cực cả.

The Correct Way to Import Lodash Libraries

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

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

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

Chiến lược thúc đẩy động lực cho nhân viên

động lực

Động lực thực sự rất quan trọng đối với nhân viên. Động lực được xem là thứ nuôi dưỡng; thúc đẩy nhân viên về nhiều khía cạnh, đặc biệt là khía cạnh tinh thần. Hiệu suất cao, phát huy tiềm năng, khả năng đồng hành và phát triển,… là những yếu tố bị chi phối bởi động lực. Để đảm bảo việc duy trì động lực cho nhân viên, nhà quản lý/lãnh đạo nhân sự cần có những chiến lược cụ thể. Cùng TopDev tìm hiểu xem đâu là chiến lược phù hợp nhất.

Thiếp lập chính sách tiếp cận 

Hãy đảm bảo rằng nhân viên của bạn hiểu rõ về các quy tắc, (dựa trên các cơ sở pháp lý). Đồng thời, việc truyền đạt các chính sách phải diễn ra rõ ràng.

Nhà quản lý/lãnh đạo nhân sự cần xác định rõ nguyên nhân, kết quả và định hướng cho nhân viên những gì họ cần phải làm trong thời gian sắp tới.

  6 xu hướng giúp định hình những nhà lãnh đạo nhân sự tương lai
  Phân tích con người - Chiến lược quan trọng trong ngành Nhân sự năm 2023

động lực

Hơn thế nữa, nhân viên cần nhận thức được những ảnh hưởng phát sinh. Điều đó được phản ánh qua chính cách hành xử; thực hiện các nhiệm vụ của họ. Họ cần biết rằng khi họ đang hoạt động trong một tổ chức, việc giảm bớt cái tôi cá nhân và cân bằng hóa những mong muốn là ưu tiên hàng đầu. Hiểu được như vậy, mỗi nhân viên sẽ có được niềm tin từ doanh nghiệp. Đồng thời, hạn chế được những rủi tro phát sinh và có back-up phù hợp nhất cho tình hình hiện tại. 

Chuẩn hóa quản lý vĩ mô (Macromanagement)

Quản lý vĩ mô là một hình thức được nhiều doanh nghiệp dành sự quan tâm. Chuẩn hóa quản lý vĩ mô sẽ giúp chính các nhân viên kiểm soát tốt các nhiệm vụ cần phải thực hiện. Tự chủ động theo dõi và báo cáo kết quả. Và đảm bảo đúng trách nhiệm với nhiệm vụ được giao. Những quy tắc riêng được đặt ra khiến họ phải thật sự để tâm đến công việc của mình.

Xem thêm: Bí mật giúp tạo động lực và tăng năng suất cho nhân viên!

động lực

Từ cơ sở đó, hình thành ở họ một tư duy độc lập. Đặc biệt là tinh thần luôn cầu tiến. Họ biết rõ mình cần làm gì, làm vì mục đích nào và đâu sẽ là những đích đến xa hơn. Chính điều đó tạo ra động lực thúc đẩy họ luôn phải cố gắng.

Phép loại trừ là yếu tố được các tổ chức thực hiện nhằm gia tăng tính cạnh tranh. Thực tế mục đích của việc này là tạo ra “lực đẩy” tác động tinh thần. Từ đó, nhân viên nhân thấy các thách thức và tự nỗ lực rèn luyện. Thế nhưng, lưu ý mọi thứ cần có giới hạn. Nếu không, định hướng dẫn dắt và mục tiêu thực hiện quản lý vĩ mô sẽ bị ảnh hưởng.  

Khen thưởng luôn là chiến lược tối ưu

Không cần bàn cãi thì ai cũng thừa nhận rằng khen thưởng chính là cách tạo ra động lực tốt nhất dành cho nhân viên. Và tất nhiên, mỗi sự xem xét cần đảm bảo các tiêu. Mỗi quyết định đều dựa trên các hệ giá trị tnương ứng về khả năng, kinh nghiệm, hiệu suất công việc, tiềm năng phát triển,… Việc khen thưởng phải được diễn ra công bằng; đảm bảo tính hợp lý trong thị trường phát triển nghề nghiệp.

Xem thêm: Để thăng tiến, cần phải có chiến lược!

Động lực gắn liền với mục tiêu thăng tiến của mỗi nhân viên. Hãy mở ra nhiêu cơ hội để nhân viên thử sức. Họ sẽ cảm nhận được sự quan tâm nhiều hơn từ tổ chức.  Đó là động lực lớn giúp họ cải thiện hiệu suất công việc. 

Lời kết

Dưới góc nhìn của một chuyên gia, các nhà lãnh đạo nhân sự cần nhìn nhận những thay đổi cũng như mong muốn từ nhân viên. Họ cần một môi trường làm việc thoải mái và đảm bảo những nhu cầu về sự thăng tiến, tính hợp tác,… Rất nhiều thứ cần được nắm bắt qua chính lăng kính của người quản lý. TopDev hi vọng, nhà lãnh đạo sẽ giúp họ tiếp cận với các thách thức tạo ra động lực. Và cho họ niềm tin rằng tổ chức của bạn hoàn hoàn là nơi phù hợp giúp họ gia tăng động lực.


Tuyển Dụng Nhân Tài IT Cùng TopDev
Đăng ký nhận ưu đãi & tư vấn về các giải pháp Tuyển dụng IT & Xây dựng Thương hiệu tuyển dụng ngay!
Hotline: 028.6273.3496 – Email: contact@topdev.vn
Dịch vụ: https://topdev.vn/page/products

Có thể bạn quan tâm

Xem thêm Top các việc làm cho lập trình trên TopDev

Ngôn ngữ Java: Không bao giờ là quá trễ để học thêm về nó

ngôn ngữ java

Tác giả: John Selawsky

Chúng ta thường nghĩ rằng mình quá già để học thêm kiến thức mới hay quá lớn tuổi để nhảy việc. Thật ra tuổi tác chưa bao giờ là giới hạn để ta đạt được thứ mình muốn hay tiếp thu thêm kiến thức, như một ngôn ngữ lập trình mới chẳng hạn?

Tôi đã chứng kiến nhiều người trên 30 tuổi mới bắt đầu học về Java. Sự thật là càng lớn tuổi bạn càng có nhiều kinh nghiệm và khôn ngoan hơn khi tiếp thu, chọn lọc những kiến thức mới. Thêm vào đó, IT là lĩnh vực ít bị tác động bởi tuổi tác vì ngành này quan trọng kinh nghiệm của lập trình viên hơn.

Việc làm Java lương cao cho bạn

Bài viết này sẽ chia sẻ những lý do bạn nên bắt đầu học thêm về ngôn ngữ Java và cũng có thể áp dụng tốt cho việc học các ngôn ngữ lập trình khác.

topdev

Xem thêm Lập trình Java cho những người mới bắt đầu: học Java để làm gì?

Các lý lo nên bắt đầu học thêm về ngôn ngữ Java

Học những điều mới khi lớn tuổi sẽ giúp bạn xử lý công việc tốt hơn

Các nghiên cứu y khoa gần đây của Cesar Quililan đã chứng minh được ảnh hưởng đáng kể của hoạt động não bộ đối với quá trình lão hóa và sức khỏe não bộ. Nghĩa là nếu bạn càng rèn luyện trí não nhiều đầu óc bạn sẽ càng minh mẫn hơn. Nghiên cứu cũng chỉ ra rằng những người ở độ tuổi 60 – 90 đã cải thiện sức khỏe não bộ của họ chỉ bằng cách làm đồ thủ công mỹ nghệ và một số sở thích chỉ vài giờ mỗi ngày. Vậy bạn có thể tưởng tượng xem bộ não của một người 30 tuổi sẽ còn làm được nhiều việc như thế nào?

  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java
  11 mẹo đơn giản để tăng hiệu suất Java cấp tốc

Khi học một ngôn ngữ lập trình mới não bộ sẽ rèn luyện khả năng suy nghĩ và vận dụng đầu óc, từ đó tăng sự tập trung và chú ý của bạn. Một người đàn ông 32 tuổi chia sẻ trên Reddit rằng trước đây anh ấy không hề biết về lập trình hay kỹ năng nào, tuy nhiên hiện tại anh ấy đang học lập trình ở trường đại học. Dù bắt đầu có nhiều khó khăn nhưng giờ đây đầu óc anh ấy đã nhạy bén hơn rất nhiều. Và chẳng ai quan tâm xem anh ấy bao nhiêu tuổi cả!

Có rất nhiều khóa học và tài liệu học trực tuyến – ở đó chẳng ai quan tâm đến tuổi của bạn!

Học trực tuyến không còn là khái niệm mới và thậm chí nhiều người còn cảm thấy nó hiệu quả hơn cả học offline. Ngành IT coi trọng kiến thức và kỹ năng hơn là khả năng thể chất của bạn. Nếu thật sự muốn học hỏi bạn sẽ thành công và đạt được công việc mơ ước rất nhanh.

Xem thêm Cẩm nang tri thức dành cho sinh viên ngành IT

Dưới đây là những nền tảng trực tuyến mà bạn có thể sử dụng để học thêm Java: 

CodeGym – cung cấp khóa học lập trình Java trực tuyến với 80% tiết học thực hành, được thiết kế cho các beginner.

topdev

CodeAcademy – chương trình này cung cấp các kỹ năng mang tính kỹ thuật rất hữu ích trong công việc tương lai của bạn.

ngôn ngữ java

Khi bạn bắt đầu học hay tìm hiểu ngành lập trình, bạn vẫn cần tham khảo thêm khá nhiều các nguồn kiến thức hay kinh nghiệm từ những dev đi trước. Đây là một số trang web cung cấp nhiều kiến thức về ngôn ngữ lập trình Java mà bạn có thể tham khảo:

Java subreddit là nền tảng chia sẻ các giải pháp và kinh nghiệm về các vấn đề liên quan đến Java.

Java world là nền tảng chứa rất nhiều tin tức, blog, chia sẻ của chuyên gia liên quan đến Java.

Programming subreddit là nền tảng cho phép bạn đặt câu hỏi hoặc được giải đáp các thắc mắc liên quan đến việc lập trình.

Java Forum là một diễn đàn quen thuộc của các dev có nhiều chủ đề và được chia thành từng phần để tìm kiếm nhanh hơn.

Java Geek là một chương trình mà bạn có thể tìm thấy những lời giải thích rõ ràng về một trường hợp hoặc một vấn đề cụ thể, ngoài ra nó còn được chia thành các danh mục tương tác với các lĩnh vực công nghệ khác nhau.

CodeGym Help là một cộng đồng dành cho những beginner, nơi họ có thể chia sẻ những khó khăn và được hỗ trợ kịp thời.

Bench Resources là nơi các tập hợp các vấn đề liên quan đến Java.

Ngoài ra còn có các khóa học video trực tuyến trên Coursera hoặc Udemy – đây là những nền tảng bao gồm các khóa học trực tuyến từ các trường đại học ở khắp nơi trên thế giới, dành cho nhiều đối tượng khác nhau.

ngôn ngữ java

Bên cạnh đó, còn có một nguồn kiến thức quan trọng khác mà bạn không nên bỏ qua đó là sách. Bạn có thể tham khảo một số cuốn như:

Head First Java by Kathy Sierra & Bert Bates: Các tác giả của sách này cố gắng truyền tải những kiến ​​thức họ có bằng một ngôn ngữ đơn giản và nội dung trực quan cho người đọc tìm hiểu về Java.

Java: A Beginner’s Guide by Herbert Schildt: mô tả những điều cơ bản của ngôn ngữ lập trình Java theo thứ tự từ dễ đến khó, cho phép người dùng hiểu và đi sâu vào ngôn ngữ Java ngay từ đầu.

Đây chỉ là một ít trong số rất nhiều nguồn khác nhau về ngôn ngữ lập trình Java mà bạn có thể học. Hãy tìm hiểu về nó ngay khi có thể vì chẳng ai quan tâm đến tuổi tác của bạn cả mà họ chỉ quan tâm đến những gì bạn biết mà thôi.

Tuổi tác không liên quan

Tuổi tác chỉ là con số. Nhưng nhiều người lại có suy nghĩ sẽ gắn bó với một công việc cho đến cuối đời. Hãy thay đổi quan điểm này và bắt đầu làm mọi thứ mà bạn muốn, hãy bắt đầu học lập trình nếu bạn muốn trở thành lập trình viên. 

Đừng so sánh với người khác. Bạn và người đó có xuất phát điểm và kinh nghiệm làm việc khác nhau. Thay vào đó, hãy tự so sánh mình của hiện tại với trước đây, nếu chăm chỉ luyện tập bạn sẽ thấy rõ sự tiến bộ của mình.

  "Code dễ đọc" là như thế nào?

Và đừng bao giờ sợ code xấu hay thiếu kinh nghiệm vì dù ở độ tuổi nào chăng nữa chúng ta vẫn mắc lỗi khi mới bắt đầu công việc và sẽ dần cải thiện khi trau dồi kỹ năng nhiều hơn. Các công ty tuyển dụng đều yêu cầu ứng viên có kinh nghiệm ở mức tối thiểu và sẽ cải thiện thêm trong quá trình làm việc. Vì chúng ta không thể học tất cả mọi thứ chỉ trong một lần, thời gian là điều cần thiết để mọi người nâng cao “tay nghề” của mình.

ngôn ngữ java

Học Java cũng giống như học các kỹ năng khác mà thôi

Học Java cũng không khác gì tập đi xe đạp, chỉ là bạn sẽ lo lắng nhiều hơn khi học đi xe đạp ở tuổi trưởng thành. Ở tuổi trưởng thành bạn sẽ còn có nhiều kinh nghiệm hơn khi đối mặt với những khó khăn và biết cách vượt qua nó tốt hơn.

Không thời điểm nào học ngôn ngữ java tốt hơn ngay bây giờ

Đừng trì hoãn những dự định của bạn, hãy bắt tay vào thực hiện ngay khi có thể vì sẽ không bao giờ có thời gian thích hợp hơn ngay bây giờ cả. Bạn sẽ lãng phí thời gian nếu chờ đợi đến lúc thích hợp. Thậm chí khi càng lớn tuổi hơn bạn sẽ càng hoài nghi nhiều hơn với những thứ mình làm. Mạnh mẽ và dám đối mặt sẽ giúp bạn sớm đạt được thành công.

Kết luận 

Không bao giờ là quá muộn để bắt đầu học ngôn ngữ lập trình Java hay bất cứ ngôn ngữ lập trình nào khác. Hãy bắt đầu càng sớm càng tốt vì IT là ngành rất coi trọng kiến thức và kĩ năng. Đủ bản lĩnh sẽ giúp bạn thành công trong công việc lập trình viên này.

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

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

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

Django dễ hơn Flask

Django dễ hơn Flask

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

Django và Flask là hai web-framework phổ biến nhất – thành công nhất của Python. Ngày này, khi nhìn các bảng tuyển dụng, sẽ thường thấy yêu cầu Django để làm web nhưng Flask dần trở thành công cụ quen thuộc của giới làm data. Nếu ai có hỏi “nên học cái nào” thì câu trả lời chuẩn nhất chỉ có một: nên học cả hai.

  11 tip học Python dành cho các “newbie”
  71 trích đoạn code Python cho các vấn đề hàng ngày của bạn

Web framework là gì

Một framework là một bộ thư viện, thường gồm nhiều tính năng phục vụ đưa ra sản phẩm cuối cùng chạm tới người dùng. Ví dụ requests là một library, chỉ cung cấp tính năng HTTP client, hay bs4 chỉ cung cấp tính năng bóc tách/ truy cập dữ liệu HTML, hay sqlalchemy là library giúp truy cập và tương tác với database, thì Flask/Django cung cấp một bộ khung kèm các “thư viện” để làm ra một sản phẩm tới tay người dùng (trang web). Frame trong tiếng Anh có nghĩa là “khung”, framework cung cấp cái khung, lập trình viên điền những thứ mình muốn vào đó, framework sẽ tự lo chạy. Vì vậy khi dùng framework, sẽ có cảm giác như ta không biết nó hoạt động thế nào, chỉ biết là điền đúng những thứ yêu cầu thì nó sẽ hoạt động.

Django là framework đầy đủ (full-fledge), có đủ mọi thứ, nên sẽ càng có thêm cảm giác ta chỉ điền chút xíu là nó tự chạy, mọi thứ đều có khuôn mẫu sẫn rồi. Flask là micro-framework, chỉ có phần khung cơ bản, các phần còn lại cho phép người dùng tùy chọn mà đắp vào, vậy nên có phần dễ hiểu hơn, ít phép màu hơn.

Cũng vì sự khác biệt này, dẫn tới tài liệu trang chủ của 2 framework viết rất khác nhau. Flask vào đời bằng một website dùng 7 dòng code, khiến người dùng rất dễ học, dễ bắt đầu với sự đơn giản này. Còn Django lại dùng ví dụ phức tạp, mặc định người dùng sẽ cần làm thứ “phức tạp” như vậy nên học thế cho quen.

Thế nhưng nếu không dựa vào 2 cái tutorial đấy để đánh giá, liệu Django có phức tạp hơn Flask, hay thậm chí còn đơn giản hơn? Bài nầy sẽ dựa trên 2 yếu tố để so sánh: 1. số khái niệm bạn cần biết 2. số dòng code bạn cần viết.

Bắt đầu.

Cài đặt

Cài đặt Flask

pip install flask

Cài đặt Django

pip install django

Kết quả: hòa, dễ như nhau: Flask 1 - Django 1

Viết một website hello world và hello mình

Flask

Tạo 1 file tên bất kỳ nhưng tốt nhất đặt là hello.py (tuyệt đối không đặt là flask.py do trùng tên flask)

1 from flask import Flask
2 app = Flask("my website")
3
4 @app.route("/")
5 def hello_world():
6    return "Hello world"
7
8 @app.route("/hello/<string:name>")
9 def hello(name):
10    return "Hello {}".format(name)

Chạy, theo hướng dẫn trên trang chủ (nếu dùng Windows vào xem lệnh tương ứng):

$ export FLASK_APP=hello.py
$ flask run
 * Running on http://127.0.0.1:5000/

Điểm ấn tượng nhất ở đây là chỉ có 10 dòng, trong đúng 1 file, mà chạy thành trang web.

Tổng số thao tác phải làm: 3 – tạo 1 file, điền nội dung, gõ lệnh để chạy.

Django

Django không làm web trong 1 file, nó dùng các câu lệnh có sẵn để sinh ra các file, tức ta chỉ phải gõ lệnh, chứ không phải gõ nhiều code. Gõ 3 lệnh sau là chạy luôn trang web:

$ django-admin startproject project1
$ cd project1/
$ ./manage.py startapp hello
$ ./manage.py runserver
Starting development server at http://127.0.0.1:8000/

Ngay lập tức đã có trang web mẫu của Django – thậm chí chưa gõ tí code nào. Để có kết quả giống Flask ở trên, cần sửa 2 file:

File hello/views.py, viết các function tương tự flask:

from django.http import HttpResponse

def hello_world(request):
    return HttpResponse("Hello world")

def hello(request, name):
    return HttpResponse("Hello {}".format(name))

File project1/urls.py thêm 3 dòng:

from hello import views

urlpatterns = [  # có sẵn
    path('admin/', admin.site.urls),  # có sẵn
    path('', views.hello_world, name='hello_world'),
    path('hello/<str:name>', views.hello, name='hello'),
] # có sẵn

Giờ chạy ./manage runserver sẽ có kết quả y hệt Flask.

So sánh thao tác

Tổng số dòng code phải thêm vào Django là 8 – cũng chính bằng số dòng Flask phải viết – không tính dòng trống. Django phải chạy nhiều hơn 2 lệnh – nhưng chỉ cần phải làm khi bắt đầu dự án. Flask viết code trong 1 file, còn Django phải sửa 2 file. ở đây có thể xem như hòa nhau không bên nào hơn/kém quá cả.

So sánh khái niệm

Phần khác nhau chủ đạo giữa Django và Flask là cách ghi URL. Người dùng Flask tạo một Flask object, đặt tên là app, sau đó sử dụng decorator

@app.route("/hello/<string:name>")

để gắn đường dẫn /hello/name cho function ngay dưới nó (function hello). Decorator không phải một khái niệm đơn giản ở đây, mặc dù người dùng có thể cứ nhắm mắt rồi gõ @ theo và hiểu nôm na là gắn đường dẫn cũng được.

Django chọn giải pháp ghép đường dẫn với function thông qua file urls.py, import module views từ thư mục hello/ (tạo lúc chạy “startapp hello”), sau đó gán đường dẫn bằng cách gọi function path:

    path('hello/<str:name>', views.hello, name='hello'),

Dài dòng hơn Flask một chút là phải ghi name="hello", không có / ở đầu URL, và kiểu str thì ghi là str chứ không ghi string như Flask.

Khi mới bắt đầu, khó có thể thấy lý do Django viết riêng file urls.py để làm gì, khi mà flask @ lên đầu rất gọn ghẽ. Thì tới lúc có 20 URL bạn sẽ hiểu tại sao. Làm thế nào để liệt kê tất cả URL trong app của mình? Các URL của Flask rải rác khắc nơi, mỗi cái nằm trên đầu 1 function, nếu như mỗi function dài 50 dòng, thì việc tìm sẽ khá vất vả – hoặc phải dùng chức năng tìm kiếm, hoặc phải có IDE để hỗ trợ. Còn với Django tất cả đều nằm gọn trong urls.py.

Không hiểu tại sao Flask lại chọn string để ám chỉ kiểu string trong Python, vốn viết là str, Django lại ghi thêm điểm ở đây.

Có thể bạn đã biết, rằng không nhất thiết phải dùng @ trong Flask, bởi decorator này chỉ làm đơn giản có 1 việc: giống Django. Thay vì viết hai dòng @app.route trên đầu function, viết hai dòng này SAU khi định nghĩa các function:

app.add_url_rule("/", "hello_world", hello_world)
app.add_url_rule("/hello/<string:name>", "hello", hello)

Đây chính làm điều mà @app.route làm, như mô tả trong tài liệu của nó:

A decorator that is used to register a view function for a given URL rule. This does the same thing as :meth:add_url_rule but is intended for decorator usage::

Chốt: Django gõ nhiều hơn 2 lệnh, sửa thêm 1 file, nhưng sử dụng ít khái niệm cao cấp hơn Flask. Nếu dễ tính, thì cho là hòa, còn không Django dành chiến thắng ở đây.

Tỉ số: 2 - 2

Thêm trang dùng template

Flask

Tạo 1 thư mục tên templates ngay cạnh file hello.py, rồi tạo file index.html chứa code HTML và Jinja2 template.

{% for fw in frameworks %}
  {% if fw|length > 5 %}
    <b>{{ fw }}</b>
  {% else %}
    {{ fw }}
  {% endif %}
{% endfor %}

Code sửa thành

from flask import Flask, render_template
@app.route("/web")
def frameworks():
    return render_template("index.html", frameworks=["Flask", "Django"])

Django

Tạo thư mục tên templates/hello trong thư mục hello, sau đó tạo index.html và nội dung copy y hệt phần template của Flask.

Thêm function sau vào hello/views.py

# chú ý render đã được import sẵn ở file view.py ngay khi tạo app
def frameworks(request):
    return render(request, "hello/index.html", {"frameworks": ["Flask", "Django"]})

Và thêm 1 dòng vào project1/urls.py:

  path('web', views.frameworks, name='frameworks'),

Ngoài ra phải thêm 'hello' vào file project1/settings.py Trong list INSTALLED_APPS

 INSTALLED_APPS = [
     ...,
     'hello',
 ]

Phần này lại hòa, template mặc định của Flask là jinja2 tương đương với Django template, kể cả cú pháp cũng rất giống nhau. Django phải thêm 1 dòng vào file settings.py nhưng việc này cũng chỉ phải làm một lần duy nhất (lẽ ra nên làm luôn sau khi createapp từ đầu).

Django app

Khi chạy lệnh startproject ban đầu, nó sinh ra các file cần thiết cho một dự án Django (urls.pysettings.pymanager.py …, và nó chỉ phải chạy duy nhất 1 lần trong 1 dự án. Với Flask, bạn tạo thư mục bằng tay.

Django đưa ra khái niệm có nhiều app trong một dự án. Flask cũng có khái niệm tương tự, gọi là Blueprint. Nó không cần thiết cho ví dụ 6-10 dòng, nhưng khi làm một website nhiều tính năng thì blueprint là cách tổ chức chính thức của Flask, ngay cả trong bài tutorial của Flask cũng dùng luôn khái niệm này. Như vậy chỉ khác nhau việc học trước hay học sau, chứ không phải Flask thì không dùng tới.

Flask không ép (không hướng dẫn) người dùng cách tổ chức code, khi dự án lớn dần lên, có 3-5000 dòng code, ắt phải sinh ra file mới, phải sắp xếp, tổ chức sao cho hợp lý – mà thế nào là hợp lý thì không phải ai cũng tìm ngay ra cách. Dự án Flask khi rơi vào tay lập trình viên chưa có nhiều kinh nghiệm làm web sẽ dẫn tới code mỗi thứ một nơi, đi tìm cũng thấy mệt. Flask không hướng dẫn người dùng ngay từ đầu, nếu gặp phải người chưa có kinh nghiệm tổ chức, sẽ trở thành vô tổ chức.

Django bắt đầu bằng việc đặt mỗi thứ vào một nơi quy định sẵn, ban đầu có vẻ hơi phiền phức, nhưng sự gọn gàng ngăn nắp sẽ trả lợi ích rõ ràng về sau. Bạn có thể xem 10 dự án Django, cấu trúc đều như nhau, như mẫu của Django, thì 10 dự án Flask mỗi cái một kiểu.

Tỉ số: Flask 2 – Django 3

Thêm Database, thêm tính năng đăng nhập, thêm trang admin

Đến đây, việc của người dùng Django là mở tài liệu ra, đọc phần model, đọc phần admin page rồi làm theo hướng dẫn, đầy đủ hàng trăm tính năng có sẵn, thì người dùng Flask lại phải lo đi tìm:

  • dùng database nào? nếu dùng MySQL thì dùng driver nào?
  • có dùng ORM không? nếu có thì phải học SQLAlchemy, tương đương với học Django ORM
  • dùng SQLAlchemy rồi có phải dùng flask-sqlalchemy không (có).
  • khi đổi schema table (thêm/bớt/sửa cột trong 1 SQL table) thì phải làm thế nào? MigrateDB thì dùng cái gì? (Flask-Migrate / alembic)
  • Viết trang admin (ví dụ website quản lý sinh viên thì đây là trang để thêm/bớt/sửa/xóa sinh viên) thì viết ra sao (có thể dùng flask-admin)
  • Đăng nhập thì làm thế nào? (flask-httpauth)
  • Nhập/validate form thì dùng cái chi? (WTForm)
  • … tiếp tục …

Tỉ số: Flask 2 – Django 4

Kết quả

Hòa.

Hành động của chúng ta

pip install django dùng ngay và luôn thôi.

Kết luận

Bài này không nói Django hoàn hảo, dùng cho mọi trường hợp. Ví dụ nếu website của bạn không dùng database, không cần trang admin (như web của data science) thì Flask nhanh, nhẹ hơn Django nhiều phần. Hay khi bạn biết mình đang làm gì, biết đủ những thư viện để dùng ghép lại xịn hơn cả những gì Django có sẵn, thì Flask là lựa chọn tuyệt hảo. Flask không phải đồ chơi, phần core của Uber đã từng được viết bằng FlaskAirflow – công cụ không thể thiếu trong các hệ thống data cũng chính là một sản phẩm dùng Flask. Vậy nên, hãy học cả 2, nhé. Và nhớ là, Django không hề khó như bạn tưởng.

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

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

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

Lập trình đa luồng trong Java (Java Multi-threading)

Lập trình đa luồng trong Java (Java Multi-threading)

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

Lập trình đa luồng (Multi-threading) là một kỹ thuật trong lập trình mà một ứng dụng có thể thực thi nhiều phần công việc (luồng – thread) một cách đồng thời. Trong Java, đa luồng là một tính năng mạnh mẽ và quan trọng, giúp các ứng dụng có thể tận dụng tối đa tài nguyên CPU và giảm thời gian xử lý bằng cách thực thi nhiều tác vụ cùng lúc.

Java cung cấp hỗ trợ sẵn có cho lập trình đa luồng thông qua lớp Thread và giao diện Runnable. Việc sử dụng đa luồng trong Java giúp tăng cường hiệu suất và cải thiện tính đáp ứng (responsiveness) của ứng dụng, đặc biệt trong các ứng dụng yêu cầu xử lý song song hoặc thời gian thực.

Khái niệm thread trong Java

Thread là gì?

Thread (luồng) về cơ bản là một tiến trình con (sub-process). Một đơn vị xử lý nhỏ nhất của máy tính có thể thực hiện một công việc riêng biệt. Trong Java, các luồng được quản lý bởi máy ảo Java (JVM).

Multi-thread là gì?

Multi-thread (đa luồng) là một tiến trình thực hiện nhiều luồng đồng thời. Một ứng dụng Java ngoài luồng chính có thể có các luồng khác thực thi đồng thời làm ứng dụng chạy nhanh và hiệu quả hơn.

VD: Trình duyệt web hay các chương trình chơi nhạc là 1 ví dụ điển hình về đa luồng.

+ Khi duyệt 1 trang web, có rất nhiều hình ảnh, CSS, javascript… được tải đồng thời bởi các luồng khác nhau.

+ Khi play nhạc, chúng ta vẫn có thể tương tác được với nút điều khiển như: Play, pause, next, back … vì luồng phát nhạc là luồng riêng biệt với luồng tiếp nhận tương tác của người dùng.

Tuyển dụng Java lương cao up to 2000USD

Đa nhiệm (multitasking)

Multitasking: Là khả năng chạy đồng thời một hoặc nhiều chương trình cùng một lúc trên một hệ điều hành. Hệ điều hành quản lý việc này và sắp xếp lịch phù hợp cho các chương trình đó. Ví dụ, trên hệ điều hành Windows chúng ta có làm việc đồng thời với các chương trình khác nhau như: Microsoft Word, Excel, Media Player, …

Chúng ta sử dụng đa nhiệm để tận dụng tính năng của CPU.

Đa nhiệm có thể đạt được bằng hai cách:

  1. Đa nhiệm dựa trên đơn tiến trình (Process) – Đa tiến trình (Multiprocessing).
    • Mỗi tiến trình có địa chỉ riêng trong bộ nhớ, tức là mỗi tiến trình phân bổ vùng nhớ riêng biệt.
    • Tiến trình là nặng.
    • Sự giao tiếp giữa các tiến trình có chi phí cao.
    • Chuyển đổi từ tiến trình này sang tiến trình khác đòi hỏi thời gian để đăng ký việc lưu và tải các bản đồ bộ nhớ, các danh sách cập nhật, …
  2. Đa nhiệm dựa trên luồng (Thread) – Đa luồng (MultiThreading).
    • Các luồng chia sẻ không gian địa chỉ ô nhớ giống nhau.
    • Luồng là nhẹ.
    • Sự giao tiếp giữa các luồng có chi phí thấp.

Đa tiến trình (multiprocessing) và đa luồng (multithreading) cả hai được sử dụng để tạo ra hệ thống đa nhiệm (multitasking). Nhưng chúng ta sử dụng đa luồng nhiều hơn đa tiến trình bởi vì các luồng chia sẻ một vùng bộ nhớ chung. Chúng không phân bổ vùng bộ nhớ riêng biệt để tiết kiệm bộ nhớ, và chuyển đổi ngữ cảnh giữa các luồng mất ít thời gian hơn tiến trình.

  10 Java Web Framework tốt nhất
  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java

Ưu điểm của Multi-thread Java

Đầu tiên, đa luồng giúp tăng hiệu suất của ứng dụng bằng cách chạy song song nhiều tác vụ. Thay vì thực hiện tuần tự, các tác vụ có thể xử lý đồng thời, tận dụng tối đa CPU, đặc biệt trong môi trường đa lõi (multi-core). Mỗi luồng có thể dùng chung và chia sẻ nguồn tài nguyên trong quá trình chạy, nhưng có thể thực hiện một cách độc lập.

Đa luồng còn giúp cải thiện tính đáp ứng của ứng dụng. Trong các ứng dụng giao diện người dùng (UI), việc sử dụng đa luồng tránh tình trạng ứng dụng bị “treo” khi thực hiện các tác vụ dài, từ đó cải thiện trải nghiệm người dùng. Điều này rất quan trọng khi cần thực hiện các tác vụ nặng như tải dữ liệu hoặc xử lý I/O.

Ngoài ra, đa luồng hỗ trợ xử lý đồng thời nhiều yêu cầu. Đối với các hệ thống máy chủ hoặc ứng dụng web, đa luồng cho phép xử lý nhiều yêu cầu của người dùng cùng lúc, giảm thời gian chờ đợi và tăng khả năng phục vụ. Các luồng cũng chia sẻ tài nguyên bộ nhớ, giúp tiết kiệm tài nguyên so với việc tạo nhiều tiến trình riêng biệt.

Nhược điểm của đa luồng trong Java

Tuy nhiên, lập trình đa luồng có một số nhược điểm lớn. Độ phức tạp của nó là một trong những thách thức lớn nhất. Khi làm việc với nhiều luồng, lập trình viên phải xử lý đồng bộ hóa, phối hợp luồng và tránh các lỗi như deadlock (tình trạng chết) hoặc race condition (điều kiện cạnh tranh). Điều này đòi hỏi kỹ năng cao và kinh nghiệm.

Đồng bộ hóa dữ liệu giữa các luồng cũng là một vấn đề quan trọng. Khi nhiều luồng truy cập chung một tài nguyên, nếu không đồng bộ đúng cách, dữ liệu có thể bị thay đổi ngoài ý muốn, dẫn đến lỗi. Đồng bộ hóa giúp ngăn chặn tình trạng này, nhưng nó làm giảm hiệu suất vì các luồng phải chờ nhau. Đồng thời, nếu đồng bộ không chính xác, có thể gây ra tình trạng deadlock, khi các luồng bị khóa lẫn nhau và không thể tiếp tục thực thi.

Deadlock (Khoá chết) là gì? Deadlock xảy ra khi 2 tiến trình đợi nhau hoàn thành, trước khi chạy. Kết quả của quá trình là cả 2 tiến trình không bao giờ kết thúc

Một vấn đề khác là race condition, khi nhiều luồng cùng thao tác với một tài nguyên mà không kiểm soát đúng cách. Điều này có thể dẫn đến dữ liệu không chính xác hoặc bị hỏng.

Cuối cùng, lập trình đa luồng còn dẫn đến tăng sử dụng tài nguyên. Mỗi luồng yêu cầu bộ nhớ và CPU riêng, và khi có quá nhiều luồng, việc chuyển đổi giữa các luồng (context switching) làm giảm hiệu suất tổng thể của hệ thống.

Vòng đời (các trạng thái) của một Thread trong Java

Lập trình đa luồng trong Java (Java Multi-threading)

Vòng đời của thread trong java được kiểm soát bởi JVM. Java định nghĩa các trạng thái của luồng trong các thuộc tính static của lớp Thread.State:

  • NEW : Đây là trạng thái khi luồng vừa được khởi tạo bằng phương thức khởi tạo của lớp Thread nhưng chưa được start(). Ở trạng thái này, luồng được tạo ra nhưng chưa được cấp phát tài nguyên và cũng chưa chạy. Nếu luồng đang ở trạng thái này mà ta gọi các phương thức ép buộc stop,resume,suspend … sẽ là nguyên nhân sảy ra ngoại lệ IllegalThreadStateException .
  • RUNNABLE : Sau khi gọi phương thức start() thì luồng test đã được cấp phát tài nguyên và các lịch điều phối CPU cho luồng test cũng bắt đầu có hiệu lực. Ở đây, chúng ta dùng trạng thái là Runnable chứ không phải Running, vì luồng không thực sự luôn chạy mà tùy vào hệ thống mà có sự điều phối CPU khác nhau.
  • WAITING : Thread chờ không giới hạn cho đến khi một luồng khác đánh thức nó.
  • TIMED_WAITING : Thread chờ trong một thời gian nhất định, hoặc là có một luồng khác đánh thức nó.
  • BLOCKED: Đây là 1 dạng của trạng thái “Not Runnable”, là trạng thái khi Thread vẫn còn sống, nhưng hiện tại không được chọn để chạy. Thread chờ một monitor để unlock một đối tượng mà nó cần.
  • TERMINATED : Một thread ở trong trạng thái terminated hoặc dead khi phương thức run() của nó bị thoát.

Cách tạo thread trong Java

Trong java ta có thể tạo ra một luồng bằng một trong hai cách sau: tạo 1 đối tượng của lớp được extend từ class Thread hoặc implements từ interface Runnable.

Tạo luồng bằng cách extend từ lớp Thread

Để tạo luồng bằng cách tạo lớp kế thừa từ lớp Thread, ta phải làm các công việc sau :

  1. Khai báo 1 lớp mới kế thừa từ lớp Thread
  2. Override lại phương thức run ở lớp này, những gì trong phương thức run sẽ được thực thi khi luồng bắt đầu chạy. Sau khi luồng chạy xong tất cả các câu lệnh trong phương thức run thì luồng cũng tự hủy.
  3. Tạo 1 thể hiện (hay 1 đối tượng) của lớp ta vừa khai báo.
  4. Sau đó gọi phương thức start() của đối tượng này để bắt đầu thực thi luồng.
package com.gpcoder.simple;

public class TheadSimple extends Thread {
    public void run() {
        System.out.println("thread is running...");
    }

    public static void main(String args[]) {
        TheadSimple t1 = new TheadSimple();
        t1.start();
    }
}

Lưu ý :

  • Tuy ta khai báo những công việc cần làm của luồng trong phương thức run() nhưng khi thực thi luồng ta phải gọi phương thức start(). Vì đây là phương thức đặc biệt mà java xây dựng sẵn trong lớp Thread, phương thức này sẽ cấp phát tài nguyên cho luồng mới rồi chạy phương thức run() ở luồng này. Vì vậy, nếu ta gọi phương thức run() mà không gọi start() thì cũng tương đương với việc gọi 1 phương thức của 1 đối tượng bình thường và phương thức vẫn chạy trên luồng mà gọi phương thức chứ không chạy ở luồng mới tạo ra, nên vẫn chỉ có 1 luồng chính làm việc chứ ứng dụng vẫn không phải là đa luồng.
  • Sau khi start một thread, nó không bao giờ có thể được start lại. Nếu bạn làm như vậy, một ngoại lệ IllegalThreadStateException sẽ xảy ra.

Tạo luồng bằng cách implement từ Interface Runnable

Để tạo luồng bằng cách hiện thực từ Interface Runnable, ta phải làm các công việc sau :

  1. Khai báo 1 lớp mới implements từ Interface Runnable
  2. Hiện thực phương thức run() ở lớp này, những gì trong phương thức run() sẽ được thực thi khi luồng bắt đầu chạy. Sau khi luồng chạy xong tất cả các câu lệnh trong phương thức run thì luồng cũng tự hủy.
  3. Tạo 1 thể hiện (hay 1 đối tượng) của lớp ta vừa khai báo. (VD : Tên đối tượng là r1)
  4. Tạo 1 thể hiện của lớp Thread bằng phương thức khởi tạo : Thread(Runnable target)
    • Runnable target: Là 1 đối tượng thuốc lớp được implements từ giao diện Runnable.
    • Ví dụ: Thread t1 = new Thread(r1);
  5. Gọi phương thức start() của đối tượng t1.
package com.gpcoder.simple;

public class RunnableSimple implements Runnable {
    public void run() {
        System.out.println("thread is running...");
    }

    public static void main(String args[]) {
        RunnableSimple runable = new RunnableSimple();
        Thread t1 = new Thread(runable);
        t1.start();
    }
}

Khi nào implements từ interface Runnable?

+ Cách hay được sử dụng và được yêu thích là dùng interface Runnable, bởi vì nó không yêu cầu phải tạo một lớp kế thừa từ lớp Thread. Trong trường hợp ứng dụng thiết kế yêu cầu sử dụng đa kế thừa, chỉ có interface mới có thể giúp giải quyết vấn đề. Ngoài ra, Thread Pool rất hiểu quả và có thể được cài đặt, sử dụng rất hơn giản.
+ Trong trường hợp còn lại ta có thể kế thừa từ lớp Thread.

Ví dụ minh họa sử dụng đa luồng

Ví dụ Tạo luồng bằng cách extend từ class Thread

Tạo luồng extend từ class Thead

package com.gpcoder.flow;

public class ThreadDemo extends Thread {
    private Thread t;
    private String threadName;

    ThreadDemo(String name) {
        threadName = name;
        System.out.println("Creating " + threadName);
    }

    @Override
    public void run() {
        System.out.println("Running " + threadName);
        try {
            for (int i = 4; i > 0; i--) {
                System.out.println("Thread: " + threadName + ", " + i);
                // Let the thread sleep for a while.
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("Thread " + threadName + " interrupted.");
        }
        System.out.println("Thread " + threadName + " exiting.");
    }

    public void start() {
        System.out.println("Starting " + threadName);
        if (t == null) {
            t = new Thread(this, threadName);
            t.start();
        }
    }

}

Chương trình sử dụng đa luồng:

package com.gpcoder.flow;

public class ThreadDemoTest {
    public static void main(String args[]) {
        System.out.println("Main thread running... ");

        ThreadDemo T1 = new ThreadDemo("Thread-1-HR-Database");
        T1.start();

        ThreadDemo T2 = new ThreadDemo("Thread-2-Send-Email");
        T2.start();

        System.out.println("==> Main thread stopped!!! ");
    }
}

Kết quả thực thi chương trình trên:

Main thread running...
Creating Thread-1-HR-Database
Starting Thread-1-HR-Database
Creating Thread-2-Send-Email
Starting Thread-2-Send-Email
==> Main thread stopped!!!
Running Thread-1-HR-Database
Running Thread-2-Send-Email
Thread: Thread-2-Send-Email, 4
Thread: Thread-1-HR-Database, 4
Thread: Thread-1-HR-Database, 3
Thread: Thread-2-Send-Email, 3
Thread: Thread-2-Send-Email, 2
Thread: Thread-1-HR-Database, 2
Thread: Thread-2-Send-Email, 1
Thread: Thread-1-HR-Database, 1
Thread Thread-2-Send-Email exiting.
Thread Thread-1-HR-Database exiting.

Kết quả chương trình trên được giải thích thông qua hình bên dưới:

Lập trình đa luồng trong Java (Java Multi-threading)

Ví dụ Tạo luồng bằng cách implement từ Interface Runnable

Tạo luồng implement từ Interface Runnable

package com.gpcoder.flow;

class RunnableDemo implements Runnable {
    private Thread t;
    private String threadName;

    RunnableDemo(String name) {
        threadName = name;
        System.out.println("Creating " + threadName);
    }

    @Override
    public void run() {
        System.out.println("Running " + threadName);
        try {
            for (int i = 4; i > 0; i--) {
                System.out.println("Thread: " + threadName + ", " + i);
                // Let the thread sleep for a while.
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("Thread " + threadName + " interrupted.");
        }
        System.out.println("Thread " + threadName + " exiting.");
    }

    public void start() {
        System.out.println("Starting " + threadName);
        if (t == null) {
            t = new Thread(this, threadName);
            t.start();
        }
    }

}

Chương trình sử dụng đa luồng:

package com.gpcoder.flow;

public class RunnableDemoTest {
    public static void main(String args[]) {
        System.out.println("Main thread running... ");

        RunnableDemo R1 = new RunnableDemo("Thread-1-HR-Database");
        R1.start();

        RunnableDemo R2 = new RunnableDemo("Thread-2-Send-Email");
        R2.start();

        System.out.println("==> Main thread stopped!!! ");
    }
}

Kết quả thực thi chương trình trên:

Main thread running...
Creating Thread-1-HR-Database
Starting Thread-1-HR-Database
Creating Thread-2-Send-Email
Starting Thread-2-Send-Email
==> Main thread stopped!!!
Running Thread-1-HR-Database
Running Thread-2-Send-Email
Thread: Thread-1-HR-Database, 4
Thread: Thread-2-Send-Email, 4
Thread: Thread-1-HR-Database, 3
Thread: Thread-2-Send-Email, 3
Thread: Thread-1-HR-Database, 2
Thread: Thread-2-Send-Email, 2
Thread: Thread-1-HR-Database, 1
Thread: Thread-2-Send-Email, 1
Thread Thread-1-HR-Database exiting.
Thread Thread-2-Send-Email exiting.

Kết quả chương trình trên được giải thích thông qua hình bên dưới:

Lập trình đa luồng trong Java (Java Multi-threading)

Các phương thức của lớp Thread thường hay sử dụng

  • suspend() : Đây là phương thức làm tạm dừng hoạt động của 1 luồng nào đó bằng các ngưng cung cấp CPU cho luồng này. Để cung cấp lại CPU cho luồng ta sử dụng phương thức resume(). Cần lưu ý 1 điều là ta không thể dừng ngay hoạt động của luồng bằng phương thức này. Phương thức suspend() không dừng ngay tức thì hoạt động của luồng mà sau khi luồng này trả CPU về cho hệ điều hành thì không cấp CPU cho luồng nữa.
  • resume() : Đây là phương thức làm cho luồng chạy lại khi luồng bị dừng do phương thức suspend() bên trên. Phương thức này sẽ đưa luồng vào lại lịch điều phối CPU để luồng được cấp CPU chạy lại bình thường.
  • stop() : Luồng này sẽ kết thúc phương thức run() bằng cách ném ra 1 ngoại lệ ThreadDeath, điều này cũng sẽ làm luồng kết thúc 1 cách ép buộc. Nếu giả sử, trước khi gọi stop() mà luồng đang nắm giữa 1 đối tượng nào đó hoặc 1 tài nguyên nào đó mà luồng khác đang chờ thì có thể dẫn tới việc sảy ra deadlock.
  • destroy() : dừng hẳn luồng.
  • isAlive() : Phương thức này kiểm tra xem luồng còn active hay không. Phương thức sẽ trả về true nếu luồng đã được start() và chưa rơi vào trạng thái dead. Nếu phương thức trả về false thì luồng đang ở trạng thái “New Thread” hoặc là đang ở trạng thái “Dead”
  • yeild() : Hệ điều hành đa nhiệm sẽ phân phối CPU cho các tiến trình, các luồng theo vòng xoay. Mỗi luồng sẽ được cấp CPU trong 1 khoảng thời gian nhất định, sau đó trả lại CPU cho hệ điều hành (HĐH), HĐH sẽ cấp CPU cho luồng khác. Các luồng sẽ nằm chờ trong hàng đợi Ready để nhận CPU theo thứ tự. Java có cung cấp cho chúng ta 1 phương thức khá đặc biệt là yeild(), khi gọi phương thức này luồng sẽ bị ngừng cấp CPU và nhường cho luồng tiếp theo trong hàng chờ Ready. Luồng không phải ngưng cấp CPU như suspend mà chỉ ngưng cấp trong lần nhận CPU đó mà thôi.
  • sleep(long) : tạm dừng luồng trong một khoảng thời gian millisecond.
  • join() : thông báo rằng hãy chờ thread này hoàn thành rồi thread cha mới được tiếp tục chạy.
  • join(long) : Thread cha cần phải đợi millisecond mới được tiếp tục chạy, kể từ lúc gọi join(long). Nếu tham số millis = 0 nghĩa là đợi cho tới khi luồng này kết thúc.
  • getName() : Trả về tên của thread.
  • setName(String name) : Thay đổi tên của thread.
  • getId() : Trả về id của thread.
  • getState(): trả về trạng thái của thread.
  • currentThread() : Trả về tham chiếu của thread đang được thi hành.
  • getPriority() : Trả về mức độ ưu tiên của thread.
  • setPriority(int) : Thay đổi mức độ ưu tiên của thread.
  • isDaemon() : Kiểm tra nếu thread là một luồng Daemon.
  • setDaemon(boolean): xác định thread là một luồng Daemon hay không.
  • interrupt() : làm gián đoạn một luồng trong java. Nếu thread nằm trong trạng thái sleep hoặc wait, nghĩa là sleep() hoặc wait() được gọi ra. Việc gọi phương thức interrupt() trên thread đó sẽ phá vỡ trạng thái sleep hoặc wait và ném ra ngoại lệ InterruptedException. Nếu thread không ở trong trạng thái sleep hoặc wait, việc gọi phương thức interrupt() thực hiện hành vi bình thường và không làm gián đoạn thread nhưng đặt cờ interrupt thành true.
  • isInterrupted() : kiểm tra nếu thread đã bị ngắt.
  • interrupted() : kiểm tra nếu thread hiện tại đã bị ngắt.

Một số thông tin liên quan đến luồng

Định danh của luồng (ThreadId)

ThreadId là định danh của luồng, nó dùng để phân biệt với các luồng khác cùng tiến trình hoặc cùng tập luồng. Đây là thông số mà máy ảo java tự tạo ra khi ta tạo luồng nên ta không thể sửa đổi cũng như áp đặt thông số này khi tạo luồng. Nhưng ta có thể lấy được nó thông qua phương thức getId() của lớp Thread

Tên của luồng (ThreadName)

ThreadName là tên của luồng, đây là thuộc tính mà ta có thể đặt hoặc không đặt cho luồng. Nếu ta không đặt cho luồng thì máy ảo java sẽ tự đặt với quy tắc sau: “Thread-” + Thứ tự luồng được tạo ra, bắt đầu từ 0.

Độ ưu tiên của luồng (Priority)

Như đã nói ở phần trước, mỗi luồng có 1 độ ưu tiên nhất định. Đây sẽ là thông số quyết định mức ưu tiên khi cấp phát CPU cho các luồng.

Trong java, đế đặt độ ưu tiên cho 1 luồng ta dùng phương thức: void setPriority(int newPriority)

  • int newPriority : Là giá trị từ 1 đến 10.

Java có định nghĩa sẵn 3 mức ưu tiên chuẩn như sau:

  • Thread.MIN_PRIORITY (giá trị 01)
  • hread.NORM_PRIORITY (giá trị 05)
  • Thread.MAX_PRIORITY (giá trị 10)

Để lấy độ ưu tiên của 1 luồng, ta dùng phương thức: int getPriority()

Ví dụ minh họa

WorkingThread.java

package com.gpcoder.info;

public class WorkingThread extends Thread {
    public WorkingThread(String name) {
        super(name);
    }

    public void run() {
        for (int i = 0; i &lt; 5; i++) {
            System.out.printf("Luồng: %s có độ ưu tiên là %d \n", getName(), getPriority());
        }
    }
}

ThreadInfoExample.java

package com.gpcoder.info;

public class ThreadInfoExample {

    public static void main(String[] args) {
        Thread t1 = new WorkingThread("Luồng 1");
        Thread t2 = new WorkingThread("Luồng 2");
        Thread t3 = new WorkingThread("Luồng 3");

        System.out.println("ID luồng 1: " + t1.getId());
        System.out.println("ID luồng 2: " + t2.getId());
        System.out.println("ID luồng 3: " + t3.getId());

        t1.setPriority(1);
        t2.setPriority(5);
        t3.setPriority(10);

        t1.start();
        t2.start();
        t3.start();
    }

}

Kết quả thực thi chương trình trên:

ID luồng 1: 10
ID luồng 2: 11
ID luồng 3: 12
Luồng: Luồng 2 có độ ưu tiên là 5
Luồng: Luồng 2 có độ ưu tiên là 5
Luồng: Luồng 2 có độ ưu tiên là 5
Luồng: Luồng 2 có độ ưu tiên là 5
Luồng: Luồng 2 có độ ưu tiên là 5
Luồng: Luồng 1 có độ ưu tiên là 1
Luồng: Luồng 3 có độ ưu tiên là 10
Luồng: Luồng 3 có độ ưu tiên là 10
Luồng: Luồng 3 có độ ưu tiên là 10
Luồng: Luồng 3 có độ ưu tiên là 10
Luồng: Luồng 3 có độ ưu tiên là 10
Luồng: Luồng 1 có độ ưu tiên là 1
Luồng: Luồng 1 có độ ưu tiên là 1
Luồng: Luồng 1 có độ ưu tiên là 1
Luồng: Luồng 1 có độ ưu tiên là 1

Sử dụng phương thức sleep()

Phương thức sleep() của lớp Thread được sử dụng để tạm ngừng một thread cho một khoảng thời gian nhất định.

Ví dụ chương trình in ra số từ 1 – 5, tạm ngừng 500 ms trước khi in chữ số tiếp theo.

package com.gpcoder.sleep;

public class SleepMethodExample extends Thread {

    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println(i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String args[]) {
        SleepMethodExample t1 = new SleepMethodExample();
        t1.start();
    }

}

Sử dụng join() và join(long)

join() : thông báo rằng hãy chờ thread này hoàn thành rồi thread cha mới được tiếp tục chạy.

Ví dụ:

package com.gpcoder.join;

public class UsingJoinMethod extends Thread {

    public UsingJoinMethod(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(getName());
        for (int i = 1; i <= 5; i++) {
            try {
                System.out.print(i + " ");
                Thread.sleep(300);
            } catch (InterruptedException ie) {
                System.out.println(ie.toString());
            }
        }
        System.out.println();
    }

    public static void main(String[] args) throws InterruptedException {
        UsingJoinMethod t1 = new UsingJoinMethod("Thread 1");
        UsingJoinMethod t2 = new UsingJoinMethod("Thread 2");
        t1.start();
        t1.join();
        t2.start();
        System.out.println("Main Thread Finished");
    }
}

Thực thi chương trình trên:

Thread 1
1 2 3 4 5
Main Thread Finished
Thread 2
1 2 3 4 5

join(long) : Thread cha cần phải đợi millisecond mới được tiếp tục chạy, kể từ lúc gọi join(long). Nếu tham số millis = 0 nghĩa là đợi cho tới khi luồng này kết thúc.

package com.gpcoder.join;

public class UsingJoinMethod2 extends Thread {

    public UsingJoinMethod2(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(getName());
        for (int i = 1; i <= 5; i++) {
            try {
                System.out.print(i + " ");
                Thread.sleep(300);
            } catch (InterruptedException ie) {
                System.out.println(ie.toString());
            }
        }
        System.out.println();
    }

    public static void main(String[] args) throws InterruptedException {
        UsingJoinMethod2 t1 = new UsingJoinMethod2("Thread 1");
        UsingJoinMethod2 t2 = new UsingJoinMethod2("Thread 2");
        t1.start();

        // Main Thread phải chờ 450ms mới được tiếp tục chạy.
        // Không nhất thiết phải chờ Thread t1 kết thúc
        t1.join(450);

        t2.start();
        System.out.println("Main Thread Finished");
    }
}

Thực thi chương trình trên:

Thread 1
1 2 Main Thread Finished
Thread 2
1 3 2 4 3 5 4
5

Xử lý ngoại lệ cho Thread

Phương thức Thread.setDefaultUncaughtExceptionHandler() thiết lập mặc định xử lý khi luồng đột ngột chấm dứt do một ngoại lệ xảy ra mà không có xử lý khác đã được xác định cho luồng đó.

Ví dụ:

package com.gpcoder.exception;

import java.util.Random;

public class WorkingThread implements Runnable {

    @Override
    public void run() {
        while (true) {
            processSomething();
        }
    }

    private void processSomething() {
        try {
            System.out.println("Processing working thread");
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Random r = new Random();
        int i = r.nextInt(100);
        if (i > 70) {
            throw new RuntimeException("Simulate an exception was not handled in the thread");
        }
    }

}

Chương trình minh họa xử lý Thread Exception

package com.gpcoder.exception;

public class ThreadExceptionDemo {

    public static void main(String[] args) {
        System.out.println("==> Main thread running...");

        Thread thread = new Thread(new WorkingThread());
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("#Thread: " + t);
                System.out.println("#Thread exception message: " + e.getMessage());
            }
        });

        thread.start();
        System.out.println("==> Main thread end!!!");
    }
}

Thực thi chương trình trên:

==> Main thread running...
==> Main thread end!!!
Processing working thread
Processing working thread
Processing working thread
Processing working thread
Processing working thread
Processing working thread
#Thread: Thread[Thread-0,5,main]
#Thread exception message: Have a problem...

Trên đây là những kiến thức cơ bản về luồng (thread) và đa luồng (Multi-thread) trong Java. Chúng ta sẽ tiếp tục tìm hiểu về các vấn đề khác của đa luồng trong Java ở các bài viết tiếp theo. Cám ơn các bạn đã quan tâm và theo dõi bài viết.

Tài liệu tham khảo:

  • https://docs.oracle.com/javase/tutorial/essential/concurrency/
  • https://www.javatpoint.com/multithreading-in-java
  • https://o7planning.org/vi/10269/huong-dan-lap-trinh-da-luong-trong-java

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

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

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

Tại sao lại có rất nhiều ngôn ngữ lập trình cùng tồn tại?

Tại sao lại có nhiều ngôn ngữ lập trình cùng tồn tại như vậy?

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

Khi nói đến việc chọn một ngôn ngữ lập trình để học, bạn hẳn sẽ đau đầu bởi số lượng không thể đo đếm được của chúng. Đó là chưa nói đến chuyện mỗi ngôn ngữ lập trình lại có những ứng dụng khác nhau trong đời sống công nghệ.

Chức năng chính của một chương trình máy tính là giải quyết một vấn đề bằng một bộ các tập lệnh (hay mã lệnh). Tuy nhiên, nếu mọi chương trình đều có thể giải quyết các vấn đề, thì tại sao chúng ta lại cần đến quá nhiều chương trình như vậy? Liệu một chương trình có thể làm được mọi thứ hay không? Để trả lời câu hỏi này, hãy cùng tìm hiểu về cách một chương trình máy tính được thực thi.

  5 ngôn ngữ lập trình “khó chịu” nhất thế giới

Phần cứng đảm nhiệm việc tính toán cho chương trình

Hầu như mọi quá trình tính toán dù dưới bất kỳ hình thức nào (với một số ít ngoại lệ) đều được thực hiện trong Bộ xử lý trung tâm (CPU). CPU hiện đại mà chúng ta sử dụng ngày nay có chứa nhiều thành phần vi điện tử.  CPU có thể được chia ra thành nhiều đơn vị tính toán nhỏ hơn, gọi là Logical Transistor Gates, hay đơn giản hơn là logic gates (cổng logic). Chức năng chính của cổng logic là thực hiện ba toán tử chính: AND, OR và NOT.

Tại sao lại có rất nhiều ngôn ngữ lập trình cùng tồn tại?

Những toán tử logic nói trên hoạt động trên một hệ thống số là một nhị phân, vốn hoạt động trên một hệ thống số gồm các số 0 và 1. Số 0 báo hiệu không có dòng điện chạy qua bóng bán dẫn, và số 1 báo hiệu có một dòng điện chạy qua bóng bán dẫn.

Điều phi thường nhất ở đây là, chỉ cần kết hợp những toán tử logic nói trên với nhị phân, bạn sẽ có thể diễn tả tất cả các logic chúng ta từng biết, bao gồm các phép toán số học, số nguyên, và gần như mọi thứ khác bạn có thể hình dung ra. Một CPU hiện đại ngày nay có một thứ gọi là vi mã được cài đặt sẵn bên trong. Một vi mã chứa một bộ các tập lệnh cơ bản được dùng để thực hiện các tác vụ phức tạp hơn, gọi là mã máy.

Các cấp độ của phần mềm dùng để thực thi mã lệnh

Ở trên, chúng ta đã biết phần cứng đằng sau quá trình thực thi mã máy. Tiếp theo, hãy nói về các cấp độ của phần mềm cần thiết cho việc thực thi của phần mềm. Chương trình đầu tiên cần đến là Asembler (trình dịch hợp ngữ), có chức năng chuyển đổi ngôn ngữ asembly (hợp ngữ) thành mã máy. Một ngôn ngữ cấp độ assembly là một ngôn ngữ cấp thấp, đóng vai trò như một chương trình trung gian giữa một ngôn ngữ lập trình bậc cao (Python, C++, Java) và mã máy. Biểu đồ bên dưới sẽ cho thấy kiến trúc của bất kỳ phần mềm nào:

Tại sao lại có rất nhiều ngôn ngữ lập trình cùng tồn tại?

Chương trình quan trọng tiếp theo là Compiler (trình biên dịch). Compiler lấy ngôn ngữ bậc cao và chuyển nó thành hợp ngữ, và đôi lúc thành mã máy nữa. Chương trình cuối cùng (hay gói) gắn kết mọi thứ lại cùng nhau là hệ điều hành. Hệ điều hành về cơ bản là một chương trình khởi động khi máy tính khởi động và chạy cho đến khi máy tính tắt đi. Hệ điều hành còn đảm nhiệm việc quản lý các tác vụ phức tạp, như quản lý tập tin, quản lý đầu vào và đầu ra. Hệ điều hành hoạt động liên tục để mỗi khi bạn muốn thực thi một chương trình, bạn không phải gọi nó lên hết lần này đến lần khác. Nó còn giúp quá trình tương tác với các chức năng người dùng trở nên trực quan hơn, thay vì buộc bạn phải giao tiếp với máy tính dưới dạng những con số 0 và 1.

Một ngôn ngữ lập trình không thể đáp ứng được mọi nhu cầu

Như vậy, mọi ngôn ngữ lập trình dù khác nhau vẫn được thực thi theo một dạng giống nhau. Một chương trình chắc hẳn phải đáp ứng được mọi nhu cầu, đúng chứ? Không đâu. Trong một thế giới lý tưởng, chúng ta sẽ chỉ cần một chương trình cho bất kỳ thứ gì. Mọi ngôn ngữ lập trình đúng là đều phục vụ cho mục đích như nhau, dù nó là C++, Java, Python… nhưng tất cả chúng đều cần thiết vì nhiều lý do khác nhau.

Tại sao lại có rất nhiều ngôn ngữ lập trình cùng tồn tại?

Chúng ta cần các ngôn ngữ lập trình khác nhau là bởi mỗi ngôn ngữ lại có một chức năng khác nhau. Khi một ngôn ngữ lập trình được tạo ra, nó được thiết kế với dụng ý làm sao để có được nhiều chức năng nhất có thể, nhưng không một ngôn ngữ lập trình nào có thể làm được mọi thứ cả. Dưới đây là một số ngôn ngữ lập trình và chức năng cụ thể của chúng:

– Java: đây là một phần mềm đa năng chủ yếu được sử dụng cho phát triển Android. Nó đôi lúc còn được dùng để phát triển website và phần mềm nhúng. Nó được xem là một trong những ngôn ngữ lập trình phổ biến nhất.

– C++: một ngôn ngữ lập trình đa năng khác, hậu bối của ngôn ngữ lập trình C nổi tiếng. Nó hiện được sử dụng cho việc phát triển game máy tính với đồ hoạ cao cấp. C++ cực tốt trong khâu quản lý bộ nhớ và vận hành rất mượt mà. Nó còn được dùng để phát triển các hệ điều hành và các ứng dụng desktop.

– Python: lại một phần mềm đa năng khác. Nó không nhanh như các ngôn ngữ lập trình khác, nhưng lại cực kỳ xuất sắc cho phát triển website và xử lý dữ liệu. Thời gian xây dựng chương trình trong Python ngắn hơn nhiều so với các ngôn ngữ lập trình khác.

– HTML/CSS: đây không hẳn là một ngôn ngữ lập trình đa năng, mà chủ yếu được thiết kế để hướng tới việc phát triển website. Các ngôn ngữ như Python, vốn được dùng để tạo ra backend (phần tương tác với cơ sở dữ liệu) của các website, hoạt động bằng cách gửi HTML đến máy chủ. HTML cung cấp cấu trúc cho website, trong khi CSS được dùng để tạo kiểu và sắp xếp lại các thành phần trong website.

– PHP: được dùng để thêm chức năng cho một chương trình HTML. Nó cho phép bạn gọi dữ liệu và tạo HTML theo nhiều cách hữu dụng trước khi gửi đến trình duyệt của người dùng để hiển thị. Các công ty như Facebook sử dụng ngôn ngữ này rất nhiều.

– R: ngôn ngữ này trong vài năm qua đã trở nên khá nổi tiếng trong cộng đồng lập trình. Nó được sử dụng chủ yếu cho phân tích số liệu thống kê và những thứ liên quan mật thiết đến lĩnh vực này.

Như bạn đã thấy, dù mỗi ngôn ngữ lập trình đều được dùng để tính toán một số dạng dữ liệu, mỗi trong số chúng lại có chức năng và tình huống sử dụng riêng. Ngoài ra, việc lựa chọn một ngôn ngữ còn phụ thuộc vào nhu cầu của mỗi người và sự thuần thục của họ đối với những ngôn ngữ cụ thể.

Theo Vnreview

Bài viết gốc được đăng tải tại Tạp chí Lập trình

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

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

Senior Frontend thì dùng Chrome DevTool như thế nào?

senior use Chome DevTool
Senior Frontend dùng Chrome DevTool như thế nào

Tác giả: bitfish

Vì lý do nào đó mà bạn đã chọn Chrome là browser để develop và Developer Tools của trình duyệt này để debug code. Chrome được các lập trình viên yêu thích là nhờ extension chrome hỗ trợ đầy đủ các devtools của hầu hết các framework frontend hiện đại, không bị giới hạn các extension hữu ích như các trình duyệt khác . Thi thoảng bạn mở Console panel để kiểm tra output của program hay Elements panel để check CSS cho DOM.

frontend dùng chrome devtool
Mở Developer Tools
frontend dùng chrome devtool
Console trong Chrome devtools

Nhưng bạn đã hiểu tường tận về Chrome DevTool chưa? Thật ra các function trong này khá đỉnh, chúng sẽ giúp bạn đẩy nhanh hiệu suất của mình.

Trước khi bắt đầu mình sẽ nói qua về Command menu. Command menu (trong Chrome) nó cũng tương đồng với Shell (trong Linux), nó cho phép gõ commands để điều khiển Chrome.

Đầu tiên mở Chrome Developer Tools lên sau đó mở Command menu với các phím tắt như sau:

  • Windows: Ctrl + Shift + P
  • macOS:Cmd + Shift + P

Hoặc là mở trên trình duyệt luôn cũng được:

frontend dùng chrome devtool
Chạy command

Sau khi mở Command panel, mình sẽ có khá nhiều lệnh command để thực hiện các loại function khác nhau:

frontend dùng chrome devtool
Command panel

Trước khi đi vào các chức năng ít được nhắc đến thì mình sẽ đề cập đến một tab panel rất nổi tiếng và thần thánh từ nhà Chrome mà các trình duyệt khác hiện chưa có, đó là Lighthouse. Panel này có chức năng kiểm tra được performance, SEO, tốc độ tải cho trang web một cách chi tiết được đánh giá từ Google.

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

Tính năng chụp màn hình – Screenshot trong Chrome DevTool

Cap một phần màn hình là lệnh khá quen thuộc mà hầu hết ai cũng có software của riêng mình rồi. Nhưng mà liệu nó có đảm bảo các task này không?

  • Cap màn hình mọi thứ trên web, bao gồm cả phần bị che, không xuất hiện hết trên visual window
  • Cap chính xác content của DOM elemet

Đây chỉ là 2 requirements cơ bản thường gặp nhất nhưng không dễ gì làm được nếu sử dụng tool screenshot thường, thay vào đó bạn có thể dùng Commands với các lệnh tương ứng:

Ví dụ: Mình sẽ ví dụ trên trang https://medium.com/tag/javascript
Sau đó mở Command menu và thực hiện Screenshot Capture full size screenshot

frontend dùng chrome devtool
screenshot

Sau đó mình đã có screenshot đầy đủ của trang hiện tại

frontend dùng chrome devtool
full size screenshot

Tương tự như vậy nếu bạn muốn chụp screenshot DOM element, bạn có thể dùng tool riêng nhưng cũng không thể cap chính xác được hết, thay vào đó có thể dùng lệnh Capture node screenshot.

Đầu tiên cần chọn element và chạy lệnh.

frontend dùng chrome devtool
Capture node screenshot

Và đây là kết quả:

frontend dùng chrome devtool
exact screenshot

Tham chiếu kết quả tới phép tính gần nhất trong console

Chúng ta hay phải debug code trong console. Giả dụ bạn muốn biết cách đảo chuỗi JavaScript, sau đó search những thông tin liên quan và tìm thấy dòng code như sau:

'abcde'.split('').reverse().join('')
frontend dùng chrome devtool
Tham chiếu kết quả

Dòng code trên đúng là có đảo chuỗi, nhưng bạn chưa hiểu method split() reverse() join() để làm cái gì và kết quả của các bước tiếp theo sẽ là như thế nào. Nếu muốn thực hiện dòng code này từng bước một thì nên viết như sau:

Tham chiếu kết quả

Sau từng đó bước thì chúng ta sẽ biết giá trị trả về của từng method. Trong Console, ta có thể dùng biến thần kỳ $_ để tham chiếu kết quả tới phép tính trước đó.

frontend dùng chrome devtool
Tham chiếu kết quả

$_ là kiểu biến khá đặc biệt, giá trị của nó luôn bằng với phép tính liền trước, cách này rất tiện để debug.

frontend dùng chrome devtool
Biến $

Gửi lại (Resend) request XHR trong Chrome DevTool

Đối với các dự án frontend vần cần dùng XHR để request tới backend lấy data. Trong trường hợp muốn gửi lại request XHR phải làm sao? Nếu refresh page thì khá cồng kềnh, thực chất mình chỉ cần debug trực tiếp trong Network panel.

[Nói qua về Network panel được coi là điều không thể thiếu đối với Frontend Dev hiện đại khi vấn đề tương tác với api là việc thường xuyên). Network panel của Chrome có nhiều option hữu ích như Mainfest, has blocked cookie, block request, throttling hỗ trợ thay đổi tốc độ mạng theo nhiều chế độ (Online, Mobile, 3G, Flow 3G, ….), ở header options có thể control việc show những option cần thiết.]

frontend dùng chrome devtool
Resend XHR
  • Mở Network panel
  • chọn nút XHE
  • Chọn request bạn muốn gửi lại
  • Phát lại XHR
frontend dùng chrome devtool
Resend XHR

Theo dõi tình trạng tải trang

Để tải trang hoàn tất từ đầu có thể mất đến hơn 10 giây, thì đây sẽ là cách monitor trang load như thế nào tại những thời điểm khác nhau. Trong Chrome DevTool có thể lưu lại ảnh screenshoot, chụp lại tốc độ tải trang với Capture Screenshots trong Network panel.

Tùy ý chọn ảnh screenshot sẽ hiển thị kết quả network request với thời điểm tương ứng.

frontend dùng chrome devtool
Page load status

Xem thêm Designer nên làm gì trong việc tối ưu hiệu năng Website

Copy biến – variable

Liệu bạn có thể copy giá trị của một cái biến JavaScript từ nơi khác không? Task này có vẻ bất khả thi nhưng trong Chrome nó có một function gọi là copy giúp bạn sao chép biến. Sau đó đã có thể paste ra bất kỳ đâu.

frontend dùng chrome devtool
Copy biến

Copy hình dưới dạng data URL

Có 2 cách xử lý hình ảnh trên trang, một là tải từ link nguồn bên ngoài, và cách kia là mã hóa hình ảnh dưới dạng data URLs.

Khi ta code hình ảnh dưới dạng Data URLs và nhúng trực tiếp vào code sẽ làm giảm số lượng HTTP request cần tạo, từ đó giúp đẩy nhanh tốc độ tải trang. Vậy trong Chrome thì làm thế nào để chuyển từ ảnh sang data URL?

frontend dùng chrome devtool
Copy URL

Mảng table object

Giả sử mình có một mảng chứa objects như sau:

let users = [{name: 'Jon', age: 22},
  {name: 'bitfish', age: 30},
  {name: 'Alice', age: 33}]

Mảng thế này thì hơi khó nhìn trong console, chưa kể nếu mảng dài hơn với các element phức tạp hơn thì sẽ càng khó hiểu hơn. Cũng may Chrome có tính năng table có thể lập bảng các object của mảng. Và nó cũng khá hữu ích.

frontend dùng chrome devtool
Table object array
frontend dùng chrome devtool
Table object array

Kéo thả trong Elements panel

Đôi lúc bạn muốn thay đổi vị trí của các element DOM nào đó trên trang để test UI. Thì với Elements panel bạn có thể kéo thả bất kỳ element HTML nào và thay đổi vị trí của nó trong trang:

frontend dùng chrome devtool
drag n drop in elements panel

Ngoài ra Elements còn cho phép edit trực tiếp element DOM, change element hoặc delete.

Truy cập element đang được chọn trong Console

$0 lại là cú pháp thần kỳ khác giúp gọi element đang được chọn trong Element panel.

Trigger CSS pseudo-class trong Chrome DevTool

Pseudo-class trong CSS được dùng để thêm các hiệu ứng đặc biệt lên các element không chỉ ở mặt nội dung mà còn những yếu tố khác như lịch sử của navigator (ví dụ như :visited), trạng thái content (như :check) hoặc vị trí của trỏ chuột (như :hover hiển thị nếu chuột đang rê lên element đó). Elements panel được cập nhật thêm tính năng khi hover kiểm tra phần từ có 1 tooltip hiển thị thông tin của phần tử bao gồm tên class, id, thuộc tính css …,

Ta có thể viết nhiều lớp pseudo-class cho 1 element, sau đó test các kiểu thì trigger trực tiếp trong Elements panel.

frontend dùng chrome devtool
CSS Pseudo-class

Ví dụ với một web thế này:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body{
      font-size: 150px;
    }

    div:hover{
      color: red;
    }
    div:active{
      color: blue;
    }
    div:focus{
      color: brown;
    }
  </style>
</head>
<body>
  <div>hello world</div>
</body>
</html>

Mở trong browser và debug pseudo-class thông qua Elements panel.

frontend dùng chrome devtool
css pseudo-class

Phím tắt để ẩn element trong Chrome DevTool

Ví dụ khi debug CSS thường cũng cần “giấu” vài element, bạn có thể chọn element và nhấn H trên phím là có thể nhanh chóng ẩn được element đó rồi.

frontend dùng chrome devtool
hide element

Trên đây là những function khá hữu ích của Chrome DevTool. Hy vọng với những tips này bạn sẽ sử dụng Chrome nhanh chóng và hiệu quả hơn.

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

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

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