Router (2): lớp nội bộ, ngoại lệ

    0

    Trong bài này chúng ta tiếp tục áp dụng các kỹ thuật để xây dựng lớp Router, bao gồm nạp chồng toán tử, lớp lồng nhau (nested class), và ngoại lệ.

    Thực hành: xây dựng lớp hỗ trợ phân tích truy vấn

    Bước 1. Tạo class Router

    Tạo file Router.cs trong thư mục Framework cho lớp Router

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Framework // lưu ý không gian tên
    {    
        /// <summary>
        /// lớp cho phép ánh xạ truy vấn với phương thức
        /// </summary>
        public class Router
        {
            
        }
    }
    

    Bước 2. Xây dựng lớp Request

    Bên trong lớp Router xây dựng lớp Request với code như sau:

    using System;
    
    namespace Framework
    {
        public class Router
        {
            /// <summary>
            /// lớp xử lý truy vấn
            /// </summary>
            private class Request
            {
                /// <summary>
                /// thành phần lệnh của truy vấn
                /// </summary>
                public string Route { get; private set; }
    
                /// <summary>
                /// thành phần tham số của truy vấn
                /// </summary>
                public Parameter Parameter { get; private set; }
    
                public Request(string request)
                {
                    Analyze(request);
                }
    
                /// <summary>
                /// phân tích truy vấn để tách ra thành phần lệnh và thành phần tham số
                /// </summary>
                /// <param name="request"></param>
                private void Analyze(string request)
                {
                    // tìm xem trong chuỗi truy vấn có tham số hay không
                    var firstIndex = request.IndexOf('?');
                    // trườn hợp truy vấn không chứa tham số
                    if (firstIndex < 0)
                    {
                        Route = request.ToLower().Trim();
                    }
                    // trường hợp truy vấn chứa tham số
                    else
                    {
                        // nếu chuỗi lối (chỉ chứa tham số, không chứa route)
                        if (firstIndex <= 1) throw new Exception("Invalid request parameter");
    
                        // cắt chuỗi truy vấn lấy mốc là ký tự ?
                        // sau phép toán này thu được mảng 2 phần tử: thứ nhất là route, thứ hai là chuỗi parameter
                        var tokens = request.Split(new[] { '?' }, 2, StringSplitOptions.RemoveEmptyEntries);
    
                        // route là thành phần lệnh của truy vấn
                        Route = tokens[0].Trim().ToLower();
    
                        // parameter là thành phần tham số của truy vấn
                        var parameterPart = request.Substring(firstIndex + 1).Trim();
    
                        Parameter = new Parameter(parameterPart);
                    }
                }
            }
    
        }
    }
    

    Phân tích code

    Nested class

    Để ý rằng khi xây dựng lớp Router, lớp Request xây dựng bên trong lớp Router. Request là một nested class của Router.

    Ở trường hợp trên, Request còn gọi là lớp trong/lớp nộ bộ, Router là lớp ngoài, đồng thời là lớp cấp đỉnh.

    Trong lớp Router có 3 loại logic tương đối độc lập: phân tích truy vấn, xử lý chuỗi tham số, đăng ký lệnh và gọi phương thức. Do đó, chúng ta tách Request thành một lớp nội bộ. Do sau này client code sẽ sử dụng đến lớp Parameter, lớp này được tách thành một lớp cùng cấp (lớp sibling) với Router. Trong thân lớp Router chỉ còn chứa code để đăng ký lệnh và gọi phương thức.

    Nếu một lớp sibling của Router muốn sử dụng lớp Request (giả sử lớp Request được đánh dấu public) thì phải sử dụng tên lớp là Router.Request trong các lệnh khai báo và khởi tạo, không thể trực tiếp sử dụng trực tiếp tên Request. Tên gọi ngắn gọn Request chỉ có thể sử dụng bên trong lớp Router.

    Lưu ý: nên hạn chế sử dụng lớp lồng nhau. Việc sử dụng lớp lồng nhau không hợp lý có thể dẫn đến những lỗi khó lường trước, đặc biệt là khi cho lớp trong và lớp ngoài gọi lẫn nhau.

    Ngoại lệ

    Khi xây dựng lớp Request chúng ta gặp một lệnh

    // nếu chuỗi lối (chỉ chứa tham số, không chứa route)
    if (firstIndex <= 1) throw new Exception("Invalid request parameter");

    Đây là một tình huống đặc biệt trong đó chuỗi truy vấn bị lỗi: người dùng vô tình chỉ nhập phần tham số mà không nhập phần route. Trong trường hợp này chúng ta không có cách gì để xử lý chuỗi truy vấn.

    Một số ví dụ khác: khi thực hiện phép chia, nếu mẫu số vô tình nhận giá trị 0, phép chia không thể thực hiện được; khi người dùng yêu cầu truy xuất một file nhưng lại cung cấp sai đường dẫn khiến không thể thực hiện thao tác truy xuất.

    Trong lập trình, những tình huống tương tự xảy ra rất nhiều và được gọi chung là ngoại lệ (exception).

    Xử lý ngoại lệ

    Khi một ngoại lệ được phát ra ở một vị trí bất kỳ trong chương trình, việc thực thi của chương trình sẽ dừng lại. Nếu chương trình đang chạy ở chế độ Debug, trình soạn thảo code sẽ được mở ra và đoạn code bị lỗi sẽ được đánh dấu giúp cho người lập trình xác định vị trí và nguyên nhân gây lỗi.

    Hình dưới đây minh họa tình huống lỗi khi người dùng nhập vào một lệnh chưa tồn tại.

    Giao diện Visual Studio khi xảy ra ngoại lệ
    Giao diện Visual Studio khi xảy ra ngoại lệ

    Nếu chương trình chạy ở chế độ Release, chương trình sẽ bị dừng lại và cơ chế xử lý ngoại lệ mặc định của .NET framework sẽ được kích hoạt để hiển thị lỗi. Chương trình được dịch ở chế độ này sẽ không chạy được ở chế độ Debug nữa.

    Nếu chương trình console chạy ở chế độ Release mà gặp lỗi, thông báo lỗi sẽ được hiển thị như dưới đây.

    Thông báo ngoại lệ ở giao diện console
    Thông báo ngoại lệ ở giao diện console

    Đây là cơ chế bắt và xử lý lỗi mặc định của .NET framework đối với ứng dụng console. Đối với ứng dụng windows form, giao diện bắt và xử lý lỗi có khác biệt.

    Tuy nhiên, cơ chế thông báo lỗi mặc định của .NET framework tương đối không thân thiện với người dùng.

    .NET cung cấp cho các chương trình tính năng bắt và xử lý ngoại lệ để tự mình xác định xem khi xảy ra lỗi (ngoại lệ) thì sẽ làm gì. Phần xử lý ngoại lệ chúng ta sẽ thực hiện trong bài thực hành cuối cùng.

    Kết luận

    Trong phần này chúng ta bắt đầu xây dựng các lớp hỗ trợ để phần sau có thể xây dựng lớp Router giúp ánh xạ truy vấn của người dùng sang thực thi phương thức của lớp điều khiển. Qua đây chúng ta đã làm quen với nạp chồng toán tử, phát ra ngoại lệ và lớp lồng nhau.

    Trong bài sau chúng ta sẽ tiếp tục sử dụng các class xây dựng trong bài này để hoàn thiện lớp Router.

    + Nếu bạn thấy site hữu ích, trước khi rời đi hãy giúp đỡ site bằng một hành động nhỏ để site có thể phát triển và phục vụ bạn tốt hơn.
    + Nếu bạn thấy bài viết hữu ích, hãy giúp chia sẻ tới mọi người.
    + Nếu có thắc mắc hoặc cần trao đổi thêm, mời bạn viết trong phần thảo luận cuối trang.
    Cảm ơn bạn!

    Subscribe
    Notify of
    guest
    0 Thảo luận
    Inline Feedbacks
    View all comments