2

Tic-Tac-Toe 구현을 위해 Rx.Net을 사용하여 기능 - 반응 프로그래밍에 대해 더 자세히 배우려고합니다. 내가 가지고있는 문제는 내 게임 논리에 순환 의존성이있는 것 같다.FRP (Rx.Net)에서 순환 종속성을 어떻게 모델링해야합니까?

스트림 (PlaceToken, ResetGame 등)은 사용자 입력 스트림에서 생성됩니다.

게임 (boardStates)의 현재 상태가 초기 상태에서 시작하여 이전의 상태로 commands를 적용하여 산출된다

var initialBoardState = new BoardState(); 

var boardStates = commands 
    .Scan(initialBoardState, (boardState, command) => command.Apply(boardState)) 
    .DistinctUntilChanged(); 

그러나 commands 스트림이 boardStates 스트림에 의존한다. 유효한 명령 세트가 현재 상태와 함께 변경되기 때문입니다.

예를 들어, PlaceToken 명령은 사용자가 빈 타일을 클릭 할 때만 발행해야하지만 빈 타일 세트는 현재 상태로 정의됩니다!

요약하면, 나는 서로에게 의존하는 것처럼 보이는 두 가지 흐름이 있습니다. 기능 대응 형 프로그래밍에서이 문제를 해결하려면 어떻게해야합니까?

+1

정말 [mcve]가 필요합니다. – Enigmativity

답변

1

@ LeeCampbell의 솔루션이 작동하지만 핵심 모델 클래스를 변경할 수 있어야합니다. 대신 cycle.js에서 사용한 방법을 복사하는 것이 가장 좋습니다. 그들의 설명은 here입니다.

문제는주기가 있다는 것입니다.

// Create a proxy 
proxyActionStream = new Stream() 

// Create our mutually dependent streams using the proxy 
boardStream = f(proxyActionStream) 
actionStream = g(boardStream) 

// Feed actionStream back into proxyActionStream 
actionStream.Subscribe(x => proxyActionStream.OnNext(x)) 
:

boardStream = f(actionStream) 
actionStream = g(boardStream) 

cycle.js 솔루션은 모든 것을 함께 연결할하기 위해 프록시 스트림을 사용하는 것입니다 : 작업 스트림이 차례로 행동의 흐름에 따라 보드 상태의 흐름에 따라 달라집니다

Rx.Net에서 프록시 스트림은 ReplaySubject이어야합니다.

조심해야 할 유일한 곳은 런 - 어웨이 피드백 루프입니다. 스트림이 안정되지 않으면 무한 루프가 발생합니다! 스트림을 상호 재귀라고 생각하면 도움이됩니다.

1

모든 것이 이벤트 일 필요는 없습니다. Rx/콜백은 당신이 의존하고있는 것을 허용하는 방법이며, (당신에게 의존하지 않고) 다시 전화하는 것을 기억하십시오. 엄지 손가락의 규칙으로

  1. 순환 종속성이
  2. 이 명령을 보내기 설계 결함을 표시, 수신 이벤트

2)도 번역 될 수

에 의존성에 대한 메소드를 호출하여 상태를 변경하면되지만, subscri 그들의 이벤트를보고 그들의 변경 사항을 볼 수있다.

이렇게 명령을 스트림으로 생각하는 대신, 사용자 동작을 듣고 명령을 만들 수있는 스트림으로 생각해야한다.

는 그래서 BoardState이

public class BoardState 
{ 
    public void PlaceToken(PlaceTokenCommand placeToken) 
    { 
     //Process, then raise event 
    } 

    public void Reset() 
    { 
     //Process, then raise event 
    } 

    public IObservable<?> StateUpdates() 
    { 

    } 
} 

와 뷰 모델처럼 보일 수있다 (?) 코드는 다음과 같이 보일 수

public class TicTacToeViewModel 
{ 
    private readonly BoardState _board; 
    public TicTacToeViewModel() 
    { 
     _board = new BoardState(); 
     MoveTokenCommand = new DelegateCommand(MoveToken, CanMoveToken); 
     ResetBoardCommand = new DelegateCommand(_board.Reset); 

     board.StateUpdates(state => UpdatePresentation(state)); 
    } 

    public DelegateCommand MoveTokenCommand { get; private set;} 
    public DelegateCommand ResetBoardCommand { get; private set;} 


    private void MoveToken() 
    { 
     var token = CurrentToken; 
     var location = ActiveLocation; 
     var cmd = new PlaceTokenCommand(token, location); 
     _board.PlaceToken(cmd); 
    } 

    private bool CanMoveToken() 
    { 
     //? 
    } 
} 

그러나 @Enigmativity, 코멘트에 요청, 같은없이

현명한 도움을 제공하는 것은 매우 어렵습니다.

마지막 메모, Rx가 기능적이며 반응성이있는 동안 광신자는 RX3800에 해당하지 않습니다. FRP (Conal, Behaviors 등 참조).

관련 문제