Month: March 2022

  • Kiến thức cơ bản về Dart(Phần 1)

    Giới thiệu

    Giới thiệu về kiến ​​thức cơ bản của ngôn ngữ lập trình Dart, được sử dụng để phát triển với Flutter SDK dành cho thiết bị di động, web và hơn thế nữa.

    Flutter là một bộ công cụ giao diện người dùng thú vị của Google cho phép bạn viết ứng dụng cho các nền tảng khác nhau bao gồm iOS, Android, web và hơn thế nữa, tất cả đều sử dụng một cơ sở mã. Flutter sử dụng ngôn ngữ Dart.

    Nếu bạn chưa quen với Dart, hướng dẫn này sẽ giới thiệu cho bạn các khái niệm cơ bản của nó và cho bạn thấy nó tương tự như thế nào với các ngôn ngữ lập trình khác mà bạn có thể đã biết.

    Trong suốt quá trình hướng dẫn này, bạn sẽ được giới thiệu về những điều cơ bản của Dart chẳng hạn như:

    • Variables, data types, and operators
    • Conditionals and loops
    • Collections
    • Functions

    Khi bạn hoàn thành, bạn sẽ sẵn sàng đi sâu vào phát triển Flutter bằng cách sử dụng Dart.

    Bắt Đầu

    Để bắt đầu nhanh chóng, cách tốt nhất của bạn là sử dụng công cụ mã nguồn mở DartPad , cho phép bạn viết và kiểm tra mã Dart thông qua trình duyệt web:

    DartPad được thiết lập giống như một IDE thông thường. Nó bao gồm các thành phần sau:

    • Khung trình soạn thảo : Nằm ở bên trái. Mã của bạn sẽ xuất hiện ở đây.
    • Nút RUN : Chạy mã trong trình chỉnh sửa.
    • Bảng điều khiển : Nằm ở phía trên bên phải, bảng này hiển thị đầu ra.
    • Bảng tài liệu : Nằm ở dưới cùng bên phải, bảng này hiển thị thông tin về mã.
    • Samples: Trình đơn thả xuống này hiển thị một số mã mẫu.
    • Nút Null Safety: Sử dụng nút này để chọn tham gia vào tính năng an toàn không có âm thanh mới của Dart.
    • Thông tin phiên bản : Ở phía dưới cùng bên phải, DartPad hiển thị phiên bản Flutter và Dart mà nó hiện đang sử dụng.

    Nếu muốn, bạn có thể cài đặt Dart SDK cục bộ trên máy của mình. Một cách để làm như vậy là cài đặt Flutter SDK . Cài đặt Flutter cũng sẽ cài đặt Dart SDK.

    Để cài đặt trực tiếp SDK Dart, hãy truy cập https://dart.dev/get-dart .

    Tại sao nên chọn Dart

    Dart có nhiều điểm tương đồng với các ngôn ngữ khác như Java, C #, Swift và Kotlin. Một số tính năng của nó bao gồm:

    • Statically typed
    • Type inference
    • String expressions
    • Multi-paradigm including object-oriented and functional programming
    • Null safe

    Dart được tối ưu hóa để phát triển các ứng dụng nhanh trên nhiều nền tảng.

    Variables, Comments and Data Types

    Điều đầu tiên bạn sẽ thêm vào main là một câu lệnh gán biến. Các biến giữ dữ liệu mà chương trình của bạn sẽ hoạt động.

    Bạn có thể coi một biến như một hộp trong bộ nhớ máy tính của bạn chứa một giá trị. Mỗi hộp có một tên, đó là tên của biến. Để biểu thị một biến bằng Dart, hãy sử dụng var từ khóa.

    Thêm một biến mới vào main:

    var myAge = 35 ;  
    
    

    Mỗi câu lệnh Dart kết thúc bằng dấu chấm phẩy, giống như các câu lệnh trong C và Java. Trong đoạn mã trên, bạn đã tạo một biến myAge và đặt nó bằng 35 .

    Bạn có thể sử dụng print Dart tích hợp sẵn để in biến vào bảng điều khiển. Thêm lệnh gọi đó sau biến:

    in (myAge); // 35
    
    

    Nhấp vào RUN trong DartPad để chạy mã. Bạn sẽ thấy giá trị của biến 35 được in trong bảng điều khiển.

    Comments

    Comments trong Dart giống như trong C và các ngôn ngữ khác. Văn bản sau // là một nhận xét một dòng, trong khi văn bản bên trong /* ... */ là một khối nhận xét nhiều dòng.

    Đây là một ví dụ:

    // Đây là một nhận xét một dòng. 
    
    in (myAge); // Đây cũng là một nhận xét một dòng. 
    
    / * 
     Đây là một khối bình luận nhiều dòng. Điều này rất hữu ích cho những 
     bình luận dài kéo dài vài dòng. 
     * /
    
    

    Data Types

    Dart là statically typed , nghĩa là mỗi biến trong Dart có một kiểu mà bạn phải biết khi biên dịch mã. Loại biến không thể thay đổi khi bạn chạy chương trình. C, Java, Swift và Kotlin cũng có statically typed .

    Điều này trái ngược với các ngôn ngữ như Python và JavaScript, được gõ động . Điều đó có nghĩa là các biến có thể chứa các loại dữ liệu khác nhau khi bạn chạy chương trình. Bạn không cần biết kiểu khi bạn biên dịch mã.

    Nhấp vào myAge cửa sổ trình chỉnh sửa và tìm trong bảng Tài liệu . Bạn sẽ thấy Dart được suy ra là myAge kiểu int vì nó được khởi tạo với giá trị số nguyên 35 .

    Nếu bạn không chỉ định rõ ràng một kiểu dữ liệu, Dart sẽ sử dụng suy luận kiểu để cố gắng xác định nó, giống như Swift và Kotlin.

    Dart cũng sử dụng kiểu suy luận cho các kiểu khác int. Nhập một biến pi bằng 3,14:

    var pi = 3,14 ; in (pi); // 3,14
    
    
    
    

    Dart pi được cho là double bởi vì bạn đã sử dụng một giá trị dấu phẩy động để khởi tạo nó. Bạn có thể xác minh điều đó trong bảng thông tin Dart bằng cách nhấp vào pi.

    Các kiểu dữ liệu cơ bản

    Dart sử dụng các loại cơ bản sau:

    • int : Số nguyên
    • double : Số phức
    • bool : Booleans
    • String: Chuỗi ký tự

    Dưới đây là một ví dụ về từng loại trong Dart:

    int và double cả hai đều bắt nguồn từ một kiểu được đặt tên numnum sử dụng dynamic từ khóa để bắt chước cách nhập động trong Dart.

    Thực hiện việc này bằng cách thay thế varbằng loại bạn muốn sử dụng:

    int yourAge = 27 ;
    
    in (yourAge); // 27
    
    

    Từ khóa Dynamic

    Nếu bạn sử dụng từ khóa dynamic từ khóa thay vì var, bạn sẽ nhận được một biến được nhập động một cách hiệu quả:

    dynamic numberOfKittens;
    
    

    Tại đây, bạn có thể đặt numberOfKittensthành một String dấu ngoặc kép. Bạn sẽ tìm hiểu thêm về String loại này sau trong hướng dẫn.

    numberOfKittens = 'There are no kittens!';
    
    print(numberOfKittens); // There are no kittens!
    
    

    numberOfKittenscó một kiểu, vì Dart có kiểu gõ tĩnh. Nhưng kiểu dynamicđó, có nghĩa là bạn có thể gán các giá trị khác với các kiểu khác cho nó. Vì vậy, bạn có thể chỉ định một intgiá trị bên dưới câu lệnh in của mình.

    numberOfKittens = 0 ; print (numberOfKittens); // 0
    
    
    
    

    Hoặc, nếu bạn có một con mèo con trong hộp của Schrödinger , bạn có thể gán một double giá trị:

    numberOfKittens = 0,5 ; print (numberOfKittens); // 0,5
    
    
    
    
    

    Nhấp vào RUN để xem ba giá trị khác nhau numberOfKittens được in trong bảng điều khiển. Trong mỗi trường hợp, kiểu của numberOfKittens phần còn lại dynamic, mặc dù bản thân biến đó giữ các giá trị của các kiểu khác nhau.

    Booleans

    Kiểu bool chứa các giá trị của một trong hai true hoặc false.

    bool areThereKittens = false ; print (areThereKittens); // false
    
    
    
    

    Nhưng, nếu bạn nhìn vào bên trong hộp của Schrödinger, bạn có thể chuyển sang có một con mèo con thực sự có:

    numberOfKittens = 1 ; 
    
    areThereKittens = true ; print (areThereKittens); // true
    
    
    
    

    Chạy lại mã để xem các giá trị Boolean của bạn trong bảng điều khiển. 

  • Bắt đầu với RxSwift ( Phần 1)

    Bắt đầu với RxSwift ( Phần 1)

    I. Giới thiệu

    Một trong những điều quan trọng của lập trình hướng đối tượng (OOP) và hướng thủ tục đó là imperative (lập trình mệnh lệnh). Chúng ta cần sử dụng những câu lệnh để thay đổi trạng thái của chương trình.

    Vậy câu hỏi đặt ra làm sao để trạng thái của chương trình có thể thay đổi một cách tự động, liệu ngôn ngữ, khái niệm lập trình nào làm được việc đó không ?

    → Câu trả lời đó là reactive programming.

    Khi mà ứng dụng của bạn phản ứng lại với những thay đổi của data, reactive programming sẽ giúp chúng ta thực hiện điều đó. Nó giúp chúng ta tâp trung vào việc xử lí logic và không cần quan tâm tới việc thay đổi giữa các trạng thái (state) với nhau.

    Chúng ta có thấy trong swift sử dụng KVO và didSet để thiết lập cho lập trình phản ứng (reactive), nhưng việc thiết lập cho dữ liệu lớn, hoặc bài toán phức tạp hơn khá rắc rối. Vậy nên chung ta sẽ dùng tới thư viện thứ 3 đó là RxSwift

    Note*: “KVO là một khái niệm chúng ta sẽ gặp nhiều khi sử dụng SwiftUI, các bạn có thể search thêm về khái niệm này nhé.”

    Thư viện RxSwift sẽ giúp chúng ta giải quyết vấn đề trên qua lập trình bất đồng bộ (asynchronous programming).

    Để không tốn thời gian của các bạn mình sẽ đi nhanh qua các thành phần mà RxSwift cung cấp

    II. Các thành thần (components) chính của RxSwift:

    • Observable và Observer
    • Subject
    • DisposeBag
    • Operators
    • Schedules

    Observable và Observer

    Có rất nhiều thuật ngữ để mô tả cho lập trình bất đồng bộ, ở đâu mình sẽ sử dụng thuật ngữ observebal và Observer luôn nhé.

    • Observer lắng nghe Observable.
    • Observable phát ra các items hoặc gửi các notifications đến các Observer bằng cách gọi các Observer methods.
    Khái niệm Observable đến từ observer design pattern là một đối tượng thông báo cho các đối tượng theo dõi về một điều gì đó đang diễn ra

    • Một Observer đăng ký lắng nghe một Observable, sau đó nó sẽ xử lý một item hoặc nhiều các item mà Observable phát ra.

    Chúng ta có thể đăng kí tới một Observable sequence thông qua subscribe(on:(Event<T>)->()).

    Trong RxSwift một sự kiện sẽ chỉ là một trong Enumeration Type với 3 trạng thái có thể xảy ra:

    .onNext(value: T) -> Observable  gọi hàm onNext  có tham số là item, item này là một trong các tập items của Observable

    .onError(error: Error) -> Được gọi khi Observable  kết thúc với một lỗi xảy ra trong quá trình chuyển đổi, xử lý dữ liệu.

    .onCompleted -> Observable  gọi hàm này sau khi hàm onNext  cuối cùng được gọi, nếu không có bất kì lỗi nào xảy ra.

    Ví dụ với code Swift: 

    let obj = Observable.from(["A", "B", "C", "D"]) // Khởi tạo một Observable
    obj.subscribe( // Thực hiện subscribe Observable
      onNext: { data in
        print(data) // Nơi nhận dữ liệu của Observer được gửi đi từ Observable
      }, 
      onError: { error in
        print(error) // Nơi nhận error và Observable được giải phóng
      }, 
      onCompleted: {
        print("Completed") // Nhận được sự kiện khi Observable hoàn thành và Observable được giải phóng
      })
       .disposed()
    

    Kết quả trả về:

    A

    B

    C

    D

    Competed

    Subject

    Một đối tượng vừa có thể là Observable vừa có thể là Observer được gọi là Subject.

    Trong RxSwift cung cấp cho chúng ta 4 subject khác nhau với cách thứ hoạt động khác nhau đó là:

    • PublishSubject: Khởi đầu “empty” và chỉ emit các element mới cho subscriber của nó.
    • BehaviorSubject: Khởi đầu với một giá trí khởi tạo và sẽ relay lại element cuối cùng của chuỗi cho Subscriber mới.
    • ReplaySubject: Khởi tạo với một kích thước bộ đệm cố định, sau đó sẽ lưu trữ các element gần nhất vào bộ đệm này và relay lại các element chứa trong bộ đệm cho một Subscriber mới.
    • BehaviourReplay (which was Variable): Lưu trữ một giá trị như một state và sẽ relay duy nhất giá trị cuối cùng cho Subscriber mới.

    Để đi sâu vào từng loại subject mà RxSwift cung cấp khá là dài, nên mình chỉ lướt qua. Các bạn có thể tìm hiểu thêm, hoặc chờ một bài viết viết của mình đi sâu phân tích các subject trên nhé!

    Ở phần 1 mình đã giới thiệu qua khái niệm Reactive Programing, và một số thành phần chính của nó là Observabel và Observer, Subject.

    Các phần tiếp theo mình sẽ gửi tới các bạn ở phần 2 nhé.

    Cảm ơn các bạn đã đọc bài viết của mình.

    CongPQ

  • Sử dụng Enum trong Enum

    1. Enum là gì?

    An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code.

    Ở đây chúng ta sẽ lấy nguyên định nghĩa mà Apple đưa ra, hiểu một các nôm na thì Enum là kiểu dữ để định nghĩa một nhóm có giá trị liên quan, từ đó giúp bạn làm việc an toàn với kiểu dữ liệu đó trong code của bạn.

    2. Enum trong Enum

    Như tiêu đề, mình sẽ đi thẳng vào việc sử dụng Enum trong Enum, các trường    hợp sử   dụng enum thông thường các bạn có thể tìm hiểu ở các blog hoặc bài viết khác.

    • Bài toán đưa ra: Khi bạn có một struct như sau:

    ở đây chúng ta thấy có một enum để định về type của các PieChart. Câu hỏi đưa ra là khi bạn vẫn muốn tiếp tục sử dụng lại struct trên cho các object tương tự, và các object đó có type khác nhau thì hướng xử lí của bạn là như thế nào?

    -> Một trong các cách mà mình nghĩ các bạn sẽ dùng tới là sử dụng lại enum, thêm case hoặc là tạo một struct và enum mới như hình:

    Ở đây chúng ta quan sát giữa strcut ChartViewEntity với ChartViewEntityInWeek. Chúng ta thấy hai struct chỉ khác nhau về type( ở đây là khác nhau vê Enum). Và giữa 2 enum lại có mối quan hệ giống nhau.

    Câu hỏi đặt ra, tại sao chúng ta không sử dụng lại cùng 1 struct mà sửa lại Enum, và trong Enum của chúng ta sẽ chưa các case là type cho ChartView trong từng trường hợp mong muốn. Và chúng ta giải quyết bài toán trên bằng cách xử lí lại như sau:

    Ở đây mình đã tạo ra 3 enum, và enum PieChartType sẽ chứa 2 Enum còn lại ( đó là các Enum con phù hợp cho từng bài toán đặt ra riêng cho mỗi Object có các thuộc tính được trìu tượng qua struct ChartViewEntity). Vậy là bài toán của chúng ta đã được giải quyết, và chúng ta nhận ra rằng việc sử dụng Enum trong Enum có hiệu quả nhất định, giúp code của bạn gọn hơn, và trở nên tường minh hơn, đảm bảo sự an toàn khi bạn viết code.

    •  Qua ví dụ trên mình đã đưa ra cách giải quyết bài toán đồng thời là ứng dụng của việc sử dụng Enum trong Enum. Vậy tạo sao chúng ta không bắt tay vào sử dụng cho các bài toán riêng của mình. Chúc các bạn thành công.

    3. Tổng kết

    Trên đây mà một số chia sẻ về việc sử dụng Enum trong Enum nói riêng, và Enum nói chung. Với Swift chúng ta có Enum giúp cho việc viết code trở nên rõ ràng và rành mạch hơn. Mong rằng qua bài viết sẽ giúp ích cho các bạn phần nào đó về việc sử dụng enum và tiến tới con đường coder chuyên nghiệp hơn.

    Cảm ơn các bạn đã đọc bài viết của mình.

    Author: CongPQ