Home Blog Page 108

Rx-MVVM(1): Cấu trúc project – lib manager

Rx-MVVM(1): Cấu trúc project – lib manager

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

Vậy là bạn đã đọc qua về phần detail của khóa học rồi đúng không? Nếu chưa hãy đọc nó tại menu lập trình IOS nhé. Dù sao, chúng ta nên nhắc lại mục đích của hàng loạt bài viết liên quan tới Rx và MVVM trước. Để chúng ta biết chúng ta sẽ đạt được gì sau khi học.

  12 Packages và Libraries của Go cực kì mạnh mẽ mà bạn cần phải biết
  67 tools, libraries và resources giúp Web developer "dễ thở" hơn
Rx-MVVM(1): Cấu trúc project – lib manager
Cây thư mục project

Hãy xem tác giả đã bố trí như nào.

  1. Thư mục Application
  2. Thư mục Common
  3. Thư mục Configs
  4. Thư mục Extensions
  5. Thư mục Managers
  6. Thư mục Models
  7. Thư mục Modules
  8. Thư mục Networking
  9. Thư mục Third Party
  10. Thư mục Resources

Vậy là có tổng 10 thư mục. Chúng ta hãy tìm hiểu lần lượt từng thư mục nhé

1. Thư mục Application

Thư mục này có 3 file:

File AppDelegate.swift:

Hãy để ý dòng code này:

 let libsManager = LibsManager.shared

Ở đây tác giả tạo 1 singleton có tên là LibsManager. Nếu ai chưa biết về singleton, thì nôm na nó là 1 lớp được khởi tạo duy nhất 1 lần, và cho dù có gọi hàm tạo đi bao lần nữa nó cũng chỉ tạo có 1 lần thôi. Người ta hay dùng singleton cho những thứ chỉ được tạo 1 lần duy nhất, như quản lý AppDelegate, loading app… Ai chưa hiểu hãy giành 30 phút để google singleton là gì?

Vậy lớp LibsManager dùng để làm gì? Chúng ta hãy vào class này xem nhé:

Để ý đoạn code này:

if UserDefaults.standard.object(forKey: Configs.UserDefaultsKeys.bannersEnabled) == nil {
            bannersEnabled.accept(true)
        }
Rx-MVVM(1): Cấu trúc project – lib manager
lúc mới chạy app lần đầu

Bạn chạy app lần đầu, hình ảnh này sẽ xuất hiện. Còn các lần tiếp theo, nó không xuất hiện nữa. Và chính dòng code trên điều khiển việc đó.

Các dòng code tiếp theo, liên quan đến Rx:

 bannersEnabled.skip(1).subscribe(onNext: { (enabled) in
            UserDefaults.standard.set(enabled, forKey: Configs.UserDefaultsKeys.bannersEnabled)
            analytics.set(.adsEnabled(value: enabled))
        }).disposed(by: rx.disposeBag)

Bắt đầu mù tịt vì đụng đến Rx rồi. Bắt đầu khó nha. Đến đây thì chúng ta bắt buộc phải đọc về Rx để hiểu nó đang làm gì. Vậy thì hãy để ý tới biến bannersEnabled. Nó được khởi tạo dạng Rx chứ không phải biến thông thường bằng câu lệnh:

let bannersEnabled = BehaviorRelay(value: UserDefaults.standard.bool(forKey: Configs.UserDefaultsKeys.bannersEnabled))

Chúng ta thấy, BehaviorRelay là 1 hàm, có value phía trong là 1 giá trị kiểu boolean. Đọc về help của Xcode như sau:

Summary
BehaviorRelay is a wrapper for BehaviorSubject.
Discussion
Unlike BehaviorSubject it can’t terminate with error or completed.

Đến đây thì đọc không hiểu mô tê gì cả. Bắt buộc chúng ta phải đọc sample ở đâu đó trên mạng. OK, vậy chúng ta cùng tìm hiểu nhé.

Đầu tiên chúng ta tải source tại đây:

https://github.com/codetoanbug/sampleRx/tree/master

Sau đó các bạn mở file RxSample.xcworkspace và xem code trong file ViewController

       let bag = DisposeBag() //0

        let bannersEnabled = BehaviorRelay<String>(value: "code")//1

        bannersEnabled.accept("toan")//2
        bannersEnabled.accept("bug")//3

        let subscriber = bannersEnabled.subscribe { (event) in
            print("event = \(event)")
        } //4

        bannersEnabled.accept("viet")//5
        bannersEnabled.accept("nam")//6

        subscriber.disposed(by: bag)//7

Giải thích từng dòng:

Dòng 1: Các bạn khởi tạo 1 biến bannersEnabled có kiểu là BehaviorRelay. Đúng ra cái này không phải biến thông thường như các bạn đã quen, là nó có giá trị kiểu số 1,2 hay là kiểu string abc.. Mà thằng này có 1 đặc điểm là biến có thẻ phát ra 1 giá trị nào đó theo thời gian thực, cụ thể mình cho nó phát ra được các giá trị string. Giá trị khởi đầu là “code”

Dòng 2, 3: Mình đang ném 2 cái giá trị string “toan” và “bug” vào biến này để nó phát ra – nó như 1 cái đài phát thanh đang nói ra 2 câu đó.

Dòng 4: Mình khởi tạo biến subscriber, biến này dùng để lắng nghe các sự kiện phát ra từ biến bannersEnabled, giống như bạn chọn đúng kênh của đài phát thanh để nghe âm thanh trên kênh. này. Và câu lệnh print để hiển thị những gì mà nó nghe được.

Dòng 5, 6: tương tự dòng 2,3 mình lại phát ra 2 câu nói “viet” và “nam”.

Dòng 7: Các bạn hiểu nôm na là quy tắc dọn dẹp bộ nhớ tự động. Nó dựa vào biến dòng số 0 để dọn dẹp lại, và nôm na nó bắt buộc luôn khi các bạn khởi tạo các subscriber thì đều phải nhờ ông bag này dọn dẹp bộ nhớ khi không dùng nữa. Hiểu thế cho đơn giản.

Kết quả như sau:

event = next(bug)
event = next(viet)
event = next(nam)

Tại sao chúng ta chỉ nghe được 3 câu trên. Đơn giản do thằng bannersEnabled nó bắt đầu nghe tính từ thời điểm cách thời điểm nó đăng ký trước đó 1 tín hiệu, nghĩa là bắt đầu nghe từ từ bug trở đi về sau.

Vậy làm sao ta chỉ muốn nghe mỗi 2 từ viet nam thôi, cách đơn giản là thêm dòng lệnh này thay thế:

let subscriber = bannersEnabled.skip(1).subscribe { (event) in
            print("event = \(event)")
        }

skip(n) ở đây nghĩa là bỏ đi n giá trị phát ra tính từ thời điểm trước đăng ký 1 sự kiện cho đến về sau. Các bạn có thể thay đổi con số để loại bỏ. Ví dụ skip(2) thì nó bỏ từ bug và từ viet, còn nghe được mỗi từ nam.

Ồ! Vậy bạn đã hiểu các biến trên làm gì chưa? Bọn nó phát ra sự kiến, xử lý sự kiện trong hàm subscribe.

Quay trở lại hàm trong dự án của chúng ta, đoạn code trên:

let bannersEnabled = BehaviorRelay(value: UserDefaults.standard.bool(forKey: Configs.UserDefaultsKeys.bannersEnabled))//0
if UserDefaults.standard.object(forKey: Configs.UserDefaultsKeys.bannersEnabled) == nil {//1
            bannersEnabled.accept(true)//2
        }

        bannersEnabled.skip(1).subscribe(onNext: { (enabled) in
            UserDefaults.standard.set(enabled, forKey: Configs.UserDefaultsKeys.bannersEnabled)//3
            analytics.set(.adsEnabled(value: enabled))//4
        }).disposed(by: rx.disposeBag)//5

Dòng 1: lệnh if nếu như kiểm tra cái bannersEnabled chưa có giá trị(app chưa được mở bao giờ) thì gán giá trị bannersEnabled.accept(true) để phát ra tín hiệu rằng nó chưa mở banner bao giờ(dòng 2).

Dòng 3: Nó đăng ký 1 subscriber và bỏ đi 1 skip để loại bỏ giá trị khởi tao ban đầu(dòng 0), chỉ bắt đầu nghe ngóng từ dòng số 2 trở đi.

Vậy khi dòng 2 phát ra sự kiện thì các dòng 3, 4 được thực thi, và nếu mình đoán không nhầm thì nó làm 2 hành động: 1 là gán giá trị để bật banner lên, và chắc chắn ở đâu đó có 1 thằng lắng nghe khi giá trị này thay đổi, để hiển thị UI như hình trên. 2 là nó bật quảng cáo lên, và cũng tương tự, ở đâu đó nhiều thằng subscriber cũng lắng nghe sự thay đổi của biến này để hiển thị UI quảng cáo(adsEnabled nghĩa là bật quảng cáo, từ ads là quảng cáo, enabled là bật lên).

Vậy chúng ta đã hiểu hết logic đống loằng ngoằng trên rồi đúng không? Các bạn bắt đầu hình dung được là Rx sẽ là công cụ giúp chúng ta phát tín hiệu và lắng nghe tín hiệu. Vậy nó có ưu điểm gì:

Ví dụ khi chúng ta bật ads lên, thì mọi UI ở khắp mọi nơi khi hiển thị cho người dùng không cần quan tâm bạn thay đổi ở màn hình nào, đều đồng bộ được giá trị. Nếu bạn làm UIKit thuần, bạn sẽ phải vất vả dùng NSNotificationCenter hay là Protocol hay là closure function để báo hiệu giá trị thay đổi cho các màn khác. Và giả sử bạn có 5 cái màn khác nhau, sub view có, parrent view có, thì câu chuyện đồng bộ hóa dữ liệu trở nên khủng khiếp biết nhường nào 🙁

OK, Rx đáng để học đúng không nào? Vậy chúng ta cùng xem các đoạn code khác nhé.

Chúng ta xem tiếp file LibsManager nhé.

Đoạn code:

func setupLibs(with window: UIWindow? = nil) {
        let libsManager = LibsManager.shared
        libsManager.setupCocoaLumberjack()
        libsManager.setupAnalytics()
        libsManager.setupAds()
        libsManager.setupTheme()
        libsManager.setupKafkaRefresh()
        libsManager.setupFLEX()
        libsManager.setupKeyboardManager()
        libsManager.setupActivityView()
        libsManager.setupDropDown()
        libsManager.setupToast()
    }

Ở đây, hàm setupLibs có các chức năng sau:

setupCocoaLumberjack – vậy nó là gì? Nó là thư viện CocoaLumberjack:

https://github.com/CocoaLumberjack/CocoaLumberjack

Như dòng giới thiệu:

CocoaLumberjack is a fast & simple, yet powerful & flexible logging framework for Mac and iOS.

Vậy nó là 1 thư viện log, chức năng là ghi lại những hoạt động của người dùng trong ứng dụng. Ví dụ người dùng bấm nút, chuyển màn hình, gõ text… bất cứ action nào trên ứng dụng của mình. Điều này nhằm cho developer đánh giá được người dùng hay xem phần nào, màn nào bị crash không, … rất nhiều thứ hay ho mà chúng ta có thể thống kê được qua thư viện này. Nhằm cải thiện app tốt hơn hay triển khai các hoạt động marketing cho app…

Còn về chi tiết, chúng ta sẽ giới thiệu ở 1 vài viết khác về CocoaLumberjack , hoặc bạn có thể tự tìm hiểu dần qua google.

setupAnalytics là gì? Ở đây chúng ta đang nói đến Firebase của Google. Nó có nhiều chức năng lắm, và cụ thể là làm server, realtime, bắn notification cho app, tracking app, quảng cáo… Rất nhiều tính năng mà Google cung cấp cho chúng ta. Và tất nhiên như thông lệ, Google vẫn hay bài cho dùng thử giới hạn, dùng quá thì phải pay 😀 Đúng là ông lớn nên biết làm kinh tế quá ha.

Cụ thể nó như nào, chúng ta sẽ nghiên cứ 1 topic sâu về Firebase sau các bạn nhé.

setupAds là gì? cái tên tiếng Anh cũng nói rằng nó là cài đặt cho phần quảng cáo trong app rồi đúng không. Và ở đây chúng ta dùng quảng cáo của Google.

setupTheme – phần này khá mới trong thời gian gần đây, khi mà các ứng dụng bắt đầu quan tâm tới thị giác của người dùng nhiều hơn. Làm sao mà họ dùng app đỡ hại mắt, và dùng trong đêm tối sẽ theo 1 chế độ màu khác với dùng ban ngày. Người ta đẻ ra dark-mode và light-mode, chính ông lớn apple cũng chơi cuộc chơi này rồi. Nếu bạn đang cầm trên tay 1 thiết bị IOS 13, bạn sẽ hiểu được vào ban đêm, nhiều ứng dụng tự nhiên chuyển màu tối, đễ đơ hại mắt hơn. Hay thậm chí facebook cũng đã bật chế độ này trên appweb của họ rồi. Nó rất nhiều thứ hay ho để học, và trong ứng dụng này chúng ta chỉ cần bấm nút switch đơn giản để chuyển qua lại giữa 2 chế độ.

setupKafkaRefresh – Cái này là gì? Thư viện ở đây:

https://github.com/OpenFeyn/KafkaRefresh

Như readme mà họ viết, thì nó đơn giản là dạng loading khi bạn vuốt xuống ở table để cập nhật data mới, hay gọi là pull to refresh mà các bạn hay thấy trên nhiều ứng dụng. Trông cũng cool ngầu đấy chứ:

một dạng loading của thư viện

setupFLEX – Nó là gì?

OKie, chúng ta lại tìm hiểu thư viện của nó nào:

https://github.com/Flipboard/FLEX

Đọc readme:

FLEX (Flipboard Explorer) is a set of in-app debugging and exploration tools for iOS development. When presented, FLEX shows a toolbar that lives in a window above your application. From this toolbar, you can view and modify nearly every piece of state in your running application.

Chi tiết, bạn đọc readme tiếng Anh, còn ai không thích tiếng anh thì mình tìm thấy 1 bài viết khá đầy đủ ở đây. Nôm na nó là thư viện cho phép xem thông tin mọi thứ của app mà ta đang làm, bao gồm view, thông số biến, hàm, log hay database…

setupKeyboardManager – nghe tên cũng biết là quản lý bàn phím rồi đúng không?

Xem detail thư viện tại:

https://github.com/hackiftekhar/IQKeyboardManager

Như readme viết, thường khi chúng ta build ứng dụng sẽ hay gặp tình trạng bàn phím che mất chữ, không nhìn thấy được. Và thư viện này giúp chúng ta giải quyết vấn đề đó mà không phải viết bất kỳ 1 dòng code nào. Nghe ra gì phết. Okie vậy chúng ta cứ dùng thôi.

setupActivityView – vào phần chi tiết chúng ta thấy 1 đối tượng NVActivityIndicatorView.

Thư viện:

https://github.com/ninjaprox/NVActivityIndicatorView


Hình ảnh thư viện

Như vậy thì chúng ta cũng biết được là nó làm gì rồi đúng không? Đó là các hiệu ứng chờ đợi trên app rất đẹp mắt và cute.

setupDropDown – control bổ sung cho IOS

Thư viện:

https://github.com/AssistoLab/DropDown


Ví dụ về dropDown

Vậy cũng dễ hình dung nó là control bổ sung do IOS mặc định không có.

setupToast – chắc chắn là các thông báo đẩy như android, control bổ sung cho IOS.

Thư viện:

https://github.com/scalessec/Toast-Swift

Rx-MVVM(1): Cấu trúc project – lib manager
Các ví dụ về thông báo đẩy Toast

Khá ok!

Vậy là chúng ta đã dạo qua 1 vòng về file LibsManager – quản lý toàn bộ library của App. Theo mình đây là cách rất thông minh để có thể tập trung lại các thư viện, dễ quản lý và dễ sửa lỗi khi cần.

2. Thư mục Managers

Chúng ta cùng nghiên cứu về cách quản lý các thư viện của tác giả ở bài viết 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 Tìm việc Project manager hấp dẫn trên TopDev

Kiểu Enum trong C/C++ (Code ví dụ Enumeration trong C/C++)

Kiểu Enum trong C/C++ (Code ví dụ Enumeration trong C/C++)

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

Kiểu Enum trong C/C++ (Code ví dụ Enumeration trong C/C++)

(Xem thêm: Tự học lập trình C, C++ qua code ví dụ)

Enum là gì?

Trong lập trình C/C++, Enum hay Enumeration là kiểu dữ liệu cố định, chỉ cho phép biến nhận số số giá trị nhất định nào đó.

Các giá trị enum có thể coi là một hằng số. Việc sử dụng enum giúp đảm bảo giá trị các biến chỉ nhận các giá trị mong đợi.

Ví dụ: Mình định nghĩa kiểu Enum là dayOfWeek và chỉ nhận các giá trị là ngày trong tuần (từ thứ 2 đến chủ nhật). Mỗi lần có tính toán tới ngày trong tuần thì mình dùng dayOfWeek sẽ giúp tránh các giá trị nằm ngoài khoảng từ thứ hai đến chủ nhât.

  Kiểu enum trong TypeScript: làm việc như thế nào, sử dụng ra sao
  1001 Tips: Con trỏ và hàm (Pointer & Function) trong C++

Tạo Enum trong C/C++

Để tạo enum trong C/C++ ta dùng từ khóa enum với cú pháp sau:

enum ten_enum {trang_thai_1: gia_tri_1, trang_thai_2: gia_tri_2,...}

Ví dụ:

#include<stdio.h> 

enum dayOfWeek{Mon=2, Tue=3, Wed=4, Thur=5, Fri=6, Sat=7, Sun=8}; 

int main()
{
enum dayOfWeek day; 
 day = Wed; 

printf("Wednesday: %d \n",day); 

printf("All day of week: %d - %d - %d - %d - %d - %d - %d", Mon, Tue, Wed, Thur, Fri, Sat, Sun); 

return 0; 
}

Kết quả:

Kiểu Enum trong C/C++ (Code ví dụ Enumeration trong C/C++)

C++ tuyển dụng nhiều vị trí, lương cao, ứng tuyển ngay!

Trường hợp bạn không truyền giá trị cho các trạng thái trong enum thì nó sẽ tự nhận các giá trị tăng dần từ 0. Hoặc tăng dần theo giá trị của trạng thái trước đó.

Ví dụ:

enum dayOfWeek{Mon, Tue, Wed, Thur, Fri, Sat, Sun};

tương đương với:

enum dayOfWeek{Mon=0, Tue=1, Wed=2, Thur=3, Fri=4, Sat=5, Sun=6};

Hay

enum dayOfWeek{Mon, Tue=3, Wed=4, Thur=5, Fri=3, Sat, Sun};

Tương đương với:

enum dayOfWeek{Mon=0, Tue=3, Wed=4, Thur=5, Fri=3, Sat=4, Sun=5};

Lưu ý

Các trạng thái trong một enum có thể có giá trị bằng nhau.

Các trạng thái trong enum chỉ nhận giá trị là kiểu integer.

Trong cùng một phạm vi (scope), thì 2 enum không thể có trạng thái trùng tên.

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

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

Xem ngay những tin đăng tuyển dụng IT mới nhất trên TopDev

Javascript sự khác biệt map và weakmap. What make a different?

Javascript sự khác biệt map và weakmap

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

Sự khác biệt map và weakmap luôn là một phần kiến thức cần nắm vững đối với lập trình viên Javascript. Nắm rõ sự khác biệt còn phải hiểu lúc nào nên sử dụng loại nào nữa. Đấy, vô vàn vấn đề cần tìm hiểu.

Tuy nhiên, khó cũng phải hiểu. Vì Data Structure không phải muốn dùng sao cũng được. Ở các System lớn, chỉ cần thay đổi một kiểu của DS thôi cũng gây ra hàng tá vấn đề.

Dữ liệu lớn, request xử lý hàng đống. Memory là thứ cần kiểm soát chặt chẽ để đảm bảo hệ thống luôn vận hành trơn tru. Kieblog hân hạnh giới thiệu bài viết sự khác biệt map và weakmap. Bắt đầu ngay thôi nào!

Tuyển dụng Javascript cho bạn

1. Định nghĩa

Map thì đã quá quen thuộc rồi

The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.

Đối tượng Map lưu cặp key-value (khoá – giá trị) theo thứ tự chèn vào của khoá. Bất kỳ giá trị nào (cả đối tượng (objects) và primitive values) đều có thể sử dụng làm key hoặc value.

WeakMap thì bản thân bao gồm 2 chữ. Weak và Map, hẳn là phải có cái gì đó “yếu hơn” rồi.

The WeakMap object is a collection of key/value pairs in which the keys are weakly referenced. The keys must be objects and the values can be arbitrary values.

Đối tượng WeakMap là collection của các cặp key/value với các key được tham chiếu yếu ớt. Các key phải là đối tượng và các value có thể là bất kỳ giá trị nào. 

Cả Map và WeakMap đều cho phép lưu trữ theo kiểu key-value. Key và uniques và một loạt Value đi kèm. Tuy nhiên vẫn tồn tại một số sự khác biệt map và weakmap.

Javascript sự khác biệt map và weakmap. What make a different
Weak không có nghĩa là yếu. Chỉ “lỏng lẻo” hơn một vài điểm thôi

2. Sự khác biệt Map và Weak Map

2.1 Key Store

Cùng là cơ chế lưu trữ key-value. Nhưng có sự khác biệt rõ ràng về tiêu chuẩn của key.

WeakMap accepts only objects as keys whereas a Map,in addition to objects, accepts primitive datatype such as strings, numbers etc.

WeakMap chỉ chấp nhận kiểu objects đóng vai trò như là key. Trong khi Map, ngoài kiểu Objects, nó còn chấp nhận cả các kiểu nguyên thủy như Strings, Numbers,…

JavaScript
map.set(44, 12);

// Lỗi
weakmap.set(44, 13);

// Lỗi. Không thể tạo WeakMap từ 2D array.
var map_1 = new WeakMap([[1, 2], [4, 5]]);

Mà cái thằng WeakMap này cũng dị. Mấy function hay methods dùng được với map thì không dùng được với Weakmap.

JavaScript
console.log(weakmap.size); //undefined


//loop through the keys in an map
for(var i of map)
{
console.log(i);
}

//loop through the keys in an weakmap doesn't work
for(var i of weakmap)
{
console.log(i);
}

//delete all keys
map.clear();

weakmap.clear(); //but this works

Ngoài chuyện Primitive Type thì còn một vấn đề khác nữa là Memory Leak. Cái này là “cốt lõi”. Có nó mới có chữ Weak trong WeakMap. Khác biệt cốt lõi nhất!

  15 ví dụ sử dụng map, reduce và filter
  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết

2.2 Vấn đề Memory Leak

Memory thì từ xưa đến nay đã luôn là vấn đề cố hữu của Map. Một Map được tạo ra cũng đồng nghĩa với một phần memory được cấp phát. Cấp thì dễ, nhưng đôi khi mấy anh dev lại quên lấy lại phần đó (mặc dù đã sử dụng xong Map).

Sự khác biệt giữa Map và WeakMap lại là vấn đề này. Đây cũng là điểm khác biệt cần nắm rõ để có lựa chọn sáng suốt khi lựa chọn Map hay WeakMap.

Để dễ hiểu hơn thì ta có thể xem xét ví dụ sau:

JavaScript

var map = new Map();
var weakmap = new WeakMap();

(function(){
var a = {x: 12};
var b = {y: 12};

map.set(a, 1);
weakmap.set(b, 2);
})()

Xét như ví dụ phía trên, function tóm gọn lại từ dòng 4 đến dòng 10. Tuy nhiên để access được b = {y: 12}; bên ngoài function scope thực sự là không thể.

Mặc dù cả Map và Weakmap đều là global access variable. Tuy nhiên cơ chế của WeakMap cho phép Garbage collector xóa pointer tới b của chính nó. Bản thân chữa weak mang nghĩa là yếu, liên kết của weak map tới chính đứa con mà nó set vào là liên kết lỏng lẻo.

So “Map” can cause more garbages in memory. We can say that “Map” references are strong pointer whereas “WeakMap” references are weak pointers.

Chính vì vậy Map có thể chiếm dụng khá nhiều về mặt memory. Cũng có thể nói “map” tham chiếu mạnh hơn so với “WeakMap”. Tham chiếu ở đây được hiểu là tham chiếu tới memory được cấp phát.

3. Lúc nào nên xài cái gì?

Không phải ngẫu nhiên mà Javascript ES6 bổ sung thêm WeakMap. Rõ ràng Map luôn có sự bất tiện khi sử dụng.

Javascript sự khác biệt map và weakmap. What make a different
Rõ ràng có sự bất tiện khi sử dụng Map

Vấn đề memory có được dọn dẹp hay không đã là sự khác biệt map và weakmap. Vậy lúc nào ta nên dùng WeakMap?

  • Đầu tiên, ta cần một Map để chứa key-value. Tuy nhiên thời gian sử dụng chỉ gói gọn trong một vài dòng code. Tính toán, mapping xong lại không xài tới Map nữa -> Ưu tiên sử dụng WeakMap.
  • Keeping private data about a specific object and only giving access to it to people with a reference to the Map. A more ad-hoc approach is coming with the private-symbols proposal but that’s a long time from now. Đảm bảo an toàn cho dữ liệu, chỉ cho phép access đối với các đối tượng có tham chiếu và cần sử dụng tới WeakMap.

Chắc sẽ còn một vài trường hợp khác WeakMap trở nên hữu ích. Tui sẽ bổ sung cho mấy ông sau.

4. Tham khảo

Thank for your attention – Have a great day – 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 tìm việc IT hấp dẫn trên TopDev

Bảo mật ứng dụng Java web bởi Spring Security

Bảo mật ứng dụng Java web bởi Spring Security

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

Chúng mình xin chia sẻ với bạn kỹ thuật bảo mật tiên tiến, mạnh mẽ dành cho Java web sử dụng Spring Security. Bài viết hội tụ các best-practice, các kỹ thuật tối tân nhất hiện nay. Nội dung sẽ hay và khó.

Công nghệ sử dụng (technology-stack)

  • Spring Security
  • Spring Boot
  • Spring Web MVC
  • Gradle (build system)
  • Thymeleaf (template engine)

Công cụ sử dụng

  • IntelliJ IDEA 2016.1.3
  • Apache Tomcat 8.0.35

Trước khi bắt tay thực hiện, Bạn nên đọc các bài viết trên SmartJob:

  • Giới thiệu Spring Boot (để hiểu về Spring Boot)
  • Kiểm tra tính hợp lệ của dữ liệu đầu vào form Spring Web MVC bởi Hibernate Validator  (để hiểu về luồng đi của Spring Web MVC)

Spring Security [1] là bộ khung bảo mật ứng dụng Java web cung cấp cơ chế cấp phép quyền (authorization) và xác thực người dùng (authentication). Sức mạnh của Spring Security thể hiện ở sự dễ dùng, dễ cấu hình, khả năng mở rộng, và khả năng bảo mật ứng dụng mạnh mẽ. Spring Security chống được các kỹ thuật hacking tinh vi:

  • Session fixation (Tấn công chiếm quyền điều khiển session của người dùng) [2]
  • Clickjacking (click chuột tự động, ví dụ click vào nút Like Facebook mà không xin phép người dùng)
  • CSRF (Cross-site request forgery: Tạo truy vấn (request) giả mạo truyền từ trang này sang trang khác)

Mục tiêu

Chúng ta sẽ xây dựng ứng dụng Java web có trang chủ, trang đăng nhập, khu vực bảo mật (chỉ truy cập được sau khi người dùng hợp lệ đăng nhập). Cấu trúc project sau khi hoàn tất sẽ như thế này

Bảo mật ứng dụng Java web bởi Spring Security

Bạn sẽ phải tạo/chỉnh sửa 7 file:

  1. Application.java
  2. MvcConfig.java
  3. WebSecurityConfig.java
  4. dang_nhap.html
  5. khu_vuc_bao_mat.html
  6. trang_chu.html
  7. build.gradle

Sử dụng IntelliJ IDEA để khởi tạo project:

Bảo mật ứng dụng Java web bởi Spring Security

Bộ khung project được dựng trên nền Spring Boot. Bấm chọn Spring Initializr, rồi bấm Next.

Bảo mật ứng dụng Java web bởi Spring Security

Bạn điền thông tin, các tùy chọn vào 10 mục như ảnh chụp màn hình. Bước thứ 11 là bấm nút Next

Bảo mật ứng dụng Java web bởi Spring Security

Chọn và nhặt vào thư viện cần dùng. 3 thành phần tham gia mở rộng ứng dụng Spring Boot là:

  • Security
  • Web
  • Thymeleaf

Phiên bản Spring Boot ổn định, mới nhất tại thời điểm viết bài là 1.3.5.RELEASE

Bảo mật ứng dụng Java web bởi Spring Security

Đặt tên project, chọn vị trí lưu mã nguồn project

Bảo mật ứng dụng Java web bởi Spring Security

Cấu hình cho Gradle build system

Bảo mật ứng dụng Java web bởi Spring Security

InteliJ IDEA và Spring Initializer tự động sinh ra cho bạn cấu trúc thư mục của project. Tìm file build.gradle sửa lại nội dung như sau:

Dòng 10, 29 cho phép chúng ta đóng gói ứng dụng Spring Boot thành file WAR truyền thống. (Nếu để theo mặc định, Spring Boot sẽ đóng gói ứng dụng web thành file JAR thực thi dùng Apache Tomcat nhúng, run trực tiếp, rất đặc sắc. Tuy nhiên theo cách này việc deploy sẽ quá đơn giản đến mức khiến bạn đọc khó hiểu, tại sao không có file WAR mà ứng dụng Java web vẫn chạy).

Tìm Java job lương cao trên TopDev ngay!

Tạo thêm thư mục java trong thư mục src/main, rồi tạo thêm package vn.smartjob.demo_spring.demo_security . Tạo class Application.java

Mã nguồn dưới đây thực chất đã chuyển đổi (convert) ứng dụng Spring Boot nguyên bản (tạo ra file JAR có thể run được) thành ứng dụng web Java truyền thống (đóng gói thành file WAR) bằng cách:

– Dòng 12, class Application  được extends từ class org.springframework.boot.context.web.SpringBootServletInitializer
– Dòng 14 đến 17, phải Override method configure  để đóng gói ứng dụng Spring Boot thành file WAR truyền thống.

  8 công cụ miễn phí để bảo mật khi lập trình phần mềm
  Bảo mật web - Một số kiểu tấn công

Tạo thêm thư mục resources bên trong thư mục src\main. Tạo thư mục templates bên trong thư mục resources.. Sau đó tạo 3 tập tin giao diện (sử dụng Thymeleaf template engine). Các file giao diện sử dụng Thymeleaf. Ở đâu Thymeleaf xử lý (render) ra giao diện, sẽ sử dụng HTML element mà trong đó chứa thuộc tính th:____  . Các thẻ security chèn vào trong giao diện sẽ do Spring Security xử lý.

File trang_chu.html

Dòng 26: Cấp phép truy cập, khởi tạo luồng lo-gic bảo mật.
Dòng 27: Cho phép tất cả người dùng (đã đăng nhập, hay chưa đăng nhập) đều được truy cập trang chủ.
Dòng 30: Nếu người dùng có nhu cầu, đưa người dùng đến trang Đăng nhập.
Dòng 31: Tất cả mọi người dùng đều có quyền tiếp cận (truy cập) trang Đăng nhập.
Dòng 34: Sau khi đăng nhập, người dùng đã được xác thực có thể Đăng xuất.

Dòng 48: Cấp phép người dùng có tên đăng nhập smartjob, mật khẩu 4321, với vai trò (role) là người dùng thông thường (USER). Trên một hệ thống sẽ có nhiều role khác nhau.

Chạy ứng dụng trên Apache Tomcat 8

Bảo mật ứng dụng Java web bởi Spring Security

Chúng ta cố tình nhập sai tên đăng nhập hoặc mật khẩu để kiểm tra thông báo lỗi và kiểm tra khả năng ngăn chặn của Spring Security:
Bảo mật ứng dụng Java web bởi Spring Security

Khi nhập đúng tên đăng nhập: smartjob và mật khẩu: 4321 thì người dùng sẽ truy cập được khu vực bảo mật:

Bảo mật ứng dụng Java web bởi Spring Security

Đăng nhập thành công, người dùng truy cập được khu vực đặc quyền riêng. Thậm chí Trình duyệt web còn hỏi bạn có muốn lưu tên đăng nhập, mật khẩu ứng dụng trong trình duyệt hay không. Để sử dụng tính năng đăng xuất (do Spring Security cung cấp), bạn bấm nút Đăng xuất để kiểm tra việc vận hành của việc xóa thông tin người dùng trên trình duyệt.

Mẹo: Trong quá trình phát triển ứng dụng, có thể bạn phải xóa thông tin đăng nhập lưu trong trình duyệt đi để test khả năng bảo mật. Bạn làm như sau: Trình duyệt Google Chrome, chọn Setting, gõ từ khóa tìm kiếm pri (privacy)

Bảo mật ứng dụng Java web bởi Spring Security

Chọn Content settings… rồi tìm

Bảo mật ứng dụng Java web bởi Spring Security

Chọn All cookies and site data… 

Bảo mật ứng dụng Java web bởi Spring Security

Nhớ bấm nút X rồi sau đó Done để xóa thông tin bảo mật lưu trên trình duyệt, nhằm mục đích chuẩn bị môi trường test ứng dụng Spring Security.

Tải về mã nguồn từ server SmartJob: spring_security hoặc clone/fork từ GitHub: https://github.com/SmartJobVN/spring_security

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

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

Xem thêm Việc làm lập trình Java hấp dẫn trên TopDev

Web app là gì? So sánh Website và Web Application

website v

Tác giả: Hillary Nyakundi

Người dùng cuối thường sẽ không phân biệt được những điểm giống và khác nhau của website và web application. Họ chỉ việc nhập URL và sử dụng kết quả tìm kiếm là được. Nhưng với các dev, bạn chính là người build nên các nền tảng này cho người dùng sử dụng. Do đó việc nắm bắt được sự khác nhau này chắc chắn sẽ giúp ích rất nhiều cho công việc.

Web developer Jobs for you in Vietnam

Web Application là gì?

Web Application còn hay được gọi tắt là web app là một phần của phần mềm có thể được truy cập bởi trình duyệt. Nói cách khác, web app là website có chức năng và các yếu tố tương tác.

Các web app có khả năng tùy biến cực cao và có thể thực hiện nhiều tác vụ và chức năng khác nhau. Chúng thường phức tạp hơn và khó xây dựng hơn, đồng thời chúng cần một đội ngũ phát triển phần mềm có kinh nghiệm để tạo ra chúng.

Một số web apps phổ biến hiện nay như Twitter, Facebook, Gmail, Adobe CC và Youtube.

website vs web app
Web Application là gì?

Đặc điểm của Web Application

  • Đa nền tảng
  • Dễ dàng test với các bài kiểm tra automated
  • Được lưu trữ trên đám mây

Bạn sử dụng Web Application để làm gì?

  • Có thể sử dụng trên mọi nền tảng vì chúng hỗ trợ tất cả các trình duyệt hiện đại
  • Bạn không cần phê duyệt từ cửa hàng ứng dụng để có một web app
  • Người dùng có thể truy cập chúng bất kỳ lúc nào, từ bất kỳ đâu
  • Có thể sử dụng trên cả thiết bị di động hoặc máy tính để bàn để truy cập dữ liệu
  • Dễ hiểu hơn vì sử dụng cùng một bộ mã trong toàn bộ ứng dụng

Xem thêm So sánh Single Page App (SPA) vs Progressive Web App (PWA)

Website là gì?

Website là một tập hợp các trang web có liên quan chứa hình ảnh, văn bản, âm thanh, video và hơn thế nữa. Nó có thể bao gồm một trang hoặc nhiều trang và nó cung cấp cả nội dung trực quan và văn bản. Có rất nhiều loại website khác nhau hiện tại trang web giáo dục, cộng đồng, tìm kiếm, viết blog,…

Một số website phổ biến như Wikipedia, Google, Amazon và Craigslist.

website vs web app
Website là gì

Đặc điểm của một Website

  • Thân thiện với người dùng
  • Có thể dễ dàng tìm kiếm bằng công cụ tìm kiếm
  • Hiển thị nội dung chất lượng
  • Có một bố cục dễ điều hướng

Khi nào bạn cần dùng đến website?

  • Bạn có thể cần một trang web để giới thiệu sản phẩm của mình
  • Trang web giúp bạn thiết lập thương hiệu cho doanh nghiệp
  • Giúp tạo ra bằng chứng xã hội để người khác có thể thấy những gì bạn đã và đang làm
  • Sử dụng nó để quảng cáo và nâng cao nhận thức về thương hiệu của mình
  15 thư viện slider jquery miễn phí cho dự án website của bạn
  Cải thiện hiệu năng cho JavaScript Web Application chỉ trong vòng vài bước đơn giản

Sự khác biệt chính giữa Website và Web Application

Sự tương tác của người dùng

Website cung cấp nội dung văn bản và hình ảnh mà người dùng có thể xem và đọc, nhưng điều này không ảnh hưởng đến hoạt động của trang web.

Với web app, người dùng không chỉ xem nội dung trên trang mà còn thao tác dữ liệu. Người dùng có thể tương tác từng người một bằng cách điền vào biểu mẫu hoặc cung cấp dữ liệu cần thiết để tương tác với ứng dụng.

Vấn đề xác thực

Xác thực không phải lúc nào cũng cần thiết cho các website dựa trên thông tin. Người dùng có thể được yêu cầu đăng ký nhận các bản cập nhật thường xuyên để truy cập các tùy chọn bổ sung, và thế là xong.

Các web app cần xác thực vì chúng cung cấp phạm vi tùy chọn và chức năng/tương tác rộng hơn nhiều so với một trang web. Điều này có nghĩa là bạn phải có tên người dùng và mật khẩu để truy cập vào tài khoản của mình.

website vs web app
Một số khác biệt cơ bản giữa website với web application

Tasks và sự linh hoạt

Một website sẽ chỉ hiển thị dữ liệu và thông tin được thu thập trên một trang cụ thể khi người dùng đã tìm kiếm.

Trong một web app, các chức năng cao hơn và phức tạp hơn so với các chức năng của một trang web.

Mục đích sáng tạo

Một website chủ yếu bao gồm nội dung tĩnh. Điều này có nghĩa là thông tin có thể truy cập công khai cho tất cả khách truy cập.

Web app được thiết kế để tương tác với người dùng cuối. Điều này có nghĩa là nếu không có thông tin đăng nhập bắt buộc, bạn có thể không truy cập được vào bất kỳ dữ liệu nào.

  1001 lý do mỗi doanh nghiệp cần có một website riêng cho mình

Deployment

Khi xử lý một website, những thay đổi nhỏ không bao giờ yêu cầu biên dịch lại và triển khai đầy đủ. Bạn chỉ cần cập nhật mã HTML và mọi thứ sẽ được cập nhật.

Trong khi với web app, bạn cần phải biên dịch lại và triển khai lại ứng dụng bất cứ khi nào bạn thực hiện thay đổi.

Phát triển một website là một quá trình tương đối đơn giản. Nhưng việc tạo một web app đòi hỏi kiến ​​thức sâu hơn, nhiều kinh nghiệm hơn và lập kế hoạch nhiều hơn. Do đó, nắm rõ sự khác biệt của chúng giúp bạn hiểu rõ mình cần làm gì và phát triển như thế nào.

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 các vị trí it jobs hấp dẫn trên TopDev

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

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

Video trong bài viết

Chúng ta có quy trình 3 bước để máy có thể học nhưng trước khi đi đến phần thuật toán, tôi muốn giới thiệu với các bạn một chút về môi trường chúng ta sẽ thực hành viết code Python.

Tham khảo: Jupyter Notebook, công cụ không thể thiếu khi học Python. Bài viết này coi như bạn đã có biết cách sử dụng Jupyter Notebook.

  Vẽ đồ thị trong Python với thư viện Matplotlib
  "Code dễ đọc" là như thế nào?

1. Markdown và LaTex trong Jupyter Notebook

Jupyter Notebook là công cụ thực hiện code Python, không những thế bạn có thể đưa vào văn bản, hình ảnh giúp cho các đoạn code dễ hiểu và có thể chia sẻ với mọi người.

Phần văn bản của Jupyter Notebook có thể đưa vào nội dung rất phong phú với các cú pháp Markdown và LaTex:

  • Markdown là một cú pháp sẽ được phân tích cú pháp thành HTML, nó có thể đưa vào tất các các phần tử của HTML, do đó Notebook của bạn sẽ không khác gì một trang web cả.
  • LaTex là công cụ đánh dấu và hiển thị cho các công thức toán học và khoa học. Bạn thử xem hai hàm số này, cái nào dễ nhìn hơn: y = x^2 + 2x + 1 và y=x2+2x+1y=x2+2x+1.

Trang web bạn đang xem All Laravel được chúng tôi xây dựng trên nền tảng OctoberCMS cũng đang sử dụng các công cụ như Markdown và LaTex để biên soạn nội dung các bài viết mà bạn đang xem.

1.1 Cú pháp Markdown

Có khá nhiều cú pháp trong Markdown nhưng tôi sẽ giới thiệu sơ qua một số cú pháp hay dùng nhất:

Tiêu đề: Trong HTML chúng ta có các thẻ tiêu đề từ H1 đến H6 thì trong Markdown, chúng ta thực hiện định dạng một câu thành tiêu đề bằng dấu # ở trước. Ví dụ:

# Đây là tiêu đề H1 
nó sẽ tương ứng với 
<h1>Đây là tiêu đề H1</h1>

Muốn có tiêu đề H2 chúng ta sử dụng hai dấu ##, H3 tương ứng với ###…

Định dạng văn bản: Một số định dạng phổ biến như viết đậm, viết nghiêng trong Markdown sẽ như sau:

**Đoạn này chữ đậm** 
nó sẽ tương ứng với 
<strong>Đoạn này chữ đậm</strong>

*Đoạn này chữ nghiêng*
nó sẽ tương ứng với 
<em>Đoạn này chữ đậm</em>

Danh sách: Có hai loại danh sách là danh sách có thứ tự với số ở đầu (ol) và danh sách không có thứ tự (ul). Trong Markdown các danh sách được viết khá dễ dàng:

* Python
* C#
* PHP

Tương đương với

<ul>
    <li>Python</li>
    <li>C#</li>
    <li>PHP</li>
</ul>

Kết quả thực tế như sau:

  • Python
  • C#
  • PHP

Tương tự với danh sách có thứ tự, chúng ta chỉ cần viết như khi đánh văn bản hay dùng:

1. Python
2. C#
3. PHP

Tương đương với

<ol>
    <li>Python</li>
    <li>C#</li>
    <li>PHP</li>
</ol>

Kết quả thực tế như sau:

  1. Python
  2. C#
  3. PHP

Có rất nhiều các cú pháp trong Markdown, bạn có thể tìm hiểu thêm trên mạng với từ khóa Markdown syntax, ở đây tôi chỉ giới thiệu để bạn hiểu được Markdown là gì? Bản chất Markdown là một ngôn ngữ đánh dấu trung gian, nó khá tiện dụng khi viết nội dung đặc biệt với các tài liệu khoa học. Các hệ thống hỗ trợ Markdown sẽ thực hiện theo thứ tự như sau:

Markdown -> HTML -> Hiển thị nội dung cho người dùng.

1.2 Cú pháp LaTex

LaTex nhận dạng nội dung bên trong một đoạn văn bản là công thức hay không thông qua thẻ $ và $$.

  • Với $, nội dung bên trong sẽ là biểu thức nằm trên cùng một dòng với văn bản ở ngoài.
  • Với $$ nội dung bên trong là biểu thức sẽ được trình bày ở giữa một dòng mới.

Ví dụ: Phương trình hàm parabol y=3x2+2x+1y=3×2+2x+1 là dạng cùng dòng (inline) với thẻ $ trong LaTex. Nhưng biểu thức sau đây lại sử dụng $$:

i=0ni2=(n2+n)(2n+1)6∑i=0ni2=(n2+n)(2n+1)6

Chỉ số trên và chỉ số dưới: sử dụng _ cho chỉ số dưới và ^ cho chỉ số trên. Ví dụ: $x^2$ sẽ có kết quả là x2x2, $n_i$ sẽ có kết quả là nini và kết hợp cả hai $\theta_0^{(i)}$ sẽ cho kết quả là θ(i)0θ0(i). Các biểu thức toán sẽ rất đẹp phải không bạn.

Tổng, tích phân: Với tổng chúng ta sử dụng \sum, tích phân là \int với các chỉ số trên và chỉ số dưới giống như ở phần trên. Ví dụ: $\sum_{i=0}^ni^2$ cho kết quả ni=0i2∑i=0ni2. Ví dụ khác về tích phân $$\int_0^{\frac{\pi}{4}}\sqrt{1-x^2}dx$$ cho kết quả

π401x2−−−−−√dx∫0π41−x2dx

Phân số: Phân số trong LaTex sử dụng cú pháp $\frac{a}{b}$, ví dụ $\frac{(n^2+n)(2n+1)}{6}$ cho kết quả (n2+n)(2n+1)6(n2+n)(2n+1)6.

Trên đây là một số cú pháp cơ bản khi biểu diễn các biểu thức toán học với LaTex, bạn có thể xem nhiều các công thức toán học khác có thể được biểu diễn bằng LaTex ở đây.

1.3 Đệ nhất lẩu Jupyter, Markdown và LaTex

Với sự kết hợp của Markdown và LaTex chúng ta có thể biểu diễn các thuật toán với các biểu thức toán học kết hợp với các nội dung diễn giải tuyệt vời. Không chỉ có vậy, Jupyter Notebook là một tài liệu có chứa cả các cell có code Python có thể thực thi được, bạn thấy đấy, giờ đây chúng ta chỉ cần 1 chỗ vừa có thể xem các diễn giải các công thức và dưới đó là các phần code thực hiện và xem các kết quả chương trình đưa ra. Có thể nói ĐỆ NHẤT LẨU JML (Jupyter-Markdown-LaTex) đã mang lại cho chúng ta những lồi nẩu cực cực cực … cực kỳ hấp dẫn.

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

2. Vẽ đồ thị trong Python

Các cụ nhà ta có câu:

Trăm nghe không bằng một thấy.

Cho thấy tầm quan trọng của việc biểu diễn dữ liệu bằng các biểu đồ, đồ thị. Trong phần này, chúng ta sẽ thực hiện vẽ đồ thị các hàm số trong Python, nó giúp cho các thuật toán lằng nhằng có thể được diễn tả bằng hình ảnh một cách dễ hiểu nhất.

Trong hệ sinh thái Python, có rất nhiều các thư viện bên thứ 3 được phát triển dưới dạng mã nguồn mở, rất phổ biến và cực hữu ích khi làm việc với Python. Trong phần này tôi giới thiệu với bạn hai thư viện được dùng khá nhiều trong Khóa học Machine Learning này đó là Numpy và Matplotlib.

  • Numpy: giúp thao tác với các mảng đa chiều, sinh dữ liệu và thực hiện các phép biến đổi dữ liệu dễ dàng hơn.
  • Matplotlib: thư viện giúp bạn mô phỏng dữ liệu thành các biểu đồ, đồ thị, thư viện không thể thiếu khi bạn thực hiện phân tích dữ liệu.

Nói thì nghe cao siêu vậy thôi, chúng ta cùng bắt tay vào một ví dụ vẽ đồ thị, bạn sẽ thấy các thư viện này rất dễ sử dụng. Trong bài trước, bạn đã nghe đến khái niệm về hàm chi phí hay hàm mất mát (từ giờ tôi sẽ chỉ dùng tên gọi Hàm chi phí), đó là cơ sở để tính toán các sai lệch khi đưa ra các giá trị khởi tạo trong bước 1 của Quy trình 3 bước trong Machine Learning. Chúng ta cần vẽ đồ thị của hàm chi phí để có thể tìm được các điểm cực tiểu mà tại đó là lời giải của thuật toán Grandient Descent.

2.1 Phương thức plot()

Giả sử chúng ta có một hàm chi phí y=x2+x+1y=x2+x+1, chúng ta sẽ vẽ hàm chi phí này để có thể tìm hiểu về điểm cực tiểu, nơi mà chi phí thấp nhất (Chi phí – cost, ở đây không có nghĩa là mất mát về tiền, chi phí ở đây với ý nghĩa là …). Bắt đầu thôi:

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

import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline

Hai dòng đầu tiên là import các thư viện matplotlib và numpy, dòng %matplotlib inline là một câu lệnh của Jupyter Notebook, nó giúp vẽ các đồ thị bên trong các cell. Tiếp đó, để vẽ được hàm y=x2+x+1y=x2+x+1 chúng ta sẽ sử dụng phương thức plot() của pyplot là một module trong matplotlib mà ta đã đặt tên ngắn gọn là plt.

Phương thức plot() giúp vẽ một danh sách các điểm thành một đồ thị, phương thức này có nhiều tham số nhưng chúng ta chỉ quan tâm đến tham số x và y là hai danh sách (Python List) với giá trị là tọa độ x và y.

Ví dụ:

x_list = [0,2,7]
y_list = [1,8,9]

plt.plot(x_list, y_list)
plt.show()

Kết quả khi thực thi chúng ta có đồ thị như sau:

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

Chú ý, phương thức plot() trả về một đối tượng Python do đó để thực sự vẽ ra đồ thị, chúng ta cần gọi phương thức show().

2.2 Tạo dữ liệu mẫu với numpy

Bạn thấy đấy, chúng ta có 3 điểm là (0,1) (2,8) và (7,9), ở đây chúng ta đưa hết giá trị trên tọa độ x vào biến x_list và trên tọa độ y vào y_list. plot() đã vẽ ra ba điểm này và giữa hai điểm liên tiếp nó vẽ một đường thẳng. Ok, vậy chúng ta có thể vẽ phương trình y=x2+x+1y=x2+x+1 như thế nào? Chẳng lẽ chúng ta phải tự tạo ra dữ liệu là danh sách các tọa độ x, y này, như thế thì thật mất nhiều công sức, chưa kể là giữa hai điểm ở đây là một đường thẳng, như vậy đồ thị vẽ ra cũng không trơn tru vì chỉ là một đường nối các điểm với nhau.

Không có vấn đề gì, chúng ta vẫn còn Numpy, bạn nhớ chứ, chúng ta đã import thư viện này vào nhưng chưa sử dụng đến. Trong numpy có phương thức linspace() cho phép tạo ra một mảng số với số lượng phần tử cho trước và nằm trong một phạm vi cho trước.

x_1 = np.linspace(start=-3, stop=3, num=100)

Dòng code này sẽ tạo ra một mảng gồm 100 phần tử chạy trong khoảng [-3,3] với giá trị các phần tử cách đều nhau.

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

2.3 Vẽ đồ thị hàm parabol

Ok, chúng ta đã tạo ra được dữ liệu mẫu cho trục x trong khoảng từ [-3, 3], giờ là lúc cần định nghĩa hàm y=x2+x+1y=x2+x+1 trong Python và tính ra các giá trị cho trục y tương ứng với các giá trị trục x.

def f(x):
    return x**2 + x + 1
y_1 = f(x_1)

Kết quả ta có biến y_1 là một mảng các giá trị hàm số y=x2+x+1y=x2+x+1 tương ứng với x tại các giá trị trong mảng x_1.

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

Ok, dữ liệu cho các trục x, y đã chuẩn bị xong, giờ chúng ta sẽ vẽ đồ thị y=x2+x+1y=x2+x+1.

plt.plot(x_1, y_1)
plt.show()

Kết quả chúng ta có đồ thị y=x2+x+1y=x2+x+1 như hình dưới đây:

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

Đồ thị đã rất đẹp, nhưng chúng ta vẫn cần định dạng lại chút, ví dụ thêm nhãn cho các trục tọa độ, giới hạn tọa độ hiển thị:

plt.xlim(-3, 3)
plt.ylim(0, 8)
plt.xlabel('X', fontsize=16)
plt.ylabel('f(x)', fontsize=16)
plt.plot(x_1, y_1)
plt.show()

Trong đoạn code trên, xlim() và ylim() để giới hạn vùng tọa độ sẽ hiển thị trên trục x và y, xlabel() và ylabel() để gán nhãn cho các trục tọa độ, kết quả chúng ta được đồ thị mới như sau:

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

2.4 Vài lời tâm sự

Đồ thị hàm parabol y=x2+x+1y=x2+x+1 rất đẹp được vẽ lên từ 100 điểm nối với nhau. Chúng ta thấy đường parabol rất trơn tru vì trong một khoảng ngắn có tới 100 điểm thì các điểm gần như sát với nhau do đó chúng ta không cảm nhận được những đoạn thẳng nối từng hai điểm liên tiếp.

Bạn sẽ đặt câu hỏi, tại sao tôi chọn khoảng [-3, 3] để vẽ đồ thị, thực ra khi vẽ chúng ta sẽ phải dò dẫm chút, đưa ra một khoảng bất kỳ và chỉnh dần về khoảng sao cho đồ thị có những điểm đặc biệt nằm chọn trong đó. Khi vẽ bạn cũng chọn số điểm vừa phải, nếu thấy chưa trơn tru thì tăng dần lên tránh việc máy tính phải tính toán nhiều, đó là thói quen cần thiết của những người làm về khoa học dữ liệu.

Một thực tế nữa là khi làm việc với data science, chúng ta chỉ luôn tính xấp xỉ chứ không thể có những con số tuyệt đối như khi học toán học. Những con số xấp xỉ đã có một giá trị rất cao mặc dù nếu khi thi toán, giải kết quả xấp xỉ là bạn bị điểm 0 liền. Ví dụ, khi tính toán một phương án đầu tư, chỉ cần cho kết quả cỡ 60-70% là đã coi như 100% chứ không như trong toán, lúc nào cũng phải 1+1=21+1=2.

3. Bài tập

Nhân tiện về chủ đề vẽ đồ thị và khảo sát hàm số, một chủ đề rất thích hợp với chương trình toán trong Phổ thông trung học. Mình đưa ra một số bài tập ở đây để mọi người vẽ và hồi tưởng về một thời mài đít quần trên ghế nhà trường :D.

Bài tập: Soạn một notebook trên Jupyter bao gồm cả đề bài, vẽ đồ thị với Python.

Cho đồ thị hàm số y=14x332x2+5y=14×3−32×2+5

  1. Khảo sát sự biến thiên, vẽ đồ thị đã cho.
  2. Tìm giá trị của m để phương trình x36x2+m=0x3−6×2+m=0 có 3 nghiệm phân biệt.

Hehe, giải kiểu gì cũng được nhé, miễn là ra kết quả, kể cả kết quả gần đúng. Lời giải có trong bài tiếp theo nhé.

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

Sử dụng Dead Letter Exchange trong RabbitMQ

Sử dụng Dead Letter Exchange trong RabbitMQ

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

Dead Letter Exchange trong RabbitMQ

Dead Letter Exchange là gì?

Dead Letter là một tin nhắn không thể gửi đến người nhận. Dead Letter Queue (DLQ), là hàng đợi chứa tin nhắn chưa được gửi, không thể được gửi đến đích của chúng vì lý do này hay lý do khác.

Trong hàng đợi tin nhắn, DLQ là một dịch vụ được cài đặt để lưu trữ các tin nhắn đáp ứng một hoặc nhiều sự kiện sau:

  • Tin nhắn bị từ chối (rejected) bởi một Queue Exchange.
  • Message hết hạn (expire) do Time to live (TTL).
  • Vượt quá giới hạn chiều dài hàng đợi (length limit).
  Giới thiệu CloudAMQP – Một RabbitMQ server trên Cloud
  Sử dụng binding Exchange to Exchange trong RabbitMQ

Dead Letter Exchange là một Exchange bình thường, có thể là một trong 4 loại Exchange (Direct, Fanout, Topic, Headers).

Điều gì xảy ra với Dead Letter Message?

  • Gửi tới một Dead Letter Exchange.
  • Thêm một số thông tin vào header của Message trước khi gửi đến Dead Letter Exchange.

Cấu hình Dead Letter Exchange sử dụng Optional Queue Arguments

Để gán một Dead Letter Exchange cho một Queue sử dụng agruments x-dead-letter-exchange khi định nghĩa Queue.

channel.exchangeDeclare("gpcoder.exchange.name", "direct");

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-dead-letter-exchange", "gpcoder.exchange.name");
channel.queueDeclare("GPCoderQueue", false, false, false, args);

Đoạn code trên đơn giản tạo một Exchange mới gọi là gpcoder.exchange.name và Exchange mới này là Dead Letter Exchange cho hàng đợi mới được tạo. Lưu ý rằng Exchange  không phải được khai báo khi hàng đợi được khai báo, nhưng nó phải tồn tại tại thời điểm các Message được Dead Letter, nếu không thì các Message sẽ bị hủy bỏ.

Theo mặc định RabbitMQ sẽ lấy khoá định tuyến từ Message ban đầu được gửi đến Exchange. Chúng ta cũng có thể chỉ định một khóa định tuyến sẽ được sử dụng khi Dead Letter Message nếu muốn.

args.put("x-dead-letter-routing-key", "some-routing-key");

Routing Dead-Lettered Message

Dead-lettered message được định tuyến tới Dead Letter Exchange theo thứ tự ưu tiên sau:

  • Theo khoá định tuyến được chỉ định cho hàng đợi Dead Letter Message được chỉ định.
  • Theo khoá định tuyến ban đầu Message được publish.

Ví dụ: Nếu một Message ban đầu được publish đến Exchange với khoá định tuyến foo. Sau đó Message này bị reject và nó trở thành một Dead Letter Message. Và nó được publish đến Dead Letter Exchange với khoá định tuyến foo. Giả sử chúng ta đã chỉ định một khóa định tuyến sẽ được sử dụng khi Dead Letter Message là bar, lúc này Message được publish đến Dead Letter Exchange với khoá định tuyến bar.

Dead-lettered message được re-published với tính năng publisher confirm được bật mặc định để đảm bảo rằng Dead-letter queue phải gửi xác nhận Message (ack) đã được lưu trữ trước khi nó bị xoá ở Queue gốc.

Message bị thay đổi như thế nào khi chuyển sang Dead-Lettered Message?

Header bị thay đổi:

  • Exchange name bị thay thế bởi Dead-letter exchange name.
  • Routing key có thể bị bởi một Routing key khác.
  • Nếu điều trên xảy ra, thì CC và BCC header cũng sẽ bị remove.

Thêm header x-death, với một mảng các giá trị:

  • queue: tên của Queue mà Message được publish trước khi nó trở thành Dead-Lettered Message.
  • reason: lý do xảy ra Dead-Lettered Message. Có thể là: rejected, expired, maxlen.
  • time: thời gian Message bị dead lettered.
  • exchange: tên Exchange mà Message được publish, nó có thể là dead letter exchange nếu Message bị dead lettered nhiều lần.
  • routing-keys: là routing key (bao gồm CC keys nhưng không bao gồm BCC keys) của Message được publish.
  • count: số lần mà Message bị dead-lettered trong Queue này vì lý do này.
  • original-expiration: nếu Message bị dead-lettered vì lý do TTL, nào là giá trị của thuộc tính expiration ban đầu của Message. Thuộc tính expiration sẽ bị remove từ dead-lettering message để ngăn việc expiring lần nữa trong Queue mà nó được định tuyến đến.

3 header được thêm cho mỗi dead-lettering event đầu tiên:

  • x-first-death-reason
  • x-first-death-queue
  • x-first-death-exchange

Chúng có cùng các giá trị như reason, queue, và exchange của event xảy ra Dead-Lettered ban đầu. Sau khi thêm, các header này không bao giờ được sửa đổi.

Lưu ý rằng: mảng giá trị x-death được sắp xếp gần đây nhất trước, do đó, Dead-Lettered gần đây nhất sẽ được ghi lại trong mục đầu tiên.

Ví dụ sử dụng Dead Letter Exchange trong RabbitMQ

Trong ví dụ này tôi sử dụng Dead Letter Exchange để mô phỏng trường hợp Retry xử lý sau mỗi 300 millisecond nếu ngay lần nhận Message đó không thể xử lý thành công.

Sử dụng Dead Letter Exchange trong RabbitMQ

  1. Tạo một WorkQueue và bind đến WorkExchange.
  2. Tạo một RetryQueue và bind đến RetryExchange.
    • Gán agruments: x-dead-letter-exchange đến WorkExchange
    • Gán agruments: x-message-ttl là 300 ms.
  3. Producer publish một Message đến WorkExchange. Sau đó, WorkExchange sẽ chuyển Message đến WorkQueue.
  4. Consumer nhận Message từ WorkQueue và cố gắng xử lý nó.
  5. Trường hợp xử lý thất bại, Consumer sẽ publish Message đó đến RetryExchange. Sau đó, RetryExchange sẽ chuyển Message đến RetryQueue.
  6. Message sẽ lưu tại RetryQueue trong 300 ms.
  7. Khi Message bị expire, nó sẽ được chuyển đến WorkExchange và được chuyển đến WorkQueue.
  8. Khi đó Consumer có thể nhận lại Message từ WorkQueue và xử lý lại.

Hãy xem code implement:

package com.gpcoder.deadletterexchange;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

public class App {

// Exchange
private static final String WORK_EXCHANGE_NAME = "GPcoder.WorkExchange";
private static final String RETRY_EXCHANGE_NAME = "GPcoder.RetryExchange";

// Queue
private static final String WORK_QUEUE_NAME = "WorkQueue";
private static final String RETRY_QUEUE_NAME = "RetryQueue";

private static final int RETRY_DELAY = 300; // in ms

private static Channel channel;
private static int RETRY_COUNT = 0;

public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();

channel = connection.createChannel();

// Create the WorkQueue
channel.exchangeDeclare(WORK_EXCHANGE_NAME, BuiltinExchangeType.DIRECT, true);
channel.queueDeclare(WORK_QUEUE_NAME, true, false, false, null);
channel.queueBind(WORK_QUEUE_NAME, WORK_EXCHANGE_NAME, "", null);

// Create the RetryQueue
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-dead-letter-exchange", WORK_EXCHANGE_NAME);
arguments.put("x-message-ttl", RETRY_DELAY);
channel.exchangeDeclare(RETRY_EXCHANGE_NAME, BuiltinExchangeType.DIRECT, true);
channel.queueDeclare(RETRY_QUEUE_NAME, true, false, false, arguments);
channel.queueBind(RETRY_QUEUE_NAME, RETRY_EXCHANGE_NAME, "", null);

// basicPublish - ( exchange, routingKey, basicProperties, body)
String message = "GPCoder Message";
System.out.println("[" + LocalDateTime.now() + "] [Work] [Send]: " + message);
channel.basicPublish(WORK_EXCHANGE_NAME, "", null, message.getBytes());

consumer(WORK_QUEUE_NAME);
}

private static void consumer(String queueName) throws IOException {
// basicConsume - ( queue, autoAck, deliverCallback, cancelCallback)
DeliverCallback deliverCallback = (consumerTag, message) -> {
String content = new String(message.getBody());
System.out.println("[" + LocalDateTime.now() + "] [Received] [" + queueName + "]: " + content);
System.out.println("");
if (RETRY_COUNT < 5) { publishToRetryExchange(content); RETRY_COUNT++; } else { RETRY_COUNT = 0; } }; CancelCallback cancelCallback = consumerTag -> System.out.println(consumerTag);
channel.basicConsume(queueName, true, deliverCallback, cancelCallback);
}

// Publish to RetryQueue on failure
private static void publishToRetryExchange(String message) throws IOException {
System.out.println("[" + LocalDateTime.now() + "] [Retry" + RETRY_COUNT + "] [Re-Publish]: " + message);
channel.basicPublish(RETRY_EXCHANGE_NAME, "", null, message.getBytes());
}
}

Output chương trình:

[2020-05-03T22:57:03.614] [Work] [Send]: GPCoder Message
[2020-05-03T22:57:03.620] [Received] [WorkQueue]: GPCoder Message

[2020-05-03T22:57:03.620] [Retry0] [Re-Publish]: GPCoder Message
[2020-05-03T22:57:03.922] [Received] [WorkQueue]: GPCoder Message

[2020-05-03T22:57:03.922] [Retry1] [Re-Publish]: GPCoder Message
[2020-05-03T22:57:04.224] [Received] [WorkQueue]: GPCoder Message

[2020-05-03T22:57:04.224] [Retry2] [Re-Publish]: GPCoder Message
[2020-05-03T22:57:04.526] [Received] [WorkQueue]: GPCoder Message

[2020-05-03T22:57:04.526] [Retry3] [Re-Publish]: GPCoder Message
[2020-05-03T22:57:04.828] [Received] [WorkQueue]: GPCoder Message

[2020-05-03T22:57:04.828] [Retry4] [Re-Publish]: GPCoder Message
[2020-05-03T22:57:05.131] [Received] [WorkQueue]: GPCoder Message

Như bạn thấy, Message được tự động chuyển từ WorkQueue sang RetryQueue sau mỗi 300 ms nhờ vào Dead Letter Message. Đây là ví dụ cho trường hợp một Message hết hạn (expire) do Time to live (TTL).

Tương tự các bạn có thể set agruments là agruments.put(“x-max-length”, 10) để test trường hợp số lượng Message trong Queue vượt quá giới hạn chiều dài hàng đợi (length limit).

Tài liệu tham khảo:

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

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

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

Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins

Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins

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

Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins.

Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins.

Truy cập vào trang quản lý Jenkins trên trình duyệt (ví dụ của mình là http://localhost:8080)

  Hướng dẫn build java project, maven project trên Jenkins
  Hướng dẫn cấu hình JDK (Java) cho Jenkins

Trên thanh menu bên trái chọn Manage Jenkins > Manage Plugins

Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins

Chọn tab Available để tìm plugin cần cài mới, sau đó gõ tên plugin cần cài.

Trong ví dụ này mình thực hiện cài plugin Maven để thực hiện build các project Maven.

Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins

Jenkins sẽ cài Maven plugin và các module liên quan.

Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins

Sau khi cài đặt xong plugin maven, chúng ta có thể kiểm tra lại bằng cách tạo 1 item maven project mới:

Chọn New Item

Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins

Bạn sẽ thấy lựa chọn cho Maven project

Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins

Okay, Done!

References: https://plugins.jenkins.io/maven-plugin/

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

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

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

Load Balancers I – Stateful App Servers và những điều nên biết

Load Balancers I – Stateful App Servers và những điều nên biết

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

Ở bài viết trước, ta đã phân tích về Load Balancer và bài toán “Server nào sẽ handle request nào?“, ở bài viết này, ta sẽ bàn tiếp về một khía cạnh khác của Load Balancer là Stateful App Servers.

Qua bài viết, phần nào ta đã hiểu được rằng tại sao App Servers không hề quan tâm tới User State. Tuy nhiên, với những Servers được thiết kế Stateful App Servers, bằng cách nào ta có thể áp dụng Load Balancer thành công?.

  Hướng dẫn sử dụng ReactJS Props và State
  Cân bằng tải (Load Balancing)

Tất cả sẽ có ngay sau đây. Bắt đầu ngay thôi nào!

1. Stateful App Servers

Bản thân nó luôn đối đãi như nhau với các request từ phía client. Công bằng và văn minh vcl.

Sự công bằng này đảm bảo cho mô hình Load Balancer hoạt động hiệu quả, server nào trống sẽ được phân công làm nhiệm vụ ngay. Nếu một server quan tâm tới user state, nó sẽ bị kẹt không biết tới khi nào (ví dụ như một chị đi shopping 3 tiếng mới thêm một món vào giỏ hàng). Server nếu hold cứ hold mãi không biết tới lúc nào.

Bản thân kiến trúc Load Balancer cũng cần giải pháp để kết nối những công việc còn “chưa xong” ở phía client. Kiến trúc này thường được biết tới như Stateful App Servers. Lúc này mỗi machine trong kiến trúc balancer sẽ giữ một số thông tin phía client. Bản thân những thông tin này cho phép Server có thể tùy ý tracking client đã làm việc với server nào

Những yếu tố có thể giúp việc stateful dễ dàng hơn:

  • IP Address
  • Session Id (Include SSL)
  • Cookies (ở Kieblog đã có một bài về Cookies rồi)

2. Persistence Layer

Với những application đã được thiết kế theo hướng Stateful App Servers thì điều quan tâm tới state hiện tại của user để có cách handle hợp lý. Trường hợp có Load Balancer, bằng cách nào ta có thể đáp ứng được “stateful”, mà vẫn đảm bảo “load balancer” thành công.

2.1 IP Address

IP address là một cách khả phố biến để phán định xem server nào sẽ tiếp tục xử lý request từ phía client. Tracking IP sẽ được thực hiện ngay từ lần đầu tiên User request tới server.

Ví dụ client A send request tới Server B. Ở các request tiếp theo, khi server phát hiện địa chỉ IP nó đã handle trước đó. Sử dụng IP Address thường đi kèm thêm lớp Network Load Balancer, có trách nhiệm phân giải IP, block các IP đến từ khu vực không cho phép thiết lập trước đó.

Load Balancers I – Stateful App Servers và những điều nên biết
Kiến trúc Application Load Balancer với IP Address. Nguồn ảnh / Source: aws.amazon.com

Sử dụng IP Address cũng là giải pháp thường biết tới với tên “Layer 4”. Bản thân Layer 4 ở đây là Transport Layer trong kiến trúc 7 tầng của mạng máy tính (7 layers OSI Model). Sử dụng IP Address cũng là biện pháp khá phổ biến cho các Stateful App Servers

2.2 Web Application

NgoàimLayer 4, ta cũng có thể sử dụng một số kỹ thuật thường được sử dụng ở phía Application như:

  • Session Id
  • Session Id SSL
  • Cookies

để phán định server sẽ handle request còn dang dở. Session và Cookies từ đâu đã là thành phần không thể thiếu của Stateful App Servers. Tuy nhiên để handle session trong kiến trúc Load Balancer, ta cần biết tới một khái niệm mới là Sticky Session.

Load Balancers I – Stateful App Servers và những điều nên biết
Với Session stickiness, request được điều phối đi đúng server để tiếp tục handle

Session stickiness, a.k.a., session persistence, is a process in which a load balancer creates an affinity between a client and a specific network server for the duration of a session, (i.e., the time a specific IP spends on a website). Using sticky sessions can help improve user experience and optimize network resource usage.

Session Stickiness là quá trình load balancer khởi tạo mối quan hệ giữa client và server trong thời gian của một phiên (session). Sử dụng sticky session cải thiện performance và user experienced, tối ưu tài nguyên server được sử dụng.

Dựa vào session id được cấp phát, Session stickiness sẽ lựa chọn đúng Server đã handle các request còn dang dở. Ở các request tiếp theo, nó cũng điều động các request đi đúng hướng, trỏ về đúng server mục tiêu.

3. Tham khảo

Thank for read my post – Wish you have best of luck – 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

Vue 3 có gì mới? – What’s new from Vue 3?

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

Bản thân tôi rất yêu thích Vuejs, không ngạc nhiên khi luôn trông chờ, tìm hiểu xem Vue 3 có gì mới?. Quả nhiên Vue 3 không làm tôi thất vọng.

Với những cải tiến đáng giá từ performance cho tới API,điển hình là sự ra đời của Composition API thay cho Options API ở Vue 2.

  3 phút làm quen với Vue.js
  API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth

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

1. Vue 3 có gì mới?

Không những thay đổi lớn về performance, không thể chê được vào đâu khi bổ sung hàng loạt tính năng mới, nhưng kích thước của Vue 3 cũng chỉ bằng Vue 2 (12KB).

Cải tiến đáng giá được nhắc tới trong bài viết này bao gồm:

  • Composition API
  • Multiple root elements
  • Suspense
  • Multiple v-models

Sơ bộ anh em có thể xem qua video này để nắm bắt thêm Vue 3 có gì mới nha!.

2. Composition API

Kể từ khi Vue 2 nổi lên như là ngôi sáng sáng giữa bầu trời, rất nhiều dự án lớn đã sử dụng Vue. Một khi dự án lớn (cỡ vài trăm component), vấn đề tái sử dụng (reusable code) và scability (mở rộng) trở nên quan trọng hơn bao giờ hết.

Ok, Composition API là câu trả lời đầu tiên cho Vue 3 có gì mới?. Vậy Composition API là gì?

Composition API as a reactive API coupled with the ability to register lifecycle hooks using globally imported functions.

Composition API là thành phần của Reactive API, với khả năng đăng kí các lifecycle hooks sử dụng các import global cho functions.

Quất thêm cái nữa khó hiểu hơn:

The main point is that the Composition API provides a different way to manage reactivity at all points in an application, without compromising organization and readability.

Điểm mấu chốt mà Composition API cung cấp là một “cách khác” để quản lý reactivity tất cả các điểm trong application, mà không ảnh hưởng tới tổ chức code và khả năng đọc hiểu.

Vãi nồi khó hiểu, đọc vậy mông lung như một trò đùa.

2.1 Dễ hiểu hơn được không?

Thực chất Composition API cho phép ta đóng gói một loạt các method trong life cycle. Ví dụ, trước kia ở Vue 2, created tính toán, chuẩn bị dữ liệu cho object A, watch theo dõi object A khi thay đổi, … Vô vàn thứ cần làm với A. Source code trở nên mất kiểm soát, khó hiểu nếu bạn không phải là người viết ra component đó.

Vue 3 có gì mới? – What’s new from Vue 3?
Các vùng có màu khác nhau thì độc lập với nhau. Nội đủ hết method trong life cycle cũng đã là nhiều với component.

Chính bởi khi có quá nhiều Component và nhiều logic phức tạp. Khó maintain và scale, nên ta cần tới Composition API.

Vue 3 có gì mới? – What’s new from Vue 3?
Với Composition API, tất cả các đoạn code xử lý liên quan tới Object A có thể được gom lại duy nhất ở setup.

Tuy nhiên, đừng quên là Vue 3 vẫn hỗ trợ Options API, nên nếu muốn, không có vấn đề gì khi cứ viết các method theo Life Cycle của Vue nha. Với Options API, cùng lướt qua component vô cùng đơn giản với Options API.

Vue.js Component

<template>
<div id="app">
<p>You clicked {{ numOfClicks }} times.</p>
<button @click="handleClick()">Click me to increment!</button>
</div>
</template>

<script>
export default {
name: "App",
data() {
return {
numOfClicks: 0,
};
},
created() {},
methods: {
handleClick: function () {
this.numOfClicks++;
},
},
};
</script>

<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

Ví dụ sử dụng Composition API với setup()

Vue.js Component

<template>
<div id="app">
<p>You clicked {{ numOfClicks }} times.</p>
<button @click="handleClick()">Click me to increment!</button>
</div>
</template>

<script>
import { ref } from "vue";

export default {
name: "App",
setup() {
let numOfClicks = ref(0);

function handleClick() {
numOfClicks.value++;
}

return {
handleClick,
numOfClicks,
};
},
};
</script>

<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

Tuy nhiên, sử dụng Composition API cần lưu ý:

Because the component instance is not yet created when setup is executed, there is no this inside a setup option. This means, with the exception of props, you won’t be able to access any properties declared in the component – local statecomputed properties or methods.

Bởi vì Component instance chưa hề được tạo ra khi method setup được thực thi, nên this chắc chắn không work. Ngoại trừ cái thằng props ra, tuyệt nhiên ta không thể access tới bất cứ properties nào khai báo trong component, local state, computed properties hoặc methods cũng không là ngoại lệ.

3. Multiple root elements

Multi root elements ở đây được hiểu là component không cần phải thuộc về duy nhất một node cha nữa. Câu trả lời thứ 2 cho Vue 3 có cái gì mới xem ra dễ hiểu hơn nhiều!.

Bai bai cái lỗi khó chịu quỷ tha ma bắt này. Bắt đầu từ Vue 3, một component có thể có nhiều hơn một node cha.

Vue 3 có gì mới? – What’s new from Vue 3?

Vue.js Component

<template>
<div class="counter">
<p> Count: {{ count }} </p>
<button @click="increment"> Increment </button>
<button @click="decrement"> Decrement</button>
</div>
</template>

Tha hồ, mặc sức mà tạo node con trong template với Vue 3. Việc bỏ đi một node cha cũng bớt phiền phức khi làm việc với css. Trước đây 2 tag p nếu bắt buộc chung nhau 1 div phải viết css parent child mệt mỏi. Tuy nhiên, giờ mạnh ai người đó xài css của mình.

Vue.js Component

<template>
<p> Count: {{ count }} </p>
<button @click="increment"> Increment </button>
<button @click="decrement"> Decrement</button>
</template>

4. Suspense

Suspense là cái tiến mới ở Vue 3 liên quan tới Asynchorous (Bất đồng bộ). Trước đây khi làm việc với API, do việc xử lý call API là bất đồng bộ, nên cần chờ tới khi có response trả về mới thực hiện render.

Thông thường sử dụng v-if, tuy nhiên với Suspense, mọi việc trở nên đơn giản hơn nhiều.

Suspense is a special component that renders a fallback content instead of your component until a condition is met.

Suspense là component dặc biệt render nội dung dự phòng thay vì component chính (lúc này chưa có data), cho tới khi condition (điều kiện để render component) được xác lập.

Sử dụng Suspense cũng khá đơn giản, chỉ cần lưu ý tới 2 từ khóa default và fallback. Cùng xem xét ví dụ sau:

Vue.js Component

<template>
<Suspense>
// Sau khi đã có response từ API, nội dung template này sẽ render sau.
<template #default>
<div v-for="item in articleList" :key="item.id">
<article>
<h2>{{ item.title }}</h2>
<p>{{ item.body }}</p>
</article>
</div>
</template>
// Trước khi có data từ API, nội dung trong template này sẽ tải trước
<template #fallback>
Articles loading...
</template>
</Suspense>
</template>
<script>
import axios from 'axios'
export default {
async setup() {
let articleList = await axios
.get('https://jsonplaceholder.typicode.com/posts')
.then(response => {
console.log(response)
return response.data
})
return {
articleList
}
}
}
</script>

5. Multiple V-models

Làm việc với Vue 2 chắc chắn đã biết tới v-models. V-models là two way binding. Dữ liệu binding 2 chiều, thường được sử dụng với form trên component.

Hữu dụng là thế, tuy nhiên Vue 2 chỉ cho phép một component có duy nhất một v-models. Vue 3 thì khác, cho phép không giới hạn số lượng v-model trong component.

Vue.js Component

<template>
<Suspense>
// Sau khi đã có response từ API, nội dung template này sẽ render sau.
<template #default>
<div v-for="item in articleList" :key="item.id">
<article>
<h2>{{ item.title }}</h2>
<p>{{ item.body }}</p>
</article>
</div>
</template>
// Trước khi có data từ API, nội dung trong template này sẽ tải trước
<template #fallback>
Articles loading...
</template>
</Suspense>
</template>
<script>
import axios from 'axios'
export default {
async setup() {
let articleList = await axios
.get('https://jsonplaceholder.typicode.com/posts')
.then(response => {
console.log(response)
return response.data
})
return {
articleList
}
}
}
</script>

6. Tham khảo

Thank for read the article – Have a nice weekend – 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

Gitlab CI

Gitlab CI

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

Đến thời điểm hiện nay, tôi thường yêu cầu các dự án của mình phải có CI. Nếu viết bằng script như nodejs thì CI sẽ có nhiệm vụ check syntax, để các thành viên trong nhóm cùng một kiểu viết giống nhau, và chạy các mức test khác nhau như unit test, CDC test.

Điểu tuyệt vời của gitlab là nó đi kèm với bộ CI miễn phí cho cả dự án private (yay). Blog này sẽ trình bày chiến lược để thiết lập ENV test trên Gitlab CI để build docker image, và upload nó lên gitlab registry.

  CI/CD là gì? Triển khai quy trình CI/CD với Gitlab
  34 sản phẩm phần mềm Social Networking tốt nhất

Gitlab CI

Gitlab runner

Là nơi chương trình test của bạn sẽ được chạy. Bạn có thể có một PC riêng biệt cho việc build và test. Gitlab cung cấp một chương trình khá tiện https://gitlab.com/gitlab-org/gitlab-ci-multi-runner để thiết lập runner cục bộ. Cá nhân tôi chỉ sử dụng multi runner này khi chương trình cần tài nguyên lớn.

Phần lớn thời gian tôi sử dụng shared runner https://about.gitlab.com/gitlab-com/settings/#shared-runners. Xin cảm ơn sự tử tế của Digital Ocean khi cho mỗi build một tài nguyên 4GB chạy trong mỗi máy ảo riêng biệt.

Shared runner chạy trên docker, nên có thể khai báo các docker có sẵn khá tiện (yay).

.gitlab-ci.yml

Là file cấu hình cho gitlab CI. Dưới đây là một ví dụ trong đó khai báo một trạng thái của test pipeline là unit test. Phần sau dựa trên giả thuyết tôi đang xây dựng một web app với nodejs, và chạy unit test với npm run test.

image: node:boron-alpine

stages:
 - unit_test

unit_test_job:
 stage: unit_test
 script:
 - npm install
 - npm run test

Với mỗi git push lên CI được trigger. CI sẽ pull về docker image node:boron-alpine giống với docker chạy trong staging và production environment của web app này. Stages khai báo các bước của CI. Trong trường hợp này, tôi chỉ có một bước duy nhất là unit test khai báo trong unit_test_job.

Gitlab CI

Nhưng tôi tin vào 12factor, và tôi muốn có quá trình build trước. CI hay staging hay production sẽ khác nhau ở ENV truyền vào docker như trình bày ở https://12factor.net/build-release-run. Tôi sẽ tạo một job để tạo artifact, và chạy test trên artifact này.

image: docker:1.12
services:
 - docker:dind

stages:
 - build

variables: 
 CONTAINER_TEST_IMAGE: registry.gitlab.com/company/project:$CI_BUILD_REF_NAME
before_script:
 - docker info
build_image_job:
 stage: build
 script:
 - docker build -t $CONTAINER_TEST_IMAGE .
 - docker run $CONTAINER_TEST_IMAGE npm run test

Setup này sử dụng docker in docker (dind)  để build docker image trong một docker (nơi CI đang chạy). Đều này đạt được do shared runner chạy với privileged enable.

Như vậy lúc này CI sẽ tạo một docker có tên biến CONTAINER_TEST_IMAGE , và chạy test trong image này.

Tôi muốn tiến thêm một bước nữa, pipeline bao gồm: build, test, và release. Quá trình release xảy ra khi tôi tag git tag -a version, nó sẽ tạo ra tag latest và upload lên gitlab registry.

Khoa, gitlab registry? Đúng vậy, gitlab cho phép bạn lưu các image lên host của họ. Bạn sẽ có CI, và registry (miễn phí).

image: docker:1.12

services:
- docker:dind

stages:
- build
- test
- release
- deploy

variables:
 CONTAINER_TEST_IMAGE: registry.gitlab.com/company/project:$CI_BUILD_REF_NAME
 CONTAINER_RELEASE_IMAGE: registry.gitlab.com/company/project:latest

before_script:
 - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com

build:
 stage: build
 script:
 - docker build --pull -t $CONTAINER_TEST_IMAGE .
 - docker push $CONTAINER_TEST_IMAGE

unit_test:
 stage: test
 script:
 - docker pull $CONTAINER_TEST_IMAGE
 - docker run $CONTAINER_TEST_IMAGE npm run unit_test

cdc_test:
 stage: test
 script:
 - docker pull $CONTAINER_TEST_IMAGE
 - docker run $CONTAINER_TEST_IMAGE npm run cdc_test

release-image:
 stage: release
 script:
 - docker pull $CONTAINER_TEST_IMAGE
 - docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE
 - docker push $CONTAINER_RELEASE_IMAGE
 only:
 - tags
 - triggers

Gitlab rất hào phóng khi cung cấp đầy đủ các công cụ và dịch vụ để bạn có thể xây dựng một quá trình CI khá hoàn chính, từ việc chạy các test đến việc lưu trữ các image của bạn.

Hy vọng bạn sẽ tìm thấy sự hữu dụng trong ecosystem của gitlab.

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

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

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

Biết Python – quen ngay Julia

Biết Python - quen ngay Julia

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

Julia là ngôn ngữ lập trình mới, trông rất giống code Python, chạy nhanh hơn Python3 ít nhất 2 lần và có nhiều tính năng hấp dẫn. Bạn không cần phải từ bỏ Python hay ngôn ngữ XYZ để học Julia, Julia chỉ đơn giản là một bông hoa đẹp mà ai thích… thì múc.

Julia là ngôn ngữ lập trình “làm gì cũng được”, nhưng được tập trung vào lĩnh vực tính toán khoa học và muốn thế chỗ Python (nhưng đường còn dài, và còn nhiều hơn chông gai).

Cài đặt

Xem https://docs.julialang.org/en/v1/

Tại thời điểm viết bài (2019 tháng 4), Julia ở bản 1.1.0 – đã ổn định hơn trước rất nhiều, ít bug hơn, chạy nhanh hơn.

Từ Python ngó sang

Julia trông rất giống Python, cách dùng các học, cách code cũng tương tự, nên nếu biết Python thì việc viết được code để làm công việc thường ngày (của 1 DevOps) chỉ trong vòng vài tiếng.

REPL

Gõ lệnh trực tiếp bằng lệnh julia trên Linux/MacOS

$ julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.1.0 (2019-01-21)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> 1 + 1
2

Đây gọi là chế độ “REPL” (Read-Eval-Print-Loop) == (gõ vào – chạy – in ra kết quả – cứ thế mà làm).

  Những cải tiến đáng giá của Python 3.12

IPython

Không cần cài thêm gì, Julia REPL tự có đủ các tính năng thiết yếu của IPython.

Đọc document của 1 function? Gõ ? rồi gõ bất cứ cái gì cần hỏi:

julia> 1 + 1
2
###### gõ ? xong , biến từ julia> thành help?>
help?> sum
search: sum sum! summary cumsum cumsum! isnumeric VersionNumber issubnormal get_zero_subnormals

...
 sum(itr)

  Returns the sum of all elements in a collection.

Màu mè (syntax highlight) cũng tự có sẵn rồi.

Chạy file code

File code Julia có đuôi .jl, ví dụ hello.jl. Chạy file code bằng cách gõ lệnh: julia hello.jl

Cài đặt package

Để cài các package trên mạng, sử dụng package manager CÓ SẴN của Julia. Chuyện về virtualenv tạm chưa bàn tới ở đây vì khá rõ ràng là không cần thiết (cài package không cần gõ sudo gì cả).

Việc cài đặt package trong Julia thực hiện hơi khác so với Python Pip hay NodeJS NPM một chút. Sẽ không có câu lệnh nào để gõ cả, không có chương trình thêm nào hết. Julia thực hiện cài đặt package khi một đoạn code Julia được chạy (gọi function thực hiện cài đặt).

Ví dụ một file tên (tuỳ ý) như sau:

# gicungduoc.jl
using Pkg
Pkg.add("HTTP")
Pkg.add("JSON")
Pkg.add("DocOpt")

Chạy code này: julia gicungduoc.jl sẽ cài đặt các package, sau đó cứ thế mà dùng các thư viện này.

  Ruby vs Python: Đâu mới là ngôn ngữ tốt hơn cho lập trình ứng dụng

The good, the OK, the ugly

The good – phần tốt

Pipe operator

Tốt hay xấu là tuỳ do từng người tự phán xét. Hãy xem đoạn code sau:

Python: ''.join(" Py thon ".strip().split())

Julia: " Py thon " |> strip |> split |> xs -> join(xs, "")

Python

def double(x):
    return x * 2
def incr(x):
    return x + 1

print(incr(double(incr(2))))
double(x) = x * 2
incr(x) = x + 1
println(2 |> incr |> double |> incr)
# 7

|> gọi là Piping operator, lấy đầu ra của function này làm đầu vào cho function khác. Giúp việc goi funciton liên tục (và đọc nó) dễ dàng hơn. Giống UNIX command.

Nhanh

Julia thường nhanh hơn Python ít nhất 2 lần

Không quan trọng indentation

Dù bạn thụt ra thụt vào 2 3 4 5 ký tự, hay dùng tab đều không quan trọng. Chuyện này vốn gây đau đầu cho không ít người dùng Python.

Python

s = 0
for i in range(1000):
    if i % 3 == 0 or i % 5 == 0:
        s = s + i
print(s)

Julia

for i in 1:999
 if i % 3 == 0 || i % 5 == 0
   global s = s + i
 end
end
println(s)
# 233168

Julia dùng từ end để kết thúc if hay for, nên không cần thiết sử dụng dấu cách hay tab để thụt dòng. Thậm chí có thể dùng ; để phân cách các phần, và viết trên 1 dòng (bạn KHÔNG THỂ làm điều này với Python khi có for):

julia> s = 0; for i in 1:999; if i % 3 == 0 || i % 5 == 0; global s = s + i ; end ; end; println(s)
233168
Range bao gồm cả số kết thúc

Một điều gây khó chịu với người mới code Python là phần kết thúc của range không được tính. Tức nếu viết range(1,1000) thì chỉ có từ 1 đến 999. Trong đầu luôn phải nhớ bớt đi 1. Julia 1:999 nghĩa là 1 đến 999, không thêm bớt gì.

Không bị “leak” biến i trong vòng lặp ra ngoài

Đây là 1 bug của Python, do sau này quá muộn để sửa, người ta coi nó như 1 tính năng.

for i in [1,2,3]:
    print(i)
print(i)  # i vốn ở trong vòng lặp for, nay thoát ra ngoài với giá trị = 3
Hỗ trợ functional

Viết map trong Julia rất dễ chịu – dễ đọc:

map([1,2,3]) do x
  x + 1
end

Cách viết dùng lambda:

map(x -> x+1, [1,2,3])

sẽ tạo array chứa [2,3,4]

Python

list(map(lambda x: x+1, [1,2,3]))

The OK – ổn

Index from 1

Chuyện này gây sốc với lập trình viên lâu năm C, Java, PHP, Python … Nhưng không phải là hiếm có. Lua, MatLab, R đều dùng index từ 1.

ns=[1,2,3,4]; print(ns[4])

Trong Julia code này sẽ in ra số 4 nhưng Python sẽ xảy ra exception do Python index đếm từ 0

Dùng nhiều sẽ quen và cũng không ghê gớm lắm, do Julia sử dụng cả phần cuối của range.

Ví dụ slice: Python lấy 3 số đầu tiên của list:

ns[0:3]

Julia:

ns[1:3]

Đều kết thúc là 3 – đều là số phần tử cần lấy.

Nhưng tệ hơn khi cần lấy 2 phần tử cuối:

ns[end-1:end]

end là một index magic (tự xuất hiện), đại diện cho index của phần tử cuối cùng.

Trong ví dụ này gõ số 4 thay end cũng được.

The ugly – thảm hại

Unicode string – sẽ rất đau đầu khi chuyển từ Python sang.

Index của string (mặc định Unicode) trong Julia là byte index, không phải index theo thứ tự của ký tự.

Python

In [16]: w = "Điêu"

In [20]: w[0],w[1]
Out[20]: ('Đ', 'i')

Julia

ulia> w = "Điêu"
"Điêu"

julia> w[1]
'Đ': Unicode U+0110 (category Lu: Letter, uppercase)

julia> w[2]
ERROR: StringIndexError("Điêu", 2)
Stacktrace:
 [1] string_index_err(::String, ::Int64) at /nix/store/2fmf5sqi0jx5zdlqx0gpw2m6nrsbcch2-julia-1.0.1/lib/julia/sys.dylib:?
 [2] getindex_continued(::String, ::Int64, ::UInt32) at /nix/store/2fmf5sqi0jx5zdlqx0gpw2m6nrsbcch2-julia-1.0.1/lib/julia/sys.dylib:?
 [3] getindex(::String, ::Int64) at /nix/store/2fmf5sqi0jx5zdlqx0gpw2m6nrsbcch2-julia-1.0.1/lib/julia/sys.dylib:?
 [4] top-level scope at none:0

julia> w[3]
'i': ASCII/Unicode U+0069 (category Ll: Letter, lowercase)

Do chữ Đ trong Unicode UTF-8 được biểu diễn bằng 2 byte, ta chỉ có thể truy cập được index 1, không truy cập được index 2. Và chữ i ngay sau Đ sẽ là index 3.

Exception

TBD

Chú ý

  • Julia khởi động mất 0.2-0.4 giây, Python khởi động nhanh gấp 10.
  • String trong Julia phải dùng double quote "", single quote '' dành cho ký tự (Char).
  • Nối string dùng * chứ không phải +.
  • Sẽ không có method gắn liền vào các object như string hay list trong Python, thay vào đó là các function có sẵn (thường không cần import, gọi là trong Base)

Ví dụ 1 chương trình CLI nhận argument, gọi HTTP với JSON

import HTTP
import JSON
using DocOpt  # import docopt function

function main()
    doc = """Fist Julia program which makes HTTP requests to httpbin endpoint

    Usage:
      main.jl request <endpoint>

    Options:
      -h --help     Show this screen.
      --version     Show version.
    """

    args = docopt(doc, version=v"0.0.1")
    endpoint = args["<endpoint>"]
    url = "https://httpbin.org/$endpoint"
    println("Accessing $url")
    resp = HTTP.get(url)
    d = JSON.Parser.parse(String(resp.body))
    println("My IP is " * d["origin"])

    println("Now also send post")
    r = HTTP.request("POST", "https://httpbin.org/post",
            ["Content-Type" => "application/json"],
            JSON.json(Dict('a'=>2, 'b'=>3))
            )
    data = JSON.Parser.parse(String(r.body))

    open("/tmp/data.json", "w") do f
        write(f, JSON.json(data["json"]))
    end
    open("/tmp/data.json", "r") do f
        d = JSON.Parser.parse(String(read(f)))
        println(d)
    end

    open(`ls -l`) do io
        for line in eachline(io)
            if !isa(match(r".*\.jl", line), Nothing)
                println(line)
            end
        end
    end
end

main()

Chạy

$ julia  main.jl  -h
Fist Julia program which makes HTTP requests to httpbin endpoint

Usage:
  main.jl request <endpoint>

Options:
  -h --help     Show this screen.
  --version     Show version.

$ julia main.jl request ip
Accessing https://httpbin.org/ip
My IP is 3.117.2.254, 3.117.2.254
Now also send post
Dict{String,Any}("b"=>3,"a"=>2)
-rw-r--r-- 1 viethung.nguyen viethung.nguyen 1189 Apr 12 08:38 main.jl

Code hoàn toàn tương đương với code Python.

Kết luận

Còn chờ gì nữa? Làm tí Julia thôi.

Phần tiếp theo (nếu có) sẽ đi vào các tính năng của Julia sử dụng trong tính toán khoa học.

Tham khảo

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

Kiểu bool C/C++ | Code hướng dẫn và ứng dụng thực tiễn

Kiểu bool, boolean trong lập trình C/C++ (Code ví dụ)

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

Trong lập trình, việc xử lý các giá trị đúng/sai là điều thường xuyên phải thực hiện, đặc biệt trong các câu lệnh điều kiện, vòng lặp và kiểm tra logic. Kiểu dữ liệu Boolean được sử dụng để biểu diễn hai trạng thái logic cơ bản này. Cùng tìm hiểu về Bool trong C/C++ được sử dụng như thế nào, cú pháp ra sao trong bài viết của TopDev.

Bool trong C/C++ là gì?

Bool trong C/C++ là gì?

Trong C++, kiểu dữ liệu boolean được sử dụng để biểu diễn hai trạng thái logic: đúng hoặc sai. Kiểu dữ liệu này được gọi là bool, và nó có thể chứa một trong hai giá trị:

  • true: Đại diện cho giá trị đúng.
  • false: Đại diện cho giá trị sai.

Kiểu dữ liệu bool được sử dụng rộng rãi trong các câu lệnh điều kiện như if, while, for, và các phép toán logic khác. Khi một giá trị bool được sử dụng trong điều kiện, giá trị true được coi là 1 và false được coi là 0.

Ban đầu, ngôn ngữ C không hỗ trợ kiểu bool, mà nó dùng số integer để biểu thị true/false (0 tức là false, khác 0 tức là true). Bắt đầu từ phiên bản C99 standard for C language thì mới bắt đầu hỗ trợ kiểu bool.

  Các kiểu dữ liệu trong lập trình C/C++ (Data type)

Cách sử dụng kiểu bool trong C/C++

Cách 1: Sử dụng thư viện <stdbool.h>

Thư viện <stdbool.h> là một phần của C99, cung cấp định nghĩa cho kiểu bool, cũng như các hằng số truefalse. Thư viện này thường được sử dụng trong C hơn là trong C++.

Với cách này ta sử dụng kiểu bool của C (với C++ thì mặc định không cần khai báo thư viện <stdbool.h>)

Ví dụ:

#include<stdio.h>
#include <stdbool.h>

int main()
{
bool value = false;
if (value) { // tương đương với kiểm tra value == true
printf("value is true"); 
} else {
printf("value is false");
}
return 0; 
}

Kiểu bool, boolean trong lập trình C/C++ (Code ví dụ)

C++ tuyển dụng nhiều vị trí, lương cao, ứng tuyển ngay!

Cách 2: Tự định nghĩa kiểu bool với enum

Nếu bạn không muốn sử dụng kiểu bool tích hợp sẵn, bạn có thể tự định nghĩa nó bằng cách sử dụng enum (liệt kê). Điều này giúp bạn tạo ra kiểu dữ liệu bool của riêng mình với các giá trị truefalse.

enum bool { false, true }; // tương đương với typedef enum { false=0, true=1 } bool;

Ví dụ:

#include<stdio.h>
typedef enum { false, true } bool;

int main()
{
 bool value = false;
if (value) { // tuong duong v?i ki?m tra value == true
 printf("value is true");
} else {
 printf("value is false");
}
return 0;
}

Cách 3: Định nghĩa kiểu bool với integer

Một cách khác để mô phỏng kiểu bool là sử dụng một số nguyên (integer). Trong cách này, bạn quy ước rằng 0 đại diện cho false1 (hoặc bất kỳ giá trị khác 0) đại diện cho true.

typedef int bool;
#define true 1
#define false 0

int main() {
    bool isTrue = true;    // isTrue = 1
    bool isFalse = false;  // isFalse = 0

    if (isTrue) {
        // Thực hiện một số hành động khi isTrue là true
    }

    return 0;
}

Cách 4: Khai báo hằng số true/false

Bạn cũng có thể tự định nghĩa các hằng số truefalse mà không cần phải tạo kiểu dữ liệu mới. Điều này thường được sử dụng trong các ngôn ngữ hoặc môi trường không hỗ trợ kiểu bool một cách tự nhiên.

#define true 1
#define false 0

int main() {
    int isTrue = true;    // isTrue = 1
    int isFalse = false;  // isFalse = 0

    if (isTrue) {
        // Thực hiện một số hành động khi isTrue là true
    }

    return 0;
}

Cách 1 chỉ chạy được từ phiên bản C99 standard for C language. Tuy nhiên hầu hết các bản compiler C/C++ đều đã update cho nên các bạn nên dùng cách này. Cách 2,3,4: thì hoạt động giống nhau.

Nhìn chung thì kiểu bool vẫn là kiểu integer, nên cho dù dùng cách nào thì bạn vẫn có thể gán bool bằng một giá trị integer bất kì (0 tức là false, khác 0 tức là true).

Các ứng dụng thực tiễn của Bool C++

Kiểu dữ liệu boolean có rất nhiều ứng dụng trong lập trình, từ việc kiểm tra điều kiện trong câu lệnh if, vòng lặp while, for, đến việc sử dụng trong các phép toán logic phức tạp.

Kiểm tra điều kiện trong câu lệnh if

Câu lệnh if là một trong những câu lệnh điều kiện phổ biến nhất trong lập trình, và boolean đóng vai trò quan trọng trong việc xác định các điều kiện đúng hoặc sai.

Ví dụ:

#include <iostream>

int main() {
    bool isLoggedIn = true;

    if (isLoggedIn) {
        std::cout << "User is logged in." << std::endl;
    } else {
        std::cout << "User is not logged in." << std::endl;
    }

    return 0;
}

Sử dụng trong vòng lặp while

Vòng lặp while sử dụng boolean để xác định khi nào vòng lặp sẽ tiếp tục chạy và khi nào sẽ dừng.

Ví dụ:

#include <iostream>

int main() {
    int count = 0;
    bool keepGoing = true;

    while (keepGoing) {
        std::cout << "Count: " << count << std::endl;
        count++;
        if (count >= 5) {
            keepGoing = false;  // Dừng vòng lặp khi count >= 5
        }
    }

    return 0;
}

Sử dụng trong các phép toán Logic

Boolean cũng được sử dụng trong các phép toán logic, như AND (&&), OR (||), và NOT (!), giúp thực hiện các kiểm tra điều kiện phức tạp.

Ví dụ:

#include <iostream>

int main() {
    bool isAdmin = true;
    bool isLoggedIn = true;

    if (isAdmin && isLoggedIn) {
        std::cout << "User is an admin and is logged in." << std::endl;
    } else {
        std::cout << "Access denied." << std::endl;
    }

    return 0;
}

Kiểu dữ liệu boolean là một phần quan trọng và không thể thiếu trong lập trình, giúp lập trình viên thực hiện các kiểm tra điều kiện và các phép toán logic một cách dễ dàng và hiệu quả. Dù là trong ngôn ngữ C với sự thiếu hụt ban đầu của kiểu boolean hay trong C++ với kiểu dữ liệu boolean tích hợp sẵn, việc hiểu và sử dụng đúng cách kiểu boolean là kỹ năng quan trọng mà mỗi lập trình viên cần nắm vững.

Qua bài viết này, hy vọng bạn đã có cái nhìn sâu hơn về cách sử dụng kiểu boolean trong C và C++, cũng như biết cách áp dụng nó vào các tình huống thực tế trong lập trình.

Nguồn tham khảo: codecute.com

Xem ngay những tin đăng tuyển dụng IT mới nhất trên TopDev

Cách viết thư trả lời kết quả phỏng vấn siêu chuẩn

thư trả lời kết quả phỏng vấn
thư trả lời kết quả phỏng vấn

Thư trả lời kết quả phỏng vấn được xem được đánh giá là khá quan trọng đối với các ứng viên. Vì thực tế, bất kỳ ứng viên nào cũng đều mong muốn nhận được phản hồi về kết quả phỏng vấn; dù có trúng tuyển hay không?

Nếu là một doanh nghiệp có công tác chuyên nghiệp trong tuyển dụng, thì việc gửi email hay gọi điện phản hồi kết quả phỏng vấn là điều nên hiển nhiên cần thực hiện. Đây cũng thể hiện doanh nghiệp có một quy trình chặt chẽ; đảm bảo tính lịch sự và để lại ấn tượng đẹp trong lòng nhiều ứng viên. Cùng TopDev tìm hiểu xem đâu là cách thức viết thư trả lời phỏng vấn hiệu quả và chuẩn nhất!

Từ chối ứng viên một cách lịch sự – Cần hay không?

Tất nhiên là có! Và đó cũng là điều mà nhiều doanh nghiệp cần phải quan tâm. Việc tìm ra cách thức để từ chối ứng viên một cách lịch sử cũng trở nên quan trọng hơn. 

Và sẽ tùy thuộc vào cách xử lý của mỗi công ty cũng như phòng nhân sự; các giải pháp cụ thể dễ dàng nhất sẽ được diễn ra. Có nhiều cách thức từ chối được thông báo đến ứng viên. Đó có thể là bằng văn bản, bằng email hay bằng liên hệ qua điện thoại thông báo trực tiếp đến từng người,… Tuy vậy, cách chuyển tải nội dung thông báo kết quả qua văn bản. Cụ thể là thư trả lời kết quả phỏng vấn được xem là ưa chuộng nhất.

thư trả lời kết quả phỏng vấn
Có nên cần hay không?

Cùng tham khảo các mẫu trả lời ứng viên dưới đây khi ứng viên của bạn chưa may mắn trúng tuyển nhé!

  Thư mời phỏng vấn? Bật mí tips viết thư mời phỏng vấn hiệu quả 

Mẫu thư trả lời kết quả phỏng vấn cho ứng viên không trúng tuyển

Mẫu email trả lời lịch sự

THÔNG BÁO

V/v …………………………

Kính gửi: ………………………………………………………………………………………………..

Trước hết Công ty xin trân trọng cảm ơn Anh/Chị đã tham gia vào chương trình tuyển dụng của công ty chúng tôi.

Sau khi kiểm tra kiến thức chuyên môn, kỹ năng và phỏng vấn, Công ty xin thông báo: Anh/Chị không trúng tuyển vào vị trí: ………………………………………………………………..

Trường hợp Anh/Chị muốn nhận lại hồ sơ, xin vui lòng liên hệ Anh/Chị ………………………..

Phòng Nhân sự. Nếu Anh/Chị không lấy lại hồ sơ, chúng tôi sẽ chuyển hồ sơ Anh/Chị vào hồ sơ lưu (ứng viên tiềm năng).

Trân trọng kính chào!

                                                                                                             TP. NHÂN SỰ

(Ký và ghi rõ họ tên)

Mẫu thư trả lời kết quả chuẩn

THƯ CẢM ƠN

V/v …………………………

Kính gửi:

Lời đầu tiên thay mặt Tập thể công ty xin trân trọng cảm ơn Anh/Chị đã tham gia vào chương trình tuyển dụng của công ty chúng tôi.

Sau khi kiểm tra kiến thức chuyên môn, kỹ năng và phỏng vấn, Công ty xin thông báo: Anh/Chị không trúng tuyển vào vị trí:

Ban tuyển dụng đánh giá cao thời gian bạn dành để ứng tuyển. Chúc bạn may mắn trong quá trình tìm việc và mong rằng có thể hợp tác với bạn ở những vị trí việc làm khác trong tương lai.

Trân trọng kính chào!

                                                                                                                 NHÂN SỰ

(Ký và ghi rõ họ tên)

Lưu ý về cách viết thư trả lời kết quả sau phỏng vấn ứng viên

Số lượng ứng viên cho một vị trí rất nhiều. Do vậy, sức cạnh tranh là vô cùng lớn. Và việc lưu ý về cách thức viết thư trả lời kết quả của buổi phỏng vấn cũng có thể giúp bạn tối ưu hóa vấn đề thời gian. Đồng thời, vẫn đảm bảo tính chuyên nghiệp, tính lịch sự,… Hãy lưu tâm đến những vấn đề sau đây:

Về thông tin cá nhân của ứng viên 

Dù đó là thư từ chối ứng viên; hay thư báo kết quả ứng viên thì cũng cần đảm bảo những thông tin cá nhân cho ứng viên. Điều này minh chứng cho sự chuyên nghiệp của tổ/doanh nghiệp đó.

Lời cảm ơn rất quan trọng!

thư trả lời kết quả phỏng vấn
thư trả lời kết quả phỏng vấn

Một lời cảm ơn chân thành là điều mà mọi ứng viên đều mong muốn nhận được từ doanh nghiệp. Đừng quên dành lời cảm ơn đến ứng viên bởi họ đã quan tâm đến công ty cũng như vị trí mà họ ứng tuyển; dành thời gian của mình để nộp hồ sơ cũng như tham gia cuộc phỏng vấn. Đây thể hiện sự trân trọng lớn với những cố gắng mà họ đã bỏ ra.

Sự phản hồi

  Giới thiệu bản thân khi phỏng vấn - Bật mí bí quyết ghi điểm tuyệt đối

Thư phản hồi ứng viên sau phỏng vấn cần được trình bày một cách rõ ràng; rành mạch về lý do. Không nên viết quá dài dòng và lan man. Hãy tập trung vào những yếu tố mang tính xây dựng; khuyến khích tạo động lực thay vì chỉ chia sẻ về việc ứng viên thiếu những gì và không phù hợp ở đâu. 

Mời ứng tuyển lại

Đây thật sự là một điểm sáng cho thư trả lời kết quả sau phỏng vấn. Vì nếu công ty thấy ứng viên chưa phù hợp với vị trí hiện tại, hãy lưu hồ sơ của họ. Có thể sẽ có những vị trí phù hợp hơn. Việc thông báo ấy cũng tạo động lực; khích lệ tinh thần của họ một cách tốt hơn. 

Lời kết

Thư trả lời kết quả phỏng vấn là một lá thư quan trọng đối với ứng viên. Và quả thật, ai trong số họ cũng quan tâm đến nó. Đó cũng là cơ sở để họ biết được tình trạng kết quả phỏng vấn của mình thế nào.

Mong rằng, với bài viết này, TopDev đã chia sẻ với các bạn các mẫu thư trả lời phỏng vấn cơ bản; cùng những lưu ý giúp thư trả lời kết quả của bạn trở nên chỉn chu; chuyên nghiệp hơn. 


Tuyển Dụng Nhân Tài IT Cùng TopDev
Đăng ký nhận ưu đãi & tư vấn về các giải pháp Tuyển dụng IT & Xây dựng Thương hiệu tuyển dụng ngay!
Hotline: 028.6273.3496 – Email: contact@topdev.vn
Dịch vụ: https://topdev.vn/page/products

 

Xem thêm Top Việc làm it trên TopDev

Ruby on Rails Developer và con đường phát triển sự nghiệp tại ADVN Computer

Ruby on Rails Developer
Ruby on Rails Developer

Tự hào là nhà phân phối chính thức các thiết bị tin học tại thị trường Việt Nam, ADVN Computer đang dần chiếm ưu thế trong mối quan hệ hợp tác với các thương hiệu công nghệ hàng đầu. Với sự phát triển mạnh mẽ trong lĩnh vực outsource, ADVN Computer luôn tìm kiếm nhân tài công nghệ và sẵn sàng trao tay những cơ hội tuyệt vời.

ADVN Computer và sự tín nhiệm bởi các doanh nghiệp hàng đầu về công nghệ

Ruby on Rails Developer
Ruby on Rails Developer

Vươn lên từ sự thành công của công ty mẹ – AceCom tại Singapore, ADVN Software hình thành năm 2014 với nền tảng ban đầu là nhà phân phối Công nghệ thông tin. Đến nay, ADVN Computer đã trở thành một trong những Công ty phần mềm cung cấp ứng dụng Website, Mobile App, Quảng cáo Google… được ưa chuộng nhất tại thị trường Việt Nam.

Từ năm 2016, ADVN Computer trở thành nhà phân phối chính thức các thiết bị tin học mang thương hiệu tầm cỡ thế giới tại Việt Nam, khẳng định vị thế của mình bởi sự tín nhiệm từ các thương hiệu công nghệ hàng đầu như MSI, Sony, Hitachi, InFocus, Prolink… 

Với mục tiêu tập trung phát triển các dự án outsource, thương mại điện tử và quảng cáo chất lượng, công ty luôn nỗ lực tìm tòi, áp dụng công nghệ hiện đại, đồng thời từ đó đáp ứng tối đa và tối ưu các yêu cầu từ khách hàng.

Hoạt động với phương châm “Chuyên nghiệp, sáng tạo, chất lượng” và sự tin cậy từ các Nhà sản xuất, ADVN Computer được chỉ định là Trung Tâm Bảo Hành Ủy Quyền Chính Thức tại Việt Nam cho tất cả các thương hiệu nhằm đảm bảo quyền lợi tuyệt đối về chất lượng, giá cả, kỹ thuật, chế độ hậu mãi (Motorola).

Và để đạt được thành tựu to lớn đó, ADVN Computer luôn ghi nhận tài năng và công sức của đội ngũ “chiến binh” công nghệ – những “phần tử” tài năng luôn cố gắng hết sức mình cho sự phát triển của công ty.

Con đường sự nghiệp rộng mở dành cho Ruby on Rails Developer khi gia nhập ADVN Computer

Ruby on Rails Developer
Ruby on Rails Developer

Ở thời điểm hiện tại, Team Dev nhà ADVN Computer đang tìm kiếm “nhân tố” tài năng cho vị trí Ruby on Rails Developer, với nhiệm vụ hỗ trợ công ty phát triển trang web, trang thương mại điện tử và ứng dụng di động, đáp ứng các nhu cầu từ phía khách hàng.

Và nếu bạn đã nhen nhóm dự định lựa chọn ADVN Computer làm “điểm đến” để phát triển sự nghiệp, đừng ngại gửi CV ứng tuyển ngay hôm nay. ADVN Computer sẵn sàng mang đến cho bạn điều kiện tốt nhất về không gian làm việc, đi kèm với mức lương thưởng và đãi ngộ xứng đáng:

  • Mức lương hấp dẫn $1,000 – $1,500;
  • Review lương hàng năm, nâng cao chất lượng sống;
  • Được đảm bảo mọi quyền lợi các chế độ (ngày phép năm, gói bảo hiểm) đầy đủ theo luật Việt Nam;
  • Được thử sức mình với các dự án đầy tính thử thách, cải thiện và trau dồi kỹ năng làm việc theo nhóm;
  • Cơ hội phát triển mạnh mẽ với sự hướng dẫn tận tình, giúp đỡ từ “đàn anh” trong công ty;
  • Được làm việc trong môi trường quốc tế chuyên nghiệp, thân thiện với đầy đủ tiện nghi và không gian tuyệt vời cho bạn thỏa sức đam mê;
  • Cùng nhiều hoạt động tập thể, team building, sự kiện thú vị khác.

Apply ngay hôm nay chờ chi?

Review source code – What make it better?

Review source code

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

Review source code không phải là “nhiệm vụ” giới hạn cho bất kì vị trí nào. Dù là dev hay senior dev, tech lead đều “rất rất cần” tự review source code của chính mình.

Bài viết này xin chia sẻ chút kinh nghiệm nhỏ nhoi khi review source cho người khác. Viết sao cho tốt. Trình bày vấn đề sao cho rõ ràng. Đặt câu hỏi sao cho thông minh?. Tất cả sẽ có ngay sau đây.

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

  Các resources mới dành cho web dev
  "Mẹo bỏ túi" cho dân coder mới vào nghề

1. Review source code là gì?

Hiểu định nghĩa là quan trọng. Nhiều khi lên mặt review dạy đời là không đúng.

Code Review, or Peer Code Review, is the act of consciously and systematically convening with one’s fellow programmers to check each other’s code for mistakes, and has been repeatedly shown to accelerate and streamline the process of software development like few other practices can.

Code Review, hoặc Peer Code review, là hành động kêu gọi có “ý thức”, có “hệ thống” với các lập trình viên đồng nghiệp để kiểm tra code của nhau có đúng hay không. Việc này đã nhiều lần được chứng minh là đẩy nhanh và hợp lý hóa tiến trình phát triển phần mềm như một số cách khác có thể làm được

Đấy, bản thân review source code là đi tìm lỗi trong các đoạn code. Chỉ ra các điểm sai, các điểm chưa hợp lý hoặc có thể cải thiện cho code.

Đã bảo rồi!. Review Source Code có dễ bao giờ đâu

Tuy nhiên, không phải bất cứ điểm nào bất hợp lý cũng raise lên. Tùy thuộc dự án, người review mà cần “không khéo” khi post các thread review hoặc bày tỏ quan điểm.

2. Chỉ thị hoặc yêu cầu trực tiếp

Chỉ thị hoặc các yêu cầu trực tiếp trong Review Source Code thường được sử dụng khi nội dung review đã “sai” rõ ràng. Cần được xử lý ngay lập tức.

Một số vấn đề đơn cử có thể được nêu ra như sau:

  • Vi phạm Coding Convention
  • Code sai dẫn tới sai bussiness
  • Vi phạm hoặc có khả năng xảy ra vấn đề trong tương lai
  • Không handle hết tất cả các case

Trường hợp này, các vấn đề được nêu lên trực tiếp. Yêu cầu người viết code phải sửa vấn đề. Tất nhiên, tùy thuộc độ nghiêm trọng và phạm vi ảnh hưởng có thể bàn bạc cách thức đối ứng.

Việc sử dụng yêu cầu trực tiếp là cần thiết để biết vấn đề nào đã gặp và không nên để tiếp diễn ở lần sau. Tuy nhiên hạn chế sử dụng khi vấn đề không chắc chắn. Lúc này ta nên sử dụng Các câu hỏi mở.

3. Các câu hỏi mở

Các câu hỏi mở thường được sử dụng khi:

  • Vấn đề được raise lên cần được bàn luận kĩ hơn để có lựa chọn tối ưu thay thế hoặc không thay thế cách hiện tại.
  • Giải pháp suy nghĩ trong đầu có thể không chính xác. Cần tham khảo.
  • Gợi ý cho người được review tìm hiểu thêm về một vấn đề nào đó.
Cách review source codeCác câu hỏi mở giúp tìm hiểu thêm để giải quyết vấn đề. Hiểu hơn về source mà mình viết ra.

Việc sử dụng các câu hỏi mở vừa “khêu gợi”. Lộn, “kích thích” tìm hiểu vấn đề được bàn luận trong code. Vừa giúp “hạ nhiệt” các vấn đề được review, đảm bảo không khí review source code không trở nên quá nóng bỏng.

4. Thông tin cần thiết

Review source code đôi khi cần thông tin đi kèm. Những thông tin này thường được gọi là rule. Việc chấp hành các “luật lệ” này đảm bảo việc review diễn ra suôn sẻ. Luôn có đáp án chính xác cho từng review.

Một số rule có thể được kể ra như sau.

  • Review code cho biết chính xác dòng code, method nào, variable nào vi phạm hoặc cần xem xét.
  • Taglib cho từng review (bussiness sẽ cần fix gấp, convention đôi khi không cần quá gấp hoặc áp dụng sau,…)
  • Checkmark hoặc comment cho biết review đã được fixed, không đối ứng hoặc bất cứ thông tin gì thêm.
Review source code là gì?Rule đôi khi vô cùng hữu ích, giúp quá trình review source trở nên “dễ thở” hơn

Luật lệ tất nhiên có thể khác nhau tùy thuộc yêu cầu từng dự án. Một số dự án mình đã tham gia sẽ trả MR (Merge Request) về cho dev khi có vấn đề cần fix hoặc cần consider. Khi đã fix xong sẽ trả lại cho reviewer để check và merge.

Việc này có thể tiến hành linh hoạt tùy “tình hình, tiến độ” project, số lượng member, … Tuy nhiên nên lựa chọn cách dễ dàng nhất mà vẫn đảm bảo yêu cầu của việc review code.

5. Tham khảo

Thank you so much – Have a great day with your family – 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

OpenSSH là gì?

OpenSSH là gì?

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

OpenSSH là một chương trình mã nguồn mở (Open Source) được sử dụng để mã hoá (encrypt) các giao dịch giữa các host với nhau bằng cách sử dụng Secure Shell (SSH). Nó là một sự thay thế an toàn cho những chương trình được sử dụng để kết nối như: Telnet, rlogin, rsh…Bởi nó luôn luôn mã hoá (encrypt) tất cả các giao dịch, ẩn đi, che dấu username và password được sử dụng cho những phiên đăng nhập từ xa. Sau khi phiên đăng nhập được thực hiện, nó sẽ tiếp tục mã hoá (encrypt) tất cả những dữ liệu giao dịch giữa 2 host.

Dự án OpenSSH được phát triển dựa trên nền tảng của dự án Open BSD (một OS thuộc họ Unix). Nó được thiết kế để sử dụng những thuật toán mã hoá mạnh để nâng cao tính an toàn và ngăn chặn sự phá hoại của các hacker. Mặc dù được xây dựng và phát triển bởi nền tảng OpenBSD, nó cũng có khả năng tương thích và có thể hoạt động trên hầu hết các OS thuộc dòng họ Unix: Linux, HP-UX, AIX, Irix, SCO, MacOS X, Cygwin, Digital Unix/Tru64/OSF, SNI/Reliant Unix, NeXT, Solaris…

OpenSSH không phải là một chương trình. Nó là một bộ các chương trình kết nối an toàn:

– OpenSSH Client (ssh): Chương trình được sử dụng cho các đăng nhập từ xa. Với sự an toàn và mã hoá (encrypt) trong mỗi phiên đăng nhập ở mức độ cao. Nó là sự thay thế an toàn cho: rlogin và telnet đã tỏ ra lỗi thời và kém an toàn.

– Secure Copy Program (scp): Được sử dụng cho việc copy file từ xa, copy các file từ các host khác nhau trên Internet. Nó hỗ trợ username và password.

– Secure File Transfer Program (sftp): Được sử dụng để phục các yêu cầu FTP một cách an toàn.

– OpenSSH Deadmon (shhd): Đặt OpenSSH chạy ở chế độ daemon trên các hệ thống Unix.
…………….

Trên đây là những Tools chính không thể thiếu trong bộ OpenSSH. Ngoài ra còn rất nhiều Tools, Plugin, Addin nữa…

  Tại sao phải tham gia phát triển open-source
  Lí do mà tôi đã trót yêu "như điếu đổ" hệ điều hành OpenBSD

CÀI ĐẶT

Để lấy OpenSSH bạn lên Homepage chính của nó:http://www.openssh.org

Download một version phù hợp với hệ thống của mình. Tôi dùng Linux nên tôi sẽ download gói *.rpm. Sau đó sử dụng lệnh

root@domain.com#: rpm -Uvh *.rpm

Nếu bạn sử dụng các hệ thống khác thì việc cài đặt nó cũng tương tự. Bạn download gói phù hợp với hệ thống của mình. Nó có thể là *.tar, *.tar.gz, *.gz…etc. Bung nén nó vào một thư mục.

root@domain.com #: ./configure
root@domain.com #: make
root@domain.com #: make install

Tiếp đó theo làm theo các chỉ dẫn của script. Công việc cài đặt không mấy khó khăn. Chúng ta hãy dành thời gian và công sức cho công việc cấu hình.

CÁC TÍNH NỔI BẬT CỦA OPEN SSH

Open SSH cung cấp khá nhiều tính năng để giúp cho việc truyền thông giữa 2 host trở lên an toàn. Dưới đây là một số tính nổi bật:

1) Khả năng mã hoá mạnh bởi việc sử dụng chuẩn mã hoá 3 DES và Blowfish: Cả 2 chuẩn mã hoá trên đều đuợc cung cấp miễn phí và sử dụng rộng rãi ở nhiều nước trên thế giới. 3DES cung cấp khả năng mã hoá chứng thực thời gian. Blowfish cung cấp khả năng mã hoá nhanh hơn. Cũng như những chuẩn mã hoá khác cả 2 chuẩn nêu trên đều cung cấp khả năng mã hoá các dữ liệu trước khi nó được đưa vào đường truyền một cách an toàn.
2) Khả năng chứng thực mạnh bởi việc sử dụng các cơ chế Public Key, OPTs (One Time Password), Kerberos: Có tác dụng bảo vệ chống lại tính dễ tổn thương trong quá trình chứng thực bởi việc khai thác và sử dụng các kỹ thuật như: IP Spoof, DNS Spoof, Fake Router…Có 4 phương pháp chứng thực được Open SSH sử dụng :
–          Chỉ chứng thực Public Key
–          Sự chứng thực host bởi việc sử dụng Public Key kết hợp với .rhost
–          Sự chứng thực dựa trên OPTs kết hợp với s/key
–          Sự chứng thực dựa trên cơ chế Kerberos
3) Mã hoá giao thức X11 cho việc sử dụng X Window: Mã hoá dữ liệu trong quá trình sử dụng X Window giữa 2 host. Được sử dụng để chống lại những cuộc tấn công từ xa nhằm vào xterm như Snooping, Hjacking…
4) Mã hoá cho quá trình chuyển đổi cổng (Port Forwarding): Cho phép quá trình chuyển đổi các port TCP/IP tới một hệ thống khác thông qua một kênh được mã hoá. Nó được sử dụng cho những giao thức Internet chuẩn không cung cấp khả năng mã hoá dữ liệu trên đường truyền như: SMTP, POP, FTP, Telnet…
5) Đại diện chuyển tiếp cho những đăng nhập vào các mạng đơn: Một Key chứng thực của người dùng có thể và thường được lưu giữ trên PC của họ, nó có thể trở thành một trạm đại diện chứng thực. Khi người sử dụng hệ thống truy cập từ một hệ thống mạng khác. Kết nối của họ sẽ được chuyển tới cho trạm đại diện chứng thực này. Nó có tác dụng cho phép người sử dụng truy cập đến hệ thống của bạn một cách an toàn từ bất kỳ hệ thống nào.
6) Nén dữ liệu: Cung cấp khả năng nén dữ liệu một cách an toàn. Nó rất có ý nghĩa trên những hệ thống mạng không được nhanh.
7) Chứng thực chung cho Kerberos và Andrew File System bằng cách sử dụng Ticket: Những người sử dụng Kerberos và AFS sẽ được cung cấp một password chung để sử dụng và truy cập 2 dịch vụ trên trong một thời gian nhất định.

TẠO OPENSSH

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

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

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

Quản lý, sử dụng package trong CHICKEN Scheme

Quản lý, sử dụng package trong CHICKEN Scheme

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

Học và hành thường ở rất xa nhau. Ta có thể học đủ loại khái niệm, đủ loại cú pháp, viết các thuật toán để luyện ngôn ngữ, nhưng rồi lại mãi luẩn quẩn ở đó, không thoát ra được, không bay lên nổi. Viết 1 vòng for, 2 câu if bằng Python, JavaScript, Golang hay Elixir cũng không hơn nhau gì cả, chỉ thay đổi chút cú pháp thôi.

Thế nên cách “tốt nhất” để học 1 ngôn ngữ lập trình, không phải là học đủ các khái niệm, best practice, viết code chuẩn đẹp tuyệt đối, mà là việc hoàn thành một sản phẩm từ đầu đến tận X Y Z. Đưa ra sản phẩm cuối cùng, có thể là trang web chạy với domain hẳn hoi, có thể là chương trình đóng thành package, thành file cài đặt, hay game có giao diện đầy đủ.

Package manager giúp cài đặt các thư viện có sẵn là công cụ giúp ta đến đích nhanh nhất. Python có pip, JavaScript có NPM, Elixir có mix, Rust có cargo … thì CHICKEN Scheme có chicken-install, câu lệnh có sẵn khi cài CHICKEN Scheme.

  12 Packages và Libraries của Go cực kì mạnh mẽ mà bạn cần phải biết
  Cách để npm packages chạy trong browser

Cài đặt extension

CHICKEN Scheme gọi các gói thư viện là extension hay “egg”.

chicken-install tên-extension

Ví dụ cài regex:

$ sudo chicken-install regex
[sudo] password for hvn:  GO PASSWORD
retrieving ...
connecting to host "chicken.kitten-technologies.co.uk", port 80 ...
requesting "/henrietta.cgi?name=regex&mode=default" ...
reading response ...
HTTP/1.1 200 OK
Date: Fri, 05 Oct 2018 14:28:32 GMT
Server: Apache/2.2.31 (Unix) DAV/2 PHP/5.5.36 mod_fastcgi/2.4.6
...
checking platform for `regex' ...
checking dependencies for `regex' ...
install order:
("regex")
installing regex:1.0 ...
changing current directory to /tmp/tempab50.21917/regex
  '/usr/bin/csi' -bnq -setup-mode -e "(require-library setup-api)" -e "(import setup-api)" -e "(setup-error-handling)" -e "(extension-name-and-version '(\"regex\" \"1.0\"))" 'regex.setup'
  '/usr/bin/csc' -feature compiling-extension -setup-mode    -s -O3 -d1 regex.scm -JS
  '/usr/bin/csc' -feature compiling-extension -setup-mode    -s -O3 -d0 regex.import.scm
  cp -r 'regex.so' '/var/lib/chicken/7/regex.so'
  chmod a+r '/var/lib/chicken/7/regex.so'
  cp -r 'regex.import.so' '/var/lib/chicken/7/regex.import.so'
  chmod a+r '/var/lib/chicken/7/regex.import.so'
  chmod a+r '/var/lib/chicken/7/regex.setup-info'

Bật csi lên để gõ code gọi function grep:

$ csi
/usr/bin/rlwrap

CHICKEN
(c) 2008-2014, The Chicken Team
(c) 2000-2007, Felix L. Winkelmann
Version 4.9.0.1 (stability/4.9.0) (rev 8b3189b)
linux-unix-gnu-x86-64 [ 64bit manyargs dload ptables ]
bootstrapped 2014-06-07

#;1> (grep "[0-9]" (list "pymi" "2018" "pymi2018"))

Error: unbound variable: grep

    Call history:

    <syntax>      (grep "[0-9]" (list "pymi" "2018" "pymi2018"))
    <syntax>      (list "pymi" "2018" "pymi2018")
    <eval>    (grep "[0-9]" (list "pymi" "2018" "pymi2018"))    <--

Nội dung error rõ ràng: Error: unbound variable: grep – không hiểu grep là cái gì – nó không phải một variable/function đã tồn tại.

Sử dụng / import extension

Dùng macro use ten-extension (tại bài này cứ hiểu là function cũng tạm ổn)

#;1> (use regex)
; loading /var/lib//chicken/7/regex.import.so ...
; loading /var/lib//chicken/7/chicken.import.so ...
; loading /var/lib//chicken/7/irregex.import.so ...
; loading /var/lib//chicken/7/regex.so ...
#;2> (grep "[0-9]" (list "pymi" "2018" "pymi2018"))
("2018" "pymi2018")

Ta thu được list các phần tử có chứa số, string “[0-9]” là regular expression biểu diễn một số hệ 10.

Đọc tài liệu của module/function

grep ở trên làm gì? CHICKEN Scheme có chương trình chicken-doc để tra tài liêu, tương tự python có pydoc. Để có chicken-doc, cần cài extension với lệnh: sudo chicken-install chicken-doc.

$ chicken-doc grep
path: (regex grep)

-- procedure: (grep REGEX LIST [ACCESSOR])

Returns all items of `LIST` that match the regular expression `REGEX`. This procedure could be defined as follows:

  (define (grep regex lst)
    (filter (lambda (x) (string-search regex x)) lst) )

`ACCESSOR` is an optional accessor-procedure applied to each element before doing the match. It should take a single argument
and return a string that will then be used in the regular expression matching. `ACCESSOR` defaults to the identity function.
$ chicken-doc -i scheme  # đầy đủ doc về R5RS
...
$ chicken-doc -c scheme  # danh sách các procedure trong R5RS
...
$ chicken-doc data-structures
path: (data-structures)

== Unit data-structures

This unit contains a collection of procedures related to data structures. This unit is used by default, unless the
program is compiled with the `-explicit-use` option.
...


$ chicken-doc when # tìm từ khóa when, thấy 2 kết quả
Found 2 matches:
(spock when)                  (when X1 BODY ...)
(chicken special-forms when)  (when TEST EXP1 EXP2 ...)
$ chicken-doc chicken special-forms when # xem kết quả thứ 2

-- syntax: (when TEST EXP1 EXP2 ...)

Equivalent to:

  (if TEST (begin EXP1 EXP2 ...))

Pydoc đi kèm với Python có khả năng tương tự:

$ pydoc len

Help on built-in function len in module builtins:

len(obj, /)
    Return the number of items in a container.

Liệt kê các extension có trên “mạng”

$ chicken-install -list
2d-primitives
3viewer
9ML-toolkit
9p
AD
F-operator
R
abnf
accents-substitute
...

Tại thời điểm viết bài, có 781 egg trong kho – hơi ít.

Xem các extension library đã cài

Dùng lệnh chicken-status

$ chicken-status
apropos ......................................... version: 2.1.0
check-errors .................................... version: 2.2.0
chicken-doc ..................................... version: 0.4.7
chicken-doc-cmd ................................. version: 0.4.7
fmt ............................................. version: 0.808
fmt-c ........................................... version: 0.808
fmt-color ....................................... version: 0.808
fmt-js .......................................... version: 0.808
fmt-unicode ..................................... version: 0.808
iset .............................................. version: 2.0

Gỡ extension

Sử dụng câu lệnh chicken-uninstall TEN-extension.

Danh sách với thông tin các extension

Xem online tai http://eggs.call-cc.org/4/ cho bản CHICKEN stable hiện tại: version 4.

Bài viết thực hiện trên:

$ lsb_release -r; csi -version
Release:    16.04

CHICKEN
(c) 2008-2014, The Chicken Team
(c) 2000-2007, Felix L. Winkelmann
Version 4.9.0.1 (stability/4.9.0) (rev 8b3189b)
linux-unix-gnu-x86-64 [ 64bit manyargs dload ptables ]
bootstrapped 2014-06-07

Hết phần 2.

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

C Token là gì? Cú pháp trong lập trình C/C++

C Token là gì? Cú pháp trong lập trình C/C++

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

C Token là gì?

C token là đơn vị nhỏ nhất có thể đứng một mình trong một câu lệnh, một khai báo.

Mỗi token có thể là một từ khóa, một định danh, biến, hằng số, ký tự có nghĩa trong lập trình C

Ví dụ 1: mình có câu lệnh sau:

printf("Hello World \n");

Đoạn code trên gồm 5 token:

printf  // token 1
(  // token 2
"Hello World \n"  // token 3
)  // token 4
;  // token 5

Ví dụ 2:

int age = 10;

Đoạn code trên có thể viết thành:

int
age
=
10
;

Dấu chấm phẩy (semicolons)

Trong lập trình C, dấu chấm phẩy ; được dùng để kết thúc một câu lệnh (trong trường hợp này, dấu ; cũng được coi là một token)

Ví dụ:

printf("Hello World \n");

int age = 10;
  Bí kíp tạo ra một tokenizer về toán học bằng Javascript
  JSON Web Token (JWT) là gì ?

Chú thích, chú giải (comment)

Phần chú thích trong lập trình C là phần bị bỏ qua khi thực hiện compile. Chỉ có ý nghĩa về mặt text hiển thị giúp lập trình viên hiểu hơn về đoạn code.

Phần chú thích nằm sau dấu gạch chéo // (trường hợp comment trong 1 dòng) hoặc nằm trong /*   */ (trường hợp comment nằm trên nhiều dòng)

Ví dụ:

/*
 * in ra màn hình dòng chữ
 * Hello World!
 */
printf("Hello World \n");

// khai báo tuổi bằng 10
int age = 10;

Định danh (identifier)

Định danh trong C là một cái tên dùng để xác định một biến, một hàm (tên biến, tên hàm).

Định danh có thể bao gồm các ký tự a-zA-Z0-9 hoặc dấu gạch dưới _. Tuy nhiên định danh không được bắt đầu bằng 0-9.

Đặc biệt, định danh không được trùng với các từ khóa của ngôn ngữ C.

Ví dụ một số định danh hợp lệ: name_ageaddress1firstName

C++ tuyển dụng nhiều vị trí, lương cao, ứng tuyển ngay!

Từ khóa (keyword) trong C

Từ khóa là các từ được định nghĩa sẵn trong ngôn ngữ C, mang một ý nghĩa nào đó. Không thể dùng từ khóa để làm định danh, tên biến hay hằng số.

Các từ khóa trong C gồm:

auto else long switch
break enum register typedef
case extern return union
char float short unsigned
const for signed void
continue goto sizeof volatile
default if static while
do int struct _Packed
double

Ngoài những từ khóa trong C thì C++ còn bổ sung thêm một số từ khóa khác:

asm else new this
auto enum operator throw
bool explicit private true
break export protected try
case extern public typedef
catch false register typeid
char float reinterpret_cast typename
class for return union
const friend short unsigned
const_cast goto signed using
continue if sizeof virtual
default inline static void
delete int static_cast volatile
do long struct wchar_t
double mutable switch while
dynamic_cast namespace template And
And bitor not_eq xor
and_eq compl or xor_eq
bitand not or_eq

Okay, Done!

References:

https://www.cprogramming.com/

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

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

Xem ngay những tin đăng tuyển dụng IT mới nhất trên TopDev

5 tips thúc đẩy sự sáng tạo trong quá trình coding

khó khăn trong lập trình
5 tips thúc đẩy sự sáng tạo trong quá trình coding

Tác giả: Andrej Kovacevic

Khó khăn trong lúc lập trình là một trong những vấn đề mà bất kì lập trình viên nào cũng có thể gặp phải. Với một số lập trình viên, việc mỗi ngày đều phải tiếp xúc với dấu chấm phẩy, dấu ngoặc và dấu ngoặc đơn (ai mà không lãng phí hàng giờ để tìm kiếm một trong những thứ mà họ đặt sai vị trí hoặc bỏ sót), gần như đã trở thành một sự “ám ảnh”.

sáng tạo trong lập trình
Đối phó với việc bí ý tưởng như thế nào?

Nhưng hiện nay, vấn đề lập trình phổ biến nhất mà các lập trình viên trải qua chính là mắc kẹt trong các ý tưởng, không thể cho ra những đoạn code và đạt kết quả mà mình mong muốn. Nhờ những kinh nghiệm làm việc của bản thân, tôi sẽ chia sẻ với bạn về việc làm thế nào để khắc phục tình trạng này.

1. Bắt đầu các dự án trên giấy trước

Hầu như bất cứ khi nào tôi gặp rắc rối khi làm việc trong một dự án, những khó khăn trong lập trình phát sinh tôi đều có thể truy tìm nguyên nhân cụ thể của nó. Bằng cách nào? Đó là tôi đã cố gắng xây dựng các dự án bằng cách xoay quanh tổng thể những việc cần phải làm.

Khi bạn làm điều này, bạn sẽ nhận ra sự to lớn và đa dạng của dự án mã hóa mà bạn phải làm việc. Thêm vào đó, bắt đầu viết code mà không có ý tưởng cụ thể về thứ mình cần làm là gì, kết quả sau cùng chắc chắn sẽ không tốt, thậm chí là một sự thất bại đáng sợ.

  10 câu nói cực hay về lập trình
  10 nguyên tắc lập trình nền tảng mà lập trình viên nào cũng cần biết

Thay vào đó, hãy phác thảo những nét sơ bộ về dự án sắp phải làm việc trên giấy trước. Đó là điều mà các lập trình viên thế hệ trước thường làm theo thói quen, nhưng các lập trình viên trẻ tuổi hiện tại có xu hướng bỏ qua. Tất cả những gì bạn phải làm là viết ra mục đích hoạt động của chương trình, sau đó là danh sách các chức năng con mà bạn nghĩ sẽ làm cho mọi thứ hoạt động tốt hơn.

Hành động tưởng chừng đơn giản này giúp bạn dễ dàng chia nhỏ dự án thành các phần hợp lý hơn. Ngoài ra, đây cũng là cơ hội phát hiện trước các vấn đề có thể làm bạn chậm lại trong quá trình làm việc sau này.

2. Hoạt động trong SandBox

Đôi khi cách tốt nhất để vượt qua việc bí ý tưởng trong lúc lập trình là xây dựng một thứ gì đó – bất cứ thứ gì – miễn là nó hoạt động được. Vì vậy, nếu tôi gặp phải một nội dung khó khăn mà cảm giác khiến tôi như chẳng thế tiến thêm được kết quả gì, tôi sẽ chuyển sang SandBox và cố gắng xây dựng một thứ gì đó thú vị hơn với nền tảng này.

Bởi vì tôi thường làm việc và xử lý giao diện người dùng web, các trang web tôi thường truy cập sẽ là CodeSandboxCodePen, nhưng chắc chắn sẽ có nhiều website khác có thể phù hợp với nhu cầu của bạn hơn một chút.

Ví dụ: Replit sẽ cho phép người dùng viết code trực tiếp bằng hơn 50 ngôn ngữ và thậm chí có thể chuyển sang cộng đồng tích hợp của họ để yêu cầu trợ giúp nếu bạn gặp khó khăn về vấn đề nào đó.

Xem thêm Lập trình viên đánh đổi gì khi theo ngành lập trình

3. Duy trì công việc đang dang dở

Một điều góp phần vào việc xây dựng ý tưởng lập trình của cá nhân tôi là không có danh sách các nhiệm vụ đơn giản, có thể hoàn thành ngay, mà tôi có thể chuyển sang khi muốn tiếp tục đạt được tiến độ trong một dự án.

Nói cách khác, khi bạn đang làm việc với một thứ gì đó đặc biệt khó khăn trong lập trình, bạn sẽ muốn dành thật nhiều thời gian để suy nghĩ và hoàn thành nó. Dù dành ra quá nhiều thời gian nhưng có thể kết quả sẽ chẳng thể đi đến đâu. Để tránh phải điều đó, bạn nên duy trì một danh sách những task còn tồn đọng trong suốt quá trình chạy dự án. Tôi sử dụng một công cụ tương tự như một Scrum product backlog (ngay cả khi tôi không làm việc với một nhóm) để lưu trữ thông tin.

Ghi chú vào đó những thứ như tái cấu trúc mã và thay đổi giao diện,… Những vấn đề đơn giản sẽ có độ ưu tiên thấp nhất và cứ thế triển khai với vấn đề khó khăn hơn. Sau đó, khi gặp trục trặc, bạn có thể giải quyết những việc đơn giản đó như một phương tiện để tiếp tục tiến lên với dự án của mình.

Đôi khi, hoàn thành ngay cả một nhiệm vụ đơn giản nhất cũng đủ giúp bạn trở lại đúng hướng và tạo ra những code tốt một lần nữa nhờ cảm giác tin tưởng vào bản thân hơn.

khó khăn trong lập trình

4. Nghỉ ngơi đúng cách và có chiến lược

Nếu bạn dành một chút thời gian để tra cứu ý tưởng lập trình trên công cụ tìm kiếm yêu thích của mình, mỗi bài viết bạn thấy sẽ đều khuyên bạn nên nghỉ ngơi để thoát khỏi những áp lực và thử thách lập trình khó khăn. Tuy nhiên, điều quan trọng là bạn phải biết cách để thư giãn một cách hợp lí. Việc nghỉ ngơi thiếu logic có thể là một con dao hai lưỡi. Nếu không cẩn thận, những khoảng thời gian nghỉ của bạn sẽ bị lãng phí cho những thứ khác, chẳng hạn như sẽ chìm đắm vào chiếc điện thoại hay game đang chơi dở. Lúc này thì những khó khăn trong lập trình sẽ như quả cầu tuyết – càng lăn càng lớn.

Tôi đã nhận ra điều này khi lần đầu tiên tìm kiếm các mẹo vượt qua khó khăn khi lập trình. Lúc đầu, tôi khá có trách nhiệm với những khoảng thời gian nghỉ ngơi của mình – chỉ cần đi bộ năm phút hoặc đến máy pha cà phê khi tôi muốn đầu óc tỉnh táo, rồi sau đó tôi sẽ quay lại với công việc.

Nhưng ngay sau đó, tôi nhận ra mình đang tìm kiếm lý do để không bị phân tâm vào bất cứ điều gì tôi đang mắc kẹt. Chẳng hạn như việc tôi dành nửa ngày lùng sục trên internet để tìm một chiếc card màn hình PCIe có giá cả hợp lý mà không cần phải đưa vào danh sách chờ.

  Học IT có khó không? 6 khó khăn khi theo học ngành CNTT

Nghỉ giải lao là một cách hợp lý để thử và vượt qua việc bí ý tưởng, nhưng đương nhiên, đó là chỉ khi bạn sử dụng chúng một cách đúng đắn. Cuối cùng tôi nhận thấy rằng việc sử dụng thời gian có hạn, không sử dụng máy tính hoạt động tốt như là bước cuối cùng trong quá trình thiết lập lại có chủ ý cho não của tôi.

Hiện tại, khi tôi gặp khó khăn, thời gian nghỉ ngơi của tôi sẽ như thế này:

  • Dành 15 phút để giải quyết vấn đề
  • Dành 5 phút để xem xét mọi thứ từ đầu
  • Dành thêm 15 phút để giải quyết vấn đề
  • Đi bộ ít nhất 10 phút để làm điều gì đó không liên quan đến mã hóa
  • Bắt đầu lại từ đầu

Hầu như mọi lúc, tôi sẽ tìm thấy câu trả lời mà tôi đang tìm kiếm sau khi nghỉ ngơi khoảng 10 phút như thế này. Đó là lý do tại sao phải có một khoảng thời gian ngắn sau đó ngay lập tức quay trở lại với nó. Lâu hơn nữa có thể khiến bạn bị phân tâm và thậm chí quên mất mình đã dừng lại ở đâu và cần làm gì tiếp theo.

Và nếu may mắn, bạn sẽ không phải lặp lại quá trình trên thường xuyên. Bằng cách đó, bạn có thể tập trung và tránh lãng phí quá nhiều thời gian cho những công việc không hiệu quả. Tuy nhiên, hãy cẩn thận, không được bỏ qua hoàn toàn các giờ giải lao. Bạn nên cân nhắc thời gian giãn cách công việc để thư giãn, nó không chỉ tốt cho việc phát huy ý tưởng mới mà còn cần thiết vì sức khỏe của bạn.

5. Luôn luôn để lại những ghi chú cần thiết

Khi nói đến sự khó khăn trong việc phát triển các ý tưởng phần mềm, câu nói “phòng bệnh hơn chữa bệnh” chắc chắn không thể đúng hơn. Đó là lý do tại sao tôi xây dựng thói quen kiểm soát thời gian và cách thức tôi tạm dừng công việc của mình khi đang thực hiện một dự án mã hóa.

Tôi làm điều này bởi vì tôi thấy rằng việc bị gián đoạn và không hoàn thành được bất cứ việc gì đang làm giữa chừng không gây ra vấn đề gì, ngoài việc đau đầu để tìm lại vị trí công việc ở nơi mà tôi đã dừng lại.

Xem thêm 8 cạm bẫy lập trình viên dù biết vẫn khó tránh khỏi

Thay vào đó, nếu tôi cần ngừng làm việc, tôi sẽ để lại những ghi chú cụ thể và chi tiết cho biết tôi cần làm gì tiếp theo. Ngay cả khi tôi đang vội, tôi vẫn để lại vài dòng note để dễ dàng hơn khi bắt nhịp công việc của mình lúc quay lại.

Nó giúp tôi giảm được những rắc rối liên quan đến việc quay trở lại “chế độ lập trình” vì tôi không phải suy nghĩ quá nhiều để bắt đầu tại nơi tôi đã dừng lại. Cả hai vấn đề đều có thể làm bạn chậm lại và khiến bạn gặp nhiều trở ngại trong việc lập trình.

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