Home Blog Page 85

So sánh nhanh Selenium và QTP

selenium vs qtp
So sánh nhanh Selenium và QTP

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

Dưới đây là bảng so sánh nhanh giữa Selenium và QTP dựa trên một số tiêu chí cơ bản để so sánh các công cụ kiểm thử tự động

STT Tiêu chí Selenium QTP

1

Chi phí bản quyền Đây là công cụ mã nguồn mở cho nên không có chi phí bản quyền, hoàn toàn miễn phí Rất mắc…khoảng 5000USD cho 1 máy

2

Thực sự mô phỏng hành động của người dùng cuối Selenium thực hiện hành động trong nền của trình duyệt  tức là người sử dụng, có thể thực hiện các kiểm thử tự động với trình duyệt được thu nhỏ tối thiểu (minimized). QTP thực hiện kiểm thử tự động tương đương với một người thực hiện các thao tác vào ứng dụng. Vì vậy, các trình duyệt không có thể được giảm thiểu (người sử dụng không thể thực hiện bất kỳ hành động nào khác trên máy tính trong khi kiểm thử đang chạy).

3

Plug-ins Có và hoàn toàn miễn phí Có. Người sử dụng phải trả tiền bản quyền

4

Nỗ lực và kỹ năng để sử dụng công cụ Người dùng cần phải có kỹ năng tốt về lập trình và coding vì đây là điều kiện cần. Đòi hỏi nỗ lực ít h ơn để tạo ra một kịch bản kiểm thử, vì nó có một môi trường phát triển rất tốt, thân thiện với người sử dụng.

5

Dễ dàng tạo ra các kịch bản kiểm thử? Tốt. Selenium IDE Recorder không mạnh mẽ như QTP nhưng là một công cụ miễn phí, nhiều hành động không được ghi lại bởi các IDE và có thể tự nhập vào. Hoàn hảo.

6

Hỗ trợ trên các HĐH Windows, Linux, Unix và Macintosh. Windows.

7

Loại ứng dụng Web based applications. Web-based và desktop applications.

8

Trình duyệt IE, Firefox, Safari, Opera và một vài trình duyệt khác IE, Chrome và Firefox.

9

Ngôn ngữ phát triển kịch bản kiểm thử Java, Ruby, Python, C#, Perl, Groovy và nhiều ngôn ngữ khác VBScript và/hoặc JavaScript.

10

Tích hợp với các công cụ quản lý thử nghiệm Khi phát triển kiểm thử (test case) sử dụng C# trong VS thì có thể sử dụng MTM để quản lý test cases HP Quality Center và TestDirector

11

Môi trường phát triển kiểm thử Kịch bản thử nghiệm có thể được phát triển trong nhiều trình soạn thảo như Eclipse, Visual Studio, Netbeans… Kịch bản thử nghiệm chỉ có thể được phát triển trong QTP.

12

Hỗ trợ kỹ thuật Vì đây là công cụ m ã nguồn mở nên không có hỗ trợ kỹ thuật chính thức. QTP cung cấp hỗ trợ kỹ thuật rất tốt qua điện thoại, mail, web, forum.

13

Quản lý và lưu trữ đối tượng giao diện (UI-Object) Không. Đối tượng có thể được quản lý bằng cách sử dụng giao diện người dùng mở rộn g (UI-Element user extension) hoặc properties files. Tất cả các phương pháp trên đểu phải sử dụng code cứng (hard-code) Có. QTP được xây dựng trong với Object Repository. Quản lý Object repository là khá dễ dàng trong QTP

14

Hỗ trợ cho các hộp thoại Chỉ hỗ trợ 1 phần. Không thể thực hiện một số hành động như lấy tiêu đề của hộp thoại. Có. QTP hỗ trợ tất cả các loại hộp thoại.

15

Hỗ trợ cho các kịch bản tải lên tập tin Không. Selenium không hỗ trợ kịch bản này vì hạn chế JavaScript. QTP không có vấn đề gì trong việc mô phỏng

 

Selenium là lựa chọn hoàn hảo nếu

  • Developer chịu trách nhiệm phát triển và bảo trì các kiểm thử
  • Những kiểm thử bạn đang phát triển sẽ là 1 phần của một cơ sở hạ tầng lớn hơn
  • Chắc chắn là bạn sẽ thử hiện những kiểm thử trên trình duyệt mà thôi
  • Bạn nghĩ là bạn sẽ thực hiện những kiểm thử trên những môi trường khác ngoài Windows
  • Bạn muốn sử dụng những công cụ miễn phí 😀

QTP có lẽ là lựa chọn tốt nếu…

  • Bạn muốn phát triển và duy trì các kiểm thử một cách nhanh chóng và dễ dàng.
  • Nếu bạn cần kiểm thử đáng kể bên ngoài trình duyệt

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Hướng dẫn load docker image từ file tar (docker load)

docker image
Hướng dẫn load docker image từ file tar (docker load)

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

Hướng dẫn load docker image từ file tar (docker load)

Trong bài này mình sẽ thực hiện restore image được back up thành file .tar bởi lệnh docker save

(Xem lại: Ví dụ docker save)

  Cách tạo một Docker đơn giản cho Node.JS
  Cách thiết lập một dự án Symfony để làm việc với Docker Subdomains

Hướng dẫn load docker image từ file tar (docker load)

Để load các image từ định dạng file .tar ta dùng lệnh docker load

Cú pháp:

docker load -i file_path

Ví dụ:

hiện tại trên máy mình không có image nào. Và mình đang có 1 image dưới dạng file .tar ở images/ubuntu.tar

(đây là images ubuntu:18.04 được backup bằng lệnh docker save)

Để load image đó mình dùng lệnh:

docker load -i images/ubuntu.tar

Hướng dẫn load docker image từ file tar (docker load)

Okay, Done!

References: https://docs.docker.com/engine/reference/commandline/load/

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Kiến trúc Web – Web Architecture

Web Architecture
Kiến trúc Web – Web Architecture

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

Hôm nay ngày 12/03, nhân kỷ niệm ngày World Wide Web, hãy cùng tìm hiểu về kiến trúc web (Web Architecture). Thiết nghĩ, với một thứ chúng ta làm việc, sử dụng hàng ngày, không ít thì nhiều, cũng nên hiểu về em nó đôi chút.

Thôi không dài dòng nữa, vào bài ngay đây.

  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết
  10 trang web hàng đầu để tìm hiểu WordPress

Todo

Duis id ante elit. Aliquam quis tellus id orci eleifend finibus. Donec consequat justo ligula, eget sodales purus hendrerit at.

  1. Ut at interdum nunc. Maecenas commodo turpis quis elementum gravida.
  2. Nunc ac sapien tellus. Quisque risus enim, tempus eget porttitor in, pellentesque vel urna.
    Donec nibh massa, rutrum a sollicitudin eu,
    lacinia in lorem.

1. DNS (Domain name server)

Graphic design is the paradise of individuality, eccentricity, heresy, abnormality, hobbies, and humors. — George Santayana

Vim te case nihil oblique, has partem interpretaris ne, ad admodum accusamus nam. Usu utinam dissentias referrentur ne, vim accusam voluptua pertinacia no. Est no posse utinam inermis, brute errem mentitum et ius, te prompta albucius quo. In pro simul soleat regione.

alt

Ne reque offendit singulis mea, ad eos ferri doming nostrud. Duis suscipit usu ut, fuisset pericula ex est, et porro prompta his. Audire definiebas voluptatibus et duo, aperiam ocurreret ad nec. Vel ad nostrud principes. Ad liber congue iracundia sed, eirmod erroribus eam te, has veniam epicurei ea.

Pri probo alterum aliquando an. Duo appetere laboramus intellegat ea, ex suas diam exerci vix. Mel simul debitis id, est nusquam fuisset mentitum in. Te mei iudico iisque.

2. Load balancer

3. Web app servers

4. Database

5. Caching service

6a. Job queue

6b. Job servers

7. Full text search service

8. Services

9a. Data “firehose”

9b. Copy of data

9c. Data warehouse

10. Cloud storage data

11. CDN (Content delivery network)

Content delivery network, tạm dịch là Mạng lưới truyền tải nội dung. Tạm thời bỏ qua các khái niệm. Hằng ngày, chúng ta vẫn đọc báo, xem youtube, giao dịch online,… Chính những hoạt động này bản thân nó đã tương tác trực tiếp với CDN.

Vậy CDN ra đời với mục đích gì?.

Một buổi sáng đẹp trời, bạn truy cập website http://bbc.com. Tuy nhiên, do origin server nằm ở United Kingdom (khoảng cách xa, nội dung trang báo lại nặng), nên thời gian từ khi ấn enter cho tới khi thấy được nội dung tờ báo là 5s. Thời gian này tuy nhỏ, nhưng nếu phải làm việc nhiều, sẽ rất tốn thời gian. Để giảm thời gian tải này, CDN ra đời.

Ý tưởng:

Ở mỗi khu vực địa lý nhất định (ví dụ: cấp châu lục), đặt một serverCDN đóng vai trò như client trong mạng lưới Content Network, người dùng sẽ request tới serverCDN gần nhất mà mình có thể tiếp cận nhằm giảm thời gian và quá trình request tới origin server ở xa.

Thay request phải vượt Đại Tây Dương (3s), với CDN, chỉ mất 1s cho CDN Server ở UK
Nhưng làm gì có nội dung BBC ở serverCDN!

Xin thưa là có,  server ở mỗi nơi đều có lưu trữ bộ đệm (cached), bao gồm hình ảnh, tài liệu, video, … Mỗi khi chúng ta request, thay vì tới thẳng origin server, sẽ chuyển qua request tới serverCDN, từ đó giảm thời gian truy xuất. Nếu số lượng request nhiều, việc sử dụng CDN còn giúp giảm tải cho origin server.

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Tăng Tốc Và Bảo Mật Website Với vStack WordPress Plugin

vstack wordpress plugin
Tăng Tốc Và Bảo Mật Website Với vStack WordPress Plugin

Với hơn 60% website trên thế giới được xây dựng trên nền tảng WordPress, nhu cầu tăng tốc và bảo mật website bằng các plugin hiện nay luôn được các doanh nghiệp ưu tiên hàng đầu. VNG Cloud giới thiệu giải pháp vStack WordPress plugin, hỗ trợ doanh nghiệp tăng tốc và bảo mật toàn diện, nâng cao 60% tốc độ của website.  

Với các tính năng nổi bật như:

  • Hỗ trợ tăng tốc website 
  • Cấu hình tường lửa theo chuẩn
  • Tự động lọc mã độc và bảo vệ khỏi các cuộc tấn công
  • Tự động làm mới nội dung khi cập nhật bài viết

Tuyển dụng wordpress lương cao lên đến 3000USD

Hướng dẫn tích hợp vStack plugin trên WordPress

Với vStack plugin của VNG Cloud, website của bạn sẽ được tăng tốc và bảo vệ chỉ bằng vài thao tác click đơn giản:

Bước 1: Cài đặt plugin

  • Cài trực tiếp trên kho plugins: Bằng cách tìm “vStack” trên plugins của wordpress.org. Bạn chọn “Active” để cài đặt.
  • Upload plugin vào source code

 Trong trường hợp “vStack” plugin không tìm thấy trên plugins của wordpress.org bạn có thể tải plugin từ github của vngcloud và giải nén vào wp-content/plugins.

Bước 2: Active Plugin

Khi plugin được hiển thị trong danh sách plugins, bạn chọn “Active” để sẵn sàng sử dụng, và chọn “Settings” để tiến hành xác thực và cấu hình.  

Bước 3: Đăng nhập vào tài khoản VNG Cloud

  • Nếu bạn chưa có tài khoản VNG Cloud, chọn “Create Your Free Account” để tạo tài khoản VNG Cloud, một cửa sổ đăng kí sẽ giúp bạn tạo tài khoản.
  • Nếu bạn đã có tài khoản VNG Cloud, chọn “Sign in here”, một cửa sổ đăng nhập sẽ giúp bạn đăng nhập bằng cách chọn “Save API Credentials”.

Tăng Tốc Và Bảo Mật Website Với vStack WordPress Plugin

Ở đây, bạn sẽ phải đăng nhập bằng tên tài khoản của VNG Cloud, và một TOKEN.

Nếu bạn chưa có TOKEN, bạn chọn “Get Your API Key from here”, một cửa sổ đăng nhập sẽ hiện ra.

Đăng nhập thành công, bạn sẽ được trả về mã TOKEN. Vui lòng lưu dự phòng TOKEN này, trong trường hợp bạn cần gỡ hoặc cài lại plugin, TOKEN này sẽ giúp bạn đăng nhập lại.

Bước 4: Quản lí plugin

Sau khi đăng nhập xong, bạn sẽ vào được trang quản lí. 

Phía trên góc trái màn hình, bạn sẽ thấy tên miền có dạng “xxx.wp.vngstack.com”.

Tăng Tốc Và Bảo Mật Website Với vStack WordPress Plugin

Đây là tên miền được khởi tạo định danh cho website của bạn trên vStack. Bằng cách tạo record CNAME domain website của bạn về đây, website của bạn đã sẵn sàng sử dụng dịch vụ.

Tăng Tốc Và Bảo Mật Website Với vStack WordPress Plugin

Trải nghiệm ngay vStack WordPress Plugin tại đây: https://www.vngcloud.vn/tang-toc-va-bao-mat-website-voi-vstack-wordpress-plugin 

Giả lập Google Cloud Storage sử dụng fake-gcs-server

google cloud storage
Giả lập Google Cloud Storage sử dụng fake-gcs-server

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

Khi làm việc với các Cloud Provider, chúng ta cần tính toán đến các giải pháp để tiết kiệm chi phí, ít nhất là ở giai đoạn development. Vì đa số các service của các Cloud Provider mà chúng ta cần sử dụng, sẽ ít nhiều tốn tiền. Một giải pháp mà mình giới thiệu với các bạn trong bài viết này là về giả lập Google Cloud Storage sử dụng một open-source tên là fake-gcs-server, phù hợp cho những dự án nào có sử dụng Google Cloud Platform. Nó giúp chúng ta có thể start lên một standalone server có chức năng gần giống với Google Cloud Storage. Các bạn có thể sử dụng các thư viện của Google provide để làm việc với Google Cloud Storage, để làm việc với open-source này luôn.

  Ứng dụng mới cực hot từ Google: Android Sunflower
  10 Add-on Google Sheets phải có dành cho các Recruiters

Cài đặt fake-gcs-server

fake-gcs-server cung cấp cho chúng ta một Docker Image, giúp chúng ta có thể dễ dàng start nó lên chỉ với vài bước.

Cụ thể, các bạn cần chạy Docker command sau:

docker run -d --name fake-gcs-server -p 4443:4443 fsouza/fake-gcs-server

Lúc này, nếu các bạn request tới URL để lấy thông tin Buckets list với host port sử dụng fake server: https://localhost:4443/storage/v1/b, các bạn sẽ thấy kết quả như sau:

Giả lập Google Cloud Storage sử dụng fake-gcs-server

Items hiển thị empty vì chúng ta chưa có một bucket nào trong fake-gcs-server.

Các bạn có thể mount một số data có sẵn và chạy fake-gcs-server như sau:

docker run -d --name fake-gcs-server -p 4443:4443 -v ${PWD}/examples/data:/data fsouza/fake-gcs-server

${PWD} là thư mục hiện hành các bạn đang chạy lệnh Docker cộng với thư mục example/data, sẽ được map với thư mục /data bên trong container của fake-gcs-server. Các bạn có thể thay đổi ${PWD}/examples/data thành bất cứ thư mục nào mà các bạn muốn. Những thư mục trong thư mục ${PWD}/examples/data này sẽ là những bucket, và tất nhiên những tập tin nằm trong các bucket sẽ là những object của những bucket này.

Ví dụ mình có tập tin test.txt nằm trong thư mục /Users/khanh/Document/data/sample-bucket, mình chạy câu lệnh start fake-gcs-server như sau:

docker run -d --name fake-gcs-server -p 4443:4443 -v /Users/khanh/Documents/data:/data fsouza/fake-gcs-server

thì lúc này sample-bucket sẽ là một bucket trong fake-gcs-server, và tập tin test.txt sẽ là một object trong bucket này.

Request lại URL https://localhost:4443/storage/v1/b, các bạn sẽ thấy kết quả như sau:

Giả lập Google Cloud Storage sử dụng fake-gcs-server

Lấy thông tin tất cả các object của bucket với URL https://localhost:4443/storage/v1/b/sample-bucket/o, các bạn sẽ thấy kết quả như sau:

Giả lập Google Cloud Storage sử dụng fake-gcs-server

Các bạn có thêm tuỳ ý bao nhiêu bucket cũng được, bao nhiêu object cũng được.

Mặc định thì fake-gcs-server sử dụng HTTPS, các bạn có thể sử dụng HTTP bằng cách thêm vào command start nó tham số scheme như sau:

docker run -d --name fake-gcs-server -p 4443:4443 -v /Users/khanh/Documents/data:/data fsouza/fake-gcs-server -scheme http

Lúc này chúng ta có thể sử dụng fake-gcs-server với HTTP:

Giả lập Google Cloud Storage sử dụng fake-gcs-server

Sử dụng Spring Cloud GCP Storage để access vào bucket của fake-gcs-server

Để access vào các bucket trên Google Cloud Storage, các bạn có thể sử dụng thư viện spring-cloud-gcp-storage. Chúng ta cũng có thể sử dụng thư viện này với fake-gcs-server.

Một điều các bạn cần lưu ý là chúng ta không cần sử dụng credentials để access vào các bucket của fake-gcs-server.

Mình sẽ tạo một Maven project đơn giản, khai báo sử dụng spring-cloud-gcp-storage để access vào fake-gcs-server mà mình đã start ở trên, như sau:

Giả lập Google Cloud Storage sử dụng fake-gcs-server

với:

<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-storage</artifactId>
<version>2.0.3</version>
</dependency>

Mình sẽ tạo mới một class main, sử dụng API của spring-cloud-gcp-storage để access vào bucket sample-bucket như sau:

package com.huongdanjava.springcloudgcs;

import com.google.cloud.storage.Blob;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;

public class Application {

public static void main(String[] args) {
Storage storage = getStorage();
Blob blob = storage.get(BlobId.of("sample-bucket", "test.txt"));

System.out.println(blob.getGeneratedId());
}

private static Storage getStorage() {
// @formatter:off
StorageOptions storageOptions = StorageOptions.newBuilder()
.setHost("http://localhost:4443")
.build();
// @formatter:on

return storageOptions.getService();
}

}

Ở đây, mình không sử dụng credentials để access vào bucket của fake-gcs-server. Các bạn có thể thao tác trên bucket của fake-gcs-server tương tự như trên Google Cloud Storage sử dụng thư viện này.

Kết quả khi chạy ví dụ này như sau:

Giả lập Google Cloud Storage sử dụng fake-gcs-server

Các bạn có thể đọc thêm cuốn sách này Google Cloud Platform for Developers: Build highly scalable cloud solutions with the power of Google Cloud Platform để tìm hiểu về cách sử dụng các thư viện của Java để làm việc với Google Cloud Platform nhé!

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Học lập trình để làm gì? Nên học lập trình gì?

học lập trình
Học lập trình để làm gì? Nên học lập trình gì?

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

Học cái gì đó mục đích cuối cùng là để có một nghề nghiệp hoặc sự nghiệp ổn định. Đó cũng là định luật muôn thuở và luôn đúng với bất kỳ người nào đang tìm kiếm các trung tâm hay học viện để học một cái gì đó? Vậy sau khi học lập trình, chúng ta có thể làm những nghề nào? Chia buồn với bạn, không phải cứ học xong thì Coder có thể làm bất cứ nghề nào về lập trình cũng được.

Bởi thế, trả lời cho câu hỏi “Tôi học cái này để làm gì?” luôn cần thiết ngay từ những bước chân đầu tiên. Câu trả lời chung chung thì rất nhiều. Nhưng câu trả lời chính xác là xác định mục đích cuối cùng và mong muốn của bạn là gì sau khi học lập trình xong. Sau đây, mình sẽ cho bạn những gợi ý về nghề nghiệp phù hợp con đường mà bạn đang theo đuổi.

  10 câu nói cực hay về lập trình
  10 kênh Youtube học lập trình không thể bỏ qua dành cho Junior Web Developer / Designer

Bạn muốn là một Software Engineer

Đối tượng phù hợp: Coder đa năng và truyền thống

Đây là công việc khá phổ biến về lập trình. Một Software Engineẻ cần phải học JavaScript, Ruby, HTML, và CSS. Ranh giới giữa Software Engineer và Software Developer khá mờ nhạt, vì vai trò của họ gần như tương đương nhau. Bạn có thể tìm hiểu kỹ hơn trên Reddit để có cái nhìn sâu hơn.

Đối với hầu hết mọi trường hợp, Software Engineer cần phải học lập trình và hiểu sản phẩm cuối được thiết kế và quản trị như thế nào. Thông qua những kiến thức đã học, kỹ sư phần mềm sẽ tìm ra hướng giải quyết hay phát triển phần mềm của mình.

Việc làm kỹ sư Software Engineer lương cao

Bạn muốn là một Data Scientist

Đối tượng phù hợp: Coder từng trải hay chuyên môn cao.

Đây là một nghề nghiệp đang hấp dẫn trong giới lập trình, theo điều tra của Glassdoor hay LinkedIn và một số người khác được khảo sát. Sở dĩ những người này khó kiếm vì yêu cầu kỹ năng đa dạng. Một người làm công việc này phải vừa là software engineer, vừa thực hành và học lập trình, vừa phân tích thống kê và trình bày số liệu để kể những câu chuyện và khám phá những thông tin đầy sức mạnh từ một lượng lớn dữ liệu thu thập được.

Data Scientist phải học Python, SQL, R và Java và sử dụng chúng thành thạo để xây dựng thuật toán và xây những model được sử dụng để phát hiện vấn đề mới và dự đoán hành vi người tiêu dùng.

Tuyển dụng lập trình Data Scientist

Bạn muốn là một Front-End Developer

Đối tượng phù hợp: Coder sáng tạo và thích hiện thực hóa các ý tưởng

Nếu bạn muốn tạo ra thứ gì đó để mọi người có thể xem trên mạng Internet, bạn nên là một Front-End Developer. Những người này sẽ phải học Front-end như JavaScript, HTML và CSS để hoàn thiện bề nổi của website. Ngoài ra, công việc của Front-End Developer còn liên quan tới thiết kế website và Back-End Developer để có thể hoàn thiện mọi thứ từ giao diện ấn tượng cho tới các chức năng độc đáo.

Bạn muốn là một Back-End Developer

Đối tượng phù hợp: Coder có kỹ năng tổ chức và đáng tin cậy

Back-End Developer vẫn thường bị đánh giá thấp. Họ sẽ phải xây dựng các nền tảng đặt nền móng cho các Front-End Developer thông qua các ngôn ngữ PHP, Java, Ruby, Python hay SQL. Ngoài ra, Back-End Developer còn sử dụng các ngôn ngữ server-side để kéo thông tin từ cơ sở dữ liệu và chuyển lại cho người dùng thông qua định dạng của ngôn ngữ Front-End.

Bạn muốn là một Full-Stack Developer

Đối tượng phù hợp: Coder trọn gói, hay còn gọi Coder “bao sô”

Full-Stack Developer nổi lên cùng với phong trào khởi nghiệp trên toàn cầu. Các công ty khởi nghiệp cần cả Front-End lẫn Back-End Developer, nhưng không đủ nguồn lực dành cho hai team độc lập. Full-Stack Developer cũng không phải là bậc thầy về ngôn ngữ lập trình. Họ biết mọi thứ ở mức vừa đủ để tạo ra và vận hành một website, đồng thời có thể xử lý sự cố ở Back-End khi có phát sinh.

Tuyển dụng Full stack Developer

2.jpg

Bạn muốn là một Mobile Developer

Đối tượng phù hợp: Coder yêu thích ứng dụng di động

Đây là những người được sinh ra dành cho các ứng dụng di động. Mobile Developer cần ngôn ngữ Swift để tạo ra ứng dụng cho hệ điều hành iOS , trong khi với Android, họ cần ngôn ngữ Java, C# hoặc C/C++. Với sự phố biến của các thiết bị di động, số lượng Mobile Developer đã tăng trưởng đáng kể trong thời gian vừa qua, tỉ lệ thuận với số lượng ứng dụng phục vụ cho cộng đồng cũng ngày một nhiều hơn

Bạn muốn là một UI/UX Designer

Đối tượng phù hợp: Coder quan tâm đến trải nghiệm của người dùng và không quan tâm đến chức danh của mình

Chức danh của những Coder này vẫn còn gây ra rất nhiều tranh cãi và có không ít chủ đề bàn luận nên có hay không sự tồn tại vị trí UI/UX Designer trong lĩnh vực IT. Vì thế chúng ta sẽ không đi sâu về phương diện này, thay vào đó là cách một UI/UX Designer có thể tận dụng code vào trong công việc hằng ngày.

UX Designer tập trung hơn vào trải nghiệm tổng thể của người dùng, họ sẽ thiết kế các phiên bản test và bản thử nghiệm trước khi chuyển chúng đến tay của Front-End Developer. UI/UX Designers cũng thường không phải lập trình, nhưng hiểu biết coding sẽ giúp công việc của họ hiệu quả hơn. Ví dụ họ cần hiểu một chút về HTML hay Swift để hạn chế những trở ngại về công việc của mình.

Bạn muốn là một Product Manager

Đối tượng phù hợp: Coder thông thường nhưng có kỹ năng lãnh đạo và khả năng đọc mã code.

Product Manager có thể không phải là một Coder trong thời điểm hiện tại năm 2018. Nhưng họ có khả năng hiểu các đoạn mã và chức năng của nhiều ngôn ngữ khác nhau, để có thể hỗ trợ nhiều nhóm khi cần thiết. Product Manager làm sao có thể hiểu được những gì Software Engineer giải thích nếu không nắm các kiến thức căn bản về lập trình. Họ không cần phải là Coder, nhưng họ giúp xử lý các vấn đề hiệu quả hơn.

Tìm việc làm Prodct Manager lương cao

Bạn muốn là một Database Developer

Đối tượng phù hợp: Coder sở hữu tất cả đáp án và tạo ra những kho dữ liệu khổng lồ

Ngay tên của chức danh này đã nói lên tất cả công việc của họ. Họ tạo ra và quản lý dữ liệu trong môi trường IT. Database Developer có thể làm việc như Database Administrator, đảm bảo khả năng lưu trữ thông tin, đảm bảo sự an toàn và khả năng truy xuất những thông tin này. Những người này cũng có thể phải liên tục nâng cấp hệ thống, và chịu trách nhiệm cập nhật liên tục dữ liệu trong hệ thống này.

Bạn muốn có vị trí trong DevOps

Đối tượng phù hợp: Coder nhanh nhẹn, thích làm việc với các quy trình vận hành

DevOps là viết tắt của Developement and Operations, kết nối quá trình phát triển và vận hành một ứng dụng hay website theo một quy trình thống nhất. Theo truyền thống, phải mất rất nhiều thời gian để một sản phẩm chuyển đổi từ bộ phận phát triển qua bộ phận triển khai. Và bộ phận DepOps giúp cho quá trình này diễn ra nhanh hơn, giúp người dùng không bị gián đoạn thông tin và các doanh nghiệp tăng khả năng cạnh tranh trong môi trường IT đang ngày một đông đúc hơn.

Tuyển dụng Devops các công ty HOT

Bạn muốn làm bất cứ việc gì mình thích, ở nơi mà mình muốn

Bạn có thể thấy sự đa dạng về nghề nghiệp của một Coder, không đâu xa mà ngay từ danh sách này. Chưa từng có một quan điểm hay chỉ dẫn cho việc lựa chọn ngôn ngữ lập trình tiếp theo sau khi hoàn thành xong một ngôn ngữ lập trình nào đó. Ví dụ một Graphic Designer có thể học thêm kiến thức cơ bản về Front-End để giúp tăng khả năng cạnh tranh trong nghề nghiệp của mình. Ít nhiều cũng giúp cho họ có cái nhìn rõ ràng hơn trước những mô tả của bạn Front-End.

Có nhiều điều thú vị nhưng cũng tùy vào cách Coder lựa chọn công việc của mình. Không phải công ty nào cũng giống nhau và công việc coding ở công ty này tương tự công ty kia, chưa kể hàng ngàn các lĩnh vực khác nhau sẽ có cách lập trình khác nhau. Data Scientist có thể là nghề được biết đến nhiều nhất trong khoa học dữ liệu, nhưng vẫn còn đó vị trí Phân tích dữ liệu, Kỹ sư tự động hóa hay kỹ sư Big Data.

Tuy nhiên hãy thoải mái vì hiện tại có rất nhiều nghề nghiệp dành cho Coders. Bước tiếp theo của tiến trình chính là các định sở thích của mình và ngôn ngữ lập trình phù hợp nhất. Cách hay nhất chính là tham gia các sự kiện coding để có cái nhìn và tiếp cận rõ hơn về hướng đi cho tương lai. uCode.vn cung cấp cho bạn rất nhiều khóa học để nắm vững các kiến thức nền tảng thông qua các công cụ và ví dụ thực tiễn. Chúng tôi cũng có những buổi hội thảo cũng như tư vấn nhằm giúp các bạn tìm ra hướng đi phù hợp cho bản thân.

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Xây dựng swift package để gọi network trong swift

Xây dựng swift package để gọi network trong swift

Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh

Tuần trước, chúng ta đã xem qua 1 cách custom về thư viện bàn phím hiển thị gợi ý tiền Việt Nam. Hôm nay tôi sẽ hướng dẫn cách tạo 1 thư viện để gọi network dạng restful API. Thư viện tên là Qnetwork. Bạn có thể tải trên github tại đường dẫn:

https://github.com/lexuanquynh/QNetwork

Thư viện này dùng để làm gì?

Đầu tiên trước khi tiến hành xây dựng, hãy tải phần demo của tôi tại đường dẫn:

https://github.com/lexuanquynh/QNetworkDemo

Đầu tiên, bạn cần biết rằng tôi xây dựng thư viện này tốt nhất cho kiến trúc MVVM. Tuy nhiên bạn vẫn có thể sử dụng nó cho các architecture khác mà bạn muốn. Nếu hiểu theo cách đơn giản, bạn dùng thư viện này, bạn tạo các service để gọi API. Sau đó, bạn dùng nó để gọi bất cứ ở đâu bạn muốn.

  Các cách sử dụng AS, AS?, AS! một cách hiệu quả và an toàn trong code Swift
  Các cải tiến của Java cho Switch statement từ Java 12

Xem thêm các việc làm Swift lương cao trên TopDev

Vậy cách sử dụng nó như nào? Hãy xem phần code demo của tôi. Ở ví dụ này tôi sẽ tiến hành gọi API của github:

curl \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/search/repositories

Trong 1 bài viết trước đây, tôi đã giới thiệu khá kỹ càng cách viết API cho nó. Các bước tiến hành như sau:

  • Tạo 1 module Github. Mỗi module sẽ phục vụ cho 1 màn hình riêng biệt. Trong thiết kế MVVM tôi hay làm như vậy, module bao gồm View, Model, servive gọi API và view model. Bạn có thể mở souce code ở trên ra xem.
  • Tạo 1 file GithubAPI. File này chứa cụm API cần gọi. Thông thường trong ứng dụng của tôi sẽ có nhiều file dạng *API. Mỗi 1 file chứa 1 cụm, ví dụ AuthenAPI sẽ chứa cụm đăng nhập, đăng xuất. FeedAPI chứa cụm API liên quan đến feed. Cách đặt tên sẽ sát nghĩa nó làm gì. Mô tả file này như sau:
//
//  GithubAPI.swift
//  QNetworkDemo
//
//  Created by Xuân Quỳnh Lê on 2021/06/26.
//

import Foundation
import QNetwork
import Moya

enum GithubAPI {
    case searchRepositories(q: String, sort: String, order: String, page: Int)
}

extension GithubAPI: TargetType {
    var baseURL: URL {
        let url = URL(string: Configs.Network.baseUrl)!
        return url
    }

    var path: String {
        switch self {
        case .searchRepositories:
            return "search/repositories"
        }
    }

    var method: Moya.Method {
        return .get
    }

    var sampleData: Data {
        var dataUrl: URL?

        switch self {
        case .searchRepositories:
            if let file = Bundle.main.url(forResource: "SearchRepositoriesResponse", withExtension: "json") {
                dataUrl = file
            }
        }
        if let url = dataUrl, let data = try? Data(contentsOf: url) {
            return data
        }

        return Data()
    }

    var task: Task {
        switch self {
        case .searchRepositories:
            if let parameters = parameters {
                return .requestParameters(parameters: parameters, encoding: parameterEncoding)
            }
        }
        return .requestPlain
    }

    var headers: [String: String]? {
        return ["Content-type": "application/json"]
    }

    var parameters: [String: Any]? {
        var params: [String: Any] = [:]

        switch self {
        case .searchRepositories(let q, let sort, let order, let page):
            params["q"] = q
            params["sort"] = sort
            params["order"] = order
            params["page"] = page
        }

        return params
    }

    // For json encode. Use in post request
    var jsonEncoding: JSONEncoding {
        return JSONEncoding.default
    }

    // For param encode. Use in get request
    var parameterEncoding: ParameterEncoding {
        return URLEncoding.default
    }
}
  • Sau đó bạn tạo tiếp file GithubSearchService. Ở đây bạn cần truyền 1 struct Codable để lúc API có response, bạn cần đưa nó vào và chuyển json sang struct này. Cụ thể là struct GithubSearchResponse:
// MARK: - GithubSearchResponse
struct GithubSearchResponse: Codable {
    let totalCount: Int?
    let incompleteResults: Bool
    let items: [GithubSearchItem]?

    enum CodingKeys: String, CodingKey {
        case totalCount = "total_count"
        case incompleteResults = "incomplete_results"
        case items
    }
}

// MARK: - Item
struct GithubSearchItem: Codable {
    let id: Int
    let name: String?
    let htmlURL: String?
    let itemDescription: String?

    enum CodingKeys: String, CodingKey {
        case id, name
        case htmlURL = "html_url"
        case itemDescription = "description"
    }
}

Nhiều bạn hỏi tôi sao có thể từ json chuyển sang struct được như trên. Tôi là 1 người lười biếng, nên tôi hay vào trang này để chuyển:
https://app.quicktype.io

Sau đó bạn chỉ cần chỉnh sửa tên cho hợp lý là được. Bạn làm nhiều sẽ quen tay thôi.

  • Sau khi xong cụm service ở trên, bạn cần tạo GithubViewModel:
import Foundation

class GithubViewModel {
    // Service call API
    let service: GithubSearchService!
    // Callback to view
    var needReloadTableView: (() -> Void)?
    var needShowError: ((String) -> Void)?
    var needSetStateBottomIndicatorView: ((_ show: Bool) -> Void)?

    private var page: Int = 0
    private var language = ""
    private var incompleteResults = false
    
    // Datasource
    private var githubSearchItem: [GithubSearchItem] = []

    init() {
        // Turn on is test is true if you need test for API
        self.service = GithubSearchService(isTest: false)
    }

    /// Clear tableview data source
    func clearTableView() {
        self.page = 0
        self.incompleteResults = false
        self.githubSearchItem.removeAll()
        self.needReloadTableView?()
    }

    /// Request repositories
    func requestRepositories(language: String, loadMore: Bool = false) {
        // Check when load more
        if self.incompleteResults {
            return
        }
        if !loadMore {
            self.page = 0
            self.githubSearchItem.removeAll()
        }

        self.language = language

        // Default param
        let sort = "stars"
        let order = "desc"

        self.service.searchRepositories(language: language, sort: sort, order: order, page: self.page) { [weak self] result in
            guard let strongSelf = self else { return }
            // Check when load more
            if loadMore {
                strongSelf.needSetStateBottomIndicatorView?(false)
            }

            switch result {
            case .success(let githubResponse):
                strongSelf.incompleteResults = githubResponse.incompleteResults
                if let items = githubResponse.items {
                    items.forEach( {strongSelf.githubSearchItem.append( $0 )})
                }
                strongSelf.needReloadTableView?()
            case .failure(let error):
                strongSelf.needShowError?(error.description)
            }
        }
    }

    func numberOfRowsInSection(section: Int) -> Int {
        return githubSearchItem.count
    }

    func cellForRowAt(indexPath: IndexPath) -> GithubSearchItem {
        // Check if the last row number is the same as the last current data element
            if indexPath.row == self.githubSearchItem.count - 1 {
                self.page += 1
                self.requestRepositories(language: language, loadMore: true)
                self.needSetStateBottomIndicatorView?(true)
            }

        return githubSearchItem[indexPath.row]
    }
}

Nhiều bạn sẽ tò mò tại sao tôi lại viết được như trên. Cũng tương tự, tôi hay tải source của người khác về xem. Sau đó tôi clone y hệt, người ta viết gì, tôi viết nấy. Lâu dần quen tay, có phản xạ. Cuối cùng là hiểu được ý nghĩa mà người ta làm. Dù sao thì thực hành vẫn là cách tốt nhất để học lập trình.

Xây dựng QNetwork như nào?

Việc này khá là mù mờ nếu như không có video. Thú thật tôi đã xem video hướng dẫn của 1 developer khác ở đường dẫn này:
https://www.youtube.com/watch?v=xu9oeCAS8aA

Bạn xem kỹ video, làm theo anh ấy, bạn sẽ tạo được 1 swift package và có thể đưa cho người khác sử dụng thông qua 1 đường dẫn. Với Qnetwork, đơn giản bạn chỉ cần thêm đường dẫn này vào phần swift package của bạn(Xcode ➞ File ➞ New ➞ Swift Package):

https://github.com/lexuanquynh/QNetwork.git

Từ nay tôi sẽ chỉ cần 1 đường link, sau đó thêm vào, và có thể dễ dàng triển khai lớp network service của mình.

Nếu bạn có câu hỏi gì, hãy vào fan page của trang tại địa chỉ:

https://www.facebook.com/codetoanbug

Hãy chia sẻ cho ai đó nếu bạn thấy bài viết có ích.

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Vuejs Design Pattern – Dăm ba pattern phổ biến

vuejs design pattern
Vuejs Design Pattern – Dăm ba pattern phổ biến

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

Làm việc với Vuejs applications là làm việc với Components, nhưng không phải là cứ component thì thảy tất cả vào.

Đối với những application lớn (large scale application), đòi hỏi người kĩ sử phải biết thêm về Vuejs Design Pattern để sử dụng tốt những pattern này

  Cách sử dụng các plugins jQuery trong VueJS
  API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth

Xem thêm nhiều chương trình tuyển dụng VueJS hấp dẫn trên TopDev

1. Cơ bản về Vuejs Design Pattern

Bắt đầu với câu hỏi Design Pattern là gì?

Hiểu sơ Vuejs Design Pattern có thể thông qua hai định nghĩa cơ bản sau:

A general reapeatable solution to a commonly occuring problem in software

Là giải pháp lặp đi lặp lại cho phần đề chung nhất trong software

Not tied to a specific problem. They’re very general and can be applied to a board spectrum of problems.

Không ràng buộc với một vấn đề cụ thể. Chúng rất chung chung và có thể được áp dụng cho một loạt các vấn đề.

Túm cái vậy lại thì đi sâu vào tìm hiểu từng pattern sẽ có ví dụ cụ thể. Nhưng pattern là mẫu chung nhất, nên hãy cố gắng suy nghĩ để hiểu concept của patten thì tốt hơn là ghi nhớ duy nhất về ví dụ

Nói về design pattern thì giới thiệu luôn cuốn Dive Into Design Patterns là đỉnh của chóp nha. Đọc xong thì master design pattern. Mua sách ở đây

2. Separation of Concerns

Mục đích của pattern này không gì ngoài

A principle for how applications should be architected

Là nguyên lý cho application nên được tổ chức như thế nào

Seperation là chia ra, theo cách hiểu này thì mỗi component sẽ được chia làm 2 phần (UI và Business). Concerns là mối quan tâm.

Trước khi bắt tay vào để hiểu tại sao cần chia ra như vậy. Cùng xem ví dụ dưới đây.

Để validation email, có 2 điều kiện ta cần phải check

  • Độ dài email phải lớn hơn hoặc bằng 4
  • Độ dài email lớn hơn 0

Đm, ví dụ đọc chán đời vcl, lớn hơn 4 kiểu gì chả lớn hơn 0. Nhưng tui chán nghĩ cái ví dụ cụ thể, nên các ông đọc tạm. Ok, lúc này ta cần bind class cho end user biết lúc nào email input đúng, khi nào sai

<template>
<input
type="email"
class="form-control"
placeholder="E-mail"
:value="email"
@input="update($event)"
:class="{
'is-valid': email.length >= 4 && email.length > 0,
'is-invalid': !(email.length < 4 && email.length > 0),
}"
/>
</template>

<script>
import validateEmail from '../validate-email';

export default {
name: 'EmailInput',
props: ['email'],
methods: {
update($event) {
this.$emit('update:email', $event.target.value);
},
validateEmail,
},
};
</script>

Trông cũng đâu tệ đúng không?. Nhưng tới hồi mà cái component nó lớn lên, tôi thề là các ông không phân biệt được đâu là UI, đâu là Business Logic code

Thay vì viết source logic loằng ngoằng trên teamplate (vốn là phần chỉ xử lý UI logic), ta có thể tách logic validation Email thành file js riêng

export default function validateEmail(email) {
return email.length >= 4 && email.length > 0;
}
Phần xử lý logic cho validation email giờ đã nằm trong một file js duy nhất. Việc này tuân thủ Vuejs Design Pattern mà ta đã đề cập ở trên

Business Logic nằm ở một phần riêng biệt. Source code giờ chia thành 2 phần UI và Business, rất tốt cho reusable sau này!

Quay trở lại với EmailInput.vue

<template>
<input
type="email"
class="form-control"
placeholder="E-mail"
:value="email"
@input="update($event)"
:class="{
'is-valid': validateEmail(email),
'is-invalid': !validateEmail(email),
}"
/>
</template>

<script>
import validateEmail from '../validate-email';

export default {
name: 'EmailInput',
props: ['email'],
methods: {
update($event) {
this.$emit('update:email', $event.target.value);
},
validateEmail,
},
};
</script>

Phần binding class cho email này được sử dụng thông qua function validateEmail. Khá là tiện và tốt cho các ứng dụng Vue lớn.

3. Third-Party Libraries as Controlled Components

Trong quá trình development một Vuejs Applications, sẽ có lúc ta cần sử dụng các Libraries bên ngoài

Các libraries này gọi chung là Third-Party Libraries. Lấy một ví dụ đơn giản, trường hợp applications của các ông muốn cho phép end user gửi emoji. Thả phẫn nộ chẳng hạn, library các ông sẽ cân nhắc là emoji

https://emoji-button.js.org/

Với yêu cầu này, với một lối suy nghĩ thông thường và đơn giản. Ta có thể thảy library này thẳng vào App.vue

<template>
<div id="app" class="row d-flex justify-content-center">
<div class="col-md-5 mt-3">
<div class="card">
<div class="card-header">Emoji Selector</div>
<div class="card-body">
<form @submit.prevent="submit">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" readonly>
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button">Button</button>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</div>
</template>

<script>
export default {
name: 'App',
data () {
return {
emoji: '',
}
},
methods: {
submit () {
console.log(
'Emoji: ',
this.emoji
);
}
}
}
</script>

<style src="bootstrap/dist/css/bootstrap.css">

Ban đầu thì vậy cũng ổn, nhưng tới khi applications sử dụng tới vài chục cái library vấn đề bắt đầu phát sinh. App.vue lúc này như một đống hỗn độn, lèo nhèo.

Chưa nói đến scalable, lúc này maintainable cũng đã là một vấn đề lớn.

Nếu sử dụng Vuejs Design Pattern, ta có thể bưng library vào trong component. Component bây giờ trở nên dễ dàng hơn để kiểm soát. Reusable khá ổn, nếu cần thì cứ import vào, như sau:

Tui tạo component EmojiInput.vue

<template>
<div class="input-group">
<input type="text" class="form-control" readonly :value="modelValue.emoji" />
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" ref="emojiBtn">
{{ modelValue ? modelValue.emoji : 'Select' }}
</button>
</div>
</div>
</template>

<script>
import { EmojiButton } from '@joeattardi/emoji-button';

export default {
name: 'EmojiInput',
props: {
modelValue: {
required: true,
},
options: {
default() {
return {};
},
},
},
mounted() {
const picker = new EmojiButton(this.options);
const btn = this.$refs.emojiBtn;

picker.on('emoji', (emoji) => {
this.$emit('update:modelValue', emoji);
});

btn.addEventListener('click', () => {
picker.togglePicker(btn);
});
},
};
</script>

Component này đứng độc lập, nhiệm vụ của nó chỉ là sử dụng Emoji từ Third-party library. Qua về các component khác hoặc App.vue, easy for us. Chỉ cần import vào là xài

<template>
<div id="app" class="row d-flex justify-content-center">
<div class="col-md-5 mt-3">
<div class="card">
<div class="card-header">Emoji Selector</div>
<div class="card-body">
<form @submit.prevent="submit">
<div class="form-group">
<EmojiInput v-model="emoji"
:options="{ position: 'bottom' }" />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</div>
</template>

<script>
import EmojiInput from '@/components/EmojiInput.vue';

export default {
name: 'App',
components: {
EmojiInput,
},
data() {
return {
emoji: '',
};
},
methods: {
submit() {
console.log('Emoji: ', this.emoji);
},
},
};
</script>

<style src="bootstrap/dist/css/bootstrap.css">
</style>
vuejs design patternRồi xong, mọi thứ trở nên đơn giản. Dễ dùng, tốt cho maintain.

4. The Teleport Component

Bắt đầu với khái niệm chuẩn chỉnh nhất về Teleport ở trang chủ của Vuejs

Teleport provides a clean way to allow us to control under which parent in our DOM we want a piece of HTML to be rendered, without having to resort to global state or splitting this into two components.

Teleport cung cấp một cách hoàn hảo để control component cha nào muốn render thêm HTML ở trên DOM, nhưng không cần phải resort lại global state hoặc chia nó thành 2,3 component nhỏ.

Teleport ở đây cũng được hiểu như đường ống bên Mẽo hay ArabSaudi đã suy nghĩ và có plan để hiện thực hóa.

Thay vì chuyển người hay chuyển hàng thì ta chuyển code ra ngoài Vue application (ra ngoài <div id=”app”>)

Ví dụ cơ bản nhất là mở dialog, open modal

<body>
<div style="position: relative;">
<h3>Tooltips with Vue 3 Teleport</h3>
<div>
<modal-button></modal-button>
</div>
</div>
</body>

Để mang component show modal ra khỏi Vue, ta có thể sử dụng CreateElement, cách làm này hơi khoai vì source trong component không phải lúc nào cũng chỉ có vài dòng. Lớ ngớ làm loạn cả Vue Applications

const app = Vue.createApp({});

app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal!
</button>

<div v-if="modalOpen" class="modal">
<div>
I'm a modal! 
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
`,
data() {
return {
modalOpen: false
}
}
})

Với teleport, ta có thể đem source của modal ra ngoài Vue app mà không cần phải create element ở App.vue

  <teleport to="body">
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal! 
(My parent is "body")
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
vuejs design pattern

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Kinh Nghiệm Khi Phỏng Vấn Với Người Nhật Giúp Ứng Viên Ghi Điểm Tuyệt Đối

kinh nghiệm phỏng vấn với người Nhật
Kinh Nghiệm Khi Phỏng Vấn Với Người Nhật Giúp Ứng Viên Ghi Điểm Tuyệt Đối

Đối với nhiều ứng viên, phỏng vấn luôn là phần căng thẳng và khó khăn vì cần phải cố gắng thể hiện tốt nhất năng lực của bản thân trực tiếp với nhà tuyển dụng. Đặc biệt, với người Nhật – những người được xem là có lối sống quy củ và tác phong nghiêm túc bậc nhất, việc phỏng vấn sẽ càng trở nên quan trọng hơn. Ở Việt Nam hiện nay đã xuất hiện khá nhiều các công ty IT đến từ Nhật Bản. Vậy có những kinh nghiệm phỏng vấn với người Nhật nào mà các ứng viên nói chung mà các lập trình viên nói riêng không nên bỏ qua nếu muốn đậu phỏng vấn?

kinh nghiệm phỏng vấn với người Nhật
Kinh Nghiệm Khi Phỏng Vấn Với Người Nhật Giúp Ứng Viên Ghi Điểm Tuyệt Đối

Cần chuẩn bị thật tốt trước khi bắt đầu buổi phỏng vấn

Khi biết mình được lên lịch để tham gia phỏng vấn với doanh nghiệp Nhật Bản, bạn cần ngay lập tức chuẩn bị cho mình mọi “hành lí” một cách chỉn chu nhất. Với người người Nhật, cái nhìn đầu tiên, sự tiếp xúc từ những giây đầu tiên ảnh hưởng khá nhiều đến thái độ và sự đánh giá của họ đối với bạn. Chính vì thế, việc có được một vẻ ngoài gọn gàng, thái độ lịch sự và chuẩn bị đầy đủ mọi tài liệu là rất cần thiết.

Đến đúng giờ là yếu tố tuyệt đối nên tuân thủ trong mọi cuộc phỏng vấn, nhất là với người Nhật. Ứng viên nên chuẩn bị cho mình một bộ Tây phục gọn gàng và vừa vặn để giúp bạn trông chuyên nghiệp và thành thạo hơn. Đầu tóc nên được cắt và buộc gọn gàng, phái nữ có thể trang điểm nhẹ nhàng để gây ấn tượng tốt hơn với nhà tuyển dụng. Khi gặp người phỏng vấn bạn nên cúi nhẹ người để chào và nở nụ cười thân thiện. Các kỹ năng mềm được phát huy khi giao tiếp sẽ giúp bạn rất nhiều trong quá trình phỏng vấn nhờ thái độ hòa nhã và cởi mở này.

Một số lưu ý khi trả lời phỏng vấn với người Nhật

Trả lời thành thật khi giới thiệu về bản thân và những điểm mạnh, điểm yếu

Người Nhật có khả năng phán đoán thái độ và biểu cảm của người đối diện khá tốt, vậy nên những ứng viên trả lời về bản thân theo kiểu nói quá hay quanh co thường rất dễ bị phát hiện. Khi trả lời, ứng viên hãy cố gắng giới thiệu một cách ngắn gọn và rõ ràng các thông tin về bản thân mình cũng như những kinh nghiệm làm việc đã có được. Hãy tự tin và nhìn thẳng vào đối phương khi trả lời, đó cũng là một cách để thể hiện bản lĩnh và sự mạnh mẽ của ứng viên.

Nhắc đến các điểm mạnh và điểm yếu của bản thân một cách thành thật. Nếu có thể, hãy khéo léo cho nhà tuyển dụng thấy được rằng những điểm mạnh này của bạn sẽ đóng góp được gì cho công ty và các điểm yếu sẽ được bạn khắc phục như thế nào trong tương lai. Sự thành thật khi trả lời những câu hỏi này sẽ giúp bạn rất nhiều khi nhà tuyển dụng tiếp tục đặt những câu hỏi từ câu trả lời của bạn và khai thác sâu hơn.

Việc làm PHP lương cao

Việc làm Javascript lương cao

Việc làm IT manager hấp dẫn

Xem thêm Nguyên Tắc 4 KHÔNG Khi Xin Việc Ai Cũng Cần Nhớ

Thái độ khiêm tốn, thân thiện và cầu tiến

Việc đạt được thành tựu trong công việc hay các bằng cấp bạn tích lũy được trong quá trình trau dồi kiến thức chuyên môn của mình là rất tốt. Điều đó chứng tỏ năng lực chuyên môn của bạn đủ giỏi và bạn hoàn toàn có thể đảm nhận công việc ở vị trí mới, công ty mới. Tuy nhiên, với người Nhật, họ đánh giá cao tinh thần ham học hỏi, sự khiêm tốn và sẵn sàng chấp nhận những thách thức hơn là các thành tích của một cá nhân.

Người Nhật rất khiêm tốn. Người Nhật không phủ nhận năng lực của một cá nhân nhưng điều họ thích thú vẫn là sự hài hòa, do đó đây cũng là lưu ý quan trọng bạn cần nắm về kinh nghiệm phỏng vấn với người Nhật. Hãy kể về những thành tích của mình một cách vừa đủ và chia sẻ với người phỏng vấn tinh thần sẵn sàng cống hiến và không ngại học hỏi của bạn để buổi phỏng vấn thành công hơn nhé!

phỏng vấn với người Nhật

Lịch thiệp và thoải mái trong cách ứng xử

Đừng quá gồng mình hay căng thẳng vì lo sợ trong buổi phỏng vấn. Hãy thoải mái với chính mình và người đối diện để buổi phỏng vấn diễn ra suôn sẻ hơn, hai bên có thể trao đổi thông tin cho nhau một cách dễ dàng để hiểu rõ nhau hơn. Hãy tự tin về những gì mình chia sẻ và thoải mái trao đổi với nhà tuyển dụng mọi vấn đề mà bạn gặp phải để tìm được hướng đi chính xác nhất cho mình nhé.

  NÊN & KHÔNG NÊN Để Đàm Phán Lương Thành Công Khi Phỏng Vấn
  Những Kinh Nghiệm Phỏng Vấn Hữu Ích Cho Sinh Viên Mới Ra Trường

Ngoài ra, trong các buổi phỏng vấn, ứng viên cũng có thể mang theo sổ tay để ghi chú các vấn đề cần thiết hoặc muốn lưu ý. Nhà tuyển dụng sẽ không có vấn đề gì với việc này mà thậm chí còn đánh giá cao những người chú trọng đến việc ghi chép để tránh quên thông tin sau này. Điều này cho thấy bạn là người cẩn thận và luôn biết cách chuẩn bị tốt trong mọi tình huống.

Mỗi đất nước, mỗi con người đều có nhiều tính cách khác nhau và nhiều thái độ khác nhau với việc phỏng vấn. Để thành công trong một buổi phỏng vấn, kinh nghiệm phỏng vấn với người Nhật là bạn hãy chia sẻ thành thật và thẳng thắn để hai bên có thể hiểu rõ nhau và làm việc tốt đẹp hơn trong thời gian sau này. Đón đọc thêm nhiều bài viết hấp dẫn khác tại TopDev dành cho dân IT nhé!

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Cách cài đặt plugin gợi ý code Tabnine, thuật toán AI thông minh

cài đặt plugin
Cách cài đặt plugin gợi ý code Tabnine, thuật toán AI thông minh

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

Chào các bạn, chúng ta đều biết rằng, ngày nay việc viết mã nguồn (code) đối với lập trình viên không còn là việc quan trọng hàng đầu nữa.

Chính vì vậy, ngày càng có nhiều công cụ ra đời để hỗ trợ cho lập trình viên giảm bớt thời gian vào những việc không cần thiết, như gõ cọc cạch từng dòng mã nguồn.

  5 tips cải tiến chất lượng phát triển Mobile App
  Bộ cài đặt Laravel Installer đã hỗ trợ tích hợp Jetstream

Mình đã có một bài viết về Codota – cũng là một AI gợi ý code khá hay cho các công cụ như InteliJ. Các bạn có thể tham khảo bài viết đó tại đây nhé:

Còn ở trong bài viết này thì mình sẽ cùng các bạn cài đặt plugin Tabnine trên  các phần mềm soạn thảo code hàng đầu tiện nay như: VS Code, InteliJ Idea, Sublime Text. Tabnine cũng là một AI gợi ý code khá hay mà các bạn nên thử.

I. Tabnine là gì?

Tabnine bản chất là một công cụ được phát triển dựa trên các thuật toán học sâu (Deep Learning), với dữ liệu đào tạo được lấy từ hơn hai triệu tệp từ mã nguồn trên Github.

Hiện tại thì plugin Tabnine hỗ trợ khoảng hơn ba mươi ngôn ngữ lập trình khác nhau. Các bạn có thể tham khảo danh sách mà nó hỗ trợ trong hình bên dưới.

cai-dat-plugin-tabnine-goi-y-code (1)

Ngoài ra thì Tabnine cũng hỗ trợ nhiều công cụ lập trình khác nhau, trong số đó hầu hết là các công cụ lập trình phổ biến. Cụ thể là:

cai-dat-plugin-tabnine-goi-y-code (2)

II. Cài đặt Tabnine trên các công cụ VS Code, InteliJ Idea, Sublime Text

Okay, trong phần tiếp theo này mình sẽ cùng các bạn cài đặt Tabnine trên VS Code, IntelliJ Idea và Sublime Text – đây đều là những công cụ lập trình phổ biến hàng đầu hiện nay.

#1. Cài đặt Tabnine trên Visual Studio Code (VS Code)

+ Bước 1: Các bạn vào mục Extension => sau đó tìm kiếm từ khóa Tabnine như hình bên dưới.

cai-dat-plugin-tabnine-goi-y-code (3)

+ Bước 2: Chọn kết quả đầu tiên => và sau đó bấm Install để bắt đầu cài đặt.

cai-dat-plugin-tabnine-goi-y-code (4)

Quá trình cài đặt diễn ra tự động, nếu trong trường hợp bạn không muốn dùng nữa thì có thể nhấn Disable để vô hiệu hóa tạm thời, hoặc nhấn Uninstall để gỡ bỏ Plugin nhé.

cai-dat-plugin-tabnine-goi-y-code (5)

#2. Cài đặt Tabnine trên InteliJ Idea

+ Bước 1: Đối với phần mềm lập trình IntelliJ thì đầu tiên, các bạn vào phần: File => chọn Setting => và chọn Plugin

cai-dat-plugin-tabnine-goi-y-code (6)

+ Bước 2: Ở bước tiếp theo, các bạn chọn Plugins => chọn Tab Marketplace => sau đó tìm kiếm từ khóa Tabnine => và bấm Install để cài đặt.

cai-dat-plugin-tabnine-goi-y-code (7)

Các bạn lưu ý là khi cài đặt một plugin trên IntelliJ thì bạn phải Restart lại để active plugin đó như hình bên dưới nhé.

cai-dat-plugin-tabnine-goi-y-code (8)

#3. Cài đặt Tabnine trên Sublime Text

+ Bước 1: Đầu tiên các bạn vào mục Tools => chọn Install Package Control… để cài đặt Package Control..

cai-dat-plugin-tabnine-goi-y-code (9)

+ Bước 2: Các bạn tiếp tục vào mục Tools => Command Palette… Hoặc phím tắt là Ctrl + Shift + P

cai-dat-plugin-tabnine-goi-y-code (10)

+ Bước 3: Tiếp tục các bạn tìm kiếm từ khóa Install Package trong thanh tìm kiếm hiện ra như hình bên dưới.

cai-dat-plugin-tabnine-goi-y-code (11)

+ Bước 4: Cuối cùng các bạn gõ Tabnine => và chọn kết quả đầu tiên như hình bên dưới sau đó bấm vào để cài đặt.

cai-dat-plugin-tabnine-goi-y-code (12)

III. Kết luận

Vâng, như vậy là việc cài đặt plugin Tabnine trên VS Code, InteliJ Idea và Sublime Text cũng tương đối đơn giản phải không nhỉ 🙂

Việc sử dụng các công cụ gợi ý mã nguồn thực sự đem lại nhiều lợi ích về mặt tốc độ cũng như sự chính xác trong cú pháp. Các bạn có thể thấy rõ trong hình bên dưới.

cai-dat-plugin-tabnine-goi-y-code (13)

Tuy nhiên, nói đi cũng phải nói lại, chúng ta vẫn nên nắm được các cú pháp cơ bản của các ngôn ngữ lập trình, bởi vì bản chất lập trình viên hay nhà phát triển vẫn là người quyết định.

Và chỉ khi nắm rõ được những gì chúng ta muốn thì lúc đó các công cụ hỗ trợ mới có ý nghĩa thực sự và thể hiện đúng vai trò của nó. Hẹn gặp lại các bạn trong các bài viết tiếp theo nha !

CTV: Nguyễn Đức Cảnh – Bài viết gốc tại blogchiasekienthuc.com

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Hướng dẫn sử dụng design system framework cho iOS

design system framework
Hướng dẫn sử dụng design system framework cho iOS

Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh

Xin chào, lại là codetoanbug.com đây. Hôm nay chúng ta sẽ cùng sử dụng 1 design system framework cho iOS. Cụ thể chúng ta sẽ xây dựng màn hình giao diện như sau:

Giao diện này thư viện đã làm sẵn, việc của bạn là thay đổi chữ trên màn hình. Hoàn toàn đơn giản và không mất thời gian.

  30 tiện ích Chrome cho designer và dev
  3 sai lầm các iOS Developers thường mắc phải

Xem thêm nhiều Việc làm iOS hấp dẫn trên TopDev

FinniversKit framework

FinniversKit framework là một mã nguồn mở được xây dựng dựa trên design system UI/UX của họ. Các bạn có thể xem mã nguồn tại đây:

https://github.com/finn-no/FinniversKit

Nếu bạn là 1 developer thích quan tâm về trải nghiệm người dùng, các phong cách thiết kế, thì có lẽ bạn đã nghe qua khái niệm design system. Mình xin phép chia sẻ các bài viết dễ hiểu về design system tại đây của tác giả An:

Vậy FinniversKit là chuyển thể 1 design system trên figma hay các công cụ thiết kế khác thành framework có thể sử dụng được trên iOS.

Cùng dạo qua về framework này 1 chút:

Color – Font – Spacing

Chúng ta có dải màu như sau:

Đây là toàn bộ những màu có thể sử dụng ở trong framework này, hay nói cách khác nếu bạn dùng 1 màu khác dải màu này bạn đã không tuân thủ design system của nó.

Nếu như bạn đã đọc về POP trong 1 bài viết trước của tôi, thì hãy theo dõi đoạn code dưới đây bạn sẽ thấy sự quen thuộc:

public protocol ColorProvider {
    var bgPrimary: UIColor { get }
    var bgSecondary: UIColor { get }
    var bgTertiary: UIColor { get }
    var bgBottomSheet: UIColor { get }
    var bgAlert: UIColor { get }
    var bgSuccess: UIColor { get }
    var bgCritical: UIColor { get }
    var btnPrimary: UIColor { get }
    var btnDisabled: UIColor { get }
    var btnCritical: UIColor { get }
    var btnAction: UIColor { get }
    var textPrimary: UIColor { get }
    var textSecondary: UIColor { get }
    var textTertiary: UIColor { get }
    var textAction: UIColor { get }
    var textDisabled: UIColor { get }
    var textCritical: UIColor { get }
    var accentSecondaryBlue: UIColor { get }
    var accentPea: UIColor { get }
    var accentToothpaste: UIColor { get }
    var textCTADisabled: UIColor { get }
    var textToast: UIColor { get }
    var tableViewSeparator: UIColor { get }
    var imageBorder: UIColor { get }
    var decorationSubtle: UIColor { get }
    var iconPrimary: UIColor { get }
    var iconSecondary: UIColor { get }
    var iconTertiary: UIColor { get }
}

Bạn sẽ thấy họ thiết kế 1 protocol để định nghĩa tất cả các màu có thể sử dụng. Định nghĩa mã màu như sau:

public struct DefaultColorProvider: ColorProvider {
    public var bgPrimary: UIColor {
        .dynamicColorIfAvailable(defaultColor: .milk, darkModeColor: UIColor(hex: "#1B1B24"))
    }

    public var bgSecondary: UIColor {
        .dynamicColorIfAvailable(defaultColor: .ice, darkModeColor: .darkIce)
    }

    public var bgTertiary: UIColor {
        .dynamicColorIfAvailable(defaultColor: .marble, darkModeColor: UIColor(hex: "#13131A"))
    }

    public var bgBottomSheet: UIColor {
        .dynamicColorIfAvailable(defaultColor: .milk, darkModeColor: .darkIce)
    }

    public var bgAlert: UIColor {
        .banana
    }

Với POP chúng ta sẽ không cần phải kế thừa, nhưng vẫn đảm bảo tính đóng gói của data, cụ thể là màu sắc ở trên.

Còn muốn apply chúng vào project của chúng ta, hãy xem demo của họ:

hay đơn giản là UIColor.ice 😆

Thứ 2 hãy nói về Font. Hay nói cách khác là Typography – kiểu chữ.

Đây là những kiểu chữ mà chúng ta có thể sử dụng. Để vận dụng cách apply vào, đơn giản vào file FontDemoView.swift.

lazy var items: [FontItem] = {
        return [
            FontItem(font: .title1, title: "title1"),
            FontItem(font: .title2, title: "title2"),
            FontItem(font: .title3, title: "title3"),
            FontItem(font: .bodyStrong, title: "bodyStrong"),
            FontItem(font: .detailStrong, title: "detailStrong"),
            FontItem(font: .captionStrong, title: "captionStrong"),
            FontItem(font: .caption, title: "caption"),
            FontItem(font: .bodyRegular, title: "bodyRegular"),
            FontItem(font: .body, title: "body"),
            FontItem(font: .detail, title: "detail")
        ]
    }()

Về spacing – khoảng cách có thể sử dụng như hình:

Components

Về các components trong framework này, là phần rất quan trọng để chúng ta có thể tái sử dụng nó ở nhiều nơi. Các components phổ biến nhất như button, textfield, loading… sẽ tiết kiệm rất nhiều thời gian cho chúng ta. Thay vì bạn sẽ phải vẽ lại 1 nút: về độ bo, đổ bóng, shadow, hiệu ứng… thì việc đơn giản là tái sử dụng lại các dạng nút mà họ đã hỗ trợ:

Để hiểu cách dùng, chúng ta lại đơn giản vào màn hình demo ButtonDemoView.swift của họ. Nếu bạn thực sự không biết nó thuộc phần demo nào, hãy sử dụng công cụ debug UI xem 🤔

Còn rất nhiều components khác mà bạn có thể chạy ứng dụng demo của họ để xem. Tôi rất thích framework này, vì nó còn hỗ trợ cả dark mode – chế độ tối:

Nhiều components khác, ví dụ loading:

Sử dụng FinniversKit vào project iOS

Để sử dụng framework này, trong phần readme có nhiều cách, trong đó có cách đơn giản là sử dụng pod.

Riêng bài viết này tôi sẽ sử dụng Carthage. Lý do vì tôi bị ám ảnh việc pod build rất chậm khi sử dụng quá nhiều pods trong Podfile. Và bài hướng dẫn này cũng có mục đích cho bạn tham khảo triển khai Carthage như thế nào.

Đầu tiên bạn phải cài đặt Homebrew:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Rồi update:

brew update

Cài đặt carthage:

brew install carthage

Khi máy bạn đã cài xong. Hãy tạo 1 file Cartfile trong thư mục project của bạn:

touch Cartfile

Thêm dòng này vào file:

github "finn-no/FinniversKit" "master"

Tạo file input.xcfilelist:

$(SRCROOT)/Carthage/Build/iOS/FinniversKit.framework

Tạo file output.xcfilelist:

$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/FinniversKit.framework

Tạo file carthage.sh:

# carthage.sh
# Usage example: ./carthage.sh build --platform iOS

set -euo pipefail

xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX)
trap 'rm -f "$xcconfig"' INT TERM HUP EXIT

# For Xcode 12 make sure EXCLUDED_ARCHS is set to arm architectures otherwise
# the build will fail on lipo due to duplicate architectures.

CURRENT_XCODE_VERSION=$(xcodebuild -version | grep "Build version" | cut -d' ' -f3)
echo "EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200__BUILD_$CURRENT_XCODE_VERSION = arm64 arm64e armv7 armv7s armv6 armv8" >> $xcconfig

echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200 = $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200__BUILD_$(XCODE_PRODUCT_BUILD_VERSION))' >> $xcconfig
echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig

export XCODE_XCCONFIG_FILE="$xcconfig"
carthage "$@"

Thêm quyền chạy cho nó bằng cách gõ terminal:

chmod +x ./carthage.sh

Cuối cùng chạy lệnh sau để build thư viện trên:

./carthage.sh update --platform iOS  --new-resolver

Lệnh trên để nó không build lại các framework Carthage đã build và chỉ build cho iOS. Đợi chờ lần đầu build, sau đó Carthage sinh ra thư mục framework đã build cho iOS:

../Carthage/Build/iOS/FinniversKit.framework

Phần còn lại là thêm thư viện vào.

Đầu tiên Tab vào General của project và nhấn vào nút “+” của phần Linked Frameworks and Library

Sau khi đã add Lib cần thiết vào, chúng ta đi chuyển đến Build Phases, nhất vào nút +, chọn New Run Script Phase:

/usr/local/bin/carthage copy-frameworks

Và điền như hình:

Việc này để Xcode copy framework vào project và sử dụng.

Sau khi đã thêm FinniversKit thành công, chúng ta hãy tạo màn hình login demo chẳng hạn:

import UIKit
import FinniversKit

class ViewController: UIViewController {
    private lazy var loginView: LoginView = {
        let loginView = LoginView()
        loginView.translatesAutoresizingMaskIntoConstraints = false
        return loginView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setup()
    }
    
    
    private func setup() {
        loginView.model = LoginViewDefaultData()
        
        view.addSubview(loginView)
        
        NSLayoutConstraint.activate([
            loginView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
            loginView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            loginView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            loginView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
    }
    
}

Kết quả như hình ảnh đầu bài.

Toàn bộ project mẫu bạn có thể tải tại đây:

https://github.com/lexuanquynh/petProject.git

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

Xem thêm tại https://www.facebook.com/codetoanbug 

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Hướng dẫn pull images từ docker repository, registry (docker pull)

docker pull

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

Hướng dẫn pull images từ docker repository, registry (docker pull)

  20 trường hợp sử dụng lệnh Docker cho developer
  Cách thiết lập một dự án Symfony để làm việc với Docker Subdomains

Ví dụ docker pull

Để pull docker image ta dùng lệnh sau:

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

Trong đó có các OPTIONS sau:

--all-tags , -a Tải tất cả các tag của image trong repsitoryDownload all tagged images in the repository
--disable-content-trust true Bỏ qua bước verify image
--platform experimental (daemon)API 1.32+Thiết lập platform nếu server cho phép nhiều platform
--quiet , -q Thu gọn log của lệnh

Ví dụ: pull image ubuntu với tag là 18.04

docker pull ubuntu:18.04

Hướng dẫn pull images từ docker repository, registry (docker pull)

Okay, Done!

References: https://docs.docker.com/engine/reference/commandline/pull/

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Lấy thông tin version của ứng dụng từ tập tin META-INF/MANIFEST.MF bên trong tập tin jar

thông tin version
Lấy thông tin version của ứng dụng từ tập tin META-INF/MANIFEST.MF bên trong tập tin jar

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

Một nhu cầu mà chúng ta thường gặp là làm sao để biết được ứng dụng mà chúng ta đang chạy có version là bao nhiêu, giúp chúng ta có thể biết được những feature mà ứng dụng đang hỗ trợ cho tới version này. Trong Java thì tuỳ theo ứng dụng mà các bạn đang sử dụng là gì, Web application hay Desktop application thì cách lấy thông tin version của ứng dụng sẽ khác nhau. Đối với các ứng dụng Java Desktop hoặc Java Console, các bạn có thể lưu trữ và lấy thông tin version của ứng dụng từ tập tin META-INF/MANIFEST.MF bên trong tập tin jar của ứng dụng.

  Hướng dẫn cài đặt và cấu hình để dùng nhiều version PHP (Multiple versions PHP)
  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java

Xem thêm các việc làm Java lương cao trên TopDev

Ví dụ như mình có một ứng dụng Java Console khi chạy sẽ in ra dòng chữ “Hello from Huong Dan Java”:

Lấy thông tin version của ứng dụng từ tập tin META-INF/MANIFEST.MF bên trong tập tin jar

Mình đã sử dụng Maven Shade Plugin để build ứng dụng này, và khi build ứng dụng, mình đã thêm một số thông tin liên quan đến ứng dụng vào tập tin META-INF/MANIFEST.MF bên trong tập tin jar như sau:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.6.3
Built-By: khanh
Build-Jdk: 15.0.1
Main-Class: com.huongdanjava.mavenshadeplugin.Application
Implementation-Title: maven-shade-plugin-example
Implementation-Vendor-Id: com.huongdanjava
Implementation-Version: 0.0.1-SNAPSHOT
Specification-Title: maven-shade-plugin-example
Specification-Version: 0.0.1-SNAPSHOT

Trong những thông tin này thì thông tin header “Implementation-Version” chứa thông tin về version của ứng dụng.

Để lấy thông tin này và hiển thị ra cho ứng dụng, các bạn có thể sử dụng đoạn code sau:

public String getVersion() throws IOException {
URLClassLoader cl = (URLClassLoader) Application.class.getClassLoader();
URL url = cl.findResource("META-INF/MANIFEST.MF");
Manifest manifest = new Manifest(url.openStream());
Attributes attr = manifest.getMainAttributes();

return attr.getValue("Implementation-Version");
}

với class Application là một class bất kỳ của ứng dụng.

Ví dụ của mình như sau:

package com.huongdanjava.mavenshadeplugin;

import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.apache.commons.lang3.StringUtils;

public class Application {

public static void main(String[] args) throws IOException {
String version = getVersion();

System.out.println(StringUtils
.capitalize("hello from Huong Dan Java. Application version is " + version));
}

private static String getVersion() throws IOException {
URLClassLoader cl = (URLClassLoader) Application.class.getClassLoader();
URL url = cl.findResource("META-INF/MANIFEST.MF");
Manifest manifest = new Manifest(url.openStream());
Attributes attr = manifest.getMainAttributes();

return attr.getValue("Implementation-Version");
}
}

thì khi build lại ứng dụng rồi chạy nó, các bạn sẽ thấy kết quả như sau:

Lấy thông tin version của ứng dụng từ tập tin META-INF/MANIFEST.MF bên trong tập tin jar

Earthly là công nghệ gì?

earthly
Earthly là công nghệ gì?

Bài viết được sự cho phép của tác giả Lê Chí Dũng

Earthly là cú pháp để định nghĩa bản build cho hệ thống của bạn và dùng lại nó để dựng lại ở nơi khác như các server, cloud,…. Nó hoạt động giống với build đã cài đặt trong hệ thống hiện tại của bạn. Các bản build đóng gói có thể dễ dàng dùng lại.

  "Cơ hội phát triển sự nghiệp AI với các ngành nghề là tương đồng" - Bảo Đại, AI Researcher tại Knorex
  5 cách mà Deep Learning ảnh hưởng đến cuộc sống của bạn

Home page: https://earthly.dev/

Earthly dùng làm gì?

Khi dùng Earthly bạn sẽ dễ dàng build system cho server mà không cần quá nhiều kiến thức như chuyên gia dựng server và rút ngắn thời gian build. Vì tất cả đều chứa trong build đều được đóng gói và dc sử dụng lại bất kỳ ngôn ngữ nào.

Tài liệuhttps://docs.earthly.dev

Tập lệnh xây dựng có thể hiểu và lặp lại với Earthly

❤️ Makefile + Dockerfile = Earthfile

Nó là kết hợp Makefile và Dockerfile. Earthly lấy một số ý tưởng hay nhất từ ​​Makefiles và Dockerfiles và kết hợp chúng thành một đặc điểm kỹ thuật.

Lợi ích

  • Các bản dựng lặp lại (Repeatable builds)
  • Cú pháp quen thuộc (A familiar syntax)
  • Lưu vào cache để tăng tốc độ cài đặt (Caching for more speed)

Ví dụ

https://docs.earthly.dev/examples/examples

Building things

Case study

Bạn có quá nhiều instants trên các Cluster server khác nhau nằm trên nhiều khu vực và trong mỗi instant thì cài docker, build abc đễ hỗ trợ các kiểu giống nhau.

Việc này thì đòi hỏi DevOps có nhiều kinh nghiệm để remote vào từng cluster build lại hệ thống mới để integration, bla bla. Thay vì lặp lại 1 việc nhiều lần mà lại có rủi ro sai sót khi miss 1 bước hay 1 package nào đó thì dùng Earthly chỉ cần build 1 bản tốt nhất rồi để nó rebuild trên các cluster khác một cách nhanh gọn.

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Clean code với Vuejs Anti pattern – Phần 2

clean code
Clean code với Vuejs Anti pattern – Phần 2

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

Tiếp nối series về chuỗi bài Vuejs Anti Pattern, Kieblog hân hạnh giới thiệu bài viết số 2 về chuỗi bài này. Xúc hết hai ba phần của chuỗi bài viết này thì khả năng code tăng lên khá nhiều rồi nhé.

Bài viết này chủ yếu bổ sung thêm một số phần còn thiếu về naming, template và prop validation. Nhưng pattern này tuy nhỏ, nhưng không nên vì nhỏ mà khinh thường bỏ qua.

Nhỏ mà có võ nha mấy ba!

  10 kinh nghiệm khi làm việc với các dự án lớn viết bằng Vue.js
  3 phút làm quen với Vue.js

Xem thêm nhiều chương trình tuyển dụng VueJS hấp dẫn trên TopDev

1. Naming components – Vuejs Anti pattern

Về việc đặt tên cho components, thường một số bạn đặt tên component vô tội vạ, thích đặt gì thì đặt cái đó

Đặt tên component quá chung chung và không thể hiện được ý nghĩa của component có thể ảnh hưởng lớn tới project sau này. Cũng gây khó khăn không nhỏ cho việc maintain.

// This would not be an appropriate name as it conflicts with HTML elements.
Vue.component('form', Form)

// This is a better name as it's multi-word and there are less chances to conflict.
Vue.component('signup-form', Form)

Component nếu chỉ đặt tên form sẽ gây confuse cho người sử dụng. Best idea là thêm vào purpose của component, signup-form.

Pattern này là một Vuejs Anti pattern khá nhỏ và đơn giản, tuy nhỏ nhưng không kém phần quan trọng.

2. Template expressions

Often times, when we’re displaying items on the screen, we may have to compute values and call functions to change the way our data looks.

Thi thoảng, khi hiển thị items lên màn hình, ta có thể tính toán giá trị và gọi function để thay đổi data nếu cần thiết

Thay vì gọi thẳng function ở phía template hoặc viết logic ở phần này, ta có thể đem function tính toán này vào computed.

Việc này giúp việc maintain và đọc source sau này trở nên cực kì đơn giản và gọn gàng

// Bad 
<nuxt-link :to="`/categories/${this.category.id}`" class="card-footer-item">View</nuxt-link>

// Good
<nuxt-link :to="categoryLink" class="card-footer-item">View</nuxt-link>

export default {
props: ['category'],
computed: {
categoryLink () {
return `/categories/${this.category.id}`
}
}
}

3. Prop validation

Giao tiếp giữa các component cũng như parent và child component tất nhiên sẽ sử dụng props. Tuy nhiên một số ông chỉ đơn giản là thảy props vào, còn chuyện props có đúng hay không thì không bàn tới

export default {
props: {
firstName: {
type: String
},
lastName: {
type: String
},
age: {
type: Number
},
friendList: {
type: Array
}
},
}

Việc này theo đánh giá thì khá là tệ. Props thì định nghĩa ở component con, nhưng việc truyền props vào cho component con lại do thằng cha quản lý

Nếu gửi props sai thì sao?, props gửi không đúng hoặc sai có thể gây ra nhiều con bug ảo lòi

  props: {
firstName: {
type: String,
required: true,
default: 'John'
},
lastName: {
type: String,
required: true,
default: 'Doe'
}
}

Hơn nữa, nếu props đóng vai trò chính trong component thì có thể set required. Nếu không có props có thể gây ra bug -> required

Ta cũng có thể tạo ra các validator cho props nếu cảm thấy việc này là cần thiết. Trường hợp ở dưới dây component sẽ chỉ render nếu age > 18. Các trường hợp khác component sẽ không render

props: {
age: {
type: Number,
required: true,
validator: value => {
return value >= 18
}
},
}
À, về pattern, anti pattenr thì Vuejs 2 Design Patterns là một cuốn sách không nên bỏ qua nha

4. Tham khảo

Vuejs Anti Pattern còn có phần 1 rất là hay nha. Anh em đã tham khảo về pattern thì không nên bỏ qua

Thank you for spend a time to read – Hope you have nice week. Happy coding!

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Build executable jar sử dụng Maven Shade Plugin

Maven Shade Plugin
Build executable jar sử dụng Maven Shade Plugin

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

Maven Shade Plugin là một Maven plugin cho phép chúng ta có thể build các uber-jar. Nói nôm na thì uber-jar là những tập tin .jar ngoài chứa source code của ứng dụng thì nó còn chứa các dependencies mà ứng dụng đó đang sử dụng. Từ đó, nó giúp chúng ta có thể build các ứng dụng Java có thể chạy standalone được.

  Tại sao lại dùng Gradle thay thế Maven và Ant
  Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins

Lấy ví dụ như mình có một Maven project với một main class đơn giản, khi chạy sẽ hiển thị dòng chữ “Hello from Huong Dan Java” như sau:

package com.huongdanjava.mavenshadeplugin;

import org.apache.commons.lang3.StringUtils;

public class Application {

public static void main(String[] args) {
System.out.println(StringUtils.capitalize("hello from Huong Dan Java"));
}
}

Trong ví dụ này, mình có sử dụng thư viện commons-lang3 để in hoa chữ cái đầu tiên của dòng chữ này.

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>

Kết quả khi chạy ứng dụng:

Build executable jar sử dụng Maven Shade Plugin

Bây giờ, mình sẽ khai báo để sử dụng Maven Shade Plugin để build ứng dụng này có thể chạy standalone được:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.huongdanjava.mavenshadeplugin.Application</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

Ở đây, mình đã cấu hình để chạy Maven Shade Plugin khi chúng ta build ứng dụng với phase “package”. Lúc đó, Maven Shade Plugin sẽ chạy goal “shade” để đóng gói source code của chúng ta với các dependencies mà nó đang sử dụng. Mình còn cấu hình resources transformer cho Maven Shade Plugin với ManifestResourceTransformer cho phép chúng ta có thể định nghĩa một mainClass trong tập tin META-INF/MANIFEST.MF của tập tin jar, giúp cho tập tin jar sau khi build có thể chạy standalone được.

À, có một lưu ý là Maven Shade Plugin chỉ chạy được với Java từ version 7 trở lên thôi nhé các bạn! Các bạn có thể cấu hình Maven project của mình như sau để có thể sử dụng Maven Shade Plugin được:

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

Này là do mình sử dụng Java 8.

Bây giờ, nếu các bạn chạy Maven build với goal “clean package” cho project này, sau đó mở Terminal trên Linux/macOS hoặc Console trên Window, vào thư mục target của project, chạy câu lệnh: “java -jar maven-shade-plugin-example-0.0.1-SNAPSHOT.jar”, các bạn sẽ thấy kết quả như sau:

Build executable jar sử dụng Maven Shade Plugin

Như các bạn thấy, mặc dù mình có sử dụng thư viện commons-lang3 cho ứng dụng của mình, nhưng mình không cần phải khai báo classpath đến thư viện này gì cả. Đó là bởi vì, thư viện này đã được include vào tập tin maven-shade-plugin-example-0.0.1-SNAPSHOT.jar rồi!

Các bạn cũng có thể định nghĩa một số thông tin khác trong tập tin META-INF/MANIFEST.MF bên trong tập tin jar, bằng cách cấu hình Maven Shade Plugin như sau:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Specification-Title>${project.artifactId}</Specification-Title>
<Specification-Version>${project.version}</Specification-Version>
<Implementation-Title>${project.artifactId}</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
<Implementation-Vendor-Id>${project.groupId}</Implementation-Vendor-Id>
</manifestEntries>
<mainClass>com.huongdanjava.mavenshadeplugin.Application</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

Lúc này, build lại project, extract tập tin jar, các bạn sẽ thấy tập tin META-INF/MANIFEST.MF có nội dung tương tự như sau:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.6.3
Built-By: khanh
Build-Jdk: 15.0.1
Main-Class: com.huongdanjava.mavenshadeplugin.Application
Implementation-Title: maven-shade-plugin-example
Implementation-Vendor-Id: com.huongdanjava
Implementation-Version: 0.0.1-SNAPSHOT
Specification-Title: maven-shade-plugin-example
Specification-Version: 0.0.1-SNAPSHOT

typeof của React element để làm gì?

typeof
typeof của React element để làm gì?

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

Chúng ta viết một react component và bạn nghĩ mình viết JSX

<marquee bgcolor="#000">Chào buổi sáng</marquee>

Nhưng thật ra chúng ta đang gọi hàm này

React.createElement(
    /* type */ 'marquee',
    /* props */ { bgcolor: '#000' },
    /* children */ 'Chào buổi sáng'
)

Và function trên sẽ trả về cho chúng ta một objectngười đời gọi object này là React element. Nó báo với React tiếp theo cần phải làm gì

  3 bước tối ưu hiệu năng React App bằng các API mới của React
  3 tools giúp bạn tăng hiệu năng của React App một cách bất ngờ

Xem thêm nhiều việc làm ReactJS lương cao trên TopDev

{
    type: 'marquee',
    props: {
        bgcolor: '#000',
        children: 'Chào buổi sáng',
    },
    key: null,
    ref: null,
    $$typeof: Symbol.for('react.element'), // ai đây ta?
}

$$typeof là cái gì vậy? và tại sao nó có value là Symbol?

Nếu chỉ cần sử dụng React thì việc biết hay không biết đến  cũng không ảnh hưởng gì thế giới, chỉ dành cho các bạn thích tò mò.

Việc chèn thêm một HTML bằng code js như thế này đã từng rất phổ biến

const messageEl = document.getElementById('message');
messageEl.innerHTML = '<p>' + message.text + '</p>';

Mọi thứ thật tuyệt vời cho đến khi ai đó cố tình nhét giá trị <img src onerror="stealYourPassword()"> cho message.text. Một kiểu hack nhẹ cũng rất phổ biến

Để tránh kiểu tấn công này, chúng ta dùng document.createTextNode() hoặc textContent, hoặc trục xuất hết các ký tự < và > để nó không thể nào chạy được.

Tất nhiên không phải ai cũng biết và nhớ hết các thủ tục xử lý này khi nhận giá trị input từ user. Đó là lý do tại sao, các thư viện như React, việc trục xuất này được thực hiện mặc định

<div>
{message.text}
</div>

Trong trường hợp chúng ta biết mình đang làm gì, muốn render thẻ HTML

dangerouslySetInnerHTML={{ __html: message.text }}

Vậy dùng React thì an toàn tuyệt đối? Không

Phải nói có nhiều lắm cách tấn công dùng HTML và DOM. Việc chặn hết là quá khó và quá tốn thời gian.

Ví dụ nếu render <a href={user.website}>, và trang web dẫn đến có thể chỉ là javascript: stealYourPassword(), hay spreading kiểu này <div {...userData}> cũng nguy hiểm phết.

Vì với cách viết này

// escape tự động
<div>
    {message.text}
</div>

…đã đủ an toàn lắm rồi đúng không? Không phải lúc nào cũng đúng. Đó là lý do tại sao có $$typeof

Một React element là một object như thế này

{
  type: 'marquee',
  props: {
    bgcolor: '#ffa7c4',
    children: 'hi',
  },
  key: null,
  ref: null,
  $$typeof: Symbol.for('react.element'),
}

Tất nhiên chúng ta sẽ tạo ra object này bằng việc gọi React.createElement(). Nếu chúng ta sẽ lưu trữ object như một JSON ở phía server

// server cho phép user lưu ở dạng JSON
let expectedTextButGotJSON = {
  type: 'div',
  props: {
    dangerouslySetInnerHTML: {
      __html: '/* put your exploit here */'
    },
  },
  // ...
};
let message = { text: expectedTextButGotJSON };

// Với React 0.13 đây là tử nguyệt
<p>
  {message.text}
</p>

React 0.13 đây là điểm bị lợi dụng để tấn công XSS. (Đáng lẽ ra ở phía Server không nên để cho user lưu dạng JSON như thế)

Phiên bản 0.14 React hỗ trợ xử lý con bug này bằng cách thêm đánh dấu đây chính hiệu là react element bằng Symbol

{
  type: 'marquee',
  props: {
    bgcolor: '#ffa7c4',
    children: 'hi',
  },
  key: null,
  ref: null,
  $$typeof: Symbol.for('react.element'),
}

Bởi gì user hổng thể nào đặt một Symbol vào trong file JSON. Thậm chí mấy ông làm backend ẩu tả cho phép return JSON thay vì text cũng không vấn đề (Đoạn này chắc lão Dan đang cáo mấy chú Backend)

Điều tuyệt vời nữa là Symbol.for() thì scope ở mức global giữa các môi trường như iframe, worker. Nghĩa là việc ném các component qua lại giữa các môi trường cũng không bị ảnh hưởng.

Tuyển dụng lập trình React lương cao

Vậy nếu trình duyệt không hỗ trợ Symbol thì sao?

Đó là chuyện của user, ai bảo xài trình duyệt cũ thì không được bảo hộ đầy đủ chứ biết sao. React sẽ vẫn thêm vào property $$typeof, nhưng với giá trị 0xeac7, tại sao là 0xeac7? Tại tụi tui (React team) thấy nhìn nó giống chữ “React”

Bài của Dan

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Những điểm mới của Java 8 (phần 5: Tham chiếu phương thức)

tham chiếu phương thức
Những điểm mới của Java 8 (phần 5: Tham chiếu phương thức)

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

Từ phiên bản 8, lập trình viên Java có thể áp dụng kỹ thuật Tham chiếu phương thức (method reference). Trong những đoạn mã nguồn Java, khi bạn nhìn thấy ký hiệu :: (hai dấu hai chấm) thì đó chính là tham chiếu phương thức.

3 dạng của tham chiếu phương thức:

– Phương thức tĩnh (static method)
– Phương thức khởi tạo đối tượng (instance methods)
– Constructor (“Constructor”: hàm tạo về bản chất cũng là phương thức)

Xem thêm các chương trình tuyển dụng Java hấp dẫn trên TopDev

Trong ví dụ trên, tại dòng 15, đã sử dụng kỹ thuật tham chiếu phương thức. Tham chiếu phương thức có thể kết hợp với Streams API giúp việc tăng tính linh hoạt (như chúng tôi đã trình bày trong phần 2).

Download mã nguồn từ server SmartJob: Java8_method_reference
hoặc clone/fork từ repository Github: https://github.com/SmartJobVN/java8

Đỗ Như Vý – Bài viết gốc được đăng tải tại smartjob.vn

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Có phải Qualcomm đang lừa dối người dùng chúng ta?

qualcomm
Có phải Qualcomm đang lừa dối người dùng chúng ta?

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

Mỗi khi Qualcomm ra mắt một thế hệ chip di động mới, hoặc là đưa ra những lộ trình mới trong việc phát triển chip thì thường đi kèm với những lời có cánh như:

Sức mạnh vượt trội, tiết kiệm điện năng hơn nhiều so với thế hệ trước và đặc biệt là ít nóng hơn… Đi cùng với đó là hàng loạt những cải tiến về AI, về sức mạnh đồ họa và khả năng chụp ảnh.

Nhưng thực tế khi ra mắt thì con chip của họ lại không được như những lời quảng cáo đó, đặc biệt là thế hệ chip Snapdragon 888 mới nhất gần đây, nó đang bị tình trạng nóng khi sử dụng các tác vụ nặng và khi chụp ảnh.

  "Ngành IT này học rất dễ, tài liệu ko bao giờ thiếu. Quan trọng là phải có đam mê và chịu cày"
  10 điều mọi nhà phát triển ứng dụng Android nên biết về kiến trúc Architecture

Vậy lý do ở đây là gì? Liệu Qualcomm có đang quảng cáo quá đà và sản phẩm thực tế của họ thì không được như mong đợi? Mời các bạn hãy cùng mình tìm hiểu kỹ hơn trong nội dung bài viết hôm nay nhé.

#1. Tiến trình 5nm không phải là thần thánh

Nếu bạn chưa biết tiến trình 5nm là gì thì các bạn hãy đọc bài viết này để hiểu thêm nhé: Tìm hiểu ý nghĩa thực sự của tiến trình 7nm, 10nm… trên CPU

Trên lý thuyết thì khi tiến trình càng nhỏ => chip càng tiêu hao ít điện năng hơn và máy thì ít bị nóng hơn, nhưng lý thuyết thì vẫn chỉ là lý thuyết mà thôi.

co-phai-qualcomm-dang-lua-doi-nguoi-dung (4)

Không giống với khái niệm tiến trình ngày trước mà Intel hay nói, thực tế hiện nay khi nói tới tiến trình 5nm thì không có nghĩa là bóng bán dẫn chỉ nhỏ tới mức 5nm, mà nó chỉ là một cái tên gọi, là một công nghệ để phân biệt giữa các thế hệ chip mà thôi.

Khi bóng bán dẫn càng nhỏ thì việc sản xuất chip sẽ càng gặp khó khăn hơn và đặc biệt là sẽ gặp phải nhiều vấn đề về kỹ thuật hơn như rò rỉ điện bên trong nơi liên kết các bóng bán dẫn, gây ra hao hụt điện năng và hiện tượng quá nhiệt cũng từ đó mà ra.

Ngoài ra, nếu bóng bán dẫn càng nhỏ thì đòi hỏi vật liệu sản xuất, cũng như là cách thức chế tạo chip cũng phải thay đổi theo để đáp ứng được các tiêu chuẩn hóa lý bên trong.

Trên thực tế ở góc độ người dùng, thậm chí là chuyên gia đi chăng nữa thì chúng ta cũng không thể biết được Qualcomm đã là gì với tiến trình 5nm của họ (đó là một bí mật không thể bật mí). Vậy nên, những hiệu quả mà tiến trình 5nm mang lại thực tế chỉ có Qualcomm mới biết.

#2. Nhồi nhét quá nhiều thứ trong một con chip

Theo như công bố, Snapdragon 888 có các cụm nhân: 1 nhân Cortex X1, 3 nhân Cortex A78 và 4 nhân Cortex A55, nhân Kyro 680.

Trong đó đáng chú ý nhất là nhân Cortex X1 với tốc độ xung nhịp cực cao, có thế nói là tiệm cận với các con chip trên máy tính PC phổ thông hiện nay (cụ thể là 2.84GHz).

Mà các bạn nên nhớ một điều rằng, nhân hay CPU nói chung có xung nhịp càng cao thì CPU đó càng mạnh, nhưng nó sẽ càng nóng hơn khi sử dụng thực tế.

Bạn nào có PC hay sở hữu cho mình một chiếc máy tính cá nhân có cấu hình khủng chắc chắn sẽ hiểu rõ điều này, những CPU có nhiều nhân xung nhịp cao luôn phải đi kèm với một hệ thống tản nhiệt bên thứ 3 mới đủ đảm bảo hiệu năng cho máy.

co-phai-qualcomm-dang-lua-doi-nguoi-dung (2)

Qualcomm cũng cho biết thêm, Snapdragon 888 đã tích hợp luôn bên trong modem 5G tốc độ cực cao, cụ thể thì tốc độ tải xuống là 7.5 Gbps và tải lên là 3 Gbps.

Theo mình nghĩ thì điều này cũng góp phần làm cho Snapdragon 888 nóng lên, bởi khi tích hợp vào bên trong thì đồng nghĩa với việc là bên trong con chip Snapdragon 888 càng chật chội hơn => dẫn tới càng dễ sinh nhiệt hơn.

Ngoài ra, Snapdragon 888 sở hữu  khả năng xử lý màn hình Quad HD với tần số quét lên đến 144Hz, đây là một con số thực sự quá khủng với một thiết bị cầm tay mỏng nhẹ như điện thoại.

Hơn nữa Qualcomm cho biết, họ đã sử dụng những thuật toán xử lý game thế hệ mới để nạp vào con chip mới này nhằm mang lại khả năng chơi game mạnh mẽ hơn.

co-phai-qualcomm-dang-lua-doi-nguoi-dung (3)

Qualcomm còn nhét vào con chip này 3 ISP ( bộ xử lý hình ảnh ) với khả năng xử lý 2.7 Gigapixels trong một giây.

Bộ xử lý này giúp kết hợp dữ liệu từ nhiều camera một lúc nhằm mang tới những bức hình đẹp và sắc nét hơn, hơn nữa chúng còn có khả năng xử lý video chất lượng 4K 120fps và 8K 30fps…

co-phai-qualcomm-dang-lua-doi-nguoi-dung (1)

Và Qualcomm lại nâng sức mạnh của cụm AI lên một tầm cao mới, mà theo như dự đoán là mạnh gấp 2 lần thế hệ trước với bộ xử lý Hexagon 780 (có khả năng xử lý 26 nghìn tỷ phép tính mỗi giây).

=> Đó là những công nghệ tích hợp mà Qualcomm thông tin đến người dùng, phải nói là quá nhiều thứ được tích hợp trong một con chip.

#3. Qualcomm vẫn chưa nghĩ tới việc tối ưu chip (hoặc chưa thể tối ưu chip được tốt hơn)

Hiện nay, các chip nhà Qualcomm đưa ra dường như không được họ quan tâm lắm tới việc tối ưu hiệu năng thực tế, họ chỉ dừng ở mức phát triển công nghệ và phần còn lại là dành cho các bên thứ 3 tự nghiên cứu.

Hoặc cũng có thể là do họ chưa tìm được cách tối ưu tốt nhất cho con chip của mình !

Và thực tế cho thấy, các Flagship chạy Snapdragon 888 gần đây của các nhà sản xuất như Samsung, Xiaomi hay Sony…. đều gặp vấn đề về nhiệt. Rõ ràng là những gì mà các hãng sản xuất điện thoại có thể làm là chưa đủ.

Có thể thấy, dường như  là Qualcomm đã nhồi nhét quá nhiều thứ vào Snapdragon 888 và có thể là những con chip trong tương lai nữa, điều này vô tình khiến mọi thứ như bị quá tải bên trong một con chip nhỏ ti tí.

co-phai-qualcomm-dang-lua-doi-nguoi-dung (5)

Hơn nữa, như mình đã nói ở trên, có vẻ như tiến trình 5nm của Qualcomm vẫn chưa thực sự được tối ưu cho lắm, nếu nhìn qua các thế hệ chip PC thì không phải ngẫu nhiên mà Intel cứ dậm chân ở 14nm – bởi họ chưa tìm được cách tối ưu ở tiến trình nhỏ hơn.

Hay là AMD chẳng hạn, dù đi trước Intel ở tiến trình 7nm nhưng mãi tới tiến trình 5nm thì họ mới thực sự đạt được những ưu thế rõ ràng.

Tóm lại, Qualcomm về cơ bản cũng chỉ là một hãng sản xuất, vậy nên công việc kinh doanh và đạt lợi nhuận cao luôn được họ đặt lên hàng đầu, những lời quảng cáo hơi quá đà cũng là điều dễ hiểu.

Hi vọng là trong tương lai họ sẽ tối ưu lại tiến trình tốt hơn thay vì nhồi nhét nhiều thứ như bây giờ, bởi thực tế là 90% người dùng chẳng dùng hết được những gì mà Qualcomm trang bị cho con chip của họ.

CTV: Lê Đinh Hoàng Vũ – Bài viết gốc tại blogchiasekienthuc.com

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

Xem thêm Việc làm IT hấp dẫn trên TopDev

Intersection Observer API

Intersection Observer API
Intersection Observer API

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

Chúng ta thường phải đặt listener trên sự kiện window.scroll thực hiện một số thao tác tính toán, so sánh với thanh scroll để biết được khi nào element bắt đầu xuất hiện.

Cách làm này gây nhiều vấn đề hiệu năng và tương đối rườm rà. Giờ các trình duyệt đã đồng loạt hỗ trợ Intersection Observer API, chúng ta có một cách hoàn toàn gọn gàng, sạch sẽ mà lại tối ưu hiệu năng hơn nhiều.

  Hiểu về setTimeout và setInterval trong Javascript
  Cấu hình JSP views trong InternalResourceViewResolver với Spring Boot JAR file

Cách sử dụng như sau, chúng ta khởi tạo một instance IntersectionObserver và gọi observe trên element muốn theo dõi (watch là thuật ngữ chuyên ngành hơn)

const myImg = document.querySelector('.animate-me');

const observer = new IntersectionObserver((entry, observer) => {
    console.log({ entry });
    console.log({ observer });
})

observer.observe(myImg);

Trong trường hợp chúng ta muốn observe trên nhiều element cùng lúc

const myImgs = document.querySelectorAll('.animate-me');

const observer = new IntersectionObserver(entries => {
  console.log(entries);
});

myImgs.forEach(image => {
  observer.observe(image);
});

Để thực thi một tác vụ nào đó khi element bắt đầu xuất hiện trong viewport hoặc leave khỏi viewport

const myImgs = document.querySelectorAll('.animate-me');

observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.intersectionRatio > 0) {
      console.log('in the view');
    } else {
      console.log('out of view');
    }
  });
});

myImgs.forEach(image => {
  observer.observe(image);
});

Với điều kiện intersectionRatio > 0 chúng ta biết được element đã xuất hiện trong viewport hay không

Với lazy load, chúng ta chỉ cần observe ở lần đầu tiên khi xuất hiện trên viewport, chúng ta sẽ unobserve nó đi vì không cần tracking tiếp nữa

const myImgs = document.querySelectorAll('.animate-me');

observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.intersectionRatio > 0) {
      console.log('in the view');
      observer.unobserve(entry.target);
    } else {
      console.log('out of view');
    }
  });
});

myImgs.forEach(image => {
  observer.observe(image);
});

IntersectionObserver API nhận thêm params thứ 2, để chúng ta truyền một số config

const config = {
  rootMargin: '50px 20px 75px 30px',
  threshold: [0, 0.25, 0.75, 1]
};

const observer = new IntersectionObserver(entry => {
  // ...
}, config);

Các giá trị có thể truyền vào cho config

  • root element dùng để kiểm tra intersection, nếu null nó sẽ lấy document viewport
  • rootMargin: khai báo như giá trị margin css, ví dụ 3rem 2rem, có thể dùng để thêm offset cho intersection point
  • threhold: mảng giá trị từ 0 đến 1, tương ứng với ratio xuất hiện của element, 0 = hoàn toàn ra khỏi viewport, 1 là đang nằm trong viewport hoàn toàn, callback sẽ được gọi vào tất cả các giá trị đã khai báo

Element được xem là nằm ngoài viewport khi nó đã nằm ngoài viewport + 15px margin

Ứng dụng 1: lazy load image

let observer = new IntersectionObserver(
(entries, observer) => { 
entries.forEach(entry => {
    /* Placeholder replacement */
    entry.target.src = entry.target.dataset.src;
    observer.unobserve(entry.target);
  });
}, 
{rootMargin: "0px 0px -200px 0px"});

document.querySelectorAll('img').forEach(img => { observer.observe(img) });

Ứng dụng 2: Tự động pause video khi ra khỏi màn hình

let video = document.querySelector('video');
let isPaused = false; /* Flag for auto-paused video */
let observer = new IntersectionObserver((entries, observer) => { 
  entries.forEach(entry => {
    if(entry.intersectionRatio!=1  && !video.paused){
      video.pause(); isPaused = true;
    }
    else if(isPaused) {video.play(); isPaused=false}
  });
}, {threshold: 1});
observer.observe(video);

Ứng dụng 3: Toggle class khi header sticky

const primaryNav = document.getElementById('primaryNav');

function callBack ([e]) {
    e.target.classList.toggle("sticky", e.intersectionRatio < 1)
}

const observer = new IntersectionObserver( 
    callBack,
    { threshold: [1] }
);

observer.observe(primaryNav)
@media (prefers-reduced-motion: no-preference) {
  .scroller {
    scroll-behavior: smooth;
  }
}

Tham khảo

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

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

Xem thêm Việc làm IT hấp dẫn trên TopDev