Home Blog Page 110

RxSwift 5: Cài đặt RxSwift

RxSwift 5: Cài đặt RxSwift

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

RxCocoa

RxSwift triển khai các hàm tương tự của Cocoa. RxCocoa hỗ trợ tất cả các API của UIKit và Cocoa. Ngoài ra RxCocoa còn có các tính năng mở rộng, và bạn cũng có thể tự viết hàm mở rộng cho nó.

Tuyển swift lương cao hấp dẫn cho bạn

  RxSwift 10: Làm việc với PublishSubjects
  RxSwift 3: Thuật ngữ về lập trình bất đồng bộ (Asynchronous programming glossary)

Ví dụ về Rx hỗ trợ lắng nghe sự kiện nút switch:

toggleSwitch.rx.isOn
  .subscribe(onNext: { enabled in
    print( enabled ? "it's ON" : "it's OFF" )
  })

trong sự kiện onNext, mỗi khi có sự thay đổi trạng thái của nút mà hiển thị nó đang bật hay tắt, hoặc xử lý tùy ý theo logic app. RxCocoa cung cấp rx.isOn để bạn có thể đăng ký lắng nghe sự kiện đó.

Tương tự, RxCocoa cung cấp API cho nhiều control khác như UITextField, URLSesion, UIViewController…

Cài đặt RxSwift

RxSwift có sẵn trên github tại đường dẫn:

https://github.com/ReactiveX/RxSwift.

RxSwift được phát hành dưới giấy phép MIT, nói đơn giản là bạn có quyền làm gì tùy ý với source code, với điều kiện bạn phải thông báo quyền phải được bao gồm trong các ứng dụng bạn phân phối. Có rất nhiều thứ cần khám phá trong repository này, bao gồm thư viện RxSwift và RxCocoa, nhưng bạn vẫn có thể tìm thấy RxTest và RxBlocking trong đó, cho phép bạn viết unit test. Bên cạnh mã nguồn tuyệt vời, bạn sẽ thấy Rx.playground, trình diễn nhiều toán tử của nó, hay RxExample, chứa nhiều ví dụ trong thực tế. Có nhiều cách để cài đặt RxSwift:

  1. Cài đặt bằng CocoaPods

B1: Đầu tiên các bạn tạo project của mình.

B2: init pod file bằng lệnh: pod init.

Trường hợp nếu máy bạn chưa cài CocoaPod thì gõ lệnh này trước:

sudo gem install cocoapods

B3: sửa Podfile thành:

# Podfile
use_frameworks!

target 'YOUR_TARGET_NAME' do
    pod 'RxSwift', '6.0.0-rc.2'
    pod 'RxCocoa', '6.0.0-rc.2'
end

# RxTest and RxBlocking make the most sense in the context of unit/integration tests
target 'YOUR_TESTING_TARGET' do
    pod 'RxBlocking', '6.0.0-rc.2'
    pod 'RxTest', '6.0.0-rc.2'
end

B4: Gõ pod install và thư viện đã cài xong.

2. Cài đặt RxSwift bằng Carthage

B1: Cài đặt Carthage theo hướng dẫn:

https://github.com/ Carthage/Carthage#installing-carthage

B2: Thêm file mới tên là Cartfile vào project của bạn, và thêm dòng:

github "ReactiveX/RxSwift" "6.0.0-rc.2"

B3: Gõ lệnh:

carthage update

Cộng đồng RxSwift

Cộng đồng hiện tại đang hoạt động rất sôi nổi, nhiệt tình và giúp đỡ nhau. Bạn có thể tham gia cộng đồng tại đường dẫn:

http://community.rxswift.org

Nhiều thư viện mới mọc lên như nấm sau mưa, xem tại đây:

https://github.com/RxSwiftCommunity

Tiếp theo là bạn có thể tham gia chat với các developer khác tại Slack:

http://rxswift-slack.herokuapp.com

Tổng kết

Vậy qua 5 bài đầu tiên, bạn đã có 1 cái nhìn cơ bản về RxSwift. Bạn đã tìm hiểu về sự phức tạp của lập trình bất đồng bộ, chia sẻ state, tạo ra side effects.

Bây giờ bạn đã biết RxSwift là giải pháp tuyệt vời để giải quyết các khó khăn đó. Chúng ta sẽ cùng nhau đi sâu vào từng phần của RxSwift trong bài tiếp theo. Cùng nghiên cứu về Observables.

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

Lib requests có gì hay mà dùng thay urllib

Lib requests có gì hay mà dùng thay urllib

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

Python là một ngôn ngữ già, có thể bạn chưa biết, Python tuổi dê Python ra đời từ thời mới có HTTP, và nổi tiếng là hỗ trợ tận răng, nên không có gì lạ nếu Python có kèm sẵn thư viện standard để thực hiện HTTP request với tên urllib.

Vậy nhưng khi lên mạng tìm kiếm hay hỏi quanh đây: dùng gì để gọi HTTP trong Python?, câu trả lời phần lớn đều là cài: pip install requests.

  Biến toàn cục (global), biến cục bộ (local), biến nonlocal trong Python
  11 tip học Python dành cho các “newbie”

Requests không phải có từ ngày Python xuất hiện, nhưng vào thời Python 2.6 2.7 (cỡ 2012-2013), requests đã rất phổ biến, ví dụ như câu trả lời trên StackOverFlow năm 2013.

Requests (có chữ s) xuất hiện với một API cực kỳ thân thiệt, với motto (khẩu hiệu): Python HTTP for Humans do urllib có sẵn trong Python2 quá rắc rối. API của requests nổi tiếng đến mức gần như ngôn ngữ lập trình nào cũng có một thư viện “nhái” requests của Python, nó quá đơn giản, tới mức … trước đây không thư viện nào từng làm vậy.

(API của thư viện là các function mà thư viện đó public cho người dùng sử dụng, ví dụ requests có: requests.get, requests.post.)

requests logo

Sau gần chục năm phát triển, requests giờ đã nằm dưới mái nhà Python Software Foundation.

Với các tính năng được quảng cáo ở bản v1.0.0, cuối năm 2012

    International Domains and URLs
    Keep-Alive & Connection Pooling
    Sessions with Cookie Persistence
    Browser-style SSL Verification
    Basic/Digest Authentication
    Elegant Key/Value Cookies
    Automatic Decompression
    Unicode Response Bodies
    Multipart File Uploads
    Connection Timeouts
    Thread-safety

Có thể dễ đoán rằng những tính năng được quảng cáo trên chính là những gì urllib Python thời đó chưa hỗ trợ (trong Python còn có cả thư viện tên urllib2… để thêm phần phức tạp). Nhưng với Python 3.5 trở đi, rất nhiều trong số trên đã được hỗ trợ trong urllib.

Còn đây là các tính năng được quảng cáo ở phiên bản mới nhất:

    Keep-Alive & Connection Pooling
    International Domains and URLs
    Sessions with Cookie Persistence
    Browser-style SSL Verification
    Automatic Content Decoding
    Basic/Digest Authentication
    Elegant Key/Value Cookies
    Automatic Decompression
    Unicode Response Bodies
    HTTP(S) Proxy Support
    Multipart File Uploads
    Streaming Downloads
    Connection Timeouts
    Chunked Requests
    .netrc Support

Nếu bạn đọc các tính năng này mà không hiểu gì, thì nó chỉ chứng minh một điều là HTTP là một giao thức rất lằng nhằng và phức tạp. Đáng kể nhất có:

Changed in version 3.4.3: This class now performs all the necessary certificate and hostname checks by default. To revert to the previous, unverified, behavior ssl._create_unverified_context() can be passed to the context parameter.

  • Connection Pooling: bình thường khi viết code truy cập vào 1 website, ta có thể nghĩ đơn giản là requests.get rồi lấy kết quả là xong chuyện, hết phiên. Nếu muốn truy cập trang khác cùng website đó, ta lại requests.get để truy cập mới. Phía dưới requests.get thực hiện tạo 1 TCP connection, sau đó mới gửi HTTP request qua connection này. Việc tạo connection là công việc khá tốn kém (CPU, thời gian), đặc biệt với HTTPS, tạo SSL connection còn tốn hơn nhiều lần. Do vậy, để tăng hiệu năng, requests sẽ tự giữ lại connection và dùng lại để truy cập website nếu như các yêu cầu sau đó cùng website, khác page. Xem code tại adapters.py.

Việc này ảnh hưởng tới hiệu năng, nhưng không ảnh hưởng gì nếu bạn chỉ gọi 1 request tới mỗi website.

Đọc code requests

Lib requests thuộc loại nhỏ, tổng cộng 5000 dòng gồm rất nhiều comment. Nó tận dụng các thư viện ngoài khác thay vì tự làm tất cả: urllib3 để thực hiện connection pooling, thực hiện HTTP requests, dùng certifi để cung cấp các SSL certificate mới nhất như các trình duyệt.

$ wc -l *| sort -nr
wc: __pycache__: Is a directory
   5049 total
    982 utils.py
    954 models.py
    767 sessions.py
    549 cookies.py
    533 adapters.py
    305 auth.py
    161 api.py
    131 __init__.py
    126 exceptions.py
    123 status_codes.py
    119 help.py
    105 structures.py
     72 compat.py
     42 _internal_utils.py
     34 hooks.py
     18 certs.py
     14 __version__.py
     14 packages.py

Phần API đơn giản lừng danh nằm trong file api.py, trích bỏ comment:

from . import sessions

def request(method, url, **kwargs):
    # By using the 'with' statement we are sure the session is closed, thus we
    # avoid leaving sockets open which can trigger a ResourceWarning in some
    # cases, and look like a memory leak in others.
    with sessions.Session() as session:
        return session.request(method=method, url=url, **kwargs)

def get(url, params=None, **kwargs):
    kwargs.setdefault('allow_redirects', True)
    return request('get', url, params=params, **kwargs)

def options(url, **kwargs):
    kwargs.setdefault('allow_redirects', True)
    return request('options', url, **kwargs)

def head(url, **kwargs):
    kwargs.setdefault('allow_redirects', False)
    return request('head', url, **kwargs)

def post(url, data=None, json=None, **kwargs):
    return request('post', url, data=data, json=json, **kwargs)

def put(url, data=None, **kwargs):
    return request('put', url, data=data, **kwargs)

def patch(url, data=None, **kwargs):
    return request('patch', url, data=data, **kwargs)

def delete(url, **kwargs):
    return request('delete', url, **kwargs)

urllib3

urllib3 là dependency quan trọng của requests, nó đảm nhận những công việc nặng nề:

urllib3 brings many critical features that are missing from the Python standard libraries:

Thread safety.
Connection pooling.
Client-side SSL/TLS verification.
File uploads with multipart encoding.
Helpers for retrying requests and dealing with HTTP redirects.
Support for gzip and deflate encoding.
Proxy support for HTTP and SOCKS.

Code mẫu:

>>> import urllib3
>>> http = urllib3.PoolManager()
>>> r = http.request('GET', 'http://httpbin.org/robots.txt')
>>> r.status
200
>>> r.data
'User-agent: *\nDisallow: /deny\n'

urllib

urllib và urllib2 thời Python2.7 là những em gái dính lời nguyền mà ai cũng muốn tha thứ. Nhưng ở Python 3.6+, việc dùng urllib không còn quá phức tạp, hãy coi nó như 1 file, nhớ đóng file, hoặc dùng with.

urllib đã kiểm tra SSL certificate

Python 3.6.9 (default, Nov  7 2019, 10:44:02)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib.request
>>> from urllib.request import urlopen
>>> with urlopen("https://dantri.com") as f:
...     content = f.read()
...     print(content[:100])
...
Traceback (most recent call last):
  File "/usr/lib/python3.6/urllib/request.py", line 1318, in do_open
    ...
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)
...
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)>

Kết quả tương tự khi dùng requests do URL https://dantri.com SSL certificate đẫ hết hạn Expire: January 19, 2020

>>> import requests
>>> requests.get("https://dantri.com")
Traceback (most recent call last):
  File "/home/hvn/py3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 672, in urlopen
    ...
  File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)

urllib redirect ngon lành

urllib với JSON API

>>> import json
>>> from urllib.request import urlopen
>>> with urlopen("https://httpbin.org/ip") as f:
...     content = json.load(f)
...     print(content)
...
{'origin': '171.247.169.69'}

>>> import json
>>> from urllib.request import Request, urlopen
>>> with urlopen(
...   Request("https://httpbin.org/post", method="POST",
...           data=json.dumps({"name": "Pymi", "since": 2015}).encode('utf-8'),
...           headers={'Content-Type': "application/json"})
...           ) as resp:
...     print(json.load(resp)['json'])
...
{'name': 'Pymi', 'since': 2015}

Tra cứu thông tin COVID-19

>>> with urlopen("https://corona-stats.online/IT") as f:
...     print(f.read().decode("utf-8"))
...
╔═══════╤═══════╤═══════════╤═══════════╤════════╤════════╤═════════════╤═════════════╤═════════╤══════════╗
        State  Confirmed  Recovered  Deaths  Active  Mortality %  Recovered %  1 Day   1 Week  
╟───────┼───────┼───────────┼───────────┼────────┼────────┼─────────────┼─────────────┼─────────┼──────────╢
 Italy  Total     31,506      2,941   2,503  26,062         7.94         9.33  3,526   21,357  
╚═══════╧═══════╧═══════════╧═══════════╧════════╧════════╧═════════════╧═════════════╧═════════╧══════════╝

Stay safe. Stay inside.

Code: https://github.com/sagarkarira/coronavirus-tracker-cli
Twitter: https://twitter.com/ekrysis

Last Updated on: 18-Mar-2020 16:03 UTC

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

Có thể dùng urllib khi script/chương trình chỉ truy cập mỗi website một lần, dùng trong các script ngắn, hay khi không tiện cài requests. Nhớ sử dụng requests Session khi truy cập 1 website nhiều lần để tăng hiệu năng.

Kết luận

Requests thành công vì sự đơn giản không thể hơn của nó, chứ không phải vì kỹ thuật cao siêu phức tạp.

A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away. The New Hacker’s Dictionary – Eric S. Raymond,

Nhớ mặc định là dùng requests, nhưng không bị sốc khi thấy người ta dùng urllib.

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

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

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

RxSwift 4: nền tảng RxSwift

RxSwift 4: nền tảng RxSwift

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

Lập trình reactive không phải là một khái niệm mới, nó đã tồn tại trong thời gian khá dài. Tuy nhiên không phải lập trình viên nào cũng muốn học về nó. Nếu bạn đang đọc bài này, bạn ít nhiều quan tâm đến nó. Khi đến 1 trình độ nào đó, bạn sẽ thấy các vấn đề xoay quanh lập trình tuần tự liên quan đến tính bất đồng bộ của chương trình, từ phía web, ứng dụng, server. Do vậy nhu cầu xử lý tính bất đồng bộ của chương trình là cần thiết.

Tìm công việc swift lương cao cho bạn

  RxSwift 10: Làm việc với PublishSubjects
  RxSwift 3: Thuật ngữ về lập trình bất đồng bộ (Asynchronous programming glossary)

Lịch sử ra đời từ 1 nhóm của Microsoft, muốn xử lý các vấn đề này. Năm 2009 họ tạo ra 1 nền tảng cung cấp cho .Net, gọi là Rx. Sau này nó được open source, các bạn có thể xem thêm tại đây:

http://reactivex.io.

Biểu tượng cho dự án Rx có tên là Volta – 1 con lươn điện!

GitHub - ReactiveX/RxSwift: Reactive Programming in Swift

Chúng ta sẽ lần lượt tìm hiểu các khái niệm của “lươn điện”: observablesoperators và schedulers. Nào chúng ta cùng tìm hiểu nào!

Observables

Một lớp Observable<T> cung cấp cho Rx khả năng tạo ra 1 chuỗi các sự kiện không đồng bộ, tại bất cứ thời gian nào, mà các lớp khác có thể đăng ký lắng nghe được. Nghĩa là có thể nhiều lớp cùng đăng ký lắng nghe(observers) các sự kiện xảy ra trong thời gian thực. Observable có thể hiểu đơn giản là 1 cái trạm phát sóng, và các quan sát viên(giống như cái radio) gọi là observers, có thể lắng nghe 1 trong 3 loại sự kiện:

  • Một next event: là sự kiện mới nhất, đây là cách observers nhận dữ liệu.
  • Một completed event: nghĩa là sự kiện thành công, nghĩa là trạm phát observable đã hoàn thành công việc của mình và không phát ra thêm tín hiệu nào nữa.
  • Một error event: nghĩa là phát ra 1 lỗi và sẽ không phát thêm sự kiện nào nữa.

Nhấn mạnh: Hãy lẩm bẩm trong miệng 2 khái niệm mới đến khi thuộc lòng và hiểu bản chất:

Observable – trạm phát tín hiệu

observers – các quan sát viên thu tín hiệu

Ví dụ, 1 chuỗi phát ra các giá trị nguyên theo thời gian thực được mô tả ở hình sau:

Ngoài số nguyên, bạn có thể phát ra bất cứ thứ gì bạn muốn. Và một trạm phát có thể có nhiều quan sát viên, do vậy bạn thích bao nhiêu observer cũng được, mà không cần phải kế thừa hay ủy quyền gì cả.

1 trạm phát và 3 quan sát viên

Để hiểu hơn, chúng ta xét tình huống cụ thể, khi ứng dụng ios đang tải xuống 1 file lớn trên mạng. Các sự kiện của chuỗi phát ra như sau:

  • File bắt đầu tải, bắt đầu quan sát dữ liệu đến
  • Sau đó, chúng ta liên tục nhận được các phần dữ liệu tải về
  • Nếu có lỗi kết nối mạng, quá trình tải xuống dừng do lỗi
  • Nếu không file tải thành công và quá trình kết thúc thành công

Follow code sẽ như sau:

API.download(file: "http://www...")
  .subscribe(onNext: { data in
    ... nối các phần của file lại
  },
  onError: { error in
    ... hiển thị lỗi cho người dùng
  },
  onCompleted: {
    ... sử dụng file download xong
  })

Trong đoạn code trên, API.Download sẽ trả về 1 Observable<Data>, phát ra chuỗi các data gửi về qua mạng. Bạn đăng ký nghe các sự kiện ở onNext, ở trên là nối các phần của file tải về và lưu tạm vào ổ đĩa. Bạn đăng ký lắng nghe lỗi ở onError, có thể hiển thị lỗi cho người dùng biết. Bạn đăng ký sự kiện tải file thành công ở onCompleted, có thể mở file, hay làm bất cứ thứ gì mà logic app của bạn muốn.

Infinite observable sequences

Hay còn gọi là chuỗi quan sát vô hạn. Không giống như ví dụ trên, chúng ta sẽ có những tính huống quan sát các sự kiện vô hạn. Ví dụ khi bạn muốn quan sát sự kiện thiết bị người dùng thay đổi khung hình ngang hay dọc.

Chuỗi này là không có kết thúc, bạn chỉ biết thời điểm bắt đầu khi bạn quan sát, và luôn xử lý nó cho đến khi ứng dụng kết thúc.

thiết bị xoay ngang hay xoay dọc

Trong RxSwift, code được mô tả như sau:

UIDevice.rx.orientation
  .subscribe(onNext: { current in
    switch current {
      case .landscape:
        ... sắp xếp giao diện người dùng ngang
      case .portrait:
        ... sắp xếp giao diện người dùng dọc
    }
})

Lưu ý đoạn code trên là hư cấu(không chạy được), để mô tả việc rx phát ra chuỗi phát thiết bị đang ở chế độ ngang hay dọc. Tuy nhiên chúng ta sẽ dễ dàng biến điều hư cấu trên thành thật bằng cách tự viết được đoạn code cho nó trong các bài tiếp theo.

Operators

Khác với toán tử thông thường, các toán tử trong Rx cung cấp khả năng mở rộng để giải quyết các phương thức tính toán trừu tượng, giải quyết các vấn đề phức tạp của bất đồng bộ. Bởi vì chúng có khả năng tách biệt và đồng bộ, nên gọi là toán tử. Chúng có khả năng nhận đầu vào không đồng bộ, kết hợp với nhau tạo thành 1 bức tranh lớn hơn về logic app.

Ví dụ phép tính số học thông thường (5 + 6) * 10 – 2. Chúng ta vận dụng thứ tự ưu tiên trong ngoặc trước, nhân chia trước, cộng trừ sau để đưa ra kết quả cuối cùng. Tương tự trong Rx, các toán tử cũng được kết hợp như vậy, theo thứ tự ưu tiên xác định, cuối cùng đưa ra kết quả.

Ví dụ lại cách Rx lắng nghe sự kiện thiết bị thay đổi chiều:

UIDevice.rx.orientation
  .filter { value in
    return value != .landscape
  }
.map { _ in
    return "Portrait is the best!"
  }
  .subscribe(onNext: { string in
    showAlert(text: string)
  })

Mỗi khi thiết bị xoay ngang hay dọc thì rx sẽ phát ra sự kiện đó.

Đầu tiên chúng ta dùng toán tử filter để lọc những giá trị không phải là landscape. Tiếp theo chúng ta dùng toán tử map để trả về 1 đoạn string thông báo “Portrait is the best!”

Schedulers

Hiểu sơ sơ nó na ná giống bộ lập lịch của Apple, tuy nhiên chúng ta sẽ nghiên cứu chúng sau khi đã hoàn thành các kiến thức cơ bản về RxSwift.

  • Trong hình ảnh trên, phần network màu xanh biển sẽ chạy trên NSOperation based scheduler
  • Phần data binddings màu xanh lá cây chạy trên bộ lập lịch background GDC
  • Phần màu đỏ UI để cập nhật các sự kiện UI trên main thread

Trông có vẻ đơn giản đúng không? Nhưng tạm thời chúng ta sẽ quan tâm nó vào các bài sau cùng nhé.

Kiến trúc ứng dụng

Chúng ta có thể chọn lựa bất kỳ loại kiến trúc nào cho RxSwift, có thể MVC – kiến trúc base của apple. Hoặc bạn có thể dùng MVVM – để giải quyết các vấn đề của MVC. Nó là sự chọn lựa của bạn.

Điều đó có nghĩa là bạn cũng có thể dùng RxSwift với những tính năng mới của app, không bắt buộc phải dùng từ đầu.

Có 1 điều là, bằng kinh nghiệm thực tiễn thì MVVM và RxSwift là 1 sự kết hợp tuyệt vời. Sau này có thể bạn ngầm hiểu dùng RxSwift thì mặc định dùng MVVM để triển khai project của mình.

View Model sẽ cho phép bạn hiển thị các thuộc tính quan sát được, bạn có thể liên kết trực tiếp với UI nên dễ dàng cho việc viết mã.

Tuy nhiên tất cả các ví dụ sau này chúng ta sẽ dùng MVC cho việc học RxSwift đơn giản nhất.

Vậy là chúng ta đã hiểu một phần về RxSwift. Trong bài tiếp theo chúng ta sẽ nghiên cứu cách cài đặt môi trường RxSwift cho việc nghiên cứu bộ môn Rx tuy cũ nhưng lại hay ho này.

NoSQL Key Value Stores must know

NoSQL Key Value Stores must know

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

Tìm hiểu về NoSQL và Amazon Web Services tất nhiên không thể bỏ qua khái niệm về Key Value Stores. Đây là nội dung quan trọng cần nắm vững.

Hiểu biết về cơ chế, cách thức lưu trữ và ưu nhược điểm giúp phát triển hệ thống thành công. Ngoài ra, nó cũng rất có ích cho những ai đang muốn thiết kế các hệ thống phân tán lớn.

Bắt đầu ngay thôi nào!

1. Key Value Stores là gì?

key-value store, or key-value database is a simple database that uses an associative array (think of a map or dictionary) as the fundamental data model where each key is associated with one and only one value in a collection. This relationship is referred to as a key-value pair.

Key value stores, hoặc key value database là kiểu cơ sở dữ liệu sử dụng mảng kết hợp. Trong đó mỗi key sẽ tồn tại duy nhất một value trong collection. Mối quan hệ này được gọi là một cặp key-value

Đối với hệ cơ sở dữ liệu phân tán (Distributed System), các khối dữ liệu dữ liệu có thể lên tới vài triệu khối

Key Value Stores

Theo cách thông thường, mỗi table sẽ tồn tại nhiều column. Đơn cử như video, ta có video id, title, url, description, …

Đối với Key Value Stores, key ở đây là video id, tất cả các thành phần khác như title, url, description đều có thể gom thành 1 trong object Json.

Đại điện của kiểu lưu trữ này là Dynamo DB, một số use case phổ biến có thể đề cập tới là:

1.1 Use case

Session store: A session-oriented application such as a web application starts a session when a user logs in and is active until the user logs out or the session times out. During this period, the application stores all session-related data either in the main memory or in a database. Session data may include user profile information, messages, personalized data and themes, recommendations, targeted promotions, and discounts.

Lưu trữ session như web application có thể bắt đầu các session khi user đã đăng nhập. Tất cả sẽ biến mất khi user logout hoặc session hết hạn. Trong quá trình này, ứng dụng sẽ lưu trữ tất cả dữ liệu session vào bộ nhớ hoặc DB. Session có thể bao gồm thông tin cá nhân, tin nhắn, cấu hình dữ liệu và themes, …

Do chỉ với một key và value, kiểu lưu trữ này còn ứng dụng trong Shopping Cart

During the holiday shopping season, an e-commerce website may receive billions of orders in seconds. Key-value databases can handle the scaling of large amounts of data and extremely high volumes of state changes while servicing millions of simultaneous users through distributed processing and storage.

Trong mùa nghỉ lễ mua sắm, các trang thương mại điện tử có thể nhận tới hàng tỷ đơn hàng. Key-value databases có thể giải quyết vấn đề scaling cho lượng dữ liệu khổng lồ này. Phục vụ hàng triệu người dùng đồng thời thông qua quá trình xử lý và lưu trữ phân tán.

2. Hai kiểu Key Value Stores

Có hai kiểu Key Value Stores thường được sử dụng khi thiết kế hệ thống là Object Stores và In Memory DB. Ta sẽ tìm hiểu cả hai kiểu này trong bài viết. Đại diện cho Object Stores là Amazon S3 và In Memory DB là Amazon Redis.

2.1 Object Stores

Object storage, often referred to as object-based storage, is a data storage architecture for handling large amounts of unstructured data

Object storage, hay còn được gọi là object-based storage, là kiến trúc lưu trữ dữ liệu handle dữ liệu lớn (không có cấu trúc)

Về cách lưu trữ này, dữ liệu được chia thành các đơn vị rời rạc được gọi là object và được lưu giữ trong một kho lưu trữ duy nhất, thay vì được lưu giữ dưới dạng tệp trong thư mục hoặc dưới dạng khối trên server.

Object Storage chia dữ liệu lớn thành các unit nhỏ (có kích thước giới hạn). Mỗi Object bao gồm data, meta data (for index, management). Cuối cùng là ID, sử dụng để tìm kiếm trong hệ cơ sở dữ liệu phân tán (Distributed System)

Ngoài ra, Object Storage còn cho phép lưu trữ nhiều bản copy của dữ liệu, nếu một phiên bản bị mất có thể backup hoặc sử dụng phiên bản thay thế một cách nhanh chóng

  • Performs best for big content and high stream throughput – Cung cấp hiệu năng tuyệt vời cho dữ liệu lớn và luồng dữ liệu khổng lồ.
  • Data can be stored across multiple regions – Dữ liệu có thể được lưu trữ trên nhiều vùng.
  • Scales infinitely to petabytes and beyond – Quy mô lớn, mở rộng lên tới hàng petabytes.
  Vì sao SQL tốt hơn NoSQL? (Phần 1)
  NoSQL là gì? Điểm mạnh vượt trội của NoSQL

2.2 In-Memory Databases

In Memory DB giống như cái tên của nó. Thay về sử dụng SSD, Hard Disk để lưu trữ dữ liệu. IM DB muốn sử dụng Ram hoặc các phần Memory khác để lưu trữ dữ liệu.

Đại diện tiêu biểu của In Memory là Amazon Elasticache for Redis.

Use case phổ biến thường được áp dụng là Real-time bidding (đấu giá trực tuyến)

Real-time bidding refers to the buying and selling of online ad impressions. Usually the bid has to be made while the user is loading a webpage, in 100-120 milliseconds and sometimes as little as 50 milliseconds.

Real-time bidding đề cập lớn vấn đề mua bán trên các trang online. Thông thường các lệnh đặt được thực hiện khi người dùng đang loading webpage, chỉ trong 100-120 milliseconds, đôi khi là dưới 50 milliseconds.

Để đáp ứng độ trễ này, In Memory tỏ ra là giải pháp hoàn hảo. Tất nhiên, IMDB cũng là vị trí lưu trữ, cách thức lưu trữ thì vẫn giống như Object Store. Cả hai đều là Key Value Stores.

Key Value StoresVới IMDB, actions writes, reads thực hiện vô cùng nhanh

4. Tham khảo

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

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

Xem thêm IT Jobs for Developer hấp dẫn trên TopDev

JavaScript Engine là gì? Tìm hiểu JavaScript Engine

JavaScript Engine là gì? Tìm hiểu JavaScript Engine

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

JavaScript Engine là gì?

JavaScript Engine là một chương trình máy tính thực thi các đoạn code JavaScript (JS).

JavaScript đọc các đoạn mã JavaScript rồi chuyển nó sang mã máy để máy tính (hoặc phần mềm máy tính như trình duyệt web, server node.js…) có thể hiểu và chạy được.

  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết
  10 trình quản lý file hàng đầu trong JavaScript

JavaScript Engine là gì? Tìm hiểu JavaScript Engine

Nếu bạn đã lập trình với Java hay C/C++ thì có thể hiểu JavaScript tương đương với JDK trong Java hay trình Compiler C/C++ trong lập trình C/C++.

Các bản JavaScript Engine phổ biến

Có nhiều bản JavaScript Engine được phát triển bởi các các vendor (nhà cung cấp) khác nhau. Một số JavaScript Engine phổ biến như:

  • SpiderMonkey  – Phiên bản Javascript engine đầu tiên, được dùng trên trình duyệt web đầu tiên trên thế giới – Netscape Navigator, hiện tại đang được sử dụng trên Firefox, viết bằng C và C++.
  • Chakra – Là một Javascript engine cũng khá lâu đời, ban đầu được sử dụng trên Internet Explorer và biên dịch JScript, nay được dùng cho Microsoft Edge, viết bằng C++.
  • Rhino – Một Engine viết hoàn toàn bằng Java, cũng có lịch sử phát triển lâu đời từ Netscape Navigator, hiện tại được phát triển bởi Mozilla Foundation.
  • Google V8 – Được phát triển bới Google (Chromium Project).

Ngoài các JS Engine trên, còn rất nhiều JavaScript Engine khác như Carakan, JavaScriptCore, TamarinNashorn

JavaScript dùng ở đâu?

Đầu tiên, các JavaScript Engine chủ yếu được phát triển và cài đặt cho các trình duyệt web (web browser). Ví dụ Chrome V8 dùng cho Google Chrome, SpiderMonkey dùng cho trình duyệt FireFox… Tức là chỉ dùng cho client.

Sau này, các JavaScript Engine được áp dụng để lập trình server với Node.js runtime system.

Một số phần mềm cũng áp dụng JavaScript Engine để lập trình phần mềm bằng JavaScript như MongoDB…

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

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

Xem thêm tìm việc javascript lương cao hấp dẫn trên TopDev

black – quên đi nỗi lo PEP8

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

Code Python phải chuẩn PEP8

Ngay khi bạn mới làm quen với Python được vài tuần, mới biết tí for loop hay function, PEP8 từ đâu đó sẽ hiện ra. PEP8 là hướng dẫn viết code chuẩn Python, chứ không phải chuẩn C, Java, hay không có chuẩn nào cả. Nếu tự hoc code một mình, có khi giờ này bạn đã làm ra vài chục script, chạy ầm ầm mà vẫn chưa 1 lần nghe PEP8. Tiêu chuẩn code là thứ chỉ hiện ra rõ ràng, khi ta làm việc với người khác, chỉ sau vài function, sự mâu thuẫn về style sẽ hiện ra ngay, và khi ông Chí Phèo không đồng ý với style của Bá Kiến, thì cả 2 phải lên phường và thống nhất dùng chuẩn chung mà làng Vũ Đại đặt ra – hay ở đây ta gọi là PEP8.

  20 tài liệu học Python thiết thực để trở thành lập trình viên chuyên nghiệp
  10 tips để trở thành Java Developer xịn hơn

PEP8 có thể xem chi tiết tại PEP0008 hay https://pep8.org/, tiêu chuẩn PEP8 được chấp nhận trên toàn trái đất, thậm chí CIA, Google cũng chỉ sửa đi chút xíu, bởi nó là chuẩn hay, chuẩn tốt.

Chuyện đau đầu về xì tai (style)

Style vốn là một thứ dễ gây ra tranh cãi. Tôi thích kiểu Việt Nam dịu dàng, anh thích kiểu Pháp say đắm, ông kia thích kiểu Mỹ mạnh mẽ và hùng hục. Vậy ai là người sai? Cuộc tranh cãi về style viết code đã kéo dài suốt từ ngày lập trình xuất hiện, tới giờ vẫn chưa kết thúc. Bởi đã là style, thì khó nói chuyện đúng sai.

Thế rồi mọi cuộc chơi vui, cũng phải đến hồi kết. Một ngôn ngữ lập trình đơn giản xuất hiện với tên hai chữ Go (sau để tránh nhầm lẫn thì gọi là Golang), và để tăng thêm sự đơn giản, nó đi kèm sẵn một chương trình với tên gofmt (đọc là gâu phằm) – chương trình này sẽ format tất cả code trong thư mục về một chuẩn mà nó đã quy định. Ban đầu, người ta vẫn còn tranh cãi về việc bị ép style, nhưng rồi sau một hồi, lợi ích của mỗi cái tôi đã sụp đổ trước lợi ích tập thể mà gofmt mang lại: mọi đoạn code đều trông giống nhau, khiến style không còn gì để tranh cãi, lập trình viên nhìn code của thằng kia cũng giống như của mình, dễ đọc – dễ hiểu hơn, expert hay newbie đều chung 1 style cả.

gofmt không phải là chương trình đầu tiên làm vậy, trước đây, trong cộng đồng Python đã xuất hiện 1 chương trình tên autopep8 hay Google cũng có YAPF. Nhưng Go là ngôn ngữ đầu tiên mang code formatter vào chính thống, chính thức chấm dứt cuộc chiến vô bổ về style kéo dài vài thập kỷ. Để rồi từ đó, các ngôn ngữ lập trình khác đua nhau học theo như RustElixir và Python thì có black.

Không có giải pháp nào để giải quyết 1 vấn đề tốt hơn là làm cho nó biến mất.

black là gì

Black là một câu lệnh cài bằng pip: pip install black, yêu cầu Python3.6 trở lên mới chạy. black xuất hiện như một project của một lập trình viên nào đó trên in tơ nét, sau vài năm trở nên cực kỳ phổ biến, và giờ đã chính thức được nằm dưới mái nhà PSF (Python Software Foundation) cùng với requests.

Code của black chỉ vọn vẹn 4000 dòng, sử dụng các tính năng mới nhất của Python như f-string, type annotation, asyncio… (vì thế nên yêu cầu Python3.6+ để chạy, mặc dù vẫn có thể format code 2.7)

Dùng black để format code Python

Ví dụ có 1 file foo.py

def sum_two(a,b):
    c= a  + b


    return c

Nếu thành thạo PEP8, thấy ngay có 4 chỗ phải sửa ở đây: a,b thiếu dấu space sau ,c thiếu dấu space theo sau, sau a thừa 1 space, thừa 1 dòng trống trước return. Vậy chỉ 3 dòng code, người review phải gõ ra 4 “vấn đề” về style, và người code ra 3 dòng này, khi đọc review cũng chẳng vui vẻ gì, kể cả người ta nói đúng.

Chạy:

$ black foo.py
reformatted foo.py
All done! ✨ 🍰 ✨
1 file reformatted.

$ cat foo.py
def sum_two(a, b):
    c = a + b

    return c

Đẹp, chuẩn, ngon! Không còn gì mong đợi thêm. black có nhiều option để chỉnh style cho phù hợp với tiêu chuẩn của bạn, hay dùng nhất là để set độ dài của 1 dòng, vốn là 79 ký tự theo chuẩn PEP8, thì black mặc định là 88:

  -l, --line-length INTEGER       How many characters per line to allow.
                                  [default: 88]

Bạn có thể gọi black -l79 . để theo PEP8.

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

Đã đến lúc để quên đi việc format code bằng tay, nhớ vài chục tiêu chuẩn của PEP8, format code hãy để cho đen (black) không vâu lo – việc này để đen không vâu lo. Thêm dòng này vào Makefile của bạn:

fmt:
    black -l79 .

hay cài đặt text editor/IDE tự động chạy black sau mỗi lần save code.

Thêm dòng sau vào CI để bắt quả tang thằng nào không dùng black:

black --check .

Black sẽ thông báo các file chưa chuẩn format:

$ black --check .
would reformat /home/hvn/me/people/content/mypy_simple.py
would reformat /home/hvn/me/people/publishconf.py
would reformat /home/hvn/me/people/pelicanconf.py
would reformat /home/hvn/me/people/fabfile.py
Oh no! 💥 💔 💥
4 files would be reformatted, 1 file would be left unchanged.

Kết luận

Hãy dùng black! Và đừng quên share bài viết này, để cộng đồng code Python không còn mất thời gian ít bổ.

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

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

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

Đánh giá chất lượng từ trải nghiệm người dùng

trải nghiệm người dùng
Đánh giá chất lượng từ trải nghiệm người dùng

Qualitative Testing – Đánh giá chất lượng là gì?

Đánh giá chất lượng có thể được thực hiện dưới hình thức phỏng vấn hoặc các thử nghiệm khả năng sử dụng được quan sát trực tiếp khác. Nó mang tính chất khám phá và với mục tiêu hiểu sâu hơn về trải nghiệm của người dùng. Nhằm mục đích thu thập thông tin về động cơ và trải nghiệm cuộc sống hàng ngày của người dùng hoặc nhóm để xem những chi tiết này có thể ảnh hưởng như thế nào đến việc sử dụng sản phẩm hoặc công cụ của họ.

tối ưu trải nghiệm người dùng
Đánh giá chất lượng trải nghiệm người dùng giúp cải thiện chất lượng app

Tổng hợp và phân tích kết quả

Khi sử dụng các phương pháp đánh giá chất lượng, điều quan trọng là nhà nghiên cứu phải nhận ra rằng chúng có thể có ảnh hưởng đến kết quả nghiên cứu. Vì trải nghiệm của con người đang được nghiên cứu thay vì dữ liệu cứng (số lần nhấp chuột, xu hướng vị trí đăng nhập,…), rất khó để duy trì sự khách quan một cách tuyệt đối trong quá trình thử nghiệm hoặc khi đánh giá kết quả.

Kết quả cũng không nhất thiết phải được sử dụng lại. Điều này là do các yếu tố ảnh hưởng đến trải nghiệm của người dùng rất đa dạng và có thể thay đổi hàng ngày.

Những yếu tố này có thể khiến người dùng bị căng thẳng vào ngày này hơn ngày khác do những sự kiện mới trong cuộc sống của họ hoặc có nhiều trách nhiệm hơn vào ngày hôm đó, người dùng có trải nghiệm cuộc sống hoàn toàn khác nhau. Thậm chí, cả các yếu tố như thời tiết xấu cũng ảnh hưởng đến tâm trạng của người dùng và bất cứ điều gì khác ảnh hưởng đến cuộc sống cá nhân hoặc tình cảm của một người.

  3 bài học xương máu mà mỗi Product Manager đều phải trải qua.
  Kinh Nghiệm Học Coding Dành Cho Dân Trái Ngành

Các phương pháp kiểm tra trải nghiệm người dùng

Tham khảo thêm từ chia sẻ của Kevin Dalvi “12 UX Research Techniques (Quantitative and Qualitative)”.

Phỏng vấn

Thông thường gồm ba loại phỏng vấn:

  • Phỏng vấn trực tiếp: nhà nghiên cứu đặt câu hỏi cụ thể cho người dùng và cố gắng so sánh câu trả lời với những người dùng khác.
  • Phỏng vấn gián tiếp: nhà nghiên cứu cố gắng thảo luận chung nhiều hơn với (các) người dùng.
  • Phỏng vấn mang tính cộng đồng: nhà nghiên cứu quan sát (các) người dùng trong môi trường của chính họ để hiểu cách họ tiếp cận các khía cạnh nhất định, hoàn thành các nhiệm vụ nhất định.

Thực hiện khảo sát

Đây là một cách nhanh chóng để thu thập thông tin từ một số lượng lớn người dùng. Nhưng hạn chế rõ ràng của nó chính là thiếu sự tương tác giữa nhà nghiên cứu và người dùng.

Kiểm tra khả năng sử dụng

  • Kiểm tra có kiểm duyệt: người dùng được đưa vào phòng thí nghiệm và được giao các nhiệm vụ hoặc bài kiểm tra cụ thể để thực hiện.
  • Kiểm tra không kiểm duyệt: người dùng hoàn thành kiểm tra theo thời gian của họ thường từ xa.
  • Kiểm tra đột xuất: là một hình thức thử nghiệm thông thường hơn trong đó người dùng ngẫu nhiên tại một địa điểm xã hội hoặc cộng đồng được yêu cầu sử dụng ứng dụng / sản phẩm và cung cấp phản hồi không chính thức.

Bài viết được phỏng dịch theo bài viết gốc tại freecodecamp.org

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

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

Vẽ đồ thị trong Python với thư viện Matplotlib

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

Trước khi bắt đầu với câu hỏi Tại sao Matplotlib là một thư viện phổ biến trong Python? chúng ta đến với vài câu nói đúc kết của người xưa mà còn nguyên giá trị đến nay.

A picture is worth a thousand words – Một bức tranh hơn ngàn lời nói

Ngạn ngữ Anh

Như chúng ta đã biết Python được sử dụng nhiều nhất trong lĩnh vực phân tích dữ liệu, mà trong khoa học dữ liệu, việc trực quan hóa thông qua các đồ thị, biểu đồ giúp cho chúng ta hiểu được các mối quan hệ trong dữ liệu dễ dàng hơn rất nhiều. Matplotlib là một thư viện sử dụng để vẽ các đồ thị trong Python, chính vì vậy nó là thư viện cực phổ biến của Python. Bạn thử tưởng tượng một file dữ liệu khoảng 20MB, khi vẽ ra đồ thị từ dữ liệu này bạn sướng như phát điên vì có thể hiểu được ngay 20MB đó nói lên cái gì? Ngày nay, khi Big data đang trở thành thực tế, hàng ngày có quá nhiều dữ liệu, việc trực quan hóa dữ liệu càng trở nên cấp thiết và càng thúc đẩy những thư viện như Matplotlib phát triển hơn.

Mục đích của bài hướng dẫn này giúp bạn hiểu được cách vẽ các đồ thị, biểu đồ với thư viện matplotlib và từ đó bạn có thể sử dụng thành thạo nó cho trực quan hóa dữ liệu.

Tìm việc làm python lương cao các vị trí cho bạn

PyLab – Matplotib Cơ Bản

Matplotlib là một thư viện vẽ đồ thị trong Python, cho phép bạn tạo ra các biểu đồ và hình ảnh chất lượng cao. PyLab là một mô-đun trong Matplotlib, cung cấp một giao diện giống như Matlab để làm việc với các biểu đồ một cách dễ dàng.

John D. Hunter, một nhà thần kinh học bắt đầu phát triển matplotlib năm 2003 để mô phỏng các tập lệnh MATLAB, ông qua đời năm 2012 ở tuổi 44. Matplotlib giờ được phát triển và duy trì bởi cộng đồng các nhà phát triển khác.

Trong MATLAB, chúng ta không cần import gì mà có thể sử dụng các hàm có sẵn ngay lập tức khác với Python phải thực hiện import các thư viện cần thiết. Matplotlib có nguồn gốc từ MATLAB do đó module Pylab trong thư viện Matplotlib được xây dựng để có được cách thức sử dụng hàm như MATLAB. Nó đưa một số hàm và lớp từ Numpy và Matplotlib vào namespace giúp cho người dùng MATLAB có thể chuyển đổi sang Python sử dụng dễ dàng.

Khi bạn thực hiện lệnh import sau vào Python:

from pylab import *

Bạn có thể sử dụng ược ngay các hàm như plot(), array() như trong MATLAB. Vấn đề là với câu lệnh import này không ổn, nó bị chồng chéo các module sử dụng trong chương trình Python. Pylab do lịch sử để lại và nó không được khuyến cáo sử dụng, nó sử dụng các tên vô tội vạ với các chức năng ẩn giấu bên trong và rất khó để kiểm tra lỗi, do đó nên sử dụng Matplotlib.

Trong Pylab có rất nhiều các import tiền ẩn khả năng xung đột được che đậy kín. Matplotlib đã từ bỏ module này và khuyến cáo không nên sử dụng Pylab, mang mọi thứ trở nên rõ ràng hơn là để ngầm định. Không có pylab, chúng ta thường sử dụng một câu lệnh thay thế một cách chính tắc:

import matplotlib.pyplot as plt

Phân cấp đối tượng trong Matplotlib

Nếu bạn đã đọc tài liệu của Matplotlib, dòng code dưới đây là một phân cấp với các đối tượng Python lồng vào nhau. Phân cấp ở đây nghĩa là kiểu cấu trúc cây các đối tượng Matplotlib trả về từ plot(). Đối tượng Figure là nơi chứa đồ họa Matplotlib, nó có thể chứa các đối tượng Axes. Dưới Axes là hệ thống phân cấp các đối tượng nhỏ hơn như các đường thẳng, các textbox… Hầu hết các phần tử của đồ thị đều có thể tương tác như đối tượng trong Python.

plt.plot([1, 2, 3])

Ví dụ:

>>> fig, _ = plt.subplots()
>>> type(fig)
<class 'matplotlib.figure.Figure'>

Trong đoạn code trên chúng ta tạo ra hai biến với plt.subplots(), biến đầu tiên là fig chứa Figure, biến thứ hai _ chứa những thứ khác. Đây là cấu trúc Tuple trong Python do plt.subplots() cũng trả về kiểu Tuple. Do cấu trúc phân cấp hình cây, chúng ta muốn truy xuất đến phần tử đánh dấu chẳng hạn:

>>> one_tick = fig.axes[0].yaxis.get_major_ticks()[0]
>>> type(one_tick)
<class 'matplotlib.axis.YTick'>

Biến fig là instance của lớp Figure chứa bên trong nhiều các đối tượng Axes. Mỗi Axes có một yaxis và xaxis và chúng lại chứa một tập các major_sticks và chúng ta lấy cái đầu tiên.

Một ví dụ sau đến từ Matplotlib cho chúng ta hiểu hơn về phân cấp đối tượng trong Matplotlib.

Vẽ đồ thị trong Python với thư viện Matplotlib

Hình ảnh trên được sinh ra từ đoạn code sau đây, bạn có thể tham khảo tại Matplotlib.

Vẽ đồ thị với plot()

import matplotlib.pyplot as plt
%matplotlib inline

plt.plot([1,2,3,4,10])
plt.show()

Khi sử dụng module pylot trong thư viện matplotlib chúng ta sẽ import vào với tên ngắn gọn là plt. %matplotlib inline là câu lệnh của Jupyter Notebook để vẽ được các đồ thị bên trong cell của Jupyter Notebook.

Để vẽ một dạng đồ thị, chúng ta cần xem đối tượng plt có những phương thức nào, bạn có thể sử dụng:

dir(plt)

Câu lệnh plt.plot() sẽ vẽ một đồ thị bằng cách nối các điểm bằng đường thẳng (matplotlib.lines.Line2D). Trong ví dụ này, chúng ta đưa vào một List các số và Matplotlib sẽ vẽ ra đồ thị bằng cách nối các điểm. Bởi vì plt.plot() trả về một đối tượng, do vậy khi muốn hiển thị đồ thị, chúng ta cần gọi plt.show().

Phương thức plot() có 3 tham số:

plot(x, y, format)
  • Tham số x là danh sách các tọa độ trục x
  • Tham số y là danh sách các tọa độ trục y
  • format định dạng đồ thị

Trong ví dụ đầu, khi chúng ta đưa vào một List thì mặc định đó là danh sách tọa độ trục y và định dạng mặc định là vẽ đường thẳng giữa các điểm. Ví dụ trên tương đương với:

plt.plot([1,2,3,4,10])

Kết quả được đường sau khi sử dụng plt.show():

code python vẽ hình

Chú ý, trong bài viết này tôi sẽ sử dụng Jupyter Notebook để demo các ví dụ. Nếu bạn chưa biết cài đặt, sử dụng Jupyter Notebook có thể tham khảo:

Quay lại với phần định dạng đồ thị trong tham số thứ 3 của phương thức plot(). Định dạng này ở dạng viết tắt, nó là tổ hợp của ba thành phần {color}{marker}{line}. Ví dụ “go-” sẽ cho định dạng điểm có màu xanh và nối hai điểm là đường thẳng. Chúng ta thử thực hiện nó xem sao:

Chúng ta có một số định dạng khác như sau:

  • ‘r*–‘ các điểm hình ngôi sao màu đỏ, đường nối các điểm dạng –.
  • ‘bD-.’ các điểm hình kim cương màu xanh dương, đường nối các điểm dạng -.
  • ‘g^-‘ các điểm hình tam giác hướng lên màu xanh lá, đường nối các điểm dạng -.
  • Nếu bạn không muốn các điểm nối với nhau, có thể bỏ định dạng đường thẳng đi, ví dụ ‘go-‘ sẽ thành ‘go’

Vẽ nhiều tập điểm phân tán trên cùng đồ thị

Bạn có thể vẽ nhiều tập điểm phân tán trên cùng một đồ thị bằng cách gọi phương thức plot() nhiều lần. Ví dụ dưới đây sẽ vẽ hai đường đồ thị dựa trên hai tập điểm khác nhau với định dạng khác nhau:

import matplotlib.pyplot as plt

# Vẽ đồ thị
plt.plot([0, 1, 2, 3, 4], [1, 2, 3, 4, 10], 'go-', label='Python')
plt.plot([0, 1, 2, 3, 4], [10, 4, 3, 2, 1], 'ro-', label='C#')
plt.plot([2.5, 2.5, 2.5, 1.5, 0.5], [1, 3, 5, 7, 10], 'bo-', label='Java')

# Đặt tiêu đề và nhãn cho các trục
plt.title('Vẽ đồ thị trong Python với Matplotlib')
plt.xlabel('X')
plt.ylabel('Y')

# Hiển thị chú thích
plt.legend(loc='best')

# Hiển thị đồ thị

thư viện matplotlib

Trong ví dụ này có thêm một số điểm cần chú ý:

  • Thêm nhãn cho từng tập điểm với tham số thứ 4 trong plot().
  • Hiển thị ghi chú các thành phần trong đồ thị với phương thức legend().
  • Hiển thị nhãn các trục tọa độ x, y với xlabel() và ylabel().
  10 Lý do nên học Python trong năm 2024
  11 tip học Python dành cho các “newbie”

Vẽ nhiều đồ thị trong cùng một ảnh

Phần đầu bài viết chúng ta đã biết về phân cấp đối tượng trong Matplotlib, mỗi plt.plot() trả về một đối tượng Figure (là hình ảnh bên ngoài), trong Figure này có rất nhiều các đối tượng Axes là một đồ thị con bên trong. Trong phần này chúng ta sẽ vẽ hai đồ thị cạnh nhau nằm trong cùng một Figure (Hình ảnh).

import matplotlib.pyplot as plt

# Tạo các subplot
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(10, 4), sharey=True, dpi=120)

# Vẽ đồ thị cho từng subplot
ax1.plot([0, 1, 2, 3, 4], [1, 2, 3, 4, 10], 'go-')
ax2.plot([0, 1, 2, 3, 4], [10, 4, 3, 2, 1], 'ro-')
ax3.plot([2.5, 2.5, 2.5, 1.5, 0.5], [1, 3, 5, 7, 10], 'bo-')

# Đặt tiêu đề cho từng đồ thị
ax1.set_title('Python')
ax2.set_title('C#')
ax3.set_title('Java')

# Đặt nhãn cho trục X
ax1.set_xlabel('X')
ax2.set_xlabel('X')
ax3.set_xlabel('X')

# Đặt nhãn cho trục Y
ax1.set_ylabel('Y')
ax2.set_ylabel('Y')
ax3.set_ylabel('Y')

# Đặt giới hạn cho trục X
ax1.set_xlim(0, 6)
ax2.set_xlim(0, 6)
ax3.set_xlim(0, 6)

# Đặt giới hạn cho trục Y
ax1.set_ylim(0, 12)
ax2.set_ylim(0, 12)
ax3.set_ylim(0, 12)

# Căn chỉnh bố cục
plt.tight_layout()

# Hiển thị đồ thị
plt.show()

vẽ đồ thị trong python

Vẽ tập hợp điểm phân tán với scatter()

Sự khác biệt giữa plot() và scatter():

  • plot() không có khả năng thay đổi màu và kích thước điểm trong tập hợp điểm ban đầu nhưng scatter() lại có thể.
  • plot() có thể vẽ các đường nối hai điểm liên tiếp, scatter() thì không.

Ví dụ dưới đây vẽ ra các điểm trên đồ thị với dữ liệu về chiều cao và cân nặng, mỗi điểm có màu ngẫu nhiên và có kích thước cũng ngẫu nhiên.

import matplotlib.pyplot as plt
import numpy as np

# Dữ liệu về chiều cao và cân nặng
height = np.array([167, 170, 149, 165, 155, 180, 166, 146, 159, 185, 145, 168, 172, 181, 169])
weight = np.array([86, 74, 66, 78, 68, 79, 90, 73, 70, 88, 66, 84, 67, 84, 77])

# Màu sắc và kích thước cho các điểm dữ liệu
colors = np.random.rand(15)
area = (30 * np.random.rand(15)) ** 2

# Đặt giới hạn cho trục x và y
plt.xlim(140, 200)
plt.ylim(60, 100)

# Tạo biểu đồ phân tán
plt.scatter(height, weight, s=area, c=colors)

# Đặt tiêu đề và nhãn trục
plt.title("Chiều cao và cân nặng")
plt.xlabel("Chiều cao - cm")
plt.ylabel("Cân nặng - kg")

# Hiển thị biểu đồ
plt.show()

Kết quả như sau:

vẽ biểu đồ trong python

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

Xem thêm tuyển dụng it hà nội, đà nẵng, hcm hấp dẫn trên TopDev

Hướng dẫn build java project, maven project trên Jenkins

Hướng dẫn build java project, maven project trên Jenkins

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

Hướng dẫn build java project, maven project trên Jenkins

Trong ví dụ này mình sẽ thực hiện clone 1 maven project từ github và thực hiện build nó thành file jar. Tất cả sẽ được thực hiện tự động bằng Jenkins.

  10 Java Web Framework tốt nhất
  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết

Yêu cầu:

Trong ví dụ này mình sử dụng 1 project maven trên github có url: https://github.com/stackjava/spring-boot-hello. Đây là 1 ví dụ về spring, đã được cấu hình chạy trên port 8081. Các bạn có thể fork/clone về account github của các bạn để dùng.

(Xem lại: Code ví dụ Spring boot Hello World)

Hướng dẫn build java project, maven project trên Jenkins

Đầu tiên, ta tạo 1 plan build bằng cách click vào New Item

Hướng dẫn build java project, maven project trên Jenkins

Chọn Maven Project và nhập tên cho plan build

Hướng dẫn build java project, maven project trên Jenkins

Ở đây mình dùng source code từ github nên mình sẽ chọn Git (khi build, jenkins sẽ clone source từ github về)

Để Jenkins clone được source code, ta cần cấu hình account git cho nó.

Hướng dẫn build java project, maven project trên Jenkins

Nhập username/password của tài khoản github mà bạn sử dụng để clone source code. (nếu bạn dùng bitbucket, gitlab… thì cũng nhập username/password tương ứng)

Hướng dẫn build java project, maven project trên Jenkins

Nhập repository URL của project git.

Hướng dẫn build java project, maven project trên Jenkins

Phần Credentials chọn account git mà bạn vừa thêm.

Click Save.

Hướng dẫn build java project, maven project trên Jenkins

Sau khi Save, ở màn hình chính chúng ta sẽ thấy plan build vừa tạo.

Click vào icon build để build project.

Hướng dẫn build java project, maven project trên Jenkins

Ở menu bên trái sẽ có trạng thái build của project. Click vào đó để xem.

Hướng dẫn build java project, maven project trên Jenkins

Click vào Console Ouput để xem log realtime của quá trình build.

Bạn sẽ thấy Jenkins tạo workspace, clone source code từ github về workspace, thực hiện build maven project (download các thư viện) thành file jar.

Hướng dẫn build java project, maven project trên Jenkins

Kết quả:

Hướng dẫn build java project, maven project trên Jenkins

Mở workspace ta sẽ thấy file jar được build ra.

Hướng dẫn build java project, maven project trên Jenkins

Chạy thử file jar vừa được build bằng lệnh:

  • java -jar spring-boot-hello-0.0.1-SNAPSHOT.jar

Hướng dẫn build java project, maven project trên Jenkins

Mở trình duyệt và truy cập địa chỉ http://localhost:8081

Hướng dẫn build java project, maven project trên Jenkins

Trong ví dụ tiếp theo chúng ta sẽ thực hiện deploy project, tức là quá trình chạy file jar sẽ được chạy tự động. Có thể là chạy giống như 1 service, up lên server tomcat…

Okay, Done!

References: https://www.jenkins.io/doc/

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

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

Xem thêm Tuyển dụng Java hấp dẫn trên TopDev

Thiết kế Messaging Service WhatsApp – P1

Thiết kế Messaging Service WhatsApp Part 1

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

Tiếp sau chuỗi bài viết về thiết kế hệ thống TinyURL, Kieblog tiếp tục giới thiệu chuỗi bài viết về System Design, hôm nay là Messaging Service.

  Discord đã lưu trữ hàng tỉ messages mỗi ngày như thế nào
  Kafka là gì? Ứng dụng Kafka cơ bản cho hệ thống message

Chat là hệ thống lớn, bao gồm nhiều thành phần và nhiều vấn đề cần giải quyết. Đại thể có thể nói tới: gửi file, các tệp định dạng khác nhau, group chat, thả reaction, …

Chính vì vậy, tóm gọn trong nội dung bài viết, ta chỉ xem xét qua thiết kế hệ thống Chat ở mức basic nhất có thể, qua đó hiểu thêm về Load Balancers và Scalable Web Application.

Bắt đầu ngay thôi!

1. Yêu cầu hệ thống

Messaging Service khi thiết kế yêu cầu phải có những tính năng tối thiểu như sau:

  • Send and receive text messages between two devices – Gửi và nhận tin nhắn giữa hai thiết bị
  • One-on-one conversations with different users – Giao tiếp 1 vs 1 với các user khác nhau trong hệ thống
  • User can see the time of each message – User có thể thấy được thời gian khi gửi từng tin nhắn

Do bài viết có giới hạn nên mình chỉ đề cập tới thiết kế một hệ thống Chat đơn giản:

  • Messages are one-on-one only, i.e, no group messages – Tin nhắn gửi 1-1, không có chat theo nhóm
  • Our server will not store the messages after they’re delivered – Server sẽ không lưu tin nhắn sau khi đã gửi
  • Our messages will be text-only – Nội dung tin nhắn tạm thời chỉ là text.

2. User case Messaging Service

Về user case cơ bản của hệ thống được thiết kế gồm có:

  • Send a message to a person – Gửi tin nhắn tới ai đó
  • If you receive a message and you are online, immediately deliver it. – Nếu nhận được tin nhắn và đang online, tin nhắn tới ngay lập tức.
  • If you receive a message and you are offline, wait till you come online – Nếu nhận được tin nhắn và đang offline, chờ tới khi online trở lại.
  • Get a notification and receive a message – Thông báo khi nhận được tin nhắn mới
Messaging Service

Về phía user, nội dung lưu trữ cũng không cần quá nhiều.

Java

User:

- id

- username

- password

- list<unread_messages>

Java

Message Properties:

- message text

- timestamp

- sender's Id

Rồi, cơ bản về User, System Requirement đơn giản chỉ cần có vậy. Bắt đầu đi sâu hơn vào phần thiết kế tính năng quan trọng nhất – Gửi tin nhắn.

3. Xử lí gửi và nhận tin nhắn

Không lòng vòng lèo vèo, về cơ bản, có hai cách để xử lí gửi tin nhắn là Push và Pull. Ta sẽ tìm hiểu chi tiết từng loại, ưu nhược điểm khi sử dụng trong Messaging Service System.

Đầu tiên là PULL

This is a less sophisticated way to “send” notifications. The device can periodically ask the server if there are any new messages. Say every 2 minutes, the device sends a REST API request to check if there are new messages, and the server responds with yes or no.

PULL là cách đơn giản để gửi notifications. Thiết bị sẽ gửi request tới server định kì trong một khoảng thời gian nhất định về tin nhắn mới. Cứ mỗi 2 phút, sẽ gửi REST API kiểm tra xem có tin nhắn mới hay không, server sẽ phản hồi với có hoặc không.

Cách này rõ ràng tồn tại hai nhược điểm lớn:

  • Độ trễ cao, nếu thời gian định kì lớn thì tin nhắn bị delay quá lâu, không thể chấp nhận tới tận 2 phút.
  • Tuy nhiên, nếu thời gian quá ngắn, request server phải nhận là cực kì lớn. Số lượng người dùng tới vài triệu -> toang.

Một phương thức khác cũng sử dụng PULL là Long Polling. Khi gửi request, server sẽ hold cho tới khi có tin nhắn mới và trả về response.

Thứ hai là PUSH

Thay vì chỉ giao tiếp một chiều với client ở phía chủ động gửi request. Tại sao không giữ connection liên tục giữa client và server sau khi đã mở

Once the client initiates the connection though, it can be kept alive and there can be bi-directional communication.

Tuy nhiên, một khi client khởi tạo kết nối, nó có thể được giữ nguyên và có thể giao tiếp hai chiều. Đó là cơ sở để đẩy dữ liệu đến các device.

3.1 Websocket

Websocket là lựa chọn tốt, đáng để cân nhắc

These are a good choice. WebSockets give you a single bi-directional connection over TCP. Once the connection is established, the client and server can freely exchange information.

Websocket cung cấp kết nối hai chiều (bi-driectional) duy nhất thông 1qua TCP. Một khi kết nối đã được khởi tạo, client và server có thể thoải mái để trao đổi thông tin

3.2 Push Notifications

Với push notification thì hện tại đã có nhiều sự lựa chọn tới từ Google hoặc Apple, mặc dù đôi khi chúng thường chậm hơn Websocket. Tuy nhiên các vấn đề vặt vãnh xung quanh đó thì lại hỗ trợ tốt hơn

Apple thì có Apple Push Notification Service (APNS), hỗ trợ tốt cho các thiết bị iOS. Google thì hỗ trợ với Firebase Cloud Messaging (FCM).

Messaging Service

Với tam giác ba điểm kết nối, Notification cho device iOS hay Android trở nên đơn giản hơn bao giờ hết. Mỗi khi server nhận được tin nhắn mới, nó sẽ gửi request Push Notification tới APNS hoặc GCM. Tuy nhiên, giới hạn cho notification với APNS là nội dung maximum có thể gửi tối đa dừng ở mức 2KB

3.3 Còn với XMPP?

XMPP cũng là một loại protocol phổ biến để messaging communications. XMPP is a protocol (giống như HTTP). Cũng có thể kết hợp XMPP với Websockets và Long Polling

4. Bắt tay vào thiết kế

Thiết kế đơng giản cho Messaging Service như sau. Lưu ý phần Caching và CDN có thể xử lí sau

Messaging Service
  • Đầu tiên, phía App Server sẽ là stateless, không quan tâm tới trạng thái của client. Cũng không lưu trữ gì ở đây (not store anything). App Server sẽ chỉ nhận request và lưu vào distributed In-Memory Cache và NoSQL
  • Khi App Server nhận được request từ notification rằng có message mới, App Servers sẽ đọc từ cache, nếu cache không có thì thực hiện query
  • Phần Load Balancer và Distributed Database tất nhiên là phần không thể thiếu cho các hệ thống muốn large scale

Trên đây là thiết kế tổng quan cho hệ thống, sẽ có phần 2 phân tích kĩ càng hơn về các feature, trả lời các câu hỏi về kĩ thuật cũng như các vấn đề có thể phải giải quyết trong thực tế.

5. Tham khảo

Thank for reading – Have a great 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 Developer hấp dẫn trên TopDev

RxSwift 3: Thuật ngữ về lập trình bất đồng bộ (Asynchronous programming glossary)

RxSwift 3: Thuật ngữ về lập trình bất đồng bộ(Asynchronous programming glossary)

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

Để đi sâu vào Rx, trước tiên chúng ta phải hiểu những khái niệm cơ bản nhất của nó. Sau đây Rx sẽ giải quyết các vấn đề về bất đồng bộ thông qua các khái niệm, thuật ngữ như sau:

Tuyển it swift nhiều ngành nghề từ các công ty

  RxSwift 10: Làm việc với PublishSubjects
  RxSwift 6: Observables

Trạng thái (State)

Cụ thể ở đây là trạng thái có thể thay đổi và chia sẻ. Trạng thái khó để mô tả, do vậy chúng ta sẽ hiểu nó thông qua các ví dụ. Khi bạn mở máy tính của mình lên, ban đầu chạy ổn định. Nhưng bạn để chế độ ngủ và tiếp tục mở nó lên, thì sau 1 thời gian nó không còn nhanh nữa, bị crash đột ngột… do trạng thái máy tính đã bị thay đổi. Dữ liệu trong bộ nhớ, tình trạng pin, các thao tác của người dùng vào máy,… là tổng hợp tất cả các trạng thái của máy tính. Quản lý các trạng thái đó, chia sẻ các trạng thái không đồng bộ và xử lý chúng là điều mà các bạn sẽ học ở loạt bài hướng dẫn Rx này.

Lập trình tuần tự

Là mô hình lập trình mà bạn sử dụng mã để thay đổi trạng thái chương trình của mình. Ví dụ bạn đang chơi với 1 con chó, bạn yêu cầu nó nằm, chạy hay sủa.. theo yêu cầu của bạn.

Mã tuần tự là mã mà bạn có thể đơn giản hiểu được, và CPU máy tính cũng làm theo 1 chuỗi tuần tự đơn giản, và vấn đề phức tạp khi làm các ứng dụng không đồng bộ phức tạp sẽ khó xử lý. Cùng xem ví dụ sau:

override func viewDidAppear(_ animated: Bool) {
  super.viewDidAppear(animated)
  setupUI()
  connectUIControls()
  createDataSource()
  listenForChanges()
}

Chúng ta có thể nôm na dịch hiểu đoạn lệnh trên làm những việc sau: tạo giao diện, kết nối các control trên giao diện với controller, tạo data source, và cuối cùng là lắng nghe các sự kiện thay đổi của nó. Chắc chúng ta hằng ngày vẫn làm những việc như này đúng không? Và có thể bạn đã gặp tình huống ai đó thay đổi thứ tự sắp xếp quá trình trên, ví dụ chúng ta lắng nghe sự kiện trước khi kết nối controls, thì crash sẽ xảy ra!

Các trạng thái của ứng dụng – Side effects

Khi người dùng thay đổi các input vào ứng dụng, thì các trạng thái khác nhau của ứng dụng sẽ sinh ra. Và tùy thuộc vào đầu vào mà sẽ sinh những side effects khác nhau. Ví dụ khi login, người dùng bấm sai thì báo alert, khi đăng nhập mà không có mạng, khi nhập thiếu ô,… Rất nhiều các effect khác nhau có thể xảy ra. Rx sẽ giải quyết toàn bộ những side effects đó, thông qua các khái niệm sau.

Declarative code

Trong lập trình tuần tự, bạn thay đổi trạng thái theo ý muốn. Trong lập trình sự kiện, bạn không tạo ra bất cứ side effects nào. Vì bạn đang sống trong 1 thế giới không hoàn hảo, cho nên sẽ có sự giao thoa giữa 2 hướng lập trình trên. RxSwift chính là sự giao thoa đó.

Declarative code – khái niệm cho phép bạn xử lý các side effects của app giống như lập trình tuần tự. Nghĩa là xử lý các sự kiện bất đồng bộ của app như là các sự kiện tuần tự có thể hiểu được.

Reactive systems

Reactive systems – dịch sát nghĩa hơi khó, bạn hiểu nôm na nó là hệ thống phản ứng sự kiện app cũng được! Nó được định nghĩa thông qua các khái niệm trừu tượng sau:

Responsive: luôn luôn cập nhất UI của người dùng, thể hiện trạng thái mới nhất. Nghĩa là trên màn hình của app đang có gì thì nó luôn lấy được trạng thái mới nhất đó.

Resilient: Mỗi hành vi được xác định riêng biệt và linh hoạt, có cơ chế sửa lỗi. Ví dụ hành vi nhập text vào 1 ô được xử lý riêng so với hành vi bấm nút.

Elastic: Mã xử lý các công việc như điền data vào table, thu thập dữ liệu, chia sẻ tài nguyên..

Message driven: Điều hướng sự kiện app nhằm tái sử dụng, tách lớp của các sự kiện trên app.

Bây giờ hẳn đọc đến đây thì bạn vẫn còn mơ hồ lắm chưa hiểu những khái niệm trên là gì. Tuy nhiên đừng hoảng sợ, bạn đầu ai cũng vậy thôi. Thật khó để giải thích nó khi mà không thực hành đúng không nào. Vậy chúng ta hãy đọc tiếp trong bài 4 nhé.

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 Jobs hấp dẫn trên TopDev

Thuật toán Gradient Descent

Thuật toán Gradient Descent

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

Video trong bài viết

Trong các bài toán machine learning hoặc các bài toán tối ưu, chúng ta thường phải làm việc với những điểm cực trị (thường là điểm cực tiểu) của một hàm số. Hẳn bạn còn nhớ trong Phần 1 của khóa học này về dự đoán doanh thu phim với Linear Regression, chúng ta đã phải cố gắng tìm giá trị nhỏ nhất của hàm chi phí (cost function) mà đôi khi còn gọi là hàm mất mát (loss function). Vậy Thuật toán Gradient Descent là gì?Gradien Descent có liên hệ gì với việc tìm kiếm cực trị bài toán tối ưu?, chúng ta sẽ cùng tìm hiểu trong bài học này nhé.

  Tại sao lại dùng Gradle thay thế Maven và Ant
  10 PHP Instagram Scripts & Widgets tốt nhất

1. Thuật toán Gradient Descent là gì?

Trong kiến thức toán phổ thông chúng ta đã biết, muốn tìm cực trị một hàm số y=f(x)y=f(x) chúng ta sẽ giải phương trình đạo hàm của hàm số f(x)f(x) bằng 0.

f(x)=0f′(x)=0

Tuy nhiên phương trình trên không phải lúc nào cũng giải được dễ dàng, có những trường hợp việc giải phương trình trên là bất khả thi. Vậy khi gặp những tình huống này, chúng ta phải làm gì? May thay, thuật toán Gradient Descent cho chúng ta cách thức tìm các điểm cực tiểu cục bộ này một cách xấp xỉ sau một số vòng lặp. Trong thực tế, các giá trị dữ liệu không có đúng 100% mà đôi khi chúng ta chỉ cần những con số gần đúng. Khi một người hỏi tôi, xác suất cho lần đầu tư chứng khoán lần này là 72%, tôi có nên đầu tư không? Thật sự mà nói 72% đã là một con số khá ấn tượng, mọi thứ ngoài đời không bao giờ có 1+1=21+1=2, nên những cách tính toán xấp xỉ, gần đúng là một giải pháp tuyệt vời.

Trước khi đi vào chi tiết thuật toán Gradient Descent, chúng ta hãy cùng trải nghiệm với một tình huống sau đây. Bạn đang ở trên một ngọn núi đầy sương mù, tầm nhìn bị hạn chế, làm cách nào để có thể xuống được thung lũng một cách nhanh nhất (Ở đây thung lũng chính là những điểm cực tiểu trong bài toán tối ưu). Cách đơn giản là nhìn xung quanh chỗ nào cảm nhận dốc nhất thì bạn bước xuống và từng bước một, cho đến khi bạn không cảm nhận được xung quanh có độ dốc thì đấy chính là thung lũng, nơi bằng phẳng và là điểm cực tiểu của đồ thị.

Tuyệt vời phải không, thuật toán Gradient Descent mô tả chính xác những gì bạn đang trải nghiệm ở tình huống trên. Trong bài viết về Đạo hàm hàm số, độ dốc (slope) của hàm số tại điểm x0x0 chính là đạo hàm của hàm số tại điểm x0x0. Bước đi xuống từ điểm x0x0 sang điểm x1x1 sẽ bằng Δ0Δ0. Ta có:

x1=x0+Δ0x1=x0+Δ0

Chúng ta sẽ tìm hiểu xem thành phần của Δ0Δ0 là gì? Để hướng đi xuống chúng ta có

Δ0=ηf(x0)Δ0=−ηf′(x0)

Dấu âm trong độ dốc nghĩa là chúng ta đang đi xuống và với hệ số ηη. Vậy ta có thể viết lại

x1=x0ηf(x0)x1=x0−ηf′(x0)

Như vậy tại bước thứ n chúng ta có:

xn=xn1+Δn1=xn1ηf(xn1)xn=xn−1+Δn−1=xn−1−ηf′(xn−1)

Nhưng đến khi nào thì kết thúc không bước tiếp? Như trong tình huống, khi nào cảm thấy xung quanh không còn dốc, nghĩa là khi đó xnxn1xn≈xn−1 hay xnxn1xn−xn−1 đạt đến một giá trị khá nhỏ mà chúng ta chấp nhận được.

2. Viết code Gradient Descent trong Python

Ví dụ chúng ta có một hàm số y=x26sinxy=x2−6sin⁡x, đây là một hàm số mà phương trình y=0y′=0 không tìm được nghiệm bằng cách giải phương trình, do vậy chúng ta cần dùng đến Gradient Descent để tìm cực tiểu.

Chú ý: Phần này có liên quan đến xuất đồ thị động dạng ảnh động trong Python, bạn nên tham khảo bài Vẽ đồ thị dạng ảnh động với Animation trong thư viện Matplotlib trước khi đến phần tiếp theo.

Sử dụng gradient descent với learning rate = 0.1

Đầu tiên chúng ta import các thư viện cần thiết.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

Tiếp đến là định nghĩa hàm f(x) và đạo hàm của nó df(x) trong Python, ở đây chúng ta sử dụng hai quy tắc tính đạo hàm:

y=xny=nxn1y=xn→y′=nxn−1
y=sinxy=cosxy=sin⁡x→y′=cos⁡x

Đây là những kiến thức phổ thông bạn đã biết từ hồi cấp 3, do vậy chúng ta có:

y=x25sinxy=2x5cosxy=x2−5sin⁡x→y′=2x−5cos⁡x
def f(x):
    return x**2 - 5*np.sin(x)

def df(x):
    return 2*x - 5*np.cos(x)

Để vẽ đồ thị động chúng ta cần thiết lập một số thông số cho đồ thị như kích thước ảnh, giới hạn các trục tọa độ, một số text sẽ hiển thị trên đồ thị.

fig = plt.figure(figsize=[10, 7])
ax = plt.axes(xlim=(-8, 8), ylim=(-10, 60))
ax.text(-6, 55, 'Hàm số $y=x^2-5\sin{x}$, $step\_multiplier=0.1$, $precision=0.00001$, $start=-10$', fontsize=12)
label_1 = ax.text(-6, 50, '', fontsize=12)
label_2 = ax.text(0, 30, '', fontsize=20)

line, = ax.plot([], [], 'ro-', lw=5)
x = np.linspace(start=-8, stop=8, num=100)
y = f(x)
ax.plot(x,y)

Giờ là lúc sử dụng thuật toán Gradient Descent ở phần 1, chúng ta thiết lập các giá trị ban đầu:

x_1 = -10
x_0 = 0
step_multiplier = 0.1
precision = 0.00001

Ở đây có 4 biến x_0 chứa giá trị trước đó, x_1 là giá trị trong bước tiếp theo, step_multiplier là hệ số kết hợp với độ dốc, ở phần cuối bài chúng ta sẽ biết đến nó với tên gọi tốc độ học (learning rate). Biến precision quyết định khi nào dừng thuật toán, nó là độ chính xác trong phép tính xấp xỉ mà chúng ta mong muốn, ở đây độ chính xác đến 1/100k.

Tiếp theo, chúng ta sẽ cài đặt thuật toán Gradient Descent kết hợp với định nghĩa các phần vẽ hoạt họa:

def animate(i):
    global x_0, x_1
    step_size = abs(x_1 - x_0)

    if step_size > precision:
        x_0 = x_1
        gradient = df(x_0)
        x_1 = x_0 - step_multiplier * gradient
        x = [x_0, x_1]
        y = [f(x_0), f(x_1)]
        line.set_data(x, y)
        label_2.set_text(str(i))
    label_1.set_text('Lần: ' + str(i) + '/50, cost:' + str(f(x_1)) + ', slope:' + str(df(x_1)))
    return line, 

Thuật toán dừng lại khi độ chính xác đạt như mong muốn hay xnxn1<percisionxn−xn−1<percision. Nếu chưa đạt được độ chính xác tính toán bước tiếp theo x1=x0ηf(x0)x1=x0−ηf′(x0) với

    x_0 = x_1
    gradient = df(x_0)
    x_1 = x_0 - step_multiplier * gradient

Cuối cùng, chúng ta sử dụng hàm FuncAnimation để xuất ra đồ thị dạng hình ảnh động:

anim = FuncAnimation(fig, animate, frames=50, interval=400, blit=True)
anim.save('gradient_descent.gif', writer='imagemagick')

Bạn có thể tải Code Jupyper Notebook. Kết quả chúng ta được hình ảnh động như sau:

Sử dụng gradient descent với learning rate = 0.1

Một số nhận xét về kết quả:

  • Những đoạn có độ dốc lớn thuật toán sẽ vượt qua nhanh chóng, những đoạn độ dốc nhỏ, sẽ rất lâu để vượt qua, ví dụ ở dải x[-4,-2] tại đây phải mất hơn 10 vòng lặp để vượt qua.
  • Khi độ dốc lớn thì bước di chuyển cũng lớn do Δ=xnxn1=ηf(xn1)Δ=xn−xn−1=−ηf′(xn−1).
  • Nhìn vào công thức trên, ta có thể kết luận số bước lặp để đi đến kết quả sẽ phụ thuộc các yếu tố:
    • Giá trị khởi tạo của thuật toán
    • Độ chính xác percision
    • Hệ số step_multiplier hay là tốc độ học (learning rate)

3. Điều chỉnh các thông số trong Gradient Descent

Trong kết quả phần trước chúng ta đã nhận xét một số các yếu tố có liên quan đến kết quả của Gradient Descent, chúng ta sẽ cùng tìm hiểu từng yếu tố liên quan này. Công thức cần nhớ là:

Δ=xnxn1=ηf(xn1)Δ=xn−xn−1=−ηf′(xn−1)

3.1 Giá trị khởi tạo

Giá trị khởi tạo là điểm x0x0, nếu điểm này càng gần với điểm cực tiểu thì số bước lặp ít đi. Do bước nhảy phụ thuộc vào độ dốc do đó nếu điểm x0x0 nằm ở phía có độ dốc lớn thì số bước lặp cũng ít đi. Thật vậy, chúng ta điều chỉnh các thông số trong phần 2 như sau:

x_1 = 10

Tức là điểm khởi tạo sẽ ở x0=10x0=10 và xuất kết quả ra được hình sau:

Điểm khởi tạo Gradient descent cho sự khác biệt

Bạn có thể thấy với điểm khởi tạo ở -10, thuật toán hội tụ (đạt đến điểm cực tiểu mong muốn) sau 33 bước lặp, trong khi với điểm khởi tạo là 10 thì chỉ cần 15 bước lặp thuật toán đã hội tụ. Do vậy, việc lựa chọn điểm khởi tạo cho Gradient Descent cũng rất quan trọng để đạt được kết quả nhanh.

3.2 Độ chính xác mong muốn

Trong ví dụ chính, chúng ta sử dụng độ chính xác là 1/100k, vậy nếu thử tăng độ chính xác thêm 1 chữ số 0 nữa tức là chính xác đến 1/1 triệu xem thuật toán hội tụ sau bao nhiêu bước.

Độ chính xác 1/1 triệu

Chúng ta thấy cần đến 35 bước lặp mới đạt đến độ chính xác 1/1 triệu trong khi chỉ cần 33 bước lặp với độ chính xác 1/100k. Trong thực tế, tùy vào lĩnh vực và bài toán cụ thể mà cần có độ chính xác cao hay thấp. Ví dụ với một bài toán kinh tế, khi đưa ra xác xuất lựa chọn phương án là 70% (1/trăm) và 72.3473% (1/triệu) là như nhau, vậy nên chúng ta chọn độ chính xác percision = 0.01 thì thuật toán sẽ hội tụ nhanh hơn mà vẫn đạt được kết quả mong muốn.

3.3 Tốc độ học – Learning rate

Tốc độ hội tụ của Gradient Descent phụ thuộc vào nhiều vào learning rate ηη. Để kiểm tra chúng ta thử tăng tốc độ học ηη từ 0.1 lên 0.2. Kết quả như hình sau:

Tăng tốc độ học

Chỉ sau 18 bước lặp thuật toán đã hội tụ so với 33 bước khi learning rate tăng từ 0.1 lên 0.2. Câu hỏi đặt ra, vậy có thể tăng tốc độ học lên thật cao không. Trong ví dụ tiếp theo chúng ta sẽ đẩy learning rate lên 0.5 xem thế nào.

Thuật toán không thể hội tụ

Thuật toán nhanh chóng kéo đến điểm cực tiểu nhưng không thể hội tụ, nó chạy qua chạy lại hai bên điểm cực tiểu nhưng không thể tiến đến điểm cực tiêu mặc dù chạy qua hơn 50 bước.

Như vậy có thể thấy việc chọn tốc độ học là rất quan trọng trong Gradient Descent, nếu learning rate bé thì tốc độ hội tụ lâu nhưng nếu chọn lớn quá thì thuật toán không thể hội tụ. Do vậy, trong thực tế để chọn được learning rate phù hợp chúng ta cần thực hiện các tốc độ khác nhau và sau vài lần thực hành, chúng ta sẽ có được con số phù hợp.

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

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

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

Viết blog sử dụng markdown, pelican, github pages

Viết blog sử dụng markdown, pelican, github pages

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

I. Markdown

Markdown được nói trong bài này là cú pháp để phục vụ việc chuyển text thành HTML. Tức là khi viết bằng cú pháp markdown, đưa qua 1 chương trình xử lý, nó sẽ cho ra kết quả là HTML.

  25 blogger IT nổi tiếng mà dân lập trình ai cũng phải biết
  Câu chuyện về cái comment tại một blog nọ

Một số cú pháp hay dùng:

Headers

# H1
## H2
### H3
#### H4
##### H5
###### H6

Kết quả: (lưu ý, xem source html của kết quả để biết chính xác, việc trình bày có thể bị ảnh hưởng bới template của blog)

H1

H2

H3

H4

H5

H6

Định dạng chữ:

Chữ nghiêng: *nghiêng* hoặc _nghiêng_. (*: asterik, _: underscore)

Chữ đậm: **đậm** hoặc __đậm__.

Nghiêng đậm: **_nghiêng đậm_** hoặc *__nghiêng đậm__*

Gạch ngang chữ: <s>gạch ngang</s>

Kết quả:

Chữ nghiêng: nghiêng hoặc nghiêng. (*: asterik, _: underscore)

Chữ đậm: đậm hoặc đậm.

Nghiêng đậm: nghiêng đậm hoặc nghiêng đậm

Gạch ngang chữ: gạch ngang

Link

[I'm an inline-style link](http://fml.vn)

[I'm an inline-style link with title](http://fml.vn "FML Academy")

[I'm a reference-style link][Arbitrary case-insensitive reference text]

[I'm a relative reference to a repository file](../blob/master/LICENSE)

[You can use numbers for reference-style link definitions][1]

Or leave it empty and use the [link text itself].

[arbitrary case-insensitive reference text]: http://fml.vn
[1]: http://fml.vn
[link text itself]:http://fml.vn

Kết quả:

I’m an inline-style link

I’m an inline-style link with title

I’m a reference-style link

I’m a relative reference to a repository file

You can use numbers for reference-style link definitions

Or leave it empty and use the link text itself.

Image

Here's our logo (hover to see the title text):

Inline-style: 
![alt text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 1")

Reference-style: 
![alt text][logo]

[logo]: https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 2"

Kết quả

Here’s our logo (hover to see the title text):

Inline-style: alt text

Reference-style: alt text

Code

`inline code` không xuống dòng

hoặc

“`python

print(‘This is python code’)

“`

Kết quả

inline code không xuống dòng

hoặc

print('This is python code')

Còn nhiều cú pháp nữa, xem chi tiết tại đây

II. Pelican

Pelican là một công cụ để tự động tạo file html, được viết bằng python. Hỗ trợ cú pháp reStructure (file đuôi .rst) và markdown (file đuôi .md)

1. Tạo virtualenv, kích hoạt và cài pelican, markdown vào virtualenv:

╭─htl@htl-homeserver  ~/pelican  
╰─$ virtualenv -p $(which python3) venv
Running virtualenv with interpreter /usr/local/bin/python3
Using base prefix '/usr/local'
New python executable in venv/bin/python3
Also creating executable in venv/bin/python
Installing setuptools, pip, wheel...done.
╭─htl@htl-homeserver  ~/pelican  
╰─$ source ./venv/bin/activate
(venv)╭─htl@htl-homeserver  ~/pelican  
╰─$ pip install pelican markdown
Collecting pelican
  Using cached pelican-3.6.3-py2.py3-none-any.whl
Collecting markdown
Collecting docutils (from pelican)
  Using cached docutils-0.12-py3-none-any.whl
Collecting six>=1.4 (from pelican)
  Using cached six-1.10.0-py2.py3-none-any.whl
Collecting unidecode (from pelican)
Collecting jinja2>=2.7 (from pelican)
  Using cached Jinja2-2.8-py2.py3-none-any.whl
Collecting feedgenerator>=1.6 (from pelican)
Collecting pytz>=0a (from pelican)
  Using cached pytz-2016.4-py2.py3-none-any.whl
Collecting pygments (from pelican)
  Using cached Pygments-2.1.3-py2.py3-none-any.whl
Collecting blinker (from pelican)
Collecting python-dateutil (from pelican)
  Using cached python_dateutil-2.5.3-py2.py3-none-any.whl
Collecting MarkupSafe (from jinja2>=2.7->pelican)
Installing collected packages: docutils, six, unidecode, MarkupSafe, jinja2, pytz, feedgenerator, pygments, blinker, python-dateutil, pelican, markdown
Successfully installed MarkupSafe-0.23 blinker-1.4 docutils-0.12 feedgenerator-1.8 jinja2-2.8 markdown-2.6.6 pelican-3.6.3 pygments-2.1.3 python-dateutil-2.5.3 pytz-2016.4 six-1.10.0 unidecode-0.4.19

2. Tạo thư mục chứa blog và chạy pelican-quickstart để thiết lập các thông số ban đầu:

(venv)╭─htl@htl-homeserver  ~/pelican  
╰─$ mkdir blog
mkdir: created directory 'blog'
(venv)╭─htl@htl-homeserver  ~/pelican  
╰─$ cd blog
(venv)╭─htl@htl-homeserver  ~/pelican/blog  
╰─$ pelican-quickstart
Welcome to pelican-quickstart v3.6.3.

This script will help you create a new Pelican-based website.

Please answer the following questions so this script can generate the files
needed by Pelican.


> Where do you want to create your new web site? [.] 
> What will be the title of this web site? Test blog
> Who will be the author of this web site? htl
> What will be the default language of this web site? [en] vn
> Do you want to specify a URL prefix? e.g., http://example.com   (Y/n) n
> Do you want to enable article pagination? (Y/n) y
> How many articles per page do you want? [10] 
> What is your time zone? [Europe/Paris] Asia/Ho_Chi_Minh
> Do you want to generate a Fabfile/Makefile to automate generation and publishing? (Y/n) y
> Do you want an auto-reload & simpleHTTP script to assist with theme and site development? (Y/n) y
> Do you want to upload your website using FTP? (y/N) n
> Do you want to upload your website using SSH? (y/N) n
> Do you want to upload your website using Dropbox? (y/N) n
> Do you want to upload your website using S3? (y/N) n
> Do you want to upload your website using Rackspace Cloud Files? (y/N) n
> Do you want to upload your website using GitHub Pages? (y/N) y
> Is this your personal page (username.github.io)? (y/N) n
Done. Your new project is available at /home/htl/pelican/blog

3. Viết blog trong thư mục content:

Đơn giản là chỉ cần tạo 1 file .md tại thư mục /blog/content, nội dung file được định dạng theo cú pháp markdown.

Các thông tin (metadata) cần thiết cho 1 bài viết được ghi ngay trên đầu file. Metadata tối thiểu bắt buộc phải có là Title, ngoài ra với cấu hình mặc định thì nên thêm Date:

Title: Tiêu đề bài viết
Date: 2016-06-28

Nội dung viết ở đây, định dạng **markdown**

Nếu metadata Date không được cung cấp trong nội dung bài viết thì pelican sẽ lấy thời gian tạo ra file, với điều kiện trong file pelicanconf.py phải có dòng (mà mặc định là chưa có):

DEFAULT_DATE = 'fs'

4. Tạo file html:

Điều kiện là khi khởi tạo bằng lệnh pelican-quickstart phải bật công cụ tự động tạo html ở câu hỏi này:

> Do you want to generate a Fabfile/Makefile to automate generation and publishing? (Y/n) y

Khi đó sẽ có file Makefile tại thư mục gốc của blog. Tạo blog bằng cách chạy lệnh make html:

(venv)╭─htl@htl-homeserver  ~/pelican/blog  
╰─$ make html                  
pelican /home/htl/pelican/blog/content -o /home/htl/pelican/blog/output -s /home/htl/pelican/blog/pelicanconf.py 
Done: Processed 1 article, 0 drafts, 0 pages and 0 hidden pages in 0.22 seconds.

Vậy là đã tạo được 1 file html trong thư mục output (ngang hàng với content).

Thử xem blog mình vừa viết trông như thế nào, dùng lệnh make serve:

(venv)╭─htl@htl-homeserver  ~/pelican/blog  
╰─$ make serve
cd /home/htl/pelican/blog/output && python -m pelican.server

Vào http://localhost:8000 để xem thử:

III. Upload lên github pages:

1. Tạo 1 github repo có tên là username.github.io với username là tên tài khoản github của bạn.

2. Clone repo về local:

(venv)╭─htl@htl-homeserver  ~/pelican  
╰─$ git clone git@github.com:fmltestblog/fmltestblog.github.io.git
Cloning into 'fmltestblog.github.io'...
warning: You appear to have cloned an empty repository.

3. Copy tất cả folder output vào thư mục của github repo:

(venv)╭─htl@htl-homeserver  ~/pelican  
╰─$ cd fmltestblog.github.io 
(venv)╭─htl@htl-homeserver  ~/pelican/fmltestblog.github.io  ‹master› 
╰─$ cp -R ../blog/output/* .

4. git add, commit và push:

(venv)╭─htl@htl-homeserver  ~/pelican/fmltestblog.github.io  ‹master*› 
╰─$ git add .
(venv)╭─htl@htl-homeserver  ~/pelican/fmltestblog.github.io  ‹master*› 
╰─$ git commit -m 'first blog commit'
[master (root-commit) 5d4216d] first blog commit
 33 files changed, 1250 insertions(+)
 create mode 100644 archives.html
 create mode 100644 author/htl.html
 create mode 100644 authors.html
 create mode 100644 categories.html
 create mode 100644 category/misc.html
 create mode 100644 index.html
 create mode 100644 tags.html
 create mode 100644 theme/css/main.css
 create mode 100644 theme/css/pygment.css
 create mode 100644 theme/css/reset.css
 create mode 100644 theme/css/typogrify.css
 create mode 100644 theme/css/wide.css
 create mode 100644 theme/images/icons/aboutme.png
 create mode 100644 theme/images/icons/bitbucket.png
 create mode 100644 theme/images/icons/delicious.png
 create mode 100644 theme/images/icons/facebook.png
 create mode 100644 theme/images/icons/github.png
 create mode 100644 theme/images/icons/gitorious.png
 create mode 100644 theme/images/icons/gittip.png
 create mode 100644 theme/images/icons/google-groups.png
 create mode 100644 theme/images/icons/google-plus.png
 create mode 100644 theme/images/icons/hackernews.png
 create mode 100644 theme/images/icons/lastfm.png
 create mode 100644 theme/images/icons/linkedin.png
 create mode 100644 theme/images/icons/reddit.png
 create mode 100644 theme/images/icons/rss.png
 create mode 100644 theme/images/icons/slideshare.png
 create mode 100644 theme/images/icons/speakerdeck.png
 create mode 100644 theme/images/icons/stackoverflow.png
 create mode 100644 theme/images/icons/twitter.png
 create mode 100644 theme/images/icons/vimeo.png
 create mode 100644 theme/images/icons/youtube.png
 create mode 100644 this-is-post-title.html
(venv)╭─htl@htl-homeserver  ~/pelican/fmltestblog.github.io  ‹master› 
╰─$ git push origin master 
Counting objects: 41, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (38/38), done.
Writing objects: 100% (41/41), 24.48 KiB, done.
Total 41 (delta 8), reused 0 (delta 0)
To git@github.com:fmltestblog/fmltestblog.github.io.git
 * [new branch]      master -> master

5. Mở trình duyệt, truy cập https://username.github.io

Blog của bạn đã online. Khi thêm 1 bài viết mới, hãy chạy lại từ bước II.4 và push lên github.

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

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

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

JavaScript là ngôn ngữ lập trình hướng đối tượng (OOP)

JavaScript là ngôn ngữ lập trình hướng đối tượng (OOP)

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

JavaScript là ngôn ngữ lập trình hướng đối tượng (OOP)

JavaScript là ngôn ngữ lập trình hướng đối tượng (OOP) vì nó đáp ứng các tính chất của lập trình hướng đối tượng như:

  • Tính đóng gói (Encapsulation)
  • Tính trừu tượng (Abstraction)
  • Tính kế thừa (Inheritance)
  • Tính đa hình (Polymorphism)

Tuyển lập trình JavaScript các công ty HOT

Có rất nhiều ý kiến cho rằng JavaScript không phải là ngôn ngữ lập trình hướng đối tượng vì nó không có từ khóa class để tạo bản thiết kế đối tượng như các ngôn ngữ lập trình OOP khác (Java, Python, C#…). Tuy nhiên, trong JavaScript ta có thể làm điều tương tự với function

JavaScript là ngôn ngữ lập trình hướng đối tượng (OOP)

Về thừa kế (inheritance) trong JavaScript, tất cả các đối tượng đều thừa kế từ prototype. (protype là thuộc tính đặc biệt mà tất cả các đối tượng đều có. Nó tương tương như trong Java, tất cả các class đều thừa kế class Object. Phần prototype này mình sẽ viết một bài riêng để mọi người hiểu rõ hơn)

  10 câu hỏi javascript để nâng cao trình độ
  10 trình quản lý file hàng đầu trong JavaScript

Tóm lại, JavaScript là một ngôn ngữ lập trình hàm nhưng đồng thời nó cũng là một ngôn ngữ lập trình hướng đối tượng vì nó có đầy đủ các tính chất của ngôn ngữ lập trình hướng đối tượng.

Một số ngôn ngữ wrapper lại JavaScript như TypeScript hay CoffeeScript cung cấp các từ khóa như class , extends sẽ giúp ta thấy rõ hơn tính chất hướng đối tượng của JavaScript. (Các ngôn ngữ này sau khi build chính là JavaScript).

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

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

Xem thêm các vị trí JavaScript hấp dẫn trên TopDev

Firefox profile preferences để download file với Selenium Webdriver

Firefox profile preferences để download file với Selenium Webdriver

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

Nhắc lại cái vấn đề ở bài ngoại truyện đã đề cập đến đó là khi bạn thực hiện download một file là các định dạng như MS Excel, MS Word, Zip File, PDF, CSV, Text file… với Selenium Webdriver từ một ứng dụng web nào đó. Sau khi nhấn nút Download để tải file xuống, thì một popup window sẽ hiển thị ra, nó sẽ hỏi bạn là bạn muốn Mở file này, hay là bạn muốn Lưu nó lại xuống máy. Cửa sổ này không phải là HTML popup thông thường để chúng ta có thể inspect và lấy locator như các popup khác đâu nha, vì nó là window popup mà.

TOP Web developer Jobs mới nhất 2022

Firefox profile preferences để download file với Selenium Webdriver

Như chúng ta đều biết, thì Selenium webdriver được sử dụng với các ứng dụng web mà thôi, tức là các ứng dụng chạy qua trình duyệt đó, và với kiểu popup trên ta sẽ không thể sử dụng trực tiếp Selenium webdriver rồi. 😀 Vậy thì bằng cách nào có thể xử lý được đây? Các bạn theo dõi tiếp bài viết này của mình nhé! 😀

Có một cái ý nho nhỏ mà mình sẽ nói qua ở đoạn này đó là với trình duyệt Firefox và trình duyệt IE, bình thường nếu làm việc với IE thì nó sẽ luôn luôn hỏi là bạn muốn Mở file, hoặc Lưu, hoặc là Lưu ở một nơi khác (click vào rồi chọn đến thư mục bạn muốn lưu file ở đó). Còn với Firefox và Chrome thì bạn có thể vào phần Settings, để tùy chọn mặc định lưu file ở một nơi nào đó mà không cần hỏi gì hết, hoặc là chọn lựa chọn là mỗi khi download sẽ phải hỏi bạn xem bạn muốn lưu ở đâu rồi mới thực hiện lưu – lựa chọn này chính là hiển thị popup mà mình đã nói phía trên đó.

Và ở bài này mình sẽ nói đến trường hợp download file với Firefox thôi nhé, Chrome chắc cũng tương tự thôi, vì mình cũng chưa thử, nên không khẳng định chỗ này đâu ha. :D. Và trước khi bắt đầu chúng ta sẽ nói về một khái niệm hơi lạ nhưng lại hơi liên quan đó là MIME một chút nhé! :v

MIME là gì?

MIME viết tắt của Multi-purpose Internet Mail Extensions, nó là một chuẩn Internet về định dạng cho thư điện tử, hầu như mọi thư điện tử Internet được truyền qua giao thức SMTP theo định dạng MIME. Ví dụ như Web server và các trình duyệt đều có một danh sách các loại MIME, vì thế mà các browser và server có thể trao đổi các loại file khác nhau theo cùng phương thức. Một loại MIME có hai phần là type và subtype, ngăn cách nhau bởi 1 dấu /, ví dụ cho dễ hình dung nhé:

  • TextFile (.txt): text/plain
  • PDFFile (.pdf): application/pdf
  • CSVFile (.csv): text/csv
  • MS Excel File(.xlsx): application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • MS word File(.docx): application/vnd.openxmlformats-officedocument.wordprocessingml.document

Và liên quan trực tiếp đến mục đích lớn nhất của chúng ta là download được file, thì trước tiên phải truyền các MIME type nào vào một cái gọi là Firefox profile.

Firefox Profile Preferences

Để thực hiện download một file với Selenium Webdriver thì chúng ta sẽ cần phải thực hiện một vài setting cho trình duyệt thông qua Firefox profile preferences, không phải đi cài đặt bằng tay đâu nhá, mà là đưa nó vào trong code ấy :v. Dưới đây là một vài preference cần lưu ý:

setPreference(“browser.download.folderList”, 2);

  • 0 – Default. Truyền vào là 0 nếu bạn muốn lưu file trên màn hình desktop.
  • 1 – Với giá trị 1 thì lưu file mặc định vào thư mục Downloads
  • 2 – Lựa chọn này khi bạn muốn lưu file vào một thư mục cụ thể nào đó trong máy tính của bạn.

setPreference(“browser.download.manager.showWhenStarting”, bool);

Mặc định của cái này là True, là cái nơi mà xác định việc có hiển thị hay không hiển thị cửa sổ khi tiến hành download file hay không.

setPreference(“browser.helperApps.alwaysAsk.force”, bool);

Mặc định của cái này cũng là True. Nó sẽ luôn hỏi bạn xem bạn muốn làm gì với những file tải xuống mà không biết loại MIME là gì.

setPreference(“browser.helperApps.neverAsk.saveToDisk”,value);

Mặc định thì là một chuỗi trống – không có nội dung đó. Đoạn này bạn có thể truyền vào danh sách các loại MIME được lưu luôn xuống máy mà không cần hỏi bạn có muốn lưu file này hay không.

setPreference(“browser.helperApps.neverAsk.openFile”,value);

Tương tự như trên, giá trị mặc định của cái này cũng là một chuỗi trống, ở đây bạn sẽ truyền vào danh sách các loại MIME được mở luôn mà cũng không cần hỏi bạn nữa.

setPreference(“browser.download.dir”,path);

Giá trị của thằng này cũng là chuỗi trống, ở đây bạn có thể truyền vào đường dẫn mà bạn muốn lưu file ở một thư mục cụ thể nào đó trên máy bạn.

Về cơ bản thì những cái trên kia đã đủ đáp ứng nhu cầu cho việc download file của chúng ra rồi, tuy nhiên mình sẽ đưa thêm một vài preferences khác nữa để các bạn tham khảo nhé, và có thể bổ sung vào trong những trường hợp cần thiết khác mà không phải là download nữa!

setPreference(“browser.download.manager.alertOnEXEOpen”,bool);

Giá trị mặc định là True. Với True thì nó sẽ cảnh báo khi người dùng muốn mở một tập tin có khả năng thực thi, như kiểu các file exe, html, js gì đó đó. Nếu để False thì nó sẽ không hiển thị cảnh báo nữa mà sẽ luôn cho phép run.

setPreference(“browser.download.manager.closeWhenDone”,bool);

Với cái preference này, giá trị mặc định của nó là False, với giá trị True thì nó sẽ đóng trình quản lý download sau khi tất cả các download đã xong.

setPreference(“browser.download.manager.focusWhenStarting”,bool);

Preference này có giá trị mặc định là False. Với giá trị True – Nó sẽ cho phép cửa sổ trình quản lý download được hiển thị khi quá trình download bắt đầu, ngược lại với False thì cửa sổ sẽ không được hiển thị, quá trình download diễn ra ngầm thôi.

Theo mình tìm hiểu thì có khá nhiều các preference khác nhau hỗ trợ các tác vụ khác nhau nữa, nhưng mà liên quan đến việc download file thì chủ yếu sẽ sử dụng những cái trên này, còn cả những cái khác nữa đấy :v nhưng nói đến đây đủ dùng rồi, nếu thiếu thì sau này bổ sung sau cũng được. hehe.

Bài viết mình có tham khảo từ nhiều nguồn thông qua tìm kiếm Google, trên stack overflow cũng nhiều người hỏi lắm, mình không tìm theo từ khóa tiếng việt, nên không rõ đã có ai nói chưa. Hehe. Hi vọng bài viết hữu ích cho tất cả các bạn, mình cũng rất mong nhận được các bình luận góp ý từ các bạn để hoàn thiện hơn mặt kiến thức cũng như trình bày.

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

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

Xem thêm it jobs for developer hấp dẫn trên TopDev

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

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

Máy tính ảo là một trong những công cụ rất quan trọng đối với nhiều nhóm đối tượng sử dụng khác nhau, đặc biệt là những bạn đang theo học và làm việc trong các ngành như: mạng máy tính, máy chủ, lập trình web, phát triển phần mềm..

Mà để học những ngành trên thì Ubuntu nói riêng hay các hệ điều hành Linux nói chung là một trong những lựa chọn rất tốt, nếu không muốn nói là rất tuyệt vời.

  Chạy file jar giống như một service trên Ubuntu (Linux)
  Hướng dẫn cách cài đặt VMware Workstation trên Ubuntu

Giống với hệ điều hành Windows 10, Linux cũng có một mớ các ứng dụng hỗ trợ cho việc tạo máy tính ảo, nhưng chỉ một vài trong số đó là miễn phí và đáng để sử dụng. Tiêu biểu là 2 cái tên VMWare Workstation - Player và Oracle VM VirtualBox.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

Về công dụng thì 2 phần mềm này là như nhau, tùy vào nhu cầu và đặc thù công việc của bạn mà lựa chọn thôi.

Trên blog đã có bài hướng dẫn chi tiết về cách cài đặt VMWare Workstation trên Ubuntu rồi, nay mình hướng dẫn nốt cách cài phần mềm VM VirtualBox trên Ubuntu để các bạn có thêm sự lựa chọn, ok – giờ thì tiến hành thôi 🙂

I. Hướng dẫn cài đặt VirtualBox trên Ubuntu

Cách #1: Cài VirtualBox trên Ubuntu bằng Software Installer

Tương tự như trên Windows 10, có vài phần mềm trên Linux cho phép bạn có thể cài đặt chỉ với vài cú click chuột mà không cần động đến dòng lệnh nào, và may mắn là VirtualBox của chúng ta nằm trong số đó.

+ Bước 1: Trước hết, bạn cần truy cập vào trang Wiki của VirtualBox để tải về bộ cài của phần mềm này, phiên bản mới nhất tính tới thời điểm mình viết bài này là 6.1.18.

+ Bước 2: Bạn sẽ thấy giao diện của trang Wiki tương tự như hình bên dưới, có thể thấy VirtualBox hỗ trợ hầu hết các hệ điều hành phổ biến của máy tính.

Vì chúng ta đang muốn cài trên Ubuntu => nên bạn hãy click vào dòng Linux distributions để tiếp tục.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

+ Bước 3: Sau đó bạn sẽ thấy danh sách các bản phân phối Linux có thể sử dụng được VirtualBox, phiên bản mới nhất của Ubuntu là Ubuntu 20.04 cũng đã được hỗ trợ luôn rồi.

Giờ hãy chọn hệ điều hành phù hợp với máy tính của bạn, ở bài viết này chúng ta sẽ chọn dòng Ubuntu 19.10 / 20.4 nhé.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

Ngay lập tức một file cài đặt có đuôi .deb với dung lượng tầm 90MB sẽ được tải xuống máy tính. Tải xong bạn hãy click vào file này để bắt đầu quá trình cài đặt VirtualBox sử dụng Software Installer của Ubuntu.

+ Bước 4: Một cửa sổ virtualbox-6.1 hiện lên cung cấp cho một vài thông tin về ứng dụng VirtualBox mà bạn sắp sửa cài đặt, tất nhiên là chúng ta chẳng đọc bao giờ.

Giờ hãy bấm vào nút Install màu xanh như trong hình để cài đặt VirtualBox vào Ubuntu. Cách này na ná giống việc bạn Search và cài đặt một ứng dụng từ cửa hàng ứng dụng của macOS và Linux, rất dễ và ai cũng có thể làm được.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

+ Bước 5: Tiếp theo, bạn cần nhập mật khẩu tài khoản Admin của mình để xác nhận việc cài đặt ứng dụng này, bao giờ cũng vậy.

Việc hỏi mật khẩu root nhằm giúp bảo vệ hệ điều hành khỏi những phần mềm độc hại, những phần mềm muốn có quyền can thiệp sâu vào hệ điều hành và nó gần giống với User Account Control của Windows, chỉ khác là không thể tắt được như UAC mà thôi.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

Quá trình cài đặt sẽ diễn ra trong khoảng 30S sau đó và nếu không có lỗi gì xảy ra thì bạn đã cài thành công ứng dụng VirtualBox trên Ubuntu và nút Install lúc đầu sẽ chuyển thành nút Remove màu đỏ.

Giờ hãy bấm phím Windows trên bàn phím => gõ từ khóa Virtualbox vào ô tìm kiếm và bạn sẽ thấy duy nhất một kết quả là Oracle VM VirtualBox như hình bên dưới => Click vào đó để chạy ứng dụng VirtualBox.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

+ Bước 6: Giao diện của VirtualBox trên Ubuntu và macOS sẽ hơi khác với giao diện của VirtualBox trên Windows 10 một chút, nhưng về cơ bản thì cách sử dụng thì không có gì khác biệt, nhưng mình vẫn sẽ có bài hướng dẫn chi tiết cách sử dụng sau.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

Okay, vậy là việc cài đặt VirtualBox trên Ubuntu đã xong !

Cách #2: Cài đặt VirtualBox trên Ubuntu bằng Terminal

Terminal là một trong những công cụ cực kỳ mạnh mẽ trên các hệ điều hành nhân Linux và tạo sự khác biệt giữa Windows và macOS.

Bạn hoàn toàn có thể cài đặt bất cứ phần mềm nào chỉ với một vài dòng lệnh trong Terminal, mình sẽ lấy luôn ví dụ là ứng dụng Oracle VM VirtualBox này nhé !

Khi muốn cài bất cứ phần mềm nào trên Ubuntu nói riêng và Linux nói chung, việc cần làm đầu tiên phải là cập nhật hệ thống.

+ Bước 1: Bạn hãy bấm tổ hợp phím Ctrl + Alt + T trên bàn phím để mở cửa sổ Terminal lên => rồi cập nhật hệ thống Ubuntu bằng dòng lệnh sau:

sudo apt-get update && sudo apt-get dist-upgrade && sudo apt-get autoremove

Ngoài ra, lệnh này còn tự động loại bỏ những gói phần mềm bổ sung của các ứng dụng đã bị gỡ ra trước đó, giúp tối ưu và tăng tốc hệ thống.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

Sau khi hệ thống đã được cập nhật xong, chúng ta cần phải cài đặt gói Linux Ubuntu Headers, nó chứa các tập tin Header và các tập lệnh để xây dựng module cho nhân Linux, và đây cũng cũng là một thành phần cần thiết để có thể sử dụng được Virtual Box trên Ubuntu.

+ Bước 2: Nhập vào cửa sổ Terminal dòng lệnh dưới đây => rồi bấm Enter để cài gói Linux Ubuntu Headers, thời gian cài đặt cũng khá lâu nên bạn cần kiên nhẫn chờ đợi nha:

sudo apt-get -y install gcc make linux-headers-$(uname -r) dkms

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

+ Bước 3: Các ứng dụng muốn cài được bằng dòng lệnh thì phải có kho lưu trữ gọi là các Repository trên Internet, đa số các ứng dụng phổ biến đều đã nằm trong kho lưu trữ mặc định của Linux hoặc kho lưu trữ của chúng đã được thêm vào Linux rồi, chỉ cần gõ lệnh nữa là xong.

Danh sách các kho lưu trữ của ứng dụng được lưu vào một tập tin có tên sources.list nằm trong thư mục etc/apt/ trên ổ đĩa hệ thống.

Đối với những ứng dụng còn lại, muốn cài được bằng dòng lệnh thì bạn phải thêm kho lưu trữ theo cách thủ công giống như cách mình làm với ứng dụng Virtual Box dưới đây.

Trước hết hãy tải về các khóa của Virtual Box về máy để có được quyền truy cập vào kho lưu trữ của ứng dụng này.

wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add –

wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add –

+ Bước 4: Sau đó, bạn sử dụng lệnh bên dưới để để thêm kho lưu trữ của Virtual Box trên Internet vào file sources.list nữa là xong:

sudo sh -c ‘echo “deb http://download.virtualbox.org/virtualbox/debian $(lsb_release -sc) contrib” >> /etc/apt/sources.list’

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

+ Bước 5: Giờ hãy cập nhật lại hệ thống một lần nữa để Ubuntu lấy dữ liệu các gói cài đặt từ kho lưu trữ của Virtual Box mà bạn vừa đã thêm vào ở trên, lệnh sau:

sudo apt-get update

Cuối cùng nhập vào Terminal lệnh bên dưới => rồi bấm phím Enter và chờ cho Virtual Box được cài đặt vào Ubuntu.

sudo apt-get install virtualbox-6.1 -y

Lưu ý về phiên bản của VirtualBox khi cài đặt, ở đây phiên bản mới nhất của VirtualBox đang là 6.1.18 nên mình nhập virtualbox-6.1, bạn cần lưu ý để chọn đúng phiên bản muốn cài đặt.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

Và đây là thành quả, nói chung là 2 cách cài này đều cài như nhau, bạn thích dùng cách nào thì tùy 😀

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

II. Làm thế nào để gỡ cài đặt VirtualBox trên Ubuntu?

Khi Virtual Box không đáp ứng được yêu cầu công việc của bạn, hoặc đơn giản là bạn thích dùng VMWare Workstation hơn thì việc gỡ cài đặt ứng dụng này cũng không có gì phức tạp.

+ Đối với những người cài bằng cách dùng Software Installer, bạn hãy chạy lại file .deb đã dùng lúc cài đặt lên, nếu lỡ xóa rồi thì vào trang download của VirtualBox để tải lại.

Cửa sổ Software Installer quen thuộc lại hiện lên nhưng thay vì nút Install như lúc đầu, bạn sẽ thấy một nút Remove màu đỏ => Bấm vào đó rồi nhập mật khẩu root để gỡ VirtualBox.

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

+ Còn với những người cài bằng Terminal, việc gỡ cài đặt thậm chí còn đơn giản hơn nữa. Chỉ việc mở Terminal lên => rồi gõ dòng lệnh sudo apt-get remove virtualbox* --purge -y và bấm phím Enter là xong rồi.

Khác với Windows, bạn có thể cài nhiều phiên bản của cùng một ứng dụng mà không gặp bất cứ lỗi gì.

Vậy nên nếu có lỡ cài nhầm và nhiều phiên bản khác của Virtual Box, hãy sử dụng lệnh tương tự dưới đây để gỡ từng phiên bản còn lệnh bên trên sẽ gỡ toàn bộ phiên bản đã cài :

sudo apt-get remove virtualbox virtualbox-5.0

sudo apt-get remove virtualbox virtualbox-5.2

sudo apt-get remove virtualbox virtualbox-6.1

………….

Hướng dẫn cài đặt VirtualBox trên Ubuntu chi tiết nhất

III. Lời kết

Vâng, như vậy là mình đã hướng dẫn xong cho các bạn 2 cách cài đặt ứng dụng VirtualBox trên Ubuntu rồi nhé. Hi vọng là qua bài viết này bạn sẽ có thêm những lựa chọn để tạo và sử dụng máy tính ảo trên Ubuntu, phục vụ cho công việc của bạn được tốt hơn.

Ở trong bài tiếp theo thì mình sẽ nói về cách tạo máy ảo bằng VirtualBox trên Ubuntu vì nó sẽ hơi khác Windows một tí, mời bạn cùng theo dõi nha. Nếu thấy thủ thuật này hay và có ích đừng quên chia sẻ để ủng hộ Blog. Chúc các bạn thành công !

CTV: Nguyễn Thanh Tùng – Bài viết gốc tại blogchiasekienthuc.com

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

Xem thêm tuyển dụng ngành cntt hấp dẫn trên TopDev

Định dạng dữ liệu trong kiểm thử API

Định dạng dữ liệu trong kiểm thử API

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

Như bài 1 đã có giới thiệu, định dạng data trong API thường dùng 2 loại chính là JSON  (JavaScript Object Notation) và XML (Extensible Markup Language). Hôm nay, mình sẽ nói kỹ hơn về từng loại định dạng.

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

JSON

Ngày nay, JSON được sử dụng nhiều trong Restful API. Nó được xây dựng từ Javascript, ngôn ngữ mà được dùng nhiều, tương thích với cả front-end và back-end của cả web app và web service. JSON là 1 định dạng đơn giản với 2 thành phần: keys và values.
– Key thể hiện thuộc tính của Object
– Value thể hiện giá trị của từng Key

Ví dụ:

Định dạng dữ liệu trong kiểm thử API

Trong ví dụ trên, keys nằm bên trái, values nằm bên phải.

Định dạng dữ liệu trong kiểm thử API

Có nhiều trường hợp, 1 Key sẽ có Value là 1 dãy key + value. Ví dụ như hình:

Định dạng dữ liệu trong kiểm thử API

Trong hình trên Key có tên là Data có Value là 2 cặp Key + value.

XML

Trong JSON dùng { } và [ ] để dánh dấu dữ liệu. XML thì tương tự như HMTL, dùng thẻ để đánh dấu và được gọi là nodes.

Lấy luôn ví dụ ở trên nhưng viết bằng xml, nó sẽ như thế này:

Định dạng dữ liệu trong kiểm thử API

Định dạng dữ liệu trong kiểm thử API

  10+ tools và extensions tuyệt vời cho GraphQL APIs
  3 bước tối ưu hiệu năng React App bằng các API mới của React

Định dạng dữ liệu được sử dụng như thế nào trong HTTP.

Quay lại bài 2, phần header có chức năng lưu những thông tin mà người dùng không biết, trong đó có 1 thành phần xác định format của data: Content-Type

Khi client gửi Content-Type trong header của request, nó đang nói với server rằng dữ liệu trong phần body của request là được định dạng theo kiểu đó. Khi client muốn gửi JSON nó sẽ đặt Content-Type là “application/json”. Khi bắt đầu nhận request, server sẽ check cái Content-Type đầu tiên và như thế nó biết cách đọc dữ liệu trong body. Ngược lại, khi server gửi lại client 1 response, nó cũng gửi lại Content-Type để cho client biết cách đọc body của response.

Đôi khi client chỉ đọc được 1 loại định dạng, ví dụ là JSON mà server lại trả về XML thì client sẽ bị lỗi. Do đó, 1 thành phần khác ở trong header là Accept sẽ giúp client xử lý vấn đề trên bằng cách nói luôn với server loại nó có thể đọc được. Ví dụ : Accept : “application/json” . Chốt lại: dựa vào 2 thành phần Content-Type và Accept, client và server có thể hiểu và làm việc một cách chính xác. Ở những bài sử dụng công cụ, mình sẽ chụp ảnh và minh họa rõ ràng Content-Type và Accept trong Header.
Chọn ảnh tiêu biểu

Định dạng dữ liệu trong kiểm thử API

Nguồn: chương 3 của cuốn sách: “An Introduction to APIs” by  Brian Cooksey

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 tester đà nẵng, hcm, hà nội hấp dẫn trên TopDev

Database Seeding là gì?

Database Seeding là gì?

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

Database Seeding là gì?

Trong môi trường Developement mà thao tác với dữ liệu thực là chết người. Nên khi có 1 ứng dụng cần sử dụng API để xử lý hàng nghìn dữ liệu thì việc thực hiện test rất cần thiết và nếu tạo bằng tay data để test thì không ai rãnh vì thế tạo dữ liệu ảo là rất cần thiết.

Vậy việc đầu tiên sau khi có Database test thì chúng ta sẽ “Dummy Data” hay tạo dữ liệu ảo và tên gọi của việc này là Database seeding.

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

Đối tượng dữ liệu nào nên sử dụng dữ liệu ảo?

Thường là mọi dữ liệu cần đúng kiểu và cấu trúc dữ liệu mà dữ liệu đó cần sự bảo mật thông tin.

Ví dụ:

  • Người dùng
  • Địa điểm
  • Số điện thoại
  • Email
  • Credit Card,…

Làm thế nào để tạo Seeder?

Công cụ Faker

Source code: Link Github

composer require fzaninotto/faker

Cách sử dụng

name;
 // Tạo dữ liệu ảo Địa chỉ
echo $faker->address;
  // Tạo dữ liệu ảo Đoạn văn
echo $faker->text;
// Nếu muốn tạo nhiều dữ liệu mẫu cùng lúc thì để trong vòng For nhé
for ($i=0; $i < 10; $i++) {
  echo $faker->name, "\n";
}

Sample code với Laravel Framework

insert([
                'name' => $faker->name,
                'email' => $faker->email,
                'password' => bcrypt('secret'),
            ]);
        }
    }
}

Kết quả:

Database Seeding là gì?

Faker gen?

Faker gen sẽ tạo sẵng những mẫu dữ liệu đã có format hoặc do chính bạn define cho nó. Xem thêm

randomDigit;
$faker->numberBetween(1,100);
$faker->word;
$faker->paragraph;
$faker->lastName;
$faker->city;
$faker->year;
$faker->domainName;
$faker->creditCardNumber;

Nếu bạn cần Faker cho các ngôn ngữ khác thì có thể tham khảo bên dưới!

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

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

Phát triển và tận dụng Google Assistant theo nhiều cách khác nhau

Google Assistant

Giới thiệu về Google Assistant

Trợ lý giọng nói (voice assistant) và tìm kiếm bằng giọng nói (voice search) đang dần trở thành một xu hướng mới. Trong số những trợ lý ảo phổ biến nhất hiện nay thì Google Assistant là cái tên bạn không nên bỏ qua. Hiện tại, Google Assistant đang hỗ trợ hơn 19 ngôn ngữ, trên hơn 80 quốc gia và có mặt trên nhiều loại thiết bị khác nhau như các thiết bị Smart Display, các dòng điện thoại Android, Iphone, Google Home, loa thông minh,… 

Bạn có thể tận dụng Google Assistant để tiếp cận lượng người dùng lớn của trợ lý ảo này bằng cách tạo ra các action thông qua nền tảng Actions on Google. Bài viết sẽ hướng dẫn chi tiết về nền tảng này thông qua topic “Multiple ways to build for Google Assistant” của Ms. Jessica Dene Earley-Cha – Developer Advocate @Google  tại sự kiện Vietnam Web Summit 2020 LIVE – biên tập bởi TopDev.

Bài viết sẽ phù hợp nếu bạn:

  • Là một Web Content Owner, hãy tìm hiểu về Content Actions: các loại công thức, những nội dung hướng dẫn, podcast, tin tức,…
  • Là một Android App Developer, hãy tìm hiểu về App Actions.
  • Là một người thích tìm hiểu về công nghệ giao tiếp bằng giọng nói, hãy tìm hiểu về Conversational Actions với Interactive Canvas.
  • Là một Hardware Developer, hãy tìm hiểu về Smart Home SDK.
google assistant
Google Assistant hỗ trợ người dùng, khiến đời sống và công việc trở nên hiệu quả hơn

Content Action – Khiến nội dung của bạn xuất hiện trên Google Assistant

Nếu bạn đã có một website, một podcast hay một danh sách công thức thì bạn có thể đưa những nội dung trên của bạn vào trong Google Assistant.

Tương tự như việc tối ưu website cho Google Search, bạn cần cấu trúc website nhằm giúp Google Search có thể hiểu được dữ liệu đó và có thể mang chúng đến và phục vụ cho user thì với Google Assistant điều này cũng diễn ra tương tự.

Tất cả những việc bạn cần làm là thêm vào scheme.org và cấu trúc các trang làm sao để Google Assistant có thể nhận biết, hiểu và mang những nội dung của bạn đến người dùng.

Các loại nội dung trên Google Assistant

Thường những nội dung trong Google Assistant được phân loại thành: news; podcast; recipes; FAQs; how-to.

Việc bạn cần làm là hãy thêm vào Structured Data Markup (Đánh dấu dữ liệu có cấu trúc) để content của bạn có thể được tìm thấy bởi nhiều công cụ tìm kiếm hơn, trong đó có cả Google Assistant.

code podcast google assistant

Đây là một ví dụ về một quyển sách nói. Họ chỉ sử dụng RSS, đồng thời có thể thêm vào cấu trúc dữ liệu ấy, từ đó mà có thể được tối ưu hoạt động trên cả Search và Assistant.

App Action – Kích hoạt chức năng giọng nói cho các ứng dụng Android

App Action là một hành động giúp bạn gửi một ứng dụng Android đến người dùng thông qua câu thoại lệnh “Hey Google, open *your app*”.

Thách thức “Tái tương tác ứng dụng”

Google Assistant giai quyet cac icon

Thông thường doanh nghiệp sẽ phải tốn rất nhiều chi phí để có thể khiến người dùng cài đặt app cũng như khiến họ tương tác, sử dụng ứng dụng một cách thường xuyên. Một trong số những lý do tại sao khiến chi phí này lại trở nên đáng kể là bởi trên thiết bị người dùng thường có hàng tá icon khiến ứng dụng của bạn bị lu mờ (mình biết điều này vì trên điện thoại mình cũng thế :P)

Bởi thế, việc mà chúng ta cần làm chính là tìm cách xem rằng làm thế nào để vượt qua những rào cản trên, giúp người dùng không cần phải nhớ xem app của bạn trông như thế nào và họ có thể dễ dàng tìm thấy nó.

Với App Action, công nghệ này cho phép Android Developer sử dụng Google Assistant như một công cụ để mang ứng dụng của bạn nhanh chóng đến người dùng thông qua giọng nói.

Để hiểu rõ hơn, chúng ta cùng xem một ví dụ được gọi là SmoresSmores.

Hoàn tất ‘chiếc bánh’ S’more theo cách cũ

  • Bước 1: Tìm ứng dụng SmoreSmores bên trong mớ icon hỗn độn trên thiết bị.
  • Bước 2: Chọn loại bánh quy.
  • Bước 3: Chọn loại marshmallow.
  • Bước 4: Chọn loại chocolate.
  • Bước 5: Xác định độ nóng giòn.
  • Bước 6: Xác định số lượng.
  • Bước 7: Xem lại order.DIY Smores Google Assistant
  • Bước 8: Hoàn tất order.

Bạn có thể hình dung một số bước có thể diễn ra để hoàn tất một chiếc bánh S’more trên ứng dụng theo cách thông thường:

Đầu tiên, người dùng sẽ phải tìm kiếm icon của ứng dụng trong số mớ icon hỗn độn trong thiết bị của họ. Sau đó, họ sẽ phải lựa chọn từng option cho mình như: loại bánh quy nào , loại marshmallow nào, có thêm chocolate hay không, độ chính và số lượng bánh,…

Người dùng sẽ phải trải qua nhiều bước mới có thể hoàn tất order của mình. Điều này sẽ mất khá nhiều thời gian. Tuy nhiên, có một phương pháp khác để hoàn tất order và tiết kiệm công sức hơn cho người dùng, đó là triển khai thực hiện App Action. Người dùng sẽ có thể nói chuyện và thực hiện order một cách tự nhiên nhất thông qua chính cách nói chuyện của họ.

Hoàn tất S’more bằng giọng nói với App Actions

Với giải pháp này, người dùng chỉ cần thực hiện 2 bước đơn giản.

  • Bước 1: Thao tác bằng giọng
  • Bước 2: Xác nhận order

Theo cách này, tất cả thông tin sẽ được đưa vào ứng dụng và ứng dụng mở lên trang xác nhận thông tin mà người dùng đã cung cấp. Điều này sẽ khiến cho người dùng dễ dàng thao tác hơn.

Với App Actions, tất cả thông tin sẽ được đưa vào ứng dụng và ứng dụng sẽ mở lên đến ngay trang xác nhận thông tin mà người dùng đã cung cấp bằng chính giọng nói của họ (loại bánh, marshmallow, chocolate, độ nóng và số lượng,…)

Một ví dụ khác, hãy tham khảo trường hợp của Nike

Bạn có thể nói chuyện với ứng dụng của Nike, yêu cầu mở ứng dụng Nike Run Club.

Ngoài ra bạn còn có thể thực hiện những thao tác khác như chuyển tiền hay đặt hàng thông qua ứng dụng.

Tất cả những tác vụ như trên có thể được thực hiện là bởi Google Assistant sử dụng một thứ được gọi là built-in intents. 

Built-in intents

Hãy để Google biết rằng bạn có những tính năng nào, chẳng hạn như tính năng đặt đồ ăn hay bắt đầu một buổi tập luyện, từ đó giúp Google có thể biết được đâu là nơi mà nó cần kết nối đến.

Hãy cho Google biết đâu là những tính năng mà người dùng có thể sử dụng; các loại parameter mà bạn cung cấp, đâu là các fulfillment URL, đâu là trang đích khi tôi tổng hợp tất cả các parameter đó lại.

Bạn có thể sử dụng bao nhiêu built-in intent và thêm vào bao nhiêu mà bạn muốn.

Các intent google assistant đang hỗ trợ
Các intent google assistant đang hỗ trợ

Và đây là một file XML để ví dụ cho việc sử dụng built-in intent cho hành động gọi món.

vi du app action tren google assistant
Một file XML để ví dụ cho việc sử dụng built-in intent cho hành động gọi món

Bạn có thể thấy trên ví dụ sử dụng:

 intentName=“actions.intent.ORDER_MENU_ITEM”

Đây là một built-in intent mà Google đã cung cấp và bạn có thể sử dụng nó và người dùng sẽ có thể gọi món từ menu.

Android Slices

Slices là các UI template có thể hiển thị các nội dung tương tác động từ ứng dụng của bạn bên trong Google Assistant.

Android slice

Hẳn rằng nhiều lần bạn muốn cung cấp cho người dùng một thông báo nhanh hay một xác nhận đơn hàng nào đó. Bạn có thể sử dụng Android Slice để cung cấp những thông tin ấy một cách đơn giản và thân thiện đến người dùng và giúp họ cập nhật thông tin một cách nhanh chóng.

Một lưu ý nhỏ: khi bắt đầu với các built-in intent và item này, Google Assistant đã kiểm soát và quản lý tất cả NLU (Natural Language Understanding) nên bạn không cần phải lo về cách mà người dùng nói chuyện khi bạn sử dụng built-in intent trong Android Slices.

Smart home – Control hardware with just your voice

google smart home integrationSmart Home Device Integration

Khi nhắc về Smart Home, tất cả những gì chúng ta cần nói đến đều chỉ là về tích hợp với phần cứng (integrating with hardware).

Nếu bạn quan tâm đến việc tự động hóa ngôi nhà của mình, bạn có thể hiện thực hóa điều ấy thông qua giải pháp Smart Home Integration của Google.

Smart home integration google assistant

Giải pháp này sẽ cung cấp cho bạn một Home Graph, giúp ngôi nhà nắm được trạng thái và khả năng thực hiện của tất cả các thiết bị kết nối bên trong ngôi nhà. Người dùng có thể đưa ra yêu cầu như “làm mờ đèn một chút” và ngôi nhà sẽ biết rằng chúng cần làm gì.

NLU

Phần hay nhất nội dung này chính là Natural Language Understanding. Giống với Android và built-in intents, Google Assistant sẽ kiểm soát tất cả vấn đề này cho bạn. Nếu ai đó nói “làm ấm phòng” hay “bật/tắt đèn” hay nói về một nhiệt độ cụ thể như “tôi muốn 24 độ”, nó sẽ chuyển dữ liệu đó như một parameter và thực hiện yêu cầu đó.

Types & traits

Type thực chất là những thiết bị, phần cứng (hardware). Bạn có thể nghĩ đến những thứ như cửa sổ, đèn, lò sưởi, rèm che,…

Trait là thuộc tính hay đặc điểm, chức năng của type. Bạn có thể hình dung về những yêu cầu đơn giản như bật/tắt đèn, nhưng cũng có một số loại đèn có thể điều chỉnh độ sáng.

Google có đề cập rất nhiều về nội dung này trong tài liệu, bạn có thể kiểm tra chúng tại đây.

Smart Home Integration

Để có thể tích hợp thiết bị của bạn với Google Assistant, nhà phát triển cần cung cấp cloud service của chính họ cho người dùng để đăng ký và quản lý thiết bị, điện thoại thông minh và Action Platform. Sau đó, hãy tích hợp với cloud service thông qua một chuỗi các webhook để truy cập và kiểm soát các thiết bị đó.

Local home SDK

Một thứ mà chúng tôi tự hào khi bắt đầu nó từ năm ngoái chính là local SDK. Local home SDK của Google được thực hiện thông qua wifi. Các thiết bị trên local network có thể được phát hiện và kiểm soát với local protocols, giúp giảm chi phí giao dịch đám mây.

Conversation

Cuối cùng, nếu bạn muốn xây dựng một trải nghiệm phong phú cho người dùng, bạn nên xây dựng các conversation action.

Tương tự như cách smart home được cấu trúc và những thứ tương tự, người dùng sẽ gửi một request và Google Assistant tiến hành xử lý.

cấu trúc Google Assistatn xử lý request

Tuy nhiên, không giống như với Android hay với Smart Home – chúng đã có các built-in intents hay types of traits, nơi mọi thứ đã được định nghĩa và Google đã xử lý phần natural language processing, tại đây, Google Assistant sẽ xử lý phần text-to-speech và cho bạn text của người dùng. Sau đó, tùy vào action mà bạn muốn thực hiện mà hệ thống sẽ xác định đâu là thứ cần gửi lại, nhưng việc xác định đâu là thứ mà cần hệ thống gửi lại bạn vẫn là người quyết định. Hãy gửi một response tới Google Assistant và Google Assistant sẽ chuyển nó đến cho người dùng.

Natural Language Understanding (NLU)

Giả sử, nếu người dùng chỉ nói “yes” thì việc phân tích cú pháp sẽ tiến hành khá nhanh phải không?

Tuy nhiên, nếu người dùng nói “yes” theo nhiều cách (biến/variation) khác nhau như: “Perfect”, “Let’s do it”, “Go ahead”, “Sure”, “Yep”, “oke”,… thì bây giờ phải làm sao?

Lúc này, bạn sẽ cần một công cụ để quản lý tất cả các biến và đó chính là NLU.

Để giúp xử lý thông tin của người dùng, bạn hãy xác định các intent khác nhau mà người dùng có thể sẽ thể hiện một “yes” intent hay “no” intent, hay khi người dùng muốn chơi một trò chơi nào đó.

Khi bạn đã xác định những thứ trên thì hãy đưa ra những hướng dẫn (training phrases) cho các intent ấy, từ đó Google Assistant có thể hiểu được và biết được rằng khi người dùng nói về các intent đó, như “yes” chẳng hạn, Google sẽ đóng gói tất các các biến của “yes” và tiếp tục xây dựng thêm dựa trên đó.

Nhưng ai sẽ làm việc đó?

Cuộc đối thoại hai chiều với action của bạn được thực hiện theo cách sau.

luong tro chuyen giua nguoi dung voi google assistant

Input của người dùng sẽ được gửi đến, và sau đó, Google Assistant sẽ tiến hành xử lý nó bằng NLU và gửi thông tin đó đến Action.

Tiếp đến, action sử dụng chúng để tạo ra một prompt và gửi prompt ấy đến Google Assistant. Cuối cùng, Google Assistant sẽ chuyển nó đến người dùng.

Nhưng làm sao để bạn biết được khi nào người dùng nói “yes”? Họ sẽ nói “yes” ở vị trí nào trong câu thoại? Có phải họ đang nói “yes, I want to play the game” hay “yes, I want to drink the magic potion in the game”. Bạn không thể xây dựng các intent kiểu như “fly around”. Bạn cần phải tổ chức nó theo một cách nào đó.

Quản lý mô hình hội thoại (conversational model) cho action chính là chìa khóa để tạo ra các prompt phù hợp ấy và bạn có thể sử dụng Actions Builder để thực hiện điều này.

Actions Builder

Actions Builder là một web-based IDE được tích hợp hoàn toàn vào Action Console.

Hiện tại bạn chỉ có duy nhất một window để xây dựng các action. Bạn có thể thiết kế các luồng hội thoại một cách trực quan và đồng thời hỗ trợ và cải tiến NLU khi nó tiến hành xử lý các input của người dùng. Đồng thời, nó cũng bao gồm một inline editor vì thế bạn cũng có thể xây dựng các phản hồi động bằng cách sử dụng webhook.

actions builder

Với Actions Builder, nó sẽ xử lý input của người dùng và cũng làm như thế với intent matching hoặc slot filling khi nó đến các types. Bạn cũng có thể lấy các phần dữ liệu ra khi nó đến users responses.

Tương tự, chúng ta có khái niệm scenes để quản lý logic. Nếu nó thực sự bắt đầu và người dùng nói “yes”, intent sẽ khớp với “Yes” intent, nhưng bởi vì nó đang ở start scene, hệ thống biết “oh, họ đang nói yes để bắt đầu trò chơi chứ không phải nói yes để sử dụng item hồi máu”. Từ đấy, nó có thể chuyển tiếp bạn tới scene kế tiếp để bắt đầu trò chơi, và bạn cũng có thể xây dựng các prompt động hoặc tĩnh bằng cách sử dụng công cụ này. 

Scenes

Scene là một khái niệm mới khi “Action Developer” sử dụng công cụ cũ của Google.

Scenes là những khối logic (logical chunks) của Mô hình thoại hội của bạn và chúng cũng là thứ sẽ thực thi các action của bạn. Chúng sẽ xử lý những phần nặng nhọc, xử lý các logic cần thiết để định hướng cuộc trò chuyện. Đây là một cách thức để modularize action của bạn.

Bạn có thể nhận được một welcome scene, và ở scene này, bạn sẽ được hỏi rằng liệu bạn có muốn làm cái này, làm cái kia hay không. Chúng có mối liên hệ chặt chẽ với nhau.

Nếu một người dùng nói gì đó, hệ thống có thể sẽ chuyển tiếp họ đến scene tiếp theo. Điều thú vị là scene của bạn có thể hỏi và thu thập dữ liệu thông qua các slot. Nếu socket của bạn được fill, một scene có thể chuyển tiếp đến scene tiếp theo. Tương tự, bạn có thể liên tưởng đến việc order, bạn có thể lấp đầy hoặc chúng ta có thể có tất cả thông tin như mua một chiếc đầm dạ hội, chúng ta sẽ biết được họ muốn mua size nào, sau đó chuyển tiếp bạn đến nơi có thể mua hàng hoặc nơi cung cấp thêm thông tin.

Vòng đời thực thi của scene

Các scene rất linh hoạt, chúng cho phép bạn thực hiện những thứ rất tuyệt và tất cả các scene chạy bên trong vòng lặp, mọi thứ điều tuyệt vời, thế nên, vòng đời thực thi (executor lifecycle) là một thứ gì đó mà chúng ta nên thử phân tích cú pháp và đào sâu thêm vào nội dung này. Hãy xem video ngắn bên dưới.

Action SDK

Bổ sung thêm cho Actions Builder là Actions SDK. Action SDK sẽ cho bạn một file-based representation của action và khả năng sử dụng các local IDE của chính bạn. Phần hay nhất là nó hoạt động song song với Actions Builder. Nó bao gồm tất cả các tài nguyên cấu hình của action của bạn, gồm có khả năng hỗ trợ và quốc tế hóa.

Bạn có thể build bằng cách sử dụng Actions Builder, sau đó kéo dự án xuống local, thay đổi và đẩy những thay đổi mới ấy lên Action Builder và cuối cùng là cho phép team làm việc với công cụ yêu thích của họ.


google assistant simulator

  • Google cũng đã cải thiện phần giả lập – thứ cung cấp cho bạn các execution log cùng với các dữ liệu về request và response để giúp bạn dễ dàng debug các action của mình. Chúng được tổ chức theo scene, theo sự tương tác giữa người dùng và Google Assistant.
  • Sau đó, bạn có thể click lên nó và bạn có thể nhìn thấy dữ liệu của scene.
  • Bạn có thể thấy những parameter nào đang được chuyển qua khi các webhook đang bị gọi.
  • Google cũng đã thêm state editor để khiến nó dễ dàng để update và debug content của bạn.
  • Thông qua việc tạo ra các thay đổi trong scene, trong phần scene editor, bạn không nhất thiết phải trải qua tất cả flow, bạn có thể kết nối tới các thứ dễ dàng hơn hoặc khiến nó như kiểu người dùng đã hoàn thành việc xyz và theo cách đó, bạn có thể đi trực tiếp đến nơi mà bạn muốn test bên trong luồng hội thoại.

Gia tăng trải nghiệm cho người dùng

Action Builder và Action SDK cung cấp các thành phần hội thoại (conversational components) của action nhưng bạn cũng có thể thêm vào những thành tố (element) khác để gia tăng trải nghiệm cho người dùng.

Bạn có thể sử dụng Interactive Canvas để build những trải nghiệm game thú vị, cung cấp những hình ảnh trực quan sinh động cho cuộc trò chuyện của bạn.

Một điều rất tuyệt chính là Interactive Canvas chỉ sử dụng như web app, vì thế HTML, CSS và JavaScript là tất cả những gì bạn cần để có thể tạo ra một web app ấy. Interactive Canvas sẽ kết nối trang web với cuộc hội thoại của người dùng và sẵn sàng để thực hiện trải nghiệm giọng nói khi bắt đầu action này.

Bạn có thể tìm hiểu chi tiết về công nghệ Interactive Canvas tại bài viết này.

Continuous Match Mode

Một điều khác là bạn có thể gia tăng thêm trải nghiệm người dùng với chế độ khớp liên tục (Continuous Match Mode). Thứ công nghệ này cho phép người dùng có thể nói nhiều từ hoặc cụm từ khác nhau nhất quán.

Một ví dụ điển hình là khi bạn muốn có một bản đồ quốc gia với tất cả các vùng, hoặc bản đồ thế giới có tất cả các quốc gia bên trong bản đồ đó, việc bạn cần làm là hiển thị chúng thông qua interactive canvas. Nhờ đó, bạn có thể trực quan hóa chúng và cho phép người dùng nói tên các quốc gia và thậm chí nói một cách nhanh chóng. Người dùng sẽ chỉ cần gọi tên từng quốc gia liên tục và chúng – hình ảnh các quốc gia sẽ được hiển thị liên tục thông qua công nghệ Continuous Match Mode.

Continuous Match Mode Developer

Ở góc độ của một lập trình viên, tất cả việc bạn cần làm là cung cấp cấu hình bao gồm danh sách các cụm từ chính xác mà người dùng có thể sử dụng / nói.

Trở lại ví dụ về bản đồ thế giới với khả năng hiển thị tất cả các quốc gia ở trên, bạn sẽ cần liệt kê ra tất cả các quốc gia và cung cấp thông tin đó đến action. Lúc này, interactive canvas web app có thể tiến hành xử lý chúng một cách nhanh chóng cho người dùng.

Bài viết được trích dẫn từ phần trình bày của Jessica Dene Earley-Cha tại sự kiện Vietnam Web Summit 2020 LIVE do TopDev tổ chức

RxSwift 6: Observables

RxSwift 6: Observables

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

Qua 5 bài trước, chúng ta đã hiểu các khái niệm cơ bản về RxSwift. Và bây giờ, chúng ta sẽ bắt đầu làm quen với Observables, khái niệm quan trọng của RxSwift. Dịch sát nghĩa là có thể quan sát được. Ở Rx, nó là 1 lớp cho phép bạn quan sát bất cứ thứ gì mà có sự thay đổi về trạng thái, như trạng thái bấm nút, ô text,..

Việc làm swift hấp dẫn nhất trong tháng

  6 ví dụ để bạn yêu luôn observable
  RxSwift 10: Làm việc với PublishSubjects

Chuẩn bị cho thực hành

Đầu tiên mở Xcode và tạo mới 1 playground và thêm đoạn code như sau:

public func example(of description: String, action: () -> Void) {
  print("\n--- Example of:", description, "---")
action() }

Nếu như bạn chưa biết cách cài RxSwift cho project của mình, vui lòng xem lại bài 5. Hoặc bạn có thể tải source code ở đây:

https://github.com/lexuanquynh/RxLearning

Sau gõ mở terminal, cd vào thư mục source code và gõ:

pod install

để cài đặt RxSwift cho project.

Vậy 1 observable là gì?

RxSwift 6: Observables

observable là trái tim của RxSwift. Chúng ta sẽ giành thời gian để nghiên cứu, thử nghiệm với nó.

Bạn sẽ nghe các khái niệm observableobservable sequence hay sequence trong Rx. Thậm chí bạn sẽ nghe các khái niệm stream từ các developer khác bằng các khái niệm ở môi trường phát triển khác tương tự. Tuy nhiên ở Rx nó không phải là stream, mà mọi thứ đều là sequence.

Nghĩa là trong Rx mọi thứ đều là luồng quan sát – dịch sát nghĩa là đối tượng quan sát sự kiện có thứ tự.

  • stream: sự kiện phát liên tục
  • sequence: sự kiện phát không đồng bộ, tùy ý
RxSwift 6: Observables
Sự kiện luồng phát 3 sự kiện 1, 2, 3 trong thời gian thực

Mũi tên từ trái sang phải mô tả thời gian, vòng tròn đánh số thể hiện sự kiện phát ra. Đầu tiên sự kiện 1 phát ra, tiếp theo lần lượt sự kiện 2, và cuối cùng là 3. Vậy lúc nào thì phát ra sự kiện? Nó có thể bất kỳ lúc nào ở trong vòng đời của 1 observable.

Vòng đời của 1 obserbvable

RxSwift 6: Observables
Sự kiện bấm vào nút

Những thứ có thể quan sát được và phát ra các sự kiện như nút bấm, được thể hiện bằng sơ đồ trên. Nút được phát ra 3 lần bấm, và kết thúc.

Tuy nhiên đôi khi sự kết thúc có thể trước 3 lần, do trục trặc lỗi.

RxSwift 6: Observables
Sự kiến phát ra có lỗi thể hiện màu đỏ

Khi 1 sự kiện lỗi phát ra, nó kết thúc luôn vòng đời của observable.

  • Một observable có thể quan sát và phát ra các sự kiện tiếp theo cho đến khi tạo ra một sự kiện lỗi và kết thúc
  • Hoặc phát ra 1 sự kiện hoàn thành và kết thúc
  • Một khi observable kết thúc, nó sẽ không thể phát ra thêm sự kiện nào nữa

Ví dụ trực tiếp từ mã nguồn RxSwift:

/// Represents a sequence event.
///
/// Sequence grammar:
/// **next\* (error | completed)**
public enum Event<Element> {
    /// Next element is produced.
    case next(Element)
    /// Sequence terminated with an error.
    case error(Swift.Error)
  /// Sequence completed successfully.
    case completed
}

Như ta thấy ở đây:

  • Sự kiện Next chứa instance của Element
  • Sự kiện error chứa lỗi Swift.Error
  • Sự kiện completed đơn giản là dừng và không có bất kỳ dữ liệu nào

Tạo observables

Quay lại với project các bạn vừa tạo ở đầu bài, chúng ta thêm đoạn code sau vào file playground:

example(of: "just, of, from") {
// 1
  let one = 1
  let two = 2
  let three = 3
// 2
  let observable: Observable<Int> = Observable<Int>.just(one)
}

Ở đoạn code trên:

  • Tạo 3 biến one, two, three
  • Tạo 1 observable và phát ra sự kiện one – tức là phát ra số nguyên one

just là hàm phát ra 1 sự kiện, nó là phương thức của observable. Tuy nhiên trong Rx, nó được gọi là toán tử.

Thêm tiếp mã sau vào cuối chương trình:

let observable2 = Observable.of(one, two, three)

Lần này, chúng ta không chỉ định rõ ràng kiểu cho observable, tuy nhiên chúng ta hiểu đây là 1 observable kiểu int, và đây không phải là mảng. Bấm Option + click chuột để xem:


observable tự chuyển về kiểu int

Nếu bạn muốn tạo 1 observable kiểu mảng, chúng ta dùng toán tử of như sau:

let observable3 = Observable.of([one, two, three])

Còn khi dùng toán tử from, chúng ta tạo 1 observable như sau:

let observable4 = Observable.from([one, two, three])

Toán tử from nhận các giá trị từ mảng, và tạo 1 observable riêng rẽ, nó có kiểu int, chứ không phải kiểu mảng [int].


from tạo ra 1 observable kiểu int, từ 1 mảng kiểu int

Subscribing tới 1 observable

Là một nhà phát triển IOS, chắc các bạn đã quen thuộc với NotificationCenter, nó phát ra 1 notification tới observers. Dưới đây là ví dụ về xử lý sự kiện UIKeyboardDidChangeFrame, được xử lý ở hàm closure:

let observer = NotificationCenter.default.addObserver(
  forName: .UIKeyboardDidChangeFrame,
  object: nil,
  queue: nil
) { notification in
  // Handle receiving notification
}

Việc đăng ký – subscribing tới 1 observable cũng tương tự. Thay vì dùng hàm addObserver(), thì ta dùng hàm subscribe().

Tuy nhiên việc đăng ký các observable hợp lý hơn. Như đã trình bày, các observable phát ra các sự kiện next, completed và error. Để hiểu hơn, chúng ta thêm ví dụ sau vào cuối chương trình:

example(of: "subscribe") {
    let one = 1
    let two = 2
    let three = 3
    let observable = Observable.of(one, two, three)
    observable.subscribe { event in
        print(event)
    }
}

Kết quả:

--- Example of: subscribe ---
next(1)
next(2)
next(3)
completed

Observable phát ra các sự kiện 1, 2, 3 và completed để kết thúc.

Thường chúng ta sẽ quan tâm giá trị phát ra từ các sự kiện đó hơn là chính nó. Chúng ta sửa ví dụ trên sau:

observable.subscribe { event in
  if let element = event.element {
    print(element)
  }
}

Kết quả:

--- Example of: subscribe ---
1
2
3

Sự kiện phát ra chứa giá trị, và là 1 giá trị optional. Vì vấy chúng ta check trước giá trị đó để tránh nil. Các sự kiện không chứa phần tử(ở đây là completed) sẽ không được in ra. Như ta đã biết, các sự kiện onNext đều có phần tử.

Thay thế đoạn code trên như sau:

observable.subscribe(onNext: { element in
  print(element)
})

Vậy là bạn đã biết cách tạo các observable có phần tử. Vậy muốn tạo 1 observable rỗng(empty) thì làm thế nào? Xem ví dụ sau:

example(of: "empty") {
  let observable = Observable<Void>.empty()
observable
  .subscribe(
// 1
    onNext: { element in
      print(element)
},
// 2
    onCompleted: {
      print("Completed")
} )
}

Một observable phải được định nghĩa 1 kiểu có thể quan sát được. Trong trường hợp này nó là kiểu void.

  1. Giống như sự kiện onNext bạn xem ở ví dụ trước
  2. sự kiện onCompleted không trả ra phần tử nào mà chỉ đơn giản là phát sự kiện hoàn thành.
--- Example of: empty ---
Completed

Nhưng mục đích của việc sử dụng 1 observable empty là gì? Nó thật sự hữu ích khi bạn muốn trả về 1 sự kiện kết thúc ngay lập tức và không trả về giá trị.

Trái với toán tử empty, toán tử never không emit ra sự kiện nào và không bao giờ kết thúc. Cùng xem ví dụ sau:

example(of: "never") {
  let observable = Observable<Any>.never()
  observable
    .subscribe(
      onNext: { element in
        print(element)
    },
      onCompleted: {
        print("Completed")
    }
) }

Nó không in ra bất cứ thứ gì kể cả Completed, vậy làm sao để biết là nó hoạt động? Hãy giữ vững tinh thần học hỏi cho đến phần Challenges sau này nhé.

Cho đến bây giờ, bạn đang làm việc với các observable có thể quan sát được. Nhưng bạn cũng có thể tạo ra observable từ 1 loạt các giá trị. Cùng xem ví dụ sinh dãy Phibonaci sau:

example(of: "range") {
    // 1
    let observable = Observable<Int>.range(start: 1, count: 10)
    observable
        .subscribe(onNext: { i in
            // 2
            let n = Double(i)
            let fibonacci = Int(((pow(1.61803, n) - pow(0.61803, n)) /
                                    2.23606).rounded())
            print(fibonacci)
        })
}
  1. Tạo 1 observable từ các số có phạm vi từ 1 đến 10
  2. Tính toán và in ra số fibonacci thứ n cho mỗi phần tử được emit ra.

hàm pow(x, y) trả về x^y.

Trên thực tế, có 1 nơi tốt hơn ngoài xử lý onNext, để đặt mã biến đổi emit sự kiện. Chúng ta sẽ tìm hiểu vấn đề này sau ở bài Transforming Operators.

Ngoài trừ ví dụ về never(), cho đến thời điểm này bạn đang làm việc với các observables có thể quan sát tự động phát ra sự kiện completed để kết thúc. Điều này giúp bạn tập trung vào cơ chế đăng ký observables, tuy nhiên lại gạt đi 1 khía cạnh quan trọng trong việc đăng ký đã xử lý như nào. Khi cấp phát thì nghĩa là cần phải giải phóng cho nó. Đã đến lúc chúng ta nghiên cứu việc giải phóng 1 observable như nào trong bài tiếp theo.

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ồ chí minh, Hà Nội, Đà Nẵng hấp dẫn trên TopDev