revisiting robocode state with generics

In my robocode series I've reworked my code into bounded contexts and so far I have a robot that does not get disabled in battle and can report that it reached turn fifty.
However, it still does very little and does not move or scan for enemies.
I have an additional acceptance test that ensures I win against the sitting duck robot so my next piece of work is to get this test to pass. I think this is going to need some more decision context work and the introduction of some new bounded contexts.

Before I reworked my code to use domain driven design concepts, I had a simple observer that at the start of the battle issued instructions for the robot to look for enemies. I want to re-implement this in one of my contexts and I decide that the manipulation context is the best location for this as I will be manipulating the robot with this observation.

I start to write my specifications for the ManipulationContextTranslator and this suggests I require a ManipulationState and thus something to keep and update this state, for example ManipulationStateKeeper.

When beginning the specs for this, it is clear that the code is almost exactly the same as the previous DecisionStateKeeper so I decide to stop and instead see if I can make any of this code reusable, using the existing DecisionStateKeeper as the blueprint and running its unit test as I go.

Here's what I originally had in the DecisionStateKeeper as a reminder:

    public class DecisionStateKeeper : IKeepDecisionState, IUpdateDecisionState
    {
        DecisionState internalDecisionState;

        public DecisionStateKeeper(IEnumerable<IObserveToMakeDecisions> 
decisionMakingObservers) { CreateObservableForDecisionState(); foreach (var observer in decisionMakingObservers) { observer.Observe(this); } } public IObservable<IEvent<DecisionState>> Situation { get; private set; } event EventHandler<DecisionState> DecisionStateHasUpdated; void CreateObservableForDecisionState() { Situation = Observable.FromEvent<DecisionState>( ev => this.DecisionStateHasUpdated += ev, ev => this.DecisionStateHasUpdated -= ev); } public void UpdateState(Action<DecisionState> decisionStateUpdate) { decisionStateUpdate(InternalDecisionState); DecisionStateHasUpdated(this, InternalDecisionState); } protected DecisionState InternalDecisionState { get { return internalDecisionState ?? (internalDecisionState = new DecisionState()); } } }

To make this generic I start with a StateKeeper (compiler errors shown in red and I'm omitting any StateKeeper specific specs in this email for brevity):

    public abstract class StateKeeper<State> : IUpdateState<State>
    {

    }

    public interface IUpdateState<State>
    {
        void UpdateState(Action<State> stateUpdate);
    }

I have a new generic interface to replace the specific IUpdateDecisionState and I'm not implementing the underlying member, so have a compilation error. I introduce that member and pull the code from the original state keeper in:

    public abstract class StateKeeper<State> : IUpdateState<State>
    {
        public void UpdateState(Action<State> stateUpdate)
        {
            stateUpdate(InternalState);
            StateHasUpdated(this, InternalState);
        }
    }

I need to pull more code in from the original class to make this work:

    public abstract class StateKeeper<State> : IUpdateState<State>
    {
        State internalState;

        State InternalState
        {
            get
            {
                return internalState ?? (internalState = xxxx? );
            }
        }

        protected event EventHandler<State> StateHasUpdated;

        public void UpdateState(Action<State> stateUpdate)
        {
            stateUpdate(InternalState);
            StateHasUpdated(this, InternalState);
        }
    }

I've now got two issues - the State generic type does not derive from EventArgs and I need to be able to create a new State if the internal state is not available. I can fix both issues with the following:

    public abstract class StateKeeper<State> : IUpdateState<State>
        where State : EventArgs
    {
        State internalState;

        State InternalState
        {
            get
            {
                return internalState ?? (internalState = EnsureThatStateHasBeenCreated());
            }
        }

        protected abstract State EnsureThatStateHasBeenCreated();

        protected event EventHandler<State> StateHasUpdated;

        public void UpdateState(Action<State> stateUpdate)
        {
            stateUpdate(InternalState);
            StateHasUpdated(this, InternalState);
        }
    }

I now have an abstract method to ensure that the state gets created and I have a generic type constraint on my class.
My next step is to make the IKeepDecisionState interface more generic:

    public interface IKeepState<State>
    {
        IObservable<IEvent<State>> Situation { get; }
    }

The StateKeeper also needs to implement this interface and I pull in the constructor code from the DecisionStateKeeper:

    public abstract class StateKeeper<State> : IUpdateState<State>, IKeepState<State>
        where State : EventArgs
    {
        State internalState;

        State InternalState
        {
            get
            {
                return internalState ?? (internalState = EnsureThatStateHasBeenCreated());
            }
        }

        protected abstract State EnsureThatStateHasBeenCreated();

        protected event EventHandler<State> StateHasUpdated;

        public void UpdateState(Action<State> stateUpdate)
        {
            stateUpdate(InternalState);
            StateHasUpdated(this, InternalState);
        }

        public IObservable<IEvent<State>> Situation { get; private set; }

        public StateKeeper()
        {
            CreateObservableForDecisionState();
        }
    }

I now have my observable at the bottom of this class and I have the constructor from the old DecisionStateKeeper.
This now presents me with a problem - I can make this method an abstract method but this would be bad thing to do.

Calling a virtual method from a constructor is a very bad idea - the base class constructors are called before the derived version so it is not good practice to call out to the derived class until it has been initialised.
I therefore need to move this to the situation property itself when it is accessed:

    public abstract class StateKeeper<State> : IUpdateState<State>, IKeepState<State>
        where State : EventArgs
    {
        IObservable<IEvent<State>> situation;
        State internalState;

        State InternalState
        {
            get
            {
                return internalState ?? (internalState = EnsureThatStateHasBeenCreated());
            }
        }

        protected abstract State EnsureThatStateHasBeenCreated();

        protected abstract IObservable<IEvent<State>> EnsureThatTheObservableHasBeenCreated();

        protected event EventHandler<State> StateHasUpdated;

        public void UpdateState(Action<State> stateUpdate)
        {
            stateUpdate(InternalState);
            StateHasUpdated(this, InternalState);
        }

        public IObservable<IEvent<State>> Situation
        {
            get
            {
                return situation ?? ( situation = EnsureThatTheObservableHasBeenCreated());
            }
        }

        public StateKeeper() { }
    }

I now create the observable situation when it is first accessed and there is an abstract method to ensure this happens.

The final piece of this generic work is to introduce the observers - I need a generic interface for this to replace the IObserveToMakeDecisions interface that took in a DecisionStateKeeper and made observations on it:

    public interface IContextObserver<State>
    {
        void Observe(IKeepState<State> stateKeeper);
    }

To implement this in the StateKeeper I have two choices: I can either use IContextObserver<State> directly or I can declare another generic type for the observers, abstracting that interface type. Samples of both are shown below:

    public abstract class StateKeeper<State> : IUpdateState<State>, IKeepState<State>
        where State : EventArgs
    {
        IEnumerable<IContextObserver<State>> observers;

        public StateKeeper(IEnumerable<IContextObserver<State>> observers) { }
    }

    public abstract class StateKeeper<State, Observer> : IUpdateState<State>, IKeepState<State>
        where Observer : IContextObserver<State>
        where State : EventArgs
    {
        IEnumerable<Observer> observers;

        public StateKeeper(IEnumerable<Observer> observers) { }
    }

I prefer the second option so am going to run with that. I now implement the observers in full:

    public abstract class StateKeeper<State, Observer> : IUpdateState<State>, IKeepState<State>
        where Observer : IContextObserver<State>
        where State : EventArgs
    {
        IObservable<IEvent<State>> situation;
        State internalState;

        State InternalState
        {
            get
            {
                return internalState ?? (internalState = EnsureThatStateHasBeenCreated());
            }
        }

        protected abstract State EnsureThatStateHasBeenCreated();

        protected abstract IObservable<IEvent<State>> EnsureThatTheObservableHasBeenCreated();

        protected event EventHandler<State> StateHasUpdated;

        public void UpdateState(Action<State> stateUpdate)
        {
            stateUpdate(InternalState);
            StateHasUpdated(this, InternalState);
        }

        public IObservable<IEvent<State>> Situation
        {
            get
            {
                return situation ?? ( situation = EnsureThatTheObservableHasBeenCreated());
            }
        }

        public StateKeeper(IEnumerable<Observer> observers)
        {
            foreach (var observer in observers)
            {
                observer.Observe(this);
            }
        }
    }

I've now got my first cut of this generic class and this changes the Decision State Keeper and the future Manipulation State Keeper dramatically.
I'll leave you with the now more lightweight and cleaner Decision State Keeper and in my next post I'll discuss one of the domain driven design issues with the observers themselves that is caused by this change.

    public class DecisionStateKeeper : StateKeeper<DecisionState, IObserveToMakeDecisions>
    {
        public DecisionStateKeeper(IEnumerable<IObserveToMakeDecisions> observers) 
                                                                   : base(observers)
        {
        }

        protected override DecisionState EnsureThatStateHasBeenCreated()
        {
            return new DecisionState();
        }

        protected override IObservable<IEvent<DecisionState>> 
                                           EnsureThatTheObservableHasBeenCreated()
        {
            return Observable.FromEvent<DecisionState>(
                ev => this.StateHasUpdated += ev,
                ev => this.StateHasUpdated -= ev);
        }
    }

    public interface IObserveToMakeDecisions : IContextObserver<DecisionState>
    {
    }



0 comments: