How do you think, β€œSay, don't ask,” with this simple example?

How would you adhere to the principle of "Tell, do not ask" (hereinafter referred to as the "principle") in the following simple scenario? In the Tetris game, I have the Board, BlockGrid, and Piece classes related to the following example:

public class Board { private var fallingPiece:Piece; private var blockGrid:BlockGrid; ... public function moveFallingPiece(xDirection:int, yDirection:int):void { blockGrid.movePiece(fallingPiece, xDirection, yDirection); } } 

Once fallPiece is placed in the bottom row of the BlockGrid, it should no longer be "fallPiece." Am I right in that I do not violate the principle as follows?

 if(blockGrid.getPiecePosition(piece).y == 0) { fallingPiece = null; } 

But is it really different from this, which, I think, clearly violates the principle?

 public function moveFallingPiece(xDirection:int, yDirection:int):void { if(blockGrid.getPiecePosition(piece).y > 0) { blockGrid.movePiece(fallingPiece, xDirection, yDirection); } else { fallingPiece = null; } } 

I do not suppose that I correctly designed these class relationships to work with this principle. If this is what I am missing, consult an alternative design.


EDIT, Suggested Solution:

I went with answers suggesting "team feedback" through events. The board advises BlockGrid to move the piece. The BlockGrid movePiece method dispatches MOVED_TO or MOVE_FAILED events, depending on the result that the Council can listen to and use to determine if the piece has stopped falling. Please feel free to report this decision.

 public class Board { ... public function Board() { ... blockGrid.addEventListener(PieceMoveEvent.MOVE_FAILED, onPieceMoveFailed); ... } public function moveFallingPiece(xDirection:int, yDirection:int):void { blockGrid.movePiece(fallingPiece, xDirection, yDirection); } public function onPieceMoveFailed(event:MovePieceEvent):void { if(event.instance == currentlyFallingPiece && event.fromPosition.y != event.toPosition.y) { currentlyFallingPiece = null; } } 
+4
source share
4 answers

I think in order to better follow the Tell, Do not Ask principle, you should have a blockGrid notifying your Board class when fallPiece reaches its quiescent point. In both of the scenarios described above, you are requesting blockGrid if position.y == 0 to determine if numPiece should be zero. Instead, you want blockGrid to tell the Board class that fallPiece.y hit 0.

+1
source

What you are looking for is event driven programming. To present events, you need a Listener interface with a .event () method and an Event interface. Objects will be registered with other objects (callbacks) in the Listener interface.

when you create Piece and Board, they must implement the Listener interface. Then you can set the board using registerListener (board); Then, when something happens inside the Piece, it will go through all the registered listeners and call .event (event) for each. Same as in Board, call board.registerListener (pcs.) Each time you create a new play, as it decides what is happening, it can tell all registered listeners what happened. Then you can say a piece that no longer falls on the object of the Council, deciding this. Here is a required Wikipedia article.

+1
source

I would expect a class representing each shape (without location information), a controller containing shape, position, and orientation, and another class representing the current resulting grid of β€œlanding” shapes. A ground grid would have

 testLanded(shape, shapePosition, orientation) 

which will be called before / after each move operation to decide whether the shape should join the placed grid or should move and remain as the falling part.

I'm going to not pass data to objects that should not own this data, but I never implemented Tetris ...

0
source

You may need to rethink your design. Do you need a board to track the falling part, or should it belong to BlockGrid? The iron that owns what behavior.

Store position information in the Piece class and your Piece class may be holding an instance of BlockGrid.

Then you can try something similar in your Board class ...

 public function moveFallingPiece(xDirection:int, yDirection:int):void { blockGrid.moveFallingPiece(xDirection, yDirection); } 

Then in the BlockGrid moveFallingPiece method ...

 public function moveFallingPiece(xDirection:int, yDirection:int):void { fallingPiece.move(xDirection, yDirection); } 

In the figure move method, add your logic ...

 public function move(xDirection:int, yDirection:int):void { setPosition(xDirection, yDirection); if (getPosition().y <= 0) { blockGrid.setFallingPiece(null); // this can bubble up to Board if need be } } 

Not sure about the power of AS3, but it makes sense to use abstractions here. (i.e. your Piece class depends on ITrackFallingPieces instead of BlockGrid and has a BlockGrid to implement ITrackFallingPieces).

Good luck

0
source

Source: https://habr.com/ru/post/1300533/


All Articles