Làm thế nào để lùi một bước và nhìn mã với đôi mắt tươi? [đóng cửa]


53

Tôi đã dành năm ngoái khi một nhóm một người phát triển ứng dụng khách hàng phong phú (hơn 35.000 LoC, với giá trị của nó). Nó hiện đang ổn định và đang được sản xuất. Tuy nhiên, tôi biết rằng các kỹ năng của tôi đã bị rỉ sét khi bắt đầu dự án, vì vậy không nghi ngờ gì nữa, có những vấn đề lớn trong mã. Tại thời điểm này, hầu hết các vấn đề nằm ở kiến ​​trúc, cấu trúc và tương tác - những vấn đề dễ dàng, thậm chí là vấn đề kiến ​​trúc / thiết kế, đã được loại bỏ.

Thật không may, tôi đã dành quá nhiều thời gian cho dự án này đến nỗi tôi gặp khó khăn khi nghĩ bên ngoài nó - tiếp cận nó từ một góc nhìn mới để thấy những sai sót bị chôn vùi sâu hoặc vốn có trong thiết kế.

Làm thế nào để tôi bước ra ngoài đầu và bên ngoài mã của tôi để tôi có thể có được một cái nhìn mới mẻ và làm cho nó tốt hơn?


15
Trong tương lai, xin vui lòng không vượt qua . Nếu bạn mắc lỗi bằng cách đăng lên trang web StackExchange sai thì gắn cờ cho việc di chuyển và giải thích nơi bạn cảm thấy nó thuộc về và người điều hành sẽ di chuyển câu hỏi cho bạn.
maple_shaft

Ok, sẽ làm! :) Một vài người đã gắn cờ để đóng, không di chuyển, vì vậy tôi đã xóa toàn bộ câu hỏi và mang nó đến đây.
BenCole

Vâng - mọi người đã nhấp vào nút 'đóng', không phải nút 'cờ' (ít nhất, tôi nghĩ đó là những gì đã xảy ra). Từ giờ tôi sẽ tự gắn cờ và chờ di chuyển.
BenCole


IMO, Nếu bạn không thể tìm cách cải thiện mọi thứ thì bạn không biết đủ. Tôi đã tạo ra một số thiết kế thực sự tuyệt vời trong quá khứ, nhưng khi tôi trở lại nó một thời gian sau, tôi luôn tự hỏi tại sao tôi sẽ làm một cái gì đó rất ngu ngốc. Dù sao, bạn có thể có cách tiếp cận rằng thiết kế của bạn là tốt. Sau đó, khi bạn thêm các tính năng, nếu nó khó, hãy tìm hiểu làm thế nào bạn có thể làm cho nó dễ dàng.
Dunk

Câu trả lời:


46

Những cách để tiếp cận điều này:

  • Tìm ai đó quen thuộc với vấn đề công nghệ và kinh doanh và nói chuyện với nó. Điều này có thể khó khăn trong một nhóm người nhưng thường là lựa chọn tốt nhất.
  • Làm việc trên một dự án khác nhau trong một thời gian. Điều này cũng có thể khó khăn nhưng thậm chí nghỉ một tuần có thể mang lại cho bạn một viễn cảnh tươi mới.
  • Nhìn vào các dự án hoặc sản phẩm tương tự, chẳng hạn như các sản phẩm nguồn mở nếu có. Hãy cẩn thận không sao chép mã nhưng họ có thể đã tiếp cận ý tưởng hoàn toàn khác.
  • Học một ngôn ngữ mới, thư viện hoặc khung. Các kỹ thuật liên quan có thể cung cấp cho bạn cái nhìn sâu sắc về cách tiếp cận các vấn đề tương tự mà bạn có khác nhau.
  • Đọc một cuốn sách / blog / tạp chí tốt về thiết kế hoặc ngôn ngữ / khung. Tôi không chắc bạn đang ở cấp độ kỹ năng nào, nhưng có rất nhiều lựa chọn thay thế trong các câu trả lời khác trên trang web này.

Nếu bạn có ví dụ cụ thể mà bạn muốn giải quyết, có lẽ gửi chúng ở đây.


6
+1 học một ngôn ngữ / khung mới. Nếu bạn đang làm việc trong một ngôn ngữ kịch bản, hãy học một ngôn ngữ hướng đối tượng. Nếu OO, tìm hiểu một chức năng (lisp-ish). Đọc +1 - đặc biệt là cấu trúc dữ liệu, mẫu thiết kế, tái cấu trúc và thực tiễn tốt nhất. Đọc sách Joel trên Phần mềm nếu bạn chưa có. Tôi cũng muốn giới thiệu các nhóm người dùng và trang web này tiếp tục đưa bạn đến những ý tưởng mới. Nếu ACM nói chuyện trong khu vực của bạn, hãy tham gia và tham dự!
GlenPeterson

2
Cụ thể hơn với các ngôn ngữ, nếu bạn chưa học nó, học Haskell, tôi nghĩ mọi người đều phóng đại và là những người hâm mộ về cách nó sẽ thay đổi căn bản cách bạn tiếp cận các vấn đề lập trình. Là một nhà khoa học giỏi, tôi đặt giả thuyết của mình để kiểm tra bằng cách học nó, tôi đã sai. Bạn sẽ tiếp cận thiết kế hiện tại của mình theo cách khác sau đó nếu bạn chưa học Haskell.
Jimmy Hoffa

1
Đi đến hội nghị nên được thêm vào đây, IMO. Se câu trả lời công phu của tôi dưới đây.
Macke

+1 cho dự án khác nhau. Hãy thử một cái gì đó hoàn toàn bên ngoài phạm vi của những gì bạn làm hàng ngày. Bạn sẽ tìm thấy một vài điểm tương đồng cũng như một thách thức kiến ​​trúc mới.
khoan hồng

13

Gỡ lỗi vịt cao su : Ngồi xuống với một đoạn mã hoặc mô-đun hoặc một tính năng và giải thích nó thành tiếng. Khi bạn thấy mình nói điều gì đó nghe có vẻ sai, dại dột, hoặc đơn giản là không đúng hãy viết nó ra như một vấn đề cần điều tra.


9

Hãy tiếp tục học hỏi và mở rộng các kỹ năng của bạn. Thật khó để biết những gì bạn không biết, nhưng khi bạn nhìn thấy nó, khoảnh khắc "aha" đó sẽ đánh vào bạn. Nó có thể đến từ việc học ngôn ngữ hoặc mẫu thiết kế khác.

Bạn sẽ được yêu cầu thay đổi. Bạn có thể tìm thấy các phần của mã không linh hoạt và sẽ yêu cầu làm lại rất nhiều. Đây không hẳn là một thất bại vì ban đầu bạn không thể nghĩ ra mọi thứ.

Người dùng sẽ bắt đầu phàn nàn. Chỉ khi bạn nghĩ rằng mọi thứ đều tuyệt vời ...


7

Một bộ nhớ ngắn giúp. Tôi đã được biết là phàn nàn về "thằng ngốc" đã thay đổi một cái gì đó một tuần trước, chỉ để tìm thấy từ kiểm soát nguồn đó là tôi.

Bước đầu tiên tốt là xác định mã có thể được cải thiện. Nhìn vào kiểm soát nguồn của bạn cho các tệp thay đổi thường xuyên nhất. Mã nào là khó nhất để làm việc với? Mã nào tạo ra nhiều lỗi nhất? Những loại thay đổi gây ra hiệu ứng gợn trong suốt mã? Ở giai đoạn này, bạn không cần phải biết tại sao mã lại rắc rối, chỉ nó rắc rối.

Khi bạn đã xác định các khu vực để làm việc, sau đó cố gắng tìm hiểu vấn đề thực sự là gì. Có những cuốn sách có một cách tiếp cận có hệ thống để phân loại các vấn đề thiết kế. Nhìn vào Tái cấu trúc của Martin Fowler , Tiêu chuẩn mã hóa C ++ của Herb Sutter , Bộ luật sạch của Robert Martin , v.v. Họ có một loạt các "quy tắc" cho phép bạn nhìn vào mã của mình một cách khách quan.

Khi bạn đã xác định được vấn đề có thể xảy ra, hãy thử các cách khác nhau để khắc phục nó. Ví dụ: nếu quy tắc bạn đã phá vỡ là "thích sáng tác hơn kế thừa", thì hãy thay đổi quy tắc thành thành phần và xem cảm giác của nó.

Rõ ràng, nó có thể hữu ích nếu có ai đó nhìn vào mã này, nhưng nó không phải luôn luôn là hữu ích như bạn nghĩ, bởi vì bạn là nhiều hơn quen với loại vấn đề mã gây ra hơn bất cứ ai khác, và lý do đằng sau việc thiết kế . Học một số cách để đánh giá khách quan thiết kế của riêng bạn sẽ trả cổ tức lớn.


3
+10 cho tính trung thực của nhận xét "đồ ngốc". :)
Jennifer S

2
Liên quan đến cách tiếp cận dựa trên "quy tắc", chạy các công cụ phân tích tĩnh (ví dụ: lint cho C, JsLint cho JavaScript, Findbugs cho Java, FxCop cho .NET) thường có thể đưa ra gợi ý hữu ích và số liệu mã (ví dụ độ phức tạp chu kỳ, LCOM4) có thể hiển thị bạn những phần nào của mã có thể có vấn đề. Tất nhiên, bạn nên luôn luôn sử dụng bộ não của mình và nhận lời khuyên của các công cụ như vậy với một hạt muối.
Daniel Pryden

4

Có một người khác nhìn vào mã của bạn. Nếu bạn không thể tìm thấy một người khác để xem nó, hãy viết một mô tả đầy đủ về sự tương tác giống như bạn sẽ hiển thị nó cho người khác. Quá trình cố gắng giải thích quyết định của bạn cho người khác (ngay cả khi chỉ là thực tế) có thể giúp bạn thực sự nghĩ ra TẠI SAO bạn đang làm mọi thứ theo một cách nhất định và giúp bạn nhìn thấy bất kỳ lỗ hổng nào trong logic của bạn.


3
Tôi thấy rằng giải thích mọi thứ ngay cả với một người không có kỹ thuật là hữu ích. Nếu tôi có thể làm cho một người không lập trình hiểu thiết kế và giải thích thỏa đáng lý do tại sao người ta có thể cần một cửa sổ-nhà máy-nhà máy-nhà máy, thì có lẽ sẽ tốt khi sử dụng một nhà máy-nhà máy-nhà máy.
Leif Carlsen

4

Tôi biết tình huống này rất rõ. Khi tôi gặp khó khăn theo cách đó, tôi cố gắng đưa ra những quan điểm khác nhau về dự án.

1.) Quan điểm của người dùng / khách hàng - sử dụng phản hồi

Thật không may, chúng tôi bị cuốn vào mã của chúng tôi theo cách mà chúng tôi không thể nhìn thấy lỗ hổng của chính mình vì chúng tôi sử dụng các ứng dụng của mình theo cách chúng tôi đã mã hóa chúng. Nhìn vào cách mọi người sử dụng nó và cố gắng tìm ra hướng dẫn người dùng trực quan nhất sẽ là gì. Chơi xung quanh với các nguyên mẫu UI. Điều này có vẻ thú vị, nhưng nếu bạn phát hiện ra rằng bạn sẽ buộc phải mã hóa lại phần lớn mã của mình chỉ bằng cách thay đổi logic sử dụng hơn thời gian để bắt đầu chu trình thiết kế lại.

2.) Thực hiện phân tích chức năng mã của bạn và trực quan hóa nó

Một số IDE và khung công tác thúc đẩy bạn, ví dụ như trộn UI và mã phụ trợ. Nếu bạn để điều này xảy ra, một ngày nào đó bạn sẽ phải đối mặt với tình huống rằng cơ sở mã của bạn khó có thể được duy trì vì sự phụ thuộc mơ hồ và khó phá vỡ. Đặc biệt là trộn mã UI với mã khác có thể dẫn đến mã spaghetti và chức năng dự phòng. Chia mã của bạn trong các khối chức năng, ví dụ như các lớp cơ sở dữ liệu, các lớp truyền thông, các lớp UI, các lớp lõi, v.v. và đưa ra các khối chức năng nói tên. Sau đó, trực quan hóa chức năng bằng một công cụ đồ họa (tôi sử dụng công cụ bản đồ tư duy) để tìm hiểu xem cấu trúc của bạn có hợp lý và mô đun đủ để bạn có thể sử dụng lại các khối mã lớn cho các dự án khác nhau và bạn có thể thay thế chúng bằng các phiên bản mới hơn mà không cần Đau lớn.

Cách tốt nhất để làm điều này theo kinh nghiệm của tôi là tạo một tài liệu trực quan hóa tất cả các phụ thuộc giữa các lớp của bạn và các cuộc gọi của chúng từ mã của bạn. Kết quả là một hình dung của thiết kế giao diện của bạn. Nếu bản đồ mã này trông giống như một cụm hoàn chỉnh *** thì đã đến lúc hành động. Nếu chưa xảy ra, bạn nên nghĩ về một quy ước đặt tên phù hợp đại diện cho cấu trúc mã của bạn theo cách bạn không phải suy nghĩ về cách gọi nó và những gì nó làm.

3.) Sử dụng các phương pháp phổ biến để đảm bảo chất lượng

Yêu thích của tôi là FMEA. Về mặt mã hóa, điều này có nghĩa là không chỉ phân tích những gì đã sai trong quá khứ mà còn nghĩ về những gì có thể sai. Một ví dụ khá phổ biến là kết nối mạng bị mất đột ngột. Sau khi thực hiện xong, bạn có thể phân loại các điều kiện lỗi theo các hậu quả như mất dữ liệu, sự cố, tính toán sai và phán đoán tác động đối với người dùng. Nếu chưa được thực hiện, việc xác định lỗi và các lớp ngoại lệ được sắp xếp hợp lý có thể giúp bạn giữ mã của mình sạch sẽ và thẳng. Cách tốt nhất là triển khai những thứ đó trong mỗi mã mới trước khi bắt đầu viết bất cứ thứ gì khác. (Chà, tôi có tội không phải lúc nào cũng làm theo lời khuyên này.)

Ngoài ra, nó giúp tôi tạo và thường xuyên cập nhật "danh sách đề xuất cải tiến" cho mã của riêng tôi. (Thành thật mà nói, vẫn còn rất nhiều mã trong các dự án của tôi, tôi chắc chắn không tự hào.) Tôi cũng cố gắng dành thời gian để thu thập và xem mã thực tiễn tốt nhất từ ​​tài liệu API, hội nghị nhà phát triển hoặc tạp chí nhà phát triển.

Cho đến thời điểm này, không cần phải chạm vào mã của bạn. Nó chỉ đơn giản là nhận thức được những gì đang sai và tìm cách xác định cách cải thiện mã của bạn.

Cuối cùng một số lời khuyên cho công việc hàng ngày từ một cái rắm cũ. Cố gắng tránh cắn nhiều hơn bạn có thể ăn. Điều này dẫn đến quá nhiều áp lực cho mã hóa sạch. Bạn hiếm khi có được thời gian để làm điều đó đúng, nhưng bạn sẽ phải dành thời gian để sửa các lỗi sau đó.

Không có gì là lâu dài như giải pháp tạm thời, nhưng khi nó bị hỏng thường là muộn để khắc phục kịp thời. Ví dụ là các bản hack khó chịu hoặc các ngoại lệ lạ mà tôi đã sử dụng để làm cho một cái gì đó hoạt động mặc dù ví dụ như một lỗ hổng trong khung hoặc hệ điều hành cơ bản. Và sau đó, lỗ hổng đã được sửa hoặc phiên bản mới chỉ cần bỏ API API

Nếu bạn bị mắc kẹt và bị buộc phải tìm cách giải quyết hơn là đưa ra nhận xét và ghi chú cần được xem xét lại theo thời gian. Thông thường chúng ta ngày càng tốt hơn vì học được điều gì đó mới. Nếu bạn tìm thấy một cách tốt hơn để thực hiện nó nhanh nhất có thể. Nếu không, bạn có thể thấy mình mã hóa cách giải quyết cho cách giải quyết và ngoại lệ một ngày nào đó. (Anh ta không có tội lỗi giữa các bạn, hãy để anh ta ném byte đầu tiên vào tôi.)


2

Đừng đổ mồ hôi những thứ nhỏ nhặt.

Mọi người có thể viết mã tốt hơn. Chúng tôi làm mọi thứ nhanh chóng và sau đó nhận ra một vài tuần sau đó nó có thể được thực hiện hiệu quả hơn. Vấn đề là 90% mã của bạn có thể đủ tốt.

Xem qua nhật ký lỗi của bạn và tìm các thói quen có thể gây ra sự cố. Khi bạn tìm thấy các lỗi, bạn cũng có thể xem lại mã và suy nghĩ về những gì có thể làm cho mã hiệu quả hơn. Hầu hết thời gian, bạn sẽ nhận ra rằng ngoài việc tự sửa lỗi, bạn sẽ không thể cải thiện đáng chú ý, nhưng đôi khi, bạn sẽ nhận ra rằng có một cách tốt hơn để làm điều gì đó.

Nói chuyện với người dùng và xem họ đang gặp vấn đề gì, cả vấn đề về UX hay tốc độ. Khắc phục các sự cố này, với một mắt để cố gắng cải thiện mã của bạn.

Tại một số điểm, bạn sẽ phát hiện ra rằng mã của bạn đã trở nên quá dễ vỡ và đơn giản là không có cách nào để thực hiện các thay đổi mà bạn cần phải làm. Sau đó suy nghĩ về cách bạn có thể làm cho hệ thống linh hoạt hơn, thông qua API hoặc phát triển theo hướng thử nghiệm. Trong nhiều trường hợp, bạn sẽ phát hiện ra rằng bạn chỉ có thể bắt đầu đưa các API này vào mã, với số lượng thay đổi không lớn. Trong các trường hợp khác, bạn sẽ nhận ra rằng nỗ lực cải thiện mã không xứng đáng.

Thay đổi tăng dần có thể khó khăn. Mục tiêu là không hoàn toàn viết lại cơ sở mã nếu bạn không phải làm vậy. Chắc chắn, bây giờ bạn là một lập trình viên giỏi hơn bạn một năm trước, nhưng những gì bạn phải làm việc ngay bây giờ. 5 năm kể từ bây giờ, khi một lập trình viên cơ sở phàn nàn với bạn về mã kế thừa họ phải cố gắng sửa, chỉ cười và gật đầu, và không thừa nhận rằng bạn đã viết nó.


1

Bạn đã cân nhắc rời khỏi và tìm một công ty nơi bạn có thể ở trong một nhóm chưa? Tôi cảm thấy rất mạnh mẽ rằng bị cô lập hoặc trong một nhóm trì trệ, các nhà phát triển bỏ lỡ rất nhiều nghề nghiệp phải cung cấp.

Đánh giá ngang hàng cho phép một người đã ở ngoài đầu cho lời khuyên của bạn. Đánh giá mã trao đổi ngăn xếp có thể là một nơi tốt để đưa một số mã không đặc biệt thuộc sở hữu của công ty bạn ra để xem xét. Nó có thể không thể xử lý các khối lớn, nhưng nhiều chương trình được tạo từ rất nhiều mã đơn giản và một số mã khác không đơn giản và tạo ra nhiều vấn đề. Nếu bạn có một ví dụ về một số mã điển hình, nhưng được lặp lại và thay đổi nhiều nơi, thì đó cũng có thể là một ứng cử viên đánh giá tốt. Ví dụ: nếu bạn định dạng tin nhắn, đừng yêu cầu xem lại tất cả tin nhắn, chỉ một tin nhắn ví dụ khá phức tạp.

Nếu bạn muốn khách quan hơn về mã của riêng mình, tôi đoán bạn có thể so sánh nó với một tiêu chuẩn mã hóa, chạy trình kiểm tra mã tĩnh hoặc động trên nó hoặc nếu bạn được ghi chép lại một cách thưa thớt, việc thêm nhận xét có thể giúp ích.

Có một tâm lý kiểm tra khiến bạn khó kiểm tra mã của riêng mình nhưng chúng tôi chắc chắn cố gắng hết sức để làm như vậy trong quá trình kiểm tra đơn vị. Đọc mã của riêng bạn có thể là một vấn đề tương tự, hoặc tồi tệ hơn. Nhiều lĩnh vực sử dụng cố vấn, đánh giá cạnh tranh, huấn luyện viên, vv Chúng tôi cũng vậy nếu bạn tính kiến ​​trúc sư, kỹ sư hệ thống và người thử nghiệm. Khách hàng có quyền truy cập vào một công cụ báo cáo lỗi hoặc bộ phận hỗ trợ khách hàng sẽ cung cấp cho bạn thông tin phản hồi từ bên ngoài đầu của bạn sau khi sản phẩm được cung cấp. Đây là một lý do tuyệt vời khác cho cách tiếp cận phát hành sớm và thường xuyên của Agile. Bạn có thể là nhà phát triển duy nhất trong công ty của bạn, nhưng có những người bị ảnh hưởng bởi mã của bạn, người có thể cung cấp cho bạn phản hồi về nó từ một số góc độ.


0

"Đây có phải là một vấn đề nhỏ hơn tôi nghĩ, hay đây cũng là một vấn đề mà người khác gặp phải?"

Sheesh. Đã đủ. Nếu mã được sản xuất, không có lỗi và làm những gì nó phải làm, kiến ​​trúc là không quan trọng. Ít nhất là bây giờ.

Tất cả chúng tôi hy vọng học hỏi khi chúng tôi đi. Tôi đã viết rất nhiều mã mà tôi tự hào vào thời điểm tôi viết nó, chỉ để quyết định rằng nó là khủng khiếp một hoặc hai năm sau đó. Ngay bây giờ tôi đang làm việc trong một dự án nhiều năm với đầy mã cực kỳ khủng khiếp, nhưng mã này hoạt động. Tôi đang thực hiện một cách tiếp cận rất bảo thủ để chạm vào bất kỳ của nó.

Và bạn cũng nên như vậy. Nếu bạn không thấy bất kỳ vấn đề kiến ​​trúc lớn nào ngay bây giờ, sau một năm làm việc, tôi nghĩ có thể an toàn cho bạn khi cho rằng, hiện tại, không có vấn đề quan trọng nào. Đây không phải là nghề thủ công xấu. Nó đang tiến về phía trước.


0

Ngoài các câu trả lời khác, tôi khuyên bạn nên tham dự một hội nghị dành cho nhà phát triển.

Điều này sẽ đưa bạn đến rất nhiều chủ đề và những người sẽ khiến bạn suy nghĩ về ứng dụng và nơi làm việc của riêng bạn. Đặc biệt là khi họ sẽ nói về những gì hoạt động và không cho sau đó, và các vấn đề phát sinh. Có khả năng lớn là có một số trùng lặp với ứng dụng của bạn.

Tốt nhất, mất 3 ngày cho việc này. Tôi đã thấy rằng đủ dài để có được khoảng cách tinh thần cần thiết cho công việc của riêng tôi và nhìn nó qua con mắt của một cộng đồng lớn hơn (có thể nói), chứ không phải là của riêng tôi.

Ngẫu nhiên, điều này cũng áp dụng cho các nhóm người, vì nhóm có thể xảy ra ở bất cứ đâu.

Cuối cùng, nếu bạn không được chấp thuận cho việc này, hãy nói một lần mỗi năm, thay đổi công việc.


-1
  • Thực hành các mẫu thiết kế và thực hành tốt nhất
  • Chọn một khung, công cụ, gói vv dựa trên yêu cầu và nhu cầu ứng dụng của bạn - vì điều này bạn cần đọc nhiều blog etch và tìm giải pháp cho từng vấn đề công nghệ riêng lẻ
  • Tạo dự thảo thiết kế / kiến ​​trúc và thảo luận với một người giỏi về kỹ thuật / kiến ​​trúc. Cải thiện dự thảo này bằng cách sử dụng thông tin phản hồi và ý kiến. tiếp tục làm điều này cho đến khi bạn đạt được trạng thái ổn định.
  • Triển khai mã sao cho mọi thứ mà ứng dụng cần đều có thể cấu hình và duy trì được

    kiến trúc lại và thực hiện lại dự án của bạn chắc chắn sẽ giúp ứng dụng có tính nhất quán, hiệu suất tốt hơn, v.v.


-1

Tôi tin rằng 'đá xung quanh' mối quan tâm với một vài người thông minh sẽ giúp ích. Cần phải có thông tin cụ thể. Đây có phải là trang web 24x7x365 không? Ứng dụng LoB? Nó đang chạy hoặc được lưu trữ ở đâu?

Khi bạn nhận được vào các mục tiêu cốt lõi và kết quả mong muốn, những người khác có thể giúp tập trung và hướng sự chú ý của bạn. Mã của bạn có thể là mã tốt nhất từng được viết cho một tác vụ cụ thể - hoặc tệ nhất. Nó thực sự không quan trọng - điều đó ảnh hưởng đến mục tiêu mong muốn như thế nào?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.