Skip to content

Resources design exercise

jennalwise edited this page Oct 3, 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. For simplicity, when money is removed from the wallet all the money must be removed.

Wallet State Chart

Resources

For each task the money and license will be referred to as resources that have the following properties/restrictions when implemented in code:

  • No duplication of resources

    • Can only be assigned to one modifying reference variable at a time
  • No "using" resources more than once

    • Can only be assigned to one modifying reference variable at a time

    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.
      }
    }
  • Resources must be passed, returned, or released

    • Letting resources go out of scope without explicitly passing, returning, or releasing them is forbidden

Task 1

Imagine you have a programming language that allows you to represent state chart diagrams quite nicely, as seen below. 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 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 {
    if (newMoney.value() + money.value() > 100) {
      // TODO: enforce wallet capacity of $100
    } else {
          money.merge(newMoney); // combines the value of newMoney with the value in the existing Money object
    }
  }

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

  transaction addMoney(Money newMoney) available in HasLicenseOnly {...}

  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
    ->HasLicenseAndMoney
  }

  transaction removeMoney() available in HasLicenseAndMoney {
    // TODO: remove all the money from the wallet
    ->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
    ->Empty
  }
}

Task 2

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 money) 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 of money " +
    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 of money " +
    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 {
  returnLicense = ->HasMoneyOnly

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

  release(returnLicense);
}

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.