Trong bài viết Abstract class và Interface trong Java, mình có giới thiệu về Marker Interface. Tuy nhiên, có một số bạn vẫn chưa hiểu rõ hoặc chưa biết trường hợp nào cần sử dụng nó. Trong bài này, chúng ta sẽ cùng tìm hiểu chi tiết hơn về Marker Interface trong Java và một số trường hợp sử dụng Marker Interface.
Marker Interface là một interface không có bất kỳ phương thức và thuộc tích nào bên trong nó. Nó cung cấp thông tin run-time type về object, vì vậy compiler và JVM có thêm thông tin về đối tượng thể thực hiện một số hoạt động hữu ích.
Một marker interface còn được gọi là một tagging interface.
Ví dụ:
public interface Serializable {
}
Built-in marker interface trong Java
Một số marker interface hiện có trong (built-in) Java: java.io.Serializable, java.lang.Cloneable, java.rmi.Remote, java.util.RandomAccess, java.util.EventListener, …
java.io.Serializable được sử dụng để đánh dấu đối tượng Serialize. Khi chúng ta gọi phương thức ObjectOutputStream.writeObject(), JVM sẽ kiểm tra đối tượng có implement một marker interface Serializable hay không. Nếu không, sẽ throw một exception NotSerializableException. Vì vậy đối tượng sẽ không được Serialize sang output stream object. Chi tiết các bạn xem bài viết “Serialization và Deserialization trong java“.
Tương tự, java.lang.Cloneable là một marker interface để nói với JVM rằng, đối tượng có thể call Object.clone() method. Nếu chúng ta thực hiện clone một object mà không được implement một marker interface Clonable, thì sẽ gặp một exception CloneNotSupportedException. Chi tiết về Clone và Clonable, các bạn xem lại bài viết “Object Cloning trong Java“.
Chúng ta có thể sử dụng Marker Interface ở đâu?
Có hai mục đích thiết kế chủ yếu của marker interface là:
Tạo một cha chung: Như với EventListener interface, mà được kế thừa bởi hàng tá các interface khác trong Java API, bạn có thể sử dụng một tagging interface để tạo một cha chung cho một nhóm interface. Ví dụ, khi một interface kế thừa EventListener, thì JVM biết rằng interface cụ thể này đang được sử dụng trong một event.
Thêm một kiểu dữ liệu tới một class: Đó là khái niệm tagging. Một class mà triển khai một tagging interface không cần định nghĩa bất kỳ phương thức nào, nhưng class trở thành một kiểu interface thông qua tính đa hình (polymorphism).
Thực hiện một số pre-processing trên các class, đặc biệt hữu dụng để phát triển các API và Framework giống như Sping, Struts.
Giúp cho code coverage và build tools để find bug dựa trên một behavior cụ thể của marker interface.
Custom Marker Interface
Trong ví dụ bên dưới, chúng ta tạo một Marker Interface gọi là SafeDeletable. Interface này chỉ ra rằng một đối tượng không được xoá khỏi database, chỉ được set flag là delete.
Marker interface:
interfaceSafeDeletable { }
Chúng ta có 2 đối tượng:
Order: đối tượng này có thể xoá khỏi database.
Customer: đối tượng này không thể xoá khỏi database, cần set flad delete khi được yêu cầu xoá.
class Order {}
class Customer implements SafeDeletable {}
Chương trình chúng ta như sau:
public class InterfaceMarkerExample {
public static void delete(Object obj) {
if (obj instanceof SafeDeletable) {
System.out.println("Set flag to delete: " + obj.getClass());
} else {
System.out.println("Call delete object from database: " + obj.getClass());
}
}
public static void main(String[] args) {
delete(new Order());
delete(new Customer());
}
}
Output:
Call delete object from database: class com.gpcoder.Order
Set flag to delete: class com.gpcoder.Customer
Marker Interface vs. Annotation
Tương tự như Marker Interface, chúng ta có thể sử dụng Annotation cho cùng mục đích. Chúng ta có thể chỉ giới hạn sử dụng Annotation ở mức class giống như interface bằng cách khai báo java.lang.annotation.ElementType là TYPE.
Hãy xem cách sử dụng Annotation để thay thế cho Marker Interface ở trên:
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface SafeDeletable {
}
class Order { }
@SafeDeletable
class Customer{ }
public class AnnotationMarkerExample {
public static void delete(Object obj) {
if (obj.getClass().isAnnotationPresent(SafeDeletable.class)) {
System.out.println("Set flag to delete: " + obj.getClass());
} else {
System.out.println("Call delete object from database: " + obj.getClass());
}
}
public static void main(String[] args) {
delete(new Order());
delete(new Customer());
}
}
Một câu hỏi đặt ra là có phải Annotation có thể thay thế 100% Marker interface?
Chúng ta có thể sử dụng Annotation để thay thế cho Marker interface, tuy nhiên trong một số trường hợp sẽ khó khăn nếu sử dụng Annotation. Chẳng hạn trong ví dụ trên, nếu chúng ta có một class con của Customer :
classVipCustomer extendsCustomer {}
Nếu sử dụng Marker inetrface, mặc định class VipCustomer cũng được đánh dấu là SafeDeletable vì tính kế thừa của Java. Tuy nhiên, với Annotation, chúng ta cần đánh dấu lại Annotation SafeDeletable cho class VipCustomer. Kế thừa cũng là một bất lợi của Marker Interface so với Annotation là chúng ta không thể bỏ Marker Interface ở subclass, với Annotation thì không cần làm gì thêm.
Vì interface cho chúng ta tính đa hình (polymorphism), nên chúng ta có thể sử dụng để type check tại thời điểm compile time. Chẳng hạn, chúng ta có class DocumentTransferExecutor, class này chỉ chấp nhận transfer cho những document có implement marker interface DocumentTransferable. Thay vì nhận vào một Object type, chúng ta có thể chỉ định là một Marker interface để tránh developer truyền sai parameter type (đối tượng không phải là document) hay cast object trong quá trình xử lý.
interface DocumentTransferable { }
class DocumentTransferExecutor {
public void transfer(DocumentTransferable obj) { }
}
Tóm lại, marker interface trong Java được sử dụng để chỉ ra một cái gì đó cho complier, JVM hoặc bất kỳ công cụ nào khác. Hiện nay, hầu hết các developer ủng hộ các Annotation để giải quyết một số vấn đề tương tự thay vì dùng marker interface. Mặc dù các marker interface vẫn đang được sử dụng, nhưng chúng nên được sử dụng cẩn thận vì tính kế thừa của nó.
Bài viết được sự cho phép của tác giả Trần Khôi Nguyên Hoàng
Nhắc đến nhận diện gương mặt thì nhắc đến một cái gì đó đao to búa lớn như là Machine Learning cùng với một số thuận ngữ mang tầm vĩ mô như Deep Learning, Training Model, Neural Network, vân vân và mây mây. Đứng dưới góc độ của một thằng Developer quèn thì mình không đủ sức dùng Machine Learning hay gì cả. Cho nên mình xin chia sẻ các bạn một cách đơn giản hơn để thực hiện việc nhận dạng gương mặt chỉ bằng Javscript với face-api-js.
Nhận điện Face Landmark (Không biết dịch ra tiếng việt là gì luôn).
Dự đoán tuổi và giới tính.
Các bước thực hiện
Trước khi bắt đầu thì có một điều quan trọng nó là như thế này. Nhận diện gương mặt bao gồm 2 bước.
Phát hiện gương mặt.
Nhận diện gương mặt.
Chuẩn bị
Đầu tiên tạo một folder cơ bản nhé.
mkdir face
touch index.html
touch script.js
mkdir data // Dùng để bỏ dữ liệu ảnh đầu vào
mkdir images // Ảnh dùng để testmkdir models // Chứa các pre-train model
face-api-js.min.js // Tải từ github ở trên về.
Dùng hàm detectSingleFace để phát hiện ra gương mặt ở trong ảnh
Dùng hàm FaceMatcher và findBestMatch để nhận diện gương mặt.
Load Model vào trong dự án
Đầu tiên là load model vào. Ở đây sử dụng 3 model chính.
ssdMobilenetV1 Model: Đây là pre-trained model dùng để phát hiện gương mặt.
faceLandmark68Net Model: Đây là pre-trained model dùng để hiển thị được các điểm xung quanh mặt của mình.
FaceRecognitionNet Model: Đây là pre-trained model dùng để nhận dạng gương mặt.
Các bạn có thể đọc thêm chi tiết của các model này ở trong link Github ở trên nhé. Tại sao phải load model faceLandmark68Net? Câu trả lời là nhờ vào faceLandmark68Net thì mình phải có thể “nhận dạng” được gương mặt. Nên cho dù không dùng cũng phải load vào.
Ví dụ về Landmark68Net
Vì thế trong file script.jsthì mình sẽ load 3 model này vào trước.
Nếu như mình đưa một tấm ảnh không phải là Nancy, ở đây ví dụ mình đưa Trump vào, thì nó sẽ hiện kết quả là Unknown.
Kết quả sau khi nhận diện Đỗ Nam Trung
Đến đây thì mình đã hoàn thành hệ thống nhận điện đơn giản chỉ bằng Javascript.
Mở rộng
Các bước ở trên thì nó chỉ nhận dạng được một gương mặt của Nancy thôi. Minh muốn nó nhận diện được thêm nhiều người nữa thì phải làm sao? Ví dụ như nhận diện Nancy và Yeonwoo thì làm thế nào? Rất đơn giản, mình chỉ cần tạo folder Yeonwoo và thêm data vào đó. Mình sẽ sửa hàm detectNancyFace() thành detectAllLabeledFaces()
asyncfunctiondetectAllLabeledFaces(){const labels =["Nancy","Yeonwoo"];returnPromise.all(
labels.map(asynclabel=>{const descriptions =[];for(let i =1; i <=2; i++){const img =await faceapi.fetchImage(`http://localhost:5500/data/${label}/${i}.jpg`);const detection =await faceapi
.detectSingleFace(img).withFaceLandmarks().withFaceDescriptor();
descriptions.push(detection.descriptor);}returnnewfaceapi.LabeledFaceDescriptors(label, descriptions);}));}
Kết quả sau khi mình sửa ảnh thành Yeonwoo như sau
Kết quả sau khi nhận diện Yeonwoo
Phát triển
Dựa vào bài này, các bạn có thể phát triển thành một dự án vui vẻ hơn. Ví dụ như clone lại cái Nhận Diện Jav Idol của anh Hoàng Code Dạo chẳng hạn. Hoặc hệ thống điểm danh nhận diện gương mặt chẳng hạn. Ngoài ra, face-api-js còn có các hàm dùng để xác định tuổi, cảm xúc nữa. Nên các bạn đem ra vọc vạch thử cũng vui. Ví dụ như đưa một tấm hình vào và đoán xem ngườ ta bao nhiêu tuổi, như cái https://www.how-old.net/ của Micro$oft chẳng hạn.
Kết luận
Trên đây là bài viết giới thiệu về face-api-js API và cách sử dụng đơn giản của nó. Chú ý là hệ thống nhận diện này được sử dụng bằng các pre-trained model mà không qua bất kì một bước phức tạp nào để tranfer dữ liệu từ pre-trained model nên độ chính xác ở mức tương đối. Không thể nào được như Deep Learning được nhé. Đôi khi mình để ảnh Yeonwoo vào mà nó nhận diện ra Nancy (Chứng tỏ là gái Hàn con nào cũng giống giống nhau).
Các bạn có thể xem source code tại link Github của mình nhé.
Làm gì cũng vậy, để có tay nghề tốt, bên cạnh việc thực hành, làm việc liên tục chúng ta cũng cần phải học hỏi để tiếp thu các kiến thức mới, không ngừng nâng cao tầm kiến thức hơn nữa. Nâng cao chất lượng rồi thì cũng cần nâng cả số lượng nữa. Điều này có nghĩa là làm tốt rồi cần làm nhanh nữa :)) Lý thuyết vẫn được mọi người nói là thế.
Tất nhiên là như thế rồi, cái đó ai chẳng biết, nhưng bên cạnh đó mình cũng rất để ý đến những kiến thức cơ bản. Bạn khẳng định bạn làm cái này rất tốt, cái kia rất tốt, có nhiều kinh nghiệm abc này nọ, nhưng mà đến khi phỏng vấn họ hỏi bạn mấy kiến thức cơ bản, bạn lại cứ ú ớ không giải thích được, giải thích được nhưng mà lại lộn chỗ này xộn chỗ kia thì họ đếch tin vào mấy dòng quảng cáo trong CV của bạn nữa đâu Hehe.
Vì vậy để đỡ quê khi đi phỏng vấn, chẳng may bị “chơi” chỗ này, mình ôn lại một lần nữa chỗ này (ai thi ISTQB rồi, hoặc đọc qua đâu đấy rồi thì sẽ là ôn lại, ai chưa đọc hay chưa biết là thì đọc cho biết nhé :D). Mấy kiến thức này đọc xong lâu lâu lại quên là chuyện bình thường thôi nhé, chịu khó đọc nhiều lần thì tự dưng sẽ nhớ thôi Như mình kiến bài đọc để viết này, bây giờ thì mình tự tin rồi! Haha.
Hôm nay sẽ nói về Smoke testing và Sanity testing. Ahihi đừng cố gắng dịch ra tiếng việt hai cái từ này nhé, ngầm hiểu là được rồi. còn nó như thế nào mời các bạn đọc tiếp bài viết ha.
Smoke testing là một loại kiểm thử phần mềm được thực hiện sau khi có một bản build mới, để đảm bảo rằng các chức năng chính, quan trọng của phần mềm vẫn hoạt động bình thường. Công việc này được thực hiện để phát hiện các vấn đề nghiêm trọng sớm nhất có thể, trong trường hợp phát hiện vấn đề, bản build đó sẽ bị từ chối, và không được bàn giao cho giai đoạn kiểm thử tiếp theo, do đó sẽ giúp tránh lãng phí thời gian cho cả người kiểm thử và phát triển. Trong smoke testing, các test case được chọn sẽ bao phủ được hầu hết các tính năng, thành phần chính quan trọng của sản phẩm phần mềm.
Ví dụ, trong một ứng dụng web, có các chức năng như đăng nhập, trang chủ, tạo mới hồ sơ, gửi hồ sơ, quản lý hồ sơ,… Để có thể thực hiện được các thao tác trên hệ thống bạn cần phải đăng nhập vào ứng dụng thành công, tuy nhiên sau bản build thì một vài vấn đề xảy ra làm cho người dùng không thể login vào hệ thống được. Hay là đăng nhập được nhưng chức năng tạo mới hay gửi hồ sơ đi không thực hiện được. Đây là những tính năng quan trọng của hệ thống, vì vậy việc thực hiện smoke test trước khi bàn giao sẽ phát hiện sớm và fix sớm những vấn đề cơ bản này, thay vì phải bàn giao, thực hiện cài cắm cấu hình các thứ xong rồi bắt đầu kiểm thử thì mới phát hiện ra, gây lãng phí khá nhiều thời gian. Mà chúng ta đều biết rằng, thời gian còn quý hơn cả vàng đó :v
2. Sanity testing là gì?
Sanity testing cũng là một loại kiểm thử phần mềm, Sanity testing được thực hiện sau khi nhận được bản build, ở bản build này một số chức năng của phần mềm được chỉnh sửa, cập nhật do yêu cầu hoặc một số lỗi nào đó đã được sửa, việc này để kiểm tra nhanh các trạng thái hoặc thay đổi đó có ảnh hưởng đến các tính năng khác hay không, có đáp ứng như mong đợi hay không? Nếu các vấn đề được tìm thấy, bản build sẽ không được đưa tới giai đoạn kiểm thử chi tiết hơn tiếp theo, giúp giảm thiểu thời gian và các chi phí khác.
Ví dụ: trong ứng dụng ví dụ bên trên, ở bản build trước có phát hiện ra lỗi liên quan đến việc gửi hồ sơ do phân quyền sai nên hồ sơ được gửi đi nhưng lại gửi không đúng người nhận, ở bản build này bug này đã được sửa, sanity test ở đây sẽ kiểm tra nhanh việc chỉnh sửa chức năng này có liên quan đến các chức năng, vai trò khác hay không? Nhưng vẫn cần phải lưu ý rằng mình sẽ chỉ kiểm tra những phần có liên quan nhất, không sa đà chi tiết quá vào việc kiểm thử chức năng, giao diện gửi hồ sơ hay những chức năng đã ổn định khác, vì thời gian dành cho sanity test là không nhiều.
3. Một vài so sánh cơ bản giữa Smoke và Sanity testing
Smoke testing
Sanity testing
Smoke testing được thực hiện để đảm bảo rằng các chức năng quan trọng của phần mềm vẫn hoạt động bình thường
Sanity testing được thực hiện để xác định các chức năng hoạt động đúng như yêu cầu, thiết kế sau khi có một vài thay đổi nhỏ, hoặc sau khi fix 1 bug nào đó.
Mục đích của Smoke testing đó là kiểm tra sự “ổn định” của hệ thống để có thể tiến hành các bước kiểm thử nghiêm ngặt hơn
Mục đích của sanity testing là kiểm tra sự hoạt động “hợp lý” của hệ thống để có thể tiến hánh các bước kiểm thử nghiêm ngặt hơn
Kiểm thử này thường được thực hiện bởi đội phát triển (Developer) hoặc đội kiểm thử (tester)
Sanity testing thì thường được thực hiện bởi đội kiểm thử
Smoke test thường được lưu thành các tài liệu cố định hoặc các script để có thể chạy tự động (Bởi vì đơn giản, khi các chức năng lớn quan trọng của hệ thống sẽ được định hình ổn định trước tiên, và mỗi lần build thì đều phải đảm bảo hoạt động của các chức năng đó thì mới được coi là build thành công, vì vậy việc tài liệu hóa hoặc viết script là việc cần thiết nên làm)
Đối với Sanity testing, do tính không ổn định trước những yêu cầu và các vấn đề phát sinh khác nên sẽ không có tài liệu cụ thể hay script nào được dựng sẵn cả.
Smoke testing được thực hiện trước giai đoạn kiểm thử hồi quy
Sanity testing được thực hiện trước giai đoạn kiểm thử hồi quy và sau giai đoạn Smoke testing.
Smoke testing sẽ kiểm tra tổng thể toàn bộ hệ thống
Sanity testing kiểm tra từng phần hệ thống.
Kiến thức cơ bản tạm thời là thế, nắm chắc mấy cái này mình nghĩ là OK rồi đấy, thoải mái chém gió tơi bời với các anh/chị phỏng vấn về sanity và smoke rồi nhé!
Đùa thôi, nếu bạn nào có thấy vấn đề gì, hay có thắc mắc, góp ý thì cứ thoải mái để lại dưới phần bình luận cho mình nha.
Tham khảo: https://www.guru99.com/smoke-sanity-testing.html
Bài viết được sự cho phép của tác giả Nguyễn Hữu Đồng
Trước khi nói tới redis, phải nói từ việc caching là và tầm quan trọng của caching.
Bình thường, cứ mỗi yêu cầu từ phía client, hầu hết trong chúng ta ai cũng chạy vàodatabase query thứ gì đó, sau đó làm vài việc rồi lại trả về kết quả cho client. Chuyện này vẫn bình thường cho tới khi số lượng request tăng lên đáng kể khiến CPU và Hard Disk gồng mình ra làm đi làm lại mãi cùng một việc, lấy data rồi lại trả về, thậm chí có những thứ đã lấy lần trước rồi tính toán xong xuôi rồi, biết kết quả rồi vẫn phải đi làm lại, thậm chí làm lại hàng ngìn lần.
Và để tránh giải quyết trường hợp đó, caching xuất hiện như là một phương tiện giúp server ghi nhớ kết quả của quá trình tính toán, để trả về nhanh hơn cho những lần request tương tự của client trong tương lai.
Redis là một công cụ hỗ trợ server giải quyết bài toán caching, không những vậy Redis có thể được sử dụng như một database được lưu trữ trong ram để tăng tốc độ xử lí, nhưng đó cũng là một nhược điểm của Redis, khi mà cúp điện đồng nghĩa với mất dữ liệu, mặc dù redis có hỗ trợ backup và restore data từ ổ cứng theo chu kì và điều đó là không hoàn hảo. Cẩn thận thì là tốt nhất : D
Redis hỗ trợ lưu data dưới dạng Key Value, value đó có thể là một chuỗi, số, danh sách, danh sách được sắp xếp hay thậm chí là một tài liệu dạng từ điển (hash).
Vậy chúng ta sẽ sử dụng Redis để caching data như thế nào ?
Bạn có thể dùng redis để caching mọi thứ bạn muốn, từ kết quả của một câu query trong database, một profile của user, profile cửa hàng. Và khi cache phải chắc chẵn những gì được cache là mới nhất vì nếu data cũ thì sẽ rất ảnh hưởng đến client.
Redis hỗ trợ Transaction, hỗ trợ Pub/Sub vì vậy nó cũng được sử dụng làm hệ thống Message Broker, kinh điển là RabbitMQ sử dụng Redis là core của hệ thống.
Thử cache thứ gì đó với Redis.
Ví dụ như mình, mình có một web app cho user sử dụng để upload ảnh, tạo ảnh thumbnail những mình chỉ cho phép user sử dụng sau khi Login bằng account hợp lệ của Google.
Và khi user Login thành công, mình sẽ xem trong database có thông tin User hay không nếu không thì sẽ tạo mới, tiếp theo mình sẽ cache luôn profile của user dựa vào email, và sau này khi user login mình sẽ lấy thẳng trong Redis luôn, nhanh hơn so với việc chui vào Database để lấy.
Các bạn thấy đấy mình đã dùng kiểu “key-value” để cache nguyên object profile của user dưới dạng string. Và sau này khi client gọi lên để lấy profile user thì mình chỉ chần chui vào ram lấy, nếu lấy không được chỉ có trường hợp user đó chưa login thôi 😀
Ngoài ra do cũng hộ trợ Transaction nên dữ liệu của Redis luôn được đảm bảo là được sửa đổi chính xác, các bạn có thể đọc trong bài viết này của mình, mình đã sử dụng Redis làm nơi lưu trữ số lượng request từ client sau đó thì chặn nếu request được thực thi một cách không hợp lệ.
Hay là một ví dụ, mình cần lên thực đơn đồ ăn món uống do công ty bình chọn cho ngày hôm nay, bởi vì thông tin chỉ được thay đổi cỡ 1 lần 1 ngày, nên mình sẽ chuẩn bị trước tất cả, query lấy hết thông tin món ăn, cửa hàng bán loại món này lưu sẵn vào Redis và qua ngày mới, nếu có hàng ngìn người cùng lấy thông tin thì cũng sẽ rất nhanh vì đã có sẵn rồi.
Nói qua vậy là đủ bây giờ mình sẽ hướng dẫn các bạn Setup một Redis server trên Ubuntu theo kiểu mì ăn liền để test xem nó có gì hay.
Trước tiên chạy lên này. Nó sẽ cài đặt redis-server và redis-cli cho bạn, redis-cli là công cụ giúp bạn giao tiếp với redis-server và thao tác với redis database.
sudo apt-get install redis-server
Để tiến hành chạy Redis Server từ terminal bạn gõ “redis-server” nếu kết quả được như trên thì đã có server để Test.
Đã có server chạy, mặc định redis server sẽ lắng nghe trên cổng 6379 bạn có thể chỉnh sửa bằng cách cấu hình các thông số trong file config. Mặc định thì sẽ nằm tại “ /etc/redis/redis.conf”. Nếu không có thì các bạn có thể tạo mới và tìm hiểu các thông số tại đây.
Tiếp theo mình sẽ dùng “redis-cli” để kết nối với “redis-server” chỉ cần chạy “redis-cli” thì mặc định nó sẽ kết nối đến “locahost:6379”. Mình sẽ dùng lệnh “ping” xem có nhận được gì không, nếu kết nối thành công thì server sẽ “pong”. Như hình dưới.
Mình chạy một vài command. Khá đơn giản, để xem full command và các kiểu dữ liệu trong redis các bạn có thể tham khảo qua bảng cheet-sheet này.
Nhưng trong hình mình tiến hành ghi vào database một biến có tên là user_393901228 với kiểu dữ liệu là hash, và sau đó setup lại giá trị rồi lại lấy ra.
Sau này nếu có điều kiên, đối mặt với lượng request lớn mình sẽ áp dụng redis thường xuyên để cache, hoặc là làm database cho thứ gì đó, và nếu có điều gì hay mình sẽ viết tiếp.
Mình xin dùng bút tại đây, à quên dừng gõ phím :V cảm ơn các bạn đã xem qua bài.
Trong một project rất là lớn (hay không lớn lắm) làm sao để cả team dev, team test và các cấp quản lý có thể nắm được thông tin về bug hay defect đang có của project? Làm sao để tìm kiếm nhanh được bug này được giao cho ai, do ai log, trạng thái đang là gì, thuộc về chức năng nào… hay trong tháng trước sản phẩm đã phát hiện bao nhiêu bug, đã fix được bao nhiêu bug và còn lại bao nhiêu, số lượng bug ở mức độ nghiêm trọng là bao nhiêu, làm sao để dev biết được những lỗi này cần phải được ưu tiên fix trước trong danh sách cả mấy chục bug kia… và rất rất nhiều những vấn đề khác nữa.
Để trả lời được những câu hỏi kia, dùng MS Excel là được hết á =)). Nhưng mà dùng excel thì sẽ khó để tất cả mọi người có thể làm việc song song cùng lúc, truy vết thông tin được, khó tránh khỏi gian lận có thể xảy ra :v, chỉ có cấp quản lý bên trên họ cần tổng hợp thông tin chung thì sẽ rất là tiện, nhưng với những dân tổ chuyên log bug và fix bug thì Excel không hẳn là lựa chọn ngon nhất :v.
Vì thế sự ra đời của các hệ thống quản lý bug đã giúp giải quyết được không chỉ các yêu cầu cơ bản trên, mà còn rất yêu cầu nâng cao hơn, bên cạnh đó còn cung cấp rất nhiều các tiện ích khác liên quan, hỗ trợ rất nhiều các công việc quản lý trong lĩnh vực phần mềm này :)) (không biết chém có quá lời không, nhưng nếu bạn nào đang dùng rồi thì chắc là cảm nhận được thôi mà) Các em mới “vào đời” chưa có cơ sở nhưng mình khẳng định tin được đến 8 -9 phần nên không có gì phải lo lắng nhé! Kaka -.- không tin thì tự chứng minh nè.
Vui thôi, dưới dây là một số hệ thống quản lý bug khá phổ biến và nổi tiếng, mọi người chắc hẳn cũng đã từng làm việc trực tiếp rồi, có thể để lại bình luận và cảm nhận dành cho các công cụ này ở phía dưới nhé!
Bugzilla
Bugzilla là một trong những công cụ quản lý bug hàng đầu được khá nhiều tổ chức, công ty sử dụng trong thời gian dài gần đây. Bugzilla được đánh giá là rất dễ dàng khi sử dụng với giao diện web thân thiện. Đặc biệt đây là một công cụ nguồn mở và miễn phí.
Một số tính năng nổi bật của Bugzilla:
Cho phép tùy biến Tìm kiếm nâng cao
Báo cáo chi tiết được thể hiện qua các dạng biểu đồ khác nhau như biểu đồ bảng, đường và biểu đồ thanh và biểu đồ hình tròn, có hỗ trợ xuất dữ liệu định dạng CSV để bạn có thể tự điều chỉnh dữ liệu của mình
Hỗ trợ quản lý, theo dõi theo thời gian
Thông tin người review
Bạn có thể theo dõi tình trạng, thông tin hoặc khi có tác động thay đổi từ người khác lên bug mà bạn có liên quan hoặc nhận theo dõi nhờ các thông báo được gửi tới email đăng ký của bạn.
Có thể tùy chọn các trường và luồng nghệp vụ tương ứng
Chức năng “Sanity Check” sẽ thực hiện chức năng quét trên toàn bộ dữ liệu của bạn để phát hiện các vấn đề như không thống nhất, các báo cáo lỗi và các đề xuất để sửa các lỗi đó.
Có rất nhiều các tiện ích mở rộng cho nhiều trình duyệt khác nhau, email, các ông cụ quản lý dự án từ đó bạn có thể liên kết các hệ thống đang sử dụng với nhau.
Để tìm hiểu hơn về Bugzilla các bạn truy cập đây nhé, hoặc các hướng dẫn chi tiết cụ thể – có hình ảnh đi kèm luôn về cách sử dụng hiệu quả các chức năng của Bugzilla thì các bạn có thể tham khảo những hướng dẫn ở đây nhé!
JIRA
Atlassian JIRA, là một công cụ chủ yếu được sử dụng để quản lý sự cố tuy nhiên bên cạnh đó nó cũng được sử dụng để theo dõi lỗi. JIRA cung cấp một bộ dữ liệu hoàn chỉnh như record, báo cáo, workflow và các tính năng tiện lợi có liên quan khác.
JIRA là một công cụ có thể tích hợp trực tiếp với code trên môi trường phát triển do đó đây là một công cụ hoàn toàn phù hợp với các developer. Ngoài ra, khả năng có thể theo dõi bất kỳ công việc và tất cả các loại issue, vì thế JIRA có thể sử dụng được với các ngành công nghiệp khác có nhu cầu quản lý các công việc hay issue, JIRA khá là hiệu quả như các công việc liên quan đến hỗ trợ (helpdesk), hệ thống quản lý nhập-xuất, vào ra, vv.
Tuy nhiên, đây là sản phẩm thương mại vì thế mà nó cũng nhiều trình bổ sung hỗ trợ khả năng mở rộng hơn, chắc chắc là đáng đồng tiền bát gạo rồi. Mình thấy khá là nhiều công ty lớn ở Việt Nam đã và đang sử dụng hệ thống này. Trên trang chủ có cung cấp bản dùng thử miễn phí, các bạn nếu chưa biết cộng với tò mò có thể tải về trải nghiệm! :v
Chi tiết về JIRA các bạn có thể tham khảo trên trang chủ của JIRA và các diễn đàn khác qua tìm kiếm google nha.
Mantis
Đây là một công cụ khá là quen thuộc, và đối với Mantis chắc là cũng chỉ cần nói một vài từ ngắn gọn thôi đó là đơn giản và dễ sử dụng. Mantis cung cấp đầy đủ các tính năng mà bạn cần. Bên cạnh đó, để đáp ứng nhu cầu của người dùng và xu thế hiện nay, Mantis không chỉ xuất hiện dưới dạng ứng dụng web mà còn có cả phiên bản riêng dành cho di động. Mantis được xây dựng bằng ngôn ngữ PHP và sử dụng miễn phí. Tuy nhiên, nếu bạn muốn một host riêng thì sẽ phải trả tiền, giá cả khá cũng là hợp lý.
Một số tính năng nổi bật của Mantis như:
Thông báo qua email: Khi có bất kỳ sự thay đổi, comment nào thì các thông tin đó sẽ được gửi tới những người liên quan thông qua email đăng ký của người đó.
Điều khiển truy cập: Cho phép bạn phân cấp, quyền người dùng truy cập theo mức project.
Tùy biến: Bạn có thể dễ dàng tùy biến điều chỉnh một số thông tin cho phù hợp với yêu cầu sử dụng của bạn.
Hỗ trợ nền tảng di động: Mantis hỗ trợ các nền tảng di dộng như iPhone, Android hay cả Windows Phone
Các bạn quan tâm có thể truy cập vào đây để xem thêm thông tin nhé!
Redmine
Redmine là một hệ thống quản lý issue nguồn mở, hệ thống này có thể tích hợp với các hệ thống quản lý source code. Tuy không phải là một công cụ chuyên biệt để “quản lý bug”, nhưng lại có liên quan đến việc xử lý các issue, các issue này có thể là các chức năng hệ thống, công việc, bug / defect, vv ..
Trong danh sách này thì Redmine là một giải pháp khác không chỉ là một công cụ theo dõi, quản lý bug. Cho đến nay giải pháp quản lý dự án nguồn mở này đã tồn tại hơn một thập kỷ và hỗ trợ 34 ngôn ngữ khác nhau. Do đó bạn có thể sử dụng công cụ này cho việc phát triển dự án của mình, hoàn toàn miễn phí. Tuy nhiên nếu bạn chỉ đang tìm kiếm một công cụ chỉ để theo dõi lỗi thì Redmine có thể có nhiều tính năng hơn mức bạn cần.
Lean Testing
Với slogan là: “Simple testing tools for complex software projects”
Lean Testing là phần mềm quản lý test case và quản lý bug miễn phí được thiết kế bởi những người kiểm thử. Bạn có thể sử dụng ứng dụng này như là một tiện ích mở rộng trên trình duyệt (Lean testing có extention trên các trình duyệt Safari, FireFox, Chrome) để report bug một cách nhanh chóng và dễ dàng, ngoài ra bạn còn có thể thực hiện report bug trực tiếp từ ứng dụng trên điện thoại di động mình. Lean Testing có thể tích hợp với các công cụ quản lý khác như Slack, Bitbuckit và GitHub.
Lean testing có mọi thứ mà bạn mong đợi từ trình quản lý lỗi đến việc quản lý test case, với điểm nhấn mạnh lớn đó là việc đảm bảo mọi thứ đều trực quan và dễ sử dụng. Lean Testing phát triển và sử dụng dựa trên nền tảng web và không yêu cầu cài đặt.
Trên đây chỉ là một phần nhỏ trong rất nhiều các hệ thống quản lý bug khác, hệ thống nào cũng có những trải nghiệm, ưu điểm và nhược điểm riêng. Các bạn có chia sẻ thêm gì về hệ thống quản lý bug nào không, nếu có để lại bình luận phía dưới cho mình nhé!
Trong phần Agile cơ bản, mình đã giới thiệu cơ bản về Agile với tuyên ngôn Agile (Agile Manifesto) và 12 nguyên tắc trong Agile. Trong phần này, mình muốn diễn giải thêm về “Tuyên ngôn Agile” để bạn hiểu thêm về Agile:
“Cá nhân và sự tương hỗ quan trọng hơn quy trình và công cụ”
“Sản phẩm xài được quan trọng hơn tài liệu về sản phẩm”
“Cộng tác với khách hàng quan trọng hơn đàm phán hợp đồng”
“Phản hồi với sự thay đổi quan trọng hơn bám theo kế hoạch”
1. “Cá nhân và sự tương hỗ quan trọng hơn quy trình và công cụ”
Ý tưởng là đặt trọng tâm vào con người và sự tương hỗ giữa những thành viên trong nhóm. Cơ bản là nếu dự án có những thành viên có năng lực, chịu làm việc cùng nhau thì sẽ mang đến thành công cho dự án. Nếu dự án của bạn có quy trình làm việc tốt, được hỗ trợ những công cụ tốt nhất nhưng những thành viên không “cùng nhìn về một hướng” thì khả năng dự án thất bại là rất lớn. Nói điều này không có nghĩa là phủ nhận tầm quan trọng của quy trình và công cụ nhưng trong Agile nó được đặt sau yếu tố con người. Có một câu bằng tiếng Anh khá phổ biến nói về điều này là “a fool with a tool is just a fool”
2. “Sản phẩm xài được quan trọng hơn tài liệu về sản phẩm”
Trong một số quy trình phát triển phần mềm, việc tạo ra và cập nhật các tài liệu về sản phẩm là bắt buộc. Nhóm Dev không thể hoặc không đồng ý tiến hành công việc nếu không có tài liệu đặc tả về yêu cầu, thiết kế hệ thống. Nhóm Test thì yêu cầu tài liệu về sản phẩm để có thể viết trường hợp kiểm thử và kiểm thử được. Nhóm QA đòi tất cả các tài liệu phải được viết trước khi sản phẩm được giao cho khách hàng nếu không thì không đủ điều kiện, chuẩn để giao sản phẩm cho khách hàng. Thực ra đứng với góc độ khách hàng thì khách hàng chỉ quan tâm đến sản phẩm có hoạt động được và tốt hay không. Trong khi việc tạo và cập nhật tài liệu mất nhiều thời gian và được cho là buồn tẻ. Vậy tại sao mình phải tập trung quá nhiều cho việc không cần thiết mà không dành thời gian đó để trao đổi để hiểu thêm về công việc phải làm. Mọi người đừng hiểu lầm là làm Agile là không viết tài liệu. Ý tưởng là chỉ viết những gì mà mọi người cần đọc.
3. “Cộng tác với khách hàng quan trọng hơn đàm phán hợp đồng”
“Khách hàng là thượng đế” hay “khách hàng luôn luôn đúng”. Tuy nhiên thì khách hàng có đủ loại khách hàng. Có khách hàng am hiểu về công nghệ, có người không. Có người suy nghĩ nhất quán có người thay đổi xoành xoạch, có người lạnh lùng có người cười nói suốt ngày, v.v và cách duy nhất để có thể làm việc tốt là phải cộng tác với khách hàng để hiểu được khách hàng muốn gì và cần gì để có thể tư vấn và điều chỉnh thay vì chỉ dựa vào những điều đã quy định trong hợp đồng.
4. “Phản hồi với sự thay đổi quan trọng hơn bám theo kế hoạch”
Có một điểm chung mà mình thấy trong hầu hết những dự án mình đã trải qua đó là không có dự án nào không có sự thay đổi điều chỉnh khi thực thi. Sự thay đổi đó có thể là thay đổi về yêu cầu, thay đổi công nghệ, thay đổi nhân sự, thay đổi deadline, thay đổi phương thức làm việc, v.v mặc dù kế hoạch đã được định ra rõ ràng từ đầu. Agile không khuyến khích cho sự thay đổi nhưng khuyến khích chúng ta tập thích nghi với thay đổi. Bạn hãy chuẩn bị tinh thần để thay đổi khi tham gia vào dự án Agile nhé.
Có một điều thú vị là đa số trong chúng ta đều cơ bản đồng ý với 4 tuyên ngôn của Agile. Nhiều người hiểu tầm quan trọng của “cá nhân” hay “cá nhân là tài sản quý giá nhất công ty” nhưng sẳn sàng thay đổi nhân lực để tương thích với quy trình/công cụ hiện có. Nhiều người hiểu “khách hàng là thượng đế” và “phải thích nghi với sự thay đổi” nhưng sẵn sàng tuyên bố “Dẹp, không làm nữa” vì khách hàng thay đổi yêu cầu liên tục. Hay như “sản phẩm xài được là quan trọng “ nhưng vẫn cố gắng viết thêm tài liệu với ý nghĩ rằng “biết đâu/lỡ sau này có ai cần thì có cái mà cung cấp”. 4 tuyên ngôn của Agile nói dễ hơn làm nhưng khi bạn theo Agile thì bạn hãy chuẩn bị tinh thần để “làm” chứ không phải để “nói”.
Progressive Web App và tương lai trong lĩnh vực E-commerce
Sutunam là công ty công nghệ của Pháp với hơn 40 nhân viên làm việc tại Việt Nam bên cạnh trụ sở chính tại Lyon, Pháp. Với hơn 10 năm kinh nghiệm trong lĩnh vực Open Source, Sutunam nổi bật với thế mạnh chuyên môn ở mảng Ecommerce. Công ty làm việc với đa dạng các dịch vụ xoay xung quanh website Ecommerce: từ hoạch định chiến lược kinh doanh số, thiết kế trải nghiệm trên website và mobile app, cho đến các dịch vụ về hạ tầng máy chủ. Sutunam hoạt động như một nhà tư vấn dự án số cho khách hàng, trong đó Progressive Web App là cũng là một hướng đi mà công ty chú trọng.
Progressive Web App và tương lai của nó trong lĩnh vực E-commerce sẽ như thế nào?
Progressive Web App (PWA) là gì?
PWA (progressive web apps) là dạng web app được xây dựng dựa trên các công nghệ của website, nhưng mang lại trải nghiệm tương tự như Native App. Nhờ vào tính năng của service worker, manifest và https, PWA có thể hoạt động offline ngay cả khi không có mạng. Khi người dùng vào website PWA thông qua trình duyệt trên mobile, họ có thể cài đặt website PWA trong điện thoại. Sau đó, họ có thể truy cập trở lại website thông qua icon ngay trên điện thoại, tương tự như khi họ click vào một icon của native app để truy cập phần mềm vậy.
Thông thường, quá trình mua hàng của người dùng sẽ đi từ việc tìm kiếm bằng phiên bản mobile website – responsive thông thường của phiên bản đó. Khi truy cập, bạn sẽ nhận được gợi ý tải app để vào web nhanh hơn chẳng hạn. Sau đó, bạn sẽ được điều hướng sang App Store hay Google Play, iOS Store, để download và cài đặt app vào máy. Cuối cùng, bạn sẽ tìm kiếm lại những thứ mình cần trong app đó một lần nữa và tiến hành thanh toán.
Đối với những người lần đầu tiên sử dụng website, hoặc ít mua hàng của doanh nghiệp đó, đây là một quy trình khá rắc rối. Theo thống kê, có gần 50% khách hàng lần đầu tiên đến với website rất dễ dàng bỏ qua giai đoạn gợi ý tải app về mobile. Ngoài ra, người dùng cũng có tâm lý ngại tải app mới để tăng dung lượng của điện thoại. Vậy phải làm gì để tăng trải nghiệm người dùng trên mobile responsive website, để giúp cho việc thanh toán trở nên dễ dàng và tiết kiệm thời gian hơn?
User flow native app
Progressive Web App chính là giải pháp.
Trải nghiệm người dùng với PWA sẽ đơn giản hơn rất nhiều. Khách hàng chỉ việc tìm kiếm trên mobile website và thanh toán đơn hàng, cuối cùng nhấn vào Add to homescreen để tải website về dưới dạng icon. Vậy là lần sau khách hàng chỉ cần nhấn vào icon để trở lại với website. Trải nghiệm này sẽ tương tự như khi người dùng app trong điện thoại. Với người dùng, đây là một giải pháp cực kỳ tiện dụng vì vẫn được sử dụng mobile website rất nhanh chóng mà không cần tải app về.
User flow PWA
Release Cycle
Với PWA, release cycle cũng đơn giản hơn. Với các lập trình viên mobile, mỗi lần có update hay tính năng mới, họ sẽ phải cập nhật phiên bản mobile app. Mỗi lần update như thế, các dev sẽ phải đẩy lên lại các chợ ứng dụng, quá trình như thế sẽ mất khá nhiều thời gian và công sức hơn so với PWA cập nhật trang web.
Với PWA, bạn chỉ việc release bản update một lần và refresh cache trên website. Tính năng đồng bộ ngay cả khi người dùng không mở PWA cũng được phát triển. Twitter được biết đến là một trong những đơn vị tiên phong trong việc sử dụng PWA. App size trên Android app của Twitter chiếm dụng 24mb, iOS app chiếm 214mb dung lượng máy, trong khi đó với PWA chỉ tốn 600 kb cho điện thoại. Đối với những khách hàng không muốn tốn quá nhiều dung lượng điện thoại hay không muốn cài đặt thêm các app khác gây tốn bộ nhớ máy thì đây là một lựa chọn tuyệt vời.
Chi phí vận hành và duy trì
Chi phí doanh nghiệp và lập trình cũng là một đề cần lưu tâm cho một dự án công nghệ. Với một doanh nghiệp e-commerce, xây dựng website cùng IOS + Android app sẽ yêu cầu chi phí vận hành lớn với đội nhân sự bao gồm front-end, back-end, IOS developer và Android developer.
Trong khi đó với PWA, với bản chất web-app dựa trên nền tảng công nghệ website, đội ngũ sẽ rút ngắn chỉ cần frontend và backend. Tuy việc thực hiện ứng dụng PWAs đòi hỏi số lượng nhân lực ít hơn, nhưng lại cần nhiều kỹ năng hơn. Đối với đội ngũ front-end đang quen thuộc với JQuery và HTML từ cách phát triển truyền thống backend-driven website, bây giờ sẽ cần học hỏi và tìm hiểu nhiều dạng kiến thức hơn để thực hiện dự án, và đội ngũ lập trình website truyền thống sẽ phải hiểu thêm về trải nghiệm người dùng trên mobile app.
Search Engine Optimization
Ưu điểm của PWA là ta có thể tối ưu hóa SEO cho nó. Vì vẫn là server side rendering nên ta vẫn có thể tối ưu hóa việc hiển thị trên Google với các kỹ thuật về technical SEO.
Đối với native app, ta khó có thể tối ưu hóa nội dung SEO mà chỉ có thể giới thiệu trên website, dẫn link tới chợ ứng dụng, hoặc trả tiền quảng cáo trên các chợ ứng dụng. Ngoài ra, PWA được tạo ra để tối ưu hóa trải nghiệm người dùng trên mobile, nhanh hơn, tiện dụng hơn, về thiết kế nó vẫn là mobile-first design và tuân thủ các nguyên tắc thiết kế được ưu ái của các công cụ tìm kiếm như Google, Bing.
PWA giúp nâng cao trải nghiệm người dùng với mobile website
Progressive Web App và Native App có đang trong thế “đối đầu” nhau?
Với những ưu thế nổi trội của PWA – là sự kết hợp của website và native app, nhiều người đã đặt các câu hỏi và so sánh PWA với Native App. Nhưng sự thật thì hai nền tảng này hoàn toàn không nằm trong thế đối đầu với nhau. Ít nhất ở thời điểm hiện tại.
Số lượng người dùng di động trên thế giới là khoảng 3 tỷ người, thị trường hoàn toàn đủ lớn để PWA và Native App cùng phát triển. Bên cạnh đó, PWA giúp chuyển hóa first-time user (người mua lần đầu) khá tốt, nhằm giúp họ làm quen với nhãn hàng và dần trở thành khách hàng trung thành. Từ đó, doanh nghiệp dễ dàng thu hút họ hơn trong việc tải và sử dụng native app của mình. Vì vậy, có thể thấy, ở thời điểm hiện tại PWA đang hỗ trợ cho Native App, chứ không hề ở thế đối đầu nhau.
Bên cạnh đó, PWA hiện tại vẫn đang trong quá trình phát triển nên vẫn còn khá mới mẻ. Đối với những doanh nghiệp có tiềm lực tài chính tốt, họ sẽ lựa chọn sử dụng cả hai vì không ai muốn mất khách hàng cả, doanh nghiệp nào cũng sẽ muốn tối ưu hóa lợi nhuận của mình.
Với các doanh nghiệp vừa và nhỏ, chi phí duy trì IOS app và Android App sẽ khá cao, nhất là với các Ecommerce app. PWA có thể chính là giải pháp phù hợp cho họ. Đặc biệt, đối với các doanh nghiệp có số lượng tải app của họ quá thấp, họ sẽ tìm cách để tối ưu hóa chi phí, tìm cách nào tiết kiệm hơn so với việc bảo trì Native App và cũng tìm đến với PWA.
Tương lai của Progressive Web App ở thị trường châu Á sẽ ra sao?
Châu Á là thị trường tiềm năng với lượng dân số đông, bối cảnh thị trường công nghệ độc đáo. Vì thế, tại châu Á, các doanh nghiệp sẽ đối mặt cả những vấn đề mà thế giới gặp phải, cũng như chưa thị trường nào từng trải qua. Nếu lựa chọn một nơi có một bước nhảy vọt và tiên phong về công nghệ, những báo cáo thị trường luôn chọn châu Á là nơi đi đầu trong tất cả những xu hướng đó.
Bối cảnh thị trường châu Á có 4 điểm chính:
Mức độ sử dụng di động rất cao
Việc sử dụng di động để mua hàng và truy cập mạng xã hội rất phổ biến
Dễ dàng chấp nhận công nghệ mới
Các công ty công nghệ nhanh chóng mở rộng cơ hội sáng tạo.
Mức độ sử dụng di động ở châu Á đặc biệt cao, nhiều hơn hẳn so với laptop, TV hay các hình thức giải trí khác. Khả năng tiếp cận công nghệ của gen Z rất nhạy bén. Vì là những người trưởng thành hoàn toàn trong thời kỳ công nghệ nên việc họ tương tác trên mạng xã hội rất cao, hình thành nên những ngành nghề hoàn toàn mới như content creator, influencer, streamer. Hành vi trên mạng xã hội rõ ràng cũng đã thay đổi rất nhiều.
Mức độ sử dụng di động ở châu Á rất cao, nhiều hơn hẳn so với laptop, TV hay các hình thức giải trí khác. Khả năng tiếp cận công nghệ của gen Z rất nhạy bén. Vì là những người trưởng thành hoàn toàn trong thời kỳ công nghệ nên việc họ tương tác trên mạng xã hội rất cao, hình thành nên những ngành nghề hoàn toàn mới như content creator, influencer, streamer. Hành vi trên mạng xã hội rõ ràng cũng đã thay đổi rất nhiều.
Châu Á đã, đang và sẽ tiếp tục là thị trường “màu mỡ” của PWA
Về khả năng thích ứng với công nghệ mới ở châu Á gần như cao hơn hẳn so với các khu vực khác trên thế giới. Một phần của vấn đề này liên quan đến bối cảnh văn hóa độc đáo của khu vực này. Đây là môi trường khá non trẻ, các công ty đa phần đều thuộc first generation (thế hệ đầu tiên) nên họ sẽ không có lịch sử 200, 300 năm hay những yếu tố lịch sử tương tự. Từ đó, các công ty thường sẽ mở rộng và dễ dàng đón nhận xu hướng hơn và có nhiều cơ hội sáng tạo hơn.
Ở châu Á cũng sẽ gặp những vấn đề mà không có châu lục nào gặp phải (như không có quốc gia nào trên thế giới có đến hơn 1 tỷ dân như Trung Quốc, Ấn Độ) nên đây cũng là động lực để đáp ứng nhu cầu thị trường đa dạng để các doanh nghiệp công nghệ tiếp tục phát triển nhiều hơn trong tương lai. Bên cạnh đó, ta cũng có thể thấy sự khác biệt về thị trường công nghệ phát triển cao (Nhật Bản – Hàn Quốc) và đang phát triển (Đông Nam Á), tạo ra một bối cảnh đặc biệt thú vị và khó dự đoán tại Châu Á
Không có một “”châu Á đồng nhất””, những công ty công nghệ lâu đời ở Hàn Quốc và Nhật Bản nên sẽ mang đến cho các lập trình viên những cơ hội công việc ổn định và môi trường phát triển chắc chắn hơn. Trong khi đó, Trung Quốc, Ấn Độ và các quốc gia khu vực Đông Nam Á sẽ phải đối mặt với những khó khăn khác nhau, nên đây cũng là cơ hội để các công ty có cơ hội tiếp xúc với PWA nói riêng và các công nghệ mới nói chung.
Từ bối cảnh công nghệ của châu Á, ta có khẳng đinh về châu Á là một mobile-first region, châu lục được thống trị bởi nhu cầu sử dụng di động. Tối ưu hóa trên di động từ đó cũng sẽ mang lại cạnh tranh màu mỡ cho doanh nghiệp.
Một đặc tính thị trường châu Á ta có thể là sự thống trị của Marketplace – những trang web trung gian, các sàn thương mại điện tử, từ Taobao, Lazada, Shopee, Tiki,… Vậy nên để các doanh nghiệp nhỏ và vừa, những doanh nghiệp không phải là Marketplace muốn tồn tại được, họ bắt buộc phải sáng tạo nhiều hơn, tiến bộ nhiều hơn, tìm những đường ngách để đi, tăng cường các kế hoạch branding cho doanh nghiệp trên tinh thần tập trung tối ưu mobile. PWA ở đây sẽ là một lựa chọn đổi mới có hiệu quả dài lâu cho các doanh nghiệp này.
PWAs trên ecommerce – bước đầu tiếp cận Headless Commerce
Kể cả khi người dùng đến với cửa hàng thực tế mua hàng, họ vẫn sử dụng di động để xem review của người mua trước, so sánh với các cửa hàng khác tương đương để đi đến quyết định có mua sản phẩm đó hay không. Khách hàng quan tâm tới việc tiếp cận nhãn hàng ở nhiều khía cạnh hơn là chỉ mua ở cửa hàng.
Khi di động là chìa khóa để phát triển doanh số, headless commerce cũng là sự phát triển tất yếu trong e-commerce.
Headless Architecture là gì? Đó là việc phát triển tách rời phần front-end và back-end của website, thông tin sẽ được gọi thông qua hệ thống API. Headless cho phép phần front-end (giao diện) không phụ thuộc và linh hoạt hơn khi tùy chỉnh và cá nhân hóa trải nghiệm người dùng, dễ dàng hơn cho doanh nghiệp kết nối thông tin với nhiều kênh bán hàng hơn (multiple touch-point) – một trong những yếu tố nền tảng của omnichannel để tạo ra vòng tròn trải nghiệm đa điểm cho khách hàng. Từ đó tăng sale, năng lực cạnh tranh và quản lý đồng nhất cho doanh nghiệp.
Thay vì là cấu trúc backend-driven truyền thống, xu hướng headless hiện tại sẽ phân tách cấu trúc frontend và backend. Backend sẽ xử lý phần logic, frontend sẽ độc lập kết nối với rất nhiều selling point để tạo ra lợi thế cạnh tranh và tăng sale cho doanh nghiệp.
Với PWA, lập trình viên cũng sẽ bắt đầu phải làm quen với việc phát triển tách rời front-end và back-end, làm việc với manifest và service worker, cho phép cache các thông tin và chức năng đẩy thông báo (push notification) tương tự như native app. Đây cũng sẽ bước đầu chuyển đổi website truyền thống trở thành cấu trúc headless.
Tuy còn khá nhiều thách thức, nhưng nếu xét tới khía cạnh thị trường và hỗ trợ công nghệ, ta có thể sự phát triển của PWAs còn tiếp tục tăng cao trong tương lai. Hi vọng bài viết sẽ đóng góp thêm một vài góc nhìn cho các bạn lập trình viên khi tiếp cận PWA.
Bài viết được trích dẫn từ phần trình bày của chị Ngô Kiều Anh tại sự kiện Vietnam Web Summit 2020 LIVE do TopDev tổ chức
Cấm kỵ khi đi phỏng vấn, đặc biệt là các phát ngôn có khiến bạn thắc mắc? Vậy đâu là lỗi khi đi phỏng vấn; cách gây ấn tượng lúc phỏng vấn như thế nào? Interview Round giúp nhà tuyển dụng khai thác tiềm năng và đánh giá mức độ phù hợp của ứng viên.
Để tạo ra sự thu hút nhà tuyển dụng, ứng viên cần có các câu trả lời ấn tượng nhất thể hiện đúng cá tính của mình. Song, cá tính là điều tốt nhưng phải luôn chừng mực và được đặt đúng chỗ. Cùng TopDev điểm qua các câu trả lời cấm kỵ khi đi phỏng vấn .
Hãy cho chúng tôi biết về bản thân bạn?
Với câu hỏi này, ứng viên sẽ chia sẻ những điều cơ bản về bản thân (có thể khác các nội dung đã đề cập trong CV).
Tăng hiệu quả ứng tuyển bằng cách tạo CV Online hiệu quả trên TopDev
Các ứng viên nói rằng họ thừa năng lực để thực hiện công việc đó. Họ nhận thấy kỹ năng của mình còn quá tệ, làm sao có thể đủ sức cạnh tranh. Đặc biệt, họ lại chia sẻ về sự lo lắng, quá hồi hộp của bạn thân. Đồng thời, ứng viên cũng thể hiện sự mơ hồ của mình trong việc lập kế hoạch tương lai. Mọi thứ chung quanh có vẻ quá sức với họ.
Hãy loại bỏ ngay những cách trả lời ấy vì bạn đang lãng phí đi các cơ hội. Bạn không thể nói quá nhiều về bản thân. Điều đó chứng tỏ bạn là người tự cao. Ngược lại, việc luôn tự ti sẽ làm buổi phỏng vấn trở nên chùn xuống. Vậy đâu là lỗi khi đi phỏng vấn, gây ấn tượng lúc phỏng vấn? Cùng tìm hiểu ngay sau đây!
Giải pháp phỏng vấn khắc phục cấm kỹ khi đi phỏng vấn
Nhà tuyển dụng sẽ không bao giờ chọn một ứng viênthiếu sự tiết chế trong cách định hướng các phản hồi cá nhân. Bạn không nên thể hiện các dấu hiệu tiêu cực và dùng nó để tạo “điểm nhấn”. Đó được đánh giá là nước đi thiếu khôn ngoan. Hơn thế nữa, nó còn làm cản trở sự tương tác giữa bạn và nhà tuyển dụng.
Đừng để mọi chuyện vượt ra khỏi trọng tâm của nội dụng phỏng vấn. Và đó là điều cấm kỵ khi đi phỏng vấn. Bạn không nên chia sẻ quá nhiều về thông tin, Vì thực tế, nhà tuyển dụng cho rằng đó là những thông tin dư thừa.
Bạn muốn mình là ai trong 5 năm tới?
Nhiều ứng viên đã trình bày các kế hoạch không một tí liên quan gì đến công việc như: mua nhà, đi du lịch, kinh doanh,…
Hoặc thậm chí, ứng viên bộc lộ nhiều sự cường điệu trong cách dẫn dắt câu chuyện. Chẳng hạn như việc chia sẻ rằng họ sẽ là một người có đam mê với công việc nhiều nhất; làm việc chăm chỉ nhất. Tồi tệ hơn là có nhiều ứng viên chỉ cười trừ vì không biết phải trả lời như thế nào. Vậy đâu là lỗi khi đi phỏng vấn, gây ấn tượng lúc phỏng vấn?
Bạn phải thật sự cẩn trọng trong cách trả lời của mình. Nếu không, bạn sẽ thất bại về vấn đề tri nhận các yêu cầu phản hồi thông điệp. Dù bạn cố tình hay vô tình (thiếu sự trải nghiệm), bạn cũng không nên khiến mình thiếu chuyên nghiệp.
Giải pháp khắc phục lỗi khi đi phỏng vấn
Cách tốt nhất là bạn nên xâu chuỗi các yêu cầu để có câu trả lời thật sự phù hợp. Thay vì nói một cách dàn trải, bạn hãy đặt ra hai dự định bạn sẽ thực hiện. Đó là dự định trong tương lai gần – Mục tiêu ngắn hạn và tương lai xa – Mục tiêu dài hạn.
Hãy tự tin để nói về các hoài bão cá nhân (tất nhiên nó vẫn đảm bảo sự tương quan với năng quan, kỹ năng, đam mê,…) của bạn. Đó có thể là lên vị trí Chuyên viên cho một lĩnh vực nào đó; mơ ước về việc điều hành một công ty mang dấu ấn của mình;… đừng ngần ngại nói cho nhà tuyển dụng biết bạn muốn mình ai.
Ngoài ra, bạn có thể mô tả đôi chút về những dự định ấy gắn với các thách thức cần bạn phải vượt ra. Đâu là điều bạn có để tạo ra lợi thế cho mình? Đâu là điểm bạn cần khắc phục? Đây đều là những điều bạn nên lưu tâm để có sự phản hồi tốt nhất với nhà tuyển dụng.
Tại sao chúng tôi nên chọn bạn?
Nhiều ứng viên khi gặp câu hỏi này họ thường nói nhiều hơn về bản thân. Đó là trường hợp thể hiện bản thân quá tự tin (như bài viết đã trình bày phía trên). Vậy đâu là lỗi khi đi phỏng vấn, gây ấn tượng lúc phỏng vấn?
Một cách trả lời khác được đánh giá là thiếu tinh tế và cấm kỵ là việc nói về những hạn chế của các ứng viên khác. Hoặc đơn giản, ứng viên sẽ thể hiện sự thất vọng thay vì thể hiện khao khát vị trí. Họ bắt đầu “bài tập làm văn” về những viễn cảnh có thể xảy ra nếu không may mắn trượt vị trí công việc này.
Giải pháp gây ấn tượng lúc phỏng vấn
Trong trường hợp này, bạn nên tập trung vào việc thể hiện mình nhiều hơn. Hãy nói về những thế mạnh của bản thân nhưng đừng quá phô trương.
Bên cạnh đó, hãy thể hiện rằng vị trí công việc bạn đang ứng tuyển là cơ hội để bạn phát triển khả năng tốt hơn. Bạn có thể kể những điểm còn hạn chế của bản thân. Song, bạn trình bày mong muốn sẽ cố gắng và học hỏi nếu có cơ hội làm việc tại đây.
Đừng thể hiện cảm xúc tiêu cực (cho dù đó là thật hay giả). Bạn cần cho nhà tuyển dụng thấy được bạn là ứng viên tiềm nang, biết tạo ra sự kết nối thông qua nguồn năng lượng từ chính khao khát được trải nghiệm vị trí này.
Tại sao bạn quan tâm đến công việc này?
Nếu có cách ứng xử thông mình, hiệu quả phỏng vấn hầu như đạt mức tuyệt đối. Tuy nhiên, nhiều câu trả lời dường như chỉ tập trung vào việc đào sâu các vấn đề nhạy cảm liên quan đến công việc. Cụ thể, nhiều ứng viên sẽ đề cập đến mức lương và các chế độ thuộc về mặt quyền lợi của nhân viên. Từ đây, các ý kiến khác nhau được bàn luận. Hãy cẩn trọng để không phải mắc phải cấm kỵ khi đi phỏng vấn nhé!
Em mong muốn mức lương bao nhiêu? Theo em tự đánh giá, với năng lực hiện tại thì mức lương cụ thể nào phù hợp với em?
Nhiều ứng viên đã đánh giá về mức lương. Họ chê mức lương hoặc đề nghị một mức lương cao hơn. Tất nhiên, câu chuyện về quyền lợi thì bất cứ ứng viên nào cũng đều quan tâm. Nhưng họ cần biết, nếu là một ứng viên thông minh và nhạy bén, ít ai lại “cò kèo” lương với nhà tuyển dụng. Vậy đâu là lỗi khi đi phỏng vấn, gây ấn tượng lúc phỏng vấn?
Một cách phản hồi cấm kỵ khi đi phỏng vấn nữa đó là ứng viên than vãn hoặc đòi hỏi quá nhiều về “giấc mơ doanh nghiệp”. Ví dụ họ muốn có một môi trường làm việc tốt, một người sếp biết quan tâm, các kế hoạch cho sự thăng tiến,… Đây mới thật sự là những gì họ quan tâm.
Giải pháp phỏng vấn
Hãy là một ứng viên ứng xử khôn khéo. Bạn có thể để xuất mức lương phù hợp với năng lực của mình. Điều này đòi hỏi bạn phải hiểu rõ những gì mình cò để đề nghị một mức lương phù hợp. Nếu không trò cười sẽ tiếp nối trò cười.
Không những thế, bạn có thể chọn cách trả lời thông mình hơn. Đó là gửi lời cam kết với nhà tuyển dụng về việc đánh giá dựa vào năng lực của bản thân. Nhả tuyển dụng sẽ đánh giá hiệu suất của bạn thông qua thành tích. Việc của bạn là cứ làm tốt và phát huy đối đa những gì mình có.
Ngưng than vãn và chấp nhận những trải nghiệm mới. Có nọ có kia thì cuộc hành trình nghề nghiệp mới trở nên thú vị.
Lời kết
Có rất nhiều câu chuyện thú vị xoay quanh vấn đề cấm kỵ khi đi phỏng vấn ứng viên. TopDev hi vong với bài viết này, các bạn sẽ hiểu thêm về thực trạng tuyển dụng. Đồng thời nhận ra những thiếu sót và bắt đầu lên kế hoạch hoàn thiện bản thân mình nhiều hơn. Những phân tích trong bài viết đều dựa trên những trải nghiệm từ đội ngũ. Hãy thảo luận và tìm ra nhiều hơn các câu trả lời cấm kỵ khi đi phỏng vấn để khắc phục nhanh chóng. Chúc các bạn có sự chuẩn bị tốt nhất cho buổi phỏng vấn của mình.
Bài viết được sự cho phép của tác giả Kien Dang Chung
Mỗi khi học một ngôn ngữ lập trình mới, việc đầu tiên chúng ta cần là học các cú pháp câu lệnh cơ bản. Với Vue.js thì có khác đi một chút do đây là một framework không phải là ngôn ngữ lập trình. Vue.js như là một ngôn ngữ trung gian, mọi thứ sẽ bạn viết sẽ Vue.js chuyển thành ngôn ngữ HTML kết hợp Javascript và CSS (còn gọi là render, thuật ngữ này sẽ được sử dụng nhiều cho ngắn gọn). Như vậy, về cơ bản Vue.js có thể sử dụng các cú pháp câu lệnh trong HTML, CSS và Javascript. Tuy nhiên, Vue.js cũng có một số các cú pháp riêng sử dụng cho những trường hợp sau:
In kết quả biểu thức ra màn hình.
Các phần xử lý có kiểm tra điều kiện.
Các phần xử lý kiểu vòng lặp.
Xử lý theo cách cá nhân hóa, xây dựng các plugin, module…
Vue.js sử dụng cú pháp {{ }} để in một biểu thức ra màn hình, kiểu cách này giống như Laravel sử dụng. Chúng ta cùng xem lại ví dụ đầu tiên của Vue.js:
<!DOCTYPE html><html><head><title>Ví dụ đầu tiên Vue.js - allaravel.com</title></head><body><div id="app"><h1>{{ message }}</h1><input v-model="message"></div><script src="https://vuejs.org/js/vue.min.js"></script><script type="text/javascript">newVue({
el:'#app',
data:{
message:'Xin chào, tôi là Vue.js'}})</script></body></html>
Trong ví dụ này chúng ta in giá trị của biến message vào thẻ <h1>. Trình biên dịch sẽ thay đối tượng message thành giá trị của nó khi render. Như vậy để in một đối tượng chúng ta chỉ cần đưa chúng vào cú pháp {{ doi_tuong_javascript }}. Chúng ta có một số chú ý khi sử dụng cú pháp {{ }} như sau:
Chú ý 1: Khi render cú pháp {{ }} xử lý dữ liệu dạng text đơn thuần chứ không xử lý các text dạng mã HTML. Ví dụ, nếu đối tượng message chứa dữ liệu dạng text HTML “Xin chào, tôi là <strong>Vue.js</strong>” thì nó vẫn in nguyên giá trị này ra. Nếu muốn trình biên dịch xử lý các biến dạng mã HTML, chúng ta sử dụng câu lệnh v-html. Chúng ta cùng xem sự khác nhau trong ví dụ dưới đây:
<html><head><title>In kết quả biểu thức trong Vue.js - allaravel.com</title></head><body><div id="app"><h1 v-html="message"></h1><h1>{{ message }}</h1><input v-model="message"></div><!-- <script src="https://unpkg.com/vue@2.5.16/dist/vue.min.js"></script> --><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script><script type="text/javascript">newVue({
el:'#app',
data:{
message:'Xin chào, tôi là <span style="color: #41B883;">Vue</span>.<span style="color: #354B5E;">js</span>'}})</script></body></html>
Trong Laravel Blade, việc xử lý text đơn thuần hay mã HTML sử dụng các cú pháp tương ứng là {{ }} và {!! !!}.
Chú ý 2: Không sử dụng cú pháp {{ }} trong một thuộc tính của thẻ HTML. Thay vào đó sử dụng câu lệnh v-bind để gán một giá trị vào một thuộc tính trong thẻ HTML. Ví dụ
<img src="{{ imageUrl }}">
không hoạt động mà phải viết lại như sau:
<img v-bind:src="imageUrl">
Câu lệnh v-bind sẽ được giới thiệu chi tiết hơn ở phần cuối bài viết.
In giá trị biểu thức Javascript
Đây là trường hợp tổng quát, nó bao hàm cả trường hợp in giá trị đối tượng ở trên, tức là đối tượng nằm trong {{ }} có thể là một biểu thức Javascript. Chúng có thể là các biểu thức tính toán hoặc một lời gọi một hàm tính toán.
Chú ý, nội dung trong {{ }} phải là biểu thức và biểu thức dạng đơn chứ không thể sử dụng các biểu thức kiểu nhiều dòng hoặc các biểu thức dạng điều kiện. Các ví dụ dưới đây sẽ không chạy ra kết quả và báo lỗi:
<!-- đây là một câu lệnh không phải là biểu thức -->{{var a =1}}<!-- Câu lệnh điều kiện, rẽ nhánh không được sử dụng -->{{if(ok){return message }}}
Câu lệnh
Trong Vue.js có một khái niệm là directive dùng để đánh dấu các chỉ thị, lệnh hướng dẫn trình biên dịch xử lý các công việc cụ thể và sinh ra mã HTML cuối cùng (render). Trong suốt loạt bài này chúng ta sẽ sử dụng trực tiếp khái niệm directive hoặc câu lệnh cho thuận tiện. Các câu lệnh này bắt đầu bằng chữ v (Vue.js), ví dụ v-if, v-for, v-bind, v-html… và nằm trong các thẻ HTML dưới dạng các thuộc tính của thẻ. Trong ví dụ Hello world! chúng ta có đoạn:
<input v-model="message">
Câu lệnh v-model ở đây trông giống như một thuộc tính của thẻ input, trình biên dịch khi xử lý đoạn mã này nó sẽ biết v-model là câu lệnh nhằm chỉ thị là gán giá trị đối tượng message vào thuộc tính value của thẻ input.
Các câu lệnh có thể có tham số, có thể tham số là một tên một thuộc tính hoặc tên một sự kiện của thẻ HTML. Cú pháp truyền tham số vào câu lệnh là cau_lenh:tham_so.
Ví dụ 1: câu lệnh v-bind có thể có tham số là tên thuộc tính cần gán giá trị. Ví dụ:
<img v-bind:src="imageUrl">
Ở đây src là tham số chính là thuộc tính src của thẻ img. Một ví dụ khác là câu lệnh v-on để xử lý các sự kiện với các phần tử HTML, ví dụ nếu click vào một nút thì sẽ thực hiện một phương thức trong Javascript:
<button v-on:click="doSomething">
thì click là một tham số. Trong Vue.js chỉ có hai câu lệnh có tham số là v-bind và v-on, khi sử dụng các câu lệnh này có thể sử dụng dạng viết tắt tương ứng là : và @. Các ví dụ sử dụng v-bind và v-on có thể được viết lại như sau:
Qua bài viết chúng ta đã trả lời được Vue.js directive là gì? cách sử dụng để gán dữ liệu hoặc in giá trị đối tượng ra màn hình. Bài viết chỉ dừng lại ở giới thiệu mà chưa đi sâu cụ thể vào từng câu lệnh v-xyz, trong những bài viết tiếp theo, chúng ta sẽ cùng tìm hiểu chi tiết từng câu lệnh của Vue.js.
Một developer trẻ nói với Chú của mình về việc cậu ta muốn trở thành một Software Architecture trong tương lai. Sau đây là cuộc nói chuyện giữa hai chú cháu.
Con muốn sau này trở thành một Software Architecture (kiến trúc sư phần mềm).
Con có định hướng cho mục tiêu nghề nghiệp vậy là tốt lắm đó.
Con muốn được dẫn đầu một nhóm và đưa ra các quyết định quan trọng như chọn loại Database nào, Framework nào, Web API thế nào và dùng những công nghệ nào cho dự án.
Khá đó chứ. Nhưng nghe có vẻ như con không phải muốn trở thành Software Architecture nữa.
Tất nhiên là con muốn chứ. Con muốn trở thành một người quyết định tất cả những thứ quan trọng.
Chú biết vậy, nhưng mà con đang liệt kê những thứ không quan trọng. Chính xác hơn là những thứ con liệt kê nó không liên quan đến quyết định của một Software Architecture.
Ý của Chú là sao? Database mà không quan trọng sao? Chú có biết phải chi bao nhiêu tiền cho chúng không?
Có lẽ là rất nhiều, nhưng mà lựa chọn database không phải là một trong những quyết định quan trọng.
Sao Chú nói vậy? Database là trái tim của toàn hệ thống. Nó là nơi dữ liệu được lưu trữ, sắp xếp, đánh index và được truy cập. Không có nó thì sẽ không có hệ thống.
Database đơn thuần chỉ là một thiết bị IO. Nó chỉ là một công cụ hữu ích để sắp xếp, truy vấn và báo cáo nhưng đó chỉ là những phụ trợ cho kiến trúc hệ thống.
Phụ trợ hả? Chú giởn với con đúng không.
Chú nói thật, nó là phụ trợ thôi. Những nghiệp vụ (Business logics) của hệ thống có thể được sử dụng một trong các công cụ đó, nhưng những công cụ đó không phải là bản chất của các nghiệp vụ. Nếu cần con có thể thay thế Database này thành Database khác hoặc chuyển sang dùng Framework khác, nhưng các nghiệp vụ trong hệ thống của con vẫn như vậy.
Ý của Chú là sao?
Vấn đề của con là tin rằng các nghiệp vụ của phần mềm phụ thuộc vào các công cụ của Database. Sẽ không có chuyện đó hoặc có ít thôi nếu con cung cấp kiến trúc phần mềm tốt.
Chú nói nghe khó hiểu quá. Làm sao để xây dựng các nghiệp vụ mà lại không dùng đến các công cụ mà chúng phải dùng chứ.
Chú không có nói chúng ta không dùng các công cụ của Database, Chú nói chúng ta không nên phụ thuộc vào các công cụ để phát triển dự án. Các quy tắt nghiệp vụ sẽ không cần biết loại Database nào sẽ được dùng.
Vậy làm sao để có được các nghiệp vụ sử dụng các công cụ mà lại không biết về các công cụ?
Con hãy đảo ngược sự phụ thuộc này lại. Nghĩa là con có database phụ thuộc vào các nghiệp vụ, bây giờ con làm cho các nghiệp vụ không còn phụ thuộc vào database.
Vô lý quá vậy Chú.
Bình tĩnh, Chú đang nói với tư cách là một Software Architecture. Trong thiết kế phần mềm có một nguyên lý gọi là Dependency Inversion Principle. Nguyên lý này nói là những thứ low level sẽ phụ thuộc vào những thứ high level hơn, không được ngược lại.
Khó hiểu quá! những thứ high level ( Con đoán ý Chú là các nghiệp vụ – business logics) gọi xuống những thứ low level ( Con đón ở đây là database nè). Thế thì những thứ high level phụ thuộc vào low level cũng giống như callers thì phụ thuộc vào callees. Ai cũng hiểu vậy hết chơn hết chội (ai cũng hiểu vậy cả).
Tại thời điểm runtime thì đúng (lúc chạy chương trình). Nhưng tại thời điểm compile time (lúc biên dịch code hay viết code) chúng ta muốn đảo ngược các phụ thuộc này. Source code của high level (các nghiệp vụ) sẽ không cần biết source code ở low level (code để kết nối, thao tác với database)
Sao được Chú! mình gọi một cái gì đó mà không cần biết đến nó sao được.
Được chứ. Cái đó gọi là lập trình hướng đối tượng (OOP).
Con biết lập trình hướng đối tượng nè. Lập trình hướng đối tượng là việc tạo các classes (hay objects) từ thế giới thực vào trong phần mềm, các đối tượng (objects) thì có các thuộc tính (properties) và các hành vi (behaviors). Các đối tượng tương tác với nhau bằng cách gọi các functions của nhau. OOP là một cách để tổ chức code trực quan hơn.
Con biết chỉ có vậy thôi hả?
Ai cũng biết vậy mà Chú. Nó đúng mà.
Con nói không sai. Tuy nhiên, việc sử dụng các nguyên lý của lập trình hướng đối tượng sẽ giúp cho con gọi một cái gì đó mà không cần biết tới nó.
Con đồng ý luôn, Vậy làm thế nào đây?
Con có biết trong lập trình hướng đối tượng, các đối tượng có thể gửi tin nhắn cho nhau không?
Dạ, con biết chứ.
Rồi, con có biết là sender (đối tượng gửi message) không cần biết gì về kiểu dữ liệu của receiver (đối tượng nhận message)?
Cái này còn tùy vào ngôn ngữ mình đang dùng. Trong Java thì sender ít nhất cũng biết được base type của receiver. Trong Ruby thì sender ít nhất cũng phải biết receiver có thể handler được message.
Đúng vậy, nhưng cả hai trường hợp sender không hề biết chính xác kiểu dữ liệu của receiver.
Dạ, đúng như vậy.
Vì vậy sender có thể gọi một hàm bên trong receiver mà không cần biết chính xác kiểu dữ liệu của receiver đó.
Dạ, đúng. Con hiểu điều đó. Nhưng sender vẫn phụ thuộc và receiver.
Tại thời điểm chạy chương trình (runtime) thì đúng, nhưng lúc viết code (compile time) thì không. Source code của sender không hề biết cũng không hề phụ thuộc vào source code của receiver. Thức tế thì source code của receiver lại phụ thuộc vào source code của sender.
Không đời nào! con nghĩ là Sender vẫn phụ thuộc vào class mà nó đang gửi message.
Có lẽ chúng ta nên dùng vài dòng code để làm rõ vấn đề hơn. Chú sẽ viết cái này với Java. Đầu tiên là package sender:
package sender;
public class Sender {
private Receiver receiver;
public Sender(Receiver r) {
receiver = r;
}
public void doSomething() {
receiver.receiveThis();
}
public interface Receiver {
void receiveThis();
}
}
Tiếp theo sẽ là package receiver:
package receiver;
import sender.Sender;
public class SpecificReceiver implements Sender.Receiver {
public void receiveThis() {
//do something interesting.
}
}
Con hãy để ý là package receiver đang phụ thuộc vào package sender. Cụ thể là class SpecificReceiver phụ thuộc vào Sender. Con cũng thấy là package Sender không hề biết bất cứ thứ gì trong package Receiver.
Dạ, nhưng Chú đã cheated code. Chú đã đặt interface của receiver bên trong class sender.
Con bắt đầu hiểu vấn đề rồi đó, khá nhanh đấy chứ.
Mà hiểu cái gì vậy Chú? ahihi
Đó là các nguyên lý của kiến trúc phần mềm. Senders sở hữu các interfaces mà receivers phải implement.
Chà..! vậy là con phải dùng các lớp lồng nhau (nested-classes).
Nested-classes chỉ là một trong những cách để đạt được điều đó. Còn nhiều cách khác nữa.
OK Chú. Bây giờ quay lại vấn đề với database mà Chú cháu mình đã nói lúc đầu đi. Chú giải quyết nó thế nào.
Con hãy xem code sau đây nhé. Đầu tiên là source code dành cho business rule.
package businessRules;
import entities.Something;
public class BusinessRule {
private BusinessRuleGateway gateway;
public BusinessRule(BusinessRuleGateway gateway) {
this.gateway = gateway;
}
public void execute(String id) {
gateway.startTransaction();
Something thing = gateway.getSomething(id);
thing.makeChanges();
gateway.saveSomething(thing);
gateway.endTransaction();
}
}
Code cho nghiệp vụ ít quá vậy Chú.
Ví dụ đơn giản cho dễ hiểu thôi con trai. Con có thể thêm nhiều class mới, viết code implement cho nhiều nghiệp vụ khác nếu con muốn.
Dạ, vậy Gateway là gì thế Chú?
Nó cung cấp tất cả các phương thức (methods) để cho business rule truy cập xuống database. Code implemented của nó như sau:
Con hãy chú ý là nó nằm trong package businessRules.
Dạ, con thấy rồi. Còn lớp Something là gì vậy Chú?
Nó là 1 object của business. Chú đặt nó trong package tên là entities.
package entities;
public class Something {
public void makeChanges() {
//...
}
}
Cuối cùng là viết code implement cho BusinessRuleGateway. Đây là class biết về database thực sự đang dùng. Trong ví dụ này, Chú sẽ dùng MySql.
package database;
import businessRules.BusinessRuleGateway;
import entities.Something;
public class MySqlBusinessRuleGateway implements BusinessRuleGateway {
public Something getSomething(String id) {
// use MySql to get a thing.
}
public void startTransaction() {
// start MySql transaction
}
public void saveSomething(Something thing) {
// save thing in MySql
}
public void endTransaction() {
// end MySql transaction
}
}
Một lần nữa, con hãy để ý là các business rules (nghiệp vụ) gọi database lúc runtime (chạy chương trình), nhưng lúc compile time (lúc viết code) thì database package lại phụ thuộc vào businessRules package.
Dạ dạ, con nghĩ là con đã hiểu. Chú dùng đa hình (polymorphism) để ẩn đi implementation của database package từ businessRules package. Nhưng Chú vẫn phải có một interface để cung cấp tất cả các thứ trong database mà business rule cần.
Không phải tất cả. Chúng ta không cung cấp tất cả các thứ trong database cho business rule. Thay vào đó, chúng ta tạo các interface trong business rule chỉ cung cấp những thứ liên quan đến database mà nó cần. Các implemenations của các interfaces này có thể gọi đến các chức năng cụ thể như: insert, delete, update trên database tương ứng mà nó đang dùng.
Dạ! nhưng mà nếu như business rules cần tất cả các chức năng liên quan đến database, như vậy thì Chú phải đặt tất cả các methods đó vào trong gateway interface.
Haizz, hình như con vẫn chưa hiểu vấn đề.
Hiểu gì nữa chứ? Con hiểu quá rõ vấn đề rồi mà.
Mỗi business rule định nghĩa 1 interface để thao tác với database mà nó cần.
Chờ đã, Chú nói cái gì con chưa rõ lắm?
Cái này gọi là Interface Segregation Principle. Mỗi class business rule sẽ chỉ dùng một số chức năng để thao tác với database. Và do đó, mỗi business rule sẽ cung cấp một interface và expose một số methods để thao tác với database.
Nhưng như vậy thì Chú phải có rất nhiều interfaces và phải có rất nhiều class để implement cho các interfaces đó.
À, đúng rồi. Chú thấy giờ con đang bắt đầu hiểu rồi đó.
Nhưng code sẽ nhiều hơn, tốn thời gian hơn? Tại sao mình phải làm vậy chứ?
Thật ra, đó là cách giúp con viết code rõ ràng và tiết kiệm thời gian.
Thôi mà Chú. Điều đó làm code phình to lên và viết nhiều code hơn thì có.
Ngược lại, đây là những quyết định kiến trúc quan trọng cho phép con trì hoãn các quyết định không liên quan.
Chú nói vậy nghĩa là sao?
Nà, có phải lúc đầu con nói là con muốn trở thành một Software Architecture? Con muốn đưa ra những quyết định quan trọng phải không?
Dạ, đó là những gì con muốn.
Trong số các quyết định con đưa ra là về: database, web api và các frameworks.
Dạ đúng rồi, nhưng Chú lại nói là những quyết định đó không quan trọng. Chúng là những thứ không liên quan.
Chính xác, những quyết định này không quan trọng cũng không liên quan. Những quyết định quan trọng mà một Software Architecture đưa ra là những quyết định giúp con KHÔNG đưa ra quyết định về database nào, web api thế nào, dùng framework nào quá sớm.
Nhưng Chú cũng phải đưa ra những quyết định này trước khi làm!
Không, không nên đâu con. Thực sự thì, con cần phải làm mọi cách để làm thế nào để có thể trì hoãn các quyết định đó càng trễ càng tốt, bởi vì làm như vậy sẽ giúp con có thêm nhiều thông tin hơn.
Điều tệ hại là nếu 1 kiến trúc sư, anh ta đã quyết định sử dụng database ngay ban đầu, và sau đó nhận ra rằng chỉ cần lưu files là đủ.
Điều tệ hại là nếu 1 kiến trúc sư, anh ta ngay từ ban đầu suy nghĩ rằng sẽ build ứng dụng trên web-server, nhưng sau đó mới nhận ra rằng, tất cả các teams thực sự chỉ cần là 1 socket interface đơn giản.
Điều tệ hại là nếu 1 kiến trúc sư, anh ta và team của mình đã sớm lựa chọn framework cho dự án, và sau đó nhận ra rằng framework cung cấp nhiều cái mà họ không cần và lại ko đáp ứng hết cái họ cần rồi tự đặt mình vào thế khó.
May mắn là team mà các kiến trúc sư đã xây dựng lên kiến trúc bằng cách nào đó cho phép họ trì hoãn các quyết định đến khi họ thực sự có đủ thông tin để đưa ra lựa chọn cuối cùng.
May mắn là team mà các kiến trúc sư là người biết cách tách kiến trúc của họ ra khỏi các device IO chậm chạp, tốn resouce và các framework để có thể tạo ra các bộ test case nhanh và nhẹ.
May mắn là team mà các kiến trúc sư chỉ quan tâm đến các vấn đề thực sự quan trọng, trì hoãn những cái không quan trọng khác.
Thua luôn, con hết hiểu nổi Chú đang nói cái gì luôn rồi.
Có lẽ con sẽ cần vài năm nữa hoặc hơn… nếu con vẫn chưa thực sự đặt chân vào công việc của 1 kiến trúc sư thực thụ, cậu bé à.
Bài viết được sự cho phép của tác giả Nguyễn Hữu Đồng
Cuộc sống thiệt là thú vị, đã code là phải có bug, muốn không có bug thì đừng code và đôi khi chúng ta cũng phải chấp nhận code là một tính năng và sống chung với nó. Lúc hệ thống của mình nhỏ, xoay đi quảnh lại mình cũng chỉ làm những việc mình làm hằng ngày, chạy task dể serve client, không có cơ hội nhìn ra xem người ta đang làm gì, xã hội phát triển như thế nào rồi, và may mắn thay mình được tạo cơ hội để bước ra, vẫy vùng trên con sông lớn, dù chưa biết mình sẽ đi về đâu nhưng thà một phút huy hoàng rồi chợ tắt còn hơn le lói cả trăm năm, huy hoàng với bản thân thôi cũng đáng giá rồi.
Lan man quá, vào vấn đề chính nào, cái RabbitMQ là gì và tại sao chúng ta nên dùng nó ? Hiện nay ở cái thời mà hệ thống web app của chúng ta lớn lên từng ngày, phân chia thành nhiều node, mỗi node lo làm một việc riêng hoặc hỗ trợ lẫn nhau để xử lí yêu cầu từ người dùng, việc đó đòi phải chúng nó phải chia sẻ được tài nguyên cho nhau và biết được mình đang được giao những gì và lấy danh sách những việc cần làm ở đâu.
Hay đơn giản với một công việc, sự kiện những mỗi thợ lại làm những việc khác nhau, ví dụ khi có chương trình mới sắp lên sóng, mọi người được thông báo và mỗi người lại làm việc theo đúng phần việc của mình.
Áp dụng vào hệ thống web, khi có một yêu cầu được gửi tới bảng thông báo, node thì truy xuất trong database lấy giữ liệu để chuẩn bị gửi cho khách hàng, node thì có nhiệm vụ ghi chú lại lại hôm nay hệ thống đã làm những gì. Mỗi node một việc, nó có thể nhận thông báo từ bảng thông báo hay lại làm nhiệm vụ của một phát thanh viên, thông báo việc đến cho các node còn lại.
Cái thứ đó cái hệ thống thông báo đó bao gồm cả các node, ngừời ta gọi là “message broker system”. Hiểu rõ hơn là hệ thống giao tiếp bằng tin nhắn giữa các hệ thống.
Như trên hình các bạn thấy, hệ thống của chúng ta gồm 4 thành phần “Producers”, “Exchanges”, “Queue” và “Consumer”. Theo hình sẽ thì ta thấy mô hình hoạt động khá đơn giản. Sẽ có một node nào đó tạo ra một tin nhắn, sau đó node đó sẽ gửi tin nhắn đó tới một trong số các Exchange sau đó Exchange sẽ phân phối tin nhắn đó tới các hàng chờ tin nhắn và sau đó, Consumer sẽ nhận tin nhắn từ hàng chờ đó và xử lí nó.
Áp dụng vào thực tế ngoài đời sống, ví dụ bạn là một nhà máy sản xuất bia, và tất nhiên bạn cần khách hàng tiêu thụ bia, bạn không thể gửi trực tiếp sản phẩm của bạn tới từng khách hàng được vì việc này rất tốn chi phí và bạn sẽ phải làm quá nhiều việc dẫn đến việc gì cũng biết mà không biết làm một việc thật tốt. Bạn cần các nhà phân phối bia và các nhà phân phối bia này cũng có thêm một vài đại lí nhỏ và cũng tương tự nhà sản xuất bia, các nhà phân phối này chỉ làm 1 việc là đi phân phối bia tới các đại lí nhỏ, đại lí nhỏ lại phân phối tới các quán tạp hoá, quán nhậu và cuối cùng tới tay ngừời tiêu dùng. Ở đây nhà sản xuất bia tương ứng với Producer, các nhà phân phối tương ứng với các Exchange, các đại lí (các hệ thống bán lẻ) tương ứng với Queue và khách hàng tương ứng với Consumer.
Bạn gái kia xinh qúa trời luôn 😀
Khách hàng uống bia, bia ngon thì khen, bia giờ thì chê, có người còn trả lại bia đòi lại tiền, consumer cũng vậy nếu consumer làm xong việc mà nó nhận từ Queue nó sẽ báo với queue là việc đó xong rồi, cho việc khác còn không thì nó sẽ báo với queue đưa việc đó cho consumer khác làm.
Có nhiều loại Exchange và cũng có loại Queue dễ tính hay khó tính, Exchange sẽ dựa vào các queue đăng kí nhận hàng từ exchange đó và phân phố tin nhắn sao cho hợp lí nhất. Sơ qua thì có 6 loại exchange từ loại chuyên chạy xe đi hỏi từng đại lí có ai muốn lấy hàng hay không cho đến loại exchange giao gì đại lí cũng lấy.
Direct Exchange
Đây là loại Exchange được dùng phổ biến nhất, nó sẽ chuyển tin nhắn đến các queue dựa vào Routing key, đúng thì gửi không đúng thì thôi, không ai nhận thì thôi.
Default exchange
Đây là loại phóng khoáng nhất và vô danh( tức là không có tên à không nó có tên là Default exchange đấy chứ ….. ), tin nhắn sẽ được vận chuyển thẳng tới Queue có tên tùng với Routing key trên tin nhắn.
Topic Exchange
Cũng vận chuyển tin nhắn tới queue đựa vào Routing key nhưng nó khá rộng rãi khi dựa vào Wildcard để xem 2 routing key có match với nhau hay không, ví dụ, “dongden” và “dongden.dev” là 2 routing key match với nhau rồi, vậy thì tin nhắn sẽ được vận đưa tới queue đó.
Header Exchange
Theo cách này mỗi queue khi khai báo nhận tin nhắn từ exchange sẽ phải khi báo rõ mình sẽ nhận tin nhắn có phần header như thế nào, bao gồm những trường và từ khoá như thế nào, exchange sẽ dựa vào tin nhắn và các điều kiện đó mà phân phối tin nhắn.
Fanout Exchange
Đúng như nghĩa fanout exchange “thổi” tin nhắn đến cho mọi queue mà đăng kí nhận từ nó.
Sơ qua vài loại đó thôi nếu bạn muốn tìm hiểu sâu hơn thì vào đây nhé 😀
Lý thuyết suông thì chán lắm “show me the code”
Ở bài viết này mình sẽ làm một ví dụ đơn giản, mình sẽ viết một con server có cho người dùng upload ảnh và sau đó mình sẽ tạo ảnh thumbna và upload chúng lên google storage.
Ở đây mình dùng Golang với Framework Gin để handle việc nhận form và lưu trữ file xuống local.
App của mình sẽ có một Producer chuyên gửi tin nhắn tới Exchange và 2 consumer làm hai việc khác nhau là Resize ảnh và Upload ảnh trong queue lên Google Storage.
package publisher
import (
"github.com/streadway/amqp"
"os"
)
var conn *amqp.Connection
var C *amqp.Channel
func JoinNetWork(){
conn,_ = amqp.Dial(os.Getenv("AMQP_URL"))
C,_ = conn.Channel()
C.ExchangeDeclare("ProcessImage",amqp.ExchangeHeaders,true,false,false,false,nil)
C.ExchangeDeclare("UploadImage",amqp.ExchangeHeaders,true,false,false,false,nil)
}
Như các bạn trong hình, sau khi mình lưu xuống local mình có hai function để kêu thằng Publisher để message vào Queue để hai anh chàng Consumer kia làm việc.
Ở đây mình dùng 3 connection và dùng 3 channel trên 3 connection đó, dùng 2 Exchange khác nhau để cho nó rõ ràng, các bạn có thể dùng 1 exchange duy nhất nếu các bạn muốn.
Cùng xem hai Consumer cuả mình có gì nào.
package consumer
import (
"encoding/json"
mystorage "github.com/dongnguyenltqb/go-rabbit/storage"
"github.com/dongnguyenltqb/go-rabbit/utils"
"github.com/streadway/amqp"
"os"
)
var C2 *amqp.Channel
var tasks_upload <- chan amqp.Delivery
func uploadWorker(pool <- chan amqp.Delivery){
for{
task := <- pool
var object mystorage.ObjectAddress
if err := json.Unmarshal(task.Body,&object); err != nil{
task.Reject(true)
utils.Logger("error",err)
continue
}
finished := make(chan bool)
go mystorage.UploadToGCloudStorage(object.FileName,finished)
if result := <- finished ; result == true {
task.Ack(false)
} else {
task.Reject(true)
}
}
}
func runUploadWorker(numWorker int){
for i:=1;i<numWorker;i++{
go uploadWorker(tasks_upload)
}
}
func InitUploadConsumer(){
conn,err := amqp.Dial(os.Getenv("AMQP_URL"))
C2,err = conn.Channel()
if err!=nil {
panic(err)
}
C2.QueueDeclare("UploadImageToGCloud",true,false,false,false,nil)
C2.QueueBind("UploadImageToGCloud","","UploadImage",true, map[string]interface{}{
"type":"image/jpeg",
"job":"upload",
})
tasks_upload,_ = C2.Consume("UploadImageToGCloud","UploadImage",false,true,false,false,nil)
go runUploadWorker(NumWorker)
}
Đầu tiên là upload_consumer, nó sẽ đăng kí lắng nghe trên UploadImage exchange và mỗi khi nào có tin nhắn mới nó sẽ dựa vào thông tin có trong tin nhắn đó để xử lí, nếu xử lí ko được thì nó lại lại và làm tiếp cái khác nếu có.
Tiếp theo là resize_consumer, cũng hoạt động tương tự chỉ khác là sau khi Resize xong nó lại gọi thằng Publisher ra nhờ Publiser gửi tin nhắn lên exchange rằng có cái gì đó mới cần dược Upload Consumer xử lí.
package consumer
import (
"encoding/json"
"fmt"
"github.com/disintegration/imaging"
mystorage "github.com/dongnguyenltqb/go-rabbit/storage"
"github.com/dongnguyenltqb/go-rabbit/utils"
"github.com/streadway/amqp"
"os"
"strings"
)
var C1 *amqp.Channel
var NumWorker int
func ResizeWorker(pool <-chan amqp.Delivery){
for{
task := <- pool
fmt.Println(utils.ApplyStyle("bold","yellow","Resizing image"))
var object mystorage.ObjectAddress
if err := json.Unmarshal(task.Body,&object);err != nil {
task.Reject(true)
utils.Logger("error",err)
continue
}
srcImage, err := imaging.Open("storage/image/"+object.FileName)
if err != nil {
task.Reject(true)
utils.Logger("error",err)
continue
}
dstImage200 := imaging.Resize(srcImage, 200, 0, imaging.Lanczos)
resizedFileName := "200@"+strings.TrimLeft(object.FileName,"/image/")
err = imaging.Save(dstImage200,"storage/image/"+resizedFileName)
if err != nil {
task.Reject(true)
utils.Logger("error",err)
continue
}
task.Ack(false)
resizedObject := mystorage.ObjectAddress{
FileName: resizedFileName,
}
go mystorage.PushTaskToExchangeUploadImage(resizedObject)
}
}
func runResizeWorker(numWorker int){
for i:=0;i<=numWorker;i++{
go ResizeWorker(tasks_resize)
}
}
var tasks_resize <- chan amqp.Delivery
func InitResizeConsumer(){
conn,err := amqp.Dial(os.Getenv("AMQP_URL"))
C1,err = conn.Channel()
if err!=nil {
panic(err)
}
C1.QueueDeclare("ResizeImage",true,false,false,false,nil)
C1.QueueBind("ResizeImage","","ProcessImage",true, map[string]interface{}{
"type":"image/jpeg",
"job":"resize",
})
tasks_resize,_ = C1.Consume("ResizeImage","ResizeImageWorker",false,true,false,false,nil)
go runResizeWorker(NumWorker)
}
Về cơ bản App sau này mình có thể clone app của mình ra thành nhiều thành phần nhỏ khác nhau và làm mỗi một việc như “ Handle Upload Form”, “Upload” và “Resize” chúng nó có thể giao tiếp với nhau dễ dàng qua RabbitMQ.
Các bạn có thể clone source code của mình ở đây và bình luận giúp mình chỗ nào cần cải thiện, nếu hay các bạn vỗ tay cho mình nhé.
12h11 đêm rồi, mình chắc cũng nên dừng bút tại đây, các ơn các bạn đã đọc bài. Hẹn gặp lại trong bài viết sau.
Có bao giờ bạn từng thắc mắc là chiếc máy tính mà bạn đang sử dụng có từ khi nào chưa? và hình dáng ban đầu của nó ra sao, các máy tính thời xưa trông sẽ như thế nào không?
Vâng ! Phải trải qua giai đoạn gần 2 thế kỉ hình thành, phát triển và tồn tại thì chúng ta mới có những chiếc máy tính mạnh mẽ mà gọn nhẹ như hiện nay đấy
Và hôm nay, hãy cùng Blog Chia Sẻ Kiến Thức tóm lược lại các mốc thời gian quan trọng trong quá trình phát triển của máy tính nhé.
#1. Mục đích người ta phát minh ra máy tính?
Xin khẳng định ngay với các bạn rằng, mục đích ban đầu của máy tính không phải là để giải trí, chơi game đâu nhé. Mà mục đích của nó là để tính toán sao cho nhanh nhất và hiệu quả nhất có thể.
Vào những năm 1880, dân số Mỹ nhiều đến mức phải mất hơn 7 năm để các nhà dân số tính toán và lập bảng kết quả điều tra dân số.
Chính vì thế mà nhu cầu về một chiếc máy có khả năng tính toán nhanh và chính xác là vô cùng quan trọng và cần thiết.
Lưu ý: đây chỉ là bài viết tóm lược các mốc thời gian được công bố, có thể sẽ không đầy đủ 100% nhưng nói chung là nó cũng cho chúng ta thấy được cái nhìn khái quát nhất về lịch sử hình thành của chiếc máy tính hiện đại như ngày nay. OK !
#2. Giai đoạn sơ khai, các máy tính “cơ học”
Năm 1801: Ông Joseph Marie Jacquard người Pháp, do nhu cầu muốn tối đa hóa tốc độ và tối ưu nguồn nhân công nên đã phát minh ra máy dệt sử dụng thẻ gỗ đục lỗ để tự động dệt các thiết kế vải.
=> Đây cũng chính là ý tưởng và mô hình cho chiếc máy tính đầu tiên.
Năm 1822: Charles Babbage – một nhà toán học người Anh đã có ý tưởng về một máy tính có thể điều khiển bằng hơi nước, có thể tính toán các bảng số.
Sau đó, ông đệ trình lên chính phủ Anh và đã được chính phủ Anh tài trợ cho ông kinh phí nghiên cứu và phát triển.
Tuy nhiên, có lẽ do những rào cản công nghệ thời bấy giờ mà dự án đã thất bại. Phải đến hơn một thế kỉ sau thì chiếc máy tính đầu tiên mới được ra đời, nhưng theo nhiều nguồn tin thì ông vẫn được xem như là “cha đẻ” của máy tính.
Năm 1890: Như đã đề cập ở trên, nhằm đáp ứng nhu cầu tính toán điều tra dân số. Ông Herman Hollerith đã thiết kế một hệ thống thẻ đục lỗ để tính toán cuộc điều tra dân số năm 1880, và chiếc máy này đã giúp hoàn thành công việc trong ba năm và tiết kiệm được hàng triệu đô cho chính phủ.
Và từ những gì đã làm được, cũng như mong muốn của ông trong tương lai thì ông đã thành lập ra một công ty – nó là tiền thân của tập đoàn IBM hiện nay.
Năm 1936: Nhà khoa học thiên tài trên rất nhiều lĩnh vực – Alan Turing trình bày khái niệm về một cỗ máy có khả năng tính toán bất cứ thứ gì có thể tính toán được. Các khái niệm cốt lõi của máy tính hiện đại dựa trên ý tưởng này của ông.
#3. Giai đoạn cận máy tính kỹ thuật số
Năm 1941: Atanasoff (người Mỹ) và sinh viên của ông (Clifford Berry), đã thiết kế ra một chiếc máy tính có khả năng giải quyết 29 phương trình cùng lúc.
Đây được xem là chiếc máy tính kỹ thuật số đầu tiên trên thế giới, và nó có khả năng lưu trữ thông tin trên bộ nhớ của chính nó.
Năm 1943 – 1944: Tại Đại học Pennsylvania (một trường đại học danh tiếng và lâu đời bậc nhất của nước Mỹ cho tới hiện tại), 2 giáo sư là John Mauchly và J. Presper Eckert cũng đã cho ra đời Electronic Numerical Integrator and Calculator (ENIAC).
Chiếc máy tính này có kích thước rất đồ sộ, chiếm hết một căn phòng với diện tích 6x12m, cao 2.4m. Với khả năng xử lý 5.000 phép tính/giây – nhanh hơn bất kì một máy móc nào thời bấy giờ.
#4. Giai đoạn của máy tính kỹ thuật số phát triển vũ bão
Năm 1947: William Shockley, John Bardeen và Walter Brattain – 3 con người này đã thay đổi cả thế giới.
Tại Bell Laboratories (Phòng thí nghiệm Bell) đã phát minh ra bóng bán dẫn. Có thể nói mọi thiết bị điện tử mà chúng ta đang dùng ngày nay là đều từ phát minh này mà có được.
Năm 1953: Con trai của Giám đốc điều hành IBM, Thomas Johnson Watson Sr đã phát minh ra IBM 701 EDPM để giúp cho Liên Hợp Quốc có thể dễ dàng theo dõi Triều Tiên trong chiến tranh.
Năm 1954: Để đáp ứng nhu cầu quốc phòng thì hệ thống phòng thủ tính toán khổng lồ SAGE đã được thiết kế với nhiệm vụ là để theo dõi rada thời gian thực. Hệ thống khổng lồ này nặng tới 300 tấn và chiếm diện tích cả một gian phòng.
Và cũng trong năm này thì ngôn ngữ lập trình FORTRAN (viết tắt của từ FORmula TRANslation) được phát triển bởi một nhóm lập trình viên tại IBM do John Backus dẫn đầu.
Năm 1958: Jack Kilby và Robert Noyce cho ra đời mạch tích hợp, được gọi là chip máy tính. Có thể nói đây là phát minh quan trọng bậc nhất trong ngành công nghiệp máy tính.
Cũng chính vì công trình vĩ đại này mà Jack Kilby đã nhận được giải Nobel Vật lý năm 2000.
Năm 1960: NEAC 2203 – một chiếc máy tính bán dẫn của hãng Nippon (NEC) được ra đời với mục đích cho các lĩnh vực kinh doanh, khoa học, ứng dụng kỹ thuật.
=> Và đây cũng là một trong những chiếc máy tính bán dẫn sớm nhất ở Nhật Bản.
Năm 1964: Nhà phát minh Douglas Engelbart đã công khai nguyên mẫu của máy tính hiện đại, với chuột và giao diện người dùng đồ họa (GUI).
Đây thực sự là một bước tiến giúp máy tính tiến gần hơn với người dùng phổ thông, khi mà trước đó máy tính chỉ được dùng cho mục đích khoa học và quân sự là chính.
Cũng vào năm 1964 thì IBM System/360 được giới thiệu là một chiếc máy tính có thể sử dụng được cho cả mục đích thương mại lẫn khoa học mà không cần nâng cấp phần mềm.
System/360 với phiên bản cao cấp hơn có vai trò lớn trong các sứ mệnh của con tàu vũ trụ Apollo của NASA khám phá vũ trụ thời đó.
Năm 1964: CDC 6600 ra đời bởi kiến trúc sư máy tính đại tài Seymour Cray, nó là bộ máy nhanh nhất trên thế giới vào thời điểm đó.
Và cho đến tận năm 1969, chính Cray đã phá vỡ kỉ lục đó với việc thiết kế ra “siêu máy tính” tiếp theo của ông.
Năm 1965: Công ty DEC cho ra đời DEC PDP-8, đây là chiếc máy tính mini đầu tiên được thương mại hóa thành công. DEC PDP-8 đã bán được hơn 50.000 chiếc thời bấy giờ.
Chúng có thể thực hiện mọi công việc mà System/360 có thể làm được, nhưng giá thành thì chỉ khoảng 16.000 USD, trong khi System/360 của IBM lên tới hàng trăm ngàn USD.
Năm 1969: Tại phòng nghiên cứu của Bell ( Bell Labs ) sản xuất UNIX, một hệ điều hành đa nền tảng hàng đầu tiên thế giới..
Được viết bằng ngôn ngữ lập trình C, UNIX sớm trở thành hệ điều hành được lựa chọn tại nhiều công ty lớn và các tổ chức chính phủ. Tuy nhiên, nó không được nhiều người dùng phổ lựa chọn, đơn giản bởi vì nó khá là phức tạp.
Năm 1970: Công ty Intel mới thành lập và đã công bố sản phẩm Intel 1103, và Dynamic Access Memory (DRAM) đầu tiên của họ.
Năm 1971: Kenbak-1 ra đời, sản phẩm này được coi là máy tính cá nhân đầu tiên trên thế giới nhưng nó sớm thất bại về mặt thương mại hóa, vì xử lí chậm chạp, không có bộ vi xử lý và không bán ra được nhiều.
Cũng trong thời gian này thì một lãnh đạo của một nhóm kỹ sư của IBM (có tên là Alan Shugart) đã phát minh ra “đĩa mềm”
Năm 1973: Một thành viên trong đội nghiên cứu của hãng Xerox (có tên Robert Metcalfe), đã phát triển ra Ethernet để kết nối nhiều máy tính và phần cứng khác.
Năm 1974 – 1977: Một loạt các máy tính cá nhân lẫn công ty ra đời như: Scelbi & Mark-8 Altair, IBM 5100, TRS-80 và PEToreore.
Năm 1975: Altair 8800 là bộ máy tính ra đời bởi MITS. Và cũng từ đây, 2 chuyên viên máy tính Paul Allen và Bill Gates đã đề nghị viết phần mềm cho Altair, với ý tưởng sử dụng ngôn ngữ BASIC mới.
Sau đó thì vào ngày 4 tháng 4, cả hai đã thành lập công ty phần mềm cho riêng họ, và đó chính là tập đoàn Microsoft bây giờ.
Năm 1976: Apple I được hình thành bởi Steve Wozniak, sau đó ông cùng hợp tác với Steve Jobs. Và Apple I cũng chính là chiếc máy tính đầu tiên có bảng mạch đơn.
Nói chung là Steve Jobs và Steve Wozniak đã đặt nền móng cho sự ra đời của máy tính Apple và cũng như đế chế Apple hiện tại (vào đúng ngày cá tháng 4).
Năm 1976: Cũng trong năm đó thì Cray-1 (một sản phẩm của kiến trúc sư máy tính Seymour Cray thiết kế) được đánh giá là chiếc máy tính mạnh mẽ nhất thời bấy giờ.
Mặc dù có giá lên tới 5 – 10 triệu USD thời bấy giờ nhưng vẫn rất đắt hàng. Do nó vượt trội hẳn so với các đối thủ khác trên thị trường thời điểm đó.
Năm 1977: TRS-80 của Radio Shack lần đầu tiên được thương mại với 3.000 máy, và chúng được bán rất chạy.
Năm 1977: Stave Jobs và Wozniak đã cho ra mắt Apple II tại hội chợ công nghệ West Coast Computer Faire đầu tiên.
Năm 1978-1979: VisiCalc – chương trình bảng tính trên máy tính đầu tiên đã ra đời. Việc xử lý văn bản đã trở nên dễ dàng hơn rất nhiều, chế chức năng in ấn đã được bổ sung.
Năm 1981: Acorn – máy tính cá nhân đầu tiên của IBM đã được giới thiệu. Acorn sử dụng con chip của Intel, chạy trên hệ điều hành MS-DOS của Microsoft, hai ổ đĩa mềm và màn hình màu tùy chọn.
Chiếc máy này đã thành công và thuật ngữ “PC” cũng đã trở nên thông dụng từ đây !
Năm 1981: Osborne 1 là chiếc máy tính di động được thương mại hóa đầu tiên, nó nặng tới 10,8kg và có giá dưới 2000 USD.
Năm 1983: Lisa của hãng Apple là chiếc máy tính cá nhân đầu tiên có GUI. Ngoài ra thì Lisa cũng có một menu sổ xuống và các icon biểu tượng. Mặc dù nó thất bại nhưng cuối cùng được phát triển thành Macintosh.
Năm 1983: Hewlett-Packard 150 ra đời. HP 150 là chiếc máy tính áp dụng công nghệ màn hình cảm ứng đầu tiên được thương mại hóa.
Kích thước màn hình cảm ứng là 9-inch, được trang bị các bộ thu và phát hồng ngoại ở xung quanh để phát hiện ra vị trí ngón tay của người dùng.
Năm 1985: Microsoft đã công bố hệ điều hành Windows. Đây là sự đáp trả của Microsoft đối với GUI của Apple.
Năm 1985: Tiên miền .com đầu tiên đã được đăng ký vào ngày 15 tháng 3.
Năm 1986: Công ty Compaq đã cho ra mắt Deskpro 386. Với kiến trúc 32-bit của nó cung cấp tốc độ tương đương với máy tính mainframe.
Năm 1990: Tim Berners-Lee – một nhà nghiên cứu tại CERN đã phát triển ra HTML (HyperText Markup Language), tạo ra World Wide Web (www).
Năm 1993: Đây được xem là khoảng thời gian mà máy tính có tiến bộ vượt bậc nhất, đó là nhờ bộ vi xử lý Pentium huyền thoại của Intel. Nó đã thúc đẩy việc sử dụng đồ họa và âm nhạc trên máy tính.
Năm 1994: Máy tính PC đã không còn dành cho công việc nữa, nó đã có thể trở thành chiếc máy giải trí với những tựa game thời đó như “Command & Conquer”, “Alone in the Dark 2”, “Theme Park”….
Năm 2001: Apple cho ra đời hệ điều hành Mac OS X, cung cấp khả năng đa tác vụ ưu tiên, cùng nhiều tính năng hay ho khác.
Ngay sau đó thì Microsoft cũng tung ra Windows XP, có GUI được thiết kế lại với nhiều thay đổi đáng kể.
Năm 2003: Thương mại hóa bộ xử lý 64-bit đầu tiên, Athlon 64 của AMD.
Năm 2006: Apple giới thiệu chiếc MacBook Pro thần thánh, một chiếc máy tính di động lõi kép dựa trên Intel đầu tiên, cũng như là iMac dựa trên Intel.
Năm 2009: Microsoft tung ra hệ điều hành Windows 7 với vô số các cải tiến đáng kể về trải nghiệm người dùng.
Năm 2011: Google phát hành Chromebook, máy tính xách tay chạy hệ điều hành Chrome OS do chính Google phát triển.
Năm 2015: Microsoft phát hành Windows 10 đến tay người dùng. Và cho đến nay, năm 2021 thì Windows 10 vẫn đang được cải tiến từng ngày.
Năm 2016: Chiếc máy tính lượng tử đầu tiên có thể lập trình lại đã được tạo ra. “Trước đây, chưa có bất kỳ nền tảng máy tính lượng tử nào có khả năng lập trình các thuật toán mới vào hệ thống của họ. Chúng thường được thiết kế riêng để giải quyết một thuật toán cụ thể,” theo lời Shantanu Debnath, nhà vật lý lượng tử và kỹ sư quang học tại Đại học Maryland, College Park.
Năm 2017: Phát triển một chương trình mới mang tên “Molecular Informatics” sử dụng các phân tử như máy tính. Anne Fischer, quản lý chương trình tại Văn phòng Khoa học Quốc phòng của DARPA, cho biết: “Hóa học cung cấp một tập hợp các tính chất phong phú mà chúng ta có thể khai thác để lưu trữ và xử lý thông tin một cách nhanh chóng và có thể mở rộng. Hàng triệu phân tử tồn tại, và mỗi phân tử có cấu trúc nguyên tử ba chiều độc đáo cũng như các biến số như hình dạng, kích thước hoặc thậm chí màu sắc. Sự phong phú này cung cấp một không gian thiết kế rộng lớn để khám phá các cách mới và đa giá trị để mã hóa và xử lý dữ liệu vượt ra ngoài các số 0 và 1 của các kiến trúc số hiện tại.”
Năm 2019: Một nhóm nghiên cứu tại Google trở thành những người đầu tiên chứng minh được “quyền tối thượng lượng tử” — tạo ra một máy tính lượng tử có thể thực hiện các tính toán vượt trội hơn so với máy tính cổ điển mạnh nhất. Họ mô tả chiếc máy tính này, có tên gọi “Sycamore,” trong một bài báo cùng năm trên tạp chí Nature. Đạt được lợi thế lượng tử – khi một máy tính lượng tử giải quyết vấn đề với các ứng dụng thực tế nhanh hơn máy tính cổ điển mạnh nhất – vẫn còn là một chặng đường dài.
Năm 2022: Siêu máy tính đầu tiên đạt mức exascale và cũng là nhanh nhất thế giới, Frontier, đã được đưa vào hoạt động tại Cơ sở Tính toán Lãnh đạo Oak Ridge (OLCF) ở Tennessee. Được xây dựng bởi Hewlett Packard Enterprise (HPE) với chi phí 600 triệu USD, Frontier sử dụng gần 10.000 CPU AMD EPYC 7453 với 64 lõi và gần 40.000 GPU AMD Radeon Instinct MI250X. Máy này đánh dấu kỷ nguyên của tính toán exascale, đề cập đến các hệ thống có thể đạt hơn một exaFLOP sức mạnh – được dùng để đo hiệu suất của hệ thống. Chỉ có một máy – Frontier – hiện có khả năng đạt được mức hiệu suất này. Hiện nó đang được sử dụng như một công cụ hỗ trợ khám phá khoa học.
#5. Đánh giá sự phát triển của máy tính
Như các bạn có thể thấy, từ năm 2001 cho tới nay thì ngành công nghiệp máy tính nói chung đã phát triển không ngừng.
PC đã trở thành thiết bị giải trí đa phương tiện, một thiết bị làm việc không thể thiếu cho tất cả mọi đối tượng, từ phổ thông cho tới doanh nghiệp hay chính phủ.
Sự phát triển của máy tính được song hành với sự phát triển của ngành bán dẫn, của những thế hệ mạch tích hợp ngày càng mạnh mẽ. Và tất nhiên, không thể không kể tới sự phát triển về phần mềm theo máy để đáp ứng các nhu cầu của con người.
Trong tương lai, khi giới hạn vật lý của bóng bán dẫn ngày càng gần, chúng ta sẽ chứng kiến những chiếc máy tính thế hệ mới – máy tính lượng tử. Không còn là bóng bán dẫn đơn thuần mà là từ những hạt cơ bản và tốc độ là gấp nhiều lần hiện nay.
Trong quá trình tổng hợp sẽ không tránh khỏi những thiếu sót, mong các bạn hãy thông cảm và nếu có bất kỳ ý kiến gì thì hãy để lại comment phía bên dưới nhé !
CV là thứ không thể thiếu khi apply vào các vị trí tuyển dụng tại Việt Nam, nghe CV thì rất quen nhưng bạn đã thật sự biết CV là gì và vì sao nó lại quan trọng trong quá trình ứng tuyển của bạn chưa? Cùng TopDev theo dõi bài viết dưới đây, chúng tôi sẽ giải đáp tất tần tật về CV và hướng dẫn cách viết CV xin việc gây ấn tượng với nhà tuyển dụng.
Tổng quan về CV
CV là gì?
CV là gì?
CV là viết tắt của cụm từ Curriculum Vitae xuất phát từ tiếng La-tinh, được dịch sang tiếng Anh là course of life. CV là bản ghi lại chi tiết về những sự kiện trong cuộc đời ứng viên, bao gồm quá trình học tập, thành tựu nghiên cứu, kinh nghiệm làm việc và các kỹ năng,…
CV còn có một tên gọi khác ở Việt Nam là hồ sơ xin việc (nhưng khác với bộ hồ sơ xin việc truyền thống). CV sẽ giúp nhà tuyển dụng có cái nhìn tổng quan về bạn. Từ đó quyết định bạn có phù hợp với vị trí họ tuyển dụng và có nên mời bạn đi phỏng vấn hay không.
CV nên bao gồm những gì?
Muốn gây ấn tượng, trước khi cố gắng tạo ra sự khác biệt bạn cần đảm bảo đã cung cấp đủ những gì nhà tuyển dụng cần. Các thông tin chia sẻ dưới đây sẽ cho bạn biết một CV xin việc cần có những gì:
1. Thông tin cá nhân
Vì có vai trò như một sơ yếu lý lịch chính vì thế ứng viên cần cung cấp đầy đủ các thông tin cá nhân cho nhà tuyển dụng. Các thông tin này thường sẽ bao gồm:
Họ và tên đầy đủ của bản thân
Ngày tháng năm sinh
Nơi sinh sống hiện tại
Số điện thoại liên lạc
Địa chỉ email
Các thông tin này thường được viết đầu tiên và ở trên cùng trong bố cục CV để nhà tuyển dụng dễ dàng quan sát được. Chẳng hạn địa chỉ nhà bạn quá xa với công ty thì có thuận tiện khi đi làm hay không, hoặc độ tuổi của ứng viên có đáp ứng được yêu cầu của công ty hay không… Nếu không thỏa mãn những điều kiện này, CV sẽ được bỏ qua mà không xem tiếp đến các thông tin tiếp theo.
Thông tin này bắt buộc phải xuất hiện trong tất cả mọi CV. Với trường hợp bạn là sinh viên mới tốt nghiệp chưa có kinh nghiệm làm việc thực tế tại một công ty ở vai trò chính thức nào thì các thông tin này nên được thay thế bằng kinh nghiệm tham gia các hoạt động khi còn ở trường đại học hoặc việc làm thêm.
Mục đích chính của phần thông tin về kinh nghiệm làm việc là để nhà tuyển dụng có thể dễ dàng quan sát và nắm bắt được những kinh nghiệm bạn sở hữu có đáp ứng được vị trí mà họ đang tuyển hay không. Chính vì thế hãy liệt kê những kinh nghiệm cần thiết thay vì liệt kê một cách dàn trải tất cả mọi thứ. Mục kinh nghiệm làm việc quá dài dòng và dàn trải nhiều thông tin sẽ không được nhà tuyển dụng đánh giá cao.
CV cần có những gì?
3. Trình độ học vấn và các chứng chỉ
Trong thông tin này, ứng viên nên đề cập đến việc mình đang học trường nào, đã tốt nghiệp hay chưa và chuyên ngành mình đã theo học. Ngoài ra, nếu đang theo học các khóa học chuyên môn có liên quan đến công việc cũng có thể đề cập đến trong CV như một cách để thể hiện năng lực của bạn.
Thông thường trong phần thông tin học vấn, ứng viên sẽ điền tên trường, ngành theo học và thời gian học (nên điền năm bắt đầu và năm tốt nghiệp). Nếu điểm GPA tốt nghiệp cao bạn hoàn toàn có thể thêm vào trong CV để tạo ấn tượng với nhà tuyển dụng.
Hoặc trong thời gian học, bạn có tham gia nghiên cứu khoa học hay thực hiện các đề án nghiệp vụ có tính chất phục vụ cho công việc mình đang ứng tuyển thì cũng có thể thêm vào trong CV. Một bằng cấp khác quan trọng không kém là chứng chỉ tiếng Anh và tin học. Ứng viên có thể điền thông tin chứng chỉ vào CV nếu cảm thấy cần thiết.
Về kỹ năng chuyên môn, có một sai lầm mà nhiều người mắc phải là tự đưa ra các kỹ năng và thang điểm cho kỹ năng đó của mình. Thực tế thì việc làm này không thể hiện tính khách quan và không có bất cứ tiêu chuẩn nào cho việc chấm điểm đó của bạn cả. Vậy nên hãy từ bỏ cách trình bày kỹ năng như thế này trong CV của mình.
Thay vào đó, hãy liệt kê những kỹ năng quan trọng và theo bạn, là cần thiết cho công việc mà bạn đang ứng tuyển. Chẳng hạn, với vị trí ứng tuyển liên quan đến công việc của lập trình viên, bạn nên trình bày các kỹ năng liên quan đến kỹ thuật như ngôn ngữ lập trình có thể sử dụng,… Kết hợp thêm với một số kỹ năng mềm khác sẽ giúp bạn dễ dàng hơn trong việc chinh phục nhà tuyển dụng.
Nội dung này có thể được chia sẻ ngắn gọn trong vài dòng để nhà tuyển dụng có thể thấy được mục tiêu ngắn hạn và dài hạn của bạn trong công việc này là gì, định hướng phát triển của bạn trong tương lai ra sao.
Tuy nhiên, cũng có nhiều ứng viên lựa chọn không chia sẻ về mục tiêu công việc trong CV. Điều này hoàn toàn phụ thuộc vào mong muốn của bạn, nếu CV đã quá dài thì có thể lược bỏ bớt phần thông tin này và trao đổi chi tiết hơn khi đến với buổi phỏng vấn.
Hiện nay, có khá nhiều công cụ tạo CV miễn phí khác nhau mà ứng viên có thể tham khảo. Với TopDevCV, các ứng viên trong lĩnh vực CNTT có thể dễ dàng tạo được cho mình chiếc CV với đầy đủ các thông tin cần thiết với vai trò là một lập trình viên.
Vai trò của CV là gì?
Có thể nói CV đóng vai trò chủ đạo khi đi xin việc cũng như tuyển dụng. Vì nếu không có sự hiện diện của CV thì các nhà tuyển dụng không thể nắm được thông tin gì về người ứng tuyển. Vì thế, CV là giấy tờ mang thông tin có vai trò rất quan trọng đối với cả 2 phía người ứng tuyển và người tuyển dụng… Hiện nay, nếu người ứng tuyển không thể cung cấp cv; thì 100% người tuyển dụng sẽ không quan tâm ngay từ đầu để tránh mất thời gian với ứng viên này.
Một đơn xin việc hoàn chỉnh sẽ không thể thiếu 1 thư xin việc (cover letter) và CV. Có một vài công ty sẽ yêu cầu thêm một vài thông tin xác nhận từ địa phương. Nhưng có một số thì không. Những thông tin đó sẽ được bổ sung sau khi được trúng tuyển vị trí làm việc; chứ nó không thật sự cần thiết khi chỉ vừa mới đi xin việc.
Viết một CV ấn tượng là bước quan trọng để thu hút sự chú ý của nhà tuyển dụng và tạo ra cơ hội cho bạn trong quá trình tìm kiếm việc làm. Dưới đây là hướng dẫn các bước để viết một CV chuyên nghiệp và ấn tượng:
1. Thông tin cá nhân + vị trí ứng tuyển
Tên đầy đủ: Đặt ở vị trí trung tâm và sử dụng font chữ lớn hơn các phần khác.
Vị trí ứng tuyển: Càng cụ thể càng tốt (tránh ghi chung chung: Thực tập sinh, Nhân viên văn phòng,…)
Hình ảnh: Nếu bạn có một tấm ảnh chuyên nghiệp và tươi tắn có thể gây ấn tượng tốt với nhà tuyển dụng (nếu bạn không tự tin về hình ảnh thì phần này không bắt buộc).
Thông tin liên lạc: Bao gồm địa chỉ email, số điện thoại, và địa chỉ nhà (có thể không cần quá chi tiết). Đảm bảo email chuyên nghiệp.
Liên kết mạng xã hội chuyên nghiệp: LinkedIn hoặc GitHub (nếu có).
Phần thông tin mở đầu CV chuẩn
2. Tóm tắt mục tiêu nghề nghiệp
Viết một đoạn tóm tắt ngắn gọn (2-3 câu) về kinh nghiệm, kỹ năng chính và mục tiêu nghề nghiệp của bạn. Tập trung vào những gì bạn có thể mang lại cho nhà tuyển dụng.
Ví dụ: Tôi là một chuyên gia phần mềm với 5 năm kinh nghiệm trong lĩnh vực phát triển ứng dụng web. Tôi có kỹ năng chuyên môn về JavaScript, Python và có khả năng làm việc nhóm xuất sắc. Mục tiêu của tôi là áp dụng kỹ năng và kinh nghiệm để gắn bó và đóng góp vào sự phát triển của công ty.
3. Kinh nghiệm làm việc
Liệt kê theo thứ tự thời gian ngược: Bắt đầu từ công việc hiện tại hoặc gần đây nhất.
Thông tin công việc: Bao gồm tên công ty, vị trí công việc, thời gian làm việc và mô tả công việc.
Thành tựu và kết quả cụ thể: Nêu rõ các thành tựu và kết quả bạn đạt được. Sử dụng số liệu và con số để làm nổi bật hiệu quả công việc (ví dụ: “Tăng doanh số bán hàng lên 20% trong 6 tháng”).
Ví dụ:
Chuyên viên Phát triển Phần mềm - Công ty ABC
01/2020 - Hiện tại
- Phát triển và duy trì các ứng dụng web sử dụng JavaScript và Python.
- Tăng hiệu suất hệ thống lên 30% thông qua tối ưu mã và nâng cấp cơ sở dữ liệu.
- Dẫn dắt nhóm 5 người trong dự án triển khai hệ thống CRM mới, hoàn thành trước thời hạn 2 tháng.
Nhân viên IT - Công ty XYZ
06/2017 - 12/2019
- Quản lý và bảo trì hệ thống mạng và máy chủ.
- Giảm thời gian sự cố hệ thống xuống 50% bằng cách cải tiến quy trình và công cụ giám sát.
4. Học vấn
Thông tin chi tiết: Tên trường, bằng cấp, chuyên ngành và thời gian học.
Thành tích học tập: Nếu có thành tích nổi bật như học bổng, giải thưởng hoặc điểm GPA cao, hãy liệt kê chúng.
5. Kỹ năng
Kỹ năng chuyên môn: Liệt kê các kỹ năng liên quan trực tiếp đến công việc bạn đang ứng tuyển (ví dụ: kỹ năng lập trình, kỹ năng phân tích dữ liệu).
Kỹ năng mềm: Bao gồm kỹ năng giao tiếp, làm việc nhóm, quản lý thời gian, v.v.
6. Chứng chỉ và khóa học
Chứng chỉ chuyên môn: Liệt kê các chứng chỉ liên quan đến công việc (ví dụ: chứng chỉ PMP, chứng chỉ Google Analytics).
Khóa học: Bao gồm các khóa học trực tuyến hoặc đào tạo liên quan mà bạn đã hoàn thành.
7. Dự án
Dự án cá nhân hoặc nhóm: Nêu rõ các dự án mà bạn đã tham gia hoặc thực hiện, mô tả ngắn gọn về mục tiêu dự án và kết quả đạt được.
Công nghệ và kỹ thuật sử dụng: Liệt kê các công nghệ, công cụ và kỹ thuật bạn đã sử dụng trong dự án.
8. Hoạt động ngoại khóa và tình nguyện
Hoạt động liên quan: Bao gồm các hoạt động ngoại khóa, câu lạc bộ, tổ chức tình nguyện mà bạn đã tham gia và có liên quan đến công việc.
9. Trình độ ngoại ngữ
Liệt kê rõ các ngôn ngữ bạn biết và mức độ thành thạo của bạn, kèm theo thông tin về chứng chỉ bạn đạt được như IELTs 7.0 hay tiếng Nhật N4,… mục này có thể là điểm cộng cực kì lớn nếu bạn apply vào các vị trí cần ngoại ngữ hoặc công ty nước ngoài.
Đầu tiên, bạn nên chú ý những nền tảng thông tin về kinh nghiệm đặc thù của vị trí mà bạn ứng tuyển nên được viết kĩ càng. Và tất nhiên, nó cần nổi bật hơn các phần kinh nghiệm khác. Ví dụ nếu bạn ứng tuyển vị trí kỹ sư lập trình, thì bạn nên sử dụng mẫu cv lập trình được thiết kế đặc thù; chỉ đưa những kinh nghiệm liên quan đến vị trí lập trình viên vào.
Đặc biệt đối với những công ty bạn chỉ làm ngắn hạn dưới 6 tháng thì đừng nên viết vào cv nhé. Vì nhà tuyển dụng sẽ nghĩ bạn là người thường xuyên nhảy việc trong thời gian ngắn. Và chắc hẳn đó sẽ đem đến ấn tượng xấu cho họ.
Ưu tiên các kỹ năng cần thiết
Việc ưu tiên viết kỹ năng liên quan đến vị trí ứng tuyển đầu tiên sẽ giúp nhà tuyển dụng dù chưa đọc hết cv của bạn. Nhưng cũng 1 phần nào hiểu được bạn đã từng có kinh nghiệm và phù hợp ở vị trí này.
Bên cạnh đó bạn nên nhớ, hãy luôn trung thực với bất cứ thông tin nào mà bạn cung cấp trong cv nhé. Rất khó có thể qua mặt đc các nhà tuyển dụng. Họ đã có kinh nghiệm tuyển dụng qua hàng trăm người . Việc bạn nói dối sẽ rất dễ lộ tẩy trước cái nhìn của họ.
Các mẫu cv online thường chỉ gói gọn trong 1 mặt giấy A4, thông tin liên hệ, kinh nghiệm, kỹ năng nên được tóm tắt hàm xúc, đủ ý nhất có thể. Tránh viết lan man, kể lể dài dòng gây khó hiểu làm HR không hiểu bạn thật sự giỏi ở mảng nào.
Trong phần hình ảnh cá nhân được đính trong cv bạn nên sử dụng hình có tông màu sáng sủa, rõ ràng mặt mũi; không dùng hình chụp tự sướng và đặc biệt là bạn phải dùng hình chính chủ nhé!
Chú trọng đến email rất quan trọng!
Cả email của bạn cũng nên dùng tên thật chứ đừng dùng các email thời “trẻ trâu” của bạn. Cách viết email xin việc cũng rất quan trọng. Bạn không nên đề cập quá nhiều thông tin đã trong email vì những thông đó đã có trong CV.
Email chỉ nên là 1 đoạn giới thiệu bạn biết đến tin tuyển dụng như thế nào. Bạn cảm thấy bạn phù hợp với vị trí của công ty ra sao. Sau đó đính kèm file CV tiếng Anh hoặc tiếng Việt tùy yêu cầu công ty; hoặc nếu công ty không ghi rõ yêu cầu thì bạn có thể đính kèm cả 2 phiên bản cv tiếng Anh và Việt.
Sau bài viết các bạn đã hiểu cv là gì chưa nào? Tất cả những ý trên là câu trả lời cho câu hỏi cv là gì và kèm thêm các tips hiệu quả để các bạn có thể hoàn thiện cv của chính mình và gây được ấn tượng với nhà tuyển dụng.
Quan tâm đến sự trải nghiệm gián tiếp
Nếu là những người mới, có thể chiếc CV cho sinh viên IT mới ra trường (CV IT student) dường như còn quá “non” để đủ sức cạnh tranh. Tuy nhiên, kinh nghiệm nhiều hay ít không quan trọng. Bạn vẫn có thể tạo được lợi thế nếu có sự chuẩn bị khoa học nhất.
Cách ứng viên nhận biết về sự trải nghiệm của bản thân rất quan trọng.
Thách thức lớn nhất đối với các ứng viên nằm ở vấn đề kinh nghiệm. Thế đâu là giải pháp hoàn hảo cho việc xoay chuyển các thách thức này?
Nếu là một ứng viên mới, đừng e ngại về năng lực. Bạn hãy liệt kê những công việc tình nguyện, hoặc các dự án về công nghệ mà bạn/team đã thực hiện, cộng tác,… Ngoài ra, nếu có các sản phẩm khoa học về ngành IT hay đã từng thực tập; làm báo cáo về một vấn đề chuyên sâu nào đó thuộc lĩnh vực IT, hãy tự tin chia sẻ với nhà tuyển dụng.
Đó được gọi là trải nghiệm gián tiếp. Tức sự cộng hưởng về mức độ am hiểu của ứng viên về một khía cạnh có liên quan đến việc giải quyết các vấn đề mà nhà tuyển dụng đặt ra.
Bạn phải tin rằng bạn đang dẫn dắt nhà tuyển dụng đi đúng hướng. Đồng thời, sự lựa chọn thông minh từ các trải nghiệm cá nhân sẽ phản ánh tính xác thực; khả năng phân tích về kiến thức và tiềm năng phát triển của bạn.
Văn phong ngôn ngữ thật sự là điểm nhấn!
Nếu một CV sở hữu cách định dạng – bố cục trình bày (format và visual), tổ chức nội dung (content) đầy đủ, thu hút thì chưa chủ để tạo nên một CV IT chuyên nghiệp. Điểm nhấn quan trọng nhất nằm ở văn phong ngôn ngữ.
Văn phong ngôn ngữ có giá trị quan trọng đối với chất lương CV IT.
Không một nhà tuyển dụng nào dành 5 phút để đọc một CV chứa các câu cú dài ngoằn, phức tạp. Thậm chí, cách viết quá hời hợt; không có sự hiểu biết về văn viết cơ bản sẽ khiến CV của bạn bị out ngay lập tức.
Cách diễn đạt trong CV cần rõ ràng, tránh mơ hồ và thiếu khả thi. Chẳng hạn, bạn ứng tuyển vị trí về Mobile App Developer, thì tính tư duy mạch lạc trong CV IT Developer được nhà tuyển dụng rất quan tâm. Đừng biến CV của bạn trở nên khó đọc, khó hiểu và không có giá trị.
Lời kết
Hãy đọc lại thông tin trong CV để chắc chắn rằng nội dung đều được liên kết với nhau một cách tốt nhất. Chính việc kiểm tra sẽ giúp CV của bạn chỉn chu hơn.
Một điều quan trọng nữa là bạn có thể cập nhật những nội dụng mới. Đâu là điểm mạnh – điểm yếu để định hướng truyền tải nội dung trong CV IT Developer một cách hợp lý. CV cần được bạn update lại nếu bạn có những thay đổi tốt hơn trong hành trình nghề nghiệp. Đó có thể là các kinh nghiệm mới, các dự án với quy mô lớn hơn. Hãy đầu tư cho CV để sẵn sàng cho cuộc chơi tuyển dụng bất cứ lúc nào!
Để trở thành một lập trình viên giỏi hơn mỗi ngày!
Tác giả: Randall Kanna
Giới thiệu
Với lĩnh vực công nghệ, bạn sẽ có vô số vấn đề mới phải tiếp xúc mỗi ngày cũng như phải làm quen với rất nhiều các kỹ thuật được tạo ra mà bạn cần cập nhật càng sớm càng tốt. Ngay khi bạn cảm thấy quen thuộc với một ngôn ngữ lập trình hay một framework mới thì lại có 2, 3 ngôn ngữ mới, framework mới được giới thiệu đến các developer. Để công việc của bạn không trở nên nhàm chán và bắt kịp những xu hướng mới nhất, hãy biết cách nắm bắt chúng một cách tốt nhất!
Update thông tin liên tục sẽ giúp lập trình viên nắm bắt kịp thời công nghệ mới
Lập trình viên chuyên nghiệp nên rèn luyện những thói quen riêng
Học hỏi thông qua thực hành
Rõ ràng ngay từ khi còn bé, để luyện tập cho mình những thói quen chúng ta đều học hỏi chúng qua cách làm nó. Bạn bắt đầu nói ngay cả khi nó không thành câu đầy đủ. Bạn bắt đầu học vẽ bằng cách vẽ. Bạn bắt đầu tập đi bằng cách đi bộ mỗi ngày. Và điều này đã giúp bạn nắm bắt các việc làm mới một cách nhanh chóng.
Với lĩnh vực kỹ thuật và công nghệ cũng tương tự thế. Để lập trình giỏi, bạn sẽ phải luyện tập thật nhiều để tiếp thu thêm những kiến thức mới. Khi tôi bắt đầu làm việc với tư cách là một kỹ sư công nghệ, tôi thường xuyên đọc sách và đánh dấu bằng các thẻ ghi chú để phân rõ các mục cần chú ý. Sau nhiều tháng cố gắng ghi nhớ các công thức và định nghĩa, tôi đã tìm được chính xác vấn đề mình mắc phải. Cho đến khi tôi bắt đầu làm việc theo cách này, kỹ năng của tôi mới bắt đầu được cải thiện một cách nhanh chóng hơn.
Mặc dù tôi thích đọc sách kỹ thuật và vẫn thực hành những công thức đó hàng ngày, nhưng phần lớn thời gian của tôi dành để đọc lướt cuốn sách và sau đó thử ngay một khái niệm mới. Đây là một cách học khó hơn. Tôi sẽ không nói dối bạn – điều đó thật đáng sợ. Nhưng không có gì giúp xây dựng các kỹ năng lập trình mới giống như tự xây dựng một thứ gì đó. Cách nhanh nhất để học viết code là tích lũy qua mỗi ngày.
Chủ động hơn trong học tập
Khi mới bắt đầu học cách viết code, tôi đã dành hàng tháng trời để làm theo các hướng dẫn. Tôi xem hướng dẫn và làm theo từng bước. Không bao giờ cố gắng làm bất cứ điều gì của riêng tôi. Nếu một hướng dẫn quá khó, tôi sẽ chuyển sang làm theo một hướng dẫn khác. Tôi dành hàng giờ mỗi ngày để xem các hướng dẫn. Tôi đã cố gắng sử dụng các kỹ năng học được từ thời đại học và áp dụng chúng vào việc viết code. Tuy nhiên, nó đã không hiệu quả.
Từ đó tôi nhận ra rằng, luyện tập coding cần sự chủ động thay vì bị động. Bạn phải chủ động đi tìm hiểu và học hỏi từ những hướng dẫn của người đi trước, từ sách vở để khắc phục vấn đề mà mình đang gặp phải thay vì chỉ chăm chăm làm theo họ. Hãy rời khỏi phần hướng dẫn ngay khi bạn cảm thấy rằng mình có thể tự làm tốt. Hướng dẫn rất tuyệt khi bạn mới bắt đầu. Nhưng ở một góc độ nào đó, chúng chỉ làm chậm quá trình học của bạn nếu bạn dựa dẫm vào hướng dẫn quá nhiều.
Điều này áp dụng trong mọi quá trình sự nghiệp của bạn. Nếu bạn là một dev mới vào nghề, hãy chọn một dự án nhỏ. Hãy hạn chế làm theo hướng dẫn. Cố gắng tìm ra cách tự xây dựng nó. Đừng cảm thấy tệ nếu bạn chưa thể xây dựng toàn bộ ứng dụng – điều đó tốt! Bắt đầu với các dự án nhỏ và xây dựng.
Và nếu bạn là một dev đã có vài năm kinh nghiệm và muốn chuyển sang machine learning từ kỹ thuật phụ trợ chẳng hạn, hãy chọn một dự án nhỏ và bắt đầu viết code.
Lập trình chuyên nghiệp đòi hỏi nhiều yếu tố khác nhau
Luôn giữ tinh thần học hỏi cao nhất
Học hỏi không ngừng là một trong những kỹ năng cần có của một người lập trình giỏi. Khi bạn mới bắt đầu học cách viết code, lượng tài liệu bạn học hàng ngày có vẻ rất nhiều và bạn đang tiếp thu các khái niệm mới liên tục. Và bạn cảm thấy dường như đang có một nguồn tài nguyên vô tận mà mình học tập.
Lý tưởng nhất là bạn vẫn luôn giữ tinh thần học hỏi ở trạng thái cao nhất dù đã có nhiều năm kinh nghiệm làm việc. Nhưng điều này đôi khi có thể chững lại. Bạn bắt đầu cảm thấy thoải mái trong công việc và sự lười biếng dần khiến bạn trở nên trì trệ và cảm thấy nhàm chán với mọi công việc hay chủ động tìm kiếm thông tin. Giữ cho kỹ năng của bạn sắc bén sẽ giữ cho tình trạng việc làm của bạn ổn định ngay cả trong thời kỳ kinh tế khó khăn.
Viết code là một công việc đòi hỏi sự tập trung sâu sắc. Việc ngắt quãng sự tập trung để kiểm tra điện thoại hoặc các nền tảng mạng xã hội sẽ gây bất lợi cho khối lượng công việc bạn có thể hoàn thành trong một ngày nhất định.
Rất nhiều người sẽ làm việc trong vài phút và sau đó kiểm tra điện thoại của họ. Nếu một nhân viên trung bình dành 8 giờ làm việc mỗi ngày và dành hai giờ trở lên cho những công việc vô bổ khác. Bạn có thể nhanh chóng được biết đến như một kỹ sư hoàn thành công việc chỉ bằng cách dành thời gian làm việc thực sự.
Bằng cách xây dựng thói quen tập trung và làm việc sâu sắc, bạn sẽ trở thành một người lập trình giỏi và nổi bật hơn so với vô số dev khác. Tạo thói quen này cũng sẽ cho thấy rằng bạn có một đạo đức làm việc không thể vượt qua. Có rất nhiều ứng dụng sử dụng kỹ thuật Pomodoro có thể giúp bạn tập trung. Hãy thử thử nghiệm với một số và xem những gì phù hợp với bạn.
Kết luận
Xây dựng một sự nghiệp nổi bật với tư cách là một nhà lập trình giỏi là công việc mà một lập trình viên nên theo đuổi suốt đời. Nếu bạn có thể sử dụng các chiến lược mà tôi đã chia sẻ ở trên để phát triển kỹ năng của mình, thậm chí bạn sẽ luôn được tuyển dụng và không phải lo sợ tình trạng thất nghiệp.
Bài viết được sự cho phép của tác giả Edward Thiên Hoàng
ASPECT ORIENTED PROGRAMMING
Trong khoảng 5 năm trở lại đây, một khuynh huớng lập trình mới xuất hiện. Nó được gọi là AOP để phân biệt với kiểu lập trình OOP đã có sẵn. Nguời viết muốn cung cấp cho bạn đọc một kiến thức cơ bản về kiểu lập trình mới mẻ này, và sử dụng springframework, một open-source phổ biến, để minh hoạ. Nếu bạn muốn tìm hiểu chi tiết về cách sử dụng springframework, thì bài viết này không nhằm mục đích đó, mà chỉ trình bày khái quát về những thuật ngữ và nguyên tắc trong việc sử dụng 1 chức năng phổ biết của spring: declarative transaction.
ASPECT ORIENTED PROGRAMMING (AOP) VÀ OBJECT ORIENTED PROGRAMMING (OOP)
Một điểm quan trọng nữa cần đuợc nêu ra, AOP đuợc xem là cái bổ sung cho OOP, chỗ mà OOP còn thiếu sót trong việc tạo những ứng dụng thuộc loại phức tạp. AOP khônng phải là cái thay thế OOP. Nguời lập trình bắt buộc phải quen thuộc với OOP để bắt đầu với AOP. Cũng vì lí do này mà AOP thuờng đuợc xem là dành cho các bạn đã có kinh nghiệm, chứ không dành cho các bạn mới bắt đầu làm quen với Java. Bạn có thể làm quen với OOP qua lí thuyết và sách vở từ truờng học. Và nếu bạn thấy vẫn còn lạc lối trong việc tìm kiếm những danh từ, tính từ, hay trả lời những câu hỏi ai, cái gì, làm gì… đại loại như vậy, trong việc tìm kiếm class, thì bạn có thể đọc lại những bài viết về OOP mà nguời viết đã trình bày truớc đây xem có giúp ích hơn không. Dù học OOP theo kiểu nào thì kết quả cuối cùng của OOP là chia ứng dụng thành nhiều phần nhỏ với những chức năng riêng biệt, theo kiểu các hộp đen (black box). Các hộp đen này làm cho việc tái sử dụng và bao quản chúng đuợc dễ dàng hơn….và còn thêm nhiều ưu điểm khác nữa không kể ra ở đây.
HẠN CHẾ CỦA OBJECT ORIENTED PROGRAMMING
Lấy ví dụ về transaction trong việc truy cập database. Trong Java, truy cập database đòi hỏi nhiều buớc: tạo ra Connection, bắt đầu transation, commit, clean up connection… Để đơn giản hoá, ta hãy tạo ra 1 class hay black box chuyên làm việc này.
public class DBTransaction {
public DBTransaction () {
//mã nguồn tạo ra Connection và bắt đầu 1 transaction
}
public Connection getConnection () {
//mã nguồn return Connection đã tạo ra
}
public void commit () {
//mã nguồn commit transaction và clean up resources
}
}
Giả sử trong 1 ứng dụng, có 1 class (hay blackbox) XuatNhapHang làm chức năng xuất nhập hàng và nó chứa 1 method làm chức năng nhập hang.
public void nhapHang ( int monHang, int soLuong )
{
//sử dụng blackbox để bắt đầu 1 transaction
DBTransation tx = new DBTransactiơn ();
// ...mã nguồn truy cập database để nhập hàng...
tx.commit ();
}
Bạn dễ dàng hình dung đuợc mục đích sử dụng của blackbox này.
Mỗi khi cần truy cập database, nguời sử dụng chỉ việc gọi các public methods của nó mà không cần biết tới bên trong nó hoạt động ra sao. Việc thay đổi bên trong của blackbox cũng không làm ảnh huởng tới nguời sử dụng nó. Đó là cái đẹp của việc tạo ra blackbox. Mọi nguời hình như đều vui vẻ và độc lập với công việc của mình. Thực tế không hoàn toàn như vậy. Giả sử ứng dụng sau này đòi hỏi phải theo dõi tất cả mọi hoạt động liên quan đến việc truy cập database. Mỗi khi database đuợc truy cập, tên nguời sử dụng và thời gian sẽ đuợc lưu trữ lại. Ta có thể tạo ra 1 blackbox đơn giản chuyên làm việc này.
public class DBTruyCapTheoDoi {
public DBTruyCapTheoDoi (Connection con, String tenNguoi) {
//mã nguồn lưu lại trong database nguời sử dụng và thời gian
.....
}
}
Method nhapHang hay những nơi trong ứng dụng đã truy cập database đều phải sửa đổi như sau
public void nhapHang ( int monHang, int soLuong )
{
//sử dụng blackbox để bắt đầu 1 transaction
DBTransation tx = new DBTransactiơn ();
//theo doi truy cap
DBTruyCapTheoDoi (tx.getConnection (), tenNguoi);
// ...mã nguồn truy cập database để nhập hàng...
tx.commit ();
}
Sửa đổi không nhiều nhưng nó rộng khắp trong toàn ứng dụng. Đây chính là điểm làm cho nhiều nguời không hài lòng. Những nguời lập trình kì cựu đều đồng ý với nhau rằng, trong thực tế, đòi hỏi của ứng dụng luôn thay đổi theo thời gian. Cứ mỗi 1 yêu cầu mới của ứng dụng thì một (hay nhiều) blackbox đuợc tạo thành, và mã nguồn sẽ bị thay đổi rộng khắp trong ứnng dụng để sử dụng blackbox mới này. Thay đổi mã nguồn rộng khắp ứng dụng là điều tối kị vì nó đòi hỏi phải testing lại toàn bộ . Những bug xuất hiện lúc này thuờng rất khó tìm vì nguời lập trình thuờng cho rằng “mình sửa có 1 chút thì không sao…” .
Câu hỏi đặt ra là làm sao tạo đuợc một kiểu lập trình uyển chuyển với sự phức tạp của ứng dụng . Mô hình này phải cho phép tạo dựng nhanh chóng ứng dụng khi nó ở trong giai đọan đầu đơn giản, và thay đổi nhanh chóng để thích ứng kịp thời với đòi hỏi mới . OOP cho phép tạo ra những blackbox và điều này vẫn đuợc xem là không thể thiếu trong việc lập trình . Bản thân những blackbox không phải là vấn đề, mà chính việc sử dụng chúng mới là vấn đề . Việc gọi trực tiếp những public method của 1 blackbox khi phải sử dụnng nó trong mã nguồn, tạm gọi là nối cứng (hard wired) blackbox vào mã nguồn. Có cách nào để sử dụng 1 blackbox mà khônng cần gọi trực tiếp nó trong mã nguồn hay không? Cần có 1 cách nào đó để gọi gián tiếp những public method, hay tạm gọi là nối mềm (soft wired) khi sử dụng những blackbox. Đây là chỗ OOP bỏ sót, và AOP ra đời để đáp ứng nhu cầu này .
Đến đây bạn có thể thấy rằng, OOP là buớc đầu tiên cần phải có để tạo thành các blackbox. AOP là buớc kế tiếp để nối mềm những blackbox tạo thành 1 ứng dụng hoàn chỉnh . Việc nối mềm đòi hỏi nguời thiết kế phải có kinh nghiệm trong việc chia ứng dụng thành nhiều lớp (layer) để ứng dụng đuợc tạo ra và chạy 1 cách hữu hiệu . Điều này sẽ đuợc nói kĩ hơn sau đây. Một rắc rối nữa của việc nối mềm là nó thuờng đòi hỏi tạo nhiều cấu hình (configuration) phụ trợ .
LÀM THẾ NÀO ĐỂ NỐI MỀM 1 ỨNG DỤNG?
Đây cũng chính là câu hỏi mà AOP cần phải trả lời . Java cho phép là đuợc việc này .
Nối mềm là cho phép sử dụng 1 class (hay blackbox) mà không cần gọi trực tiếp public methods của nó trong mã nguồn, và bạn có thể ngạc nhiên nếu biết rằng điều này thực sự đã đuợc làm từ lâu . Nó đuợc làm bởi các container chẳng hạn như của EJB, portlet, servlet. Lấy EJB container làm ví dụ, vì nó rất gần với khái niệm AOP . Muốn sử dụng 1 EJB, bạn phải gọi create… chứ không bao giờ sửng dụng new . EJB trong thực tế chạy bên trong 1 container. Container trực tiếp tạo ra instance của EJB và chuyển cho nguời sử dụng khi method create… được gọi . Mỗi lần nguời sử dụng gọi method của EJB, container sẽ đón đầu (intercept) cú gọi này, rồi mới chuyển giao cho instance của EJB . Truớc khi chuyển giao cho EJB, thuờng container có thể sẽ làm nhiều việc khác nữa …. Container có thể bắt đầu 1 transaction, hay kiểm tra xem nguời gọi có đuợc phép gọi hay không, tùy theo cách cấu hình của EJB đó bên trong file ejb-jar.xml . Nếu xem EJB là 1 blackbox thì việc nối giữa EJB và nguời sử dụng nó mặc dù là gián tiếp nhưng chưa đuợc xem là nối mềm . Bản thân EJB container có thể chứa sẵn bên trong nó 1 blackbox làm công việc bắt đầu 1 transaction, hay 1 blackbox khác làm công việc kiểm tra mức độ cho phép nguời gọi . Việc nối kết giữa EJB và những blackbox bên trong của container mới chính xác là mềm … Bản thân EJB hay nguời viết nó hoàn toàn không biết đến có tồn tại 1 blackbox có sẵn bên trong container làm công việc transaction . Nguời viết EJB chỉ việc thông tin với container qua file cấu hình ejb-jar.xml rằng phải bắt đầu 1 transaction hay làm thêm những chuyện khác mỗi khi method của nó đuợc gọi . Cũng dựa trên ý tuởng này, spring framework chính là 1 container thuộc loại nhẹ và nó có thể chứa đựng những Java object thông thuờng chứ không phức tạp như EJB .
Trở lại ví dụ xuất nhập hàng ở trên, nếu class XuatNhapHang chạy bên trong spring framework thì method nhapHang ở trên có thể viết lại như sau
public void nhapHang ( int monHang, int soLuong )
{
// ...mã nguồn truy cập database để nhập hàng...
}
Không hề có 1 đọan mã nguồn nào bên trong method nhapHang nói đến việc tạo ra transaction hay theo doi truy cap . Bản thân các blackbox transaction và theo dõi try cập cũng đuợc chạy trong spring. Nguời viết class XuatNhapHang chỉ việc truyền đạt cho spring, qua 1 file cấu hình, rằng mỗi khi method nhapHang đuợc gọi , hãy gọi blackbox transaction và theo dõi truy cập truớc khi chuyển nó đến nhapHang . Bằng cách nối mềm này, việc bao gồm hay loại bỏ những blackbox đuợc thực hiện qua việc thay đổi file cấu hình, chứ không cần phải thay đổi mã nguồn của class XuatNhapHang . Đây chính là lập luận mạnh nhứt trong việc cho ra đời AOP . Những nguời ủng hộ AOP trong ví dụ này lí luận rằng class XuatNhap hay method nhapHang chỉ nên lo lắng việc xuất nhập hàng . Việc bắt đầu 1 transaction hay theo dõi truy cập dữ liệu , đành rằng phải có do yêu cầu của ứng dụng, cũng không nên chen lấn 1 cách thô bạo vào trong mã nguồn của class XuatNhap, hay bất kì vào trong những blackbox nào khác khi chúng cũng cần truy cập dữ liệu . Có như vậy thì 1 blackbox mới giữ đuợc tính độc lập của nó với những thay đổi của yêu cầu của ứng dụng, dẫn đến việc tái sử dụng blackbox đuợc triệt để hơn .
Những khía cạnh như transaction hay theo dõi truy cập, nếu cần phải ‘chen lấn ‘ thì mã nguồn không phải là chỗ tốt để làm . Có những chỗ tốt hơn chẳng hạn như dùng file cấu hình, và spring framework làm đúng như vậy . Công việc của spring framework là đón đầu các cú gọi và thực hiện các chức năng thể hiện qua file cấu hình . Đây cũng chính là nguyên tắc cơ bản của AOP: thay các cú gọi trực tiếp, bằn các cú gọi qua file cấu hình ..
KHÓ KHĂN KHI ÁP DỤNG ASPECT ORIENTED PROGRAMMING
Đọc đến đây, có thể bạn không mấy hào hứng với AOP . Thực tế các file cấu hình cho spring hay các AOP framework khác như AspectJ không đơn giản chút nào . Gọi trực tiếp method chỉ mất 1 dòng và cũng dễ theo dỏi logic của ứng dụng . Thay đổi file cấu hình liệu có an toàn hơn thay đổi mã nguồn hay không ? Những nguời ủng hộ AOP thì cho rằng nó rất nên làm . Những nguời còn hoài nghi thì luỡng lự . Các AOP framework khác nhau đều có cách tạo file cấu hình khác nhau. Không giống như EJB có thể chạy trong mọi EJB container, ứng dụng viết cho AOP framework này không chạy đuợc trong AOP framework khác . Những cố gắng để thống nhứt các AOP framework cho đến bây giờ vẫn chưa kết thúc . Việc container đón đầu các cú gọi có thể ảnh huởng đến tốc độ chạy của ứng dụng . Thêm nữa, không phải mọi class trong ứng dụng đều cần đuợc quản lí bởi AOP framework cũng như không phải mọi class đều trở thành EJB. Nếu ứng dụng thiết kết kém cỏi có thể dẫn đến số luợng class mà AOP container phải quản lí cùng với các file cấu hình tăng lên nhanh chóng . Có lẽ cũng chính vì những lí do này mà AOP vẫn chưa cất cánh nhanh chóng như OOP . Điểm khó khăn cuối cùng nữa của AOP là lí thuyết hoá nó để truyền đạt . AOP đưa ra những khái niệm lạ hoắc khó nắm bắt, dễ làm nản lòng những nguời mới bắt đầu . Phần kế tiếp nguời viết sẽ trình bày những khái niệm cơ bản của AOP, và nguyên tắc Inversion of Control hay còn gọi là Dependency Injection của springframework trong việc triển khai AOP .
NHỮNG KHÁI NIỆM TRONG ASPECT ORIENTED PROGRAMMING
Khái niệm đầu tiên thuờng gặp trong AOP là concern (1 mối lo âu) hay aspect ( 1 khía cạnh của vấn đề). Concern hay aspect trong AOP chỉ là 1, và nó tuơng đuơng với chức năng của 1 blackbox trong OOP. Lấy ví dụ trong ứng dụng cho 1 cửa hàng mua bán . Những yêu cầu của ứng dụng bao gồm : chi thu tài chính, xuất nhập hàng, kết toán cuối tháng, cuối năm, quản lí nhân viên … Và có thể thay đổi trong tuơng lai theo yêu cầu của thực tế . Việc chia nhỏ 1 yêu cầu cùng với OOP sẽ đưa đến các blackbox như xuất nhập hàng, transaction, hay theo dõi truy cập như ở trên . Chức năng của mỗi blackbox có thể đuợc xem là 1 khía cạnh của ứng dụng mà nguời thiết kế phải lo lắng . Tới đây bạn có thể thấy vì sao 2 chữ concern và aspect mang nghĩa không mấy ăn nhập với nhau lại đuợc dùng để chỉ chung 1 khái niệm . Có những khía cạnh, như transaction, cần phải ‘chen lấn ‘ vào các khía cạnh khác . Những khía cạnh đó đuợc gọi là crosscutting aspect, tạm gọi là những khía cạnh cắt ngang . Trong thực tế, điểm chen lấn của những crosscutting aspect không tùy tiện mà nó thuờng là các điểm đặc biệt . Ví dụ như khía cạnh trasaction chỉ chen vào khi bắt đầu method nhapHang để khởi tạo 1 transaction và lại chen vào 1 lần nữa khi method nhapHang return để commit transaction. Những điểm đặc biệt có thể kể ra là bắt đầu hay kết thúc 1 method, khi xảy ra exception. Spring chỉ cho phép chen vào các điểm đặc biệt, còn AspectJ thì cho phép hầu như vào bất cứ điểm nào trong mã nguồn . Việc chen lấn tuỳ tiện cần được cân nhắc kĩ lưỡng và thuờng đuợc khuyên nên tránh . Điểm chen lấn đuợc gọi là joinpoint (điểm nối ) . Tập họp các điểm nối đuợc gọi là pointcut (cắt điểm). Bản thân blackbox XuatNhapHang bị chen lấn nên nó đuợc gọi là target object. Bản thân blackbox transaction, triển khai transaction aspect, làm công việc chen lấn, đuợc gọi là advice. Vì có nhiều điểm chen lấn đặc biệt kể trên, nên có nhiều loại advice.
_ Around advice: là loại chen vào truớc khi cú gọi đuợc chuyển tới method và sau khi method thực hiện xong. Transaction advice chính là loại này
_ Before advice: chen vào truớc khi cú gọi đuợc chuyển tới method
_ Throws advice: chen vào khi bản thân method thows excpetion
_ After returning advice: chen vào sau khi method thực hiện và không có exception .
Ta có thể hình dung như sau: mỗi khi ứng dụng gặp điểm ‘chen lấn ‘, container sẽ đón đầu cú gọi và chạy mã nguồn của advice cho điểm ‘chen lấn ‘ đó rồi mới chuyển giao cho method.
Tới đây có lẽ khá đủ cho nguời mới làm quen với AOP. Để thực sự có thể lập trình theo kiểu AOP, bạn cần phải thông thạo với 1 AOP framework như spring hay aspectJ, đặc biệt là cách tạo file cấu hình cho mỗi framework.
Trở lại spring framework, nó đuợc đề cập ở đây vì 1 chức năng phổ biến : declarative transaction, giống như trong EJB, nhưng đơn giản và dễ sử dụng hơn nhiều. Để sử dụng chức năng này, chỉ cần khái niệm của AOP ở trên là đủ . Khi sử dụng spring, 1 khái niệm luôn gặp phải là Inversion of Control (IoC) hay còn gọi là Dependency Injection, nó sẽ đuợc nói rõ duới đây .
INVERSION OF CONTROL (IOC) VÀ DEPENDENCY INJECTION (DI)
IoC (tạm dịch là đảo nguợc kiểm soát) thuờng được thực hiện bởi các loại container như servlet, portlet, hay EJB.
Lấy ví dụ EJB container, nguời sử dụng không trực tiếp tạo ra instance của EJB, mà container tạo ra nó và chuyển giao nguời sử dụng khi cần tới . Khi nào instance đuợc tạo ra nằm ngoài sự kiểm soát của nguời sử dụng . Container có thể tạo instance ra truớc và chờ đến khi nguời sử dụng, hoặc tạo ra ngay vào lúc đuợc cần tới . Tên gọi IoC cũng nhằm chỉ lí do này: container giành sự kiểm soát từ nguời sử dụng (trong lập trình thông thuờng nguời sử dụng giành kiểm soát bằng cách gọi new để tạo ra instance). Khi instance của EJB đuợc tạo ra và trong truờng hợp session bean, container luôn gọi method setSessionContext(SessionContext sc) để cho EJB sử dụng SessionContext của nó .
Tuơng tự trong servlet container, khi instance của servlet đuợc tạo ra, container luôn gọi method init(ServletConfig sc) để servlet sử dụng . Trong cả 2 truờng hợp, container đuợc xem là nạp (injection) cho instance cái mà nó cần . Cái đuợc cần như SessionContext hay ServletConfig gọi là dependency .
Tên gọi Dependency Injection cũng từ đây mà ra. Có 1 điểm bất đồng giữa cách gọi tên Dependency Injection và định nghĩa về mối quan hệ giữa class trong UML . Dựa trên tài liệu “Mastering UML with Rational Rose” thì instance của EJB sử dụng SessionContext nên instance mới chính là dependency phụ thuộc vào SessionContext . Nếu bạn giải thích đuợc tại sao có sự bất đồng này thì làm ơn cho mọi nguời cùng biết . Dù sao thì chúng ta không nên mất quá nhiều thời giờ cho vấn đề định nghĩa và tên gọi ở đây .
ASPECT ORIENTED PROGRAMMING TRONG SPRING FRAMEWORK
Muốn sử dụng Spring, ít nhiều bạn phải làm quen với Spring container . Class tiêu biểu cho spring container là ApplicationContext . Nguời sử dụng phải trực tiếp tạo ra instance của spring container truớc khi có thể sử dụng những object mà nó chứa . Có nhiều cách tạo ra spring container. Cách thông thuờng nhứt là (những ví dụ theo sau đuợc dựa trên tài liệu spring-reference.pdf vversion 1.2.8)
ApplicationContext ac = new ClassPathXmlApplicationContext( new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
Spring container tạo ra theo cách này sẽ đọc những file config duới dạng xml để load tất cả các Java ojbect mà nó cần quản lí .
Như ví dụ sau
Theo mặc định thì container sẽ tạo ra singleton instance cho mỗi bean, có nghĩa là chỉ 1 instance của 1 bean đuợc tái sử dụng cho những lần gọi sau . Ta có thể sử dụng Dependency Injection của container như sau
Bản thân ExampleBean phải chứa những setter method để container gọi ngay sau khi tạo ra chúng và truớc khi chuyển cho nguời sử dụng .
Nguyên tắc sử dụng spring container chỉ đơn giản như vậy thôi . Nó cho phép định nghĩa qua file cấu hình những logic phức tạp hơn mà bài viết không trình bày hết ra đây . Tới đây bạn có thể thắc mắc như vậy thì sức mạnh của spring nằm ở đâu ? Tiện lợi chỉ đơn giản như vậy thì có đáng đuợc sử dụng không ?
Cần nhắc lại 1 nguyên tắc làm việc của mọi dạng container là đón đầu những cú gọi . Spring làm việc này bằng cách dựa trên file cấu hình để tạo ra những object phụ trợ khác vào lúc runtime . Cái return từ method getBean đuợc xem là 1 proxy đuợc tạo ra vào lúc runtime của java object mà spring quản lí . Đằng sau proxy này là 1 tập họp các phụ trợ object thực hiện các chức năng theo yêu cầu của file cấu hình truớc khi chuyển cú gọi tới cho java object . Chẳng hạn như các phụ trợ object có thể chạy mã nguồn của advice, hoặc bắt đầu 1 transaction, một chức năng đã được làm sẵn trong Spring, sẽ đuợc nói tới duới đây .
Trong việc truy cập database, ứng dụng có thể sử dụng các phuơng pháp khác nhau như: trực tiếp sử dụng SQL, Hybernate, EJB Entity … Để đơn giản hoá vấn đề, ta lấy truờng sử dụng SQL để cập nhật database .
Trong Java, connection thường tạo ra duới dạng connection pool hay DataSource, là 1 tập họp những connection để xử dụng chung cho toàn bộ ứng dụng . Giả sử apache datasource đuợc xử dụng ở đây . Để container có thể tạo ra datasource cho oracle, ta xử dụng cấu hình duới đây
Trở lại class XuatNhapHang ở trên, muốn spring tự động bắt đầu và kết thúc 1 transaction mỗi khi 1 method của class này đuợc gọi , cần có những cấu hình cho pointcut hay advice khá phức tạp theo kiểu AOP . Rất may là spring đã gói gọn trong 1 class TransactionProxyFactoryBean đơn giản sau
Chúng ta sẽ kiểm tra kĩ lưỡng cấu hình này .
_ abstract=”true” có nghĩa là ứng dụng không đuợc phép gọi method getBean(“txProxyTemplate”) . Cấu hình này chỉ đuợc dùng để các cấu hình khác extends . Giống như tính chất inheritance trong OOP
_ property name=”transactionManager” ref=”txManager” cho biết class TransactionProxyFactoryBean sẽ đuợc nạp bean txManager bởi container.
_ prop key=”*” : áp dụng cho mọi method của những class extends cấu hình này
_ PROPAGATION_REQUIRED: bắt đầu 1 transaction nếu chưa có hoặc tiếp tục 1 transaction có sẵn .
_ MyException: nếu method throw MyException, thì dấu – đằng truớc sẽ làm transaction bị rollback, và dấu + sẽ commit transaction truớc khi throw MyException.
Cấu hình của class XuatNhapHang sẽ extends cấu hình này như sau:
Bằng cách extends cấu hình của txProxyTemplate qua việc sử dụng attribute parent, mỗi khi 1 method của class XuatNhapHang đuợc gọi, 1 transaction sẽ tự động bắt đầu và kết thúc . Transaction sẽ bị rollback trong truờng hợp exception MyException xảy ra . Spring còn giúp mô hình JDBC operations như những java object qua việc xử dụng class MappingSqlQuery, SqlUpdate, StoredProcedure .
Bài viết đuợc kết thúc ở đây chỉ với mục đích giúp bạn làm quen với những khái niệm của AOP . Vì AOP là cái bổ sung cho những thiếu sót của OOP, AOP không dành cho những bạn mới bắt đầu lập trình . Spring framework mặc dù triển khai AOP đơn giản hơn so với AspectJ, cũng khác phức tạp với rất nhiều chức năng có thể dùng đuợc, và nguời viết chỉ tóm tắt 1 chức năng phổ biến nhất của nó là declarative transaction. Dù sao thì bạn vẫn cần tham khảo những tài liệu huớng dẫn về Spring truớc khi có thể dùng nó 1 cách hữu hiệu . Chúc bạn may mắn.
Phương thức phát triển phần mềm linh hoạt (Agile Software Development) – sau đây được gọi vắn tắt là “Agile” – đã trở nên phổ biến trong ngành phát triển phần mềm. Với những phương phức tổ chức và triển khai mới lạ, năng động và linh hoạt, Agile đã thu hút sự quan tâm lớn của cộng đồng làm phần mềm và dĩ nhiên là một kỹ sư kiểm thử mình không thể nào thờ ơ với Agile được. Trước hết mình xin nói ngay rằng mình không phải là một chuyên gia về Agile cũng không phải là kỹ sư kiểm thử nhiều năm chinh chiến với Agile. Mình chỉ là một kỹ sư kiểm thử với chút kinh nghiệm dự án thực tế và ít kiến thức lụm lặt được về Agile. Tuy nhiên mình vẫn mong muốn được chia sẻ những hiểu biết suy nghĩ của mình và hy vọng nhận được sự chia sẻ từ các anh chị em trong ngành về Agile.
Bài viết “Tổng quan về Agile” sau đây là một phần trong một loạt bài giới thiệu về Agile theo cách nhìn của mình, nội dung được tinh giản nhưng hy vọng vẫn giữ được nguyên giá trị của Agile và…chúng ta bắt đầu thôi.
Wiki định nghĩa như sau: “Phương thức phát triển phần mềm Agile là một tập hợp các phương thức phát triển lặp và tăng dần trong đó các yêu cầu và giải pháp được phát triển thông qua sự liên kết cộng tác giữa các nhóm tự quản và liên chức năng v.v và v.v”. OK. Bỏ qua phần định nghĩa nhé vì mình thấy không giúp ích gì nhiều. Đại ý là Agile là cách thức làm phần mềm linh hoạt để làm sao đưa sản phẩm đến tay người dùng càng nhanh càng tốt càng sớm càng tốt và được xem như là sự cải tiến (ở một khía cạnh nào đó) khi đặt cạnh những mô hình cũ như Mô hình “Thác nước (waterfall)” hay “CMMI”.
Định nghĩa Agile có thể trừu tượng và bạn có thể không nhớ nhưng bạn không thể không nhớ “Tuyên ngôn của Agile” (Agile manifesto). “Tuyên ngôn của Agile” được xem là cốt lõi là ngôi sao dẫn đường trong Agile. Theo tuyên ngôn, Agile hoạt động dựa trên những tôn chỉ sau:
Tuyên ngôn của Agile
“Cá nhân và sự tương hỗ quan trọng hơn quy trình và công cụ”
“Sản phẩm xài được quan trọng hơn tài liệu về sản phẩm”
“Cộng tác với khách hàng quan trọng hơn đàm phán hợp đồng”
“Phản hồi với sự thay đổi quan trọng hơn bám theo kế hoạch”
Tuyên ngôn cũng nói rằng mặc dù những mục bên phải vẫn có giá trị nhưng Agile đánh giá cao các mục bên trái hơn (phần in đậm)
4 tôn chỉ trên được dựa trên 12 nguyên tắc sau:
Thỏa mãn yêu cầu của khách hàng thông qua việc giao hàng sớm và liên tục
Chào đón việc thay đổi yêu cầu, thậm chí là những thay đổi yêu cầu muộn
Giao phần mềm chạy được cho khách hàng một cách thường xuyên (giao hàng tuần hơn là hàng tháng)
Nhà kinh doanh và kỹ sư lập trình phải làm việc cùng nhau hàng ngày trong suốt dự án
Các dự án được xây dựng xung quanh những cá nhân có động lực. Cung cấp cho họ môi trường và sự hỗ trợ cần thiết, và tin tưởng họ để hoàn thành công việc
Trao đổi trực tiếp mặt đối mặt là phương pháp hiệu quả nhất để truyền đạt thông tin
Phần mềm chạy được là thước đo chính của tiến độ
Phát triển bền vững và duy trì được nhịp độ phát triển liên tục
Liên tục quan tâm đến kĩ thuật và thiết kế để cải tiến sự linh hoạt
Sự đơn giản là cần thiết – nghệ thuật tối đa hóa lượng công việc chưa hoàn thành
Nhóm tự tổ chức
Thích ứng thường xuyên với sự thay đổi
Mình vừa giới thiệu các bạn tổng quan về Agile. Cũng không đến nỗi khó hiểu lắm phải không các bạn. Trong phần kế tiếp mình sẽ giới thiệu rõ hơn về “Tuyên ngôn của Agile”.
Rất vui nếu nhận ý kiến đóng góp, phê bình, chia sẻ từ các bạn.
(?) Bạn có biết cách phát âm “Agile”. Agile có phiên âm quốc tế là /ˈædʒaɪl/, /ˈædʒəl/. Nghe phát âm tại đây. Mình phát âm là “Á-chai-ồ” :-s (coi như các bạn chưa nghe thấy gì đi)
Bài viết có tham khảo và lược dịch từ Wiki và Agilemanifesto.org
Là một developer trong công ty Nhật đang áp dụng tìm hiểu mô hình TDD nên mình muốn chia sẽ hiểu biết của mình về Test-Driven Development (TDD) và Behavior-Driven Development (BDD) – mô hình phát triển phần mềm hướng kiểm thử (test oriented) theo tinh thần Agile đang được áp dụng rộng rãi.
Chính xác với nghĩa đen của nó: “Test-Driven Development” có thể được tạm hiểu là mô hình phát triển với trọng tâm hướng về việc kiểm thử. TDD được xây dựng theo hai tiêu chí: Test-First (Kiểm thử trước) và Refactoring (Điều chỉnh mã nguồn) [1]. Trong đó, khi một yêu cầu phần mềm (requirement) được đặt ra:
Người developer soạn thảo kịch bản kiểm thử (test case) cho yêu cầu đó trước tiên và chạy thử kịch bản đó lần đầu tiên. Hiển nhiên, việc chạy thử sẽ đưa ra 1 kết quả thất bại vì hiện tại chức năng đó chưa được xây dựng (và thông qua kết quả đó, ta cũng kiểm tra được là kịch bản kiểm thử đó được viết đúng).
Theo đó, dựa vào mong muốn (expectation) của kịch bản kia, người developer sẽ xây dựng một lượng mã nguồn (source code) vừa đủ để lần chạy thứ 2 của kịch bản đó thành công.
Nếu trong lần chạy thứ 2 vẫn đưa ra 1 kết quả thất bại, điều đó có nghĩa là thiết kế chưa ổn và người developer lại chỉnh sửa mã nguồn và chạy lại kịch bản đến khi thành công.
Khi kịch bản kiểm thử được chạy thành công, người developer tiến hành chuẩn hóa đoạn mã nguồn (base-line code) và tiếp tục hồi quy với kịch bản kiểm thử tiếp theo. Việc chuẩn hóa bao gồm thêm các comment, loại bỏ các dư thừa, tối ưu các biến…
Quy trình phát triển TDD vẽ bởi Colin Kloes, đề cập vấn đề khó khăn trong việc hiểu rõ yêu cầu chức năng trước khi viết kịch bản kiểm thử
2. Điểm khác biệt của TDD với một mô hình truyền thống Waterfall là gì?
Thông qua quy trình TDD trình bày ở trên, ta có thể dễ dàng nhận ra là thứ tự các bước xây dựng 1 tính năng phần mềm gần như đã được đảo ngược so với 1 quy trình truyền thống. Vậy điều này giúp ích gì và có gì hay hơn?
Trước hết, hãy nhìn lại 1 mô hình thác đổ (Waterfall Model) thông thường: việc phân tích các yêu cầu (requirements) thường được tiến hành bởi Business Analyst (BA) 1 cách chuyên hóa và khi đến giai đoạn xây dựng (implementing phase) thì đa phần các developer tiếp xúc với các yêu cầu phần mềm dưới dạng các bản thiết kế. Họ chỉ quan tâm đến đầu vào, đầu ra (Input, Output) của tính năng mình xây dựng mà thiếu đi cái nhìn thực tiễn từ góc nhìn người dùng (end-users). Một hệ quả tất yếu là lỗi phần mềm đến từ việc sản phẩm ko tiện dụng với người dùng.
Cùng với Agile, việc ứng dụng TDD góp phần làm gần khoảng cách giữa đội ngũ thiết kế phần mềm và sản phẩm thực tiễn, tối ưu quy trình [2]. Cụ thể như sau:
Thông qua kịch bản kiểm thử, developer có cái nhìn trực quan về sản phẩm ngay trước khi xây dựng mã nguồn. Sản phẩm họ tạo ra chính xác và gần gũi người dùng hơn.
Phần mã nguồn được thêm vào chỉ vừa đủ để chạy thành công kịch bản kiểm thử, hạn chế dư thừa và qua đó hạn chế khả năng xảy ra lỗi trên những phần dư thừa.
Bảo đảm mã nguồn luôn phản ánh đúng và vừa đủ yêu cầu phầm mềm, hạn chế được công sức tối ưu mã nguồn về sau.
3. TDD và Agile
Trong quá trình hình thành, TDD có liên quan mật thiết đến khái niệm “Test-First Programming” trong mô hình eXtreme Programming “XP” thuần túy Agile – thịnh hành từ năm 1999 [3]. Tuy nhiên, bằng việc ứng dụng đa dạng và linh hoạt, TDD cũng có những đặc điểm và tùy biến của riêng nó (mình sẽ trình bày rõ hơn bên dưới).
TDD trong Agile framework phác họa bởi Mohammad Sami
TDD đáp ứng “Tuyên ngôn về Agile” khi bản thân quy trình TDD thúc đẩy tính thực tiễn của sản phẩm, tương tác với người dùng. Để phát huy tối đa những lợi ích mà TDD mang lại, độ lớn của 1 đơn vị tính năng phần mềm (unit of function) cần đủ nhỏ để kịch bản kiểm thử dễ dàng được xây dựng và đọc hiểu, công sức debug kịch bản kiểm thử khi chạy thất bại cũng giảm thiểu hơn.
Thực tế cho thấy một số sự kết hợp giữa TDD và mô hình Agile khác như Scrum có thể hỗ trợ và tối ưu lợi ích của nhau. Ví dụ, việc chia nhỏ Backlog thành các User Story của Scrum khiến việc xây dựng kịch bản kiểm thử hướng TDD trở nên dễ dàng và thuận tiện. Thêm vào đó, cả Scrum và TDD tương đồng trong việc loại bỏ sự chuyên hóa về vai trò của bộ đôi Developer – Tester. Vì lý do đó, đôi lúc có thể bạn sẽ thấy vừa TDD vừa Scrum được áp dụng trong cùng 1 dự án.
Như vậy, trong mô hình TDD nhiệm vụ kiểm thử do developer đảm nhiệm và vai trò chuyên hóa của người tester gần như không còn nữa. Chắc hẳn các bạn sẽ tự hỏi: “Vậy một Acceptance Tester như chúng ta có vai trò gì trong mô hình?”, “Tại sao tôi phải hiểu về TDD khi người ta ko cần tôi trong quy trình đó?”
Quả thực, trong mô hình TDD người Acceptance Tester thực sự đã chết. Tuy nhiên, việc cộng gộp vai trò phát sinh vấn đề quá tải cho người developer [2]. Để làm tốt công việc, xuyên suốt chu trình người developer phải chú ý thêm những vấn đề thuần túy của kiểm thử (test) như: “Cái gì cần test và cái gì không?” “Viết bao nhiêu kịch bản là đủ?” “Làm sao để hiểu là test đó thất bại?” “Bắt đầu test từ đâu?” …
Để giải quyết vần đề phát sinh mà vẫn tận dụng triệt để lợi ích mà TDD mang lại, Dan North phát triển một mô hình mới với tên gọi: Behavior-Driven Development – BDD (hoặc ta có thể hiểu là Acceptance Test-Driven Development – ATDD) [5]. Trong đó, một vai trò mới trong việc thiết kế kiểm thử (Test Design) được đặt ra:
Thay vì chờ đợi sản phẩm hoàn thành và kiểm thử, người tester/analyst tham gia vào quá trình xây dựng mã nguồn với vai trò phân tích và xây dựng hệ thống kịch bản kiểm thử dưới góc độ ngôn ngữ tự nhiên dễ hiểu từ các yêu cầu (requirement).
Đồng thời, họ giúp đỡ developer trong việc giải thích và đưa ra các phương án xây dựng mã nguồn mang tính thực tiễn với người dùng ngay trước khi bắt tay xây dựng.
Người developer liên hệ mật thiết với người tester và xây dựng mã nguồn với những phương án mà tester cung cấp theo mô hình TDD.
Kịch bản kiểm thử được phân chia làm 2 lớp: Lớp chấp nhận (feature/acceptance test) và Lớp đơn vị (unit test) [1].
Theo đó, kịch bản kiểm thử lớp đơn vị mang thuần tính thiết kế và phục vụ cho việc kiểm thử lớp đơn vị (Unit test) còn kịch bản kiểm thử lớp chấp nhận có thể được tái sử dụng cho quá trình kiểm thử hồi quy về sau (Regression Test)
Mô hình BDD – TDD trong Agile mô phỏng bởi Paul Littlebury
Từ mô hình trên ta dễ dàng nhìn nhận được sự ưu việt BDD mang lại đặc biệt là trong các dự án phần mềm lớn và phức tạp, khi cả hai khía cạnh phân hóa vai trò và chất lượng phải đi đôi. Ngoài ra, việc chạy kịch bản kiểm thử và xử lý sớm các vấn đề thiết kế ngay trong khâu xây dựng giúp giảm thiểu tối đa chi phí và công sức sữa chữa lỗi.
Trong khi khái niệm BDD mang tính lý thuyết, việc ứng dụng của nó lại đặt nặng sự thực nghiệm. Để phát huy lợi ích về thời gian trong việc xây dựng kịch bản kiểm thử, ngôn ngữ và cách truyền tải là 1 thử thách khi phải đáp ứng khả năng đọc hiểu từ cả 2 khía cạnh: tự nhiên và thiết kế. Bằng sự vay mượn từ ngôn ngữ viết User Story, ngôn ngữ Gherkin được phát triển để phục vụ nhu cầu đó với cấu trúc đơn giản, hướng đối tượng và tương đồng cho mọi kịch bản: Given – When – Then (mình sẽ trình bày rõ hơn về ngôn ngữ này ở các loạt bài khác).
Bài viết được sự cho phép của tác giả Nguyễn Trần Chung
Thực sự mà nói về code thì 100 coder code 100 cách khác nhau, không biết đâu mà lần phải không các bạn. Người thì xài tab, người thì xài space (khoảng trắng), đã thế lại còn có tab 2 với tab 4, space 2 với space 4… chưa kể đến việc space và tab ở mỗi Editor/IDE là không giống nhau nữa. Nếu bạn code một mình thì chả có vấn đề gì cả phải không nào, những hãy thử nghĩ xem trong 1 team thì sao? Mỗi người 1 kiểu sẽ gây mất tính thống nhất với nhau, khó đọc code hơn đối với người khác trong team nữa chứ.
Đó chính là lí do vì sao cần phải có EditorConfig trong mỗi project của các bạn. EditorConfig giúp developer và các team thống nhất code style về mặt tab indent. Việc thiết lập .editorconfig sẽ tăng tính chuyên nghiệp, giảm thiểu việc code lệch dòng.
EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.
EditorConfig giúp lập trình viên định nghĩa và duy trì một phong cách viết code thống nhất giữa các editor và IDE khác nhau. Dự án EditorConfig bao gồm một hướng dẫn định nghĩa các phong cách lập trình và tập hợp plugin cho các editor, giúp cho editor có thể đọc file thiết lập và thay đổi tương ứng. Tập tin EditorConfig dễ đọc và hoàn toàn phù hợp với các chương trình quản lý phiên bản.
Nạp EditorConfig vào Editor/IDE
Bạn đang code bằng Editor/IDE gì nhỉ: Sublime Text, Atom, Visual Studio Code, PhpStorm, Eclipse, … trước tiên bạn hãy vào https://editorconfig.org/#download để xem thử Editor/IDE của mình có hỗ trợ EditorConfig không nhé. Sau đó hãy cài đặt plugin theo hướng dẫn nha.
Để bắt đầu với EditorConfig rất đơn giản, ở thư mục gốc của project của bạn chỉ cần có 1 file tên là .editorconfig thì ngay lập tức Editor/IDE sẽ nạp thông tin cấu hình và áp dụng đối với từng trường hợp cụ thể. Trong các thư mục con cũng có thể có file .editorconfig và file này sẽ đè lên file ở thư mục gốc. Sau này, khi tạo file mới Editor/IDE sẽ tự động đọc file .editorconfig và thiết lập style cho bạn.
Cách dùng EditorConfig
Để định nghĩa style cho 1 file nào đó ta bắt đầu bằng
[tên file]
thuộc tính 1 = định nghĩa 1
thuộc tính 2 = định nghĩa 2
thuộc tính 3 = định nghĩa 3
...
Tên file hỗ trợ Wildcard Patterns các bạn nhé, cụ thể như sau:
*
Khớp bất kỳ chuỗi ký tự nào, trừ dấu tách đường dẫn (/)
**
Khớp bất kỳ chuỗi ký tự nào
?
Khớp với bất kỳ ký tự đơn nào
[name]
So khớp bất kỳ ký tự đơn nào trong name
[! name]
Khớp bất kỳ ký tự đơn nào không có trong name
{s1, s2, s3}
Phù hợp với bất kỳ chuỗi nào được cho (phân tách bằng dấu phẩy)
{num1..num2}
Khớp bất kỳ số nguyên nào giữa num1 và num2, trong đó num1 và num2 có thể là số dương hoặc âm
Nếu bạn để ý thì trong repository của Laravel cũng có file .editorconfig mặc định như thế này này:
Ta hãy cùng xem ý nghĩa của các thuộc tính ở dưới này nhé:
indent_style
Định dạng thụt lề văn bản là tab hay space
Giá trị khả dụng: tab, space
indent_size
Kích cỡ thụt lề văn bản.
Giá trị khả dụng: một số nguyên dương, tab
Nếu indent_size bằng tab, indent_size sẽ được đặt thành kích thước tab, tab_width sẽ được đặt nếu tab_width được chỉ định hoặc được đặt bởi Editor/IDE nếu tab_width không được chỉ định.
tab_width
Chiều rộng của một ký tự tabstop đơn
Giá trị khả dụng: một số nguyên dương (giá trị mặc định bằng indent_size khi indent_size là một số)
end_of_line
Định dạng tệp kết thúc dòng (Unix, DOS, Mac)
Giá trị khả dụng:
lf
crlf
cr
charset
File character encoding
Giá trị khả dụng:
latin1
utf-8
utf-16be
utf-16le
utf-8-bom
trim_trailing_whitespace
Cho biết khoảng trắng có được phép ở cuối dòng hay không
Giá trị khả dụng:
true
false
insert_final_newline
Cho biết tệp có kết thúc bằng dòng mới hay không
Giá trị khả dụng:
true
false
max_line_length
Giới hạn số ký tự có trên 1 dòng
Giá trị khả dụng:
Một số nguyên dương
off
Hỗ trợ bởi
Emacs
Vim
Atom
ReSharper and Rider
AppCode, IntelliJ IDEA, PhpStorm, PyCharm, RubyMine, and WebStorm
Nhân sự là gì? Mô tả về công việc nhân sự có gì thú vị? Nhiều người nghĩ nghề Nhân sự chỉ là đơn thuần nhằm mục đích tuyển dụng và hiển nhiên dừng lại ở đó. Tuy nhiên, đó chỉ là sự mô tả về một khía cạnh nhỏ mà thôi. Bài viết dưới đây sẽ giúp bạn giải đáp những thắc mắc xoay quanh ngành nghề này.
Nhân sự là gì?
Nhân sự hay HR là gì? Chúng ta cùng nhau đi tìm câu trả lời nhé!
Nhân sự là bộ phận thực hiện các công việc liên quan đến quản lý, phát triển và sử dụng nguồn lực con người trong một tổ chức hoặc doanh nghiệp. Nhân sự không chỉ bao gồm việc tuyển dụng và sa thải, mà còn liên quan đến việc đào tạo, đánh giá, phát triển kỹ năng, và tạo động lực cho nhân viên để họ có thể phát huy tối đa năng lực của mình, góp phần vào sự thành công của tổ chức.
Nhân sự là làm gì
Nói một cách dễ hiểu, nghề nhân sự chịu trách nhiệm quản lý toàn bộ quá trình làm việc của nhân viên từ tìm kiếm ứng viên và tuyển dụng, cho đến đào tạo và sa thải. Bên cạnh đó, nhân sự còn quản lý các phúc lợi, tạo ra một môi trường làm việc lành mạnh, nhằm giữ chân những nhân viên giỏi, thúc đẩy năng suất làm việc và khuyến khích sự trung thành, tận tâm của nhân viên đối với tổ chức.
HR (Human Resources) là thuật ngữ dùng để chỉ ngành quản trị nhân sự.
Vai trò của bộ phận nhân sự
Bộ phận nhân sự (Human Resources – HR) đóng vai trò quan trọng trong việc duy trì và phát triển lực lượng lao động của một doanh nghiệp. Các hoạt động chính của bộ phận nhân sự bao gồm:
Tuyển dụng và lựa chọn: Tìm kiếm, tuyển dụng và lựa chọn những ứng viên phù hợp cho các vị trí công việc trong tổ chức.
Đào tạo và phát triển: Cung cấp các chương trình đào tạo và phát triển kỹ năng cho nhân viên, giúp họ nâng cao năng lực và chuẩn bị cho các vai trò lớn hơn trong tương lai.
Quản lý hiệu suất: Đánh giá và quản lý hiệu suất làm việc của nhân viên, bao gồm việc thiết lập mục tiêu, theo dõi tiến độ và đánh giá kết quả công việc.
Quản lý lương thưởng và phúc lợi: Đảm bảo rằng nhân viên được hưởng lương, thưởng và các phúc lợi khác một cách công bằng và cạnh tranh.
Quan hệ lao động: Giải quyết các vấn đề liên quan đến quan hệ lao động, bao gồm việc giải quyết tranh chấp, khiếu nại, và duy trì môi trường làm việc tích cực.
Phát triển văn hóa tổ chức: Xây dựng và duy trì văn hóa doanh nghiệp, bao gồm các giá trị, quy tắc và hành vi mà tổ chức mong đợi từ nhân viên.
Một ví dụ rất dễ nhận thấy trong thực tế về vai trò của quản trị nhân sự là khi người làm nhân sự tìm được đúng người cho đúng việc; vào đúng thời điểm (right person for right job at right time) thì cả doanh nghiệp/tổ chức và người lao động đều có lợi.
Ở Việt Nam, ngành nhân sự vẫn chưa được đánh giá đúng tầm quan trọng của hoạt động quản trị; phát triển nguồn nhân lực như đúng bản chất của nó. Và cũng ít ai hiểu được rằng, ngành nhân sự là hoạt động liên quan đến mọi hoạt động quản trị khác; có ảnh hưởng đến mối quan hệ giữa tổ chức/doanh nghiệp với người lao động.
Các vị trí trong ngành nhân sự
Tùy vào vị trí, kinh nghiệm mà người làm tuyển dụng sẽ được phân công phần lượng công việc phù hợp. Song, chúng ta có thể khái quát mô tả công việc nhân sự sẽ phải thực hiện ngay sau đây:
Nhóm công việc tuyển dụng
Tuyển dụng là quá trình thu hút, sàng lọc; lựa chọn và chỉ định ứng viên phù hợp cho vị trí công việc đang cần tuyển của doanh nghiệp. Thành công của hoạt động tuyển dụng được đánh giá bằng số lượng vị trí trống được lấp đầy và thời gian cần thiết để tuyển dụng. Đây là hoạt động chính giúp củng cố lực lượng lao động của công ty.
Các vị trí trong ngành nhân sự
Nhân viên tuyển dụng trong phòng nhân sự sẽ phải thực hiện các công việc:
Lập kế hoạch; triển khai công tác tuyển dụng đáp ứng nhu cầu hoạt động, phát triển của doanh nghiệp;
Đăng thông tin tuyển dụng trên các kênh; cung cấp đầy đủ thông tin cho ứng viên, tiếp cận với ứng viên tiềm năng;
Sàng lọc CV và Sắp xếp lịch phỏng vấn cho ứng viên, v.v.
Nhóm công việc về lương thưởng và phúc lợi (C&B)
Lương thưởng là khoản tiền công hoặc tiền lương trả cho nhân viên để đổi lấy sự hoàn thành công việc của nhân viên. Phúc lợi là những lợi ích có thể không bằng tiền mặt; tạo động lực làm việc và giữ chân nhân viên.
Nhân viên C&B phải xây dựng cấu trúc lương thưởng và đảm bảo cung cấp những lợi ích cạnh tranh nhằm thu hút và giữ chân nhân tài cho công ty. Các mô tả công việc nhân sự cụ thể như:
Thực hiện công tác chấm công, quản lý việc nghỉ phép, đi trễ, nghỉ việc…;
Xây dựng bảng lương theo vị trí công việc và năng lực;
Xây dựng chính sách phúc lợi, đãi ngộ, khen thưởng, kỷ luật, chế độ bảo hiểm, đóng thuế…
Xử lý những tranh chấp phát sinh trong quan hệ lao động.
Nhóm công việc hành chính
Bộ phận hành chính nhân sự quản lý trải nghiệm tổng thể của nhân viên tại nơi làm việc. Nhân viên làm việc chặt chẽ với các nhà quản lý và nhân viên để giải quyết các vấn đề của nhân viên; xem xét đánh giá hiệu suất; thực thi các chính sách – quy trình của công ty; giám sát sự phát triển của tổ chức và điều tra nội bộ khi cần thiết:
Quản lý hợp đồng lao động cho nhân viên, hồ sơ nhân viên, định biên nhân sự;
Hướng dẫn nhân viên mới về hợp đồng lao động; làm rõ về mức lương, chính sách phúc lợi tại công ty;
Theo dõi, thực hiện các chế độ nghỉ việc hay hết hạn hợp đồng theo quy định;
Lập báo cáo theo định kỳ và thực hiện các công việc khác theo chỉ thị cấp trên;
Thực hiện chuyển phát nhanh, giao nhận văn thư, hợp đồng, hóa đơn cho công ty và các phòng ban, v.v.
Nhóm quản lý, đánh giá hiệu suất
Mảng này tập trung vào việc đánh giá và cải thiện hiệu suất làm việc của nhân viên, giúp tổ chức đạt được mục tiêu chiến lược. Các công việc chính bao gồm:
Thiết lập hệ thống đánh giá hiệu suất: Xây dựng các tiêu chí và quy trình đánh giá hiệu suất rõ ràng và công bằng.
Tổ chức đánh giá hiệu suất định kỳ: Thực hiện các đánh giá hiệu suất hàng quý, hàng năm, hoặc theo yêu cầu để đánh giá kết quả công việc của nhân viên.
Phản hồi và phát triển cá nhân: Cung cấp phản hồi xây dựng và hỗ trợ phát triển kế hoạch hành động cá nhân để giúp nhân viên cải thiện hiệu suất làm việc.
Xây dựng kế hoạch thăng tiến: Đề xuất các chương trình thăng tiến và phát triển sự nghiệp cho những nhân viên có thành tích tốt.
Đánh giá và cải thiện môi trường làm việc: Đánh giá môi trường làm việc và đề xuất các giải pháp để nâng cao năng suất và sự hài lòng của nhân viên.
Nhóm công việc đào tạo và phát triển
Doanh nghiệp phải cung cấp cho nhân viên các công cụ cần thiết cho sự thành công của họ. Trong đó bao gồm tổ chức cho nhân viên mới những khóa đào tạo định hướng sâu rộng; giúp họ nắm vững nghiệp vụ cũng như hòa nhập với văn hóa doanh nghiệp.
Nhiều bộ phận nhân sự cũng cung cấp những buổi tập huấn kỹ năng lãnh đạo và phát triển chuyên môn. Đào tạo lãnh đạo có thể dành cho các giám sát viên; quản lý mới được tuyển dụng; thăng chức về các chủ đề như: quản lý hiệu suất và cách xử lý các vấn đề quan hệ nhân viên ở cấp bộ phận.
Người làm trong lĩnh vực nhân sự (HR) đóng vai trò quan trọng trong việc quản lý và phát triển nguồn lực con người của tổ chức. Để thành công trong vai trò này, họ cần phải có một số kỹ năng, kiến thức và phẩm chất quan trọng. Dưới đây là các yêu cầu cơ bản cần có của những người làm nhân sự:
Kiến thức chuyên môn về quản trị nhân sự
Để thành công trong nghề nhân sự, người làm cần có kiến thức sâu rộng về luật lao động, bảo hiểm và các quy định liên quan đến hợp đồng lao động. Kiến thức này không chỉ giúp đảm bảo tuân thủ pháp luật mà còn bảo vệ quyền lợi của cả nhân viên và tổ chức. Ngoài ra, hiểu biết về các lý thuyết quản trị nhân sự, quy trình tuyển dụng, đào tạo và quản lý hiệu suất là yếu tố không thể thiếu. Kỹ năng quản lý lương thưởng và phúc lợi cũng là một phần quan trọng của công việc này, giúp xây dựng và thực hiện các chính sách lương thưởng công bằng, cạnh tranh.
Kỹ năng giao tiếp và quan tâm đến con người
Kỹ năng giao tiếp hiệu quả là yếu tố quan trọng giúp người làm nhân sự truyền đạt thông tin một cách rõ ràng, thuyết phục và hiệu quả. Đồng thời, người làm nhân sự cần có sự quan tâm đến con người, hiểu và cảm thông với mong muốn, nhu cầu của nhân viên. Họ cần tạo ra một môi trường làm việc lành mạnh, tích cực, thúc đẩy động lực và đóng góp của nhân viên vào sự phát triển của tổ chức. Sự lắng nghe chủ động là cần thiết để hiểu rõ và giải quyết kịp thời những vấn đề mà nhân viên gặp phải.
Kỹ năng giải quyết vấn đề và phân tích tình huống
Người làm nhân sự thường xuyên phải đối mặt với các vấn đề liên quan đến nhân viên, từ xử lý khiếu nại, giải quyết vấn đề lương thưởng, đến các vấn đề liên quan đến phúc lợi. Kỹ năng giải quyết vấn đề là yêu cầu thiết yếu giúp họ linh hoạt ứng phó với các tình huống, hạn chế xảy ra những vấn đề tiêu cực không cần thiết. Kỹ năng phân tích và đánh giá cũng đặc biệt quan trọng, nhất là trong quá trình tuyển dụng và quản lý nhân viên. Khả năng phân tích câu trả lời của ứng viên, đánh giá kỹ năng, kiến thức và tính cách sẽ giúp chọn lọc ra những ứng viên phù hợp với yêu cầu công việc.
Khả năng phân tích còn giúp người làm nhân sự đánh giá tiềm năng phát triển của nhân viên, từ đó có những chính sách thăng tiến phù hợp hoặc bổ sung vào các vị trí quản lý còn thiếu.
Tinh thần tổ chức và trách nhiệm
Tinh thần tổ chức và trách nhiệm là những phẩm chất cần thiết của một người làm nhân sự. Họ cần chủ động trong công việc, tuân thủ và làm gương cho đội ngũ nhân viên theo các quy định và chính sách của công ty. Việc này không chỉ đảm bảo rằng các hoạt động của bộ phận nhân sự được thực hiện đúng thời hạn và hiệu quả, mà còn giúp duy trì sự chuyên nghiệp và trật tự trong tổ chức.
Khả năng làm việc dưới áp lực
Bất kỳ công việc nào cũng sẽ có những căng thẳng và áp lực nhất định, và nghề nhân sự cũng không ngoại lệ. Người làm nhân sự phải chịu được áp lực khi không tuyển đủ người cho các bộ phận, khi có nhiều nhân viên nghỉ việc, hoặc khi ứng viên đến phỏng vấn không đáp ứng được yêu cầu. Khả năng chịu được áp lực công việc là yếu tố quan trọng giúp họ giữ vững tinh thần và hiệu suất làm việc trong những tình huống khó khăn.
Khả năng làm việc với các công nghệ quản lý nhân sự
Sự thành thạo trong việc sử dụng các hệ thống quản lý nhân sự (HRIS) là một yêu cầu cần thiết đối với người làm nhân sự hiện đại. Họ cần biết cách sử dụng các công cụ công nghệ để theo dõi, quản lý thông tin nhân viên và xử lý công việc một cách hiệu quả. Khả năng phân tích dữ liệu nhân sự từ các hệ thống này giúp họ đưa ra những quyết định chính xác liên quan đến tuyển dụng, đánh giá hiệu suất và quản lý phúc lợi.
Đạo đức nghề nghiệp và tính chính trực
Người làm nhân sự phải luôn duy trì sự bảo mật và kín đáo trong việc xử lý thông tin cá nhân và các vấn đề nội bộ của nhân viên. Đạo đức nghề nghiệp vững vàng và tính chính trực giúp họ đưa ra những quyết định công bằng và khách quan, xây dựng lòng tin và sự tôn trọng từ phía nhân viên và các bên liên quan.
Tinh thần cầu tiến và học hỏi liên tục
Ngành nhân sự liên tục thay đổi và phát triển, đặc biệt trong bối cảnh thị trường lao động đầy biến động. Người làm nhân sự cần có tinh thần cầu tiến, luôn cập nhật kiến thức mới và áp dụng những phương pháp, công nghệ tiên tiến nhằm cải thiện quy trình tuyển dụng và quản lý nhân sự. Khả năng thích ứng với sự thay đổi và học hỏi liên tục sẽ giúp họ nâng cao kỹ năng, cải thiện hiệu quả công việc và đóng góp tích cực vào sự phát triển của tổ chức.
Để theo đuổi nghề nhân sự, bạn có thể lựa chọn học các ngành học có liên quan trực tiếp đến quản trị nhân sự hoặc các ngành khác có liên quan đến quản lý và phát triển con người. Dưới đây là một số ngành học phổ biến mà nhiều người lựa chọn để bước vào lĩnh vực nhân sự:
Ngành Quản trị Nhân sự
Ngành Quản trị Kinh doanh
Ngành Tâm lý học
Ngành Luật
Ngành Xã hội học
Các nhóm ngành Kinh tế
Recruitment và Talent Acquisition có sự khác biệt như thế nào?
Tuyển dụng (Recruitment) là một quy trình được đơn giản hóa bởi các bước: Đăng tin tuyển dụng, tiếp nhận hồ sơ từ ứng viên, sàng lọc hồ sơ, phỏng vấn ứng viên và chọn người phù hợp (dựa trên các tiêu chí đã được xác lập.
Trong khi đó, Talent Acquisition là một quá trình “dài hơi” hơn vì nó được định hướng phát triển với với một tầm nhìn chiến lược trước và sau quá trình tuyển dụng. Điểm khác ở Talent Acquisition là ngoài việc tuyển dụng đơn thuần. Nó còn có nhiệm vụ lựa chọn nguồn nhân sự; theo dõi và xây dựng mối quan hệ với các ứng viên không được chọn để có thể tuyển dụng họ cho những vị trí phù hợp hơn.
Nói cách khác, Talent Acquisition giúp công ty tạo ra một nhóm ứng viên tiềm năng sẵn có để tuyển dụng trong tương lai. Các công ty có thể lưu dữ liệu của các ứng viên; tạo lập hệ thống để xem xét; chuẩn bị được một nguồn nhân lực dồi dào thay vì phải tuyển dụng nhiều lần.
Có khác biệt gì về nhân sự giữa công ty – HR Internal và các công ty dịch vụ nhân sự – HR Services?
Cả internal và services HR đều tìm những ứng viên phù hợp cho vị trí đang trống. Nhưng recruiter sẽ trực tiếp tham gia vào toàn bộ quá trình tuyển dụng. Từ đăng tin tuyển dụng; đọc hồ sơ của ứng viên và phỏng vấn trực tiếp. Một vài nhà tuyển dụng sẽ chủ động tìm kiếm ứng viên. Nhưng phần lớn họ sẽ đăng tin lên các trang tìm việc hoặc dùng trang web của công ty. Những nhà tuyển dụng sẽ thường xuyên theo dõi; tìm kiếm người cho vị trí còn trống trong công ty.
Các HR services – sẽ được các công ty thuê để tìm những ứng viên phù hợp cho những vị trí yêu cầu những kỹ năng đặc biệt và có trình độ cao. Nhiều công ty gặp nhiều khó khăn trong việc tuyển dụng những vị trí. Thông qua các kênh tìm kiếm thông thường hay muốn tiết kiệm thời gian; tiền bạc và công sức, họ sẽ tìm đến các headhunter.
Hiện nay, trên thị trường có nhiều công ty chưa xây dựng một cách hoàn thiện bộ phận Nhân sự. Do vậy, các chức năng nên có nhu cầu thuê ngoài từ các công ty cung cấp dịch vụ Nhân sự.
Có thể kể đến các dịch vụ như:
Dịch vụ tuyển dụng (Headhunter): Đây là dịch vụ tuyển nhân sự cho các công ty có nhu cầu;
Dịch vụ tiền lương và bảo hiểm: Dịch vụ này giúp xây dựng hiệu quả hệ thống bản lương và tính, chi trả lương hàng tháng cũng như các nghiệp vụ khác có liên quan đến việc đóng thuế thu nhập cá nhân cho người lao động;
Nhiều dịch vụ tư vấn quản trị nhân sự khác, thậm chí nhiều công ty tuyển dụng, đào tạo nhân sự và cho các công ty khác thuê lại nguồn lực nhân sự này.
Nguồn tài liệu nào phù hợp để tích lũy thêm kiến thức về Nhân sự, đặc biệt là trong mảng Tuyển dụng?
Trên thị trường, hiện vẫn chưa có một nguồn thông tin chính thống nào cung cấp những tài liệu về mảng Tuyển dụng, tuy nhiên, các bạn vẫn có thể tham khảo những nguồn sau đây:
Nguồn kiến thức từ các khóa học, đào tạo chuyên sâu về tuyển dụng. Lưu ý, các bạn nên cân nhắc vì chỉ khi bạn thật sự mong muốn đi theo và đồng hành, phát triển lâu dài với ngành nghề này thì hãy thử sức trải nghiệm; Lúc đó, bạn mới tìm thấy giá trị thật sự của công việc mà bạn sẽ theo đuổi;
Nguồn kiến thức từ các tài liệu là các trang web, bài viết, ebook, sách, tin tức về nhân sự, tuyển dụng (VD: Linkedin, SHRM,…). Một số quyển sách hay và khá nổi tiếng chuyên về Nhân sự như: Nguyên tắc nơi công sở (Work rules) của Google, Đắc nhân tâm, Sức mạnh của việc đặt câu hỏi đúng, Đừng bao giờ đi ăn một mình.
Lời kết
Hãy cẩn trọng trong việc chọn lọc thông tin vì với thời đại phát triển của truyền thông – mạng xã hội; lượng thông tin dễ bị nhiễu và có nhiều nguồn chưa thật sự chính xác. Nghề nhân sự ngày càng được quan tâm nhiều hơn thì đòi hỏi và thách thức với người làm nghề lại càng lớn. Hy vọng với những thông tin vừa chia sẻ, mọi người sẽ hiểu hơn về nhân sự là làm gì? HR là gì và những vấn đề xoay quanh. Nhân sự là làm gì sẽ không còn khiến nhiều người thắc mắc nữa. Chúc cho các bạn sẽ có những hành trang về thông tin bổ ích cho định hướng phát triển nghề nghiệp của mình.
Bài viết được sự cho phép của tác giả Trần Anh Tuấn
Hi! Xin chào các bạn hôm nay mình lại mang đến cho các bạn một bài viết mới khá là hay và chất lượng được tham khảo và viết lại dưới ngôn ngữ của chúng ta dựa trên bài viết gốc của tác giả Ishadeed. Trong bài viết này mình và các bạn sẽ cùng nhau tìm hiểu về CSS Scroll Snap nhé để xem thử nó là cái gì ? Và áp dụng vào thực tế ra sao nha.
Tại sao phải dùng scroll-snap ?
Chắc các bạn cũng biết nhu cầu sử dụng các thiết bị mobile, tablet ngày càng nhiều thì các trang web chúng ta phát triển việc phải có Responsive là đương nhiên, kèm theo đó là UX(trải nghiệm người dùng) trên các thiết bị đó. Ví dụ như một danh sách hình ảnh, nếu chúng ta để hiển thị chiều dọc trên điện thoại thì buộc người dùng phải scroll rất nhiều do đó phải tối ưu làm sao để người dùng có thể lướt qua xem dễ dàng hơn(scroll ngang).
Nếu các bạn code cho những giao diện dạng danh sách hình ảnh hay bài viết, thì chắc hẳn các bạn cũng có làm cho các phần tử scroll ngang với thuộc tính overflow-x: auto rồi. Ví dụ chúng ta có HTML và CSS như sau
Trước đây khi chưa có Flexbox thì white-space: nowrap thường hay được dùng để làm cho các phần tử nằm trên cùng một hàng mà không bị rớt xuống. Nhưng giờ đã có Flexbox rồi thì chúng ta sẽ cải thiện nó đơn giản hơn như này
.section{
display: flex;overflow-x: auto;
}
Vấn đề scroll với overflow
Vấn đề chính ở đây là chỉ với overflow thì việc trải nghiệm người dùng vẫn chưa tốt. Chúng ta cần giải pháp khác tốt hơn để người dùng dễ dàng sử dụng và thích nó. Nếu như với cách cơ bản là dùng overflow-x: auto thì nó sẽ không được mượt mà, các bạn xem video sẽ hiểu rõ hơn
Giới thiệu CSS scroll-snap
Để sử dụng scroll-snap cho một container nào đó thì những phần tử bên trong phải là inline và rất dễ dàng để làm việc đó với CSS Flexbox mà mình đã đề cập ở trên.
DÀNH CHO BẠN:
Mình có khoá học HTML CSS từ cơ bản tới nâng cao cho người mới, nếu bạn quan tâm thì bạn có thể học thử miễn phí bằng việc nhấn vào đây nha.
Với đoạn code ở trên thì vẫn chưa được, chúng ta cần thêm 2 thuộc tính nữa thì scroll-snap nó mới có thể hoạt động được. Vậy câu hỏi đặt ra là 2 thuộc tính đó là gì và dùng chúng ở đâu và dùng như thế nào ?
Đầu tiên chúng ta cần sử dụng thuộc tính scroll-snap-type cho container bao ngoài. Trong ví dụ của chúng ta thì container chính là thẻ div có class .section. Sau đó thì chúng ta sẽ thêm một thuộc tính khác scroll-snap-align cho các phần tử con bên trong, ở đây là .section__item
.section{
display: flex;overflow-x: auto;scroll-snap-type: x mandatory;}.section__item{scroll-snap-align: start;
}
Mình đoán là các bạn sẽ tự hỏi là những giá trị như x mandatory và start là cái gì thế nhỉ ? Đừng lo lắng, mình sẽ giải thích kỹ càng và chi tiết cho các bạn ngay sau đây thôi. Với những thuộc tính này thì cái container của chúng ta .section lúc này scroll nó mượt hơn và tốt hơn nhiều rồi. Xem video nè
Theo như CSS thì thuộc tính scroll-snap-type xác định kiểu snap cho container sử dụng scroll-snap có kiểu snap như thế nào và hướng scroll của container đó. Đọc khái niệm thì khó hiểu thật, vì mấy từ này không có dịch sang tiếng Việt của chúng ta đươc, thôi vào phân tích và code thử xem nó hoạt động như thế nào nha.
Hướng snap của container
Như khái niệm của nó thì trong thuộc tính scroll-snap-type có giá trị truyền vào là hướng mình muốn hiển thị ở đây là x và y tương ứng chiều ngang và chiều dọc.
Như ở trên thì chúng ta có thể xác định hướng của scroll snap, còn ở đây thì chúng ta có thể sử dụng kiểu mà nó được snap khi chúng ta scroll với 2 giá trị là mandatory | proximity
Giá trị mandatory nghĩa là trình duyệt phải snap theo từng điểm scroll. Giả sử thuộc tính scroll-snap-align có giá trị là start đi ha. Nghĩa là scroll lúc này phải snap theo hướng bắt đầu của container.
Các bạn thấy ở đường line màu xanh dương, là mỗi khi người dùng scroll ngang thì các phần tử luôn nằm sát về phía bên trái(đây gọi là start)
.section{
display: flex;overflow-x: auto;scroll-snap-type: x mandatory;}.section__item{scroll-snap-align: start;
}
Tuy nhiên, nếu giá trị là proximity, thì trình duyệt cũng vẫn hoạt động bình thường, nhưng kiểu snap của nó hơi khác chút đôi khi không có ngon lành như mandatory. Và các bạn lưu ý rằng proximity là giá trị mặc định nếu các bạn không thiết lập giá trị nhé.
.section{
display: flex;overflow-x: auto;scroll-snap-type: x proximity;
}
Scroll Snapping Alignment
Tiêu đề mục này mình để tiếng Anh luôn vì không biết ghi ra tiếng Việt sao cho dễ hiểu, nói chung là canh vị trí snap cho phần tử con bên trong nha. Và có 3 giá trị đó là start, center và end. Để dễ hiểu hơn thì các bạn nhìn vào cái hình này cho nó trực quan hơn nà(nhìn cái hình nam châm nha)
CHỜ 1 CHÚT:
Nếu bạn muốn tự học thiết kế web hiệu quả thì đừng quên tham khảo khoá học của mình, khoá học này mình dành tâm huyết xây dựng với hơn 130 videos chất lượng. Bạn có thể nhấn vào đây để mua ủng hộ mình nha.
Có nghĩa là khi dùng scroll-snap-type khi scroll ngang và các phần tử con mỗi lần scroll thì nó nằm theo kiểu canh bên trái, ở giữa hoặc là nằm cuối như hình trên nha. Ngược lại khi các bạn làm scroll dọc thì nó sẽ là trên cùng, ở giữa và dưới cùng như hình này:
Lý thuyết và hình thôi thì mình nghĩ các bạn vẫn chưa hình dung ra được đâu, đặc biệt bài này mình viết mấy từ cũng khó hiểu nữa. Coi video của từng giá trị khác nhau thì các bạn sẽ thông não hơn.
START
CENTER
END
Sử dụng scroll-snap-stop
Đôi khi các bạn cần tìm cách để tối ưu trải nghiệm hơn, giả sử người dùng vô tình lướt quá nhanh khi scroll, điều đó sẽ làm họ bị miss vài phần tử mà họ không biết. Các bạn coi video dưới này demo vấn đề đó nè
Giá trị mặc định của thuộc tính scroll-snap-stop là normal. Nghĩa là nó cho phép người dùng lướt nhanh qua các phần tử như video demo ở trên. Để khắc phục vấn đề này thì các bạn chỉ cần thay đổi giá trị lại thành always là ngon lành cành đào.
.section__item{
scroll-snap-align: start;scroll-snap-stop: always; // mặc định là normal
}
Các ví dụ thực tế
Friends List
Một ví dụ thực tế có sử dụng scroll snap là giao diện danh sách bạn bè từ Facebook như hình
.list{
display: flex;overflow-x: auto;scroll-snap-type: x mandatory;gap: 1rem;scroll-padding: 48px;padding-bottom: 32px;-webkit-overflow-scrolling: touch;}.list-item{scroll-snap-align: start;
}
Có một vấn đề khi sử dụng scroll snap đó chính là nếu các phần tử có box-shadow thì nó sẽ bị cắt đi, cho nên tuỳ vào thiết kế thì các bạn nên thêm padding vào các phần tử nha. Như ở giao diện Friend List này thì các bạn sẽ thấy có padding-bottom: 32px để box-shadow có thể hiển thị đẹp đó.
Avatars List
Với trường hợp này thì nếu sử dụng scroll-snap-align với giá trị là center thì sẽ đẹp hơn vì khi người dùng scroll thì thông tin sẽ được hiển thị chính giữa luôn.
.list{
display: flex;overflow-x: auto;scroll-snap-type: x mandatory;-webkit-overflow-scrolling: touch;
}.list-item{scroll-snap-align: center;
}
Lưu ý
Nếu các bạn sử dụng CSS scroll snap thì mình khuyến khích làm cho những layout dạng danh sách, người dùng lướt ngang trên các thiết bị như điện thoại, tablet, chứ đừng có dùng bừa bãi vào nội dung như dưới này là tèo ngay
.wrapper{
scroll-snap-type: y mandatory;}h2{scroll-snap-align: start;
}
Tạm kết
Giờ mình mới viết về bài này của tác giả Ishadeed, còn sử dụng scroll-snap này thì mình đã sử dụng lâu rồi. Lúc trước mình được giao task làm slider mượt mà trên điện thoại, mình dùng thư viện Slick Slider nhưng cảm thấy nó không được mượt và hay bị giật, ngồi mày mò và tìm được những đoạn code về CSS scroll-snap này và từ đó mình sử dụng nó thường xuyên luôn.
Mình hi vọng với bài viết này thì sẽ giúp cho các bạn biết thêm nhiều kiến thức mới hơn, từ đó biết cách áp dụng vào dự án của riêng mình nhé. Bài viết này khá là rối và sẽ có nhiều chỗ chưa tốt, mong được các bạn góp ý.