Làm sao inherit từ một object khác? Câu trả lời là dùng Prototype
Nếu pet là một prototype của cat, khi đó cat sẽ có luôn property legs
Khi khởi tạo object bằng cách viết object literal, chúng ta có thêm một property đặc biệt __proto__ để set prototype cho object đó.
Với ví dụ trên, chúng ta sẽ làm như sau
const pet ={ legs:4}const cat ={ sound:'Meow!', __proto__: pet }
cat.legs;// => 4
Property sound, chỉ tồn tại trong cat, người ta gọi tên nó là Own Property (property này là của anh, do anh tạo ra, anh không thừa hưởng từ bất kỳ ai).
Bạn có thể sẽ thắc mắc, tại sao lại sinh ra inheritance trong JS lằng nhằng thế ?
Vì bản chất JS ngày xưa không hỗ trợ class.
const pet ={ legs:4};const cat ={ sound:'Meow!', __proto__: pet };const dog ={ sound:'Bark!', __proto__: pet };const pig ={ sound:'Grunt!', __proto__: pet };
Sử dụng __proto__ không còn được chấp nhận, thay vào đó hay dùng Object.create()
const pet ={ legs:4};const cat =Object.create(pet);
cat.sound='Meow!';
Bên dưới, code trên sẽ được viết lại (bằng babel) gần giống thế này
const pet ={
legs:4};functionCreatePet(sound){return{ sound, __proto__: pet };}CreatePet.prototype= pet;const cat =CreatePet('Moew!');
cat.legs;// => 4
cat instanceofCreatePet;// => true
Bạn có thể sẽ thấy hơi bối rối, nếu bạn có nền tảng từ những ngôn ngữ có hỗ trợ class ngay trong trứng như Java hay PHP, không sao cả, ai cũng cần thời gian để tiếp thu những kiến thức mới.
Khi dùng React, hầu hết chúng không bận tâm đến việc tối ưu code vì bản thân nó đã khá nhanh. Trong bài viết hôm nay, chúng ta sẽ cùng xem qua cách sử dụng useMemo trong React để tối ưu tốc độ chương trình, hiểu và biết cách sử dụng useMemo sẽ giúp ích cho bạn trong sự nghiệp developer của mình đấy!
useMemo là gì?
useMemo là một hook trong React được sử dụng để ghi nhớ kết quả của một phép tính tốn kém (expensive calculation) và chỉ thực hiện lại phép tính đó khi các dependencies thay đổi. Hook này giúp tối ưu hóa hiệu suất bằng cách tránh việc thực hiện lại các phép tính không cần thiết mỗi khi component re-render.
computeExpensiveValue: Hàm tính toán mà bạn muốn ghi nhớ kết quả.
[a, b]: Danh sách các dependencies. Kết quả được ghi nhớ sẽ chỉ được tính lại khi một trong các dependencies này thay đổi.
Ví dụ
Ví dụ sử dụng useMemo
Trong ví dụ này, giá trị expensiveValue sẽ chỉ được tính toán lại khi giá trị của a hoặc b thay đổi. Điều này giúp tối ưu hóa hiệu suất của component bằng cách tránh các tính toán lại không cần thiết.
Khi nào sử dụng useMemo
Khi có những tính toán để lấy giá trị khá mất công, chúng ta lưu kết quả tính lại cho tiết kiệm thời gian tính toán.
Đừng dùng nhầm với React.memo và useCallback, chúng nó được dùng vào những mục đích rất khác nhau.
Bài viết được sự cho phép của tác giả Edward Thien Hoang
Cloud computing thì ai cũng đã quá quen thuộc, người người lên Cloud, nhà nhà lên Cloud. Gần đây lại xuất hiện trào lưu Cloud-native. Cloud native đã xuất hiện ở nước ngoài khá lâu rồi nhưng chỉ cập bến ở Việt Nam chúng ta vài năm gần đây thôi. Vậy Cloud-native là gì? Khác gì với Cloud computing vậy? Cloud-native là 1 buzzword, cũng giống như Cloud Computing, Blockchain. Buzzword mang một nghĩa chung chung mà không thể nào hiểu theo nghĩa đen được. Điện toán đám mây là gì? Có phải là máy tính để lên các đám mây cho mát thì gọi là điện toán đám mây. Trong bài này mình sẽ không cắt nghĩa Cloud Computing hay nói tắt là Cloud nữa, vì giờ ai cũng biết nó rồi. Quay lại với Cloud-native.
Cloud-native gồm 2 phần: “cloud” và “native”. Cloud trong Cloud Computing. Còn native? Google dịch sẽ ra: tự nhiên, bản xứ, bẩm sinh. Yeah, để dễ hình dung, hãy nghĩ về native speaker, là 1 người sinh ra và lớn lên đã sử dụng 1 ngôn ngữ làm ngôn ngữ mẹ đẻ. Và Cloud-native cũng vậy, nghĩa là từ khi sinh ra cho đến khi sản phẩm đưa vào vận hành thì phải chạy trên Cloud. Tuy nhiên, một ứng dụng Cloud-native thì chắc chắn chạy trên Cloud rồi, nhưng một ứng dụng chạy trên Cloud thì chưa chắc đã đạt tới cảnh giới Cloud-native. Như người Việt nói tiếng Anh tài đến cách mấy cũng chỉ đạt trình độ của người bản xứ được.
Tuy nhiên, cũng cần lưu ý thêm về các định nghĩa phổ biến về Cloud-native, đó là một ứng dụng Cloud-native sẽ không đề cập đến việc ứng dụng đó được triển khai ở đâu – WHERE (cụ thể ở đây chắc chắn là trên Cloud rồi), mà đề cập đến việc làm thế nào – HOW để ứng dụng có tính “bẩm sinh”, “native”.
“Cloud-native” is an approach to building and running applications that exploits the advantages of the cloud computing delivery model. “Cloud-native” is about howapplications are created and deployed, not where.
CONTAINER-NATIVE
OK, để có thể hiểu hơn về Cloud-native thì mình khuyên các bạn nên đọc qua bài viết về “Container-native” của tác giả Minh Monmen đăng trên Kipalog, mình xin trích dẫn 1 xíu ở đây.
…1 bác bên techcrunch có đưa ra 1 định nghĩa khá sát về khái niệm container-native:
Software that treats the container as the first-class unit of infrastructure (as opposed to, for example, treating the physical machine or the virtual machine as the first-class unit)
Software that does not just “happen to work” in, on or around containers, but rather is purposefully designed for containers
Đại khái định nghĩa này nói rằng bạn 1 là phải coi container là thứ sẽ triển khai ứng dụng của bạn, không phải 1 con VM hay máy chủ vật lý. Thứ 2 là việc bạn định hướng container-native phải được làm từ đầu khi khởi tạo ứng dụng, chứ không phải là cứ code rồi… Bụp một cái mang nó vào container là chạy được…
Sau khi đọc xong, có thể là cái hiểu của bạn sẽ được tăng lên để hiểu được từ “native”.
VẬY TẠI SAO PHẢI CẦN CLOUD-NATIVE?
What thì mình đã cắt nghĩa ở trên. Còn Why, mình sẽ đưa ra 1 số ý kiến. Như mọi người đã biết và hiểu được một trong những đặc tính quan trọng bậc nhất của Cloud Computing đó là tính đàn hồi (elasticity), giúp cho ứng dụng chạy trên Cloud sẽ có thể co dãn, scaling up and down hay in and out một cách dễ dàng, phù hợp với nhu cầu, workload hiện tại của system. Tuy nhiên càng hiện đại thì càng hại điện. Có bao nhiêu hệ thống hoặc ứng dụng có thể tận dụng tối đa lợi ích mà Cloud Computing mang lại? Trong quá trình phát triển sản phẩm, bạn có đặt ưu tiên về scalability của ứng dụng lên trên cùng? Hay việc vận hành, bảo trì, CI/CD? Với việc microservices đang ngày càng thịnh hành, thì việc quản lý một đống service cũng không phải là điều dễ dàng. Và yeah, Cloud-native chính là keyword, tập hợp rất nhiều practices, guideline, là cứu cánh cho chúng ta. Cùng điểm qua 1 số ý chính bằng tiếng Anh (vì lười dịch quá :D)
10 Key Attributes of Cloud-Native Applications
Packaged as lightweight containers
Developed with best-of-breed languages and frameworks
Designed as loosely coupled microservices
Centered around APIs for interaction and collaboration
Architected with a clean separation of stateless and stateful services
Isolated from server and operating system dependencies
Deployed on self-service, elastic, cloud infrastructure
Phìu, có thể túm qua 1 số ý chính là: hệ thống nên buid dạng microservices, chạy trong container (Docker) và có sự hỗ trợ của các Container management platform như Kubernetes. Cần, agility và automation với DevOps và mọi thứ trên Cloud. Và quan trọng nhất là mọi thứ phải được consider ngay từ khâu thiết kế, chứ không phải đợi đến lúc triển khai thì too late và có thể là impossible
VẬY LÀM SAO ĐỂ ĐẠT TỚI CẢNH GIỚI NATIVE?
Cái khó nhất khi tìm hiểu 1 vấn đề nào đó nằm ở WHAT and WHY, chứ HOW thì đó là nghề của anh em developer rồi. Google phát là ra ngay, nên mình để phần này cho anh em tự khám phá.
Hôm nay tình cờ đọc được 1 quyển sách về MySQL thấy khá hay nên muốn chia sẻ lại với mọi người những cái mình đã học được.
Về MySQL thì chắc ai cũng đã từng dùng hay đang dùng nó cho một số dự án từ vài người dùng đến hàng triệu người dùng. Từ các website về blog cho đến các trang thương mại điện tử, các server dành cho game…
Với hệ thống nhỏ nhỏ thì chắc chẳng cần quan tâm gì nhiều đến cách hoạt động của nó làm gì cho mệt. Nhưng mà khi hệ thống dã lớn lên, phải xử lí hàng nghìn, hàng triệu queries/s thì việc hiểu rõ được cơ chế hoạt động cũng nó là điều vô cùng quan trọng.
Việc master được tất tần tật về MySQL thì vô cùng khó, nhưng mà hiểu được cái gì đó sâu sâu 1 chút thì cũng giúp chúng ta hơn hẳn được nhiều người rồi.
Nên hôm nay mình sẽ giới thiệu đến mọi người 1 số vấn đề mà mọi người đang chưa hiểu hoặc hiểu nhầm về MySQL nhé.
Mục tiêu bài viết:
・Hiểu được chức năng bên trong MySQL
・Biết cách thiết kế dữ liệu cho tối ưu nhất
Đối tượng hướng đến:
・Người đã từng làm việc với MySQL
・Người muốn tối ưu hiệu năng MySQL
1. Đơn vị I/O
Khi dùng MySQL thì đa số là thao tác trên các record(bản ghi) của MySQL. Nên đa số chúng ta đều nghĩ là dữ liệu được xử lí theo đơn vị record. Nhưng thực tế MySQL lại thao tác dữ liệu theo từng đơn vị page (trang) có kích thước được định nghĩa trước.
Để dễ hiểu thì chúng ta cùng xem ảnh bên dưới:
Nhìn vào ảnh bên trên thì mình nghĩ mọi người có thể hiểu được. Thì đơn vị I/0 nhỏ nhất trong MySQL không phải là record mà là page nhé.
Với MySQL thì kích thước của page default là 16KB. (Ở đây mọi người nên chú ý 1 điểm là nếu muốn change size của page thì chúng ta phải xoá instance đi và tạo lại thì mới change được, còn chỉ start stop mysql thì không thể change được nhé)
Chính vì lí do đó mà thằng RDS của AWS không có option change được size của page.
Vậy đến đây đa số cũng biết được đơn vị cấu tạo nhỏ nhất của I/O trong MySQL là gì rồi đúng không ak?
Vậy biết được cái này để làm gì? Thì đi đến phần tiếp theo nhá.
2. Ảnh hưởng to lớn của AUTO_INCREMENT
Việc setting primary key (khoá chính) với AUTO_INCREMENT thì chắc ai cũng biết rồi. Nhưng mà việc setting này có ảnh hưởng to lớn đến hiệu năng như thế nào thì chúng ta cùng đi xem 2 ví dụ dưới đây nhé.
Để dễ hiểu, mình sẽ lấy 1 ví dụ trong game nhé. Đó là muốn tạo ra 1 bảng lưu giữ thông tin nhân vật(character) của người dùng.
Ví dụ 1:
CREATE TABLE user_characters {
user_id INT NOT NULL DEFAULT 0,
user_character_id INT NOT NULL DEFAULT 0,
character_id INT NOT NULL DEFAULT 0,
PRIMARY_KEY (user_id, user_character_id),
}
Ví dụ 2:
CREATE TABLE user_characters {id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL DEFAULT 0,
user_character_id INT NOT NULL DEFAULT 0,
character_id INT NOT NULL DEFAULT 0,
}
Khi chúng ta muốn lấy thông tin nhân vật mà người dùng có ID =4 1234 đang giữ thì sẽ thực hiện câu SQL như sau:
SELECT * FROM user_characters WHERE user_id = 41234
Vậy hiệu năng khi thực hiện câu SQL này trên 2 ví dụ trên khác nhau thế nào?
Cụ thể như ảnh bên dưới:
Với ví dụ 1, thì userid được gắn là khoá chính. Nên dữ liệu sẽ được sắp xếp theo thứ tự của userid. Do đó mà thông tin lấy được từ user_characters khả năng cao sẽ được nằm trong 1 page. Mà nếu dữ liệu được nằm trong 1 page thì chắc chắn I/O sẽ được giảm mạnh, và hiệu suất query sẽ tốt hơn.
Nhưng với ví dụ 2 thì hoàn toàn khác. Lúc này khoá chính của chúng ta là id. Nên việc dữ liệu tất cả nhân vật mà user_id = 41234 đang nắm giữ khả năng cao sẽ nằm rải rác trên nhiều page khác nhau. Kết quả là I/O sẽ tăng và hiệu năng query sẽ giảm đi rất là nhiều.
Chính vì vậy, với nhiều dữ liệu sử dụng đồng thời như ví dụ trên thì chúng ta cố gắng sắp xếp nó cùng vào 1 page nhé.
Kết luận
Hôm nay thế thôi nhỉ. Để hôm khác mình sẽ bổ sung thêm(Tại ngại vẽ hình). Hi vọng qua bài này sẽ giúp ích mọi người trong quá trình thiết kế cơ sở dữ liệu sao cho hiệu năng tốt nhất.
Mỗi ngành khác nhau đều có những thuật ngữ mà chỉ những người trong ngành mới hiểu, bạn là người vừa mới đi làm thì sẽ khá lạ lẫm với những thuật ngữ chuyên ngành của lập trình nên tôi viết bài này để chia sẻ này để bạn có thể hiểu được những anh chị trong công ty đang nói về chủ đề gì.
Source code dịch ra tiếng việt đó là mã nguồn, khi nói về source code thì ta hiểu là đang nói về những tất cả những cái mà mình lập trình ở trong một dự án nhé.
2. Commit code
Trong mỗi dự án của chúng ta thì đều sử dụng SVN hoặc GIT. SVN/GIT công cụ để quản lý source code, là nơi để chứa source code, tất cả lập trình viên mà làm chung một dự án sẽ sử dụng chung một nguồn này. Tại sao người ta dùng nó thì tôi sẽ có một bài viết chi tiết hơn nói về những tính năng hay ho của nó. Phần này đang nói về thuật ngữ commit code. Commit code có nghĩa là mình sẽ đẩy hết những cái gì mình vừa code được lên nơi chứa source code của SVN/GIT.
3. Testcase
Thường thì sau khi kết thúc giai đoạn code thì sẽ đến một giai đoạn nữa đó là test(kiểm thử) sản phẩm của mình xem có làm đúng theo yêu cầu của khách hàng chưa, có bug gì hay không. Testcase là các trường hợp kiểm tra cho những đoạn mã (code) của mình đảm bảo rằng nó đã chạy đúng với yêu cầu, không phát sinh vấn đề gì.
4. Bug, Fix Bug
Bug là những cái sau khi test theo testcase nhưng không đúng với yêu cầu khách hàng hoặc bug do lỗi coding (exeption..) . Sau khi phát sinh bug thì người lập trình phải đi sửa lỗi, làm sao cho nó đúng với yêu cầu của khách hàng. Lúc này người ta gọi là Fix bug.
5. Schedule
Mỗi khi vào dự án thì các leader sẽ chuẩn bị schedule, đây là lịch trình làm dự án, ví dụ màn hình A sẽ code vào ngày 16/03/2020 – 18/03/2020. Schedule sẽ lên danh sách tất cả các màn hình và thời gian làm của mỗi màn hình đó, việc của bạn là phải tuân thủ đúng thời gian trong schedule
6. Evidence
Evidence dịch ra tiếng việt là bằng chứng. Khi thực hiện công việc test, thì nhiều khi phải chụp lại bằng chứng cho khách hàng biết là mình đã test qua trường hợp này rồi.
7. Kick off
Kick off là bắt đầu một dự án mới.
8. UT
Về test thì có rất nhiều kiểu test khác nhau, UT là viết tắt của unit test.
Bài viết được sự cho phép của tác giả Trần Hữu Cương
1.FrameLayout trong Android
Framelayout là một layout thuộc loại đơn giản nhất và hiệu quả nhất về bố cục.
FrameLayout là một ViewGroup được sử dụng rất nhiều trong android.
Bởi vì nó là ViewGroup đơn giản nhất, và thời gian tính toán của nó để layout ra các view con trong nó là thấp nhất nên performence của ViewGroup này là cao nhất.
Bạn cũng có thể sử dụng nhiều view con vào FrameLayout với thuộc tính android:layout_gravity.
Xác định drawable để vẽ lên nội dung và giá trị có thể có thể là một trong các giá trị màu dưới dạng “#rgb”, “#argb”, “#rrggbb” hoặc “#aarrggbb”.
android:foregroundGravity
Xác định gravity để áp dụng cho nền trước có thể vẽ được. Gravity mặc định sẽ lấp đầy, giá trị có thể là trên cùng, dưới cùng, bên trái, bên phải, giữa, center_vertical, center_horizontal…
android:measureAllChildren
Xác định xem có đo lường tất cả children hay chỉ những children ở trạng thái VISIBLE hoặc INVISIBLE, mặc định là FALSE.
Thuộc tính android:layout_gravity trong các View con
Khi các View nằm trong FrameLayout thì khi gán thuộc tính android:layout_gravity gán các giá trị ở bảng sau vị trí của nó thay đổi tương ứng:
<?xml version="1.0" encoding="utf-8"?><FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:padding="10dp"android:layout_width="match_parent"android:layout_height="match_parent"><!--Ảnh kín FrameLayout--><ImageViewandroid:src="@drawable/tramanh"android:scaleType="centerCrop"android:layout_width="match_parent"android:layout_height="match_parent"/><!--Button ở giữa, bên phải và cách mép phải FrameLayout 20dp--><Buttonandroid:layout_gravity="center|right"android:layout_marginRight="20dp"android:text="Button"android:layout_width="wrap_content"android:layout_height="wrap_content"/><!--Dòng chữ ở giữa, phần trên FrameLayout--><TextViewandroid:layout_gravity="center|top"android:layout_marginTop="10dp"android:text="Đây là một TextView"android:layout_width="100dp"android:gravity="center"android:layout_height="wrap_content"/></FrameLayout>
Và đây là kết quả sau khi bạn sử dụng FrameLayout khi thêm vào xml.
Ưu điểm
+ Là ViewGroup đơn giản nên thời gian tính toán để layout các view con nhanh.
Bài viết được sự cho phép của tác giả Trần Hữu Cương
I. Giới thiệu
ConstraintLayout là một layout mới mà Google cung cấp cho chúng ta để xây dựng giao diện cho các ứng dụng Android
ConstraintLayout giúp cho việc thiết kế các layouts phức tạp trở nên đơn giản hơn bằng cách cho phép các views kết nối với nhau thông qua các ràng buộc dựa trên mối quan hệ giữa các views khác nhau.
ConstraintLayout hướng tới việc thiết kếgiảm các views lồng nhau ,điều này sẽ làm tăng hiệu suất thực thi cho các tập tin layout.
II.Làm Quen Với ConstraintLayout
Định vị các views
ConstraintLayout cung cấp các thuộc tính cho phép chúng ta định vị view hiện tại một cách dễ dàng. Các thuộc tính được mô tả như bảng sau:
Các thuộc tính
Mô tả
layout_constraintTop_toTopOf
Ràng buộc phần trên (top) của view hiện tại đến phần trên của view khác.
layout_constraintTop_toBottomOf
Ràng buộc phần trên của view hiện tại đến phần dưới (bottom) của view khác.
layout_constraintBottom_toTopOf
Ràng buộc phần dưới của view hiện tại đến phần trên của view khác.
layout_constraintBottom_toBottomOf
Ràng buộc phần dưới của view hiện tại đến phần dưới của view khác.
layout_constraintLeft_toTopOf
Ràng buộc bên trái (left) của view hiện tại đến phần trên của view khác.
layout_constraintLeft_toBottomOf
Ràng buộc bên trái của view hiện tại đến phần dưới của view khác.
layout_constraintLeft_toLeftOf
Ràng buộc bên trái của view hiện tại đến bên trái của view khác.
layout_constraintLeft_toRightOf
Ràng buộc bên trái của view hiện tại đến bên phải (right) của view khác.
layout_constraintRight_toTopOf
Ràng buộc bên phải của view hiện tại đến phần trên của view khác.
layout_constraintRight_toBottomOf
Ràng buộc bên phải của view hiện tại đến phần dưới của view khác.
layout_constraintRight_toLeftOf
Ràng buộc bên phải của view hiện tại đến bên trái của view khác.
layout_constraintRight_toRightOf
Ràng buộc bên phải của view hiện tại đến bên phải của view khác.
Start, End
Chúng ta có thể dùng Start để thay thế cho Left và dùng End để thay thế cho Right. Lưu ý rằng, khi dùng Start thì phải dùng Start hay End tương ứng, không được dùng Start kết hợp với Left hay Right.Ví dụ layout_constraintRight_toLeftOf tương đương với layout_constraintEnd_toStartOf
layout_constraintHorizontal_bias
Định vị view theo trục ngang màn hình.
layout_constraintVertical_bias
Định vị view theo trục dọc màn hình.
Ví dụ :Cho Textview ở giữa màn hình và button cuối màn hình và ở dưới textview
Giống như các views, ConstraintLayout cung cấp hai thuộc tính là layout_width và layout_heightcho phép chúng ta điểu khiển kích cỡ của ConstraintLayout như ý. Có 3 kiểu giá trị phổ biến dùng cho layout_width và layout_height như sau:
Tùy ý, ví 18dp hay 133dp: kích cỡ layout là cố định theo giá trị cho trước
wrap_content: điều chỉnh kích cỡ layout vừa khớp với nội dung bên trong nó
match_parent: mở rộng kích cỡ layout khớp kích cỡ của view cha hay view chứa nó
Bias
bias – có thể hiểu là bạn muốn sắp xếp View này thiên về bên nào hơn. Giá trị của bias nằm trong khoảng từ 0 đến 1 và có kiểu Float. Thuộc tính này chỉ có tác dụng khi View đang neo 2 cạnh đối diện hoặc cả 4 cạnh. ConstraintLayout cung cấp thuộc tính này cho cả chiều ngang (horizontal) và chiều dọc (vertical). Và nếu khi đã neo 2 cạnh hoặc 4 cạnh, nếu không có giá trị bias nào được chỉ định, bias sẽ có giá trị mặc định là 0.5, tức là vào giữa của 2 hoặc 4 điểm neo.
Hy vọng bài hôm nay sẽ giúp các bạn sử dụng tốt Constraint layout trong Android.
Bài viết được sự cho phép của BQT Kinh nghiệm lập trình
Thông thường khi cài đặt sẽ có thông báo mật khẩu tự sinh ra bởi MySQL để đăng nhập. Tuy nhiên nếu quên mất mật khẩu root hoặc muốn đổi mật khẩu thì phải làm sao? Khi mình mới làm quen với MySQL cũng đã phải mất nhiều thời gian chỉ vì vấn đề này. Có lẽ nhiều bạn sẽ có điều băn khoăn tương tự. Vậy hãy cùng tìm hiểu hướng giải quyết nhé.
Trước hết, nếu bạn vẫn còn mông lung về khái niệm và phân loại cơ sở dữ liệu, MySQL thuộc loại nào, chắc bạn sẽ muốn xem qua bài viết này.
Đây không phải là vấn đề quá khó khăn, phức tạp. Tuy nhiên, khi chúng ta mới làm quen thì những điều nhỏ nhặt nhất cũng làm ta bối rối. Thậm chí, kể cả những người đã làm việc nhiều với MySQL cũng có thể không nhớ, hay không nhớ hết, những bước phải làm khi lỡ quên mật khẩu.
Vậy chúng ta phải xử lý trường hợp này như thế nào? Hãy làm theo 8 bước dưới đây nhé.
Nếu không có Go Modules thì anh em có nhớ mỗi lần clone project về để tham khảo là phải sử dụng lệnh “go get” để tải thư viện, rất chi là mất thời gian luôn, nếu project ít thư viện thì không nói, project mà sử dụng nhiều module thư viện thì tải về bằng “go get” sẽ rất là nản.
Sử dụng Go Mod
Anh em có thể tải code tham khảo và thực hành với project Go ở đường link sau đây: Github
Project trên mình xây dựng trong GOPATH với link hướng dẫn chi tiết tại: https://anhlamweb.com/bai-viet-70/xay-dung-rest-api-co-ban-trong-golang.html
Và giờ từ project đó mình sẽ chuyển qua dùng Go Modules để quản lý các module thư viện dễ dàng hơn nha.
Anh em có thể để ý, sau khi clone project về với đường link Git ở trên thì có 2 file go.mod và go.sum.
go.mod : Định nghĩa đường dẫn của các module.
go.sum: Để lưu vết version của thư viện mà project đang sử dụng.
Anh em nhớ check lại version go mà mình đang sử dụng nhé, nếu Go 1.11 trở lên thì mới có Go Modules nhé.
Với việc sử dụng Go mod, đường dẫn tới project phải nằm ngoài thư mục src của GOPATH hoặc anh em có thể xóa biến môi trường của GOPATH đi luôn cũng được.
Bước 1: sau khi clone project về nếu anh em muốn chạy ngay chương trình thì cứ việc chạy lệnh go run main.go là được, go mod sẽ tự động tải các gói module về cho anh em luôn.
Bước 2: Bước này anh em muốn tự tay mình biểu diễn kỹ thuật, thì hãy xóa go.mod và go.sum đi sau đó chạy lệnh:
go mod init
Sau khi chạy lệnh trên thì file go.mod được khởi tạo.
Sau khi ứng dụng đã chạy, anh em có thể tham khảo bài viết này https://anhlamweb.com/bai-viet-70/xay-dung-rest-api-co-ban-trong-golang.html để test lại các API nhé. Chúc anh em thành công.
Một CV hoàn chỉnh cần đảm bảo các nội dung cần thiết. Mục kỹ năng được xem là 1 trong 3 yếu tố quan trọng nhất mà nhà tuyển dụng khai thác ở ứng viên. Việc trình bày kỹ năng không chỉ đơn thuần dừng lại ở việc liệt kê. Nó còn đòi hỏi ứng viên cần nắm bắt tốt các khía cạnh khác để CV đạt hiệu quả. Cùng TopDev theo dõi bài viết sau để tìm ra cách thức giúp làm nổi bật mục kỹ năng trong CV của bạn.
Phần kỹ năng trong CV có thật sự quan trọng?
Nhà tuyển dụng chỉ cần 3-5s để phân loại chất lượng CV IT của bạn. Nó ngắn hơn các loại văn bản dài như sơ yếu lý lịch cho IT,…Điều đó đồng nghĩa cơ hội để bạn tạo ấn tượng là hết sức cạnh tranh.
Kỹ năng có thật sự quan trọng trong CV IT
Nếu không biết tạo điểm nhấn, đặc biệt đối với các vị trí cao hơn như Senior Developer, CV của bạn sẽ bị quên lãng.
Phần kỹ năng là phần rất quan trọng. Nó chiếm phần trăm lớn sự kỳ vọng mà mọi nhà tuyển dụng tìm kiếm ở ứng viên. Do vậy, việc trình bày, chọn lọc các kỹ năng cũng cần phải thông minh và có chiến lược. Đừng để CV IT của bạn trở nên không có giá trị. Và tất nhiên, bạn sẽ bị out khỏi vòng phỏng vấn đấy!
Những điều cần lưu ý khi trình bày kỹ năng trong CV
Có thể bạn có rất nhiều kỹ năng. Thế nhưng, điều này không có nghĩa bạn có thể phô trương hết chúng vào trong CV của mình. Với trường hợp là CV cho sinh viên IT mới ra trường, có thể bạn còn thiếu sót.
Tuy nhiên, khi apply các vị trí khác thì CV Junior Developer, Senior Developer, Mobile App Developer thì CV IT của bạn cần phải tập trung vào các kỹ năng chuyên sâu hơn. Vì vậy, hãy lưu tâm những tips sau đây:
Cụ thể hóa và trình bày các kỹ năng ứng với vị trí công việc
Mục đích quan trọng của phần kỹ năng là thuyết phục nhà tuyển dụng bạn phù hợp với vị trí ứng tuyển.
Vì vậy, chỉ những kỹ năng quan trọng đến vị trí ứng tuyển thì mới nên hiện diện trong list kỹ năng CV. Ví dụ như đối với CV Senior Developer, bạn nên lựa chọn các kỹ năng chuyên sâu về công nghệ như các ngôn ngữ lập trình, viết code, và các kiến thức có liên quan.
Đồng thời, viết CV giúp bạn định hình và có những trải nghiệm tốt hơn. Trường hợp bạn ứng tuyển các vị trí khác như freelancer it hay Senior Developer đều sẽ đạt hiệu quả ứng tuyển cao hơn.
Việc linh hoạt trong việc phân chia các kỹ năng có ý nghĩa rất quan trọng
Hãy chia các kỹ năng của bạn thành từng các mục nhỏ ứng với các đặc trưng chuyên môn khác nhau. Bạn có thể liệt kê và phân chia các kỹ năng về ngôn ngữ lập trình; các nhóm kỹ năng về phần mềm. Chính việc phân loại giúp bạn hiểu rõ hơn về vị trí. Đồng thời, nhà tuyển dụng sẽ đánh giá cao hơn về năng lực phân tích của bạn.
Tập trung vào các kỹ năng quan trọng theo tần suất
Đây là cách ứng viên nhấn mạnh các kỹ năng quan trọng bằng cách lặp lại các kỹ năng. Tất nhiên, việc “rải” từ khóa về kỹ năng cần ứng viên phải khéo léo và tinh tế. Bạn có thể phân theo từng mục và giới hạn xuất hiện để đảm bảo các kỹ năng không bị trùng lặp quá nhiều lần.
Cụ thể bạn có thể liệt kê kỹ năng trong phần đầu – phần giới thiệu và phần kinh nghiệm làm việc. Từ khóa về kỹ năng rất quan trọng để nhà tuyển dụng kết luận đâu là điểm mạnh của bạn. Tuy vậy, tần suất hoàn hảo nhất của một kỹ năng chỉ nên từ 2-3 lần.
Ứng viên không nên quá lạm dụng. Đặc biệt, kỹ năng được lặp lại phải thật sự phản ánh chính xác năng lực của bạn.
Lời kết
Kỹ năng là một yếu tố quan trọng xét về nội dung CV. Một CV sẽ mất đi giá trị tổng thể nếu thiếu đi mục kỹ năng. TopDev hy vọng với những chia sẻ thông qua bài viết, các ứng viên sẽ biết cách điều chỉnh và hoàn thiện chuyên mục kỹ năng của CV IT, giúp CV của mình ghi điểm tuyệt đối với nhà tuyển dụng.
4 tips học Java cơ bản nhanh nhất dành cho Beginner Developer
Tác giả: Back To Back SWE
Cách tôi bắt đầu làm quen với Java cơ bản
Bài viết hôm nay của tôi sẽ chia sẻ với các bạn những tips để lập trình Java, android cũng như những thứ khác một cách nhanh nhất. Giới thiệu qua một chút về bản thân thì cho đến 2 năm trước, tôi vẫn chưa biết gì nhiều về lập trình cả. Lúc đó trong đầu tôi xuất hiện rất nhiều các ý tưởng về lập trình app nhưng không biết nên bắt đầu từ đâu cả. Vậy là tôi tìm kiếm rất nhiều các nguồn tài liệu để nghiên cứu về lập trình từ các video, đến sách vở và tham gia thêm các khóa học.
Tôi đăng ký khóa học Java online trong 1 tháng và học android trong 2 tháng. Sau khi kết thúc khóa học, tôi đã tự build được app đầu tiên trong sự nghiệp của mình với những idea mà mình vẫn luôn ấp ủ trước giờ. Tuy nhiên, nhìn lại quá trình này tôi rút ra một số kinh nghiệm để có thể làm việc tốt hơn khi bắt đầu với Java cơ bản.
Học java cơ bản giúp ích rất nhiều cho quá trình lập trình sau này
Những kinh nghiệm để học Java cơ bản hiệu quả
1. Đừng vội vàng khi bắt đầu học Java cơ bản
Nhiều bạn nghĩ rằng càng đi nhanh việc học sẽ càng đạt kết quả sớm hơn. Tuy nhiên sự thật là bạn không nên vội vàng khi học lập trình. Học một cách chậm rãi sẽ khiến bạn có nhiều thời gian để tiếp thu kiến thức cũng như nắm vững những vấn đề về Java cơ bản. Sau đó bạn có thể tăng tốc quá trình học một cách nhanh nhất có thể khi đã có căn bản. Có nhiều bạn khi mới bắt đầu học chỉ lướt sơ về kiến thức với một số điểm nổi bật, vì thế mà bạn không thể nắm được bức tranh tổng thể về Java cơ bản.
Nếu học theo kiểu sơ sài như thế này, nó sẽ trở thành thứ ngăn cản bạn học thêm các ngôn ngữ lập trình mới và chỉ khiến quá trình tiếp thu kiến thức ngày càng chậm đi mà thôi. Vì vậy hãy dành nhiều thời gian học tập khi mới bắt đầu để đẩy tốc độ học về sau. Java cơ bản gần như là kiến thức tối quan trọng mà bạn cần nắm chắc để không mắc sai lầm về sau cũng như học nhanh hơn sau này.
2. Tập trung nghiên cứu các lỗi sai bạn mắc phải
Việc mắc lỗi luôn xảy ra khi mới bắt đầu học lập trình, tuy nhiên nhiều dev chỉ đơn giản bỏ qua những dòng code lỗi và viết mới. Bạn thật sự rất cần tìm hiểu về những code bị lỗi, để có thể nghiên cứu và tìm ra nguyên nhân tại sao code đó lại không chạy được, vấn đề đang nằm ở đâu, có như vậy bạn mới tìm ra được những dòng code tốt nhất cho chương trình của mình.
Hơn nữa, nếu bạn không tìm hiểu nguyên nhân và sửa lại, chương trình bạn viết ra sẽ ngày càng nhiều code hơn. Nó là một bản chắp vá của rất nhiều lỗi nhỏ khác nhau. Đến một lúc nào đó, bạn sẽ hoàn toàn không thể quản lý được những gì bạn viết ra nữa. Nó sẽ trở thành cơn ác mộng cho việc sửa chữa hay để người khác quản lý được chương trình này. Nghe có vẻ khó hiểu đúng không? Bạn phải thật sự đang coding và đọc những dòng này thì mới hiểu những gì tôi đang nói đó.
Để học tốt java, bạn nên có sự đầu tư và nghiên cứu bài bản
3. Cố gắng nắm rõ và bao quát được nhiều bài học
Để học tập hiệu quả hơn, bạn nên cố gắng xem qua mỗi một bài học có liên quan đến Java cơ bản. Ngay cả khi bạn đã học thuộc lòng chúng hay đang cầm tài liệu trên tay, bạn vẫn nên cố gắng xem qua mỗi bài học và hiểu rõ về mọi khía cạnh của chúng. Vì chẳng ai biết được một lúc nào đó, khi đang coding và build program một cách trơn tru, bạn lại đột nhiên quên mất một chi tiết nhỏ nhưng rất cần thiết để hoàn thành được chương trình một cách hoàn hảo nhất. Vì quên kiến thức bạn phải quay lại từ đầu để tìm cách và việc này chắc chắn sẽ mất rất nhiều thời gian.
Hãy đảm bảo rằng bạn có đủ thời gian để xem qua các bài học. Đó cũng là cách để bạn có thể học nhanh nhất. Bạn có thể hiểu được sự liên kết của những kiến thức Java cơ bản trong số rất nhiều các ngôn ngữ lập trình khác.
Bạn nên lên lịch để luyện tập coding mỗi ngày, bạn có thể dành từ 30 phút đến 2 giờ để code. Khi mới bắt đầu học lập trình, tôi dành ra 4 đến 5 tiếng mỗi ngày để tập tành làm việc, kể cả là phải thức khuya. Thật sự thì tôi không khuyến khích bạn làm quá nhiều việc vì nó sẽ không hiệu quả. Tôi nghĩ bạn nên dành ra 30 phút đến 1 tiếng mỗi ngày để thực hành 1 hoặc 2 bài tập liên quan đến học Java cơ bản là tốt rồi.
Chẳng hạn như với khóa học Java online mà tôi đăng ký với thời gian học trong 1 tháng. Trong suốt 1 tháng đó, mỗi ngày có 3 video được gửi đến email của tôi, tôi mất 15 phút để xem qua chúng. Đây thật sự là phương pháp hiệu quả để tôi nâng cao tay nghề của mình. Tôi nghĩ rằng việc học tập và thực hành mỗi ngày là cần thiết và bạn nên sắp xếp thời gian hợp lý để làm điều đó. Hãy xem việc học như một sở thích và đừng quá đặt nặng áp lực phải làm cho tốt. Mọi thứ sẽ được cải thiện dần dần.
Bên cạnh đó, việc nắm chắc các kiến thức Java cơ bản cũng giúp bạn làm việc tốt hơn hoặc khi chuyển sang làm việc ở lĩnh vực khác cũng dễ dàng thích nghi và học hỏi hơn. Chẳng hạn như hiện nay, tester đang là một trong những hot job được nhiều người nhắm đến. Lương Senior Tester luôn nằm trong hạng top đối với các công việc khác của ngành IT.
Kết luận
Để học tập tốt cũng như làm việc hiệu quả hơn, các dev nên biết cách sử dụng các tip để làm quen với việc học và thực hành. Nó không chỉ mang lại kết quả khả quan hơn mà còn giúp bạn tiết kiệm được kha khá thời gian của mình đấy. Và nhờ kỹ năng làm việc tốt bạn sẽ tìm được công việc yêu thích của mình ở môi trường chuyên nghiệp như Gear Inc. chẳng hạn.
Gear Inc. Vietnam tuyển dụng hiện đang được đánh giá là một trong những cơ hội làm việc hấp dẫn dành cho các developer. Môi trường làm việc hiện đại, đội ngũ phát triển đạt tầm quốc tế cùng với sự gắn kết giữa các đồng nghiệp sẽ giúp bạn dễ dàng học hỏi và tích lũy kinh nghiệm làm việc. Sự năng động và phóng khoáng của môi trường sáng tạo game chắc chắn sẽ khiến bạn thấy thoải mái hơn khi làm việc tại Gear Inc. Đây là những đánh giá được ghi nhận về Gear Inc review.
Bắt đầu từ một pet product để giải quyết những vấn đề cá nhân gặp phải trong quá trình làm việc, bạn Nghĩa Trần đã dày công theo đuổi và xây dựng Proxyman trở thành một sản phẩm chuyên nghiệp thu hút được hàng nghìn user đến từ khắp nơi trên thế giới, đem về doanh thu cực khủng.
Bài phỏng vấn dưới đây là những chia sẻ hết sức thú vị và bổ ích của Nghĩa về kinh nghiệm cũng như quá trình xây dựng và phát triển Proxyman.
Xin chào Nghĩa, cảm ơn Nghĩa đã nhận lời mời phỏng vấn ngày hôm nay. Nghĩa có thể giới thiệu qua một tí về bản thân cũng như về Proxyman với các độc giả được không?
Mình là Nghĩa Trần. Hiện tại mình đang là macOS Developer ở Toggl.com
Cơ bản thì ý tưởng về Proxyman chỉ đơn giản là giải quyết cái ức chế của mình khi xài Charles Proxy mà mình “bị”, “phải” xài hằng ngày lúc mình còn ở Zalora Vietnam.
Nếu bạn đã từng xài Charles Proxy, Wireshark hay Fiddler để bắt được HTTP/HTTPS traffic từ mac hoặc iPhone để debug dễ dàng thì bạn sẽ biết Proxyman là gì ;]
Còn nếu chưa, thì Proxyman là một HTTP Debugging Proxy app, dùng dễ capture / intercept / manipulate HTTP / HTTPS requests / response từ macOS, iPhone, Android và cả Simulator.
Một vài selling-point của Proxyman là:
Native macOS app
Dễ xài, không cần Google để setup certificates.
Đầy đủ features như Charles Proxy (Hopefully)
Và phải nhanh (ai cũng muốn nhanh nên app phải nhanh ;]
Bạn build Proxyman lâu chưa? Trước Proxyman thì bạn có product nào khác nữa không? Bạn làm team hay một mình?
Proxyman là pet product mà mình theo đuổi lâu nhất : D hơn 1 năm và vẫn chưa có ý định chán =)) (Hy vọng là thế)
Version Prototype đầu tiên của Proxyman được ra mắt vào ngày Aug 3, 2018, và bản Stable gần nhất là Proxyman 1.7.2 Oct 24, 209. Tổng cộng có tất cả 46 releases.
Ngày launch app bất ngờ trên Product Hunt là hôm March 31st, 2019. Do một bạn nào đó tự post và tag mình vào 😀 nên phải cuốn theo chiều gió và coi như làm hôm launch chính thức, dù mình vẫn định delay thêm vài tháng cho để có thêm thời gian fix thêm một mớ bugs.
Launch trên Setapp ngày Jun 1st, 2019 và cũng là ngày launch cái licensing system.
Trước Proxyman thì mình chỉ build vài product chơi, chủ yếu là học code macOS. Ví dụ
Cả 2 project hiện tại đã stop, vì Uber không còn ở VN và Artify cũng đã gần xong 😀
Proxyman thì mình là người build từ những ngày đầu tiên. Hiện tại thì có bạn gái mình tham gia viết blog và đảm nhiệm phần users acquisition, Huy – TablePlus là co-founder sau này giúp mình có thêm business insight về users và SaaS product.
Về pricing model thì bạn dựa vào đâu để định mức giá? Và việc distribute nó trên Setapp có khiến bác thay đổi gì về pricing không?
Về Pricing thì mình tham khảo đối thủ chính của Proxyman là
Một số apps (Sketch, NSSurge, TablePlus, Postico) có customer chủ yếu là individual / SMEs.
Giá License thường tầm $49 / năm nên mình chọn mức này. Fun fact là với giá $49 này, mình cũng bị một vài users complain về việc quá mắc, mà feature lại chưa đầy đủ :)) nhưng kệ, cứ ra feature và giữ standard cao.
Ngoài ra vẫn có kha khá users (developers) có 2 máy, và việc mua 2 license ($90) thì không khả thi, nên mình offer thêm Combo với mức giá $59. Team license (>= 3) thì $39.
Ngoài ra, vẫn có những đối thủ cộm cán như Fiddler, Wiresharke, Debookee …. tuy nhiên customers chủ yếu là enterprise.
Việc distribute lên Setapp không ảnh hưởng gì tới mức license hiện tại cả. Vì 80% users của mình không xài Setapp. User vẫn thích mua license và được support trực tiếp từ mình khi có bug hay feature request. Mục đích của việc distribute lên Setapp là giúp tăng độ trust của Proxyman.
Bạn có run ads hay gì để marketing cho nó không? Hay để… hữu xạ tự nhiên hương?
Hiện tại mình không run ads. Tất cả chi phí dành cho ads hay marketing hiện là 0. Tất cả điều nhờ “word of mouth”.
Approach này có thể sẽ chậm lúc ban đầu, nhưng khá hiệu quả để build trust của users. Vì thường mọi người sẽ thích xài app khi bạn bè mình giới thiệu hơn là xài một cái app thấy trên Ads. Cách này cũng rất dễ convert một user thành loyaty user (purchased license, cuồng app, tweet Proxyman và khoe với mọi người). Họ đã trờ thành local influencers, và Proxyman cũng từ từ được biết tới.
Ngoài ra mình cũng chú trọng tới viết blogs và trả lời nhiều câu hỏi liên quan tới SSL Proxying, debugging trên StackOverflow, … và có link lại Proxyman.
Ngoài ra, 1 chiến thuật khác để acquire users là quick responsiveness. Mình sẽ support trong vòng 1-2 tiếng. Nếu user report 1 bug trên Github, Twitter, Gitter, thì mình sẽ fix và gửi bản hotfix cho user ngay lập tức. Cách này rất hiệu quả ở giai đoạn đầu của product, vì chứng tỏ product mình rất active, có hot-fix build thì user nó có thể tiếp tục job của nó mà không cần phải đợi qua tuần cho bản Stable release.
Kết quả là có rất nhiều users appreciated, và họ rất thích được chat với founder của products. Chắc vì họ cũng painful khi Charles Proxy (product họ đang xài) không có 1 kênh chính thức nào để support họ. Và cũng kha khá user mua license để cảm ơn sau khi mình support họ 😄
Tất cả những điều trên điều giúp mình acquire nhiều users hơn và cũng là go-to-market strategies của Proxyman hiện tại.
Về tình hình revenue thì hiện tại như nào, nếu tiện thì Nghĩa có thể chia sẻ một tí được không?
Revenue hiện tại tầm “chưa đến $5K MRR” từ License + Setapp. Cũng không nhiều so với những app SaaS khác, nhưng cũng đủ cho thời điểm hiện tại.
Plan của Proxyman là long term nên mình vẫn tin là Proxyman sẽ bump lên được vài năm tới. Thực tế là, Charles Proxy cũng mất 15 năm mới lên được vị trí như bây giờ, và Charles Proxy team chỉ có 1 người 😀
Khi build sản phẩm này thì bạn có từng cân nhắc giữa chuyện có nên open source nó for free và kiếm tiền từ nó không?
Kha khá users email hỏi về việc mình Open Source, tuy nhiên mình không cân nhắc approach này. trong thời điểm hiện tại (Cả founder của Insomnia cũng khuyên mình OSS).
Thật ra mục đích đầu tiên ở Proxyman là thử sức với những technical challenges mới. Mình có vài năm code iOS, cơ bản công việc vẫn chỉ là app listing, social apps, mọi thứ đã có sẵn và điều này khiến mình cảm thấy rất boring.
Charles Proxy không có alternative nào và có rất nhiều người đang tìm alternative, nhưng bất lực, nên mình nghĩ có thể đây là cơ hội để mình disrupt, kiểu Trello vs Jira 😀
Mình cũng cân nhắc chuyện bán license. Vì đó là cách để thuyết phục users là Author của Proxyman là nghiêm túc trong việc làm product.
OSS sợ mọi người thấy code dỏm, user bỏ đi 😄
Nói về technical challenges, Nghĩa có thể chia sẻ thêm về những challenge bạn đã gặp phải trong quá trình làm Proxyman được không?
Một vài challenges trong Proxyman là:
Build 1 app macOS native, developer tool.
Làm sao để buit được Intuitive UI? Không cần train vẫn mà naive users vẫn có thể xem được HTTPS Response? In fact, những ngày đầu mình xài Charles Proxy và Wireshark, thì gần như user phải biết mình phải làm gì, 90% (cả mình) cũng phải google cách sử dụng. Xài app mà cũng phải google cách xài LOL.
Làm sao build được 1 cái Proxy server? Làm sao parse được Raw HTTP Message?
Làm sao biết được request đó đi ra từ client nào?
Làm sao xem được HTTP Response? Cả HTTPS?
Làm sao trở thành MitM app, và không bị client reject the certificates?
Làm sao generate chain certificate on the fly?
Làm sao xem được requests từ iPhone, iOS Simulator và Android?
SSL Handshake?
Làm sao implement được “Privileged Helper Tool” để override system HTTP/HTTPS Proxy trên macOS?
Và rất rất nhiều thứ mình không có cơ hội làm nếu là iOS dev 😀
Tóm lại, code developer tool nó nhều challenges và hẳn là fun hơn 😀
Khi quyết định hướng kiếm tiền từ nó, bạn có từng phải cân nhắc giữa chuyện “bao nhiêu là đủ” cho việc xài free và bản trả phí không? Bạn có nghĩ tới chuyện sẽ bị user nó abuse cái free trial không?
Mình cũng cân nhắc rất nhiều về Business Model cho Proxyman: Premium, Freemium hay Trial.
Cuối cùng thì mình chọn Freemium. Cơ bản tất cả features (basic và advanced features) điều free và xài thoải mái để hoàn thành công việc hơn là phải mua license trước.
Bản Paid Proxyman chỉ unlock một vài cái cơ bản như Multiple-Tabs, số pin item, số rule trong Local Map, Breakpoint, …
Mục đích là để users cho dù xài bản free, vẫn có thể hoàn thành công việc của họ mà không có bất kỳ cản trở nào. Khi họ enjoy, làm được việc, thì họ sẽ thích app và mua license. Hạn chế việc làm user cảm thấy ức chế khi xài.
Một vài ví dụ, Charles Proxy bản free sẽ tự kill cái session trong 30p, nghĩa là sau 30p, sẽ mất hết 😀 rất ức chế.
Kha khá users mua app ngày từ đầu, vì họ vui mừng tìm được 1 app thay thế Charles Proxy mà họ đã xài một cách “chịu đựng” vài năm.
Với kinh nghiệm từ Proxyman, thì bạn đánh giá tỉ lệ giữa free user và paid user là như nào? và conversion rate ở đây như nào? Thị trường nào có tỉ lệ paid user cao nhất? Và so với thị trường VN thì sao?
Convert rate của Proxyman hiện tại là 1-2%. US và EU là 2 thị trường có user mua nhiều nhất. VN và ASIA nói chung chỉ có free users, không có paid users hiện tại.
Proxyman có khoảng 4k monthly users và khoảng 250-350 daily user. Returned user là ~80% users. US + EU chiếm khoảng 95%, còn lại China và một chút Southern-ASIA.
Có vài điểm mình để ý là Nghĩa có đề cập đến trong quá trình build và marketing cho Proxyman, nghe có vẻ khá thú vị và mình muốn đào sâu vào khía cạnh này một tí như việc làm thế nào để build được intuitive UI, hay như việc tập trung quảng bá bằng cách educate người dùng thông qua blog, hay trả lời câu hỏi trên StackOverflow. Nghĩa có thể chia sẻ về con đường mà bạn đã trải qua để có được những kinh nghiệm này được không?
Để trả lời được câu hỏi làm sao build được intuitive UI thì rất khó trả lời, vì nó không có câu trả lời cuối cùng nào cả:
Mình chỉ xài nhiều modern native app như TablePlus, Dropbox, Paw, Sublime, … và hiểu được cái Common-sense của những app native đó. Nó cũng giống như việc để design một app iOS thì cách đơn giản nhất là download nhiều features iOS app trên AppStore và xài hằng ngày. Về lâu dài gì mình sẽ hiệu được kha khá common-sense và biết được trend hiện tại.
Những feature nào users xài nhiều nhất thì mình để ra toolbar, còn lại sẽ được hide trong Context Menu. Để users không bị choáng nếu app mình có quá nhiều buttons. Lấy ví dụ một số app theo style Windows như Pycharm, Wireshare,… sẽ có rất nhiều feature và buttons trên toolbars.
UI Đơn giản là quan trọng nhất.
Và may mắn???
Bởi vì plan của Proxyman là không dùng Ads nên cách duy nhất để reachout tới users là thông qua nhưng channels như Blog, StackOverFlow, Reddit, … Trả lời giúp mấy bạn đang bí trên StackOverflow và offer họ 1 solution tốt hơn là cách mình đang áp dụng.
Có một vấn đề mà mình và nhiều người khác cũng hay gặp phải, đó là việc giữ cho bản thân mình tập trung và có thêm động lực trong quá trình build ý tưởng của mình thành một sản phẩm hoàn chỉnh, nhất là khi gặp phải những trở ngại trong quá trình build, nó khiến chúng ta rất dễ nản chí và thậm chí là bỏ cuộc. Nghĩa nghĩ sao về điều này? Chắc bạn cũng đã từng gặp vấn đề này trong quá trình làm Proxyman?
Việc này là điều hiển nhiên nếu bạn build SaaS product và việc duy nhất có thể làm được là chấp nhận nó tiếp tục làm.
Ko có silver-bullet cho việc này. Tất cả chỉ là từ phía bạn và chỉ là bạn có muốn tiếp tục hay ko?
Mình nhớ có tới 3 giai đoạn mình cũng rơi vào thế bí toàn cục khi làm Proxyman. Ví dụ
Làm sao build được native Proxyman Core (MitM) và có thể xem được HTTPS Request/Response?
Làm sao làm được Local Map hay Breakpoint feature? Mà có thể can thiệp và chỉnh được Message on-the-fly?
Làm sao design được UI vừa đẹp mà cũng vừa dễ xài?
Để trả lời được mấy câu hỏi trên thì mình cũng phải làm 3-4 prototype versions cho từng vấn đề. Google đủ kiểu, đọc OSS, và code prototype. Bí quá thì tìm cách khác hoặc đi hỏi bạn bè.
Ngoài ra mình còn 1 lời khuyên là nên build MVP version cho từng feature. Đừng bao giờ expect là mình có thể làm 100% feature rồi mới release vì sẽ rất lâu, và cũng không có cái gọi là 100% hoàn hảo.
MVP version, log lại hành trình của mình lên Twitter, và làm hài lòng một nhóm nhỏ user trước khi tiếp tục code tiếp v2 là cách dễ dàng nhất để có thêm động lực làm tiếp. Vì user họ khoái, họ support mình : D
UI hiện tại mình là version 4. Tạm coi là được nhưng mình đang improve v5 cho phần Filter bar.
Proxyman core của mình cũng là 3 version, hiện tại khá stable.
Có rất nhiều bạn độc giả cũng gửi mail và message cho mình rằng họ rất quan tâm đến việc tự phát triển và phát hành sản phẩm, như những gì mà Nghĩa đã làm với Proxyman. Là một người đi trước và cũng nếm trải đủ nhiều, Nghĩa có lời khuyên gì cho các bạn không?
Mình cũng không chắc là lời khuyên của mình có hợp với mọi người hay ko. Nhưng đây là những gì mình đã và đang làm:
Nếu mục tiêu của product là học hỏi, thử nghiệm framework, language mới thì bạn có thề start từ ngay bây giờ. Open Source, và nếu được bạn có thể viết blog kể về journey của bạn. Hướng đi này rất hay vì bạn có thể build được reputation cho chính bạn, vừa có cả quality product để apply job sau này.
Nếu muốn build một product nghiêm túc thì theo mình tìm cái pain point và validate cái idea này ở global market ngày từ những ngày đầu tiên.
Có rất nhiều cách reach tới global market là bạn publish app lên Product Hunt, Reddit, Hackernews, Markerlog hoặc một kênh distributions nào đó như Setapp.
Twitter + Github làm channel chính mà make connection với những authors khác. Ví dụ Insomnia, NativeConnect, Chime, …
Rất cảm ơn Nghĩa đã dành thời gian tham gia cuộc phỏng vấn này. Chúc Nghĩa sẽ ngày càng thành công hơn nữa với Proxyman cũng như với các sản phẩm của bạn trong tương lai nhé 😀
Hôm nay mình sẽ chia sẻ đến các bạn về cách thực hiện Todo Web App đơn giản với ASP.NET MVC và Entity Framework. Mình không chuyên .NET hay web, nhưng mình có học qua rồi nên viết cho vui để sau này biết đâu cần lại quên.
Todo của mình sẽ có các thông tin như Name, Content, DateAdded, IsDone và UserId. UserId để xác định todo đó của user nào. App sẽ có các thao tác cơ bản như xem toàn bộ todo, xem chi tiết 1 todo, thêm, sửa, xóa todo.
Mình sẽ tạo một project ASP.NET MVC, .NET Framework hiện tại là 4.7.2, chọn Authentication là Individual User Accounts.
Sau khi tạo project xong, các model và controller quản lý việc đăng nhập đã được tạo sẵn, mình sẽ không mất công tạo lại nữa, mình cũng chỉ cần đăng nhập thôi nên không cần thêm sửa gì.
Các trang như About, Privacy mình không dùng đến nên xóa nó đi (nhớ xóa cả action của nó trong HomeController.cs), xóa luôn các link trên thanh nabbar trong ~/Views/Shared/_Layout.cshtml.
Enable migraitons
Mình sẽ sử dụng Code-First workflow để tạo database, đỡ phải viết query dài dòng. Do lúc tạo project, mình đã chọn Authentication rồi nên nó sẽ tự tạo cho mình các cái table cần thiết để quản lý user. Vậy nên, mình sẽ enable migrations rồi add migration authentication trước.
Lúc này khi người dùng vào trang mà chưa đăng nhập thì sẽ bị chuyển hướng đến trang đăng nhập.
Add Todo Model
Tiếp theo mình sẽ tạo Todo model với các thông tin mình đã nêu. Do Id của user là string(128) nên mình sẽ để thuộc tính UserId của Todo là string luôn.
namespaceTodoWebApp.Models{[Table("TodoTable")]publicclassTodo{publicint Id {get;set;}[Required][MaxLength(256)]publicstring Name {get;set;}[Required][MaxLength(1024)]publicstring Content {get;set;}[Required][Display(Name ="Have you done it?")]publicbool IsDone {get;set;}=false;[Required]publicDateTime DateAdded {get;set;}= DateTime.Now;[Required][MaxLength(128)]publicstring UserId {get;set;}}}
Sau khi đã có model rồi thì mình tiến hành thêm nó vào ApplicationDBContext. Mở file IdentityModels.cs và thêm vào thuộc tính todo:
publicclassApplicationDbContext:IdentityDbContext<ApplicationUser>{publicDbSet<Todo> Todo {get;set;}// Add this line// Code goes here...}
Sau đó tiếp tục add migration:
Add-Migration AddTodoModel
Sau khi add migraiton, mình sẽ chỉnh sửa lại một chút. Trong khi create table, mình sẽ để mặc định cho IsDone là false và DateAdded là lấy ngày tháng hiện tại, mình sẽ sửa lại như sau:
Tiếp theo, trong action Index, mình cần lấy ra toàn bộ todo của user đã login, mình sẽ lấy UserId sau đó tìm todo có UserId đó trong database và return về View kèm theo ViewModel là một todo list:
Sau đó, trong Index.cshtml, mình cho Model của nó là một IQueryable<Todo> (tương tự như list vậy) sau đó foreach và đổ data ra table, sử dụng bootstrap.
@model IQueryable<TodoWebApp.Models.Todo>
@{
ViewBag.Title = "Home Page";
}
<h1 class="page-header">All Your Todo</h1><div><table class="table table-bordered table-hover"><thead><tr><th>Name</th><th>Done</th><th>Edit</th><th>Delete</th></tr></thead><tbody>
@foreach (var todo in Model)
{
<tr><td>@todo.Name</td><td>
@if (todo.IsDone)
{
<p>Done</p>
}
</td><td>Edit</td> // các action này sẽ được thay thế sau
<td>Delete</td> // các action này sẽ được thay thế sau
</tr>
}
</tbody></table></div>
Do mình chưa có data nên nó sẽ không có gì cả. Các bạn có thể test bằng cách bỏ Where() sau _context.Todo đi sau đó thêm data thủ công vào database và refresh lại trang.
View Detail
Tiếp tục, tạo action Detail và view Detail để xem thông tin chi tiết của todo. Trong action Detail sẽ nhận vào một id của todo, trong action này sẽ lấy thêm UserId để lấy được chính xác todo của user cần xem và trả về view cho người dùng.
publicActionResultDetail(int id){var uid = User.Identity.GetUserId();var todo = _context.Todo.SingleOrDefault(t => t.Id == id && t.UserId == uid);if(todo ==null)thrownewHttpException(404,"Not found");returnView(todo);}
Phần view thì đơn giản mình sẽ cho hiển thị thêm thông tin:
@model TodoWebApp.Models.Todo
@{
ViewBag.Title = "Detail";
}
<div class="jumbotron"><h1>@Model.Name</h1><p>@Model.Content</p><p>Added on @Model.DateAdded.ToLongDateString()</p>
@if (Model.IsDone)
{
<p>You have done this task!</p>
}
</div>
Sau đó để xem thông tin, mình sẽ cho một đường dẫn đến action Detail kèm theo id của todo. Mình sẽ sửa lại Index.cshtml:
// Thay
<td>@todo.Name</td>
// Thành
<td>@Html.ActionLink(@todo.Name, "Detail", new { id = todo.Id })</td>
Add Todo
Để add todo, mình cần 2 action, 1 là để điều hướng người dùng đến form, 2 là để thực hiện add todo vào trong database:
Và form edit thì cũng tương tự, mình chỉ sửa action của BeginForm() thành “Edit” thôi. Tiếp theo mình cần dẫn người dùng từ index đến chỉnh sửa todo và truyền kèm id của todo.
// Thay
<td>Edit</td>
// Thành
<td>@Html.ActionLink("Edit", "Edit", new { @id = todo.Id })</td>
Delete Todo
Phần Delete cũng khá đơn giản, mình chỉ cần truyền Id của todo được nhấn vào action và tìm xem có không, có thì delete đi.
publicActionResultDelete(int id){var uid = User.Identity.GetUserId();var todo = _context.Todo.SingleOrDefault(t => t.Id == id && t.UserId == uid);if(todo ==null)thrownewHttpException(404,"Not found");
_context.Todo.Remove(todo);
_context.SaveChanges();returnRedirectToAction("Index");}
Và sửa Index như sau:
// Thay
<td>Delete</td>
// Thành
<td>@Html.ActionLink("Delete", "Delete", new { @id = todo.Id })</td>
Tổng kết
Như vậy là mình đã có thể tạo được một App Todo đơn giản rồi. Mình chỉ làm project nhỏ này cho vui thôi, chưa tối ưu, chưa sử dụng các kỹ thuật dùng ajax để gọi API, client-side render… Các bạn có thể tự tạo API rồi dùng ajax gọi nó để giảm tải cho server và nó cũng có thể dễ dàng upscale.
Hi vọng là các bạn thích bài viết của mình. Nếu các bạn thấy bài viết có ích, đừng quên chia sẻ cho bạn bè cùng biết nha. Cảm ơn các bạn.
Bài viết được sự cho phép của tác giả Kien Dang Chung
Trong phần trước chúng ta đã cài đặt và cấu hình PHPUnit cho một dự án, chúng ta cũng đã tìm hiểu vài quy ước mà PHPUnit yêu cầu, sau đó tạo ra một ví dụ kiểm thử đầu tiên đơn giản và không hữu dụng lắm. Tuy nhiên, có một phương thức assertTrue() được sử dụng trong ví dụ này mà chúng ta chưa hiểu nó làm gì?
In computer programming, an assertion is a statement that a predicate (Boolean-valued function, a true–false expression) is expected to always be true at that point in the code. If an assertion evaluates to false at run time, an assertion failure results, which typically causes the program to crash, or to throw an assertion exception. Nguồn Wiki
Assertion là một câu lệnh khẳng định cho kết quả true – false, nó được đặt trong chương trình để chỉ cho lập trình viên thấy rằng xác nhận này luôn đúng ở vị trí đặt câu lệnh, hay nói một cách khác assertion kiểm tra một câu lệnh là đúng. Trong ví dụ trước:
Chúng ta xác nhận rằng giá trị foosẽlàtrue,nếufoosẽlàtrue,nếufoo là false thì kiểm thử cho kết quả là không đạt. PHPUnit có khoảng 90 phương thức assertion, chúng ta không cần phải nhớ tất cả, các assertion có mở đầu là assert: $this->assert*. Một số các assertion hay dùng assertArrayHasKey(), assertEquals(), assertFalse, assertSame() và assertTrue(). Các phương thức assertion chỉ là các phương thức thông thường, nó trả về true hoặc false tùy thuộc vào kết quả các đoạn code mà bạn truyền vào. Nếu bạn không tìm thấy assertion nào phù hợp, bạn có thể tạo ra một assertion. Không có gì quá phức tạp, nó chỉ đơn giản là tạo ra một phương thức trong class kiểm thử. Chúng ta sẽ quay lại vấn đề này trong các bài sau. ## 2. Ví dụ kiểm thử thứ hai
Chúng ta sẽ thực hiện một ví dụ kiểm thử thứ hai hữu ích hơn trong thực tế. Trong tối ưu bộ máy tìm kiếm (SEO) như Google, Bing… các đường dẫn trang web nên sử dụng dấu gạch ngang để phân cách các từ, do vậy cần có một phương thức chuyển từ dòng tiêu đề bài viết sang thành nội dung đường dẫn bằng cách bỏ dấu đi và phân cách bằng dấu gạch ngang. Ví dụ bài viết “Unit Testing với PHPUnit” sẽ được chuyển thành “unit-testing-voi-phpunit”. Chúng ta cùng tạo ra một Class URL trong app để xử lý các vấn đề về URL:
Sau khi tạo ra được phương thức sluggify() chúng ta muốn kiểm thử xem phương thức này hoạt động có đúng như mong muốn hay không? Có thể có những lỗi tiềm ẩn không lường trước được. Để kiểm thử phương thức chúng ta sẽ tạo ra một file test ./test/URLTest.php với nội dung như sau:
Admin@ADMIN-PC c:\xampp\htdocs\phpunit
$ vendor\bin\phpunit
PHPUnit 5.7.21 by Sebastian Bergmann and contributors..W 2/2(100%)
Time:60 ms, Memory:2.50MB
There was 1 warning:1) Warning
No tests found in class"app\Test\URLTest".WARNINGS!
Tests:2, Assertions:1, Warnings:1.
Như vậy là đã có hai kiểm thử đã được thực hiện, trong đó có 1 xác nhận là kiểm thử thành công và 1 cảnh báo. Nguyên nhân cảnh báo là do PHPUnit không tìm thấy phương thức test nào trong file test\URLTest.php. Tiếp theo chúng ta sẽ đưa vào phương thức test cho URL::sluggify() để xác nhận rằng phương thức này sẽ trả về một kết quả như mong muốn.
<?phpnamespaceTest;classURLTestextends\PHPUnit_Framework_TestCase{publicfunctiontestSluggifyReturnsSluggifiedString(){ // Kiểm tra phương thức sluggify có trả về một chuỗi không dấu và phân cách bằng dấu gạch ngang
}}
Khi chạy lại PHPUnit chúng ta đã thấy không còn cảnh báo. Tuy nhiên trong phương thức kiểm thử chúng ta chưa thực hiện gì, tiếp theo sửa đổi nội dung phương thức testSluggifyReturnsSluggifiedString():
<?phpnamespaceTest;useapp\URL;classURLTestextends\PHPUnit_Framework_TestCase{publicfunctiontestSluggifyReturnsSluggifiedString(){$originalString='Đây là chuỗi cần được xử lý dấu và gạch ngang';$expectedResult='day-la-chuoi-can-duoc-xu-ly-dau-va-gach-ngang';$url=newURL();$result=$url->sluggify($originalString);$this->assertEquals($expectedResult,$result);}}
Phương thức testSluggifyReturnsSluggifiedString() sẽ kiểm tra một chuỗi “Đây là chuỗi cần được xử lý dấu và gạch ngang” xem sau khi qua phương thức URL::sluggify() có ra kết quả như mong đợi là “day-la-chuoi-can-duoc-xu-ly-dau-va-gach-ngang” hay không? Chúng ta chạy PHPUnit:
Admin@ADMIN-PC c:\xampp\htdocs\phpunit
$ vendor\bin\phpunit
PHPUnit 5.7.21 by Sebastian Bergmann and contributors...2/2(100%)
Time:63 ms, Memory:2.25MBOK(2 tests,2 assertions)
Như vậy cả hai kiểm thử (ví dụ 1 và ví dụ 2) đều thành công với 2 xác nhận. Trường hợp test ở trên chúng ta mới chỉ kiểm tra các chuỗi chứa ký tự thông thường, trong một kịch bản test đầy đủ, chúng ta có thể test cả các trường hợp khác như chuỗi chứa các ký tự số, ký tự đặc biệt… Điều chỉnh lại code của file test URLTest.php như sau:
<?phpnamespaceTest;useApp\URL;classURLTestextends\PHPUnit_Framework_TestCase{publicfunctiontestSluggifyReturnsSluggifiedString(){ // Phương thức này kiểm thử với một chuỗi thông thường
$originalString='Đây là chuỗi cần được xử lý dấu và gạch ngang';$expectedResult='day-la-chuoi-can-duoc-xu-ly-dau-va-gach-ngang';$url=newURL();$result=$url->sluggify($originalString);$this->assertEquals($expectedResult,$result);}publicfunctiontestSluggifyReturnsExpectedForStringsContainingNumbers(){ // Phương thức này kiểm thử với một chuỗi có chữ số
$originalString='Unit testing phần2 PHPUnit có 100phương thức xác nhận';$expectedResult='unit-testing-phan2-phpunit-co-100phuong-thuc-xac-nhan';$url=newURL();$result=$url->sluggify($originalString);$this->assertEquals($expectedResult,$result);}publicfunctiontestSluggifyReturnsExpectedForStringsContainingSpecialCharacters(){ // Phương thức này kiểm thử với một chuỗi có ký tự đặc biệt
$originalString='Unit testing - Phần 2: Assertion() và dataProvider';$expectedResult='unit-testing-phan-2-assertion-va-dataprovider';$url=newURL();$result=$url->sluggify($originalString);$this->assertEquals($expectedResult,$result);}publicfunctiontestSluggifyReturnsExpectedForEmptyStrings(){ // Kiểm thử với chuỗi đầu vào là rỗng
$originalString='';$expectedResult='';$url=newURL();$result=$url->sluggify($originalString);$this->assertEquals($expectedResult,$result);}}
Trong nội dung file test tiếp theo này, chúng ta đã thêm vào các phương thức test mới: – testSluggifyReturnsExpectedForStringsContainingNumbers: để kiểm tra xem URL::sluggify() có hoạt động tốt với một chuỗi có chứa số.
testSluggifyReturnsExpectedForStringsContainingSpecialCharacters: kiểm tra xem URL::sluggify() có hoạt động tốt với ký tự đặc biệt không.
testSluggifyReturnsExpectedForEmptyStrings: kiểm tra xem URL::sluggify() hoạt động tốt chuỗi đầu vào rỗng không.
…
Thực hiện chạy test với PHPUnit:
Admin@ADMIN-PC c:\xampp\htdocs\phpunit
$ vendor\bin\phpunit
PHPUnit 5.7.21 by Sebastian Bergmann and contributors.......6/6(100%)
Time:71 ms, Memory:2.25MBOK(6 tests,6 assertions)
``
Như vậy chúng ta thấy có 6 trường hợp kiểm thử được thực hiện và kết quả đều là tốt. Tuy nhiên, chúng thấy có một vấn đề là có quá nhiều phương thức kiểm thử được viết ra, cảm giác như có cái gì đó được lặp đi lặp lại. Nếu như URL::sluggify() có hàng trăm trường hợp cần test mà viết như thế này thì thật là không ổn. PHPUnit cũng đã tính đến trường hợp này, với dataProvider, các phương thức kiểm thử sẽ được cô đọng lại.## 2. Phương thức cung cấp dữ liệu
Như ở trong ví dụ trên chúng ta thấy có rất nhiều các phương thức kiểm thử, PHPUnit đã đưa ra phương thức cung cấp dữ liệu (data provider) giúp cho các phương thức kiểm thử này có thể được viết lại rất ngắn gọn. Chúng ta sẽ cùng tìm hiểu các phương thức này, trước khi đi vào tìm hiểu data provider chúng ta tìm hiểu về annotation vì nó được sử dụng để các phương thức kiểm thử nhận biết được phương thức nào sẽ cung cấp dữ liệu cho nó. Annotation là các thẻ được sử dụng trong một khối chú thích giúp tăng thêm thông tin cho mã nguồn. Ngôn ngữ PHP không có core engine cho annotation, các classtrong PHPUnit sử dụng annotation để có thêm các thông tin, nó có thể dùng trong lúc chạy để thiết lập các hành vi. Một khối chú thích trong PHP được bắt đầu bằng /\*\* và kết thúc bằng \*/.
```{.language-php}/**
* @annotationName Annotation value
*/publicfunctiontestFoo(){ //
}
Chúng ta quay lại với phương thức cung cấp dữ liệu data provider, như đã nói ở trên có thể dùng nó để cung cấp dữ liệu kiểm thử cho một phương thức kiểm thử. Nó sử dụng annotation @dataProvider để nhận biết là nó thuộc về phương thức kiểm thử nào. Như vậy chúng ta không cần tạo ra nhiều các phương thức kiểm khác nhau, thay vào đó chúng ta chỉ cần tạo ra một phương thức với tham số là một data provider.
<?phpnamespaceTest;useApp\URL;classURLTestextends\PHPUnit_Framework_TestCase{/**
* @param string $originalString Chuỗi cần xử lý
* @param string $expectedResult Kết quả mong đợi
*
* @dataProvider providerTestSluggifyReturnsSluggifiedString
*/publicfunctiontestSluggifyReturnsSluggifiedString($originalString,$expectedResult){$url=newURL();$result=$url->sluggify($originalString);$this->assertEquals($expectedResult,$result);}publicfunctionproviderTestSluggifyReturnsSluggifiedString(){returnarray(array('Đây là chuỗi cần được xử lý dấu và gạch ngang','day-la-chuoi-can-duoc-xu-ly-dau-va-gach-ngang'),array('ĐÂY LÀ CHUỖI CẦN XỬ LÝ DẤU VÀ GẠCH NGANG','day-la-chuoi-can-duoc-xu-ly-dau-va-gach-ngang'),array('Unit testing phần2 PHPUnit có 100phương thức xác nhận','unit-testing-phan2-phpunit-co-100phuong-thuc-xac-nhan'),array('Unit testing - "Phần 2": Assertion() và dataProvider!','unit-testing-phan-2-assertion-va-dataprovider'),array('',''),);}}
Bạn thấy đấy, thay vì rất nhiều các phương thức kiểm thử, chúng ta đã có một phương thức kiểm thử duy nhất và một phương thức cung cấp dữ liệu để kiểm thử và được mapping thông qua annation @dataProvider. Kết quả khi thực hiện kiểm thử với PHPUnit:
Admin@ADMIN-PC c:\xampp\htdocs\phpunit
$ vendor\bin\phpunit
PHPUnit 5.7.21 by Sebastian Bergmann and contributors........7/7(100%)
Time:79 ms, Memory:2.50MBOK(7 tests,7 assertions)
Như vậy, thay thì phải viết 6 phương thức kiểm thử chúng ta sử dụng Data Provider giúp cho code được gọn gàng hơn. ## 3. Kết luận
Phần 2 đã kết thúc với những kiến thức giúp bạn có thể viết các chương trình kiểm thử ngắn gọn nhưng rất đầy đủ các trường hợp cần test. Chúng ta đã đi qua các vấn đề cơ bản nhất của Unit testing trong PHP, trong phần tiếp theo chúng ta sẽ đi sâu hơn vào cách kiểm thử các thành phần của một class với các phạm vi truy cập thành phần khác nhau, cuối cùng chúng ta sẽ cùng tìm hiểu cách thức sinh ra các báo cáo kiểm thử (test report) giúp công tác quản lý tốt hơn.
Click nút Capture Screenshots , nó chuyển sang xanh, để capture screenshot trong suốt quá trình trang được load
Bước 2: Giả lập mobile
Sử dụng web trên máy tính thì ít có vấn đề, vì tốc độ mạng ngày nay được cải thiện nhiều, nếu máy tính mà vẫn chậm thì bạn xem lại nhé, giả lập xem trải nghiệm trên mobile thế nào
Check vào ô Disable Cache để quá trình kiểm tra chính xác hơn
Từ dropdown menu đang có giá trị No throttling chọn xuống Regular 2G. DevTools sẽ giả lập tốc độ mạng xuống 2G
Bước 3: Đánh giá kết quả
Tìm xem đâu là nguyên nhân làm chậm page load bằng cách reload lại trang và xem xét kết quả.
Tìm các đoạn script block render
Khi trình duyệt gặp tag <script>, nó sau pause việc render, thực thi đoạn script ngay lập tức. 1. Tìm các đoạn script không thật sự cần chạy ngay lập tức, đánh dấu async hoặc defer Ấn tổ hợp Ctrl + R để load lại trang.
Để ý giá trị của DOMContentLoaded trong tab Summary, phía dưới tab Network. Bạn sẽ thấy 4 giây.
Click file main.js để xem, nó mở ra một tab mới show chi tiết hơn
Click vào tab Preview để xem source code. Đoạn script này đợi 4000ms, đánh dấu nó là async và chuyển xuống dưới <body>
Java là một một ngôn ngữ lập trình hiện đại, bậc cao, hướng đối tượng, bảo mật và mạnh mẽ. Java cũng được biết đến là platform hiệu quả để chạy các phần mềm. Với những tính năng ưu việt và nổi bật của mình, nhiều dev xem việc tìm hiểu Java cơ bản là cần thiết để nâng cao tay nghề và kỹ năng làm việc của mình.
5 bước để bắt đầu học Java cơ bản
1. Đừng chần chừ khi bắt đầu
Không chỉ riêng với việc bắt đầu học Java cơ bản mà với bất cứ ngôn ngữ lập trình nào, bất cứ lĩnh vực nào đi chăng nữa, bạn cũng nên bắt đầu ngay lập tức. Đừng chờ đợi vào ngày mai hay một lúc nào khác cả. Lúc tốt nhất để bắt đầu là ngay bây giờ.
Theo thống kê, có từ 80% – 90% sinh viên khi bắt đầu học lập trình luôn do dự và chần chừ. Khi bạn dừng lại cũng là lúc người khác bắt đầu, trì hoãn sẽ khiến bạn chậm bước hơn người khác mà thôi.
Java cơ bản là kiến thức giúp ích cho quá trình làm việc của các dev
2. Hãy tìm ra phương pháp học tập thích hợp nhất với bạn
Để học Java cơ bản hiệu quả bạn cần tìm ra phương pháp học cũng như thực hành phù hợp với mình. Nhất là với những bạn lần đầu làm quen với Java thì nên sớm tìm ra cách học hiệu quả để đảm bảo có thể hiểu được ngọn nguồn của Java cũng như cách áp dụng nó vào thực tiễn làm việc.
Bạn có thể tìm hiểu về ngôn ngữ lập trình Java trên sách vở hoặc các bài giảng của thầy cô nếu còn là sinh viên. Bên cạnh đó, nhiều dev hiện nay lựa chọn học Java online vì sự tiện lợi mà nó mang lại. Có hàng tá các trang web, kênh video phục vụ học lập trình online. Không mất thời gian đến lớp cũng như linh hoạt được thời gian, học trực tuyến trở thành giải pháp hợp lí cho những người bận rộn và muốn học thêm các kiến thức bên ngoài.
Nhưng quan trọng nhất vẫn là sự chủ động của người học. Để đạt được kết quả tốt nhất khi học Java cơ bản, bạn nên thường xuyên thực hành các bài tập và áp dụng những kiến thức mình đã được học vào công việc. Như thế, bạn sẽ không chỉ nhớ nhanh mà còn nhớ sâu được các kiến thức liên quan Java cơ bản. Từ đó dễ dàng trong việc học các ngôn ngữ lập trình nâng cao hơn.
Luyện tập chính là chìa khóa của việc tiếp thu và áp dụng kiến thức tốt, nhất là với ngành IT. Mỗi ngày có rất nhiều các data mới, kiến thức mới và những sự thay đổi trong lĩnh vực này mà bạn cần tiếp nhận. Mỗi ngày bạn nên dành ra ít nhất 30 – 45 phút để học thêm các kiến thức Java mới.
Trong khoảng thời gian đó, bạn có thể nghiên cứu thêm các thông tin liên quan đến Java từ Java cơ bản đến nâng cao. Nếu gặp phải những vấn đề khó khăn mà không thể tự giải thích được, bạn có thể tham khảo thêm ý kiến và lời khuyên từ các dev đi trước. Những kinh nghiệm thực tế mà họ đã trải qua chắc chắn sẽ giúp ích cho bạn rất nhiều đó.
Sự tập trung và kiên định giúp bạn học java hiệu quả hơn
4. Giữ sự thoải mái khi học tập
Sự gò bó và khó chịu khi học tập và làm việc sẽ khiến bạn cảm thấy mệt mỏi và không thể tiếp thu kiến thức hiệu quả được. Vậy nên hãy cố gắng giữ sự thoải mái và vui vẻ khi học Java cơ bản, bạn sẽ làm quen với các kiến thức lý thuyết và xử lý các bài tập tình huống tốt hơn.
5. Kiên định với quá trình học ngôn ngữ lập trình Java
Điều kiện tiên quyết để thành công khi học Java cơ bản, kể cả học Java online đó là bạn cần lên kế hoạch để đi đúng hướng và giữ sự tập trung trong việc học hành. Trước khi bắt đầu, bạn nên lên kế hoạch rõ ràng và sắp xếp thời gian biểu hợp lý để tránh việc xao nhãng hay phải dừng việc học lại để làm việc khác. Gián đoạn giữa chừng sẽ khiến bạn không nhớ kiến thức và mất tập trung khi làm việc.
Kết luận
Java được sử dụng trong các lĩnh vực khác nhau từ Desktop app như Acrobat Reader, Media Player, Antivirus,… Web app như irctc.co.in, javatpoint.com,… hay Enterprise app. Do đó việc học Java sẽ giúp bạn hoạt động tốt hơn trong lĩnh vực lập trình. Đó cũng sẽ là cơ hội để bạn tìm được công việc ở những công ty tốt và chuyên nghiệp như Gear Inc.
Lập trình viên sẽ viết CV Junior Developer như thế nảo? Có những điều gì thú vị xoay quanh CV IT? Ứng viên IT cần làm gì để CV của mình ăn điểm với nhà tuyển dụng. Cùng TopDev theo dõi bài viết sau đây để biết cách viết CV Junior Developer cực chuẩn.
Thông tin cá nhân của bạn
Hãy cung cấp các thông tin về:
Số điện thoại
Email
Kênh liên hệ cá nhân (nếu có)
Ngoài ra, bạn có thể dẫn một số link tài khoản networking cá nhân để gia tăng mức độ chuyên nghiệp như LinkedIn, Skype,… Một điều đặc biệt nữa là hãy chọn một bức hình thật phù hợp trong CV Junior Developer của mình.
Mục tiêu phát triển nghề nghiệp
Mục này, bạn cần chia sẻ nhựng mục tiêu phát triển rõ ràng, đúng trọng tâm, tránh lan man.
Ví dụ: Tôi apply với mục đích: Học tập, trải nghiệm với một mọi trường làm việc chuyên nghiệp hơn. Tôi muốn làm việc tại … với vị trí Junior Developer và mục tiêu ngắn hạn/dại hạn của tôi là… trở thành….
Đồng thời, viết CV giúp bạn định hình và có những trải nghiệm tốt hơn. Trường hợp bạn ứng tuyển các vị trí khác như freelancer it hay Senior Developer đều sẽ đạt hiệu quả ứng tuyển cao hơn.
Là một Junior, kinh nghiệm của bạn chưa nhiều. Nhưng nếu được hãy khéo léo đưa thêm một số mô tả về các điểm nổi trội của bạn.
+ Những trải nghiệm việc làm (Junior chưa cần đề cập số năm kinh nghiệm)
+ Chứng chỉ chuyên ngành mà bạn đã đạt được trong quá trình học tập
+ Các kỹ năng liên qua trực tiếp đến vị trí Junior Developer
Nền tảng chuyên môn (Kiến thức)
Trình bày trường học hoặc các khóa học bạn được trải nghiệm. Một mẹo là bạn hãy đề cập các khóa học chuyên môn có liên quan vị trí Junior. Có thể là ứng viên mới nên CV cho sinh viên IT mới ra trường của bạn chưa thật sự hoàn hảo.
Bên cạnh đó việc nắm bắt các cách viết CV, kỹ năng viết đơn xin nghỉ việc, đơn xin nghỉ phép, kỹ năng giao tiếp, cũng đều là khía cạnh cần được quan tâm.
Tuy nhiên, đặt trong trường hợp ứng tuyển nhiều vị trí khác nhau từ Junior, Senior Developer, Mobile App Developer thì CV IT ít nhất phải đảm bảo được những tiêu chuẩn nhất định.
Kinh nghiệm làm việc
Trình bày những trải nghiệm mà bạn có trên hành trình trở thành Junior Dveloper. Có thể là những dự án nhỏ, các chương trình tiếp cận khoa học chuyên nghiệp. Hoặc cũng có thể là thời gian bạn làm thực tập sinh (ghi cụ thể thời gian). Kinh nghiệm freelancer IT cũng được xem là một kinh nghiệm khá quan trọng cho CV lập trình của bạn.
Bạn ghi rõ nhiệm vụ nhưng cần đảm bảo không quá dài dòng. Thông qua từng trải nghiệm công việc, nhà tuyển dụng sẽ hiểu rõ hơn về sự định hướng sự nghiệp sắp tới của bạn.
Liệt kê các kỹ năng bạn có đồng thành thể hiện cột phản ánh mức độ tương ứng năng lực thật sự của bạn. Cùng TopDev checklist các kỹ năng cần có trong hành trình trở thành một IT Junior chính hiệu nhé. Quan trọng hơn, bạn cần phải lưu tâm về việc các kỹ năng phải thể hiện đúng năng lực mà bạn sở hữu.
+ Kỹ năng giao tiếp
+ Kỹ năng tư duy hệ thống/quản lý
+ Teamwork
+ Tin học văn phòng
+ Ngoại ngữ
Các chứng chỉ giải thưởng – hoạt động ngoại khóa/sở thích
Những nội dung này không bắt buộc có trong CV Junior Developer. Một phần vì độ nhận diện không quá phổ biến. Và hầu như các nhà tuyển dụng cũng ít quan tâm đến các phần nội dung này. Các ứng viên cho vị trí Junior Dveloper cần linh động trong việc lựa chọn các nội dung phù hợp trong CV của mình.
Các mẫu CV Junior Developer trên TopDev
Bạn có thể tham khảo nội dung để hoàn thiện CV IT của mình.
Bài viết được sự cho phép của tác giả Trần Anh Tuấn
Khi làm về UI, giải pháp nào cho khoảng cách đều nhau giữa các phần tử, cũng như là các phần tử luôn cao bằng nhau dù content thay đổi ?
Vấn đề 1: Để các cột cao bằng nhau thì trong Flexbox khi dùng display: flex thì giá trị mặc định flex-direction: row và align-items: stretch, giá trị stretch làm các phần tử con trực tiếp của thẻ cha dùng display: flex luôn cao bằng nhau. Lưu ý là theo flex-direction: row và flex-wrap: nowrap, nếu dùng wrap thì một phần tử rớt xuống tạo thành hàng mới và nó sẽ so sánh với các phần tử cùng hàng với nó mà thôi, dù nó cao thế nào thì cũng không ảnh hưởng tới chiều cao của các phần tử hàng khác.
Vấn đề 2: Khi chia layout với chỉ 3 phần tử như hình thì dùng justify-content: space-between sau đó xác định khoảng cách giữa mỗi phần tử, ở đây ta có 30px, chúng ta có 3 cột từ đó khoảng cách ở giữa sẽ là 30×2 = 60px sau đó chia cho 3 cột = 20px. Từ đó ta có thể CSS độ rộng của các phần tử là width: calc(33.333% - 20px) kết quả ra sẽ chính xác như Design (đã test) ở bài PSD phần 5.
Vấn đề 3: Cũng layout như trên nhưng chỉ có 5 phần tử, khi dùng space-between, có flex-wrap: wrap thì phần tử số 4 và 5 sẽ xuống hàng, tuy nhiên phần tử số 5 sẽ nằm về cuối làm xấu layout. Giải pháp là để giá trị justify-content về mặc định là flex-start, tuy nhiên các phần tử sẽ dính nhau.
Từ đây ta có giải pháp khác đó là chúng ta đã biết khoảng cách giữa các phần tử là 30px, suy ra mỗi bên của phần tử sẽ chiếm 15px khoảng trống, ta có thể dùng margin: 0 15px cho các phần tử đó, kết hợp với width: calc(33.333% - 30px), -30px vì khi dùng margin hai bên 15px nó đẩy ra. Nhưng phần tử đầu và cuối như số 1 và 3 sẽ bị bóp vào do margin-left cũng như margin-right, từ đây ta CSS cho class cha margin số âm là margin: 0 -15px để đẩy ra lại, cái này khá quen nếu các bạn dùng Bootstrap3 trong các class như col-md-x hay dùng cái này.
Trên đây là vài tips tricks của bản thân mình hi vọng sẽ giúp ích cho các bạn. Chúc các bạn học tập tốt, nâng cao trình độ.
Bài viết được sự cho phép của tác giả Kien Dang Chung
1. Kiểm thử ứng dụng là gì?
Kiểm thử phần mềm là một khâu quan trọng trong phát triển phần mềm, trước đây chúng ta thường xem nhẹ việc này vì mấy lý do: thích làm tùy tiện cho nhanh, thực hiện tốn kém hơn… Những sản phẩm được gọt dũa cẩn thận mang lại trải nghiệm tốt cho người dùng và cũng vì thế nó tồn tại lâu hơn, thành công hơn. Kiểm thử phần mềm được chia thành nhiều dạng khác nhau theo phạm vi và giai đoạn triển khai, chúng ta cùng xem một số dạng kiểm thử chính:
Unit testing: Kiểm thử ở mức đơn vị mã nguồn. Một đơn vị mã nguồn là thành phần nhỏ nhất trong mã nguồn mà chúng ta có thể kiểm tra. Như vậy, trong Unit testing chúng ta sẽ kiểm thử các lớp (class), phương thức (method)… Mục tiêu của unit testing là kiểm tra tính đúng đắn trong các xử lý của từng đơn vị mã nguồn.
Integration testing: Kiểm thử tích hợp các thành phần một ứng dụng, được thực hiện sau Unit test. Trong Integration testing chúng ta có thể kiểm tra cấu trúc ứng dụng, kiểm tra chức năng, hiệu năng sản phẩm cũng như khả năng chịu tải ứng dụng.
Ngoài ra còn rất nhiều các dạng kiểm thử khác như Acceptance testing, kiểm tra xem ứng dụng đã đạt được yêu cầu khách hàng chưa, security testing – kiểm tra tính bảo mật của ứng dụng…
Trong loạt bài viết này, chúng ta sẽ chỉ tập trung vào Unit testing khi thực hiện một dự án bằng ngôn ngữ PHP.
2. Unit testing với PHPUnit
PHPUnit là một gói thư viện mã nguồn mở sử dụng trong Unit testing với ngôn ngữ PHP rất tốt, nó cung cấp rất nhiều các class, phương thức giúp cho việc viết các đoạn mã kiểm thử trở nên nhanh chóng và thuận lợi. Chúng ta sẽ cùng nhau khám phá PHPUnit để thấy được sức mạnh của nó trong việc kiểm thử ứng dụng PHP.
2.1 Cài đặt PHPUnit
Đầu tiên, để sử dụng được PHPUnit chúng ta cần cài đặt nó vào dự án. Trong loạt bài viết này, chúng ta sẽ tạo ra một dự án tên phpunit nằm trong C:/xampp/htdocs (do tôi dùng XAMPP). PHPUnit được cài đặt thông qua composer:
Admin@ADMIN-PC c:\xampp\htdocs\phpunit
$ composer require phpunit/phpunit
Using version ^5.7for phpunit/phpunit
./composer.json has been updated
Loading composer repositories with package information
...
phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)
phpunit/phpunit suggests installing ext-xdebug (*)
Writing lock file
Generating autoload files
Cài đặt PHPUnit như vậy đã xong, chúng ta cùng xem cấu trúc thư mục dự án PHPUnit:
Các thư mục và file trong thư mục phpunit như sau:
app: Chứa code ứng dụng.
test: Chứa code cho kiểm thử ứng dụng.
vendor: được tạo ra bởi composer, chứa mã nguồn của gói thư viện PHPUnit.
composer.json: thiết lập các gói thư viện trong ứng dụng với composer.
phpunit.xml là file cấu hình cho PHPUnit.
Mặc định file phpunit.xml chưa có, bạn có thể tạo ra với nội dung như sau:
<?xml version="1.0" encoding="UTF-8"?><phpunit colors="true"><testsuites><testsuite name="Application Test Suite"><directory>./test/</directory></testsuite></testsuites></phpunit>
Giải thích qua một số thiết lập trong phpunit.xml:
colors=”true” thiết lập để PHPUnit hiển thị màu trong kết quả test.
./test/
Ứng tuyển ngay các vị trí PHP tuyển dụng mới nhất trên TopDev
2.2 Các quy ước trong PHPUnit
2.2.1 Cấu trúc thư mục và tên file
PHPUnit có một số quy ước để quá trình test thuận lợi. Quy ước đầu tiên là về cấu trúc file và tên file. Các file test cần được ánh xạ 1-1 với codebase và tên file được thêm chữ Test. Ví dụ:
Tên class là giống với tên file và phải mở rộng class PHPUnit_Framework_TestCase. Phương thức kiểm thử cần được đặt tên với bắt đầu bằng test, tên phương thức phải mô tả được hành động test. Ví dụ, nếu bạn test một phương thức verifyAccount(), bạn có thể đặt tên phương thức kiểm thử là testVerifyAccountMatchesPasswordGiven(). Các phương thức test phải là public, PHPUnit không thể chạy các test với các phương thức protected hoặc private. ## 3. Ví dụ kiểm thử đầu tiên
Chúng ta thực hiện ví dụ kiểm thử đầu tiên, trong ví dụ này việc test chỉ đơn giản là kiểm tra xem một biến có giá trị là true hay không? Tạo ra file FirstTest.php trong thư mục test với nội dung:
không có gì đặc biệt, chỉ đơn giản là tạo ra một Class mở rộng PHPUnit_Framework_TestCase. Tiếp theo chúng ta sẽ tạo ra một phương thức để kiểm tra xem biến $foo có giá trị true hay không? OK, giờ là lúc chạy PHPUnit từ màn hình dòng lệnh để thực hiện kiểm thử:
Admin@ADMIN-PC c:\xampp\htdocs\phpunit
$ vendor\bin\phpunit
PHPUnit 5.7.21 by Sebastian Bergmann and contributors..1/1(100%)
Time:53 ms, Memory:2.25MBOK(1 test,1 assertion)
PHPUnit đã thông báo là có 1 kiểm thử được thực hiện và kết quả là kiểm thử này có kết quả tốt. Ví dụ đầu tiên này có vẻ quá đơn giản, nhưng cũng nhờ đó chúng ta kiểm tra các thiết lập ban đầu cho PHPUnit và cũng là để chúng ta thấy việc kiểm thử không phải là một cái gì đó phức tạp.
4. Lời kết
Trong bài đầu tiên này, bạn đã hiểu sơ lược về Unit testing và cách sử dụng gói thư viện PHPUnit với ví dụ khá đơn giản. Việc kiểm thử ứng dụng là phải tìm ra nhiều các trường hợp thử nghiệm khác nhau để tránh bị bỏ sót lỗi, chính vì thế các đoạn mã kiểm thử cũng phải vét cạn được các trường hợp kiểm thử. Phần tiếp theo chúng ta sẽ đi sâu hơn về Assertsion và Anotation, những ý tưởng này giúp cho việc kiểm thử gọn gàng hơn.
Entity-relationship model (tạm dịch là mô hình thực thể – mối quan hệ hay mô hình quan hệ – thực thể, viết tắt là ER model) là mô hình biểu diễn mối quan hệ giữa các thực thể với nhau. Trong thực tế thì hầu như mọi thực thể đều có mối quan hệ với nhau.
Ví dụ như một người sở hữu một hoặc nhiều căn nhà, khi đó, người này và căn nhà là vật thể, quan hệ giữa người và nhà là quan hệ sở hữu và được sở hữu bởi.
Bằng việc sử dụng mô hình ER, chúng ta có thể dễ dàng đặc tả được mối quan hệ giữa các thực thể ngoài đời thực, từ đó thiết kế các cơ sở dữ liệu quan hệ phù hợp để lưu trữ trên máy tính. Bạn nào không biết cơ sở dữ liệu là gì có thể xem lại bài viết này của mình nha.
Các thành phần của mô hình ER
Như đã đề cặp ở trên, đương nhiên hai thành phần phải có là thực thể và mối quan hệ rồi. Ngoài ra còn có thuộc tính của thực thể.
Thực thể
Thực thể (Entity) đơn giản là các đối tượng, sự vật, đồ vật. Nhiều thực thể thì được gọi là một tập thực thể. Trong mô hình ER có thể có nhiều thực thể khác nhau, được ký hiệu bằng hình chữ nhật và tên thực thể bên trong (xem hình kế tiếp trong mục Thuộc tính, nhân viên là thực thể). Ví dụ thực thể (Nhà cửa, xe cộ, phòng ban, nhân viên, sinh viên…).
Ngoài ra còn có 1 loại là thực thể yếu. Thực thể yếu là thực thể thêm vào để bổ sung thông tin cho thực thể chính trong quan hệ và nó không quan trọng. Thông thường khi thiết kế ER model, bạn sẽ hiếm khi thấy thực thể yếu xuất hiện trong mô hình.
Thuộc tính
Thực thể sẽ có các thuộc tính liên quan đến nó. Ví dụ như con người thì sẽ có họ tên, ngày sinh, giới tính, địa chỉ, số CMND… Sinh viên thì có thêm MSSV, trường, lớp…
Thuộc tính trong mô hình ER được ký hiệu là hình bầu dục hoặc tròn cùng với tên thuộc tính bên trong. Thuộc tính thuộc thực thể nào thì sẽ được nối đến thực thể đó.
Thuộc tính dùng để phân biệt giữa các thực thể với nhau gọi là thuộc tính khóa. Thuộc tính khóa ký hiệu tương tự thuộc tính thường nhưng có thêm gạch chân dưới tên thuộc tính.
Thực thể và thuộc tính
Giá trị của thuộc tính có 2 loại là đơn trị và đa trị. Đơn trị là các thuộc tính như tên, ngày sinh, giới tính… Đa trị là các thuộc tính như certificates, studied school (có thể có nhiều hơn 1).
Kiểu dữ liệu của thuộc tính đơn trị có thể là string, float, integer, datetime… Các thuộc tính đa trị có thể coi như 1 danh sách các giá trị thuộc các kiểu vừa nêu. Ví dụ ngày sinh kiểu datetime, tên kiểu string, điểm trung bình kiểu float…
Mối quan hệ
Như cái tên của mô hình này, thành phần “mối quan hệ” này thể hiện quan hệ giữa các thực thể trong mô hình và cũng là thành phần cực kỳ quan trọng. Quan hệ này được ký hiệu bằng hình thoi, bên trong là tên mối quan hệ và nó sẽ nối đến các thực thể có quan hệ với nhau.
Mối quan hệ giữa các thực thể có các kiểu sau:
Quan hệ 1 – 1: ví dụ như chức trưởng phòng chỉ có thể thuộc về 1 người và cũng chỉ có 1 người có thể giữ chức trưởng phòng trong cùng 1 thời điểm.
Quan hệ 1 – n (hoặc n – 1): ví dụ như mỗi chiếc xe hơi được đứng tên bởi 1 người nhưng 1 người có thể có nhiều chiếc xe hơi.
Quan hệ n – n: ví dụ như trên đại học, mỗi sinh viên sẽ được tham gia vào các lớp thuộc các môn học khác nhau và mỗi lớp cũng có nhiều sinh viên khác nhau tham gia.
Mối quan hệ giữa thực thể còn được đánh bảng số để biểu thị số chiều của mối quan hệ. Bảng số có dạng sau (min, max), trong đó min là số lượng thực thể tối thiểu tham gia mối quan hệ và max là số thực thể tối đa trong mối quan hệ đó.
Ví dụ như mỗi phòng ban có thể có 1 hoặc nhiều nhân viên (ít nhất 1 và nhiều nhất n nhân viên), mỗi nhân viên thì chỉ có thể thuộc về 1 và chỉ 1 phòng ban (ít nhất 1 và nhiều nhất 1). Ta sẽ thể hiện như sau:
Mối quan hệ giữa thực thể Nhân viên và Phòng ban
Tất nhiên đó chỉ là một ví dụ nhỏ thôi, trong thực tế thì một diagram sẽ cực kỳ cực kỳ phức tạp và để tạo nên diagram đó cũng là điều không dễ dàng gì.
Ngoài ra, một thực thể có thể có mối quan hệ với chính nó, ví dụ mỗi nhân viên trong một phòng ban có thể chịu sự quản lý trực tiếp từ một nhân viên khác. Lúc này thì một nhân viên có thể là quản lý hoặc cũng có thể là người bị quản lý. Ta sẽ có như sau:
Trong diagram trên, nhân viên có thể không quản lý nhân viên nào (không phải quản lý) và cũng có thể quản lý nhiều nhân viên (là người quản lý). Và một nhân viên cũng có thể được quản lý bởi một nhân viên khác hoặc không bị quản lý (không có quản lý hoặc nhân viên đó là quản lý).
Bonus: mối quan hệ mở rộng – nó cũng là một mối quan hệ nhưng trong mối quan hệ đó có các thông tin (thuộc tính) bổ sung cho nó. Ví dụ như khi phân công đề án cho nhân viên, mối quan hệ ở đây là phân công và được phân công, thì trong đó có thể bổ sung thêm thông tin về số giờ làm việc / tuần được phân công trong đề án đó.
Quy tắc và cách xây dựng ER Model
Có một số quy tắc bạn cần nhớ khi xây dựng ER Model như sau:
Mỗi thành phần phải có ý nghĩa trong model
Xác định đúng thực thể
Có đầy đủ các thuộc tính của thực thể
Xác định đúng các mối quan hệ giữa thực thể
Model phải đơn giản nhưng đầy đủ thông tin và dễ đọc hiểu
Để xây dựng ER Model, ta thực hiện theo các bước sau:
Xác định tập thực thể
Xác định thuộc tính của thực thể
Xác định kiểu của các thuộc tính
Xác định thuộc tính khóa của các thực thể
Xác định mối quan hệ giữa thực thể
Vẽ ER Model
Chuẩn hóa model
Thực chiến
Từ đầu bài đến giờ toàn nói suôn, giờ thì mình sẽ có một ví dụ thực tế cho các bạn xem để dễ hiểu bài viết hơn. Bài của mình như sau:
Công ty gồm nhiều nhân viên, mỗi nhân viên được gán mã nhân viên để tiện việc quản lý, có họ tên, ngày sinh, mức lương được hưởng. Công ty gồm nhiều phòng ban, mỗi phòng ban có chức năng riêng của mình, có mã phòng, tên phòng, có một trưởng phòng. Mỗi nhân viên chỉ thuộc vào một phòng ban và một phòng có thể có nhiều nhân viên. Mỗi nhân viên trong phòng còn có thể chịu sự quản lý trực tiếp từ một nhân viên khác.
Do công ty thực hiện đề án, nên mỗi phòng có thể có nhiều văn phòng giao dịch hay làm việc khác nhau ở tại những địa điểm khác nhau. Mỗi một đề án khi được xây dựng, có mã đề án, tên đề án, địa điểm thực hiện đề án đó và do một phòng ban chịu trách nhiệm chủ trì đề án.
Quá trình thực hiện đề án có thể được chia nhỏ thành nhiều công việc và phân côn cho các nhân viên thực hiện, khi đó công ty sẽ ghi nhận lại thời gian phân công công việc cho nhân viên (tính bằng số giờ / tuần) để theo dõi tiến độ thực hiện. Nhằm có thể chăm lo đời sống của nhân viên, công ty có ghi nhận lại những thông tin về những thân nhân của nhân viên, bao gồm những người như cha mẹ, chồng vợ, và con cái.
Như vậy từ những thông tin đặc tả vấn đề trong đề bài, mình sẽ vẽ được Entity-relationship model sau:
Bên trên cũng là bài tập của mình nên có thể có sai sót, nếu có sai sót gì mọi người cứ comment bên dưới để mình sửa nha.
Lời kết
Bài viết đến đây khá là dài rồi, mình hi vọng là mọi người có thể hiểu được Entity-relationship model. Trong các bài viết sắp tới, mình sẽ trình bày cách chuyển sang mô hình dữ liệu quan hệ sau, mình sẽ sớm có chuỗi bài viết về mô hình dữ liệu quan hệ và SQL thôi, các bạn hãy nhấn đăng ký nhận thông báo nhé!
Nếu các bạn có bất kỳ thắc mắc hay góp ý nào đừng ngần ngại comment phía bên dưới bài viết để giúp mình phát triển bài viết tốt hơn nha. Đừng quên chia sẻ bài viết nếu mọi người thấy nó hay cũng như để ủng hộ tinh thần cho mình. Cảm ơn các bạn đã đọc bài viết!