- vừa được xem lúc

Những sai lầm tôi mắc phải khi là một lập trình viên mới bắt đầu (P2)

0 0 8

Người đăng: Michelle Nguyen

Theo Viblo Asia

Chào các bạn, tôi sẽ tiếp tục chủ đề “Những sai lầm tôi mắc phải khi là một lập trình viên mới bắt đầu” ở bài viết này.

11. Viết nhận xét về những điều hiển nhiên

Tôi đã học cách tránh viết nhận xét khi có thể và điều đó không hề dễ. Hầu hết các nhận xét có thể được thay thế bằng các yếu tố được đặt tên tốt hơn trong mã của bạn.

Ví dụ, thay vì đoạn mã sau:

Mã tương tự có thể được viết mà không có nhận xét như thế này:

Việc chỉ sử dụng các tên tốt hơn cho các hàm và đối số sẽ làm cho hầu hết các nhận xét trở nên không cần thiết. Hãy nhớ điều này trước khi viết bất kỳ nhận xét nào.

Tuy nhiên, đôi khi bạn bị ép buộc vào tình huống mà sự rõ ràng duy nhất bạn có thể thêm vào mã là thông qua các nhận xét. Đây là lúc bạn nên cấu trúc các nhận xét của mình để trả lời câu hỏi TẠI SAO mã này thay vì câu hỏi MÃ này đang làm gì.

Nếu bạn rất muốn viết một nhận xét WHAT để làm rõ mã, xin đừng chỉ ra những điều hiển nhiên. Dưới đây là một ví dụ về một số nhận xét vô ích chỉ làm tăng tiếng ồn trong mã:

Đừng trở thành một lập trình viên như vậy. Đừng chấp nhận đoạn mã đó. Hãy loại bỏ những nhận xét như vậy nếu bạn phải đối mặt với chúng. Quan trọng nhất, hãy truyền tải thông điệp tới những người lập trình viết những nhận xét như vậy thì tồi tệ như thế nào. Nếu bạn tình cờ đang thuê những người lập trình viết những nhận xét như trên, hãy cho họ biết rằng họ thực sự có thể mất công việc vì điều này.

12. Không viết các bài kiểm tra (Tests)

Tôi sẽ trình bày điểm này đơn giản. Nếu bạn nghĩ rằng bạn là một chuyên gia lập trình và suy nghĩ đó cho bạn sự tự tin để viết mã mà không cần kiểm tra, bạn chỉ là người mới trong quyển sách của tôi.

Nếu bạn không viết các bài kiểm tra trong mã, có khả năng bạn đang kiểm tra chương trình của mình theo cách khác, một cách thủ công. Nếu bạn đang xây dựng một ứng dụng web, bạn sẽ làm mới và tương tác với ứng dụng sau mỗi vài dòng mã. Tôi cũng làm như vậy. Không có gì sai với việc kiểm tra mã một cách thủ công như của bạn. Tuy nhiên, bạn nên kiểm tra thủ công mã của mình để tìm hiểu cách kiểm tra tự động nó. Nếu bạn kiểm tra thành công một sự tương tác với ứng dụng của mình, bạn nên quay lại trình soạn thảo mã và viết mã để tự động thực hiện cùng một sự tương tác chính xác vào lần tiếp theo bạn thêm mã vào dự án.

Bạn là một con người. Bạn sẽ quên kiểm tra tất cả các xác nhận thành công trước đó sau mỗi sự thay đổi mã. Hãy để máy tính làm việc đó cho bạn!

Nếu bạn có thể, hãy bắt đầu bằng cách đoán hoặc thiết kế các xác nhận của bạn ngay cả trước khi bạn viết mã để đáp ứng chúng. Phát triển dựa trên kiểm tra (TDD) không chỉ là một sự cường điệu lạ mắt.

Nó ảnh hưởng tích cực đến cách bạn suy nghĩ về các tính năng của mình và cách tìm ra một thiết kế tốt hơn cho chúng.

TDD không phải là dành cho tất cả mọi người và nó không hoạt động tốt cho mọi dự án, nhưng nếu bạn có thể sử dụng nó (thậm chí là chỉ một phần thôi) bạn hoàn toàn nên làm như vậy.

13. Giả sử rằng nếu mọi thứ đang hoạt động đều đúng

Hãy xem xét hàm này thực hiện tính năng sumOddValues. Chúng ta hãy xem có gì sai với nó không nhé?

Việc khẳng định được thông qua. Cuộc sống tốt lành. ĐÚNG không?

Vấn đề với đoạn mã trên là nó không hoàn chỉnh. Nó xử lý đúng một số trường hợp (và việc khẳng định được sử dụng ngẫu nhiên là một trong những trường hợp đó) nhưng nó có nhiều vấn đề hơn nữa.

Chúng ta hãy cùng tìm hiểu một số trong số đó:

— Vấn đề #1: Không có xử lý cho đầu vào trống. Điều gì sẽ xảy ra khi hàm được gọi mà không có đối số nào? Hiện tại bạn sẽ nhận được một lỗi tiết lộ cách thực hiện của hàm khi điều đó xảy ra:

Điều đó thường là dấu hiệu của mã tệ vì hai lý do chính.

Người dùng hàm của bạn không nên gặp phải các chi tiết về cách thực hiện của nó.

Lỗi không hữu ích cho người dùng. Hàm của bạn chỉ đơn giản không hoạt động cho họ. Tuy nhiên, nếu lỗi rõ ràng hơn về vấn đề sử dụng, họ sẽ biết rằng họ đã sử dụng hàm không đúng cách. Ví dụ: bạn có thể chọn để hàm đưa ra một ngoại lệ do người dùng xác định như sau:

Có lẽ thay vì ném ra một lỗi, bạn cần thiết kế hàm của mình để chỉ cần bỏ qua đầu vào trống và trả về tổng là 0.

— Vấn đề #2: Không có xử lý đầu vào không hợp lệ. Điều gì sẽ xảy ra nếu hàm được gọi với một chuỗi, một số nguyên, hoặc một giá trị đối tượng thay vì một mảng?

Dưới đây là điều mà hàm sẽ cho ra bây giờ:

Thật đáng tiếc vì array.reduce chắc chắn là một hàm!

Vì chúng ta đã đặt tên cho đối số của hàm là array, bất cứ thứ gì bạn gọi hàm với (42 trong ví dụ trên) sẽ được gắn nhãn là array trong hàm. Lỗi cơ bản đang nói rằng 42.reduce không phải là một hàm.

Bạn thấy lỗi đó gây nhầm lẫn, phải không? Có lẽ lỗi hữu ích hơn có thể đã là:

Vấn đề #1 và #2 đôi khi được gọi là trường hợp biên. Đây là một số trường hợp biên phổ biến cần lập kế hoạch, nhưng thường có những trường hợp biên ít rõ ràng hơn bạn cần suy nghĩ. Ví dụ, điều gì xảy ra nếu chúng ta sử dụng số âm?

-13 là một số lẻ. Đây có phải là hành vi mà bạn muốn hàm này có không? Nó có nên ném ra một lỗi không? Nó có nên bao gồm các số âm trong tổng không? Hay nó đơn giản chỉ bỏ qua các số âm như hiện tại? Có lẽ bạn sẽ nhận ra rằng hàm nên được đặt tên là sumPositiveOddNumbers.

Việc đưa ra quyết định trong trường hợp này rất dễ. Điểm quan trọng hơn là, nếu bạn không viết một trường hợp kiểm tra để ghi lại quyết định của mình, những người duy trì hàm của bạn trong tương lai sẽ không biết việc bạn bỏ qua các số âm có mục đích hay là lỗi.

Đó không phải là một lỗi. Đó là một tính năng.

— Vấn đề #3: Không phải tất cả các trường hợp hợp lệ được kiểm tra. Quên trường hợp biên, hàm này có một trường hợp hợp pháp và rất đơn giản mà nó không xử lý đúng:

Số 2 trên đã được bao gồm trong tổng khi đáng lẽ ra nó không nên như vậy.

Giải pháp rất đơn giản, reduce chấp nhận một đối số thứ hai để được sử dụng làm giá trị ban đầu cho accumulator (bộ tích luỹ). Nếu đối số đó không được cung cấp (như trong mã trên), reduce sẽ sử dụng giá trị đầu tiên trong bộ sưu tập làm giá trị ban đầu cho bộ tích luỹ. Đây là lý do tại sao giá trị chẵn đầu tiên trong trường hợp kiểm tra trên đã được bao gồm trong tổng.

Dù bạn có phát hiện ra vấn đề này ngay lập tức hay khi mã được viết, trường hợp kiểm tra đã tiết lộ nó nên đã được bao gồm trong các bài kiểm tra, ngay từ đầu, cùng với nhiều trường hợp kiểm tra khác, như tất cả các số chẵn, danh sách có số 0 trong đó, và một danh sách trống.

Nếu bạn thấy các bài kiểm tra tối thiểu mà không xử lý nhiều trường hợp hoặc bỏ qua các trường hợp biên, đó là dấu hiệu khác của mã người mới học (newbie code).

Trong việc phát triển phần mềm, việc viết các bài kiểm tra đầy đủ, bao gồm cả các trường hợp biên và các tình huống phức tạp, rất quan trọng để đảm bảo rằng mã của bạn hoạt động đúng cách và đáng tin cậy.

Việc bỏ qua việc kiểm tra không chỉ gây nguy hiểm cho chất lượng mã của bạn mà còn cho thấy sự thiếu kinh nghiệm và sự không chuyên nghiệp. Dù có đánh giá mã của mình là "hoàn hảo" đến mức nào, không thể phủ nhận rằng mỗi dòng mã có thể chứa lỗi. Chính xác vì lý do này, việc sử dụng các bài kiểm tra tự động, bao gồm cả các trường hợp biên, là một phần quan trọng của quy trình phát triển phần mềm.

Những người lập trình viên có kinh nghiệm hiểu rằng việc viết mã chỉ là một phần của câu chuyện. Việc đảm bảo rằng mã hoạt động đúng cách thông qua việc kiểm tra là một phần không kém phần quan trọng. Điều này giúp xác định và sửa lỗi, đồng thời cũng tạo ra một tài liệu sống động cho mã, giúp các lập trình viên khác trong tương lai dễ dàng hiểu và làm việc với nó.

14. Không đặt câu hỏi về mã hiện tại

Trừ khi bạn là một lập trình viên siêu cấp luôn làm việc một mình, không còn nghi ngờ gì rằng bạn sẽ gặp phải một số loại mã ngớ ngẩn trong cuộc đời bạn. Người mới học sẽ không nhận ra nó và họ thường cho rằng đó là mã tốt vì nó dường như đang hoạt động và đã là một phần của cơ sở mã từ lâu.

Tệ hơn là nếu mã xấu sử dụng các thực hành xấu, người mới học có thể bị cám dỗ lặp lại thói quen xấu đó ở nơi khác trong cơ sở mã bởi vì họ đã học được nó từ những gì họ nghĩ là mã tốt.

Một số mã trông xấu nhưng có thể có điều kiện đặc biệt xung quanh nó buộc nhà phát triển phải viết nó theo cách đó. Đây là nơi tốt cho một bình luận chi tiết giảng dạy cho người mới học về điều kiện đó và tại sao mã được viết như vậy.

Là người mới học, bạn chỉ cần cho rằng bất kỳ mã nào không được tài liệu hóa mà bạn không hiểu là ứng viên có khả năng xấu. Hãy đặt câu hỏi. Hỏi về nó. git blame nó!

Nếu tác giả của mã đó đã ra đi hoặc không nhớ nó, hãy nghiên cứu mã đó và cố gắng hiểu mọi thứ về nó. Chỉ khi bạn hoàn toàn hiểu mã, bạn mới có quyền hình thành ý kiến về việc nó xấu hay tốt. Không nên giả sử bất cứ điều gì trước đó.

15. Ám ảnh về best practices

Tôi nghĩ rằng thuật ngữ “thực hành tốt nhất” (best practices) thực sự có hại. Nó ngụ ý rằng không cần nghiên cứu thêm. Đây là thực hành TỐT NHẤT từ trước đến nay. Đừng đặt câu hỏi!

Không có thực hành tốt nhất nào. Có lẽ có những thực hành tốt ngày nay và cho ngôn ngữ lập trình này.

Một số điều chúng ta đã xác định trước đây là thực hành tốt nhất trong lập trình ngày nay được gắn nhãn là thực hành tệ.

Bạn luôn có thể tìm thấy những thực hành tốt hơn nếu bạn dành đủ thời gian. Hãy ngưng lo lắng về thực hành tốt nhất và tập trung vào những gì bạn có thể làm tốt nhất.

Đừng làm điều gì chỉ bởi vì bạn đã đọc một lời trích dẫn ở đâu đó, hoặc vì bạn đã thấy người khác làm điều đó, hoặc vì ai đó nói rằng đây là thực hành tốt nhất. Điều này bao gồm tất cả những lời khuyên mà tôi đang đưa ra trong bài viết này! Hãy đặt câu hỏi về mọi thứ, thách thức tất cả các lý thuyết, biết hết tất cả các lựa chọn của bạn, và chỉ đưa ra những quyết định có hiểu biết.

16. Đặt vấn đề về Hiệu suất lên hàng đầu

Quy tắc tốt để nhớ về điều này là nếu bạn không thể đo được vấn đề về hiệu suất mà bạn nghi ngờ với đoạn mã, đừng cố gắng tối ưu hóa nó.

Nếu bạn đang tối ưu hóa trước khi thực hiện mã, có khả năng bạn đang làm điều đó sớm. Cũng có một khả năng lớn rằng việc tối ưu hóa mà bạn đang dành thời gian vào hoàn toàn không cần thiết.

Tất nhiên có một số tối ưu hóa rõ ràng mà bạn nên luôn xem xét trước khi giới thiệu mã mới. Ví dụ, trong Node.js, điều cực kỳ quan trọng là bạn không nên làm ngập lụt vòng lặp sự kiện hoặc chặn ngăn xếp cuộc gọi. Đây là một ví dụ về tối ưu hóa sớm mà bạn nên luôn nhớ. Hãy hỏi bản thân: Liệu mã tôi đang nghĩ có chặn ngăn xếp cuộc gọi không?

Bất kỳ tối ưu hóa không rõ ràng nào được thực hiện trên bất kỳ mã hiện có nào mà không có phép đo đạc được coi là có hại và nên tránh. Những gì bạn nghĩ có thể là một lợi ích về hiệu suất, nếu thực hiện, có thể trở thành nguồn gốc của các lỗi mới, không lường trước.

Đừng lãng phí thời gian của bạn để tối ưu hóa những vấn đề về hiệu suất không được đo lường.

17. Không nhắm đến Trải nghiệm của Người dùng cuối

Cách dễ nhất để thêm một tính năng vào một ứng dụng là gì? Hãy nhìn nó từ quan điểm của chính bạn, hoặc cách nó phù hợp với Giao diện Người dùng hiện tại. Đúng không? Nếu tính năng là để thu thập một số loại dữ liệu nhập từ người dùng, sau đó thêm nó vào biểu mẫu mà bạn đã có. Nếu tính năng đó là thêm một liên kết vào một trang, sau đó thêm nó vào menu liên kết lồng nhau mà bạn đã có.

Đừng trở thành người phát triển như vậy. Hãy trở thành một trong những người chuyên nghiệp đặt mình vào vị trí của người dùng cuối của họ. Họ tưởng tượng những gì người dùng của tính năng cụ thể này cần và họ có thể hành động như thế nào. Họ nghĩ về những cách để làm cho tính năng dễ dàng cho người dùng tìm kiếm và sử dụng, chứ không phải cách dễ dàng để làm cho tính năng tồn tại trong ứng dụng một cách nào đó mà không có bất kỳ suy nghĩ nào về khả năng phát hiện và sử dụng của tính năng đó.

18. Không chọn đúng Công cụ cho Công việc

Mọi người đều có danh sách các công cụ yêu thích của họ để hỗ trợ họ trong các hoạt động liên quan đến lập trình. Một số công cụ tốt và một số công cụ tệ nhưng hầu hết các công cụ tốt cho một điều cụ thể và tệ cho nhiều điều khác.

Búa là một công cụ tuyệt vời để đóng một cái đinh vào tường nhưng đó là công cụ tồi tệ nhất để sử dụng với một cái vít. Đừng dùng búa vào một cái vít chỉ vì bạn "yêu" cái búa đó. Đừng dùng búa vào một cái vít chỉ vì đó là cái búa phổ biến nhất trên Amazon với 5.0 đánh giá của người dùng.

Dựa vào sự phổ biến của một công cụ thay vì mức độ nó phù hợp với vấn đề là dấu hiệu của một người mới học.

Một vấn đề về điểm này là bạn có thể sẽ không biết các "công cụ tốt hơn" cho một công việc cụ thể. Trong kiến thức hiện tại của bạn, một công cụ có thể là công cụ tốt nhất mà bạn biết. Tuy nhiên, khi so sánh với các tùy chọn khác, nó có thể không nằm trong danh sách hàng đầu. Bạn cần làm quen với các công cụ có sẵn và giữ tâm trí mở cửa về những công cụ mới mà bạn có thể bắt đầu sử dụng.

Một số lập trình viên từ chối sử dụng các công cụ mới. Họ thoải mái với các công cụ hiện tại của mình và có lẽ họ không muốn học bất kỳ cái mới nào. Tôi hiểu điều đó và tôi có thể cảm thông với nó, nhưng đó đơn giản là sai.

Bạn có thể xây một ngôi nhà bằng các dụng cụ nguyên thủy và phải dành nhiều thời gian của mình, hoặc bạn có thể đầu tư thời gian và tiền bạc vào các dụng cụ tốt và xây dựng một ngôi nhà tốt hơn, nhanh hơn. Các công cụ đang không ngừng được cải tiến và bạn cần phải thoải mái học về chúng và sử dụng chúng.

19. Không hiểu rằng vấn đề mã sẽ gây ra vấn đề dữ liệu

Một khía cạnh quan trọng của chương trình thường là việc quản lý một dạng dữ liệu nào đó. Chương trình sẽ là giao diện để thêm bản ghi mới, xóa bản ghi cũ, và sửa đổi bản ghi khác.

Ngay cả những lỗi nhỏ nhất trong mã chương trình cũng sẽ dẫn đến trạng thái không thể đoán trước được cho dữ liệu mà nó quản lý. Điều này đặc biệt đúng nếu tất cả các xác thực trên dữ liệu được thực hiện hoàn toàn thông qua chương trình lỗi.

Người mới học có thể không lập tức nắm được mối liên hệ giữa mã và dữ liệu. Họ có thể cảm thấy ổn khi tiếp tục sử dụng mã lỗi trong sản xuất vì tính năng X không hoạt động không quan trọng lắm. Vấn đề là mã lỗi có thể liên tục gây ra các vấn đề về tính toàn vẹn dữ liệu mà ban đầu không rõ ràng.

Tệ hơn nữa là việc triển khai mã đã sửa lỗi mà không khắc phục các vấn đề dữ liệu tinh vi mà những lỗi này gây ra chỉ làm tích tụ thêm các vấn đề dữ liệu, đưa vụ việc vào nhãn "không thể khôi phục".

Làm thế nào để bạn bảo vệ bản thân khỏi những vấn đề như vậy? Bạn chỉ cần sử dụng nhiều lớp xác thực tính toàn vẹn dữ liệu. Không phụ thuộc vào giao diện người dùng duy nhất. Tạo xác thực trên front-end, back-end, giao tiếp mạng và cơ sở dữ liệu. Nếu điều đó không phải là một lựa chọn, thì bạn phải ít nhất sử dụng các ràng buộc ở cấp độ cơ sở dữ liệu.

Làm quen với các ràng buộc cơ sở dữ liệu và sử dụng tất cả chúng khi bạn thêm cột và bảng vào cơ sở dữ liệu của mình:

  • Ràng buộc NOT NULL trên một cột có nghĩa là giá trị null sẽ bị từ chối cho cột đó. Nếu ứng dụng của bạn giả định sự tồn tại của một giá trị cho trường đó, nguồn của nó nên được xác định là not null trong cơ sở dữ liệu của bạn.

  • Ràng buộc UNIQUE trên một cột có nghĩa là cột không thể có các giá trị trùng lặp trên toàn bảng. Ví dụ, điều này rất tốt cho trường tên người dùng hoặc email trên bảng Users.

  • Ràng buộc CHECK là một biểu thức tùy chỉnh phải được đánh giá là đúng để dữ liệu được chấp nhận. Ví dụ, nếu bạn có một cột phần trăm bình thường mà giá trị của nó phải nằm giữa 0 và 100, bạn có thể sử dụng ràng buộc check để thực thi điều đó.

  • Ràng buộc PRIMARY KEY có nghĩa là giá trị của cột đó cả không-null và duy nhất. Bạn có lẽ đang sử dụng ràng buộc này. Mỗi bảng trong cơ sở dữ liệu nên có một khóa chính để xác định các bản ghi của nó.

  • Ràng buộc FOREIGN KEY có nghĩa là giá trị của cột phải khớp với giá trị trong cột của bảng khác, thường là một khóa chính.

Vấn đề khác của người mới học liên quan đến tính toàn vẹn dữ liệu là thiếu suy nghĩ về giao dịch. Nếu nhiều hoạt động cần thay đổi cùng một nguồn dữ liệu và chúng phụ thuộc vào nhau, chúng PHẢI được đóng gói trong một giao dịch có thể được lùi lại khi một trong những hoạt động này thất bại.

20. Thái độ sai lầm đối với việc rà soát mã (Code Reviews)

Một dấu hiệu của người mới học lập trình là họ thường coi việc rà soát mã là sự chỉ trích. Họ không thích chúng. Họ không đánh giá cao chúng. Họ thậm chí còn sợ chúng.

Điều này hoàn toàn sai lầm. Nếu bạn cảm thấy như vậy, bạn cần thay đổi thái độ này ngay lập tức. Hãy xem mỗi lần rà soát mã là một cơ hội học hỏi. Hãy đón nhận và đánh giá cao chúng. Học hỏi từ chúng. Và quan trọng nhất, hãy cảm ơn người rà soát khi họ dạy bạn điều gì đó.

Bạn là người học mã mãi mãi. Bạn cần chấp nhận điều đó. Hầu hết các lần rà soát mã sẽ dạy bạn điều gì đó mà bạn không biết. Phân loại chúng như một nguồn lực học tập.

Đôi khi, người rà soát sẽ sai và đó sẽ là lượt bạn dạy họ điều gì đó. Tuy nhiên, nếu điều gì đó không rõ ràng chỉ từ mã của bạn, thì có lẽ mã của bạn cần được sửa đổi trong trường hợp đó. Và nếu bạn cần dạy người rà soát điều gì đó, hãy biết rằng việc dạy dỗ là một trong những hoạt động đáng giá nhất mà bạn có thể làm như một lập trình viên.

Nếu bạn đang tìm kiếm cho mình một môi trường làm việc cởi mở với sự hỗ trợ tận tình từ các chuyên gia đi trước cũng như cơ hội tham gia vào các dự án thực tiễn thì có thể liên hệ ITBee Solutions để phát triển sự nghiệp lập trình của mình nhé.

_Nguồn: Medium

Bình luận

Bài viết tương tự

- vừa được xem lúc

Closure trong Javascript - Phần 2: Định nghĩa và cách dùng

Các bạn có thể đọc qua phần 1 ở đây. Để mọi người không quên, mình xin tóm tắt gọn lại khái niệm lexical environment:.

0 0 51

- vừa được xem lúc

Var vs let vs const? Các cách khai báo biến và hằng trong Javascript

Dạo này mình tập tành học Javascript, thấy có 2 cách khai báo biến khác nhau nên đã tìm tòi sự khác biệt. Nay xin đăng lên đây để mọi người đọc xong hy vọng phân biệt được giữa let và var, và sau đó là khai báo hằng bằng const.

0 0 31

- vừa được xem lúc

VueJS: Tính năng Mixins

Chào mọi người, hôm nay mình sẽ viết về Mixins và 1 số vấn đề trong sử dụng Mixins hay ho mà mình gặp trong dự án thực. Trích dẫn từ trang chủ của VueJS:.

0 0 27

- vừa được xem lúc

Asset Pipeline là cái chi chi?

Asset Pipeline. Asset pipeline là cái chi chi. . Giải thích:.

0 0 47

- vừa được xem lúc

Tạo data table web app lấy dữ liệu từ Google Sheets sử dụng Apps Script

Google Sheets là công cụ tuyệt vời để lưu trữ bảng tính trực tuyến, bạn có thể truy cập bảng tính bất kỳ lúc nào ở bất kỳ đâu và luôn sẵn sàng để chia sẻ với người khác. Bài này gồm 2 phần.

0 0 266

- vừa được xem lúc

Học Deep Learning trên Coursera miễn phí

Bạn muốn bắt đầu với Deep Learning nhưng không biết bắt đầu từ đâu? Bạn muốn có một công việc ở mức fresher về Deep Learning? Bạn muốn khoe bạn bè về kiến thức Deep Learning của mình. Bắt đầu từ đâu.

0 0 35