Là định danh ngắn xấu? [đóng cửa]


26

Là định danh ngắn xấu? Làm thế nào để độ dài định danh tương quan với hiểu mã? Những yếu tố nào khác (ngoài việc hiểu mã) có thể được xem xét khi nói đến việc đặt tên định danh?

Chỉ cần cố gắng để giữ chất lượng của các câu trả lời, xin lưu ý rằng đã có một số nghiên cứu về chủ đề này!

Chỉnh sửa

Tò mò rằng mọi người đều không nghĩ rằng độ dài có liên quan hoặc có xu hướng thích số nhận dạng lớn hơn, khi cả hai liên kết tôi cung cấp cho thấy số nhận dạng lớn đều có hại!

Liên kết bị hỏng

Liên kết dưới đây chỉ ra một nghiên cứu về chủ đề này, nhưng giờ nó đã bị hỏng, tôi dường như không có một bản sao của bài báo với tôi, và tôi không nhớ nó là gì. Tôi sẽ để nó ở đây trong trường hợp người khác tìm ra nó.


5
Điểm dữ liệu. Định danh ngắn yêu thích của tôi là :, như trong :(){ :;:& };:- Tôi muốn nói rằng hầu hết mọi người nghĩ rằng nó khá tệ. ;)

@fennec: Bom ngã ba có xu hướng.
Josh K

Kiểm tra câu hỏi này của stackoverflow có một nhận xét về Thực hành lập trình một cuốn sách mà mọi lập trình viên nên đọc.
slu

1
Chỉ vì nên tránh những cái tên dài hơn không có nghĩa là bạn nên nỗ lực thêm để rút ngắn chúng vì sự ngắn gọn.
JeffO

1
@cessor Hài hước rằng một cái gì đó được dự định là về nghiên cứu đã bị đóng cửa dựa trên quan điểm. Đáng buồn thay, tôi đồng ý, đưa ra câu trả lời mà nó nhận được.
Daniel C. Sobral

Câu trả lời:


67

"Quy tắc" tốt nhất mà tôi đã nghe là độ dài tên phải tỷ lệ thuận với độ dài của phạm vi của biến. Vì vậy, một chỉ số ilà tốt nếu phần thân của vòng lặp dài một vài dòng, nhưng tôi thích sử dụng một cái gì đó mô tả hơn một chút nếu nó dài hơn 15 dòng.


6
Tôi chưa bao giờ nghe về một điều như vậy và tôi không nghĩ rằng nguyên tắc này sẽ cải thiện khả năng đọc mã.
NimChimpsky

8
@Nim: Tôi đồng ý. Ngay cả trong một forvòng lặp ngắn , tôi sẽ đặt tên cho chỉ mục customerCounterhoặc một cái gì đó. Nó cần nỗ lực thêm tối thiểu và làm cho mã của bạn tốt hơn rất nhiều. Sử dụng các biến ngắn cho một phạm vi ngắn nghe có vẻ là một cái cớ để lười biếng.
Không ai là

2
Hmm, nó không phải là một quy tắc hay một hướng dẫn đối với tôi mà là một cách khiến bạn suy nghĩ về chiều dài và trong bối cảnh đó, nó có ý nghĩa gì đó. Tôi chắc chắn không nghĩ đó là một cái cớ cho sự lười biếng (mặc dù tôi sẽ đồng ý rằng một số người có thể coi nó như vậy). Số nhận dạng của tôi thường dài hơn không (dấu hiệu được dạy pascal từ rất sớm) ngoại trừ bây giờ khi tôi nhận được những thứ như truy vấn linq và biểu thức lambda trong đó số nhận dạng 1, 2 hoặc 3 ký tự (thường là tên viết tắt) dường như có ý nghĩa với tôi .
Murph

33
+1 Thành thật mà nói, một tên "mô tả" chỉ là tiếng ồn trong một vòng lặp năm dòng; Tôi nghĩ rằng hầu hết mọi người đều nắm bắt khá tốt về những gì bạn đang làm với "i". Tôi đã sử dụng tên mô tả trong các vòng lặp lồng nhau, nhưng những cái đó có phạm vi dài hơn.
Jeremy

18
+1 - Sử dụng ijtên phổ biến mà mọi nhà phát triển sẽ có thể hiểu IMO.
TheCloudlessSky

48

Mỗi biến nên có một ý nghĩa và tên của nó là một phần của ý nghĩa đó. Và một phần rất quan trọng, vì nó giúp người đọc hiểu được nó dùng để làm gì mà không đào sâu vào thuật toán. i, jrõ ràng là được sử dụng như chỉ số, chúng ngắn, nhưng rất nhiều thông tin. bntlà xấu xí, closehoặc closeButtoncó ý nghĩa. Vì vậy, ngắn hay dài không phải là tiêu chí quan trọng nhất cho tên biến, nó phải có ý nghĩa. Ý nghĩa mạnh mẽ phụ thuộc vào bối cảnh. Ví dụ: bạn có thể đặt một tên rất ngắn như nbiến chuỗi cục bộ được sử dụng trong một khối nhỏ của mã nói 10 dòng và đề cập đến tên của một thuộc tính ( vđối với giá trị là một ví dụ khác).

Vì vậy, tên biến nên có nhiều thông tin và không quan trọng chúng ngắn hay dài .


2
+1 và chỉ cần lưu ý, đóng và đóngButton cũng không đồng nghĩa. Đóng là một động từ và do đó, nên là tên của hàm hoặc phương thức. Trong khi closeButton là một danh từ, và rõ ràng, nên là tên của nút kích hoạt chức năng đóng.
CaffGeek

close là một tính từ, vd close = true;)
Armand 8/12/2016

13

Tôi sẽ sử dụng một định danh mô tả biến, không phân biệt độ dài.

Các trường hợp của i, j và k là bản thân chúng rất phổ biến, chúng tự mô tả, bạn tự động biết chúng là các chỉ số vòng lặp. Bạn cũng có thể nói tương tự cho:

foreach loop (Strings s : myString)

Tuy nhiên, IDE hiện cung cấp các công cụ hoàn tất mã, do đó, tác dụng phụ tiêu cực duy nhất của các định danh mô tả rất dài và đã được loại bỏ afaik.

Tôi sẽ vui vẻ thêm và thêm từ vào một định danh, nếu nó được yêu cầu để giải thích mục đích của biến.


3
BTW, việc sử dụng i, j và k cho các chỉ báo vòng lặp trở lại hơn 50 năm trước FORTRAN. Các biến bắt đầu bằng các chữ cái tôi thông qua N theo mặc định là kiểu INTEGER. Các biến bắt đầu bằng bất kỳ chữ cái nào khác theo mặc định là REALs. Điều này tự nhiên dẫn đến việc sử dụng I, J và K cho các chỉ số for-loop. (Quy ước FORTRAN có lẽ xuất phát từ việc sử dụng các biến này được sử dụng trong các phương trình toán học trước đó.)
tcrosley

2
Bài báo thứ hai mà tôi liên kết đã chỉ ra rằng các định danh mô tả rất dài làm giảm khả năng hiểu mã của một người, mâu thuẫn với nhận xét "chỉ có tác dụng phụ tiêu cực".
Daniel C. Sobral

3
Tác dụng phụ tiêu cực thực sự của các định danh rất dài là ở khả năng đọc. Thật khó để nói nhanh rằng hai số nhận dạng rất dài giống nhau hay khác nhau và thật khó để chọn ra tất cả các yếu tố của một biểu thức có số nhận dạng rất dài.
David Thornley

tcrosley - Tôi muốn nói thêm rằng chỉ vì nó đến từ Fortran không có lý do gì để tiếp tục thực hành như vậy. Tôi đặc biệt không khuyến khích việc sử dụng các bộ đếm vòng lặp / vòng lặp được gọi là "i", "j", "k", v.v ... Đó là sự lười biếng trí tuệ đơn giản. Tuyệt vời <> tốt.
quick_now

9

Chúng không tệ như các định danh sai lệch. Tôi không ngại mã gỡ lỗi trong đó các mã định danh chỉ có một chữ cái, nhưng khoảnh khắc các quy ước đặt tên khác nhau xuất hiện trong bức tranh, nó trở nên khó chịu. Ví dụ, nếu một nơi nào đó bạn nhìn thấy strPersonID, và sau đó ở một nơi khác bạn nhìn thấy s_EmployeeID, thì thật khó hiểu để biết liệu cả hai chuỗi này và liệu có sự khác biệt nào không. Ngoài ra nếu các biến được sao chép-dán ( pmapIntString = new std::map<int,int>) và hoàn toàn sai, tôi sẽ lo lắng.

Khi nói đến tôi, tôi thêm nhận xét trong mã cho các biến quan trọng được sử dụng và cố gắng duy trì tiêu chuẩn được đưa ra trong hướng dẫn phát triển. Nếu không có tiêu chuẩn thì tôi cố gắng duy trì quy ước đặt tên giống nhau trong suốt mã.


5

Tôi đấu tranh...

Tôi sử dụng để luôn sử dụng tên mô tả làm định danh, nhưng cuối tôi đã sử dụng các định danh rất ngắn.

Tôi nghĩ rằng, nó phụ thuộc vào ngữ cảnh của mã:

  • Nếu bạn viết các hàm phức tạp (thuật toán), thì LUÔN LUÔN sử dụng các định danh ngắn (ký tự đơn là tốt nhất)
  • Khi viết các giá trị tham số cho các hàm sử dụng tên mô tả.

Tôi đoán nó phụ thuộc vào mức độ dày đặc của mã. Đôi khi có tên thực sự làm cho nó khó đọc hơn.

Đôi khi không có tên hoàn toàn khó hiểu!


1
Tuy nhiên, nếu bạn đang viết các thuật toán phức tạp, bạn có muốn các mã định danh mô tả nhiều hơn cho những người nhìn vào mã của bạn lần đầu tiên không?
Tối đa

Khi nào một định danh nhân vật duy nhất bao giờ thích hợp?
Amir Afghani

1
Tôi cũng từng nghĩ vậy, nhưng tôi thực sự thấy đây không phải là vấn đề, hãy tự mình thử. Lấy một thuật toán phức tạp và thử với các tên mô tả so với các biến chữ cái đơn.
Đêm tối

1
Tôi đồng ý nhưng chỉ với một công thức phức tạp dài hơn, bởi vì chúng có xu hướng quá dài và thậm chí sau đó bạn có thể sử dụng các hàm (tên hàm) để mô tả các phần của công thức đó là gì.
Emile Vrijdags

1
Nếu nó phức tạp và có các mẫu, các mẫu đó sẽ được chia thành các hàm
CaffGeek

3

Suy nghĩ của tôi là bản thân họ không xấu nhưng họ không thông minh trừ khi họ rất chuẩn.

Vì vậy, các biến vòng lặp là i, jk chuẩn đến mức không có lý do gì để không sử dụng chúng nếu bạn đang tạo một vòng lặp được lập chỉ mục.

Một nơi khác tôi sẽ sử dụng một định danh rất ngắn là khi tôi khai báo một biến tạm thời sẽ vượt ra khỏi phạm vi trong một vài dòng thời gian - ví dụ, biến tạm thời từ một vòng lặp foreach. Nếu nó sẽ không được đề cập đến bất cứ nơi nào khác thì thật dễ dàng cho bất cứ ai đọc mã để xem khai báo và làm theo những gì nó đang được sử dụng cho. Tuy nhiên, nếu nó sẽ được sử dụng cho hơn năm hoặc sáu dòng, tôi sẽ tìm cách đặt cho nó một cái tên rõ ràng hơn.

Ngoài ra, tôi cố gắng sử dụng các định danh độ dài thông tin - đặc biệt ở cấp độ lớp tôi muốn một mã định danh mà bạn có thể đọc và có ý tưởng về biến số đó dùng để làm gì. Nếu chúng trở nên quá dài (và đôi khi tôi thấy mã có bốn hoặc năm từ được xâu chuỗi lại cho một mã định danh) Tôi có xu hướng coi đó là mùi mã - nếu tôi cần nhiều văn bản để phân biệt các biến của mình thì chúng thực sự là một nhóm có thể được lưu trữ tốt hơn trong một hashmap hoặc danh sách? Tôi có thể tạo một số loại đối tượng để mô hình hóa dữ liệu này chính xác hơn không? Đôi khi bạn không thể nhưng một định danh rất dài là một chỉ báo cho thấy có một cái gì đó đáng xem ở đây.


3

Tôi đồng ý rất nhiều với các câu trả lời khác ở đây, nhưng muốn chỉ ra một yếu tố khác mà tôi nghĩ là thường bị bỏ qua. Một tên hay thường là một tên thành ngữ cho mã. Điều này có thể ở cấp độ ngôn ngữ, cấp độ thuật toán hoặc một số thành ngữ nội bộ cho cơ sở mã trong tay. Vấn đề là trong khi tên có thể không có ý nghĩa gì với người không biết tên miền của mã, thì nó vẫn có thể là tên tốt nhất trong ngữ cảnh cụ thể.


3

Đặt tên một biến luôn là một bài tập trong việc cân bằng tính độc đáo và dễ hiểu. Độ dài của tên có liên quan đến cả hai, theo những cách khác nhau. Tên dài hơn dễ làm cho độc đáo; tên có độ dài trung bình có xu hướng dễ hiểu hơn so với tên quá ngắn hoặc quá dài.

Một tên biến rất ngắn chỉ hữu ích nếu nó có một lịch sử mà làm cho nó dễ hiểu (ví dụ i, j, & kcho chỉ số; dxcho một khoảng cách dọc theo một trục) hoặc một phạm vi đó là đủ nhỏ cho tất cả các tài liệu tham khảo để được nhìn thấy cùng một lúc (ví dụ như , temp) Các tên biến tồi tệ nhất trên thế giới là những thứ như thế t47. ("Điều đó có nghĩa là gì và tại sao nó khác với t46?") Cảm ơn chúa vì phong cách đặt tên chủ yếu xuất hiện với FORTRAN, nhưng đây là nơi mong muốn về các tên biến dài hơn được bắt nguồn.

Như bài báo gốc của bạn cho thấy, những cái tên quá dài cũng khó đọc, vì những khác biệt bên trong tinh tế có thể bị bỏ qua khi liếc vào mã. (Sự khác biệt giữa DistanceBetweenXAxisAbscissae& DistanceBetweenYAxisAbscissaethực sự rất khó để nhận nhanh.)

Như NoteToSelf đã chỉ ra trước đó, các yêu cầu về tính duy nhất của tên phụ thuộc chủ yếu vào phạm vi mà tên phải là duy nhất. Chỉ số của một vòng lặp 5 dòng có thể là i; một chỉ mục của một bản ghi hoạt động được truyền từ chức năng này sang chức năng tốt hơn có một tên mô tả nhiều hơn.

Một biến cục bộ cho một hàm có thể có một tên mô tả nhỏ như deltaXkhông có vấn đề. Biến delta X tĩnh trong mô-đun phải có tên phân biệt deltaX này với deltaX khác trong cùng mô-đun, làm cho nó dài hơn. Và một biến delta X toàn cầu phải được tạo thành duy nhất trên tất cả các mô-đun và tất cả các mô-đun khác có thể được tạo, có thể bằng cách ghép tên mô-đun với tên mô tả khác. Đây là một trong nhiều vấn đề với toàn cầu; để độc đáo một cách hữu ích, các tên phải đủ dài để làm cho chúng khó đọc.


2

Ngược lại, tôi nghĩ số nhận dạng dài còn tệ hơn số nhận dạng ngắn (trừ khi bạn giao dịch với hằng số). Việc sử dụng TheVariableThatHoldsTheCapacityOfMyContainerClasslàm cho mã của bạn dễ bị lỗi hơn rất nhiều so với sử dụng Capacity.


1
Bạn sẽ rất vui khi biết rằng một trong những nghiên cứu mà tôi liên kết hỗ trợ lý luận của bạn, nếu không phải vì những lý do tương tự, sau đó. ;-)
Daniel C. Sobral

1
Thật dễ dàng để đọc sai các định danh rất dài, có thể gây nhầm lẫn cho họ hoặc có thể không nhận ra rằng hai trong số đó là giống nhau.
David Thornley

2
TheVariableThatHoldTheCapacityOfMyContainerClass lớn hơn tôi nghĩ là "dài" - mười từ là quá dài để CamelCase giúp đỡ; bạn cần không gian để có thể đọc được.
Richard Gadsden

1
Chắc chắn, nhưng đây là một người đàn ông rơm. Ví dụ của bạn về một tên dài thêm verbiage nhưng không có thông tin. Hãy xem xét trường hợp bạn có nhiều biến liên quan đến các dạng năng lực khác nhau. Sau đó, bạn thực sự có thể muốn các tên phân biệt các mục đích, như initalCapacity hoặc FinalCapacity.
Charles E. Grant

2
@Maxpm, var total = Capacity + Capacity2; Cái gì Capacitychứa, và cái gì Capacity2chứa? Chúng sẽ được sử dụng để làm gì? Phải tìm kiếm manh mối bối cảnh lãng phí thời gian. Trong khi đó nếu nó được viết như var totalStorageCapacity = truckCapacity + trailerCapacity;tôi biết những gì chúng ta đang nói về.
CaffGeek

2

Trong và của chính họ, định danh ngắn không phải là xấu. Mục đích của việc chọn tên tốt (ngắn hoặc dài) là để phục vụ cho sự rõ ràng của mã. Việc chọn định danh trong dịch vụ về độ rõ của mã quan trọng hơn việc đáp ứng một số yêu cầu về độ dài tối thiểu. Nói chung điều này có nghĩa là viết tên dài hơn một chút có ý nghĩa.


+1 bạn đã nói rất hay, tôi không thể tìm thấy lời của mình khi tôi viết câu trả lời :-)
ComputerSaysKhông

1

Một quan sát mà tôi đã có trong nhiều năm và ngày nay nó ít hơn so với 10 hay 15 năm trước. Các lập trình viên không thể gõ là người sẽ chiến đấu với bạn bằng cách đặt tên thay đổi. Họ là những người có tất cả các tên biến 1-3 chữ cái.

Vì vậy, lời khuyên của tôi là sử dụng một tên có ý nghĩa như nhiều người bình luận đã nói và sau đó học cách gõ. Tôi đã xem xét việc thêm một bài kiểm tra đánh máy vào các cuộc phỏng vấn, chỉ để xem mọi người đang ở đâu, nhưng tôi bắt đầu thấy ít hơn những người không đánh máy khi máy tính trở thành một phần lớn của xã hội.


2
Tôi đã thấy không có mối tương quan như vậy, thực sự. Nếu bất cứ điều gì có vẻ như mọi người từ các ngôn ngữ OO đi cho các định danh dài và những người từ ngôn ngữ chức năng đi cho các ngôn ngữ ngắn. Nó đặt câu hỏi về cáo buộc rằng OO giúp mô hình hóa. :-)
Daniel C. Sobral

Đừng quên rằng tên không chỉ cần được gõ mà còn được đọc. Sử dụng định danh quá dài thực sự có thể làm giảm khả năng đọc rất nhiều. Sử dụng bất cứ điều gì nhưng itrong một vòng lặp như thế for (int i=0; i<dst.size(); ++i) dst[i] += src[i]nên bị cấm theo luật.
maaartinus

1

Bài báo đầu tiên bạn liên kết có vẻ thú vị, nhưng kết luận của nó là họ không tìm thấy bằng chứng quan trọng nào cho hoặc chống lại giả thuyết rằng "gợi ý căn cứ", bao gồm các tên biến có ý nghĩa, giúp hiểu mã. Cái nhìn được sử dụng trong thời gian như một proxy để hiểu mã rất thú vị, nhưng không phải là một cú đánh trượt.

Tôi sợ tôi tìm thấy tờ giấy thứ hai chỉ là ngớ ngẩn. Vấn đề đầu tiên là các ví dụ về tên dài mà họ cung cấp dài vô cớ, không cung cấp thêm thông tin. Tôi nghĩ rằng tất cả chúng ta có thể đồng ý rằng làm cho một tên biến dài hơn chỉ để làm cho nó dài hơn là ngu ngốc. Ví dụ của họ về việc đặt tên một khoảng cách biến_b between_abscissae thay vì dx là một người rơm.

Quan trọng hơn, thí nghiệm của họ là một bài kiểm tra ghi nhớ đơn giản hơn là hiểu. Nó kiểm tra khả năng của các đối tượng để điền vào các phần còn thiếu của một tên biến khi được trình bày trong một danh sách không có ngữ cảnh. Đúng, tên dài hơn khó ghi nhớ hơn, nhưng khi tôi viết mã tôi không ghi nhớ tên biến, tôi sử dụng chúng để cung cấp ngữ cảnh. Tôi cho rằng bạn có thể lập luận rằng khó khăn trong việc ghi nhớ biến dài làm cho mã khó viết hơn, nhưng mã được đọc thường xuyên hơn nhiều so với viết, vậy hoạt động nào cần được tối ưu hóa?


Lưu ý rằng bài báo thứ hai nêu rõ rằng "Tám tên được sử dụng trong tám câu hỏi đã được trích xuất từ ​​mã sản xuất." Ngoài ra, họ không kiểm tra ghi nhớ một mình, mà còn cho chính xác.
Daniel C. Sobral

1

Một trong những số liệu chính của tôi để xác định xem một dòng mã có thể đọc được hay không là bao nhiêu bối cảnh khác từ các dòng khác phải được đọc để thực sự chắc chắn rằng bạn hiểu dòng đó đang làm gì.

Thật dễ dàng để nói rằng "bất cứ ai cũng có thể hiểu rằng i, j và k là các biến vòng lặp". Và hầu hết các lần nó thực sự rõ ràng. Nhưng tôi vẫn cố gắng khiêm tốn và chuyên nghiệp về điều này và cho rằng thật dễ mắc sai lầm khi lập trình. Vì vậy, nếu tôi lặp qua một mảng Grobble, tôi sẽ đặt tên cho biến vòng lặp là grobble Index. Tôi cũng có thể chấp nhận tôi là một từ viết tắt của chỉ mục. Khi bạn đang sử dụng ij và k, sẽ khó phát hiện ra lỗi hơn như sử dụng chỉ mục sai với mảng sai, v.v. Và nó thậm chí còn tồi tệ hơn khi bạn có một vòng lặp bên trong.

Tái bút Tại thời điểm tôi viết câu trả lời này, tôi đã mã hóa một số javascript trên máy tính xách tay mini 10 "với màn hình chia theo chiều dọc trong vim và tôi vẫn dành thời gian để đặt tên cho các biến vòng lặp của mình là row Index và cột Index.


0

Trong một số ứng dụng, một biến ngắn chỉ đơn giản là không thể giải thích dữ liệu trong biến đó. Ngắn hay dài là không liên quan. Sử dụng một biến dài hơn không làm cho mã của bạn chậm hơn. Chắc chắn sẽ nỗ lực hơn khi gõ một tên biến dài nhưng ít nhất người đọc mã 6 tháng sau (có thể là bạn) sẽ có thể biết được chuyện gì đang xảy ra mà không cần phải đặt dấu vết cho rằng điều đó thậm chí có thể xảy ra.


0

Tôi nghĩ lý tưởng là tên nên được mô tả trừ khi ...

Ý tưởng rằng các tên có thể (có thể nên) ngắn hơn - và do đó bằng cách ngụ ý ít mô tả hơn - nếu chúng có phạm vi giới hạn chỉ là một lý do để đi chệch khỏi lý tưởng.

Cá nhân tôi thường sử dụng tên ngắn cho một số lượng nhỏ các thực thể được tham chiếu nhiều lần. Ví dụ, thường được gọi là chương trình con dành riêng cho ứng dụng.


-2

Tôi sẽ không bao giờ sử dụng tên định danh có ít hơn 4-5 ký tự, ví dụ: biến vòng lặp có thể là Index hoặc j Index hoặc k Index tùy thuộc vào số lượng vòng lặp bên trong tôi cần để thực hiện một cái gì đó, nhưng đối với các tên khác, hãy nói "khóa" tôi sẽ sử dụng "Chuỗi LKey" hoặc "int LKey", "L" cho cục bộ nếu đó là biến phương thức hoặc "F" cho biến lớp riêng, tất cả các định danh khác như được đề cập trước tôi nên giải thích lý do tồn tại trong tên của nó, nếu không thì Phạm vi "định danh" là vô dụng phải không?!


5
Những thông tin bổ sung nào "chỉ mục" truyền đạt rằng "i" không? Tên biến dài không cho bạn biết bất cứ điều gì tồi tệ hơn tên một ký tự.
Anon.

2
Gần đây đã viết một số thứ hoạt động trên lưới 3d, tôi có nhiều biến có tên x, y và z. Với bối cảnh họ đã được mô tả hoàn hảo.
Loren Pechtel
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.