it-swarm-vi.com

Những "thực hành tốt nhất" phổ biến nào không phải lúc nào cũng tốt nhất, và tại sao?

"Thực hành tốt nhất" ở khắp mọi nơi trong ngành công nghiệp của chúng tôi. A Tìm kiếm trên Google về "thực hành tốt nhất về mã hóa" tăng gần 1,5 triệu kết quả. Ý tưởng dường như mang lại sự thoải mái cho nhiều người; Chỉ cần làm theo hướng dẫn, và mọi thứ sẽ trở nên tốt đẹp.

Khi tôi đọc về a cách thực hành tốt nhất - ví dụ, tôi chỉ đọc qua vài lần trong Clean Code gần đây - Tôi cảm thấy lo lắng. Điều này có nghĩa là tôi nên luôn luôn sử dụng thực hành này? Có điều kiện kèm theo? Có những tình huống mà nó có thể không là một thực hành tốt? Làm thế nào tôi có thể biết chắc chắn cho đến khi tôi biết thêm về vấn đề này?

Một số thực tiễn được đề cập trong Mã sạch không phù hợp với tôi, nhưng tôi thực sự không chắc đó có phải vì chúng có khả năng xấu hay không, hoặc đó chỉ là sự thiên vị cá nhân của tôi. Tôi biết rằng nhiều người nổi bật trong ngành công nghệ dường như nghĩ rằng không có thực tiễn tốt nhất , vì vậy ít nhất những nghi ngờ dai dẳng của tôi đặt tôi vào một công ty tốt.

Số lượng thực tiễn tốt nhất tôi đã đọc chỉ đơn giản là quá nhiều để liệt kê ở đây hoặc đặt câu hỏi riêng lẻ, vì vậy tôi muốn diễn đạt điều này như một câu hỏi chung:

Những thực hành mã hóa nào được gắn nhãn phổ biến là "thực tiễn tốt nhất" có thể không tối ưu hoặc thậm chí có hại trong một số trường hợp nhất định? Những hoàn cảnh đó là gì và tại sao họ làm cho việc thực hành trở nên nghèo nàn?

Tôi muốn nghe về các ví dụ và kinh nghiệm cụ thể.

100
Steven Evers

Tôi nghĩ rằng bạn đã đánh vào đầu với tuyên bố này

Tôi ghét lấy mọi thứ theo mệnh giá và không nghĩ về chúng một cách nghiêm túc

Tôi bỏ qua gần như tất cả các Thực tiễn Tốt nhất khi nó không đi kèm với lời giải thích về lý do tại sao nó tồn tại

Raymond Chen đưa nó tốt nhất vào bài viết này khi anh ấy nói

Lời khuyên tốt đi kèm với một lý do để bạn có thể biết khi nào nó trở thành lời khuyên tồi. Nếu bạn không hiểu tại sao nên làm gì đó, thì bạn đã rơi vào cái bẫy của lập trình sùng bái hàng hóa, và bạn sẽ tiếp tục làm nó ngay cả khi không còn cần thiết hoặc thậm chí trở nên khó hiểu.

125
Conrad Frix

Cũng có thể ném cái này vào vòng:

Premature optimization is the root of all evil.

Không, không phải.

Báo giá đầy đủ:

"Chúng ta nên quên đi những hiệu quả nhỏ, nói khoảng 97% thời gian: tối ưu hóa sớm là gốc rễ của mọi tội lỗi. Tuy nhiên, chúng ta không nên bỏ qua cơ hội của mình trong 3% quan trọng đó."

Điều đó có nghĩa là bạn tận dụng cụ thể, cải tiến hiệu suất chiến lược trong suốt quá trình thiết kế của bạn. Điều đó có nghĩa là bạn sử dụng các cấu trúc dữ liệu và thuật toán phù hợp với mục tiêu hiệu suất. Nó có nghĩa là bạn nhận thức được các cân nhắc thiết kế ảnh hưởng đến hiệu suất. Nhưng điều đó cũng có nghĩa là bạn không tối ưu hóa một cách phù phiếm khi làm như vậy sẽ mang lại cho bạn những lợi ích nhỏ với chi phí bảo trì.

Các ứng dụng cần phải được kiến ​​trúc tốt, để cuối cùng chúng không bị rơi khi bạn áp dụng một chút tải cho chúng, và sau đó bạn sẽ viết lại chúng. Điều nguy hiểm với trích dẫn rút gọn là, tất cả quá thường xuyên, các nhà phát triển sử dụng nó như một cái cớ để không nghĩ về hiệu suất cho đến khi kết thúc, khi có thể quá muộn để làm bất cứ điều gì về nó. Tốt hơn hết là xây dựng hiệu suất tốt ngay từ đầu, miễn là bạn không tập trung vào những chi tiết vụn vặt.

Giả sử bạn đang xây dựng một ứng dụng thời gian thực trên một hệ thống nhúng. Bạn chọn Python làm ngôn ngữ lập trình, bởi vì "Tối ưu hóa sớm là gốc rễ của mọi tội lỗi." Bây giờ tôi không có gì chống lại Python, nhưng nó is một ngôn ngữ được dịch. Nếu khả năng xử lý bị hạn chế và một số lượng công việc nhất định cần được thực hiện trong thời gian thực hoặc gần thời gian thực và bạn chọn một ngôn ngữ đòi hỏi nhiều sức mạnh xử lý cho công việc hơn bạn có, bạn thực sự bị lừa, bởi vì bạn bây giờ phải bắt đầu lại với một ngôn ngữ có khả năng.

95
Robert Harvey

Một trả về cho mỗi chức năng/phương thức.

94
iMacUwhAK

Đừng phát minh lại bánh xe là một giáo điều được sử dụng rộng rãi. Ý tưởng của nó là nếu một giải pháp phù hợp tồn tại, hãy sử dụng nó thay vì tạo ra giải pháp của riêng bạn; ngoài nỗ lực tiết kiệm, giải pháp hiện tại có khả năng được triển khai tốt hơn (không có lỗi, hiệu quả, đã được kiểm tra) so với những gì bạn sẽ đưa ra ban đầu. Càng xa càng tốt.

Vấn đề là hiếm khi có giải pháp phù hợp 100%. Một giải pháp phù hợp 80% có thể tồn tại, và sử dụng nó có lẽ là tốt. Nhưng làm thế nào khoảng 60% phù hợp? 40%? Bạn ve con đương nay ở đâu vậy? Nếu bạn không vẽ đường, cuối cùng bạn có thể kết hợp một thư viện cồng kềnh cho dự án của mình vì bạn đang sử dụng 10% các tính năng của nó - chỉ vì bạn muốn tránh "phát minh lại bánh xe".

Nếu bạn phát minh lại bánh xe, bạn sẽ nhận được chính xác những gì bạn muốn. Bạn cũng sẽ tìm hiểu cách chế tạo bánh xe. Học bằng cách không nên đánh giá thấp. Và cuối cùng, một bánh xe tùy chỉnh có thể tốt hơn so với bánh xe chung ngoài giá.

87
Joonas Pulakka

"Đơn vị kiểm tra mọi thứ."

Tôi đã nghe nói rằng tất cả các mã nên có các bài kiểm tra đơn vị, một điểm tôi không đồng ý. Khi bạn có một thử nghiệm cho một phương thức, bất kỳ thay đổi nào đối với đầu ra hoặc cấu trúc của phương thức đó phải được thực hiện hai lần (một lần trong mã, một lần trong thử nghiệm).

Như vậy, theo tôi, các thử nghiệm đơn vị phải tỷ lệ thuận với sự ổn định cấu trúc của mã. Nếu tôi đang viết một hệ thống lớp từ dưới lên, lớp truy cập dữ liệu của tôi sẽ kiểm tra wazoo; Lớp logic kinh doanh của tôi sẽ được kiểm tra khá tốt, lớp trình bày của tôi sẽ có một số thử nghiệm và quan điểm của tôi sẽ không có nhiều thử nghiệm.

78
Fishtoaster

Luôn luôn chương trình để giao diện.

Đôi khi sẽ chỉ có một thực hiện. Nếu chúng ta trì hoãn quá trình trích xuất một giao diện cho đến khi chúng ta thấy cần nó, chúng ta thường sẽ thấy nó không cần thiết.

57
Eric Wilson

Không sử dụng bất cứ thứ gì nguồn mở (hoặc không phải Microsoft cho các nhà phát triển .NET)

Nếu Microsoft không phát triển nó - chúng tôi sẽ không sử dụng nó ở đây. Muốn sử dụng ORM - EF, muốn sử dụng IOC - Unity, muốn đăng nhập - khối ứng dụng ghi nhật ký doanh nghiệp. Có rất nhiều thư viện tốt hơn tồn tại - nhưng tôi luôn bị kẹt khi đặt hàng từ menu đô la của thế giới phát triển. Tôi thề mỗi khi nghe Microsoft Thực hành tốt nhất tôi nghĩ rằng "Nguyên tắc dinh dưỡng của McDonald". Chắc chắn, bạn có thể sẽ sống nếu bạn tuân theo chúng, nhưng bạn cũng sẽ bị suy dinh dưỡng và thừa cân.

  • Lưu ý rằng điều này có thể không phải là của bạn cách thực hành tốt nhất, nhưng đó là một cách phổ biến theo hầu hết mọi nơi tôi đã làm việc.
46
Watson

Hướng đối tượng

Có một giả định, chỉ vì mã là "hướng đối tượng", nó thật tuyệt vời. Vì vậy, mọi người tiếp tục ép chức năng vào các lớp và phương thức, chỉ để hướng đối tượng.

40
LennyProgrammers

Tất cả các mã nên được bình luận.

Không, không nên. Đôi khi bạn có mã rõ ràng, ví dụ setters không nên được nhận xét, cho đến khi họ làm điều gì đó đặc biệt. Ngoài ra, tại sao tôi nên bình luận điều này:

/** hey you, if didn't get, it's logger. */
private static Logger logger = LoggerFactory.getLogger(MyClass.class);
35
Vladimir Ivanov

Phương pháp, đặc biệt là scrum. Tôi không thể giữ khuôn mặt thẳng thắn khi nghe người lớn sử dụng cụm từ "Scrum Master". Tôi cảm thấy mệt mỏi khi nghe các nhà phát triển phản đối rằng một số khía cạnh của Phương pháp X không làm việc cho công ty của họ, chỉ được nói bởi Đạo sư và vì vậy lý do nó không hoạt động là trên thực tế, họ không phải là những học viên thực thụ của Phương pháp X. "Scrum khó hơn, bạn phải, người học Padawan của tôi!"

Có rất nhiều sự khôn ngoan trong các phương pháp nhanh nhẹn --- rất nhiều trong số đó --- nhưng chúng thường bị vùi lấp trong quá nhiều phân đến nỗi tôi không thể chống lại phản xạ bịt miệng của mình. Lấy bit này từ trang scrum của Wikipedia :

Một số vai trò được xác định trong Scrum. Tất cả các vai trò thuộc hai nhóm khác nhau, lợn và gà, dựa trên bản chất của sự tham gia của chúng vào quá trình phát triển.

Có thật không? Lợn và gà, bạn nói gì? Hấp dẫn! Không thể chờ đợi để đưa cái này cho ông chủ của tôi ...

32
evadeflow

Ánh xạ quan hệ đối tượng ... http://en.wikipedia.org/wiki/Object-relational_mapping

Tôi không muốn bị trừu tượng hóa khỏi dữ liệu của mình, tôi cũng không muốn mất sự kiểm soát và tối ưu hóa chính xác đó. Trải nghiệm của tôi với các hệ thống này cực kỳ kém ... Các truy vấn được tạo bởi các lớp trừu tượng này thậm chí còn tồi tệ hơn những gì tôi đã thấy từ ngoài lề.

25
Fosco

Viết tên hàm như thể chúng là câu tiếng Anh:

Draw_Foo()
Write_Foo()
Create_Foo()

v.v ... Điều này có thể trông tuyệt vời, nhưng thật đau khổ khi bạn học API. Làm thế nào dễ dàng hơn để tìm kiếm một chỉ mục cho "Mọi thứ bắt đầu với Foo"?

Foo_Draw()
Foo_Write()
Foo_Create()

vân vân.

22
Colen

YAGNI

( Bạn sẽ không cần nó )

Cách tiếp cận này đã khiến tôi mất hàng giờ liền khi tôi phải triển khai các tính năng trên một cơ sở mã hiện có, trong đó việc lập kế hoạch cẩn thận sẽ bao gồm các tính năng này trước đó.

Ý tưởng của tôi thường bị từ chối vì YAGNI, và hầu hết những lần ai đó phải trả tiền cho quyết định đó sau đó.

(Tất nhiên người ta có thể lập luận rằng một cơ sở mã được thiết kế tốt cũng sẽ cho phép các tính năng được thêm vào sau này, nhưng thực tế thì khác)

22
Sean Patrick Floyd

MVC - tôi thường thấy rằng việc xử lý nhiều vấn đề thiết kế web trong cách tiếp cận MVC là về việc làm cho một khung (Rails, v.v.) hài lòng hơn là về sự đơn giản hoặc cấu trúc. MVC là một yêu thích của "các phi hành gia kiến ​​trúc", người dường như đánh giá cao giàn giáo quá mức đơn giản. ymmv.

dựa trên lớp OO - theo tôi khuyến khích các cấu trúc phức tạp của trạng thái có thể thay đổi. Các trường hợp hấp dẫn duy nhất tôi tìm thấy cho lớp dựa trên OO trong nhiều năm qua là các ví dụ "hình dạng-> hình chữ nhật-> hình vuông" tạo thành chương 1 của bất kỳ OO cuốn sách

22
Brad Clawsie

Đối với SQL

  1. Không sử dụng kích hoạt
  2. Luôn ẩn bảng phía sau lượt xem

Theo thứ tự:

  1. Chúng là một tính năng có vị trí của nó. Bạn có nhiều đường dẫn cập nhật tới một bảng hoặc yêu cầu kiểm toán 100%?

  2. Chỉ là vì sao? Tôi sẽ làm nếu tôi tái cấu trúc để duy trì hợp đồng, nhưng không phải khi tôi đọc rằng dân gian thay đổi quan điểm để phù hợp với bất kỳ thay đổi bảng nào

Biên tập:

Số 3: Tránh * với EXISTS. Hãy thử 1/0. Nó hoạt động. Danh sách cột không được đánh giá theo tiêu chuẩn SQL. Trang 191

20
gbn

Mẫu thiết kế chủ yếu. Chúng được sử dụng quá mức và được sử dụng.

20
Geek

Nguyên tắc trách nhiệm duy nhất

("mỗi lớp chỉ có một trách nhiệm duy nhất; nói cách khác, mỗi lớp nên có một, và chỉ một, lý do để thay đổi")

Tôi không đồng ý. Tôi nghĩ rằng a phương thức chỉ nên có một lý do để thay đổi và tất cả các phương thức trong một lớp nên có mối quan hệ logic với nhau , nhưng bản thân lớp có thể thực sự do một số thứ (liên quan).

Theo kinh nghiệm của tôi, nguyên tắc này quá thường xuyên được áp dụng quá nhiệt tình và bạn kết thúc với nhiều lớp một phương thức nhỏ. Cả hai cửa hàng nhanh nhẹn mà tôi làm việc đã làm điều này.

Hãy tưởng tượng nếu những người tạo API .Net có loại tâm lý này: thay vì List.Sort (), List.Reverse (), List.Find (), v.v., chúng tôi sẽ có các lớp ListSorter, ListReverser và ListSearcher!

Thay vì tranh luận nữa với SRP (về lý thuyết không phải là khủng khiếp), tôi sẽ chia sẻ một vài kinh nghiệm về giai thoại dài hơi của tôi:


Tại một nơi tôi làm việc, tôi đã viết một bộ giải dòng chảy tối đa rất đơn giản bao gồm năm lớp: một nút, một biểu đồ, một người tạo biểu đồ, một trình giải đồ thị và một lớp để sử dụng trình tạo/giải đồ thị để giải quyết vấn đề trong thế giới thực. Không có gì đặc biệt phức tạp hoặc dài (bộ giải cho đến nay là dài nhất với ~ 150 dòng). Tuy nhiên, quyết định rằng các lớp có quá nhiều "trách nhiệm", vì vậy các đồng nghiệp của tôi đã thiết lập về việc tái cấu trúc mã. Khi chúng được thực hiện, 5 lớp của tôi đã được mở rộng thành 25 lớp, với tổng số dòng mã nhiều hơn gấp ba lần so với ban đầu. Luồng mã không còn rõ ràng nữa, cũng không phải là mục đích của các bài kiểm tra đơn vị mới; Bây giờ tôi đã có một thời gian khó khăn để tìm ra những gì mã của riêng tôi đã làm.


Ở cùng một nơi, hầu hết mọi lớp chỉ có một phương thức duy nhất ("trách nhiệm" duy nhất của nó). Theo dòng chảy trong chương trình gần như không thể, và hầu hết các bài kiểm tra đơn vị bao gồm kiểm tra rằng lớp này được gọi là mã từ lớp khác, cả hai mục đích của chúng là cũng là một bí ẩn đối với tôi Có hàng trăm lớp học chỉ có hàng chục (IMO) chỉ có hàng chục. Mỗi lớp chỉ thực hiện một "điều", nhưng ngay cả với các quy ước đặt tên như "AdminUserCreationAtteemorFactory", rất khó để nói mối quan hệ giữa các lớp.


Ở một nơi khác (cũng có class-Should-have-only-one-method tâm lý), chúng tôi đã cố gắng tối ưu hóa một phương thức chiếm 95% thời gian trong một hoạt động nhất định. Sau khi (khá ngu ngốc) tối ưu hóa nó một chút, tôi chuyển sự chú ý của mình về phía tại sao nó được gọi là một tỷ lần. Nó đang được gọi trong một vòng lặp trong một lớp ... có phương thức được gọi trong một vòng lặp trong một lớp khác .. cũng được gọi trong một vòng lặp ..

Tất cả đã nói, có năm cấp độ vòng lặp trải rộng trên 13 lớp (nghiêm túc). Điều mà bất kỳ một lớp nào đang thực sự làm là không thể xác định chỉ bằng cách nhìn vào nó - bạn phải phác thảo một biểu đồ tinh thần về phương thức mà nó gọi, và phương thức mà các phương thức đó gọi, v.v. Nếu tất cả đã được gộp thành một phương thức, thì nó sẽ chỉ dài khoảng 70 dòng với phương pháp vấn đề của chúng ta được lồng trong năm cấp độ vòng lặp rõ ràng ngay lập tức.

Yêu cầu của tôi để cấu trúc lại 13 lớp đó thành một lớp đã bị từ chối.

15

Bây giờ bạn đã đề cập đến Clean Code, trong khi nó chứa một số ý tưởng hay, tôi nghĩ rằng nỗi ám ảnh của nó là tái cấu trúc tất cả các phương thức thành submethod và những cái đó thành sububmethods v.v ... đã đi quá xa. Thay vì một vài phương thức mười dòng, bạn nên thích hai mươi (được cho là cũng được đặt tên). Rõ ràng có ai đó nghĩ rằng nó sạch, nhưng với tôi nó dường như tồi tệ hơn phiên bản gốc.

Ngoài ra, thay thế những điều cơ bản đơn giản như

0 == memberArray.length

trong một lớp với một cuộc gọi đến phương thức riêng của lớp như

isEmpty()

là một IMHO "cải tiến" đáng ngờ. Bổ sung: Sự khác biệt là kiểm tra đầu tiên thực hiện chính xác những gì nó nói: kiểm tra xem độ dài mảng có phải là 0. Ok, isEmpty() cũng có thể kiểm tra độ dài mảng. Nhưng nó cũng có thể được thực hiện như thế này:

return null != memberArray ? 0 == memberArray.length : true;

Đó là, nó bao gồm một kiểm tra null ngầm! Đây có thể là hành vi tốt đối với một phương thức công khai - nếu mảng là null, thì một cái gì đó chắc chắn trống rỗng - nhưng khi chúng ta nói về nội bộ lớp, điều này không tốt lắm. Trong khi đóng gói ra bên ngoài là điều bắt buộc, lớp bên trong phải biết chính xác những gì đang diễn ra trong lớp. Bạn không thể đóng gói lớp từ chính nó . Rõ ràng là tốt hơn ngầm định.


Điều này không có nghĩa là phá vỡ các phương pháp dài hoặc so sánh logic liên quan là không tốt; tất nhiên là vậy, nhưng đến mức độ nào để làm điều đó - điểm ngọt ở đâu - rõ ràng là một câu hỏi về hương vị. Việc chia nhỏ một phương pháp dài dẫn đến nhiều phương thức hơn và điều đó không miễn phí. Bạn phải nhảy xung quanh mã nguồn để xem điều gì đang thực sự xảy ra, khi bạn có thể thấy nó trong nháy mắt nếu tất cả những thứ đó nằm trong một phương thức duy nhất.

Tôi thậm chí sẽ đi xa hơn khi nói rằng trong một số trường hợp, phương thức 1 dòng là quá ngắn để xứng đáng là một phương thức.

14
Joonas Pulakka

"Hãy tự do với ý kiến"

Nhận xét chắc chắn là một điều tốt, nhưng quá nhiều cũng tệ như vậy nếu không tệ hơn là không đủ. Tại sao? Vâng, mọi người có xu hướng điều chỉnh các bình luận nếu họ thấy quá nhiều những thứ không cần thiết. Tôi không nói rằng bạn có thể có mã tài liệu hoàn toàn tự động, nhưng tốt hơn là mã cần bình luận để giải thích.

13
Jason Baker

GoTo được coi là có hại

Nếu bạn đang triển khai một máy trạng thái, một câu lệnh GOTO có thể có ý nghĩa hơn (mã dễ đọc và mã hiệu quả) hơn là cách tiếp cận "lập trình có cấu trúc". Nó thực sự lo lắng cho một số đồng nghiệp khi đoạn mã đầu tiên tôi viết trong một công việc mới không chỉ bao gồm một mà là một vài câu lệnh goto. May mắn thay, họ đủ thông minh để nhận ra rằng đó thực sự là giải pháp tốt nhất trong trường hợp cụ thể này.

Bất kỳ "thực hành tốt nhất" nào không cho phép các ngoại lệ hợp lý và được ghi lại theo quy tắc của nó đều đáng sợ.

12
MZB

Những hy sinh chúng tôi thực hiện để làm cho mã có thể kiểm tra được

Tôi nhảy qua rất nhiều vòng để làm cho mã của mình có thể kiểm tra được, nhưng tôi không giả vờ rằng tôi sẽ không được lựa chọn. Tuy nhiên, tôi thường nghe mọi người thúc đẩy ý tưởng rằng đây là những "cách thực hành tốt nhất". Các thực tiễn này bao gồm (được viết bằng ngôn ngữ của .Net, nhưng cũng áp dụng cho các ngôn ngữ khác):

  • Tạo giao diện cho every class. Điều này nhân đôi số lượng lớp ( tập tin) để đối phó và sao chép mã. Có, lập trình giao diện là tốt, nhưng đó là ý nghĩa của các công cụ xác định công khai/riêng tư.
  • Mỗi ​​lớp không được khởi tạo khi khởi động cần một nhà máy. Rõ ràng, new MyClass() đơn giản hơn nhiều so với viết một nhà máy, nhưng bây giờ phương thức đó tạo ra nó không thể được kiểm tra trong sự cô lập. Nếu không phải vì thực tế này, tôi sẽ chỉ tạo ra 1/20 số lượng nhà máy mà tôi làm bây giờ.
  • Đặt mọi lớp thành công khai, đánh bại mục đích có các chỉ định truy cập trên các lớp. Tuy nhiên, các lớp không công khai không thể được truy cập (và do đó, đã được kiểm tra) từ các dự án khác, vì vậy lựa chọn duy nhất khác là chuyển tất cả mã kiểm tra sang cùng một dự án (và do đó phát hành nó với sản phẩm cuối cùng).
  • Tiêm phụ thuộc. Rõ ràng phải cung cấp every lớp khác tôi sử dụng một trường và tham số hàm tạo là công việc đáng kể hơn hơn là chỉ tạo ra chúng khi tôi cần chúng; nhưng sau đó tôi không còn có thể kiểm tra lớp này trong sự cô lập.
  • Nguyên tắc trách nhiệm duy nhất, đã khiến tôi rất đau đầu Tôi đã chuyển nó sang câu trả lời của riêng mình .

Vậy chúng ta có thể làm gì để khắc phục điều này? Chúng ta cần một sự thay đổi mạnh mẽ trong kiến ​​trúc ngôn ngữ:

  • Chúng ta cần khả năng để chế nhạo các lớp
  • Chúng tôi cần khả năng kiểm tra các phương thức riêng của các lớp bên trong, từ một dự án khác (điều này có vẻ như là một lỗ hổng bảo mật, nhưng tôi không thấy vấn đề gì nếu người được kiểm tra buộc phải đặt tên cho các lớp thử nghiệm của nó) .
  • Tiêm phụ thuộc (hoặc vị trí dịch vụ), cũng như một cái gì đó tương đương với mẫu nhà máy hiện tại của chúng tôi, sẽ phải là một core một phần của ngôn ngữ.

Nói tóm lại, chúng ta cần một ngôn ngữ được thiết kế từ đầu với khả năng kiểm tra .

12

Tách các ứng dụng thành Tầng; Lớp dữ liệu, Lớp nghiệp vụ, Lớp UI

Lý do chính mà tôi không thích điều này là hầu hết các nơi theo phương pháp này, sử dụng các khung rất dễ vỡ để hoàn thành nó. I E. Lớp UI được mã hóa bằng tay để đối phó với các đối tượng của lớp nghiệp vụ, các đối tượng của lớp nghiệp vụ được mã hóa bằng tay để xử lý các quy tắc và cơ sở dữ liệu kinh doanh, cơ sở dữ liệu là SQL và khá dễ vỡ và được quản lý bởi nhóm "DBA" không thích thay đổi.

Tại sao điều này là xấu? Yêu cầu nâng cao phổ biến nhất có thể là "Tôi cần một trường trên màn hình X có Y." Bang! Bạn chỉ có một tính năng mới ảnh hưởng đến từng lớp và nếu bạn tách các lớp với các lập trình viên khác nhau, nó sẽ trở thành một vấn đề lớn liên quan đến nhiều người và các nhóm, vì một sự thay đổi rất đơn giản.

Ngoài ra, tôi không biết đã bao nhiêu lần tôi tranh cãi với nhau như thế này. "Trường tên được giới hạn ở độ dài tối đa là 30, đây có phải là lớp UI hay lớp nghiệp vụ hay lớp dữ liệu không?" Và có một trăm lập luận, và không có câu trả lời đúng. Câu trả lời là như nhau, nó ảnh hưởng đến tất cả các lớp, bạn không muốn làm cho UI bị câm và phải trải qua tất cả các lớp, và thất bại tại cơ sở dữ liệu, vì vậy người dùng phát hiện ra mục nhập của mình quá dài. Nếu bạn thay đổi nó, nó sẽ ảnh hưởng đến tất cả các lớp, v.v.

Các "lớp" cũng có xu hướng rò rỉ; Nếu bất kỳ lớp nào được phân tách vật lý bởi các ranh giới quy trình/máy (I.E. web UI và logic phụ trợ kinh doanh), các quy tắc sẽ được sao chép để mọi thứ hoạt động hợp lý. I E. một số logic nghiệp vụ kết thúc trong UI, mặc dù đó là "quy tắc kinh doanh", bởi vì người dùng cần UI để phản hồi.

Nếu khung được sử dụng hoặc kiến ​​trúc được sử dụng, có khả năng phục hồi các thay đổi và rò rỉ nhỏ, tức là dựa trên dữ liệu meta và được điều chỉnh động qua tất cả các lớp, điều đó có thể ít gây đau đớn hơn. Nhưng hầu hết các khung công tác này là một nỗi đau của hoàng gia, đòi hỏi thay đổi giao diện người dùng, thay đổi lớp doanh nghiệp và thay đổi cơ sở dữ liệu, cho mỗi thay đổi nhỏ và gây ra nhiều công việc hơn và ít trợ giúp hơn so với kỹ thuật được cho là tạo ra.

Tôi có thể sẽ bị đánh sập vì điều này, nhưng nó đây :)

10
Jay

JavaBeans

Việc sử dụng JavaBeans trong Java. Xem câu hỏi của tôi Tại sao tôi không nên sử dụng POJO bất biến thay vì JavaBeans? trên StackOverflow.

9
Jonas

Câu chuyện của người dùng/Các trường hợp sử dụng/Personas

Tôi hiểu sự cần thiết của những điều này khi bạn lập trình cho một ngành mà bạn không quen thuộc, nhưng tôi nghĩ rằng khi chúng được thực thi đầy đủ, chúng trở nên quá tập thể và trở nên lãng phí thời gian.

7
riwalk

Giới hạn 80 char/dòng bị câm

Tôi hiểu rằng một số thỏa hiệp cần phải được thực hiện để phù hợp với tốc độ của người chạy chậm nhất về phía GUI (giới hạn độ phân giải màn hình, v.v.), nhưng tại sao quy tắc đó lại áp dụng cho định dạng mã?

Xem ... Có một phát minh nhỏ này được gọi là thanh cuộn ngang được tạo ra để quản lý không gian màn hình ảo bên ngoài ranh giới pixel bên phải nhất. Tại sao các nhà phát triển, những người đã quản lý để tạo ra các công cụ nâng cao năng suất tuyệt vời như tô sáng cú pháp và tự động hoàn thành sử dụng nó?

Chắc chắn, có những biên tập viên CLI được sử dụng một cách tôn giáo bởi những con khủng long * nix tuân theo những hạn chế cũ mệt mỏi của thiết bị đầu cuối VT220 của họ, nhưng tại sao phần còn lại của chúng ta lại giữ cùng tiêu chuẩn?

Tôi nói, vít giới hạn 80 char. Nếu khủng long đủ sử thi để hack emacs/vim cả ngày, tại sao không thể có khả năng tạo tiện ích mở rộng tự động bao bọc các dòng hoặc cung cấp khả năng cuộn ngang cho IDE CLI của chúng?

Các màn hình pixel 1920x1080 cuối cùng sẽ trở thành chuẩn mực và các nhà phát triển trên toàn thế giới vẫn đang sống trong cùng những hạn chế mà không có lý do gì để làm ngoại trừ, đó là những gì họ đã nói với những người lớn tuổi khi họ mới bắt đầu lập trình.

80 giới hạn char là không một thực tiễn tốt nhất nhưng là một thực tiễn thích hợp cho rất ít lập trình viên và nên được đối xử như vậy.

Chỉnh sửa :

Có thể hiểu rằng nhiều nhà phát triển không thích thanh cuộn ngang vì nó yêu cầu cử chỉ chuột nên ... Tại sao không tăng giới hạn chiều rộng cột lên số cao hơn (hơn 80) đối với những người sử dụng màn hình hiện đại.

Khi màn hình máy tính 800x600 trở thành tiêu chuẩn cho hầu hết người dùng, các nhà phát triển web đã tăng độ rộng trang web của họ để phù hợp với đa số ... Tại sao các nhà phát triển không thể làm như vậy.

7
Evan Plaice

Đo, Đo, Đo

Rất tốt, đo lường đi, nhưng for cô lập lỗi hiệu suất, đo lường hoạt động cũng như loại bỏ liên tiếp. Đây là phương pháp tôi sử dụng.

Tôi đã cố gắng truy tìm nguồn gốc của "trí tuệ" đo lường. Ai đó với một hộp xà phòng đủ cao nói điều đó, và bây giờ nó đi du lịch.

5
Mike Dunlavey

Sử dụng Singletons

Khi bạn chỉ nên có một ví dụ của một cái gì đó. Tôi không thể không đồng ý thêm. Không bao giờ sử dụng một singleton và chỉ phân bổ nó một lần và chuyển xung quanh con trỏ/đối tượng/tham chiếu khi cần thiết. Hoàn toàn không có lý do để không làm điều này.

5
user2528

Giáo viên của tôi yêu cầu tôi bắt đầu tất cả các định danh của mình (không bao gồm các hằng số) bằng các chữ cái viết thường, ví dụ: myVariable.

Tôi biết nó có vẻ như là một điều nhỏ, nhưng nhiều ngôn ngữ lập trình yêu cầ biến để bắt đầu bằng chữ in hoa. Tôi coi trọng tính nhất quán, vì vậy đó là thói quen của tôi để bắt đầu mọi thứ bằng chữ in hoa.

5
Maxpm

Sử dụng int unsign như iterator

Khi nào họ sẽ biết rằng sử dụng int đã ký sẽ an toàn hơn và ít bị lỗi hơn. Tại sao điều quan trọng là chỉ số mảng chỉ có thể là số dương, mà mọi người đều vui mừng bỏ qua thực tế rằng 4 - 5 là 4294967295?

5
AareP

Các phương thức không nên dài hơn một màn hình

Tôi hoàn toàn đồng ý với nguyên tắc trách nhiệm đơn lẻ nhưng tại sao mọi người lại cho rằng nó có nghĩa là "một chức năng/phương pháp có thể có nhiều hơn một trách nhiệm duy nhất ở mức độ chi tiết logic tốt nhất"?

Ý tưởng rất đơn giản. Một chức năng/phương thức nên hoàn thành một nhiệm vụ. Nếu một phần của chức năng/phương thức đó có thể được sử dụng ở nơi khác, hãy cắt nó thành chức năng/phương thức riêng của nó. Nếu nó có thể được sử dụng ở nơi khác trong dự án, hãy chuyển nó vào lớp riêng hoặc lớp tiện ích và làm cho nó có thể truy cập được trong nội bộ.

Có một lớp chứa 27 phương thức của trình trợ giúp chỉ được gọi một lần trong mã là ngu ngốc, lãng phí không gian, tăng độ phức tạp không cần thiết và thời gian chìm rất lớn. Nghe có vẻ giống như một quy tắc tốt cho những người muốn tìm mã tái cấu trúc bận rộn nhưng không sản xuất nhiều.

Đây là quy tắc của tôi ...

Viết hàm/phương thức để thực hiện một cái gì đó

Nếu bạn thấy mình sắp sao chép/dán một số mã, hãy tự hỏi liệu có tốt hơn không khi tạo một hàm/phương thức cho mã đó. Nếu một hàm/phương thức chỉ được gọi một lần trong một hàm/phương thức khác, thì thực sự có một điểm trong việc có nó ở vị trí đầu tiên (nó sẽ được gọi thường xuyên hơn trong tương lai). Có giá trị khi thêm nhiều lần nhảy vào/ra các chức năng/phương thức trong quá trình gỡ lỗi không (nghĩa là bước nhảy được thêm vào giúp việc gỡ lỗi dễ dàng hay khó hơn)?

Tôi hoàn toàn đồng ý rằng các hàm/phương thức lớn hơn 200 dòng cần được xem xét kỹ lưỡng nhưng một số hàm chỉ hoàn thành một nhiệm vụ trong bao nhiêu dòng và không chứa các phần hữu ích có thể được trừu tượng hóa/sử dụng trên phần còn lại của dự án.

Tôi nhìn nó từ góc độ nhà phát triển API ... Nếu một người dùng mới nhìn vào sơ đồ lớp của mã của bạn, thì có bao nhiêu phần của sơ đồ đó sẽ có ý nghĩa trong toàn bộ dự án và có bao nhiêu tồn tại duy nhất như người trợ giúp cho các bộ phận khác nội bộ của dự án.

Nếu tôi chọn giữa hai lập trình viên: người đầu tiên có xu hướng viết các hàm/phương thức cố gắng làm quá nhiều; cái thứ hai phá vỡ mọi phần của mọi chức năng/phương pháp đến mức độ chi tiết tốt nhất; Tôi sẽ chọn tay đầu tiên xuống. Đầu tiên sẽ thực hiện được nhiều hơn (nghĩa là viết nhiều thịt hơn của ứng dụng), mã của anh ta sẽ dễ gỡ lỗi hơn (do ít nhảy vào/ra khỏi các chức năng/phương thức trong quá trình gỡ lỗi) và anh ta sẽ lãng phí ít thời gian hơn để hoàn thành công việc bận rộn mã trông vs hoàn thiện cách mã hoạt động.

Hạn chế trừu tượng không cần thiết và không gây ô nhiễm tự động hoàn thành.

4
Evan Plaice

Tuyệt đối, nghiêm ngặt, đóng gói

Tôi đồng ý với việc đóng gói phần lớn, nhưng đó là một người giải phóng thực sự để tạm thời phá vỡ quy tắc đó để chuyển đổi một số mã thủ tục thành OOP bằng cách sử dụng tái cấu trúc mảng thành đối tượng . ( Cần một chút lực đẩy để nới lỏng một chút. Cảm ơn, Martin Fowler)

  • Mảng

    ->

  • lớp mới với mảng là thuộc tính công khai

    ->

  • đi qua mã máy khách/thêm người truy cập

    ->

  • chỉ sau đó đóng gói nó và làm cho nó riêng tư/được bảo vệ

2
JW01

Quá khái quát.

Khối vuông KHÔNG vừa với lỗ tròn!

1
PMV

Chỉ có một điều tôi có thể nghĩ đến là định dạng Java if các câu lệnh như thế này:

if (condition) ...

thay vì

if(condition) ...

Đối với hầu hết các phần, tôi đã tìm thấy các thực tiễn tốt nhất là tốt nhất và bất kỳ đặt phòng ban đầu nào tôi có với chúng có xu hướng bị đặt sai chỗ hoặc bị ghi đè bởi các mối quan tâm quan trọng hơn.

1
Armand

"Nếu nó không bị hỏng, đừng sửa nó". Mã là luôn luôn bị hỏng. Lý do không ai nói với nhà phát triển ban đầu là họ

  1. nghĩ rằng đó là lỗi của họ,
  2. không biết liên lạc với ai
  3. không thể thông qua hỗ trợ để nói chuyện với một "techie",
  4. không thể bị làm phiền, hoặc
  5. không biết làm thế nào để mô tả vấn đề một cách chi tiết.
1
l0b0

Luôn ưu tiên các tên dài, rõ ràng, biến và thường xuyên trên mẫu rút gọn

ví dụ: ủng hộXác thựcoverAuthN

Bit này cho tôi , khi đường dẫn tệp MS quá dài đến nỗi bản sao làm việcSubversion của tôikhông thể tải vào PC của tôi.

Xem: https://stackoverflow.com/questions/3282303/my-choice-of-group-names-is-hampered-by-windows-xp-max-path-length-issues-with-sv

1
JW01

Tôi có xu hướng bỏ qua hầu hết tất cả các thực tiễn tốt nhất khi thực hiện một dự án tương đối nhỏ, một lần, như viết một trình phân tích cú pháp cần thiết để di chuyển các tệp. Khi tất cả những gì tôi cần là kết quả, một lần, tôi không quan tâm đến khả năng đọc, khả năng mở rộng, khả năng bảo trì, v.v.

1
user281377

Luồng là câu trả lời cho tất cả các vấn đề về hiệu suất

Không đồng ý với điều đó vì nhiều lý do.

  • Trong lập chỉ mục chung và bộ nhớ đệm tạm thời cho hiệu suất tăng cao hơn nhiều. Tất nhiên bạn thực sự có thể cần phải sử dụng "cờ bẩn" .. Làm cho thiết kế của bạn trở nên lộn xộn và nhiều thứ ..

  • Các vấn đề xuất phát từ đa luồng thừa cân tất cả lợi ích về thời gian và tiền bạc.

  • Những gì công nghệ đa lõi thực sự mang lại cho chúng tôi là đa tác vụ tốt hơn (chạy vài ứng dụng chỉ nhanh như một). Việc sử dụng các chương trình đa luồng được viết khéo léo chỉ là một tác dụng phụ.

0
AareP

TUYÊN BỐ TIẾP TỤC IS BAD

Tôi sẽ tham khảo các tiêu chuẩn mã hóa chung của máy bay chiến đấu không quân C++ ở đây:

Quy tắc AV 190 (Quy tắc MISRA 57) Câu lệnh tiếp tục sẽ không được sử dụng.

và một giáo sư của tôi:

"TUYÊN BỐ TIẾP TỤC IS BAD"

Logic của họ là nó phá vỡ dòng điều khiển và làm cho mã ít đọc hơn. Sử dụng các câu lệnh lồng nhau if là một cách tiếp cận sạch hơn.

Tuy nhiên, tôi thấy điều này dễ đọc hơn:

 
for(int i = 0; i < CONST_FOO; ++i) {
    if(aTwo[i] == NULL) continue;
    aTwo[i]->DoBar();
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
}
 

Hơn cái này:

 
for(int i = 0; i < CONST_FOO; ++i) {
    if(aTwo[i] != NULL) {
        aTwo[i]->DoBar();
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
    }
}
 

Đây là một ví dụ rất đơn giản, (hãy tưởng tượng các if lồng nhau đi nhiều hơn một cấp) nhưng nó tương tự như cách thực hành "chỉ một câu trả về cho mỗi hàm" "tốt nhất". Nó ngăn trình gỡ lỗi nhảy xung quanh (có thể cách xa vài trang), ít thụt lề thường giúp mã dễ đọc, v.v.

0
Casey

Trong JavaScript, nhiều người cho rằng cách tốt nhất là viết tất cả các dấu chấm phẩy họ cần bằng các ngôn ngữ nhánh C khác, và rất nhiều người trong số họ không ngại chỉ ra "lỗi" bất cứ khi nào họ thấy mã có thể có nhiều dấu chấm phẩy hơn). Tôi chưa bao giờ tìm thấy nhu cầu đối với họ, vai trò của họ là điểm đánh dấu trực quan đã được lấp đầy bởi các dịch chuyển dòng.

Mặt khác, thật buồn cười khi thấy một trình biên dịch yêu cầu dấu chấm phẩy, nhưng vẫn tự tin ném lỗi "Thiếu dấu chấm phẩy". "Cả hai chúng tôi đều biết bạn muốn viết gì, nhưng tôi phải từ chối đơn đăng ký của bạn vì tôi chính thức không được phép phân biệt giữa không gian và dịch chuyển dòng."

Một số thực tiễn tốt nhất theo kiểu JavaScript/C khác đang được lưu hành, nhưng không có cách nào trong số chúng đến gần về sự cường điệu mà không có đối số đủ điều kiện.

Chỉnh sửa: Hoàn toàn có thể thu nhỏ mã mà không có dấu chấm phẩy Trình biên dịch đóng sẽ chèn chúng khi cần.

0
aaaaaaaaaaaa

Chà, một trong những nút nóng của tôi là phân tích hiệu suất . Người ta nói

Tối ưu hóa sớm là gốc rễ của mọi tội lỗi.

Và sau đó họ nói trích dẫn hoàn chỉnh là:

Chúng ta nên quên đi những hiệu quả nhỏ, nói về 97% thời gian: tối ưu hóa sớm là gốc rễ của mọi tội lỗi. Tuy nhiên, chúng ta không nên bỏ qua cơ hội của mình trong 3% quan trọng đó.

Điều này có ý nghĩa hoàn hảo khi bạn thảo luận về "thuật toán" - công cụ học thuật thông minh trong đó 3% chương trình có thể là hai dòng mã.

Tôi làm việc trong 10 ^ 6 dòng ứng dụng, với 10 ^ 5 phương thức trong 10 ^ 4 lớp, đã làm việc trong nhiều năm qua bởi hàng tá lập trình viên và người thử nghiệm, trải qua nhiều lần sửa đổi và phát hành, trong đó trích dẫn đó hoàn toàn không liên quan. Thông thường, thời gian là những dòng mã duy nhất có thể là "cơ hội" nhưng không ai có thể đoán được chúng đang ở đâu.

OTOH, mọi người nói "hồ sơ", hoặc họ nói "biện pháp đo lường". Cũng tốt. Họ nói vậy, nhưng họ không thường xuyên làm điều đó. Có thể, lý do họ không làm điều đó là nó không hoạt động tốt .

Câu trả lời này nói thêm về điều đó và chỉ ra những gì hoạt động .

0
Mike Dunlavey

Bảng dữ liệu

Tôi ghét nó và yêu nó. (Phụ thuộc vào độ phức tạp của dự án)

0
Amir Rezaei