Mock phương thức static trong Unit Test sử dụng PowerMock
Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh
Trong bài viết này, mình sẽ hướng dẫn các bạn Mock các phương thức static trong Unit Test các bạn nhé!
Nếu bạn nào chưa biết về Mock trong Unit Test thì mình có thể nói sơ qua như thế này: Mock là giải pháp giúp chúng ta tạo ra một đối tượng giả để chúng ta có thể chỉ định hành vi của một đối tượng nào đó trong Unit Test. Ví dụ như, bạn có một đối tượng kết nối tới SFTP server nhưng trong Unit Test bạn không thể thiết lập một SFTP server thực được, do đó không thể test hàm kết nối của đối tượng này tới SFTP server được. Trong trường hợp này, bạn có thể tạo một đối tượng Mock để giả lập hành vi của đối tượng kết nối tới SFTP server và chỉ định khi đối tượng khác gọi tới hàm kết nối SFTP server của đối tượng này thì đối tượng này sẽ trả về giá trị gì.
Tại sao chúng ta phải sử dụng PowerMock để Mock các phương thức static? Đơn giản là bởi vì chỉ có PowerMock mới hỗ trợ cho chúng ta làm điều này.
OK, bây giờ chúng ta đi vào chủ đề chính của bài viết này nhé các bạn!
Mình sẽ tạo một project Maven để làm ví dụ cho các bạn dễ hiểu. Project của mình như sau:
Bây giờ chúng ta sẽ thêm dependency cần thiết của JUnit và PowerMock vào project của chúng ta nhé các bạn! Các bạn hãy mở tập tin pom.xml và thêm những dependency sau:
Và class có chứa phương thức static mà chúng ta cần Mock sẽ có nội dung như sau:
package com.huongdanjava.mockstatic;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class SSHCommandLineHelper {
/**
* Execute command: "<strong>ssh <i>server</i> test -e <i>remoteFilePath</i> && echo 1 || echo 0</strong>" to check whether
* a file is existing or not in remote SSH server.
* <p />
* The pre-condition is: we can use SSH to login into other server without username and password.
*
* @param server
* SSH server.
* @param remoteFilePath
* Path of remote file on SSH server.
* @return True if executing success otherwise will false.
*/
public boolean checkFileExistingWithoutUsernamePassword(String server, String remoteFilePath) {
StringBuilder sb = new StringBuilder();
sb.append("ssh ");
sb.append(server);
sb.append(" test -e ");
sb.append(remoteFilePath);
sb.append(" && echo 1 || echo 0");
return executeCommandOnRemote(sb.toString());
}
/**
* Execute the command on remote SSH server.
*
* @param command
* The command.
* @return True if executing success otherwise will false.
*/
private boolean executeCommandOnRemote(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return "1".equals(output.toString().trim());
}
}
Mục đích của class này là sử dụng Java để thực thi một command line kiểm tra sự tồn tại của một tập tin ở một máy tính khác sử dụng SSH mà không cần phải sử dụng user và password để đăng nhập (để chạy một chương trình sử dụng class này, chúng ta phải cài đặt việc đăng nhập tới máy khác không cần user với password trước).
Các bạn có thể thấy, trong class này, mình đã sử dụng đối tượng Runtime với phương thức static là getRuntime() để thực thi một command line trong Java. Trong Unit Test, làm sao mà chúng ta có thể simulate một máy tính khác để test phương thức static checkFileExistingWithoutUsernamePassword trong class SSHCommandLineHelper phải không các bạn? Giải pháp của chúng ta chỉ có thể là dùng Mock mà thôi.
Đầu tiên, các bạn hãy tạo một class SSHCommandLineHelperTest nằm trong thư mục test với package là com.huongdanjava.mockstatic như sau:
Trong class này, đầu tiên các bạn hãy khai báo annotation @PrepareForTest và @RunWith trước như sau:
package com.huongdanjava.mockstatic;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest({SSHCommandLineHelper.class})
public class SSHCommandLineHelperTest {
}
Trong phần @Before của Unit Test, chúng ta sẽ khai báo sử dụng PowerMock để Mock phương thức static trong class Runtime như sau:
@Before
public void init() {
PowerMockito.mockStatic(Runtime.class);
}
Bây giờ, chúng ta sẽ viết test cho trường hợp khi chúng ta chạy chương trình để kiểm tra tập tin tồn tại trên một máy SSH khác thì phương thức checkFileExistingWithoutUsernamePassword trả về giá trị TRUE nhé các bạn!
Nội dung của phương thức testCheckFileExistingSuccessWithoutUsernamePassword như sau:
@Test
public void testCheckFileExistingSuccessWithoutUsernamePassword() throws IOException {
// Khai báo Mock cho đối tượng Runtime
Runtime mockedRuntime = PowerMockito.mock(Runtime.class);
PowerMockito.when(Runtime.getRuntime()).thenReturn(mockedRuntime);
// Khai báo Mock cho đối tượng Process
Process mockedProcess = PowerMockito.mock(Process.class);
// Vì đây là trường hợp success nên đối tượng Process sẽ trả về giá trị "1" khi execute command line
InputStream is = new ByteArrayInputStream("1".getBytes());
PowerMockito.when(mockedProcess.getInputStream()).thenReturn(is);
PowerMockito.when(mockedRuntime.exec(anyString())).thenReturn(mockedProcess);
// Khởi tạo đối tượng SSHCommandLineHelper
SSHCommandLineHelper helper = new SSHCommandLineHelper();
// Assert khi gọi phương thức sẽ trả về TRUE
Assert.assertTrue(helper.checkFileExistingWithoutUsernamePassword("abc", "abc"));
}
Kết quả:
Trường hợp chúng ta test cho tập tin không tồn tại thì chỉ cần chỉnh sửa một xíu như sau:
@Test
public void testCheckFileExistingSuccessWithoutUsernamePassword() throws IOException {
// Khai báo Mock cho đối tượng Runtime
Runtime mockedRuntime = PowerMockito.mock(Runtime.class);
PowerMockito.when(Runtime.getRuntime()).thenReturn(mockedRuntime);
// Khai báo Mock cho đối tượng Process
Process mockedProcess = PowerMockito.mock(Process.class);
// Vì đây là trường hợp không success nên đối tượng Process sẽ trả về giá trị "0" khi execute command line
InputStream is = new ByteArrayInputStream("0".getBytes());
PowerMockito.when(mockedProcess.getInputStream()).thenReturn(is);
PowerMockito.when(mockedRuntime.exec(anyString())).thenReturn(mockedProcess);
// Khởi tạo đối tượng SSHCommandLineHelper
SSHCommandLineHelper helper = new SSHCommandLineHelper();
// Assert khi gọi phương thức sẽ trả về FALSE
Assert.assertFalse(helper.checkFileExistingWithoutUsernamePassword("abc", "abc"));
}
Kết quả:
Toàn bộ code của class SSHCommandLineHelperTest như sau:
package com.huongdanjava.mockstatic;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.mockito.Matchers.anyString;
@RunWith(PowerMockRunner.class)
@PrepareForTest({SSHCommandLineHelper.class})
public class SSHCommandLineHelperTest {
@Before
public void init() {
PowerMockito.mockStatic(Runtime.class);
}
@Test
public void testCheckFileExistingSuccessWithoutUsernamePassword() throws IOException {
Runtime mockedRuntime = PowerMockito.mock(Runtime.class);
PowerMockito.when(Runtime.getRuntime()).thenReturn(mockedRuntime);
Process mockedProcess = PowerMockito.mock(Process.class);
InputStream is = new ByteArrayInputStream("1".getBytes());
PowerMockito.when(mockedProcess.getInputStream()).thenReturn(is);
PowerMockito.when(mockedRuntime.exec(anyString())).thenReturn(mockedProcess);
SSHCommandLineHelper helper = new SSHCommandLineHelper();
Assert.assertTrue(helper.checkFileExistingWithoutUsernamePassword("abc", "abc"));
}
@Test
public void testCheckFileNotExistingWithoutUsernamePassword() throws IOException {
Runtime mockedRuntime = PowerMockito.mock(Runtime.class);
PowerMockito.when(Runtime.getRuntime()).thenReturn(mockedRuntime);
Process mockedProcess = PowerMockito.mock(Process.class);
InputStream is = new ByteArrayInputStream("0".getBytes());
PowerMockito.when(mockedProcess.getInputStream()).thenReturn(is);
PowerMockito.when(mockedRuntime.exec(anyString())).thenReturn(mockedProcess);
SSHCommandLineHelper helper = new SSHCommandLineHelper();
Assert.assertFalse(helper.checkFileExistingWithoutUsernamePassword("abc", "abc"));
}
}
Top 4 Công Việc Có Thu Nhập Hấp Dẫn Trong Tương Lai
Lương cao và nhu cầu nhân lực lớn luôn là hai yếu tố tiên quyết khi người lao động tìm kiếm và lựa chọn công việc. Với những sinh viên đang cân nhắc lựa chọn ngành học, việc tìm hiểu những ngành nghề lương cao dễ kiếm việc trong tương lai chắc chắn là điều rất cần thiết. Bài viết dưới đây sẽ tổng hợp một số công việc được đánh giá sẽ có mức thu nhập hấp dẫn trong tương lai, giúp bạn phần nào định hướng nghề nghiệp tương lai cho mình.
Một số ngành nghề có mức thu nhập hấp dẫn trong tương lai
1. Ngành Công nghệ thông tin
Khi cuộc cách mạng công nghiệp 4.0 đang bước vào thời điểm phát triển rực rỡ nhất, nhu cầu nhân lực cho ngành nghề này càng trở nên rộng mở hơn. Số lượng thí sinh nộp hồ sơ vào những ngành học có liên quan đến công nghệ thông tin cũng như khoa học máy tính luôn tăng cao qua mỗi năm. Cơ hội việc làm với những sinh viên tốt nghiệp ngành IT luôn được hứa hẹn là hấp dẫn hơn bao giờ hết. Vậy mức thu nhập của ngành IT hiện đang phát triển ra sao?
Theo số liệu trong Báo cáo thị trường IT Việt Nam 2021 của TopDev, số lượng nhân lực có thể đáp ứng yêu cầu của các công ty công nghệ thông tin hiện nay vẫn còn thiếu hụt đến 30% và mức lương cho các vị trí IT cũng ngày càng được cải thiện đáng kể. Đặc biệt trong số đó, 3 ngành có mức thu nhập được đánh giá cao nhất thị trường IT hiện nay là Security, High Tech và Fintech.
Lĩnh vực Hightech – công nghệ cao như AI, IoT, điện toán đám mây,… được coi là xu hướng bắt buộc không chỉ trong năm 2021 mà sẽ còn kéo dài trong suốt thời gian tới. Do đó, những lập trình viên có năng lực trong chuyên ngành này đang sở hữu lợi thế về lương bổng cạnh tranh mạnh hơn hẳn so với các lĩnh vực khác trong ngành IT.
Cụ thể, theo báo cáo, mức lương trong ngành IT hiện nay được thống kê dựa vào công nghệ làm việc, trình độ, chuyên ngành và vị trí làm việc của lập trình viên. Có thể tham khảo thêm các biểu đồ thống kê trong ảnh.
Mức lương dựa vào công nghệMức lương dựa vào trình độMức lương dựa vào vị trí làm việc
Nhìn chung, trong khoảng 5 năm làm việc đầu tiên sau khi ra trường, mức lương của lập trình viên sẽ dao động trong mức 342$/tháng tương đương với trình độ fresher đến dưới 1.161$/tháng với vị trí Senior. Khi đã bắt đầu có kinh nghiệm và năng lực chuyên môn nhất định trong công việc, mức lương của lập trình viên lúc này sẽ thay đổi dựa vào vị trí chuyên môn mà họ đảm nhận.
Bên cạnh công nghệ thông tin, sự phát triển của thời đại 4.0 kéo theo sự lớn mạnh của các ngành nghề liên quan đến Marketing và truyền thông. Theo thống kê của Trung tâm Dự báo nhu cầu nhân lực và thông tin thị trường lao động TPHCM, từ nay đến năm 2025, mỗi năm ngành Marketing sẽ còn cần đến hơn 10.000 lao động. Đặc biệt, cơ hội thăng tiến trong ngành marketing cũng được đánh giá cao hơn hẳn so với nhiều ngành nghề khác. 30% nhân lực ngành marketing hiện nay đều là các nhân sự cấp cao điều hành hoạt động của các công ty.
Theo đó, mức lương ở các vị trí của ngành Marketing hiện nay dao động trong khoảng từ 300$ – 2000$/tháng. Cụ thể, với các sinh viên mới ra trường, mức lương sẽ dao động trong khoảng từ 300$ – 500$. Đối với các nhân sự đã có kinh nghiệm làm việc trong ngành Marketing, mức lương có thể nằm trong khoảng từ 500$ – 1000$. Ở các cấp từ quản lý trở lên, mức lương từ 1000$ – 2000$ là điều bạn hoàn toàn có thể làm được.
Xã hội ngày càng phát triển dẫn đến nhu cầu về an sinh xã hội cũng ngày càng tăng cao. Ngành bác sĩ – dược sĩ vẫn sẽ tiếp tục là những ngành nghề lương cao dễ kiếm việc cũng như đòi hỏi lực lượng nhân lực lớn trong tương lai. Việc thi tuyển vào các trường đào tạo y bác sĩ vốn được biết đến là cực kỳ gay go và khốc liệt. Nhưng “trái ngọt” sẽ đến với những khối óc và đôi tay chấp nhận thách thức và khó khăn. Mức lương của ngành Bác sĩ – Dược sĩ hiện vẫn luôn nằm trong top lương cao.
Bác sĩ, dược sĩ vẫn tiếp tục là nghề có thu nhập hấp dẫn
Mức lương của các y bác sĩ và điều dưỡng hiện nay đang dao động trong mức trung bình từ 500$ – 1500$, tùy vào các vị trí khác nhau mà mức lương sẽ có sự chênh lệch nhất định. Hơn nữa, theo như kế hoạch về phát triển đội ngũ nhân lực mà Bộ Y Tế đưa ra, trong thời gian tới, ngành phải bổ sung khoảng 10.887 dược sĩ bậc Đại học, số lượng điều dưỡng là 83.851. Do đó không chỉ có mức lương cao mà cơ hội nghề nghiệp của các cử nhân sau khi ra trường cũng rất lớn.
4. Ngành Du lịch và Quản trị nhà hàng – khách sạn
Từ lâu ngành du lịch và quản trị nhà hàng khách sạn vẫn luôn nằm trong top những ngành nghề được đánh giá có mức thu nhập tốt và cơ hội công việc rộng mở. Ở thời điểm hiện tại, do ảnh hưởng của dịch bệnh nên công việc ở ngành này chịu không ít ảnh hưởng, nhưng khi cuộc sống trở lại bình thường, chắc chắn mọi thứ sẽ tiếp tục phát triển.
Xuất phát từ nhu cầu cải thiện chất lượng đời sống cũng như gia tăng về thu nhập, người dân từ trong đến ngoài nước ngày càng chú trọng hơn đến những chuyến du lịch và nghỉ dưỡng. Đây chính là cơ hội cực lớn cho những ai đang theo đuổi ngành nghề này. Mức lương trung bình của các nhân viên làm việc trong ngành du lịch và quản trị nhà hàng khách sạn hiện đang nằm trong khoảng từ 15 – 30 triệu đồng/tháng.
Mỗi ngành nghề tùy theo tính chất sẽ có mức thu nhập khác nhau. Việc tìm hiểu trước các vấn đề liên quan đến lương bổng đương nhiên chỉ giúp phần nào định hướng công việc trong tương lai của bạn. Điều quan trọng để thành công trong bất kì ngành nghề nào, sự đam mê và tâm huyết với nghề vẫn là yếu tố mang tính quyết định. Đón đọc thêm nhiều bài viết với nội dung hấp dẫn khác tại TopDev nhé!
Ở các bài viết trước chúng ta đã cùng tìm hiểu về một số khái niệm cơ bản của RabbitMQ và cách cài đặt RabbmitMQ Server. Trong bài này, chúng ta sẽ cùng tìm hiểu cách tạo RabbitMQ Client (Producer và Consumer) sử dụng AMQP library để kết nối đến RabbitMQ server, đồng thời cũng giới thiệu với các bạn cách hoạt động của Default Exchange trong RabbitMQ.
Tạo maven project và mở file pom.xml, khai báo dependency như sau:
<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.gpcoder</groupId><artifactId>rabbitmq-example</artifactId><version>1.0-SNAPSHOT</version><properties><java.version>1.8</java.version><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.source>1.8</maven.compiler.source></properties><dependencies><!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client --><dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.8.0</version></dependency></dependencies><build><plugins><!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><!-- include all the dependencies into the jar for easier to execute the application --><!-- https://mvnrepository.com/artifact/org.fusesource.mvnplugins/maven-uberize-plugin --><plugin><groupId>org.fusesource.mvnplugins</groupId><artifactId>maven-uberize-plugin</artifactId><version>1.45</version><executions><execution><phase>package</phase><goals><goal>uberize</goal></goals></execution></executions></plugin></plugins></build></project>
Tạo Producer và Consumer
Tạo Producer
Các bước thực hiện:
Tạo ConnectionFactory : xác định remote URI đến RabbitMQ server. Cần cung cấp một số thông tin như: Virtual Host, Host, Port, Username, Password. Nếu chỉ chạy ở lcoalhost và sử dụng các thông số mặc định của RabbitMQ, thì chỉ cần khai báo Host là “localhost”.
Tạo Connection từ ConnectionFactory. Đây là một kết nối TCP giữa ứng dụng và RabbitMQ broker.
Tạo Channel: tạo một kết nối ảo trong một Connection. Việc publishing hoặc consuming message từ một queue đều được thực hiện trên channel. Mỗi Connection có thể có nhiều Channel quản lý những thứ như Exchange và Message riêng biệt.
Tạo Exchange: Là nơi nhận message được publish từ Producer và đẩy chúng vào queue dựa vào quy tắc của từng loại Exchange. Để nhận được message, queue phải được nằm (binding) trong ít nhất 1 Exchange. Tôi sẽ giới thiệu cách sử dụng Exchange ở bài viết khác.
Tạo Queue: Tạo queue để lưu trữ các Message.
Tạo Message: Nội dụng tin nhắn sẽ được gởi đến client. Thông tin này được truyền từ Producer đến Consumer qua RabbitMQ.
Gửi Message: thực hiện gửi message đến Exchange thông qua phương thức channel.basicPublish(). Sau khi nhận message, Exchange sử dụng sẽ định tuyến (route) Message đến Queue.
Đóng kết nối: sau khi sử dụng xong cần đóng kết nối, để giải phóng các tài nguyên được sử dụng cho kết nối đó.
factory.setHost(“localhost”) : chúng ta chỉ cần khai báo như thế này là đủ để kết nối đến RabbitMQ Server. Những tham số còn lại, RabbitMQ sẽ lấy những giá trị mặc định. Nếu bạn deploy ứng dụng lên server có thể khai báo thêm các tham số khác như đoạn code mình đã comment lại trong chương trình trên.
channel.queueDeclare() : tạo một Queue để lưu trữ các Message. Một số đối số của phương thức này:
boolean durable : queue và message sẽ bị xoá khi RabbitMQ server stop, để giữ lại chúng ta cần set giá trị này là true.
boolean exclusive : queue sẽ bị xoá khi Connection close.
boolean autoDelete : Queue tự động bị xóa khi Consumer cuối cùng của nó bị hủy hoặc đóng hoặc mất kết nối TCP với máy chủ.
Map<String, Object> arguments : các tham số nếu có.
channel.basicPublish() : gửi message lên Exchange. Một số đối số của phương thức này:
String exchange : tên của Exchange. Trong bài này, tôi sẽ không xác định Exchange Name, để giá trị nó là empty. Đây là loại Default Exchange. Default Exchange được liên kết ngầm định với mọi Queue với khóa định tuyến bằng với tên Queue.
String routingKey : key của Exchange.
BasicProperties props : các thuộc tính khác cho message.
byte[] body : nội dung của tin nhắn.
Tạo Consumer
Các bước thực hiện tương tự như tạo Producer, khác biệt duy nhất là thay vì tạo Producer để gửi tin nhắn, ta tạo Consumer để nhận tin nhắn.
channel.queueDeclare() : tương tự như Producer.
channel.basicConsume() : nhận Message từ Queue. Một số đối số của phương thức này:
String queue : Tên của Queue muốn nhận message từ.
boolean autoAck : tự động gửi một ACK message đến RabbitMQ để báo với RabbitMQ rằng một Message đã được consumer nhận, xử lý và Rabbit có thể xoá nó.
DeliverCallback deliverCallback : cung cấp một call back để xử lý khi một message đến.
CancelCallback cancelCallback : cung cấp một call back để xử lý khi một consumer bị cancel vì một lý do nào đó, chẳng hạn Queue bị cancel.
Lưu ý rằng tại sao Consumer lại cần declare một Queue. Vì chúng ta có thể start một Consumer trước một Producer, chúng ta muốn đảm bảo Queue tồn tại trước khi chúng ta cố gắng consume message từ nó.
Tại sao chúng ta không sử dụng câu lệnh try-with-resource để tự động close Connection và Channel? Bằng cách làm như vậy, chúng ta chỉ đơn giản sẽ làm cho chương trình tiếp tục, đóng mọi thứ và thoát. Điều này sẽ gây khó khăn vì chúng ta muốn quá trình này tồn tại trong khi Consumer đang chờ tin nhắn bất động bộ đến.
Chạy ứng dụng
Trước hết, chúng ta cần package ứng dụng trên thành gói jar, chạy lệnh: mvn clean install
Sau khi chạy lệnh trên, trong thư mục target của project, chúng ta có gói: rabbitmq-example-1.0-SNAPSHOT.jar
Start RabbitMQ Server: xem lại bài viết trước “Cài đặt RabbitMQ“.
Nhập một vài giá trị ở cửa sổ Producer, chúng ta có kết quả sau:
Như bạn thấy, một tin nhắn chỉ được gửi cho một client tại một thời điểm và client thay phiên nhau nhận tin nhắn (Round-robin).
Hãy đóng các console trên bằng cách nhấn tổ hợp phím Ctrl + C.
Producer gửi message trước khi Consumer start
Tiếp tục hãy test thử một trường hợp khác: Start Producer và gửi một vài message:
Sau đó start Consumer và check kết quả.
Bạn có thể thấy rằng, người nhận không cần active tại thời điểm Producer gửi message. RabbitMQ Broker sẽ deliver message ngay khi Consumer active.
Kiểm tra request trên RabbitMQ Management Interface
Start Producer và gửi một vài message.
Mở admin page: http://localhost:15672/#/exchanges
Chọn AMQP default, bạn sẽ thấy message rates được gửi trong một phút qua ở AMQP Default Exchange (do chúng ta không xác định tên của exchange ở chương trình trên, nên mặc định Message sẽ được gửi thông quan Default Exchange).
Chọn menu Queue, bạn sẽ thấy thông tin của Mesages Ready để gửi cho Consumer.
Reverse Array là bài toán phổ biến mà bất cứ kĩ sư phần mềm nào cũng cần phải hiểu rõ và áp dụng thành thục. Mở rộng ra cho cả string và các bài toán khác.
Cùng tìm hiểu một số lời giải cơ bản cho Array ngay thôi nào!
Làm việc với Array tất nhiên phải chú ý tới complexity (độ phức tạp). Arrays provide O(1) lookup by index (Tìm kiếm theo index trên Array luôn có độ phức tạp nhỏ nhất O(1)
Ngoài đảo ngược Array, cũng có một bài toán khác khá hay liên quan tới Array là duplicate item trong array.
Given an array of numbers, replace each even number with two of the same number. e.g, [1,2,5,6,8] -> [1,2,2,5,6,6,8,8]
Cho một danh sách các mảng, thay thế mỗi số chẵn bằng 2 số.
Time Complexity: O(n) aka linear time
Space Complexity: O(1) aka constant space
Độ phức tạp về thời gian là O(n) do duyệt mảng từ đầu tới cuối
package com.src;
public class Main {
public static void main(String[] args) {
// Mảng input sẽ có -1 đại diện cho index sẽ duplicate bằng số chẵn
int[] a = new int[]{2, 4, 1, 0, 3, -1, -1, -1};
cloneEvenNumber(a);
for (int item : a) {
System.out.println(item);
}
}
public static int[] cloneEvenNumber(int[] a) {
if (a == null || a.length == 0) {
return a;
}
int end = a.length;
int i = getLastNumber(a);
while (i >= 0) {
// Mảng chạy từ phải qua trái
if (a[i] % 2 == 0) {
a[--end] = a[i];
}
// Set vào phía sau mảng nếu là số lẻ, lặp nếu là số chẵn
a[--end] = a[i];
i--;
}
return a;
}
// Tìm vị trí i cuối cùng không phải là -1
public static int getLastNumber(int[] a) {
int i = a.length - 1;
while (i >= 0 && a[i] == -1) {
i--;
}
return i;
}
}
2. Traverse từ Both Ends
1) Initialize start and end indexes as start = 0, end = n-1
2) Swap arr[start] with arr[end]
3) Recursively call reverse for rest of the array.
Về ý tưởng cơ bản thì khi muốn đảo ngược array, ta sẽ thực hiện đổi chỗ tuần tự phần tử đầu và cuối. Tiến dần về trong cho tới phần tử ở giữa. Có thể hiện thực code như sau:
package com.src;
public class Main {
public static void main(String[] args) {
int[] a = new int[]{3, 4, 2, 7, 1};
reverse(a);
for (int item : a) {
System.out.println(item);
}
}
public static void reverse(int[] a) {
int start = 0;
int end = a.length - 1;
while (start < end) {
swap(a, start, end);
start++;
end--;
}
}
private static void swap(int[] a, int start, int end) {
int temp = a[start];
a[start] = a[end];
a[end] = temp;
}
}
3. Traverse String
Bài toán đảo ngược không những áp dụng cho Array mà còn có thể áp dụng cho String. Cho dãy string “This is Kieblog”, đảo ngược chuỗi với Time Complexity và Space Complexity là O(n)
package com.src;
public class Main {
public static void main(String[] args) {
System.out.println(reverseWord("This is Kieblog"));
}
public static String reverseWord(String s) {
StringBuilder builder = new StringBuilder();
int currentWordEnd = s.length();
for (int i = s.length() - 1; i >= 0; i--) {
// Thêm space nếu có
if (s.charAt(i) == ' ') {
if (builder.length() > 0) {
builder.append(' ');
}
// Lấy từ kí tự cuối từ phải qua trái
builder.append(s.substring(i + 1, currentWordEnd));
currentWordEnd = i;
}
}
String firstWord = s.substring(0, currentWordEnd);
if (builder.length() > 0) {
builder.append(" ");
}
builder.append(firstWord);
return builder.toString();
}
}
Ngoài Reverse Array, cũng có những bài mở rộng hơn là tìm kiếm 2 vị trí trong array sao cho tổng là một số nguyên (target nhất định). Ước định rằng array đã được sort từ ban đầu. Ta cũng có thể lặp từ start tới end, tăng start nếu sum nhỏ hơn target và giảm end nếu sum đã lớn hơn target
package com.src;
public class Main {
public static void main(String[] args) {
int[] a = new int[]{1, 2, 3, 5, 6, 7};
System.out.println(twoSum(a, 11));
}
public static int twoSum(int[] a, int target) {
int start = 0;
int end = a.length - 1;
while (start < end) {
int sum = a[start] + a[end];
if (sum < target) {
start++;
}
if (sum > target) {
end--;
}
if (sum == target)
return a[start] + a[end];
}
return 0;
}
}
Vậy nếu có nhu cầu chạy các hàm một cách bất đồng bộ, như phất cờ là cho toàn bộ chạy một lúc giống thi chạy diệt dã? Chúng ta có một lựa chọn rất hiển nhiên Promise.all
Bài viết được sự cho phép của tác giả Kien Dang Chung
Video trong bài viết
Trong bài trước, bạn đã được giới thiệu lý thuyết về Hồi quy tuyến tính (Linear Regression), bạn cũng đã hiểu thuật toán này hoạt động như thế nào, giờ là lúc chúng ta áp dụng nó vào trong bài toán thực tế: Dự đoán doanh thu phim thông qua ngân sách.
Scikit-learn thư viện cần thiết cho Machine Learning
Scikit-learn có lẽ là thư viện phổ biến nhất trong lĩnh vực machine learning, với thư viện này công việc của chúng ta chỉ là cung cấp dữ liệu và mọi thuật toán machine learning đã được xây dựng sẵn trong bộ thư viện này sẽ mang về cho bạn kết quả như mong muốn.
Để sử dụng thuật toán Linear Regression đã được cài đặt sẵn trong Scikit-learn, chúng ta thực hiện import thư viện này vào chương trình:
from sklearn.linear_model import LinearRegression
Bộ thư viện Scikit-learn rất là đồ sộ, do chúng ta đã tìm hiểu về thuật toán Linear Regression nên chúng ta chỉ import phần liên quan đến thuật toán này mà thôi. Để thực hiện thuật toán Hồi quy tuyến tính trên các dữ liệu X, y đã được bóc tách và mô phỏng trong bài trước, chúng ta thực hiện đoạn code trong Python:
Biến regression chứa một đối tượng LinearRegression trong bộ thư viện Scikit-learn và tiếp theo là thực hiện phương thức fit() trên đối tượng này. Fit() thực hiện tính toán tối ưu hóa các tham số θ0 và θ1, phương thức này trả về một model. Sau khi thực hiện phương thức này, chúng ta đã có một đối tượng chứa đầy đủ thông tin kết quả, ví dụ chúng ta cần lấy về giá trị của các tham số θ0 và θ1:
Với hai tham số θ0θ0 và θ1θ1 là đủ để chúng ta vẽ ra đường thẳng mô tả mối quan hệ giữa ngân sách và doanh thu trong làm phim ảnh. Thực hiện vẽ đường thẳng này với matplotlib:
plt.figure(figsize=(10,6))
plt.scatter(X, y, alpha=0.3)# Adding the regression line here:
plt.plot(X, regression.predict(X), color='red', linewidth=3)
plt.title('Film Cost vs Global Revenue')
plt.xlabel('Production Budget $')
plt.ylabel('Worldwide Gross $')
plt.ylim(0,3000000000)
plt.xlim(0,450000000)
plt.show()
Đoạn code này tận dụng những gì đã code để vẽ lên biểu đồ các điểm (ngân sách, doanh thu).
Dự đoán và đánh giá kết qủa
Với kết quả các tham số θ1 (độ dốc) và θ0 (điểm cắt trục y), chúng ta có thể dự đoán được doanh thu của một phim với ngân sách cho trước như sau:
Doanh_thu =-7,236,192.7+3.1115 x Ngân_sách
Với công thức này, một phim có ngân sách 50 triệu USD sẽ có doanh thu là 148 triệu USD, gần gấp 3. Trong phương pháp này cũng có những điểm bất bình thường, ví dụ khi ngân sách = 0 thì doanh thu phim tính được là -7,236,192.7 USD, một điều không thể khi tôi không bỏ tiền ra thì một ai đó có thể lấy của tôi hơn 7 triệu đô. Ngoài ra cũng có những trường hợp rất đặc biệt như phim Avatar chẳng hạn, với chi phí cỡ 450 triệu đô và thu về gần 3 tỉ đô.
Để đánh giá kết quả khi áp dụng Linear Regression chúng ta có một phương thức là score(), phương thức này trả về một hệ số xác định cho R^2. Trong đó, R^2 được tính bằng công thức 1 – u/v với:
u = ((y_true – y_pred)^2).sum() là tổng bình phương các độ lệch.
v = ((y_true – y_true.mean())^2).sum()
Giá trị tốt nhất là 1.0, giá trị này có thể âm.
Lời kết
Như vậy chúng ta đã hoàn thành dự án đầu tiên mở màn cho việc học tập nghiên cứu về Trí tuệ nhân tạo nói chung hay Machine learning nói riêng. Với dự án dự đoán doanh thu phim từ tổng chi phí sản xuất, chúng ta đã được làm quen với các quy trình cần thiết khi thực hiện một bài toán bằng các công cụ khoa học dữ liệu. Chúng ta cũng đã làm quen với thuật toán đầu tiên Linear Regression (Hồi quy tuyến tính), qua đó cũng nắm bắt được cách dùng một số thư viện như Matplotlib hay scikit-learn trong Python. Trong bài tiếp theo, chúng ta sẽ thực hiện tổng quát hóa thuật toán Linear Regression với nhiều tham số đầu vào hơn và chính thức kết thúc dự án 1 để chuyển sang những dự án rất thú vị đang chờ phía trước.
Trong quá trình học tập, có bất kỳ câu hỏi, thắc mắc hoặc đơn giản là trao đổi những suy nghĩ của mình, bạn đừng ngại hãy để lại comment trên từng bài viết, tôi và các bạn đang học khác sẽ giúp bạn.
Bài viết được sự cho phép của tác giả Võ Quang Huy
Phỏng vấn lập trình php – Lang thang trên facebook thì đọc được bài viết của bạn “Anh Hùng Thời Loạn” Viết về những câu hỏi thường gặp khi phỏng vấn lập trình viên, thấy cũng khá hay nên mình lấy về chia sẽ cho những ai cần
Câu hỏi về PHP thuần: (dành cho cấp độ cơ bản)
1- PHP có mấy cách khai báo ?. Những cách nào được xem là chính thống và không ảnh hưởng khi các phiên bản update sau này?
– Có 3 cách là <? ? > và <?php ?> <% %>…cách 2 là chính thống
2- Hằng trong PHP khác gì so với biến ? Nếu 1 hằng được định nghĩa 2 lần, thì liệu có bị lỗi không ?. Cho ví dụ minh họa. Hằng có thể nội suy như biến hay không ?
– Khác nhau : hằng không thay đổi trong suốt chương trình, biến thì có
– Nếu định nghĩa hăng 2 lần thì sẽ có thông báo hằng đã tồn tại, chương trình vấn chạy với hằng được định nghĩa đầu tiên
– Không hiểu nội suy là cm gì luôn
3- Có bao nhiêu biến môi trường ?. $_REQUEST có thể nhận được giá trị từ form hay không ?
– Có 4 bến môi trường là : $_GET, $_POST, $_REQUEST,$_SERVER
– $_REQUEST nhận được, dùng nó trong trường hợp không biết dữ liệu nên là post hay get
– $_GET : gửi dl lên server thông qua URL, thông tin hiển thị lên url , kích thước url giới hạn
– $_POST : gửi dl lên server dưới dạng ẩn, không hiển thị param lên url, dữ liệu không giới hạn.
– Get thực thi nhanh hơn post vì cơ chế
+ get : quăng chuỗi string lên URL, server tách chuỗi lấy đc tham số
+ Post : các tham số được đóng gói vào 1 file tạm, sau đó trình duyệt gửi file tạm đó lên server và server lưu lại file tạm đó sau đó mới phân tích
– Post chậm hơn get
– Về tính bảo mật thì 2 thằng như nhau
5- Mảng tuần tự là gì ?. Khác gì với bất tuần tự ?. Để duyệt mảng ta dùng vòng lặp nào ?. Tại sao vòng lặp for, while, do….while lại không ưu tiên sư dụng trong duyệt mảng ?
– Mảng tuần tự là mảng mà các khóa được đánh theo số, bắt đầu từ 0
– Mảng bất tuần tự là các key của nó k phải là số mà có thể là string.
Để duyệt mảng tuần tự dùng vòng lặp for
Duyệt mang bất tuần tự dùng vòng lặp foreach
—không biết, vấn dùng for vs while duyệt hoài mà )
6- Để chuyển mảng thành chuỗi ta dùng hàm gì ?. Để tách chuỗi thành mảng ta dùng hàm gì?. Để gộp mảng ta dùng hàm gì ? Để tách mảng ta dùng hàm gì ?
– Chuyển mảng thành chuỗi dùng : implode(“Chuỗi nối”,$mảng)
– Chuyển chuỗi thành mảng dùng : explode(“Chuỗi tách”,$string)
– Để gộp mảng dùng : array_merge($mang1, $mang2)
– Để tách mảng dùng : array_slice($mang, vị trí tách, số lượng tách)
7- Cho biết sự khác nhau giữa serialize và json_encode. Lý giải theo cách bạn hiểu.
– Json_encode : để giải mã dữ liệu json đã được mã hóa bằng json_decode : từ phiên bản php 5.2 trở đi, người ta thay thế json_encode và decode cho serialize
– Serialize : chuyển đổi mảng thành string và unseriallize để lấy lại mảng ban đầu
Không biết luôn
8- Cookie và session có gì khác nhau ?. Người ta nói bản thân của session là cookie, điều đó đúng hay sai ?. Nếu muốn tăng thời gian sống của session thì thiết lập thế nào ?
– Cookie lưu ở client trên browser
– Session : lưu trên server và đồng thời ở client cũng có 1 cookie sinh ra tương ứng đúng như session id của nó trên server : PHPSESSID, các giá trị biến của session đc lưu trong file đó (dùng để quản lý đăng nhập)
– coi session là cookie cũng đúng.
– chả biết chỉnh ở đâu? Php.ini chăng ?
9- Giả sử bạn là chủ của server, làm thế nào có thể biết được các file session lưu ở đâu ?. Bạn có thể can thiệp, chỉnh sửa file session này hay không ?
Biết được. lưu ở file php.ini (tham số session.save_path)
10- Theo bạn, sự khác nhau của toán tử & và && là gì ?. Hãy cho biết $a++ và ++$a khác nhau ở đâu ?. Tính nhanh kết quả của đoạn code sau trong 2 phút:
12- Muốn chuẩn hóa dữ liệu về utf-8 ta phải làm gì ?
– Sử dụng dạng utf-8 trong meta charset
– Sử dụng utf-8-unicode-ci trong sql
13- Làm sao lấy được id vừa tiến hành thêm vào CSDL ngay ?
– Sử dụng hàm mysql_insert_id hoặc sử dụng limit(0,1) DESC
– Trong các framework sẽ có các hàm khác nhau hỗ trợ
14- Để đếm số dòng, ta nên dùng mysql_num_rows() trên câu truy vấn “select * from….” hay count trực tiếp trong câu truy vấn ?
– Không hiểu ý câu hỏi lắm.
15- Việc enter có giá trị hay không trong textarea bình thường (không nhúng khung soạn thảo). Và làm thế nào để có thể hiển thị ra bên ngoài thao tác xuống dòng như bình thường.
– Ít làm nên không hiểu lắm
16- fgets() và fgetc() khác nhau như thế nào ?. fgets() và fread() khác nhau ra sao ?. feof là gì, nó có ý nghĩa như thế nào ?. file_get_contents() khác gì so với fread() ?
– File_get_contents() : dùng để lấy nội dung của files
– Fread phải open xong mới đọc được, phải chỉ ra kích thước file
Bài viết được sự cho phép của blogchiasekienthuc.com
Chào các bạn, trong các bài viết trước mình đã giới thiệu tới các bạn một số những công cụ UI (công cụ giao diện đồ họa) được sử dụng để làm việc với các hệ quản trị cơ sở dữ liệu rất hay.
Nhưng sẽ là rất thiếu sót nếu như mình không đề cập đến DataGrip – một công cụ đến từ JetBrains với những tính năng có thể nói là rất mới và “ăn đứt” các công cụ cùng chức năng khác.
Trong khuôn khổ bài viết hôm nay mình sẽ cùng các bạn cài đặt công cụ này trên hệ điều hành Windows 10 và thực hiện kết nối đến hệ quản trị cơ sở dữ liệu MySQL.
#1. Hướng dẫn cài đặt DataGrip mới nhất
+ Bước 1: Đầu tiên các bạn download file cài đặt tại đây:
Hiện tại thì DataGrip hỗ trợ cả ba hệ điều hành phổ biến nhất hiện nay là Windows, macOS và Linux. Ở trong bài hướng dẫn này mình sẽ cùng các bạn cài đặt DataGrip trên hệ điều hành Windows 10 nhé.
Sau khi download các bạn chạy file cài đặt (file *.exe) để bắt đầu quá trình cài đặt như hình bên dưới.
+ Bước 2: Các bước cài đặt cũng tương tự như khi cài đặt các phần mềm khác của JetBrains. Đầu tiên các bạn bấm Next như hình bên dưới.
+ Bước 3: Tiếp đến là thông báo về yêu cầu phần cứng, cũng như vị trí cài đặt.
Ở đây, về yêu cầu phần cứng thì ổ cứng của các bạn phải còn tối thiểu khoảng 942 MB (các phiên bản trong tương lai có thể nặng hơn), vậy nên tối thiểu các bạn phải còn khoảng 1GB ổ cứng.
Nếu bạn muốn thay đổi vị trí cài đặt sang một phân vùng ổ cứng khác thì có thể bấm vào Browse… Ở đây mình sẽ để mặc định thì bấm bấm Next để tiếp tục thôi.
+ Bước 4: Bây giờ bạn hãy lựa chọn một số Option
Ở bước này, các bạn cứ tích như trong hình bên dưới là được. Mục đích của bước này là thiết lập một số cấu hình cơ bản (thực ra thì sau khi cài các bạn thiết lập sau cũng được).
=> Sau đó thì bấm Next để tiếp tục.
+ Bước 5: Bước này các bạn cứ để mặc định rồi bấm Install nhé.
+ Bước 6: Các bạn chờ khoảng 30 là quá trình cài đặt sẽ hoàn tất.
+ Bước 7: Okay, đến đây thì đã xong bước cài đặt các bạn bấm Finish để hoàn tất.
#2. Cách kết nối đến hệ quản trị cơ sở dữ liệu
DataGrip là một phần mềm trả phí của JetBrains. Vì vậy sau khi cài đặt các bạn có thể chọn mua bản quyền để sử dụng lâu dài, hoặc là bạn cũng có thể dùng thử 30 ngày trước khi quyết định mua.
Ở đây mình chọn chế độ dùng thử 30 ngày như hình bên dưới.
Ở màn hình Welcome như hình bên dưới các bạn có thể chọn New Project để tạo một Project mới.
Tiếp theo chúng sẽ tạo một kết nối đến hệ quản trị cơ sở dữ liệu. DataGrip hỗ trợ hầu hết các hệ quản trị cơ sở dữ liệu phổ biến hiện nay.
Trong bài viết này mình sẽ tạo một kết nối đến hệ quản trị cơ sở dữ liệu MySQL như hình bên dưới.
Tiếp theo chúng ta sẽ điền các thông tin để kết nối đến hệ quản trị cơ sở dữ liệu.
Host: Là địa chỉ IP của Server
Port: Là cổng cho dịch vụ MySQL (mặc định là 3306)
User: Tên đăng nhập vào hệ quản trị csdl
Password: Mật khẩu đăng nhập vào hệ quản trị csdl
Database: Là database mà các bạn muốn kết nối đến
Sau khi kết nối thành công thì chúng ta đã có thể thực hiện các thao tác trên hệ quản trị cơ sở dữ liệu.
Tiếp theo các bạn có thể viết các câu query ở tab Console như hình bên dưới và biên dịch để xem kết quả.
Nếu câu query được biên dịch thành công thì các bạn có thể thấy câu query được tích xanh như hình bên dưới.
#3. Lời Kết
Vậy là trong bài viết này mình đã cùng các bạn cài đặt DataGrip trên Windows, cũng như tìm hiểu về cách kết nối đến hệ quản trị cơ sở dữ liệu MySQL rồi ha.
Còn rất nhiều chức năng hay khác của DataGrip mà mình sẽ cùng các bạn tìm hiểu kỹ hơn ở trong những bài viết tiếp theo 🙂
Hi vọng là bài viết này sẽ hữu ích với bạn. Hẹn gặp lại các bạn trong các bài viết tiếp theo !
5. Anh/chị hiểu như thế nào về kiểm thử hồi quy (regression test) và kiểm thử lại (re-test)?
6. Anh/chị được yêu cầu kiểm thử 600 trường hợp kiểm thử và mỗi trường hợp kiểm thử mất 10 phút. Nếu sếp yêu cầu Anh/chị phải hoàn tất 600 trường hợp này trong 1 tuần, Anh/chị sẽ làm gì?
7. Những nguyên nhân nào thường gây ra lỗi sản phẩm?
8. Sự khác biệt giữa kiểm thử (testing) và kiểm tra (checking)?
9. Những nguyên nhân nào anh/chị có thể nghĩ ra để giải thích việc kỹ sư kiểm thử không tìm được lỗi?
10. Khi nào thì Anh/chị ngừng kiểm thử?
11. Theo Anh/chị thì những tiêu chí nào để đánh giá chất lượng công việc của kỹ sư kiểm thử?
12. Kỹ sư kiểm thử có cần kỹ năng lập trình hay không và tại sao?
13. Anh/chị báo cáo một lỗi sản phẩm nhưng Devs nói không phải là lỗi. Anh/chị làm gì tiếp theo?
14. Sau khi sản phẩm được đưa ra thị trường, khách hàng tìm được một lỗi quan trọng. Là người kiểm thử sản phẩm đó, Anh/chị đánh giá như thế nào về tình huống đó?
15. Anh/chị hãy liệt kê vài cách mà theo Anh/chị sẽ nâng cao năng lực cũng như kiến thức về kiểm thử phần mềm?
Những câu hỏi trên đa phần là những câu hỏi mở giúp ứng viên thể hiện hết khả năng tư duy của mình. Trên thực tế đây là những câu hỏi mở đầu cho một loạt những câu hỏi khác tùy vào câu trả lời của ứng viên. Do đó, các bạn cũng không nên cố gắng đi tìm câu trả lời đúng nhất mà cố gắng hiểu câu hỏi và trả lời tùy vào sự hiểu biết của bạn.
Trên server Cron files được lưu trong thư mục /var/spool/cron, cấu trúc giống như trên các os unix-like khác.
Các lệnh dùng với crontab:
crontab -e: tạo hoặc chỉnh sửa file crontab
crontab -l: hiển thị file crontab
crontab -r: xóa file crontab
Nếu server chưa có crontab cần install:
# Install:
yum install cronie
# Start crontab và tự động chạy mỗi khi reboot:
systemctl start crond
chkconfig crond on
Cấu trúc:
* * * * * owner command to execute 1
* * * * * owner command to execute 2
* * * * * owner command to execute 3
Giải thích
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday;
│ │ │ │ │ 7 is also Sunday)
│ │ │ │ │
│ │ │ │ │
* * * * * owner command to execute
Setup schedule for cron tab
Schedule
Description
Format
yearly
Run once a year at midnight of 1 January
0 0 1 1 *
monthly
Run once a month at midnight of the first day of the month
0 0 1 * *
weekly
Run once a week at midnight on Sunday morning
0 0 * * 0
daily
Run once a day at midnight
0 0 * * *
hourly
Run once an hour at the beginning of the hour
0 * * * *
Example
# Run a task for every Friday at 17:01pm
1 17 * * 5 /var/cron/pkgtabs/shutdown_server_and_go_drinking
# Run db_export_dump at 23:45 (11:45 PM) every Saturday
45 23 * * 6 /var/cron/pkgtabs/db_export_dump
# Run task for every hours
0 * * * * /var/cron/pkgtabs/send_mail
Config crontab
Để crontab tự động chạy cần kích hoạt và cấu hình crontab như sau:
crontab -e
# Sau đó nhập nội dung
# Chạy cron đơn giản, repeat theo từng giờ
crontab 0 * * * * $(OWNER) /var/share/point_tool/task1.sh
# Chạy cron tab theo từng phút, đồng thời tại lock để tránh trường hợp task chạy chồng lên nhau (task xữ lý chưa hết thời gian thì task sau đến thời điểm chỉ định sẽ không được chạy
crontab * * * * * $(OWNER) /usr/bin/flock -n /var/point_tool/cron/task2.lockfile php /var/share/point_tool/task2.php --minutely >> /var/log/cron/task2.log
Trong đó
/usr/bin/flock -n /path/to/lockfile tạo file lock cho task, chống chạy nhiều task một lúc
–minuly lock task theo phút
Execute crontab
Có thể start crontab ở console như sau:
# Run a task for every Friday at 17:01pm
1 17 * * 5 /var/cron/pkgtabs/shutdown_server_and_go_drinking
# Run db_export_dump at 23:45 (11:45 PM) every Saturday
45 23 * * 6 /var/cron/pkgtabs/db_export_dump
# Run task for every hours
0 * * * * /var/cron/pkgtabs/send_mail
Bài viết được sự cho phép của BQT Kinh nghiệm lập trình
Chắc hẳn ai trong chúng ta cũng từng nghe qua từ khóa Cache. Vậy cache là gì? Vai trò của cache trong các hệ thống website như thế nào. Trong bài viết này mình sẽ giới thiệu tổng quan về Cache. Cuối bài mình chia sẻ 1 kinh nghiệm về việc disable cache/ tắt chế độ caching trên IIS của Windows Server.
Trong tin học, cache được hiểu chung là bộ nhớ đệm. Tức là bộ nhớ tạm thời được sinh ra để phục vụ cho việc truy cập từ các ứng dụng khác trong 1 thời gian hữu hạn để sẵn sàng sử dụng lại 1 cách nhanh chóng. Thực tế cache là các dữ liệu trong phiên làm việc trước của ứng dụng, được lưu lại để việc thực hiện ở các phiên tiếp theo được nhanh hơn (nếu có sử dụng lại dữ liệu của phiên trước đó). Tuy nhiên cần lưu ý là cache có thể làm đầy dung lượng ổ cứng trên thiết bị của bạn.
Cache website hoạt động như thế nào?
Cache sinh ra giúp tăng tốc độ truy cập website ở các phiên tiếp theo. Web content có thể chia thành 2 loại chính
Static content: Là những nội dung không thay đổi/ít thay đổi qua các request lên server. Thông thường là các file tĩnh như Logo, tiêu đề, banner, hình ảnh, âm thành, video, css, js….
Dynamic content: Những dữ liệu thay đổi qua các request ví dụ như ASP content, PHP content, hay kết quả của các query. Tuy nhiên đôi khi ta cũng có thể caching lại dữ liệu này để tăng tốc độ website.
Lợi ích chính của Cache
Cache gần như là công nghệ không thể thiếu với website ngày nay. Sử dụng cache đem lại những lợi ích nổi bật sau:
Tăng tốc độ truy cập, dữ liệu được load ra gần như tức thời
Giảm thiểu băng thông tới server
Giảm thiểu tài nguyên CPU, RAM trên server
Có thể truy cập ngay cả khi không có internet
Đáp ứng lượng lớn truy cập với các hệ thống lớn
Caching trên IIS
Chi tiết cách cấu hình, theo dõi cache mình sẽ giới thiệu ở bài viết sau. Bài viết này mình xin chia sẻ kinh nghiệm sử dụng cache trên IIS của Windows server. Mặc định IIS đã hỗ trợ sẵn caching static content. IIS hỗ trợ 2 cơ chế đệm:
varyByQuerystring: Các truy vấn tương tự từ URL sẽ trả về kết quả giống nhau.
varybyHeaders: Thay đổi bộ nhớ đệm dựa vào HTTP Header được gửi từ Client tới Server
Config Output Caching trên IIS Manager
Cache có thể cấu hình một cách dễ dàng trên giao diện quản lý của IIS Manager như sau:
Click Start -> Administrative Tools -> Internet Information Services (IIS) Manager
Ở cột bên trái, chọn website bạn muốn cấu hình.
Chọn Output Caching
Ở cột bên phải, chọn Add ở menu Action
Ở ô File name extension, điền vào .php hoặc định dạng khác sau đó chọn User-mode caching
Chọn tiếp Advanced, sau đó tích vào Query string variable(s)
Tùy chọn các biến của bạn ở ô này và Lưu lại
Disable caching trên IIS
Không thể phủ nhận các lợi ích tuyệt vời mà cache đem lại. Tuy nhiên trong 1 số trường hợp, việc server tự động cache cũng gây không ít phiền toái cho người sử dụng. Đôi khi không phù hợp với nhu cầu của người dùng. Dưới đây là cách tắt bỏ cơ chế cache trên IIS.
Đầu tiên, chọn website của bạn từ IIS Manager
Chọn Explore để tìm đến Web.config
Mở file Web.config ra và thêm đoạn cấu hình như dưới đây:
Như vậy là mình đã tắt bỏ cơ chế tự động caching static content trên website của bạn. Điều này rất hữu ích cho các bạn Developer trong quá trình xây dựng Website.
Trong bài viết tiếp theo, mình sẽ giới thiệu thêm các cách bật/tắt Cache ở nhiều phía khác nhau. Hi vọng mọi người đã có cái nhìn tổng quan hơn về Cache nói chung và Cache Website nói riêng.
Trong bài viết trước, chúng ta đã cùng tìm hiểu về cách tạo RabbitMQ Client (Producer và Consumer) sử dụng AMQP library để kết nối đến RabbitMQ server. Trong bài này, chúng ta sẽ cùng tìm hiểu chi tiết hơn về Work Queues được sử dụng để phân phối các task đến nhiều Worker.
Ý tưởng chính của Work Queues (còn gọi là Task Queues) là tránh thực hiện một nhiệm vụ (work/task) tốn nhiều tài nguyên ngay lập tức và phải chờ nó hoàn thành. Thay vào đó chúng ta sẽ lên lịch (schedule) và các nhiệm vụ sẽ được thực hiện sau.
Chúng ta gói gọn (encapsulate) một task dưới dạng Message và gửi nó đến Queue. Một tiến trình worker chạy background sẽ lấy các task và cuối cùng thực thi chúng.
Có thể tạo nhiều worker để thực hiện các task, các task sẽ được chia sẻ giữa chúng.
Ví dụ
Trong ví dụ bên dưới, tôi sẽ tạo:
class Thread Producer có nhiệm vụ tạo các task và đưa vào Queue (RabbitMQ Broker).
class Thread Consumer (đóng vai trò như Worker) có nhiệm vụ lấy các task từ Queue về xử lý.
Sử dụng method channel.basicQos(1) : Mặc định, RabbitQM sử dụng Round-robin để gửi Message đến Consumer kế tiếp một cách tuần tự. Mỗi Consumer có thời gian xử lý mỗi task khác nhau. Để tránh một Consumer nhận quá nhiều mà không có thời gian để xử lý, một Consumer quá rãnh không có thời gian thực hiện. Chúng ta có sẽ sử dụng option basicQos() để nói với RabbitMQ rằng chỉ gửi 1 Message cho Consumer, khi nào xử lý xong hãy gửi Message kế tiếp. Nhờ vậy thời gian hoàn thành sớm hơn.
Sử dụng thuộc tính autoAck = false : Trong bài viết trước, chúng ta sử dụng thuộc tính autoAck là true khi Consumer nhận Message, thuộc tính này chỉ ra răng một ACK message sẽ được auto gửi đến RabbitMQ để báo với RabbitMQ rằng một Message đã được Consumer nhận, xử lý và Rabbit có thể xoá nó. Một vấn đề đặt ra là nếu một Consumer xử lý Task trong một thời gian dài, chỉ một phần của Task được hoàn thành và nó die. Khi đó, Message đã bị xoá bởi RabbitQM và Task sẽ bị mất. Để giải quyết vấn đề này, chúng ta sẽ không auto gửi Message, mà chúng ta sẽ gửi một ACK message đến RabbitMQ khi nó hoàn thành xử lý Message.
class App : mô phỏng việc tạo Task bởi Producer và lấy task xử lý bởi Consumer. Tôi sẽ tạo 1 Producer để tạo ra 10 Tasks và 2 Consumer để thay phiên nhau xử lý các Task được tạo bởi Producer. Một lưu ý là Consumer 1 sẽ xử lý mỗi task trong 100 milliseconds, Consumer 2 sẽ xử lý mỗi task trong 300 milliseconds. Nếu theo cơ chế Round-robin dispatching của RabbitMQ thông thường thì mỗi Consumer sẽ xử ý 5 Tasks, thời gian xử lý mỗi Task của Consumer 2 lâu hơn nên Consumer 1 sẽ rỗi rảnh trong khi Consumer 2 vẫn còn việc phải xử lý. Tuy nhiên, mình đã sử dụng basicQos() nên sẽ không có chuyện một Consumer rỗi rảnh và một Consumer có nhiều Task cần làm. Hãy xem kết quả ở chương trình bên dưới nhé.
Producer.java
package com.gpcoder;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Producer implements Runnable {
private final static String QUEUE_NAME = "gpcoder-queue";
private String name;
private int numOfMessage;
public Producer(String name, int numOfMessage) {
this.name = name;
this.numOfMessage = numOfMessage;
}
@Override
public void run() {
System.out.println("Create a ConnectionFactory for " + name);
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try ( Connection connection = factory.newConnection();
Channel channel = connection.createChannel() ) {
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println("Start sending messages ... ");
int index = 1;
while (index <= numOfMessage) {
String message = " Task #" + index++;
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] " + name + " Sent: '" + message + "'");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("Close connection and free resources");
}
}
}
Consumer.java
package com.gpcoder;
import com.rabbitmq.client.*;
public class Consumer implements Runnable {
private final static String QUEUE_NAME = "gpcoder-queue";
private int numberConsumedMessage = 0;
private String name;
private int timeToFinishATask;
public Consumer(String name, int timeToFinishATask) {
this.name = name;
this.timeToFinishATask = timeToFinishATask;
}
@Override
public void run() {
try {
System.out.println("Create a ConnectionFactory for " + name);
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
/**
* This tells RabbitMQ not to give more than one message to a worker at a time.
* Or, in other words, don't dispatch a new message to a worker
* until it has processed and acknowledged the previous one.
* Instead, it will dispatch it to the next worker that is not still busy.
*/
channel.basicQos(1);
System.out.println("Start receiving messages ... ");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] " + name + " Received: '" + message + "'");
consume(message);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
System.out.println(" [-] " + name + " Already consumed: " + (++numberConsumedMessage) + " Tasks");
};
CancelCallback cancelCallback = consumerTag -> { };
boolean autoAck = false;
String consumerTag = channel.basicConsume(QUEUE_NAME, autoAck, deliverCallback, cancelCallback);
System.out.println("Tag for " + name + ": " + consumerTag);
} catch (Exception e) {
e.printStackTrace();
}
}
private void consume(String message) {
try {
Thread.sleep(timeToFinishATask); // simulate time to produce the data
System.out.println(" [-] " + name + " Consumed for " + message + " in " + timeToFinishATask + " ms");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
App.java
package com.gpcoder;
public class App {
public static void main(String[] args) throws InterruptedException {
Producer producer1 = new Producer("[Producer 1]",10);
Consumer consumer1 = new Consumer("[Consumer 1]", 100);
Consumer consumer2 = new Consumer("[Consumer 2]", 300);
new Thread(producer1).start();
new Thread(consumer1).start();
new Thread(consumer2).start();
}
}
Output của chương trình trên:
Create a ConnectionFactory for [Producer 1]
Create a ConnectionFactory for [Consumer 2]
Create a ConnectionFactory for [Consumer 1]
Start sending messages ...
Start receiving messages ...
Start receiving messages ...
[x] [Producer 1] Sent: ' Task #1'
[x] [Producer 1] Sent: ' Task #2'
[x] [Producer 1] Sent: ' Task #3'
[x] [Producer 1] Sent: ' Task #4'
[x] [Producer 1] Sent: ' Task #5'
[x] [Producer 1] Sent: ' Task #6'
[x] [Producer 1] Sent: ' Task #7'
[x] [Producer 1] Sent: ' Task #8'
[x] [Producer 1] Sent: ' Task #9'
[x] [Producer 1] Sent: ' Task #10'
Tag for [Consumer 2]: amq.ctag-yVYxlwJ6750wJrwcMrO0nQ
Tag for [Consumer 1]: amq.ctag-RBZ-9HjR0-B_Gf2lQ0js7g
[x] [Consumer 2] Received: ' Task #2'
[x] [Consumer 1] Received: ' Task #1'
Close connection and free resources
[-] [Consumer 1] Consumed for Task #1 in 100 ms
[-] [Consumer 1] Already consumed: 1 Tasks
[x] [Consumer 1] Received: ' Task #3'
[-] [Consumer 1] Consumed for Task #3 in 100 ms
[-] [Consumer 1] Already consumed: 2 Tasks
[x] [Consumer 1] Received: ' Task #4'
[-] [Consumer 2] Consumed for Task #2 in 300 ms
[-] [Consumer 2] Already consumed: 1 Tasks
[x] [Consumer 2] Received: ' Task #5'
[-] [Consumer 1] Consumed for Task #4 in 100 ms
[-] [Consumer 1] Already consumed: 3 Tasks
[x] [Consumer 1] Received: ' Task #6'
[-] [Consumer 1] Consumed for Task #6 in 100 ms
[-] [Consumer 1] Already consumed: 4 Tasks
[x] [Consumer 1] Received: ' Task #7'
[-] [Consumer 1] Consumed for Task #7 in 100 ms
[-] [Consumer 1] Already consumed: 5 Tasks
[x] [Consumer 1] Received: ' Task #8'
[-] [Consumer 2] Consumed for Task #5 in 300 ms
[-] [Consumer 2] Already consumed: 2 Tasks
[x] [Consumer 2] Received: ' Task #9'
[-] [Consumer 1] Consumed for Task #8 in 100 ms
[-] [Consumer 1] Already consumed: 6 Tasks
[x] [Consumer 1] Received: ' Task #10'
[-] [Consumer 1] Consumed for Task #10 in 100 ms
[-] [Consumer 1] Already consumed: 7 Tasks
[-] [Consumer 2] Consumed for Task #9 in 300 ms
[-] [Consumer 2] Already consumed: 3 Tasks
Như bạn thấy, 2 Consumer cùng xử lý các công việc được tạo bởi Producer. Tuy nhiên, thời gian xử lý mỗi Task của Consumer 1 nhanh hơn Consumer 2, nên nó có thể done nhiều task hơn: Consumer 1 có thể xử lý 7 tasks, trong khi Consumer 2 chỉ xử lý 3 tasks.
Trong xã hội hiện đại ngày nay, việc đảm bảo an toàn cho từng kết nối tới thế giới đang ngày được quan tâm. Thông tin đăng nhập Facebook, các giao dịch internet banking, các email quan trọng, … đều được người dùng yêu cầu tính bảo mật cao. Có nhiều phương pháp được sử dụng để đảm bảo yêu cầu này. Ngoài các phương pháp như sử dụng SSL, truy cập mạng wifi an toàn thì VPN cũng là một phương pháp thường được sử dụng để đảm bảo an toàn thông tin. Vậy VPN là gì?.
Mời các bác cùng tìm hiểu với em qua bài viết dưới đây.
Không TROLL 🤣 – Đầu tiên, VPN là viết tắt của Virtual Private Network (mạng riêng ảo). Đối với những người không rành công nghệ, hãy hình dung khi chúng ta kết nối internet, bản thân chúng ta đang kết nối vào một đường ống rộng lớn. Vì quy mô đường ống rất lớn, nên ta không thể đảm bảo các thông tin cá nhân của chúng ta có bị hacker giòm ngó hay không?. Để cải thiện độ an toàn khi giao tiếp với thế giới internet, mạng riêng ảo (VPN) ra đời.
Với VPN, người sử dụng có thể tránh được sự dòm ngó của hackers, các tổ chức hoặc chính phủ
Mạng riêng ảo ở đây có thể hình như một đường ống (tunnel), mọi giao tiếp của chúng ta với thế giới web đều sẽ di chuyển qua đường ống này. Qua đó, tất cả các thông tin này đều tránh được bị đánh cắp (một hình thức phổ biến là Man in the middle 🧐).
2. OK, tao đã ở trong cái ống, có lợi gì không mà viết dài quá vậy mày?
“Ơ cái đ*t, từ từ chứ ba, mày mới đọc tí tẹo thế sao hiểu“,
Đấy đấy, mấy thằng blogger không có tâm sẽ trả lời như thế., riêng em, em sẽ trình bày ưu điểm của VPN như sau:
Mã hóa dữ liệu – Enhanced security
Mọi tập tin truyền nhận giữa bạn và internet đều được mã hóa. Điều này cũng giải thích tại sao sử dụng VPN thường có cảm giác chậm như rùa.
Làm việc thông qua remote – Remote control
Còn điều gì tuyệt vời hơn khi sáng thức dậy ở nhà, code rầm rầm trong khi vẫn đảm bảo yêu cầu về security của dự án. Nhờ có VPN, các thím có thể dễ dàng remote tới máy ở công ty, thoải mái làm việc mà không sợ các file code có bị một anh hacker đẹp trai (tao thẳng – ok?) nào đó dòm ngó hay không?
Chia sẻ file – Share files Sử dụng VPN, việc chuyển file sẽ có độ an toàn cao hơn. Với mình, một số dự án làm cho khách hàng Nhật. Khi commit code cho khách hàng luôn phải sử dụng VPN, cũng là dễ hiểu khi các dự án làm về kinh doanh, không ai muốn lộ bussiness model ra ngoài cả).
4 điểm mạnh của VPN (Nguồn ảnh/ Source: thebestvpn.com
Ẩn địa chỉ IP – Hide your IP
Khi sử dụng dịch vụ VPN, địa chỉ IP public của chúng ta vẫn sẽ được nhà cung cấp VPN biết, nhưng tất cả các gói tin chúng ta gửi ra internet (đầu ra tunnel) sẽ là một địa chỉ IP từ nhà cung cấp. Nhắc tới đây, một số thanh niên lại manh nha làm bậy. Xin thưa là ĐỪNG, bởi một khi các anh bên cục an ninh mạng dò ra địa chỉ IP tấn công từ VPN. Các anh sẽ nhanh như đạn bắn yêu cầu đơn vị cung cấp VPN show ra đị chỉ IP của các thím. “Ngồi đếm lịch năm” sẽ là bài các thím hát lên đấy. 😂😂😂
Vượt tường rào – Unblock websites & bypass filters Đây có vẻ như là phần anh em hào hứng. Một tính năng bonus thêm khi anh em sử dụng VPN là có thể truy cập một số trang web block theo khu vực. Ví dụ: nếu website block địa chỉ IP tới từ châu á thì khi sử Avira VPN, chọn location là Germany, các anh em có thể truy cập được.
3. Có phải VPN là thần thánh?
Câu trả lời là không!. Việc sử dụng VPN HOÀN TOÀN không giúp loại bỏ tất cả các rủi ro. Tin buồn cho các thanh niên đang sử dụng 😥.
Thực tế là các streamer rất ít khi sử dụng VPN để live stream, đơn giản là chi phí tăng cao và đôi khi hiện tượng giật lag xảy ra thường xuyên. Nguồn ảnh/ Source: limevpn.com
Ngoài các điểm mạnh, việc sử dụng cũng kèm theo không ít phiền toái và rủi ro.
3 điểm yếu của VPS
Đầu tiên, vì tất cả các file khi thực hiện kết nối hay truyền nhận đều được mã hóa nên VPN sẽ chậm. Cảm giác chậm có nhiều hay không còn tùy vào thuật toán sử dụng để mã hóa. Trường hợp sử dụng loại mã hóa cao cấp như AES hay RSA thì thời gian còn lâu hơn.
Chi phí, of course. Một số nhà cung cấp tính tiền dựa theo lưu lượng data truyền tải qua VPN. Chính vì vậy, đối với một số doanh nghiệp, sử dụng cho cả doanh nghiệp luôn là vấn đề lớn.
Mã hóa không đạt yêu cầu. Việc mã hóa ngày nay yêu cầu tối thiểu là 128 bit. Trường hợp sử dụng thấp hơn sẽ là các file bị mã hóa yếu (weak encryption), không đáng tin cậy.
Varied logging policies – đa dạng các loại thông tin được ghi log. Ngoại trừ một số VPN chui, hầu hết khi sử dụng, tất cả các nhà cung cấp VPN đều ghi log. Thông tin log ở đây bao gồm Usage logs và Connection logs. Usage logs lưu toàn bộ những gì chúng ta làm thông qua VPN, chi tiết từng hoạt động đó. Connection logs thì lưu đị chỉ IP thật, truy cập từ đâu, tên tuổi, …
4. Kết luận.
“The only truly secure system is one that is powered off, cast in a block of concrete and sealed in a lead-lined room with armed guards” Gene Spafford
“Hệ thống thực sự an toàn là khi tắt nguồn, đóng nó trong một khối bê tông ,canh giữ cẩn mật trong một căn phòng chì và tất nhiên là được bảo vệ bởi lính có vũ trang” Gene Spafford
Chính vì vậy, VPN không phải là một công cụ đảm bảo chúng ta được an toàn tuyệt đối. Có chăng nó chỉ là một công cụ an toàn, khi có nó, việc giao tiếp giữa chúng ta với internet sẽ trở nên an toàn hơn. Vẫn KHUYẾN KHÍCH sử dụng VPN cho các giao dịch quan trọng
Một số thao tác cơ bản khi sử dụng Navicat mà bạn nên biết
Bài viết được sự cho phép của blogchiasekienthuc.com
Chào các bạn, hiện nay với sự phát triển của rất nhiều hệ quản trị cơ sở dữ liệu khác nhau như MySQL, PostgreSQL, MySQL Server… thì cũng kéo theo sự ra đời của rất nhiều các ứng dụng GUI hỗ trợ cho chúng.
Có thể kể đến như MySQL Workbeach, SSMS (SQL Server Management Studio)… và rất nhiều công cụ khác nữa.
Nhưng trong nhiều trường hợp bạn phải thao tác với nhiều hệ quản trị cơ sở dữ liệu một lúc thì sao? Liệu chúng ta có thể mở một lúc vài ba phần mềm quản trị cơ sở dữ liệu khác nhau không?
Chính vì vậy mà ở trong bài viết này, mình sẽ cùng với các bạn cài đặt và tìm hiểu về Navicat – một phần mềm quản trị cơ sở dữ liệu có thể làm việc với nhiều loại cơ sở dữ liệu khác nhau.
Đầu tiên các bạn hãy tải file cài đặt tại đây: https://www.navicat.com/en/products. Các bạn lưu ý rằng Navicat có cả các phiên bản cho từng hệ quản trị cơ sở dữ liệu khác nhau nhé.
Đây là phiên bản dùng thử, nếu bạn nào có điều kiện thì có thể mua bản quyền để sử dụng lâu dài nhé. Còn không thì có thể tìm các bản Portable được chia sẻ trên mạng ha.
+ Bước 2: Cài đặt phần mềm Navicat
Các bước cài đặt thì tương đối đơn giản, đầu tiên các bạn chạy file cài đặt vừa tải về bằng cách đúp chuột vào file => Sau đó bấm Next.
Ở bước tiếp theo, các bạn tích chọn I accept the agreement => rồi tiếp tục bấm Next để sang bước tiếp theo.
Bước này các bạn hãy chọn vị trí cài đặt, mặc định thì phần mềm sẽ được cài đặt tại ổ C với đường đường dẫn như hình bên dưới (mình khuyên các bạn để mặc định nếu dung lượng ổ cứng đủ).
Tiếp tục bấm Next để sang bước tiếp theo.
Các bạn có thể tích vào Create a desktop icon để tạo một shortcut ngoài màn hình => rồi tiếp tục bấm Next để sang bước kế tiếp..
Okay, đến đây thì các bạn bấm Install là quá trình cài đặt sẽ được bắt đầu với các cấu hình bạn chọn ở các bước trước.
Okay, đến đây là quá trình cài đặt đã hoàn tất rồi đó. Các bạn bấm Finish là xong.
#2. Một số thao tác cơ bản khi sử dụng Navicat
2.1. Tạo kết nối đến cơ sở dữ liệu.
Trong bài này mình sẽ lấy ví dụ về việc kết nối đến hệ quản trị cơ sở dữ liệu MySQL. Các bạn chọn File => chọn New Connection => MySQL… như hình bên dưới.
Các thông tin bạn phải điền đó là:
Connection Name: Tên của kết nối (các bạn có thể đặt thế nào tùy thích)
Host: Nếu trên laptop hay máy tính cá nhân thì các bạn điền localhost, còn nếu ở server thì các bạn điền địa chỉ IP của server đó.
Port: Là cổng kết nối (mặc định của MySQL là 3306)
Username: Là username lúc các bạn cài đặt MySQL Server
Password: Là mật khẩu lúc các bạn cài đặt MySQL Server
Note: Các bạn có thể bấm vào Save password để ghi nhớ thông tin kết nối cho các lần sau.
Để kiểm tra kết nối các bạn có thể bấm vào Test Connection. Sau đó nếu được thì bấm OK để thực hiện kết nối đến cở sở dữ liệu.
2.2 – Chuyển đổi Database sang dạng model
Đây là một tính năng mà theo mình thấy là rất hay, nhất là trong nhiều trường hợp chúng ta muốn xem quan hệ giữa các bảng một cách trực quan.
Đầu tiên, các bạn kết nối đến cơ sở dữ liệu. Sau đó chuột phải vào cơ sở dữ liệu các bạn muốn chuyển đổi => Reverse Database to Model… như hình bên dưới.
Với cơ sở dữ liệu mẫu của mình thì đây chính là Database Model sau khi được chuyển đổi. Khi nhìn vào thiết kế này chúng ta sẽ dễ dàng hình dung được mối quan hệ giữa các bảng.
2.3 – Export dữ liệu thành Script File
Trong nhiều trường hợp chúng ta phải kết xuất dữ liệu thành file để Import vào một cơ sở dữ liệu khác. Và tất nhiên, một phần mềm bản quyền như Navicat thì cũng hỗ trợ chúng ta điểm này luôn.
Các bạn chọn: Table => Export Wizard… để Export toàn bộ dữ liệu của tất cả các bảng. Hoặc làm tương tự với từng bảng cũng được.
Navicat hỗ trợ Export dữ liệu thành rất nhiều định dạng (loại file) khác nhau, phù hợp với nhiều loại cơ sở dữ liệu khác nhau.
Trong bài viết này mình chọn SQL script file để có thể Import biên dịch dễ dàng từ các phần mềm quản trị cơ sở dữ liệu khác.
Tiếp theo, các bạn có thể chọn các bảng sẽ được Export dữ liệu và chọn Export ra một file hay nhiều file như hình bên dưới.
Ở bước này các bạn tiếp tục bấm Next để sang bước tiếp theo.
Tiếp tục bấm Next để sang bước tiếp theo.
Ở bước này, các bạn bấm Start để bắt đầu quá trình Export dữ liệu. Tùy vào dung lượng dữ liệu trong cơ sở dữ liệu của các bạn mà quá trình Export này có thể nhanh hay chậm.
Okay, như này là quá trình Export đã hoàn tất rồi đó. Các bạn có thể mở file Script vừa được Export ra để kiểm tra và đem đi Import vào một cơ sở dữ liệu khác.
2.4 – Viết SQL Script
SQL Script là một đoạn lệnh được dùng để thực thi một hoặc nhiều các truy vấn đến cơ sở dữ liệu.
Để có thể viết một câu SQL thì các bạn có thể chọn New Query. Một tab mới sẽ được mở ra và các bạn có thể viết câu lệnh SQL ở đó => rồi bấm Run để chạy lệnh đó.
Bên dưới sẽ là kết quả của câu truy vấn nếu đó là một câu truy vấn đúng.
#3. Kết luận
Vậy là trong bài viết này mình đã cùng các bạn cài đặt Navicat và tìm hiểu về cách sử dụng của một số tính năng cơ bản của Navicat rồi nhé. Đây thực sự là một công cụ rất hay khi giúp chúng ta có thể thao tác với nhiều loại cơ sở dữ liệu khác nhau.
Không những thế, Navicat cũng là công cụ được sử dụng rất nhiều trong các doanh nghiệp, nên việc tiếp cận và sử dụng thành thạo công cụ này sẽ giúp các bạn không bị bỡ ngỡ khi làm việc thực tế.
Hi vọng là bài viết này sẽ hữu ích vớ bạn. Hẹn gặp lại các bạn trong các bài viết tiếp theo nha !
Bài viết được sự cho phép của tác giả Kien Dang Chung
Một website hấp dẫn người xem phải có giao diện đẹp và có sự tương tác qua lại. Bạn hãy tưởng tượng một cô gái xinh đẹp nhưng hỏi gì cũng không biết, chạm vào không có phản ứng thì không gây cảm hứng cho người đối diện. Như vậy, tương tác là một yếu tố rất quan trọng, khéo léo bố trí các tương tác bạn vừa có thể khai thác được thông tin người dùng tối đa, vừa giúp cho họ tìm được những thông tin phù hợp, giữ người dùng ở lại với website lâu hơn và đồng nghĩa với lợi nhuận cao hơn.
Xem thêm nhiều chương trình tuyển dụng VueJS hấp dẫn trên TopDev
Vue.js giúp bạn xử lý các sự kiện, tương tác với người dùng rất dễ dàng thông qua câu lệnh v-on. Câu lệnh này có thể kiểm soát tất cả các sự kiện có thể xảy ra với một phần tử HTML như nhấp chuột, gõ phím… Cuối bài viết chúng ta sẽ cùng nhau xây dựng một ứng dụng máy tính bỏ túi đơn giản như dưới đây:
Sự kiện trong HTML là những gì xảy ra với các thẻ HTML, Vue.js là một bộ máy biên dịch mà kết quả cuối cùng là HTML, CSS và Javascript đơn thuần, do vậy Vue.js hoàn toàn có thể tương tác với các sự kiện của HTML. Có rất nhiều các sự kiện xảy ra khi người dùng làm một việc gì đó trên trang web:
Sự kiện tải trang web xảy ra khi người dùng nhập đường dẫn vào một trình duyệt web.
Sự kiện giá trị ô nhập liệu thay đổi khi người dùng thêm vào văn bản.
Một nút được nhấn cũng phát sinh sự kiện
Sự kiện một form đăng ký thông tin được gửi đi.
…
Trong framework Vue.js, để “lắng nghe” các sự kiện trên DOM (các thẻ HTML), bạn có thể sử dụng câu lệnh v-on với cú pháp:
v-on:tên_sự_kiện="mã_xử_lý_sự_kiện"
Có rất nhiều sự kiện trong HTML, chúng ta có thể tạm chia thành các nhóm sự kiện như sau:
Nhóm sự kiện liên quan đến trình duyệt như onload, onresize…
Nhóm sự kiện liên quan đến form: onsubmit, onchange, onblur…
Sự kiện liên quan đến bàn phím: onkeyup, onkeydown, onkeypress
Sự kiện liên quan đến chuột: onlick, onmouseover, onwheel…
…
Các sự kiện này khi sử dụng với v-on chúng ta bỏ đi tiền tố “on” ở đầu, ví dụ khi sử dụng v-on để quản lý sự kiện nhấp chuột chúng ta dùng v-on:click, khi sử dụng v-on với sự kiện gửi dữ liệu đi trong form (onsubmit) cú pháp là v-on:submit.
Mã xử lý sự kiện là mã viết bằng ngôn ngữ Javascript (hiện nay thường gọi là ECMAScript hay ES với phiên bản thường dùng hiện nay là ES5, ES6). Đoạn mã này có thể ở dạng inline, tức là nhồi toàn bộ code vào một dòng hoặc cũng có thể là lời gọi đến một phương thức.
1.1 Mã xử lý sự kiện inline
Đôi khi mã xử lý sự kiện rất đơn giản và không cần phải sử dụng lại, bạn có thể viết kiểu inline cho nhanh chóng. Ví dụ dưới đây chúng ta cùng xây dựng nút like cho bài viết, mỗi lần bấm nút like nó sẽ hiển thị số lượng like tăng thêm 1.
<!DOCTYPE html><html><head><title>Quản lý sự kiện với v-on Vuejs - Allaravel.com</title><link rel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"></head><body><div class="container"id="app"><div class="row"><div class="col-md-12"><h1>Quản lý sự kiện dễ dàng với v-on Vue.js</h1></div></div><div class="row"><div class="col-md-12"><p>
Một website hấp dẫn người xem phải có giao diện đẹp và có sự tương tác qua lại. Bạn hãy tưởng tượng một cô gái xinh đẹp nhưng hỏi gì cũng không biết, chạm vào không có phản ứng thì không gây cảm hứng cho người đối diện. Như vậy, tương tác là một yếu tố rất quan trọng, khéo léo bố trí các tương tác bạn vừa có thể khai thác được thông tin người dùng tối đa, vừa giúp cho họ tìm được những thông tin phù hợp, giữ người dùng ở lại với website lâu hơn và đồng nghĩa với lợi nhuận cao hơn.
</p></div></div><div class="row"><div class="col-md-12"><button type="button"class="btn btn-outline-primary"v-on:click="likes++"><i class="far fa-thumbs-up"></i> Thích <span class="badge badge-pill badge-primary">{{ likes }}</span></button></div></div></div><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script><script src="https://use.fontawesome.com/releases/v5.0.9/js/all.js"></script><script type="text/javascript">newVue({
el:'#app',
data:{
likes:9}})</script></body></html>
Trong ví dụ trên, chúng ta đã quản lý sự kiện nhấp vào nút “Thích” bằng đoạn mã:
Khi sự kiện nhấp chuột xảy ra, biến likes được cộng thêm 1, do việc cộng thêm 1 khá đơn giản chúng ta không cần dùng lời gọi phương thức mà đưa mã xử lý vào trong cùng câu lệnh v-on, do vậy có tên là inline. Giá trị biến likes được in ra bằng cú pháp biểu thức {{ }} mà chúng ta đã được làm quen trong Cú pháp câu lệnh trong Vue.js.
1.2 Sử dụng lời gọi phương thức trong code quản lý sự kiện
Code xử lý sự kiện trong v-on có giới hạn là một câu lệnh, như vậy chúng ta không thể đưa nhiều dòng lệnh inline vào v-on. Như vậy, nếu bạn muốn khi sự kiện xảy ra, thực hiện những công việc phức tạp thì giải pháp sử dụng lời gọi đến phương thức là lựa chọn duy nhất. Trong ví dụ ở trên, chúng ta muốn mỗi lần nhấp vào nút Thích phải cách nhau 10 giây nếu không sẽ hiển thị một thông báo.
<!DOCTYPE html><html><head><title>Quản lý sự kiện với v-on Vuejs - Allaravel.com</title><link rel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"></head><body><div class="container"id="app"><div class="row"><div class="col-md-12"><h1>Quản lý sự kiện dễ dàng với v-on Vue.js</h1></div></div><div class="row"><div class="col-md-12"><p>
Một website hấp dẫn người xem phải có giao diện đẹp và có sự tương tác qua lại. Bạn hãy tưởng tượng một cô gái xinh đẹp nhưng hỏi gì cũng không biết, chạm vào không có phản ứng thì không gây cảm hứng cho người đối diện. Như vậy, tương tác là một yếu tố rất quan trọng, khéo léo bố trí các tương tác bạn vừa có thể khai thác được thông tin người dùng tối đa, vừa giúp cho họ tìm được những thông tin phù hợp, giữ người dùng ở lại với website lâu hơn và đồng nghĩa với lợi nhuận cao hơn.
</p></div></div><div class="row"><div class="col-md-12"><div class="alert alert-danger"role="alert"v-if="alert">
Chỉ được thêm like sau 10 giây
</div><button type="button"class="btn btn-outline-primary"v-on:click="like"><i class="far fa-thumbs-up"></i> Thích <span class="badge badge-pill badge-primary">{{ likes }}</span></button></div></div></div><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script><script src="https://use.fontawesome.com/releases/v5.0.9/js/all.js"></script><script src="https://momentjs.com/downloads/moment.js"></script><script type="text/javascript">newVue({
el:'#app',
data:{
likes:9,
lastClickTime:null,
alert:false},
methods:{
like:function(){if(this.lastClickTime ===null||moment().diff(moment(this.lastClickTime),'seconds')>10){this.likes ++;this.lastClickTime =moment().format();this.alert =false}else{this.alert =true;}}}})</script></body></html>
Trong đoạn code trên có một số vấn đề có lẽ bạn sẽ chưa rõ hiểu rõ nhưng đừng quá lo lắng vì có một số kiến thức chúng ta sẽ được làm quen ở các phần tiếp theo. Trong khuôn khổ bài viết sẽ cố gắng trình bày các thông tin cơ bản nhất. Thứ nhất, đoạn mã v-on:click ở phần 1.1 đã được thay thế bằng một lời gọi phương thức like() thay vì sử dụng câu lệnh inline.
<div class="alert alert-danger"role="alert"v-if="alert">
Chỉ được thêm like sau 10 giây
</div><button type="button"class="btn btn-outline-primary"v-on:click="like"><i class="far fa-thumbs-up"></i> Thích <span class="badge badge-pill badge-primary">{{ likes }}</span></button>
Thông báo “Chỉ được thêm like sau 10 giây” có sử dụng cú pháp điều kiện v-if, nếu biến alert có giá trị là true thì thông báo này sẽ được hiển thị. Thứ hai, chúng ta thấy xuất hiện một phương thức like() được khai báo trong thuộc tính methods của Vue instance. Vậy Vue instance là gì, thuộc tính methods của Vue sử dụng như thế nào? Tạm thời, khi cần một phương thức như trong Javascript đơn thuần, chúng ta sẽ khai báo trong thuộc tính methods của Vue, cụ thể cách dùng thế nào sẽ có một bài viết riêng cho vấn đề này.
Khi tham chiếu đến các biến được khai báo trong thuộc tính data của Vue, chúng ta sử dụng this. Chúng ta có 3 biến likes để lưu giữ số like hiện tại, lastClickTime chứa thời gian nhấp chuột được like sau cùng, alert là true sẽ hiển thị thông báo, mặc định là false.
Thứ ba, chúng ta sử dụng thêm một thư viện ngoài là moment.js, đây là một thư viện rất mạnh về xử lý thời gian nó giống như thư viện Carbon chúng ta hay dùng trong Laravel vậy.
1.3 Viết tắt khi sử dụng v-on
Vue.js cho phép bạn viết tắt cú pháp v-on:tên_sự_kiện thành :tên_sự_kiện. Ví dụ
Cách viết này giúp bạn đỡ phải gõ code nhiều và code nhìn trông cũng đỡ rối rắm hơn, nhất là với các dự án sử dụng framework Vue.js có số lượng code lớn. Chú ý, khi mới làm quen với Vue.js có thể bạn sẽ nhầm sang cách viết tắt :click do v-bind:thuộc_tính được viết tắt thành :thuộc_tính.
2. Thay đổi sự kiện gốc
Nếu bạn đã làm việc nhiều với Javascript hẳn bạn sẽ biết phương thức preventDefault() của đối tượng event. Phương thức này sẽ hủy bỏ sự kiện nếu có thể, tức là hành động mặc định của phần tử HTML sẽ không xảy ra. Chúng ta cùng xem ví dụ sau, thẻ <a> là một liên kết, khi bạn nhấp chuột vào liên kết này trình duyệt sẽ đưa bạn đến trang web có URL được thiết lập trong thẻ <a> đó. Tuy nhiên, vì lý do nào đó chúng ta muốn khi nhấp vào liên kết này sẽ hiển thị một cảnh báo thay vì chuyển sang trang, preventDefault() sẽ giúp bạn.
Với Vue.js bạn hoàn toàn có thể sử dụng các phương thức kiểu như preventDefault(), stopPropagation()… bên trong các sự kiện tuy nhiên sẽ tốt hơn nếu v-on hỗ trợ cú pháp sử dụng các tính năng tương tự, nó giúp cho tường minh và hợp logic hơn. Rất may, Vue.js cũng đã quan tâm đến điều này và nó đưa ra cú pháp để thực hiện thay đổi sự kiện như sau v-on:tên_sự_kiện.phương_thức_thay_đổi_sự_kiện. Trong Vue.js có các phương thức để thay đổi sự kiện gốc như sau:
.stop
.prevent
.capture
.self
.once
Ví dụ thuần Javascript ở trên có thể được viết lại như sau trong Vue.js
<!DOCTYPE html><html><head><title>Quản lý sự kiện với v-on Vuejs - Allaravel.com</title><link rel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"></head><body><div class="container"id="app"><div class="row"><div class="col-md-12"><a href="https://allaravel.com/tutorials/vuejs-framework/khoa-hoc-vue-js-2-mien-phi/" @click.prevent="courseClick">Khóa học Vue.js miễn phí</a></div><div class="col-md-12"v-if="show"><div class="list-group"><a :href="tut.url"class="list-group-item"v-for="tut in tutorials"target="_blank">{{ tut.title }}</a></div></div><div class="col-md-12"><a href="https://allaravel.com/tutorials/vuejs-framework/khoa-hoc-vue-js-2-mien-phi/"target="_blank">Khóa học Vue.js miễn phí</a></div></div><div class="row"><div class="col-md-12"><p>Thay đổi sự kiện gốc trong Vue.js, cũng là thẻ a bạn hãy nhấp thử hai liên kết trên để trải nghiệm</p></div></div></div><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script><script type="text/javascript">newVue({
el:'#app',
data:{
show:false,
tutorials:[{title:'1.1 Giới thiệu framework Vue.js', url:'https://allaravel.com/tutorials/vuejs-framework/gioi-thieu-framework-vue-js/'},{title:'1.2 Cài đặt môi trường Vue.js', url:'https://allaravel.com/tutorials/vuejs-framework/cai-dat-moi-truong-vue-js/'},{title:'1.3 Công cụ sử dụng trong phát triển Vue.js', url:'https://allaravel.com/tutorials/vuejs-framework/cong-cu-su-dung-trong-phat-trien-vue-js/'},{title:'2.1 Cú pháp câu lệnh', url:'https://allaravel.com/tutorials/vuejs-framework/mau-cu-phap-cau-lenh-trong-vue-js/'},{title:'2.2 Cú pháp điều kiện v-if, v-show', url:'https://allaravel.com/tutorials/vuejs-framework/cau-lenh-dieu-kien-v-if-va-v-show/'},]},
methods:{
courseClick:function(){this.show =!this.show;}}})</script></body></html>
Trong ví dụ này, khi quản lý sự kiện click vào thẻ a, chúng ta đã sử dụng phương thức ngăn chặn sự kiện xảy ra .prevent.
<a href="https://allaravel.com/tutorials/vuejs-framework/khoa-hoc-vue-js-2-mien-phi/" @click.prevent="courseClick">Khóa học Vue.js miễn phí</a>
3. Thay đổi hoạt động bàn phím, chuột
Trong ứng dụng web của bạn, đôi bạn muốn thay đổi cách hành xử khi một phím được nhấn. Ví dụ, trên một form khi bạn nhấn Enter thì dữ liệu form sẽ được gửi đi (submit) hoặc khi bạn nhấn PageUp, PageDown trình duyệt sẽ cuộn cả nội dung trang nhưng bạn lại muốn chỉ cuộn nội dung phần danh sách ảnh trong trang… Vue.js cho phép bạn thay đổi cách hành xử các phím trên bàn phím hoặc chuột được nhấn. Cú pháp quản lý hoạt động của bàn phím như sau:
Trong ví dụ trên 13 là mã của phím enter, khi bấm enter form sẽ được submit. Ngoài ra chúng ta có thể sử dụng tên phím thay cho mã phím:
<input type="button"v-on:keyup.enter="submit">
Danh sách một số tên phím được định nghĩa sẵn:
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
Với các phím của chuột, chúng ta có danh sách sau:
.left
.right
.middle
Chúng ta có thể tổ hợp các phím với nhau, ví dụ khi ấn Ctrl + F1 trên phần tử HTML nào đó sẽ hiển thị hướng dẫn về phần tử đó.
<p v-on:keyup.ctrl.112="showHelp">
112 là mã của phím F1. Trong ví dụ này, nếu bạn nhấn tổ hợp nhiều phím mà có chứa Ctrl + F1 thì v-on:keyup vẫn hoạt động, để có thể quản lý chính xác phím hoặc tổ hợp phím sử dụng .exact.
<p v-on:keyup.exact.ctrl.112="showHelp">
4. Bài tập
Các kiến thức quản lý sự kiện với v-on trong Vue.js là khá nhiều nhưng cũng rất đơn giản. Bạn hãy thực hành thật nhiều các ví dụ trong bài và hoàn thành bài tập sau đây, tôi tin chắc bạn sẽ nắm vững những gì được trình bày trong bài viết này. Phần bài tập tiếp theo sẽ cần vận dụng khá nhiều các kiến thức khác nhau, hãy cố gắng hoàn thành nhé.
Viết một ứng dụng web dạng máy tính bỏ túi với tính năng cộng trừ nhân chia cơ bản.
Phần 1: Xây dựng giao diện Giao diện được xây dựng dựa trên framework CSS Bootstrap dạng lưới, mỗi nút trên máy tính bỏ túi là một thẻ div có kích thước bằng 1 ô trong lưới 12 ô. Bạn nên tìm hiểu về framework Bootstrap vì hiện nay có rất nhiều các giao diện web được xây dựng dựa trên nó.
Phần 2: Quản lý sự kiện khi bấm thành phần của số.
Chúng ta xây dựng một phương thức inputNumber() để nhập các thành phần của một số bao gồm các số từ 0 đến 9 và dấu chấm (.) cho các số thập phân. Đầu vào của phương thức inputNumber() chính là thành phần của số cần tính toán.
Nếu số hiện tại đã có phần thập phân thì bấm vào nút thập phân sẽ không thêm dấu thập phân nữa. Khi bấm các nút số thì nó thêm số đó vào chuỗi số. Phần 3: Quản lý sự kiện khi bấm các nút liên quan đến tính toán Chúng ta có một số toán tử cơ bản trong máy tính bỏ túi là:
cộng hai số
trừ hai số
x nhân
/ chia
i đảo dấu
% tính phần trăm
= tính toán kết quả cuối cùng
Phương thức calculate() sẽ thực hiện tính toán. Trong phương thức này, chúng ta sử dụng hàm eval() của Javascript để thực hiện tính toán một biểu thức ở dạng chuỗi.
Phần 5: Nâng cao Bài tập này có hai phần có thể mở rộng:
Xây dựng máy tính bỏ túi khoa học có thể tính toán sin, cos, giải các phương trình cơ bản…
Nâng cao khả năng nhập bằng bàn phím.
5. Kết luận
Qua bài viết chúng ta đã nắm bắt được cách quản lý sự kiện trong Vue.js với câu lệnh v-on. Xây dựng ứng dụng bằng framework Vue.js thật đơn giản, tính logic chặt chẽ, code gọn gàng, khoa học. Bạn đã cùng với chúng tôi đi được gần hết các phần câu lệnh cơ bản, chỉ với những kiến thức đơn giản này, bạn đã có thể xây dựng được những ứng dụng nhỏ hữu ích. Bạn bắt đầu thấy mê Vue.js rồi phải không, rất nhiều bài viết của sẽ được xuất bản trong thời gian tới. Hãy đón xem và có bất kỳ câu hỏi nào đừng ngại, comment ở cuối bài nhé.
Tạo thư viện bằng Swift Package Manager trong Xcode
Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh
Thường thì dev iOS chúng ta đều đã biết về CocoaPods và Carthage. Hôm nay mình sẽ giới thiệu tới các bạn một thế lực mới được Apple công bố tại WDDC 2019 là Swift Package Manager. Chúng ta đi vào từng nội dung chính thôi nào.
I. Swift Package Manger là gì ?
Swift Packager Manager là một công cụ giúp quản lý việc phân phối mã nguồn, giúp cho việc chia sẻ và dùng lại code được dễ dàng. Được Apple tích hợp từ Xcode 11 giúp cho việc chúng ta quản lí dependency một cách đơn giản hơn. Mình chỉ nói sơ qua còn các bạn tìm đọc thêm ở https://swift.org/package-manager nhé.
II. Demo project và hướng dẫn sử dụng Swift Package Manager
Đầu tiên mình sẽ tạo package kế thừa UITextField giúp format string về VNĐ ( chắc hẳn nhiều dev sẽ cần điều này)
Mở Xcode ➞ File ➞ New ➞ Swift Package
chọn tên của Package như trên là “VNDTextField” ở đây chúng ta đã tạo được Swift Package
Sau khi tạo xong, chúng ta vào file package và sẽ tiến hành config trong như sau:
Ở đây chúng ta chú ý:
products đây là phần định nghĩa chúng ta có thể thấy các file của package khi dùng vào project khác
platforms chúng ta thêm tham số vào cho hệ điều hành mình muốn build
Sau khi chỉnh sửa và setup file xong chúng ta tiến hành push code lên GitHub, và sau đó import lại cho project mà bạn muốn sử dụng. Đơn giản phải không nào !
1.Đầu tiên chúng ta nhấn chuột vào fiel .xcodeproj -> chọn Swift Packager, chúng ta sẽ có như hình, ở đây mình đã thêm package mình vào project demo.
2. Sau đó chúng ta nhấm vào dấu cộng(+) ở góc trái phía dưới để thêm package bạn muốn vào project, còn nếu muốn xóa package mà bạn đang sử dụng thì nhấn vào dấu trừ(-) nhé. Đây là lúc chúng ta bấm dấu +
Ở đây bạn paste vào link package của bạn đã tạo trên github, chờ đợi trong vài giây chúng ta sẽ có kết quả như mình đây:
Mình đã thêm package VNDTextField vào class của mình, và sử dụng lại nó như sau:
Đây là class mình demo sử dụng lại VNDTextField. Chúng ta cần import lại package ở class mình muốn sử dụng, sau đó bạn có thể sử dụng thoải những gì package cung cấp. Sau khi sử dụng VNDTextField đây là kết quả mà mình đạt được.
Thật đơn giản, với Swift Packager bạn có thể tự custom cho mình những class common, tái sử dụng lại nhiều lần, giúp giảm chí phí build lại từ đầu, dynamic hơn. Đồng thời cũng dễ dàng cho bạn thoải sức custom và mong muốn nhiều người sử dụng lại dễ dàng. Từ nay việc sử dụng 1 third party hay class common đã trở nên dễ dàng hơn rất nhiều.
Qua bài viết, hi vọng các bạn có cái nhìn cơ bản về cách tạo Swift Packager và sử dụng lại nó. Đồng thời cũng thêm vào bộ kĩ năng dev iOS của càng bạn trên hành trang fix bug. Hi vọng các bạn yêu thích bài viết này
Diễn ra ba ngày liên tiếp 25 – 27/08/2021, sự kiện công nghệ lớn nhất trong lĩnh vực Mobile chính thức trở lại cùng nhiều điểm nổi bật & chương trình quà tặng hấp dẫn cho người tham dự.
MOBILE TECH – Ba ngày với hơn 15 chủ đề
Sự kiện công nghệ Vietnam Mobile Day trở lại dưới hình thức Online Event, tổ chức công khai, không thu phí và diễn ra trong 3 ngày liên tiếp từ ngày 25 – 27/08/2021 cùng nhiều chương trình quà tặng hấp dẫn khác.
Sự kiện hướng đến những người làm & đam mê trong lĩnh vực lập trình, kinh doanh, công nghệ. Nội dung dự kiến của sự kiện năm nay có thể kể đến các lĩnh vực và từ khóa như:
Mobile Marketing:#DataDriven #AppGrowth #Privacy #DataPower #OnlineBehavior
Mobile Business:#mCommerce #eCommerce #Phonosapiens
Sự kiện năm nay với tên gọi chính thức: Vietnam Mobile Day 2021 – Intelligent Touch
INTELLIGENT TOUCH – Những ‘cú chạm’ thông minh trong kỷ nguyên di động
Trong bối cảnh công nghệ liên tục cải tiến và đổi mới, cùng với sự xuất hiện của 5G và những đột phá mà trí tuệ nhân tạo (AI) mang đến, đặc biệt bên cạnh sự phổ biến của các thiết bị di động cùng nhiều công nghệ khác (blockchain, cloud, AR/VR, IoT…), tất cả đã tạo ra một cơ hội lớn cho sự phát triển của công nghệ di động (Mobile Technology), trong một kỷ nguyên mới mang tên “kỷ nguyên di động”.
Tận dụng xu thế này, nhiều mô hình kinh doanh và dịch vụ mới ra đời. Các doanh nghiệp ứng dụng sức mạnh của công nghệ để thấu hiểu và chạm đến người dùng thông qua sức mạnh của dữ liệu (Data Power). Đồng thời, chính sự phát triển của công nghệ cũng tạo ra động lực lớn lên các doanh nghiệp truyền thống dẫn đến câu chuyện về “chuyển đổi” trong vận hành và kinh doanh (Digital Transformation).
Thông qua các hệ thống công nghệ và thiết bị di động, doanh nghiệp và người dùng liệu có thể kết nối và hiểu nhau hơn thông qua những cái chạm trên các màn hình cảm ứng? Đội ngũ cần nắm vững những kiến thức, công nghệ nào từ năm 2021 để giúp doanh nghiệp đạt được mục tiêu của mình?
Development: Xu hướng phát triển ứng dụng & hệ thống công nghệ trong doanh nghiệp trong thời đại mới để gia tăng tính cạnh tranh.
Business: Doanh nghiệp cần làm gì để hiểu người dùng và đưa ra chiến lược kinh doanh đúng đắn? Lựa chọn công nghệ nào và triển khai thế nào?
Marketing: Làm sao để người dùng biết đến, sử dụng và trung thành với sản phẩm, dịch vụ thông qua thiết bị di động?
Trong sự kiện năm nay, Vietnam Mobile Day 2021 – Intelligent Touch với hơn 15 chủ đề được livestream trực tiếp, liên tiếp ba ngày từ ngày 28 – 30/07/2021, tập trung vào những câu chuyện kể trên, thông qua 3 nhóm chủ đề (theme):
Rise of Mobile Technologies: Innovate Your Future
Mobile Commerce Revolution: Transform Your Business
Những Kinh Nghiệm Phỏng Vấn Hữu Ích Cho Sinh Viên Mới Ra Trường
Phỏng vấn là một cơ hội quan trọng để ứng viên có thể trực tiếp trao đổi thông tin với nhà tuyển dụng và nâng cao giá trị năng lực của mình. Nếu thật sự muốn được thông qua buổi phỏng vấn và tìm được công việc mới, bạn phải dành nhiều tâm sức và thời gian để đầu tư và trau dồi các lưu ý khi phỏng vấn. Do đó với các sinh viên mới ra trường, trau dồi kỹ năng phỏng vấn ngay từ bây giờ càng là điều quan trọng. Cùng tìm hiểu những kỹ năng xin việc cho sinh viên mới ra trường với bài viết này cũng TopDebv nhé!
Những vấn đề cần chuẩn bị trước khi bắt đầu buổi phỏng vấn cho sinh viên mới ra trường
Để buổi phỏng vấn có thể diễn ra suôn sẻ và đạt được kỳ vọng, việc chuẩn bị và checklist ra những vấn đề quan trọng là rất cần thiết.
Tìm hiểu các thông tin cơ bản về công ty ứng tuyển
Đây chắc chắn là thao tác cần thiết nếu bạn muốn thể hiện sự tâm huyết của mình với vị trí đang ứng tuyển. Việc tìm hiểu trước các thông tin của công ty như sứ mệnh phát triển, mục tiêu kinh doanh và các sản phẩm sẽ giúp bạn linh hoạt hơn trong quá trình trao đổi thông tin. Bên cạnh đó, nó cũng giúp cho nhà tuyển dụng thấy rằng bạn đã dành thời gian để nghiên cứu về công ty và nắm được vấn đề một cách cơ bản nhất.
Đây chắc chắn là phần không thể thiếu đối với bất cứ cuộc phỏng vấn nào. Nhà tuyển dụng sẽ khai thác kiến thức chuyên môn của bạn với công việc này thông qua một số câu hỏi hoặc các tình huống cần giải quyết. Do đó, bạn nên xem qua về những kiến thức căn bản liên quan đến vị trí mình ứng tuyển để không bị bối rối khi được hỏi. Nếu có thời gian bạn có thể tham khảo thêm một số vấn đề tình huống thường gặp ở công việc chuyên môn của mình để khi được hỏi, có thể xử trí một cách dễ dàn và chuyên nghiệp hơn.
Ứng viên nên chuẩn bị một bản cứng CV để có thể sử dụng trong trường hợp cần thiết. Đa phần các nhà tuyển dụng sẽ tự chuẩn bị CV và xem qua trước buổi phỏng vấn. Tuy nhiên để chuẩn bị cho mọi tình huống có thể xảy ra thì tốt hơn hết bạn vẫn nên có một bản CV mang theo để gây ấn tượng với nhà tuyển dụng. Việc chuẩn bị đầy đủ các loại giấy tờ cũng cho thấy bạn là người chu đáo và cẩn thận hơn.
Mang CV và các giấy tờ cần thiết cho buổi phỏng vấn
Trang phục tươm tất và đúng giờ
Đây chính là hai yếu tố cực kỳ quan trọng mà bất cứ ai cũng không nên bỏ qua để gây ấn tượng với nhà tuyển dụng. Hãy chuẩn bị những bộ quần áo lịch sự, tươm tất và sạch sẽ để có tạo thiện cảm trong mắt nhà tuyển dụng. Đừng nên ăn mặc quá se sua nhưng cũng không nên ăn mặc quá tùy tiện vì nó sẽ khiến bạn trở nên kém chuyên nghiệp hơn. Tốt hơn hết bạn nên mặc trang phục công sở lịch sự, vì vẫn chưa biết văn hóa làm việc và ăn mặc ở trang phục đó như thế nào.
Đừng bao giờ đi muộn. Rất nhiều nhà tuyển dụng đã chia sẻ rằng họ đánh rớt ứng viên dù ứng viên thể hiện rất tốt trong buổi phỏng vấn vì họ không đúng giờ. Đặc biệt đối với các công ty có văn hóa nước ngoài, yếu tố này càng được yêu cầu cao hơn. Hãy sắp xếp đi sớm hơn so với thời gian phỏng vấn từ 10 – 30 phút để đề phòng có thể xảy ra vấn đề kẹt xe hay xe hỏng,…
Những kinh nghiệm phỏng vấn cho Junior Developer hay ho
Với những sinh viên công nghệ thông tin vừa ra trường, việc phỏng vấn vào các vị trí liên quan Junior Developer sẽ được chia sẻ trong phần này.
Thể hiện đam mê của bản thân với công việc
Khi nhắc đến đam mê với công việc chúng ta thường nghĩ đến những vấn đề lớn lao và trừu tượng. Đặc biệt là đối với các junior developer, hoặc những lập trình viên không có kỹ năng giao tiếp tốt thì đây dường như sẽ là trở ngại lớn để thể hiện đam mê của mình với công việc. Vậy nên làm thế nào để thuyết phục nhà tuyển dụng?
Hãy tận dụng nó thông qua những câu hỏi tương tự như “Tại sao bạn muốn trở thành lập trình viên?” – đây chính xác là câu hỏi để bạn thể hiện đam mê với công việc đúng không? Hãy cho nhà tuyển dụng thấy sự hào hứng và nhiệt huyết của bạn với việc lập trình, coding hay các xu hướng công nghệ thông tin mới nhất. Ngắn gọn, rõ ràng nhưng thành thật và đúng trọng tâm chắc chắn sẽ giúp bạn ghi điểm trong mắt nhà tuyển dụng.
Việc tạo dựng hình ảnh là một yếu tố rất quan trọng và là kinh nghiệm phỏng vấn cho junior developer được nhiều người đánh giá cao. Hãy thể hiện những dự án nổi trội nhất mà bạn đã từng thực hiện trong CV để nhà tuyển dụng có thể khai thác và tìm tòi nhiều hơn về kỹ năng của bạn. Lúc đó bạn có thể tự tin chia sẻ về những gì bạn có, những gì bạn đã học hỏi được cũng như những gì bạn mong muốn đạt được trong thời gian tới.
Bên cạnh đó, hãy tận dụng các nền tảng mạng xã hội cũng như các nền tảng tuyển dụng để chia sẻ về những gì bạn đã làm được. Đây cũng được xem là yếu tố quan trọng để nhà tuyển dụng có cái nhìn và đánh giá tổng quan nhất về bạn. Câu hỏi phỏng vấn phổ biến liên quan đến vấn đề này mà bạn có thể gặp đó là “Dự án nào đã từng tham gia khiến bạn tâm đắc nhất? Bạn đã đóng góp và học hỏi được gì từ dự án đó?” Hãy chia sẻ thành thật với nhà tuyển dụng về những trải nghiệm của bạn, đó là bí quyết để bạn ghi điểm với người phỏng vấn.
Hãy luyện tập coding thường xuyên hơn
Rõ ràng mục đích cuối cùng mà nhà tuyển dụng cần ở bạn vẫn là kỹ năng làm việc. Rất nhiều junior developers lại thường bỏ qua bước này mà quên rằng luyện tập coding thường xuyên chính là cách duy nhất để bạn nâng trình chuyên môn của bản thân. Hãy nhớ rằng bạn sẽ không thể biết hết được tất cả mọi thứ, mà công nghệ thông tin lại là lĩnh vực được cập nhật thông tin mỗi giờ, mỗi ngày. Nếu không chịu khó bỏ thời gian để học hỏi, việc thành công hay đạt được những thành tựu đáng kể trong lĩnh vực này gần như là rất khó khăn.
Hãy chịu khó đầu tư nhiều hơn để luyện tập viết code, đó cũng là kinh nghiệm để bạn chinh phục nhà tuyển dụng trong quá trình phỏng vấn. Thậm chí, bạn có thể chia sẻ với họ những chương trình hay những dự án cá nhân bạn đã đạt được để chứng minh kỹ năng làm việc của mình. Một điều cần lưu ý là hãy chia sẻ những gì bạn đã thật sự làm việc được và đừng tâng bốc bản thân quá đà vì nhà tuyển dụng đều là những người đã dày dặn kinh nghiệm, họ sẽ dễ dàng nhận ra và đánh giá được năng lực của bạn mà thôi.
Công việc lập trình luôn đòi hỏi rất nhiều yếu tố kỹ năng và chuyên môn, điều quan trọng là bạn cần thể hiện được tinh thần và thái độ cầu tiến trong công việc, không ngại khó ngại khổ, đó chính là con đường của một lập trình viên thành công.
Không có một quy chuẩn chung nào cho các junior developers hay kỹ năng xin việc cho sinh viên mới ra trường về việc phỏng vấn và chắc chắn thành công. Tuy nhiên, nếu biết trước một số kinh nghiệm hay ho sẽ giúp bạn chuẩn bị tốt hơn cho buổi phỏng vấn cũng như có được sự tự tin khi đối diện với nhà tuyển dụng. Những kỹ năng xin việc cho sinh viên mới ra trường trong bài viết này có thể phần nào giúp bạn làm tốt hơn trong buổi phỏng vấn của mình. Đón đọc nhiều bài viết hấp dẫn khác tại TopDev trong lĩnh vực nhân sự bạn nhé!
Cách Import dữ liệu từ các bảng khác nhau trong MySQL Workbench
Bài viết được sự cho phép của blogchiasekienthuc.com
#1. Đặt vấn đề
Khi làm việc với các hệ quản trị cơ sở dữ liệu, chắc hẳn có không ít lần các bạn muốn sao chép dữ liệu của một bảng từ cơ sở dữ liệu này sang bảng tương tự của cơ sở dữ liệu khác.
Nhiều bạn sẽ trích xuất (Export) dữ liệu thành file Script => và mang sang cơ sở dữ liệu khác, rồi đổi tên và Import ngược lại. Có đúng không ạ !
Cách làm này không sai, nhưng đôi khi nó hơi mất thời gian và tốn nhiều công sức nếu như số lượng dữ liệu tương đối nhiều.
Vì vậy, ở trong bài viết này mình sẽ cùng các bạn tìm hiểu về một cách làm khác, để thực hiện thao tác này trong công cụ MYSQL WORKBENCH.
#2. Hướng dẫn Import dữ liệu từ các bảng khác nhau
Ví dụ ở đây mình đang có hai cơ sở dữ liệu là store và store_copy. Trong đó, mỗi cơ sở dữ liệu có một bảng là products với cấu trúc giống nhau.
Bài toán là bảng store.products trong cơ sở dữ liệu store của mình đang có dữ liệu, giờ mình muốn sao chép toàn bộ dữ liệu đó sang bảng store_copy.products của cơ sở dữ liệu store_copy
+ Bước 1: Đầu tiên chúng ta sẽ phải Export dữ liệu đó ra một file có định dạng *.csv hoặc là một file *.json bằng cách chuột phải vào table => và chọn Table Data Export Wizard như hình bên dưới.
+ Bước 2: Các bạn chọn những trường dữ liệu nào được Export (có thể chọn tất hoặc một vài trường) => sau đó bấm Next để tiếp tục.
+ Bước 3:
(1) Ở bước tiếp này các bạn sẽ lựa chọn loại file các bạn muốn Export ra.
(2) Sau đó bấm vào Browse… để chọn vị trí lưu file.
(3) Các bạn đặt tên file (các bạn nên đặt tên file viết liền không dấu).
(4) Bấm Save để lưu file.
+ Bước 4: Tiếp theo, các bạn xác nhận các lựa chọn ở Bước 3 => rồi bấm Next để sang bước tiếp theo.
+ Bước 5: Tiếp tục bấm Next để bắt đầu kết xuất dữ liệu ra file *.csv
+ Bước 6: Bấm Finish để hoàn tất việc kết xuất dữ liệu (các bạn có thể thấy thời gian Export là 0.468s và số lượng bản ghi là 110 bản ghi).
+ Bước 7: Tiếp theo ở trong bảng store_copy.products mình kiểm tra thì chưa có bất kỳ bản ghi nào.
+ Bước 8: Để Import dữ liệu từ file .cvs vào trong bảng store.products thì chúng ta nhấn chuột phải vào Table đó => và chọn Table Data Export Wizard.
+ Bước 9: Bước tiếp theo chúng ta sẽ chọn file .cvs mà chúng ta đã Export ra từ bước trước. Sau đó bấm Next để chuyển sang bước tiếp theo.
+ Bước 10:
(1) Các bạn chọn bảng sẽ Import dữ liệu vào (mặc định là bảng chúng ta chọn products)
(2) Các bạn có thể lựa chọn tạo một bảng bảng mới khi chọn lựa chọn này.
+ Bước 11:
(1) Sau khi chọn được bảng chúng ta sẽ chọn các trường trong bảng xem trường nào sẽ được Import dữ liệu.
(2) Sau khi chọn xong các trường dữ liệu thì bấm Next để tiếp tục.
+ Bước 12: Ở bước này các bạn bấm Next để tiếp tục.
+ Bước 13: Tiếp tục bấm Next sau khi data được Import xong.
+ Bước 14: Vậy là toàn bộ bản ghi từ file đã được Import vào bảng store_copy.products. Bạn bấm Finish để hoàn thành.
+ Bước 15: Bây giờ mình quay lại kiểm tra dữ liệu trong bảng thì thấy bảng đã có đầy đủ dữ liệu từ file Import đầu vào.
#3. Kết luận
Okay, vậy là trong bài viết này mình đã cùng các bạn tìm hiểu về cách để Export và Import dữ liệu từ các bảng khác nhau trong cơ sở dữ liệu MySQL thông qua công cụ MySQL Workbench rồi ha.
Đây sẽ là một thủ thuật khá hay trong nhiều trường hợp chúng ta có dữ liệu mẫu được lưu dưới dạng file *.csv hoặc *.json
Hi vọng là thủ thuật nhỏ trong bài viết này sẽ hữu ích với bạn. Xin chào vào hẹn gặp lại các bạn trong các bài tiếp theo nhé !