State-based Behavior II SWEN-261 Introduction to Software - - PowerPoint PPT Presentation

state based behavior ii
SMART_READER_LITE
LIVE PREVIEW

State-based Behavior II SWEN-261 Introduction to Software - - PowerPoint PPT Presentation

State-based Behavior II SWEN-261 Introduction to Software Engineering Department of Software Engineering Rochester Institute of Technology There are a number of benefits for explicitly modeling state-based behavior. Explicitly defining


slide-1
SLIDE 1

SWEN-261 Introduction to Software Engineering

Department of Software Engineering Rochester Institute of Technology

State-based Behavior II

slide-2
SLIDE 2

There are a number of benefits for explicitly modeling state-based behavior.

  • Explicitly defining this state-based behavior

provides a common specification for the team.

  • Allowing the state behavior to evolve implicitly

creates a situation where every team member may have a different model of the behavior.

  • You can model state-based behavior in many

areas of your software system.

  • Web application interface
  • User interface
  • Individual class-behavior

2

Today's discussion

slide-3
SLIDE 3

With class behavior modeled, you may decide to have the states be implicit in the implementation.

  • Allow the state definition to implicitly evolve
  • Standard approach as behavior develops
  • Maintain information in a collection of attributes
  • State is defined as logical combinations of values
  • Consider that you are implementing scoring for
  • bowling. What information do you need to use?
  • How many combinations are there?

3

  • Balls thrown
  • Pins knocked down
  • Frame number
  • Previous strike or spare
  • Previous frame score
slide-4
SLIDE 4

Here is what one Intro to SE team turned that approach into.

if (pe.pinsDownOnThisThrow() >= 0) { if (frameNumber == 9) { if (pe.totalPinsDown() == 10) { if(pe.getThrowNumber() == 1) { if ((pe.totalPinsDown() != 10) && (pe.getThrowNumber() == 2 && tenthFrameStrike == false)) { if (pe.getThrowNumber() == 3) { if (pe.pinsDownOnThisThrow() == 10) { } else if (pe.getThrowNumber() == 2) { } else if (pe.getThrowNumber() == 3) { if( i%2 == 1 && curScore[i - 1] + curScore[i] == 10 && i < current - 1 && i < 19){ if (i > 1) { } else if( i < current && i%2 == 0 && curScore[i] == 10 && i < 18){ if (curScore[i+2] != -1) { if(curScore[i+3] != -1) { } else if(curScore[i+4] != -1) { if (strikeballs == 2){ if(curScore[i+1] != -1) { if (curScore[i+2] != -1){ if( curScore[i+2] != -2){ if( curScore[i+3] != -2){ if ( i/2 > 0 ){ if (curScore[i+3] != -1){ if( curScore[i+3] != -2){ if( i%2 == 0 && i < 18){ if ( i/2 == 0 ) { if(curScore[i] != -2){ } else if (i/2 != 9){ if(curScore[i] != -2){ } else if (i < 18){ if(curScore[i] != -1 && i > 2){ if(curScore[i] != -2){ if (i/2 == 9){ if (i == 18){ if(curScore[i] != -2){ } else if (i/2 == 10) { if(curScore[i] != -2){

4

38 if statements in a file of 621 lines of code.

slide-5
SLIDE 5

You should not be afraid to implement state-based behavior using explicit states.

  • It may seem more complex but in the end it often is
  • Easier to implement
  • Easier to expand
  • Easier to understand
  • Easier to maintain
  • Alan Skorkin gives the following reason for

developers not using states explicitly.

5

… early on you don't feel like your objects' state machine behaviour is complex enough to warrant a "full-blown" state machine (YAGNI and all that jazz), but later on – when it IS complex enough – you feel like you've invested too much time/effort to replace it with something that has equivalent functionality. It's a bit

  • f a catch-22. It's overkill and by the time it's not, it's too late.

Alan Skorkin Why Developers Never Use State Machines

slide-6
SLIDE 6

Explicitly using states in the implementation provides an easier model to code translation.

  • There are multiple approaches that you can use for

an implementation with explicit states.

  • Switch-based implementation
  • State-transition table (2 dimensions: states x events)
  • State design pattern
  • These are discussed in the book chapter listed in

the resources for this lesson.

6

Today's discussion

slide-7
SLIDE 7

You need to decide how you will implement the core aspects of a state machine.

  • States
  • State attribute in class
  • Separate class for each

state

  • Events
  • Calling a method
  • Event dispatch
  • Interrupt
  • Time out
  • End of an activity.
  • Transitions
  • Setting state attribute
  • Transition class
  • Guards
  • If statement tests
  • Explicit guard methods
  • Actions
  • Statement execution
  • Explicit action methods

7

Simplest approach for switch-based implementation.

slide-8
SLIDE 8

Here are the mechanics for the simplest to understand switch-based implementation.

  • Use an enum to define the states.
  • Current state is stored in a class attribute.
  • Transition to a new state by changing current state.
  • Every method on the interface will be

implemented with a switch on the current state.

  • Events will be method calls.
  • Guards will be if statement conditions.
  • Actions will be statements executed in the event

method.

  • Use private helper methods as needed.

8

slide-9
SLIDE 9

We will go back and consider the state-based behavior of the Guessing Game sample webapp.

  • What states does a GuessGame object have?
  • There is more than one possible set of states.
  • Here is one possible statechart for its behavior.

9

slide-10
SLIDE 10

In the original implementation, the states are encoded implicitly in combinations of attributes.

  • The game is lost

public synchronized boolean hasMoreGuesses() { return howManyGuessesLeft > 0; }

  • The game is won – detected as return value from

makeGuess()

return myGuess == numberToGuess;

  • Waiting for another guess

public synchronized boolean hasMoreGuesses() { return howManyGuessesLeft > 0; }

10

slide-11
SLIDE 11

You start with a definition of the states and an attribute to hold the current state.

/** * States for the game in a state-based implementation. */ private enum State {WAIT_FOR_GUESS, GAME_WON, GAME_LOST} /** * The current state the object is in. */ private State currentState = State.WAIT_FOR_GUESS; 11

slide-12
SLIDE 12

With the state-based implementation the states are explicitly coded.

public synchronized boolean makeGuess(final int myGuess) { boolean validGuess = false; switch (currentState) { case WAIT_FOR_GUESS: if (myGuess >= 0 && myGuess < UPPER_BOUND){ howManyGuessesLeft--; if (myGuess == numberToGuess) { currentState = State.GAME_WON; } else if (howManyGuessesLeft <= 0) { currentState = State.GAME_LOST; } validGuess = true; } break; // Guesses are expected only when the game is in WAIT_FOR_GUESS. default: throw new IllegalStateException("No more guesses allowed."); } return validGuess; } 12

This state machine has only one event—a call to makeGuess(). You need to implement code for each state where this event triggers a transition. What you do if the event is received when you do not expect it, is application dependent. You typically implement guards as the conditional of an if statement. The transition is completed by setting the current state to the next state.

slide-13
SLIDE 13

For objects with complex behavior, a state machine is often the only design that is maintainable.

  • Add state machines to your toolbox for defining

software behavior

  • Even without implementing the states explicitly, you

gain by having a clear definition of the behavior

  • For more complex systems, implementation

techniques other than switch-based are better.

  • State design pattern separates concerns for each

state into a separate class

  • State-machine frameworks provide polymorphic

design of state machine

  • Dispatch mechanism sends events through system
  • Tools provide auto-coding of state machine
  • peration directly from the statechart definition

13