Skip to content

Resources design exercise

jennalwise edited this page Oct 9, 2017 · 15 revisions

Typestate

Most real world problems or scenarios can be solved or modeled with an emphasis on state, sometimes for the better. For example, consider the state chart diagram below used to model the state of a wallet containing a money and a license.

Wallet State Chart

Resources

For each task the money and license must follow certain properties/restrictions:

  • The money and license cannot be duplicated.

    For example,

    @Resource class Money {...}
    
    class Person {
      Wallet wallet;
    
      // If I find money on the street, I put it in my wallet.
      transaction foundMoney(Money newMoney) {
        Money money = newMoney;
        wallet.addMoney(newMoney); // COMPILE ERROR: Money cannot be duplicated because it is a @Resource
        wallet.addMoney(money); // no compiler error
      }
    }
  • The money and license can only be used once.

    For example,

    @Resource class Money {...}
    
    class Person {
      Wallet wallet;
    
      // If I find money on the street, I put it in my wallet.
      transaction foundMoney(Money money) {
        wallet.addMoney(money);
        wallet.addMoney(money); // COMPILE ERROR: can't consume Money twice because it is a @Resource.
      }
    }
  • The money and license cannot be dropped on the floor.

    • They must be either passed, returned, or released.

The money and license are special and will be referred to and marked as resources.

Task 1

The Wallet state chart diagram is implemented as a class with state member variables and transaction methods. The state member variables contain their own member variables (resources) appropriate to each state and the transaction methods contain one or more transitions (-><state name>) from the current state to another.

However, the code below is incomplete as resources are not being handled properly. Your task is to add to and/or modify the code below (where indicated with // TODO:) to ensure the license and money resources are handled properly by following the rules listed in the Resources section above.

Do not limit yourself to known language constructs; ie. make up any language features you may want. We want to see the kind of code you would want to be able to write.

@Resource class License {...}
@Resource class Money {...}

class Wallet {
  state HasLicenseOnly;
  state HasMoneyOnly;
  state HasLicenseAndMoney;
  state Empty;

  License license available in HasLicenseOnly, HasLicenseAndMoney;
  Money money available in HasMoneyOnly, HasLicenseAndMoney;

  transaction addMoney(Money newMoney) available in HasMoneyOnly {...}
  transaction addMoney(Money newMoney) available in Empty {...}

  transaction addMoney(Money newMoney) available in HasLicenseOnly {
    // TODO: add money to the wallet, there is no wallet money capacity
    // you may modify the method declaration (like with a return statement/type) or the state transition to your liking

    ->HasLicenseAndMoney
  }

  transaction addMoney(Money newMoney) available in HasLicenseAndMoney {...}
  transaction addLicense(License newLicense) available in HasMoneyOnly {...}
  transaction addLicense(License newLicense) available in Empty {...}

  transaction addLicenseAndMoney(License newLicense, StudentId newMoney) available in Empty {
    // TODO: add a license and money to the wallet, there is no wallet money capacity
    // you may modify the method declaration (like with a return statement/type) or the state transition to your liking

    ->HasLicenseAndMoney
  }

  transaction removeMoney() available in HasLicenseAndMoney {
    // TODO: remove all the money from the wallet
    // you may modify the method declaration (like with a return statement/type) or the state transition to your liking

    ->HasLicenseOnly
  }

  transaction removeMoney() available in HasMoneyOnly {...}
  transaction removeLicense() available in HasLicenseOnly {...}
  transaction removeLicense() available in HasLicenseAndMoney {...}

  transaction removeLicenseAndMoney() available in HasLicenseAndMoney {
    // TODO: remove all the money and the license from the wallet
    // you may modify the method declaration (like with a return statement/type) or the state transition to your liking

    ->Empty
  }
}

Task 2

Implement the addMoney transaction method that is available in the HasMoneyOnly state of the Wallet class in Task 1. A Money object has a "merge" method that takes another Money object as input, merging the two money values. A Money object also has a "value" method to return the total money value of the object. The addMoney transaction method should enforce a wallet capacity of $100. If the money to be added into the wallet is over capacity, money must be added to the wallet to fill it to capacity and the left over money should be handled appropriately.

Task 3

For this task you will be given various code design options for resource handling based on the Wallet code example from Task 1. Your job is to answer the questions following each set of code samples.

Code Sample Set 1

// Option 1
transaction addLicenseAndMoney(License newLicense, Money newMoney) available in Empty {
  ->HasLicenseAndMoney(license = newLicense, money = newMoney)
}

// Option 2
transaction addLicenseAndMoney(License newLicense, Money newMoney) available in Empty {
  HasLicenseAndStudentId.license = newLicense;
  HasLicenseAndStudentId.money = newMoney;
  ->HasLicenseAndMoney
}

// Option 3
// specialized state constructor
state HasLicenseAndMoney(License license, Money money);

transaction addLicenseAndMoney(License newLicense, Money newMoney) available in Empty {
  ->HasLicenseAndMoney(newLicense, newMoney)
}

// Option 4
transaction addLicenseAndMoney(License newLicense, Money newMoney) available in Empty {
  ->HasLicenseAndMoney
  license = newLicense;
  money = newMoney;
}

Questions

  1. For each option above briefly describe how it differs from the other three options.
    • The differences can be syntactic and/or conceptual.
  2. Rank the options from 1 to 4 with 1 being your favorite and 4 being your least favorite. Briefly indicate the reasons for your choices.

Code Sample Set 2

// Option 1
transaction removeLicenseAndMoney() available in HasLicenseAndMoney returns x {
  x = ->Empty

  console.out("License with license number " +
    x.license.licenseNumber + " is being removed.");
  console.out("This total dollars of " +
    x.money.value() + " is being removed.");

  return x;
}

// Option 2
transaction removeLicenseAndMoney() available in HasLicenseAndMoney returns (returnLicense, returnMoney) {
  (returnLicense = license, returnMoney = money) = ->Empty

  console.out("License with license number " +
    returnLicense.licenseNumber + " is being removed.");
  console.out("This total dollars of " +
    returnMoney.value() + " is being removed.");

  return (returnLicense, returnMoney);
}

Questions

  1. For each option above briefly describe how it differs from the other option.
    • The differences can be syntactic and/or conceptual.
  2. Choose your favorite option. Briefly indicate the reason for your choice.

Code Sample Set 3

// Option 1
transaction licenseExpires() available in HasLicenseAndMoney {
  console.out("License with license number " +
    license.licenseNumber + " has expired.";

  release(license);

  ->HasMoneyOnly
}

// Option 2
transaction licenseExpires() available in HasLicenseAndMoney {
  ->HasMoneyOnly

  console.out("License with license number " +
    old.license.licenseNumber + " has expired.";

  release(old.license);
}

// Option 3
transaction licenseExpires() available in HasLicenseAndMoney {
  returnedLicense = ->HasMoneyOnly

  console.out("License with license number " +
    returnedLicense.licenseNumber + " has expired.";

  release(returnedLicense);
}

Questions

  1. For each option above briefly describe how it differs from the other options.
    • The differences can be syntactic and/or conceptual.
  2. Rank the options 1 to 3 with 1 being your favorite and 3 being your least favorite. Briefly indicate the reasons for your choices.