Articles NutritionCheckpoint Hangman Survey Says About Steven Cleary

Tell Don't Ask

Tell Don’t Ask is a principle that can be used to help reduce coupling. The primary idea behind Tell Don’t Ask, is that you should tell an object what to do, and not ask an object for information so that you can decide what it does. Some do not like this principle because they believe it leads to people never using getter methods, even though there are perfectly good reasons to use getters.

For example, imagine programming a bouncing ball application. On the left is the code for the program that doesn’t follow the Tell Don’t Ask principle. On the right is the code for the program that does follow the Tell Don’t Ask principle. The problem with the code on the left side is that the two classes are tightly coupled. The images at the bottom show the coupling for each application.

It is important to also note that the DataBall class is a Data Class. A Data Class is a code smell that almost always needs to be refactored.

            
class DataBall{
  constructor(){
    this.x = 0;
    this.y = 0;
    this.xVelocity = 4;
    this.yVelocity = 2;
  }
  getX(){
    return this.x;
  }
  getY(){
    return this.y;
  }
  setX(x){
    this.x = x;
  }
  setY(y){
    this.y = y;
  }
  getXVelocity(){
    return this.xVelocity;
  }
  getYVelocity(){
    return this.yVelocity;
  }
  setXVelocity(xVelocity){
    this.xVelocity = xVelocity;
  }
  setYVelocity(yVelocity){
    this.yVelocity = yVelocity;
  }
}
            
          
            
class Ball{
  constructor(){
    this.x = 0;
    this.y = 0;
    this.xVelocity = 4;
    this.yVelocity = 2;
  }
  moveBall(){
    var newX = this.x + this.xVelocity;
    var newY = this.y + this.yVelocity;
    if( !( newX > 0 && newX < maxWidth)){
      this.xVelocity = -this.xVelocity;
    }
    if( !( newY > 0 && newY < maxHeight)){
      this.yVelocity = -this.yVelocity;
    }
    this.y += this.yVelocity;
    this.x += this.xVelocity;
  }
}
            
          
            
class Visualization1{
  constructor(){
    this.ball = new DataBall();
  }
  async run(){
    while(true){
      this.moveBall();
      await sleep(sleepTime);
    }
  }
  moveBall(){
    var newX = this.ball.getX() + this.ball.getXVelocity();
    var newY = this.ball.getY() + this.ball.getYVelocity();
    if( !( newX > 0 && newX < maxWidth )){
      this.ball.setXVelocity(-this.ball.getXVelocity());
    }
    if( !( newY > 0 && newY < maxHeight)){
      this.ball.setYVelocity(-this.ball.getYVelocity());
    }
    this.ball.setY(this.ball.getY() + this.ball.getYVelocity());
    this.ball.setX(this.ball.getX() + this.ball.getXVelocity());
  }
}
            
          
            
class Visualization2{
  constructor(){
    this.ball = new Ball();
  }
  async run(){
    while(true){
      this.ball.moveBall();
      await sleep(sleepTime);
    }
  }
}
            
          
solutionOneDiagram solutionTwoDiagram