Những bước cần thiết phải làm khi lập trình
Nói trước:
- Chủ đề này chưa đóng và bài này chưa phải là sơ kết hay tổng kết, chỉ là bài gợi ý về cách lập trình và phương pháp test sau khi lập trình. Những gợi ý sau đây áp dụng cho bài tập trong chủ đề này và những bài tương tự (chuyển cột thành dòng và tách kết quả)
- Bài viết này có thể chưa đầy đủ, nhưng là những bước tối thiểu.
Bước 1: Chọn thuật toán
Một bài toán có nhiều cách giải, tương tự như vậy việc lập trình sẽ có nhiều thuật toán. Vấn đề là tư duy của người lập trình sâu sắc đến đâu, thì thuật toán sẽ phù hợp. trước khi chọn thuật toán phải nắm thật chắc yêu cầu của đề bài, các điều kiện cần tuân thủ, các giới hạn của kết quả.
Ví dụ code bài 17 và 23 dùng 2 vòng lặp cho 2 chiều của dữ liệu và biến đếm kết quả, khi biến đếm đạt mức yêu cầu thì trả về 0 để đếm lại từ đầu.
Code bài 26 lại dùng 1 vòng lặp cho cả 2 chiều dữ liệu và 2 biến đếm cho 2 chiều: Khi mỗi biến đếm đạt tới số cần thiết thì trả về giá trị ban đầu để đếm lại. Vòng lặp thứ hai là vòng lặp tạo sheet và gắn kết quả.
Hai code 17 và 23 chưa biết trước số sheet, vòng lặp chạy đến khi hết dữ liệu, chạy đến đâu tạo sheet đến đó.
Code bài 26 và 31 tính trước số sheet, số dòng dữ liệu cho mỗi sheet, sau đó dùng 1 vòng lặp sheet, mỗi sheet 2 vòng lặp tính kết quả.
Thuật toán có thể đơn giản, có thể phức tạp tùy theo tư duy và cả phong cách của người lập trình. Tuy nhiên hãy thử ít nhất 2 thuật toán.
Bước 2: Xét tính khả thi của thuật toán
Hãy tập thói quen dùng giấy và bút. Nếu khả năng trung bình thì vẽ sơ đồ khối, con đường đi của dữ liệu từ bảng dữ liệu ban đầu cho đến khi thành kết quả: Lặp, rẽ nhánh, tính toán, quay về, …
Nếu thấy sơ đồ quá phức tạp thì hãy thử bỏ thuật toán tìm thuật toán khác.
- Sơ đồ có thể thực hiện là “có thể vẽ được”, rõ ràng, tường minh, trong tầm kiểm soát
- Sơ đồ không nên thực hiện là “không vẽ được”, quá nhiều nhánh rẽ không kiểm soát được.
Nếu có 2 thuật toán thì so sánh 2 sơ đồ để chọn.
Khi trình độ khá hơn và bài toán tương đối dễ có thể tưởng tượng sơ đồ, nhưng với dự án lớn vẫn phải vẽ ra giấy. Nếu cần thì sẽ vẽ những sơ đồ con. Ai không biết sơ đồ khối thì cần phải tìm tài liệu để đọc.
Bước 3: Chọn phương tiện dùng trong code
Giữa việc đọc và ghi lên sheet với việc dùng mảng, hãy ưu tiên dùng mảng.
Nếu cần kiểm soát dữ liệu theo danh mục, nên cân nhắc việc có dùng Dictionary hay không. Không phải lúc nào dùng Dict. cũng là tối ưu.
Nếu dùng mảng:
- Cân nhắc việc chỉ tạo 1 mảng hay nhiều mảng đầu vào (dữ liệu nguồn). Đôi khi dùng nhiều mảng nguồn dễ kiểm soát hơn là 1 mảng: Ví dụ code bài 17, 26 chỉ dùng 1 mảng dữ liệu nguồn, khi chạy vòng lặp sẽ phải lưu ý thứ tự cột đầu, cột cuối của vùng 2, 3 và thứ tự dòng đầu của vùng 1, 3. Trong khi code bài 23 dùng 3 mảng dữ liệu nên vòng lặp chạy từ đầu đến cuối không quan ngại.
- Trường hợp cần lấy dữ liệu trên 5, 7 cột rời rạc thì dùng 5, 7 mảng mỗi cột 1 mảng vẫn tốt hơn là dùng 1 mảng lớn cả chục cột.
- Redim mảng kết quả với kích thước đúng và vừa phải. Hãy ước lượng số dòng tối đa, tối thiểu, cũng như số cột tối đa tối thiểu. Lớn quá thì hao tài nguyên mà nhỏ thì thiếu. Tuân thủ nguyên tắc thà dư còn hơn thiếu nhưng đừng dư quá đáng. Ví dụ đề bài chủ đề này đọc kỹ sẽ thấy câu: “Số lượng mặt hàng cần kiểm tra và số lượng cửa hàng cần kiểm tra chưa biết trước”, thì có thể hiểu dữ liệu có thể chỉ có năm mười dòng và cũng có thể lên hàng chục ngàn dòng (tương tự là cột). Kết quả ước lượng khoảng vài ngàn dòng, nếu số lượng dòng tối đa theo sheet là 500 ngàn, mà Redim theo 500 ngàn thì quá dư. Vậy kết hợp là Redim theo số nhỏ hơn giữa 2 số đó.
Nếu dùng Dict:
- Cân nhắc việc sử dụng bao nhiêu Dict. Một Dict dùng chung cho 2, 3 nội dung chưa hẳn là tối ưu lại còn khó kiểm soát. Khi cần đếm riêng lại không đếm được.
- Cân nhắc việc sử dụng items của Dict thế nào để tận dụng nó.
Dùng If ElseIf hay dùng Select Case
Cần nắm vững tính chất và ứng dụng của từng loại để chọn dùng cho phù hợp.
Bước 4: Viết code phần tính toán ra kết quả
Khai báo biến
Khai báo rõ ràng, tên biến gợi lên ý nghĩa của giá trị biến.
Xác định vị trí đặt các câu lệnh phụ và đặt điều kiện đúng:
- Câu lệnh điều kiện (If): Điều kiện theo đề bài và điều kiện theo thuật toán. Xem lại sơ đồ giấy cho chắc chắn. Code bài 17 mắc lỗi này (thiếu điều kiện bằng) nên mỗi sheet tạo ra (kể từ sheet thứ hai) mất 1 dòng kết quả. Code bài 26 để điều kiện cột F bằng “Y” ở ngoài vòng lặp nên không có tác dụng.
- Câu lệnh tăng biến đếm: Khi nào tăng, khi nào không tăng, tăng trước hay tăng sau câu lệnh chính.
- Câu lệnh trả giá trị biến đếm về giá trị ban đầu: Điều kiện gì và đặt ở đâu.
- Câu lệnh thoát vòng lặp: Thoát 1 vòng hay thoát cả 2 vòng, điều kiện thoát là gì. Vòng lặp Do có điều kiện thoát chưa, điều kiện đó có khi nào thỏa không?
- Nếu mảng dùng lại trong các vòng lặp, phải bảo đảm mảng phải bị xóa giá trị của vòng lặp trước. Code bài 26 bị lỗi này. Cách xóa dễ nhất là Redim lại.
- …
Bước 5: Viết code phần gán kết quả
Tạo sheet mới hay dùng sheet đang có
- Tạo sheet mới khi nào, có cần đặt tên lại không, nếu đặt tên lại phải xét tên dự định đạt đã tồn tại chưa
- Dùng sheet đang có thì dùng sheet nào, khi nào tạo sheet mới, tên gì, đã tồn tại chưa.
- Kiểm soát trường hợp đặc biệt: Dữ liệu nguồn ít khiến cho kết quả ít hơn số dòng tối đa mong muốn, đã kiểm soát được chưa. Code bài 26 tính trước số sheet và khi gặp trường hợp này số sheet bằng không, chẳng có kết quả để gán xuống.
Xóa dữ liệu đang có
Nếu dùng sheet đang có, phải bảo đảm trên sheet đó không có kết quả của lần chạy trước. Nếu có phải xóa cho hết.
Viết hàm con – thủ tục con
Viết hàm con và/ hoặc thủ tục con giúp cho code gọn gàng hơn khi trong code chính có những đoạn code thực hiện nhiều lần với những trường hợp khác nhau hoặc những thông số khác nhau.
Ví dụ trong bài 31, hàm con nhận 2 tham số dòng đầu & dòng cuối của dữ liệu, tự lấy đoạn dữ liệu giữa 2 dòng tham số và trả về kết quả trong đoạn dữ liệu đó.
Xác định chức năng cho hàm/ thủ tục con
- Nếu chỉ muốn trả về mảng kết quả thì dùng hàm con
- Nếu muốn mỗi lần ra kết quả là 1 lần tạo sheet luôn thì dùng thủ tục con.
Xác định tham số truyền vào
- Truyền bao nhiêu tham số
- Truyền những gì
Code bài 31 chọn dùng hàm, và chỉ truyền 2 tham số dòng đầu dòng cuối của dữ liệu. Hai tham số này được code chính tính toán sẵn.
Cũng có thể truyền chỉ 1 tham số là mảng dữ liệu đã tìm sẵn theo dòng đầu & dòng cuối.
Bước 7: Kiểm tra kết quả
Viết code xong chạy lần đầu mà đúng ngay, hãy tự nhủ là hên, chứ không phải là giỏi. Phải kiểm tra có phương pháp và kiểm tra kỹ.
So sánh với kết quả tính tay
- Tính nhẩm hoặc dùng công thức (CountIf) ra số lượng dòng kết quả, đối chiếu với kết quả mới chạy ra.
- Tìm kiếm bằng mắt hoặc Ctrl F xem 1 dòng, 1 ô dữ liệu đáng lẽ không tính có bị tính không
- Nếu kết quả là tính toán số liệu, dùng công thức tính tay hoặc bằng hàm Excel để kiểm tra.
- Dùng pivot table để kiểm tra kết quả có bỏ sót trường hợp hoặc dư trường hợp nào. Trong nhiều trường hợp phương pháp này rất hiệu quả ví dụ như Count = Count If không giống Count = Pivot table.
- Để ý cột số thứ tự nếu có. Số thứ tự phải kế thừa từ sheet này qua sheet kia chứ không phải mỗi sheet mỗi đánh lại từ 1.
Chạy thử trường hợp đặc biệt:
- Cho LastRw là số khá nhỏ (10 – 100 dòng dữ liệu)
- Cho ExpectRow là số khá lớn (hơn 1 triệu)
- Cho ExpectRow là số khá nhỏ (50.000 – 100.000)
- Cho ExpectRow là vài số không tròn ngàn, tròn vạn, đặc biệt là không phải ước số của tổng kết quả.
- Cho ExpectRow là ước số (chia hết) của tổng kết quả
Chạy code nhiều lần
Chạy code cùng 1 điều kiện ít nhất 2 lần để đối chiếu kết quả. Ví dụ code bài 26 chạy lần 2 thì câu lệnh gán tiêu đề A1:F1 mất tác dụng.
Ngoài ra nếu 1 lần chạy tạo mới 5 sheet, chạy nhiều lần thì số sheet mới bị nhân lên, không còn biết sheet nào của lần chạy nào. Nên có thủ tục xóa sheet hoặc dùng lại sheet