Làm thế nào để bạn sử dụng vịt gõ trong javascript mà không luôn luôn kiểm tra các thuộc tính và phương thức?


11

Tôi biết javascript sử dụng kiểu gõ vịt và lúc đầu tôi nghĩ rằng điều này sẽ làm cho tính đa hình dễ dàng so với các ngôn ngữ được gõ mạnh như C #. Nhưng bây giờ các chức năng của tôi có các đối số được đặt rải rác với những thứ như:

if(myObj.hasSomeProperty())

hoặc là

if(myObj.hasSomeMethod())

hoặc là

if(isNumber(myParam))

Vân vân.

Điều này thực sự xấu xí đối với tôi. Tôi đến từ nền tảng C # và tôi thấy các giao diện được xác định sẽ tốt hơn nhiều.

Tôi tự hỏi liệu tôi có đang cố gắng áp dụng các chiến lược hiệu quả trong các ngôn ngữ được nhập tĩnh không và có cách nào tốt hơn để làm điều này trong javascript không?

Tôi biết tôi chỉ có thể không kiểm tra, nhưng theo dõi các lỗi thời gian chạy javascript có thể là một cơn ác mộng vì chúng không luôn xảy ra khi lỗi thực sự xảy ra trong mã.


2
Tôi nghĩ rằng bạn có thể chỉ đang dò dẫm về bản chất của một ngôn ngữ được gõ động. Bạn phải làm quen với suy nghĩ rằng rất nhiều lỗi sẽ xảy ra trong thời gian chạy thay vì thời gian biên dịch. Nếu bạn cảm thấy cần phải kiểm tra xem mọi đối số có phải là một số trong mọi hàm nhập số hay không, nó có thể trở thành một gánh nặng (mặc dù có thể đáng giá nếu bạn vận chuyển một lib với an toàn là mục tiêu hàng đầu). Đối với bất kỳ quy mô nào, tôi thấy thật cần thiết khi chỉ cho phép các hàm bị lỗi nếu các loại sai được truyền vào. Thay vào đó, một trọng tâm năng suất hơn có thể là vào việc xây dựng các bài kiểm tra.

Trường hợp có thể giúp thực hiện các kiểm tra này để đảm bảo các loại phù hợp với các yêu cầu giao diện cần thiết (kiểm tra xem liệu chúng có các phương thức cần thiết hay không, ví dụ) nằm trong các chức năng trung tâm và được sử dụng rộng rãi nhất của bạn (các hàm có tính không ổn định = 0 với số liệu khớp nối efferent / afferent Martin cung cấp). Đó nên là một mục tiêu khá nhỏ. Thông thường có rất nhiều chức năng cục bộ một lần được phân lập trong phạm vi - những chức năng này có thể không cần một bộ kiểm tra thời gian chạy toàn diện như vậy. Họ không tích lũy nhiều phức tạp.

Chuyển sang loại Script. Nó vẫn gõ vịt, nhưng hỗ trợ gõ tĩnh để phát hiện nhiều lỗi khi biên dịch.
CodeInChaos

2
Bạn đã gặp phải vấn đề lớn nhất của việc gõ vịt: sức mạnh của nó xuất phát từ điểm yếu. Nếu bạn muốn làm JavaScript hướng đối tượng, bạn chỉ cần sống với các lỗi thời gian chạy và hy vọng các bài kiểm tra đơn vị của bạn sẽ tìm thấy chúng ngay sau khi bạn tạo chúng :-(
Ross Patterson

@RossPatterson Vấn đề của OP là với kiểu gõ động chứ không phải gõ vịt. TypeScript và Go đều được gõ vịt, nhưng tránh được vấn đề của OP. Vấn đề với việc gõ vịt là một vấn đề khác, cụ thể là bạn có thể có các thành viên vượt qua bài kiểm tra vịt nhưng không hoàn thành hợp đồng mà bạn mong đợi.
CodeInChaos 3/03/2016

Câu trả lời:


11

Làm thế nào để bạn sử dụng vịt gõ trong javascript mà không luôn luôn kiểm tra các thuộc tính và phương thức?

Đơn giản: không luôn luôn kiểm tra các thuộc tính và phương thức.

Trong Ruby, những gì bạn đang gọi được gọi là "gõ gà". Trong một ngôn ngữ gõ vịt năng động, bạn chỉ cần tin tưởng rằng người gọi chuyển cho bạn một đối tượng phù hợp. Đó là công việc của người gọi để tôn vinh hợp đồng của anh ấy.

Tôi biết javascript sử dụng kiểu gõ vịt và lúc đầu tôi nghĩ rằng điều này sẽ làm cho tính đa hình dễ dàng so với các ngôn ngữ được gõ mạnh như C #.

Bạn đang nhầm lẫn nhiều trục trực giao của việc gõ ở đây. Có bốn trục gõ trực giao:

  • Khi nào : kiểu gõ động (kiểu không được biết và được kiểm tra cho đến khi chạy) so với kiểu gõ tĩnh (kiểu được biết và được kiểm tra trước khi chạy)
  • Cái gì : gõ vịt (các loại dựa trên hành vi ), gõ cấu trúc (các loại dựa trên cấu trúc ) và gõ danh nghĩa (các loại dựa trên tên )
  • Bạn có thể nhìn thấy chúng? gõ rõ ràng (các kiểu phải được chú thích rõ ràng) so với gõ ngầm (các kiểu được suy ra)
  • gõ mạnh so với gõ yếu - bạn có thể nhận thấy rằng tôi đã không đặt cho cái này một tiêu đề hấp dẫn cũng như một lời giải thích trong ngoặc đơn, đó là vì không giống như bảy thuật ngữ ở trên, mỗi thuật ngữ có một định nghĩa chính xác được chấp nhận phổ biến, hai thuật ngữ này có khoảng một tá định nghĩa mơ hồ được sử dụng rộng rãi mâu thuẫn với nhau; lý tưởng nhất là bạn nên tránh các thuật ngữ này hoàn toàn và nếu bạn phải sử dụng chúng, hãy xác định chính xác chúng trước

Vì bạn đã đề cập đến C #: nó chủ yếu được gõ tĩnh, nhưng hỗ trợ gõ động thông qua kiểu dynamic, nó chủ yếu được gõ, nhưng các kiểu ẩn danh sử dụng kiểu cấu trúc và các kiểu cú pháp (như cú pháp hiểu truy vấn LINQ) có thể được tranh luận là vịt -typed hoặc gõ theo cấu trúc, phần lớn được gõ rõ ràng nhưng hỗ trợ nhập ngầm cho các đối số kiểu chung và biến cục bộ (mặc dù trường hợp biến cục bộ khá lạ so với hầu hết các ngôn ngữ khác, vì bạn không thể bỏ kiểu này, thay vào đó bạn phải cung cấp cho nó một loại giả rõ ràngvar, nói cách khác, nếu bạn muốn một kiểu ẩn, bạn phải nói rõ ràng như vậy). Việc C # được gõ mạnh hay yếu là vấn đề định nghĩa hai thuật ngữ bạn sử dụng, tuy nhiên, lưu ý rằng có thể có nhiều lỗi loại thời gian chạy trong C #, đặc biệt là do hiệp phương sai không an toàn.

Tôi biết tôi chỉ có thể không kiểm tra, nhưng theo dõi các lỗi thời gian chạy javascript có thể là một cơn ác mộng vì chúng không luôn xảy ra khi lỗi thực sự xảy ra trong mã.

Gỡ lỗi không phải là một kỹ năng dễ học. Tuy nhiên, có các kỹ thuật để làm cho việc gỡ lỗi dễ dàng hơn, ví dụ Saff Squeeze là một kỹ thuật được mô tả bởi Kent Beck, sử dụng các bài kiểm tra và tái cấu trúc để gỡ lỗi:

Lượt 'em cao, nhấn' em thấp :

Kiểm tra hồi quy và Saff Bóp

Kent Beck, Học viện Three Rivers

Tóm tắt: Để cách ly một cách hiệu quả một khiếm khuyết, hãy bắt đầu với một bài kiểm tra ở cấp độ hệ thống và tiến hành nội tuyến và cắt tỉa cho đến khi bạn có bài kiểm tra nhỏ nhất có thể chứng minh được lỗi đó.


Điều đó khiến tôi đạt được liên kết cao, liên kết thấp nhận được http 500 cho tôi, với "Trang không còn khả dụng" là thông điệp hướng đến con người.
joshp

Tên miền threeriversinst acad.org dường như đã bị bỏ rơi.
Bart van Ingen Schenau

À, chết tiệt. Và nó thậm chí không được lưu trữ trên WayBack Machine .
Jörg W Mittag

Làm thế nào là người gọi có nghĩa vụ tôn vinh phía của họ trong hợp đồng? Có vẻ như không có cách nào để giao tiếp (bằng mã) các tham số nên là gì. Mọi hàm đều thuộc dạng hàm fname (objParam, objParam, ...). Điều này có nghĩa là các ngôn ngữ như javascript hoàn toàn phụ thuộc vào tài liệu bên ngoài để giao tiếp sử dụng?
Quân đoàn

@Legion: tài liệu, đặt tên tốt, thông thường, kiểm tra như thông số kỹ thuật hành vi, đọc mã nguồn, bạn đặt tên cho nó. Lưu ý rằng điều này thực sự không khác nhiều so với các hệ thống loại yếu hơn như C # hoặc Java: Ví dụ: ý nghĩa của giá trị trả về IComparer<T>.Compare(T, T)chỉ rõ ràng từ tài liệu, không phải loại. Và ở đâu trong java.util.Collections.binarySearch(java.util.List<T>)đó, nó nói rằng trận đấu
Jörg W Mittag

1

Tôi biết tôi chỉ có thể không kiểm tra, nhưng theo dõi các lỗi thời gian chạy javascript có thể là một cơn ác mộng vì chúng không luôn xảy ra khi lỗi thực sự xảy ra trong mã.

Thật vậy, thực tế điển hình là không kiểm tra. Và, vâng, điều này có nghĩa là bạn sẽ gặp lỗi javascript được báo cáo ở nơi khác từ sự cố thực tế. Nhưng trong thực tế, tôi không thấy đây là một vấn đề lớn.

Khi làm việc trong javascript, tôi liên tục kiểm tra những gì tôi đang viết. Trong hầu hết các mã, tôi đã có các bài kiểm tra đơn vị tự động chạy mỗi khi tôi lưu trình soạn thảo của mình. Khi một cái gì đó bất ngờ xảy ra, tôi biết gần như ngay lập tức. Tôi đã có một vùng mã rất nhỏ trong đó tôi có thể đã mắc lỗi, vì đó gần như luôn là điều cuối cùng tôi chạm vào có lỗi.

Khi tôi gặp lỗi thời gian chạy, ít nhất tôi đã có dấu vết ngăn xếp và trong trường hợp có lỗi trong trình duyệt, tôi có khả năng đi đến bất kỳ cấp độ nào của dấu vết ngăn xếp và kiểm tra các biến. Thông thường, rất dễ dàng để theo dõi lại giá trị xấu đến từ đâu và do đó, theo dõi nó trở lại vấn đề ban đầu.

Nếu bạn giống như tôi khi tôi viết chủ yếu bằng các ngôn ngữ được nhập tĩnh, tôi đã viết các khối mã lớn hơn trước khi thử nghiệm và tôi đã không thực hành truy tìm lại một giá trị mà nó xuất phát. Lập trình trong một ngôn ngữ như javascript là khác nhau, bạn phải sử dụng các kỹ năng khác nhau. Tôi nghi ngờ việc lập trình như thế có vẻ khó hơn, vì đó không phải là những kỹ năng bạn đã phát triển khi làm việc với các ngôn ngữ khác như C #.

Phải nói rằng, tôi nghĩ có rất nhiều điều để nói về các loại rõ ràng. Chúng là tuyệt vời cho tài liệu và bắt lỗi sớm. Tôi nghĩ rằng trong tương lai chúng ta sẽ thấy việc áp dụng những thứ như Flow và Typecript sẽ thêm việc kiểm tra kiểu tĩnh vào javascript.


0

Tôi nghĩ rằng bạn đang làm đúng, bạn chỉ cần tìm phong cách sẽ được lòng bạn hơn. Đây là một số ý tưởng:

  • Thay vì if(myObj.hasSomeProperty())bạn có thể sử dụng if( myobj.prop !== undefined ). Điều này, BTW sẽ chỉ hoạt động ở chế độ không nghiêm ngặt, ở chế độ nghiêm ngặt bạn phải sử dụng if( typeof myobj.prop !== 'undefined' ).

  • Bạn có thể giảm tải một số loại kiểm tra để tách các trình xác nhận. Điều này có lợi ích là có thể bỏ qua xác nhận một khi các giao diện đã hoàn thiện, ví dụ: bắt đầu từ if( is_valid( myobject ))đâu .is_validif( !DEBUG ) return true;

  • Đôi khi nó có ý nghĩa để sao chép đầu vào thành một hình thức chính tắc, trong trường hợp đó bạn có thể thu thập các mục tiêu xác thực khác nhau vào chức năng / đối tượng nhân bản. Đối với exmaple, trong my_data = Data( myobj, otherstuff )hàm Datatạo có thể thuận tiện chạy tất cả các xác nhận khác nhau ở một vị trí trung tâm.

  • Bạn có thể sử dụng một số thư viện sẽ (với mức phí hiệu suất) hợp lý hóa việc xác thực loại của bạn thành một thứ gì đó thanh lịch hơn. Ngay cả khi bạn sẽ không đi theo con đường này trong thời gian dài, bạn vẫn có thể thấy thoải mái khi đưa bạn vào phong cách của riêng bạn. Một số ví dụ bao gồm xtype.js , kiểm tra loại , validator.js , v.v.

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.