node seneca_使用Node.js和Seneca編寫國際象棋微服務,第2部分

node seneca

處理新需求而無需重構 (Handling new requirements without refactoring)

Part 1 of this series talked about defining and calling microservices using Seneca. A handful of services were created to return all legal moves of a lone chess piece on a chessboard. The series continues in Part 3.

本系列的第1部分討論了使用Seneca定義和調用微服務。 創建了一些服務,以返回棋盤上一個單獨的棋子的所有合法舉動。 該系列在第3部分中繼續。

快速回顧: (A quick review:)

  • Seneca services are identified by a pattern consisting of role and cmd properties. Additional properties can be added to the pattern as well.

    Seneca服務由包含rolecmd屬性的模式標識。 附加屬性也可以添加到模式中。

this.add({role: "movement",cmd: "legalMoves"   //, otherProp: value, ...}, (msg, reply) => {...}
  • Services also have an implementation that takes a msg object and a reply callback. Themsg object contains the pattern properties in addition to all other data sent to the service.

    服務還具有一個接受msg對象和回復回調的實現。 msg對象除了發送到該服務的所有其他數據之外,還包含模式屬性。

  • Seneca.act()is used to indirectly invoke a service. The act method takes an object and a callback function. The object contains the role, cmd, and other properties that comprise the message to the service.

    Seneca.act()用于間接調用服務。 act方法帶有一個對象和一個回調函數。 該對象包含rolecmd和其他屬性,這些屬性構成向服務發送的消息。

seneca.act({role: "movement",cmd: "legalMoves",piece: p,board: board}, (err, msg) => {
  • When an action could be handled by more than one service that matches the pattern, the service with the most specific pattern match will be invoked.

    當一個動作可以由多個與模式匹配的服務來處理時,具有最特定模式匹配的服務將被調用。

There were a handful of services defined in the first part of this series. One of threerawMoves services took a piece and its position as parameters and returned 15 x 15 movement mask. These were truncated to an 8 x 8 board using alegalSquares service. The result was that the services together can return all the legal moves of any piece on any legal square of the otherwise empty chessboard.

在本系列的第一部分中定義了一些服務。 三個rawMoves服務之一將一塊及其位置作為參數,并返回15 x 15移動蒙版。 使用legalSquares服務將它們截斷成8 x 8的木板。 結果是這些服務可以一起返回原本空的棋盤的任何合法廣場上的任何棋子的所有合法移動。

微服務和技術債務 (Microservices and Technical Debt)

One of the motivations for microservices is to reduce technical debt. Every project has deadlines and, as they loom larger, expediency often trumps quality. FIXME and TODO comments litter the source code after a while. Those comments identify technical debt that “someday” will be taken care of.

微服務的動機之一是減少技術債務 。 每個項目都有最后期限,并且隨著期限的增加,權宜之計往往比質量重要。 FIXME和TODO注釋過了一會兒會亂碼源代碼。 這些評論指出了“某天”將得到解決的技術債務。

總有一天永遠不會來 (Someday never comes)

Microservices focus on functional decomposition and loose coupling. Neither of those are new ideas, but it is a rethinking about how to implement those concepts. A microservice should be small, single-purposed, and extensible. Extending a service can happen with few or no side-effects. A new service can extend an existing service, and neither the old service nor the client that once called it will know the service implementation changed. Less refactoring of classes, methods, method signatures, process flow… all this makes it easier to deal with dreaded TD.

微服務專注于功能分解和松散耦合。 這些都不是新想法,但這是對如何實現這些概念的重新思??考。 微服務應小型,單一用途且可擴展。 擴展服務幾乎沒有副作用。 新服務可以擴展現有服務,并且舊服務或曾經調用它的客戶端都不會知道服務實現已更改。 更少的類,方法,方法簽名,過程流的重構……所有這些使得處理可怕的TD更容易。

回到游戲進行中… (Back to the game in progress…)

Moving a single chess piece around a lonely board is not really all that entertaining. In a real chess game the chessboard is shared with friendly and hostile pieces, and these impact each other’s movement.

在一個孤獨的棋盤上移動單個棋子并不是真正有趣的事情。 在真正的國際象棋游戲中,國際象棋棋盤與友善而敵對的棋子共享在一起,這些棋子相互影響著對方的動作。

Right now I have alegalSquares service which can be the basis of a more completelegalMovesservice. If you recall, the legalSquares service would invoke a rawMovesservice, then remove all the ‘bad’ squares that didn’t belong on a chessboard.

現在,我有一個legalSquares服務,可以作為更完整的legalMoves服務的基礎。 如果您還記得的話, legalSquares服務將調用rawMoves服務,然后刪除所有不屬于棋盤的“壞”正方形。

The new legalMoves service will take into account other pieces, something that legalSquares didn’t. This requires an extra parameter, one called board. The board is just going to be an array of ChessPiece instances, and will assume that the pieces on the board have already been checked for validity. For instance, two pieces don’t occupy the same square, pawns aren’t on the first rank, kings aren’t be next to each other, and so forth.

新的legalMoves服務將考慮其他部分,而legalSquares沒有。 這需要一個額外的參數,稱為boardboard將只是一個ChessPiece實例的數組,并將假定棋盤上的棋子已經過有效性檢查。 例如,兩個棋子不在同一廣場上,棋子不在第一位,國王不在彼此之間,依此類推。

The following pattern will identify the service:

以下模式將標識服務:

'role: movement;cmd: legalMoves'

This pattern is a stringified version of JSON called jsonic; you can use a regular JSON object if you prefer. The message to the service will contain the pattern. It will also contain a ChessPiece instance that has a piece type such as ‘K’ing, ‘Q’ueen, ‘R’ook and board position (see algebraic notation). Later I’ll add to this class a piece color (White or Black) so that the service can tell friend from foe. But for now the service will assume all pieces are friendly.

此模式是JSON的字符串化版本,稱為jsonic ; 您可以根據需要使用常規JSON對象。 發送給服務的消息將包含該模式。 它還將包含一個ChessPiece實例,其實例類型為“ K”,“ Q”,“ R”和棋盤位置(參見代數表示法)。 稍后,我將在該類中添加一塊顏色(白色或黑色),以便該服務可以將敵人告訴朋友。 但就目前而言,該服務將假定所有部件都友好。

Since a friendly piece cannot be captured, it will restrict movement of other friendly pieces. Determining those restrictions is a bit of work. I made it harder for myself in the implementation of the rawMoves service… which brings me to:

由于無法捕獲一個友善的棋子,它將限制其他友善棋子的移動。 確定這些限制需要一些工作。 在執行rawMoves服務時,我自己變得更加困難……這使我從事以下工作:

微服務不是萬能藥 (Microservices are not a Panacea)

If you design a service that retrieves or calculates information and doesn’t pass that data on up the chain, some service upstream may have to redo that work later. In my example, rawMoves returned an array of move objects (file and rank positions on the board). Let’s take the method that generates diagonal moves for a piece using the rawMoves service:

如果您設計的服務可以檢索或計算信息, 但不會在鏈上傳遞該數據,則上游的某些服務可能必須稍后重做。 在我的示例中, rawMoves返回了一組移動對象(板上的文件和排名位置)。 讓我們采用使用rawMoves服務為一塊生成對角線移動的方法:

module.exports = function diagonal(position, range = 7) {var moves = [];const cFile = position.file.charCodeAt()const cRank = position.rank.charCodeAt();for (var i = 1; i < range + 1; i++) {moves.push({file: String.fromCharCode(cFile - i),rank: String.fromCharCode(cRank - i)});moves.push({file: String.fromCharCode(cFile + i),rank: String.fromCharCode(cRank + i)});moves.push({file: String.fromCharCode(cFile - i),rank: String.fromCharCode(cRank + i)});moves.push({file: String.fromCharCode(cFile + i),rank: String.fromCharCode(cRank - i)});}return moves;
}

At first glance, there’s nothing wrong with this. But, those fourmove.push operations actually operate along movement vectors. I could have constructed four movement vectors, then returned a list of moves by concatenating them, like so:

乍看之下,這沒有什么錯。 但是,這四個move.push操作實際上是沿著運動矢量進行操作的。 我本可以構造四個運動矢量,然后通過將它們連接起來返回一個運動列表,如下所示:

function diagonalMoves(position, range) {var vectors = [[], [], [], []];const cFile = position.file.charCodeAt()const cRank = position.rank.charCodeAt();for (var i = 1; i < range + 1; i++) {vectors[0].push({file: String.fromCharCode(cFile - i),rank: String.fromCharCode(cRank - i)});vectors[1].push({file: String.fromCharCode(cFile + i),rank: String.fromCharCode(cRank + i)});vectors[2].push({file: String.fromCharCode(cFile - i),rank: String.fromCharCode(cRank + i)});vectors[3].push({file: String.fromCharCode(cFile + i),rank: String.fromCharCode(cRank - i)});}const moves = Array.prototype.concat(...vectors)return moves;
}

As it stood, there was no point in doing this. But later on those vectors would have come in handy for truncating movements along diagonals (or ranks or files) when a friendly piece is in the way. Instead, I had to decompose the move list along vectors in services upstream — more work and inefficiency which you will see later.

就目前而言,這樣做是沒有意義的。 但是后來,當友好片段出現時,這些矢量將可以方便地沿對角線(或等級或文件)截斷運動。 取而代之的是,我不得不沿著上游服務中的向量分解移動列表,這會增加工作量和效率,這將在以后看到。

The real flaw, though, was that I returned an array, rather than a data object. Data objects have properties that are extendable, not so arrays. As a consequence, all my upstream services depend on receiving a movement array, and only a movement array. No flexibility. I can’t now add a list of movement vectors in addition to a move list. But I could if I had returned an object from this method and the service that called it instead.

但是,真正的缺陷是我返回了一個數組,而不是一個數據對象。 數據對象具有可擴展的屬性,而不是數組。 結果,我所有的上游服務都依賴于接收移動數組, 并且只有一個運動數組。 沒有靈活性。 我現在不能添加除了運動向量的列表 到移動列表。 但是我可以從該方法和調用它的服務中返回一個對象。

Lesson learned? Consider returning data objects from your services. Have your upstream services work on parts of the data, but pass all data they receive back upstream. Exceptions to this rule will abound, of course.

學過的知識? 考慮從服務中返回數據對象。 讓上游服務處理部分數據,但將它們接收的所有數據傳回上游。 當然,會有很多例外。

和像這樣的朋友一起... (With Friends like These…)

In Part 1, there was a service under the pattern:

在第1部分中,使用以下模式提供服務:

role:"movement",cmd:"legalSquares"

role:"movement",cmd:"legalSquares"

It returned all moves of an unimpeded piece. Since this will be the base service for determining legal moves on a populated chessboard, I’ll rename the cmdto legalMoves. Now I want to extend that to take into account friendly pieces that might be blocking a path of my chosen piece.

它返回了一塊暢通無阻的動作。 由于這將是確定填充棋盤上法律動作的基本服務,因此我將cmd重命名為legalMoves 。 現在,我想擴展該范圍,以考慮到可能會阻礙我選擇的作品路徑的友好作品。

擴展服務 (The extended service)

The service that extends role:"movement",cmd:"legalMoves" is… role:"movement",cmd:"legalMoves" !

擴展role:"movement",cmd:"legalMoves"是… role:"movement",cmd:"legalMoves"

Yep, it has the same service pattern as the service it calls. You may recall that services are identified by pattern, and so how it this going to work? When the program acts on role:"movement",cmd:"legalMoves", it will use the most recently defined service. But the new service has to call the formerlegalMoves service. That can be solved easily:

是的,它具有與其調用的服務相同的服務模式。 您可能還記得,服務是通過模式來標識的,那么它如何工作? 當程序執行role:"movement",cmd:"legalMoves" ,它將使用最新定義的服務。 但是新服務必須調用以前的legalMoves服務。 這很容易解決:

this.add({role: "movement",cmd: "legalMoves"}, (msg, reply) => {//returns unimpeded moves}this.add('role:movement,cmd:legalMoves', function (msg, reply) {this.
prior(msg, function (err, moves) {if (msg.board) {const boardMoves = legalMovesWithBoard(msg, moves);reply(err, boardMoves);return;}reply(err, moves);});});

This new service is able to call the former service by using the prior() method in Seneca. If no board parameter is supplied in the incoming msg object, then this service will just act as a pass-thru to the former service. But what if there is a board?

通過使用Seneca中的Priority prior()方法,此新服務可以調用以前的服務。 如果傳入的msg對象中未提供board參數,則此服務將msg當前一個服務的直通。 但是,如果有董事會呢?

I’m not going to show a complete code listing here (see link below), but the gist of it is:

我不會在此處顯示完整的代碼清單(請參見下面的鏈接),但是要點是:

module.exports = function (msg, moves) {if (!msg.board) return moves;const blockers = moves.filter(m => {return (msg.board.pieceAt(m))})var newMoves = [];const pp = msg.piece.position;const rangeChecks = {B: diagonalChecks,R: rankAndFileChecks,K: panopticonChecks,Q: panopticonChecks,P: pawnChecks,N: knightChecks};var rangeCheck = rangeChecks[msg.piece.piece];// console.error(msg.piece.piece, rangeCheck.name)newMoves = moves.filter(m => {return rangeCheck(m, blockers, pp);})return newMoves;
}

Remember our old friend diagonalMoves from the rawMoves service? In order to do a range check on diagonals without handy vectors, the new legalMoves service calls this:

還記得我們來自rawMoves服務的老朋友diagonalMoves rawMoves嗎? 為了對不帶方便向量的對角線進行范圍檢查,新的legalMoves服務將其稱為:

Ugly, no? I’d be happy if some algorithmically-inclined reader reduced this to two lines in the comments section. Three, even.

丑陋,不是嗎? 如果某些有算法傾向的讀者在評論部分將其減少到兩行,我將感到高興。 三,甚至。

So that takes care of friendly pieces. The next installment will deal with hostile pieces, which can be captured.

這樣就可以處理友好的片段。 下一部分將處理可捕獲的敵對碎片。

Full source code for this article can be found at GitHub.

可以在GitHub上找到本文的完整源代碼。

翻譯自: https://www.freecodecamp.org/news/follow-the-rules-with-seneca-ii-c22074debac/

node seneca

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/395234.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395234.shtml
英文地址,請注明出處:http://en.pswp.cn/news/395234.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【OCR技術系列之八】端到端不定長文本識別CRNN代碼實現

CRNN是OCR領域非常經典且被廣泛使用的識別算法&#xff0c;其理論基礎可以參考我上一篇文章&#xff0c;本文將著重講解CRNN代碼實現過程以及識別效果。 數據處理 利用圖像處理技術我們手工大批量生成文字圖像&#xff0c;一共360萬張圖像樣本&#xff0c;效果如下&#xff1a;…

mysql 修改字段類型死鎖_mysql數據庫死鎖的產生原因及解決辦法

數據庫和操作系統一樣&#xff0c;是一個多用戶使用的共享資源。當多個用戶并發地存取數據 時&#xff0c;在數據庫中就會產生多個事務同時存取同一數據的情況。若對并發操作不加控制就可能會讀取和存儲不正確的數據&#xff0c;破壞數據庫的一致性。加鎖是實現數據庫并 發控制…

openwrt無盤服務器,搭建基于 OpenWrt/gPXE/iSCSI 的 Windows 無盤工作站

本文要介紹的是如何在 OpenWrt 平臺上面搭建無盤工作站服務器以及 Windows 的 iSCSI 部署。當然&#xff0c;由于 OpenWrt 也可以算得上一種 Linux 發行版了&#xff0c;所以本文所介紹的一些方法&#xff0c;在其它 Linux 發行版上面仍有一定的參考價值。整個過程大概分為以下…

Ralink5350開發環境搭建

一、安裝虛擬機(Oracle VM VirtualBox 或 VMware Workstation) 二、在虛擬機中安裝linux操作系統&#xff08;當前使用的是Ubuntu1204桌面版&#xff09; 三、配置linux相關服務 安裝、配置、啟動ftp服務apt-get install vsftpd 改動 vsftpd 的配置文件 /etc/vsftpd.conf,將以…

figma下載_Figma重新構想的團隊庫

figma下載一個新的&#xff0c;功能更強大的界面&#xff0c;用于在整個組織中共享組件 (A new, more powerful interface for sharing Components across your organization) The Team Library in Figma is a set of shared Components across all files in a Team. Component…

boost python導出c++ map_使用Boost生成的Python模塊:與C++簽名不匹配

我正在使用名為Mitsuba的軟件。它附帶了一個用Boost包裝的Python實現。 Python中的這一行&#xff1a;使用Boost生成的Python模塊&#xff1a;與C簽名不匹配scene SceneHandler.loadScene(fileResolver.resolve("model.xml"), paramMap)產生一個錯誤。根據文檔&…

CSU-1982 小M的移動硬盤

CSU-1982 小M的移動硬盤 Description 最近小M買了一個移動硬盤來儲存自己電腦里不常用的文件。但是他把這些文件一股腦丟進移動硬盤后&#xff0c;覺得這些文件似乎沒有被很好地歸類&#xff0c;這樣以后找起來豈不是會非常麻煩&#xff1f; 小M最終決定要把這些文件好好歸類&a…

杜比服務器系統安裝教程,win10杜比音效如何安裝?win10安裝杜比音效的詳細教程...

杜比音效想必大家都不陌生&#xff0c;聽歌或者看電影開啟杜比音效可以給人一種身臨其境的感覺。不少朋友都升級了win10系統卻不知道如何安裝杜比音效&#xff1f;如何為自己的系統安裝杜比音效呢&#xff1f;感興趣的小伙伴請看下面的操作步驟。win10安裝杜比音效的方法&#…

劍指Offer_52_正則表達式匹配

題目描述 請實現一個函數用來匹配包括.和的正則表達式。模式中的字符.表示任意一個字符&#xff0c;而表示它前面的字符可以出現任意次&#xff08;包含0次&#xff09;。 在本題中&#xff0c;匹配是指字符串的所有字符匹配整個模式。例如&#xff0c;字符串"aaa"與…

分布式系統開發注意點_分布式系統注意事項

分布式系統開發注意點by Shubheksha通過Shubheksha 分布式計算概述&#xff1a;分布式系統如何工作 (Distributed Computing in a nutshell: How distributed systems work) This post distills the material presented in the paper titled “A Note on Distributed Systems”…

前端if else_應該記錄的一些項目代碼(前端)

1.共享登錄&#xff08;單點登錄&#xff09;主要是前端部分主要是根據是否有cookie來判斷是否已經登錄主系統&#xff0c;然后再根據是否有當前系統的登錄信息來&#xff08;這塊主要是sessionStorage做的&#xff09;判斷是否要再登錄當前系統。設置、讀取和設置cookie的方法…

Mac端解決(含修改8.0.13版的密碼):Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)...

1. 安裝mysql但是從來沒啟動過&#xff0c;今天一啟動就報錯&#xff1a; Cant connect to local MySQL server through socket /tmp/mysql.sock (2) 其實是mysql服務沒起來。。。 localhost:~ miaoying$ mysql.server start Starting MySQL ... SUCCESS! 然后再去sudo mysql就…

塔塔建網站服務器,塔塔帝國忘記哪個區怎么辦

7條解答1.在哪個區玩戰艦帝國忘記了怎么辦?忘了的話可以去官網登陸看看自己的 充值 或者禮包記錄 有沒有對應的區服 或者電話聯系問問客服 通過賬號 角色名字來查詢2.我忘記在哪個區怎么找如果你有游戲人生資格的話&#xff0c;就很容易找了&#xff0c;在游戲人生的個人主頁里…

Ixia推出首款太比特級網絡安全測試平臺

2016年11月18日&#xff0c;Ixia宣布推出全新CloudStorm平臺。作為首款太比特級網絡安全測試平臺&#xff0c;該平臺擁有前所未有的非凡性能&#xff0c;可用于測試及驗證超大規模云數據中心不斷擴大的容量、效率以及彈性。 ▲Ixia CloudStorm安全測試平臺 CloudStorm的正式面市…

[轉]oracle分析函數Rank, Dense_rank, row_number

oracle分析函數Rank, Dense_rank, row_number 分析函數2(Rank, Dense_rank, row_number) 目錄1.使用rownum為記錄排名2.使用分析函數來為記錄排名3.使用分析函數為記錄進行分組排名一、使用rownum為記錄排名&#xff1a; 在前面一篇《Oracle開發專題之&#xff1a;分析函數》&a…

Bali BaloCSS天才

Today Bali Balo, a French designer and developer, published a new piece: a cube suspended in darkness that rotates on its own. As it does, it reveals different sides, each offering a glimpse into a different world:今天&#xff0c;法國設計師兼開發商Bali Bal…

luogu P2470 [SCOI2007]壓縮

傳送門 dalao們怎么狀態都設的兩維以上啊?qwq 完全可以一維狀態的說 設\(f[i]\)為前綴i的答案,轉移就枚舉從前面哪里轉移過來\(f[i]min(f[j-1]w(j,i))(j\in [1,i])\) 現在要知道\(w(i,j)\)怎么寫,也就是區間\([i,j]\)的最小長度(要求區間最多只能在開頭有一個W),首先不壓縮的長…

服務器選擇重裝系統,云服務器重裝系統選擇

云服務器重裝系統選擇 內容精選換一換將外部鏡像文件注冊成云平臺的私有鏡像后&#xff0c;您可以使用該鏡像創建新的云服務器&#xff0c;或對已有云服務器的系統進行重裝和更換。本節介紹使用鏡像創建云服務器的操作。您可以按照通過鏡像創建云服務器中的操作指導創建彈性云服…

T-Mobile美國加速開展5G實驗:28GHz頻段成為新寵

據日經社報道&#xff0c;T-Mobile美國公司正在加速開展5G相關工作&#xff0c;在過去的一個月中動作頻頻。 T-Mobile美國與三星電子美國公司上月初共同宣布&#xff0c;將在今年下半年使用28GHz頻段和配備三星的波束成形技術的5G驗證實驗系統&#xff0c;開展室外5G移動通信的…

軟件項目可行性分析定義_如何定義最低可行產品

軟件項目可行性分析定義by George Krasadakis通過喬治克拉薩達基斯(George Krasadakis) 如何定義最低可行產品 (How to define a Minimum Viable Product) 從概念轉變為正確定義的MVP (Moving from a concept to a properly defined MVP) The Minimum Viable Product, althoug…