2012-10-30 44 views
12

Tôi đang viết một số mã trong Node.js đã nhảy ra khỏi tôi như được cấu trúc tốt hơn bằng cách sử dụng mẫu chiến lược. Đến từ Net Tôi sẽ tạo ra giao diện phần còn lại được dựa trên và di chuyển từ đó, trong JavaScript này không phải là quá rõ ràng cắt.Đang cố gắng bắt chước một giao diện/lớp trừu tượng trong thực hành javascript xấu

Tôi hiểu là ngôn ngữ nguyên mẫu JavaScript không có khái niệm về giao diện thừa kế, vì vậy tôi không chắc mình đã làm gì hay không, vì tôi không thể tìm thấy tài liệu tham khảo, ngoài một bài đăng trên blog để suy ra một giao diện bằng cách sử dụng một lớp trừu tượng cơ sở để buộc các lớp kế thừa thực hiện hàm (khi nó ném).

lớp cơ sở của tôi

QueryStrategy = function() { 

}; 

QueryStrategy.prototype.create = function(){ 
throw new Error("Not Implemented"); 
} 

module.exports = QueryStrategy; 

Thực hiện 1

var util = require('util'); 
var QueryStrategy = require('./queryStrategy'); 

SelectQueryStrategy = function (query) { 
    this.parameters = query.parameters || []; 
    this.entity = query.entity || ''; 
}; 

util.inherits(SelectQueryStrategy, QueryStrategy); 

SelectQueryStrategy.prototype.create = function() { 
    var self = this, 
     params = self.parameters, 
     paramList = self.parameters.length >= 1 ? '' : '*'; 

    for (var i = 0; i < params.length; i++) { 
     var suffix = i === (params.length - 1) ? '' : ', '; 
     paramList = paramList + params[i].key + suffix; 
    } 

    return util.format("SELECT %s FROM %s", paramList, self.entity); 
}; 

module.exports = SelectQueryStrategy; 

Hiện nay các cơ sở không có bất kỳ chức năng chia sẻ, hoặc tài sản. Chức năng chia sẻ sẽ đến, thuộc tính, vì tìm kiếm chuỗi nguyên mẫu tôi không thấy điểm thêm thuộc tính "được chia sẻ" khi chúng được ghi đè bởi các cá thể đã tạo (vui lòng nếu điều này sai, hãy cho tôi biết).

Đây có phải là phương pháp có thể chấp nhận được hay tôi nên bỏ qua di sản trong trường hợp này. Có thể có một số loại kiểm tra và nó sẽ làm cho nó dễ dàng hơn nếu bạn có thể suy ra các loại một (tức là tất cả họ phải là loại QueryStrategy) nhưng tôi không muốn định kiến ​​.Net của tôi để tiếp nhận ở đây.

Alternative tiếp cận

Thứ nhất, tôi không cố gắng để bán sách ở đây, tôi đang chỉ đọc rất nhiều xung quanh vấn đề này với những cuốn sách mà tôi có, nhưng muốn cung cấp tín dụng hợp do của nó.

Dựa trên một vài nhận xét, có thể nói rằng suy luận kiểu sẽ không thực sự tạo ra bất kỳ sự khác biệt nào ở đây và có thể chỉ còn lại để gõ Vịt để kiểm tra và có thể cố gắng sắp xếp thứ gì đó không được định nghĩa trong ngôn ngữ không phải là cách tiếp cận tốt nhất. Tôi đã đọc trong các mẫu Javascript của Addy Osmani về các giao diện, mặc dù việc triển khai của tôi không giống nhau, và mặc dù việc sử dụng giao diện được chấp nhận, nhưng có lẽ không cần thiết. Nó có thể đơn giản hơn để giữ cho phương pháp tiếp cận chiến lược nhưng với một thực hiện khác, một trong đó được nêu trong mẫu Javascript của Stoyan Stefanov, nơi bạn có một thực hiện và dựa trên một số hình thức cấu hình bạn biết chiến lược để sử dụng.

Pseudo mẫu

QueryBuilder = function() { 
    this.types = []; 
} 

QueryBuilder.prototype.create = function (type, query) { 
    var strategy = types[type]; 
    strategy.create(query); 
}; 

QueryBuilder.types.Select = { 

    create: function (query) { 
     params = query.parameters, 
     paramList = query.parameters.length >= 1 ? '' : '*'; 

     for (var i = 0; i < params.length; i++) { 
      var suffix = i === (params.length - 1) ? '' : ', '; 
      paramList = paramList + params[i].key + suffix; 
     } 

     return util.format("SELECT %s FROM %s", paramList, query.entity); 
    } 
}; 

Đó có thể là một cách sạch hơn để đi, có một điều tôi lưu ý chắc chắn về là nếu tôi nên thêm các loại với nguyên mẫu, nhưng tôi đoán trong trường hợp này đơn giản nó wouldn không cần thiết, nhưng trong một kịch bản phức tạp hơn, bạn có thể có rất nhiều chiến lược và trong một tệp có thể cần phải được trừu tượng hóa.

đây có phải là cách tiếp cận được chấp nhận hơn không?

Những gì tôi đã kết thúc với

Tôi nhìn xung quanh và cố gắng để hiểu thêm về vịt đánh máy, thuận và chống, vvvà cố gắng đơn giản hóa thiết kế của tôi dựa trên một số nhận xét và câu trả lời tôi nhận được. Tôi bị mắc kẹt với cách tiếp cận chiến lược-ish trong mỗi chiến lược được định nghĩa cùng một chức năng, về cơ bản đóng gói những gì khác nhau trên các triển khai và cho họ một hợp đồng chung cho muốn có một thuật ngữ tốt hơn.

Một điều đã thay đổi là lớp cơ sở/giao diện, như được chỉ định không thực hiện bất kỳ thứ gì có tính xây dựng đã bị xóa, mỗi chiến lược độc lập (vì vậy không phải 100% trong biểu diễn cổ điển của mẫu). cùng chức năng tạo.

Từ nơi mà các ifs lồng nhau và chuyển mạch đã từng được thay thế bằng một công tắc duy nhất quyết định chiến lược truy vấn nào sẽ sử dụng dựa trên loại truy vấn được yêu cầu. Điều này có thể được tái yếu tố vào một nhà máy sau này, nhưng bây giờ nó phục vụ mục đích của nó:

Query.prototype.generate = function() { 

var self = this, 
    strategy = undefined; 

switch (this.queryType) { 
    case "SELECT": 
     strategy = new Select(self); 
     break; 
    case "INSERT": 
     strategy = new Insert(self); 
     break; 
    case "UPDATE": 
     strategy = new Update(self); 
     break; 
    case "DELETE": 
     strategy = new Delete(self); 
     break; 
} 

return strategy.create(); 
}; 

Mỗi chiến lược được kiểm tra một cách độc lập, và tôi cảm thấy đây là dễ dàng hơn để duy trì như thể một cái gì đó thất bại, nó sẽ thất bại trong một nơi và điều tra sẽ dễ dàng hơn dựa trên các bài kiểm tra đơn vị. Rõ ràng là có một giao dịch tắt, nhiều tệp hơn và cấu trúc phức tạp hơn một chút ... chúng ta sẽ thấy điều gì xảy ra.

+0

Tôi không thực sự nhìn thấy những gì nó đạt bạn, hợp đồng giao diện không được thi hành hoặc thông qua dụng cụ, tại thời gian biên dịch, hoặc khi chạy. Mặt khác, giao diện TypeScript, nếu bạn có thể sử dụng TypeScript, hãy thực thi hợp đồng (tại thời gian biên dịch). –

+0

Sử dụng gõ văn bản – Bergi

+0

Trong cách tiếp cận mới, bạn vẫn không đạt được bất kỳ loại an toàn nào (bạn không thể - đó là javascript). Nếu bạn tôn giáo gắn bó với việc xác định chiến lược ở một nơi có lẽ cách tiếp cận này giúp bảo trì dễ dàng hơn một chút, nhưng bạn vẫn có thể thêm bất kỳ đối tượng nào bạn muốn làm thành viên của các loại []. Nó phụ thuộc vào giả sử của bạn về mục tiêu của bạn là gì ở đây, để thực thi các hợp đồng (bạn không thể - trừ khi kiểm tra tại thời gian chạy) hoặc cái gì khác? –

Trả lời

7

Đây là một cách tiếp cận có thể chấp nhận được nhưng nó không thực sự mang lại lợi ích cho bạn theo bất kỳ cách nào và có thể làm cho đoạn mã này khó khăn hơn để duy trì. Các mẫu Chiến lược thực sự chỉ mang lại lợi ích bằng các ngôn ngữ có tính năng gõ tĩnh. Bạn có thể xem xét TypeScript, như một người bình luận khác đã đề cập.

Trong JavaScript, bạn sẽ dựa nhiều hơn vào "Đánh máy vịt" ... Nếu nó trông giống như một con vịt, có mùi giống như một con vịt, đó có thể là một con vịt.

http://en.wikipedia.org/wiki/Duck_typing

+0

Đánh máy vịt có lẽ là cách để đi, tôi đã thấy việc tạo ra một chức năng giao diện sử dụng gõ Duck để thực thi hợp đồng. https://gist.github.com/1057989. Tôi vẫn nghĩ rằng mô hình chiến lược là hợp pháp ngay cả trong JavaScript. Nhìn vào một cách tiếp cận thay thế, cập nhật câu hỏi. – Modika

+0

Sẽ chấp nhận điều này, nó trả lời câu hỏi ban đầu, và chỉ cho tôi một số đọc thêm. Tôi bị mắc kẹt với giải pháp của tôi trong chính (cập nhật ở trên) nhưng những điều đơn giản dựa trên câu trả lời này và ý kiến ​​khác. – Modika

Các vấn đề liên quan