Introduction

Flash is a lightweight cross-platform runtime for rich media, enterprise applications and mobile applications, as well as an integrated development environment. Flash can be programmed in ActionScript 1/2/3.

Saturday, July 12th, 2003 at 7:27 pm

Refactoring: Improving The Design Of Existing Code [Chapter 1]

Today I started reading Martin Fowler’s book about Refactoring. When I saw the example code for the first chapter I was shocked because it wasn’t written in ActionScript but in Java. It was the first time I saw a Java code. So I sat down and tried to understand how the code works. It took at least one hour. After I understood the bigger part I thought why not translate the example into ActionScript syntax. So here is the final result. If you want the code step by step (like in the book) write me a mail.

// ::MOVIE CLASS:: //
function Movie(title, priceCode){
        this.$title = title;
        this.setPriceCode(priceCode);
}
Movie.CHILDRENS = 2;
Movie.REGULAR = 0;
Movie.NEW_RELEASE = 1;
Movie.prototype.getPriceCode = function(){
        return this.$price.getPriceCode();
}
Movie.prototype.setPriceCode = function(arg){
        switch(arg){
                case Movie.REGULAR:
                this.$price = new RegularPrice();
                break;
                case Movie.CHILDRENS:
                this.$price = new ChildrensPrice();
                break;
                case Movie.NEW_RELEASE:
                this.$price = new NewReleasePrice();
                break;
                default:
                trace(”Incorrect Price Code“);
        }
}
Movie.prototype.getTitle = function(){
        return this.$title;
}
Movie.prototype.getCharge = function(daysRented){
        return this.$price.getCharge(daysRented);
}
Movie.prototype.getFrequentRenterPoints = function(daysRented){
        return this.$price.getFrequentRenterPoints(daysRented);
}

// ::RENTAL Class:: //
function Rental(movie, daysRented){
        this.$movie = movie;
        this.$daysRented = daysRented;
}
Rental.prototype.getDaysRented = function(){
        return this.$daysRented;
}
Rental.prototype.getMovie = function(){
        return this.$movie;
}
Rental.prototype.getCharge = function(){
        return this.$movie.getCharge(this.$daysRented);
}
Rental.prototype.getFrequentRenterPoints = function(){
        return this.$movie.getFrequentRenterPoints(this.$daysRented);
}

// ::PRICE:: //
function Price(){}
Price.prototype.getFrequentRenterPoints = function(daysRented){
        return 1;
}
function ChildrensPrice(){};
ChildrensPrice.prototype = new Price();
ChildrensPrice.prototype.getPriceCode = function(){
        return CHILDRENS;
}
ChildrensPrice.prototype.getCharge = function(daysRented){
        var result = 1.5;
        if(daysRented > 3){
                result += (daysRented - 3)*1.5;
        }
        return result;
}
function NewReleasePrice(){};
NewReleasePrice.prototype = new Price();
NewReleasePrice.prototype.getPriceCode = function(){
        return NEW_RELEASE;
}
NewReleasePrice.prototype.getFrequentRenterPoints = function(daysRented){
        return daysRented > 1 ? 2 : 1;
}
NewReleasePrice.prototype.getCharge = function(daysRented){
        var result = daysRented*3;
        return result;
}
function RegularPrice(){};
RegularPrice.prototype = new Price();
RegularPrice.prototype.getPriceCode = function(){
        return REGULAR;
}
RegularPrice.prototype.getCharge = function(daysRented){
        var result = 2;
        if(daysRented > 2){
                result += (daysRented - 2)*1.5;
        }
        return result;
}

// ::CUSTOMER CLASS:: //
function Customer(name){
        this.$name = name;
        this.$rentals = new Array();
}
Customer.prototype.addRental = function(rental, daysRented){
        this.$rentals.push({rental:rental, daysRented:daysRented});
}
Customer.prototype.getName = function(){
        return this.$name;
}
Customer.prototype.statement = function(){
        return new TextStatement().value(this);
}
Customer.prototype.htmlStatement = function(){
        return new HtmlStatement().value(this);
}
Customer.prototype.$getTotalCharge = function(){
        var result = 0;
        for(var i=0; i < this.$rentals.length; ++i){
                var each = new Rental(this.$rentals[i].rental, this.$rentals[i].daysRented);
                result += each.getCharge();
        }
        return result;
}
Customer.prototype.$getTotalFrequentRenterPoints = function(){
        var result = 0;
        for(var i=0; i<this.$rentals.length; ++i){
                var each = new Rental(this.$rentals[i].rental, this.$rentals[i].daysRented);
                result += each.getFrequentRenterPoints();
        }
        return result;
}

// ::STATEMENT CLASS:: //
function Statement(){}
Statement.prototype.value = function(aCustomer){
        var result = this.headerString(aCustomer);
        for(var i=0; i < aCustomer.$rentals.length; ++i){
                var each = new Rental(aCustomer.$rentals[i].rental, aCustomer.$rentals[i].daysRented);
                result += this.eachRentalString(each);
        }

        result += this.footerString(aCustomer);
        return result;
}

// ::TEXT STATEMENT CLASS:: //
function TextStatement(){}
TextStatement.prototype = new Statement();
TextStatement.prototype.headerString = function(aCustomer){
        returnRental Record for ” + aCustomer.getName() + “. “;
}
TextStatement.prototype.eachRentalString = function(aRental){
        return aRental.getMovie().getTitle() + “ ” + aRental.getCharge() + “ Euro. ”
}
TextStatement.prototype.footerString = function(aCustomer){
        returnAmount owed is ” + aCustomer.$getTotalCharge() + “ Euro. ”
        + “You earned ” + aCustomer.$getTotalFrequentRenterPoints() + “ frequent renter points.“;
}

// ::HTML STATEMENT CLASS:: //
function HtmlStatement(){}
HtmlStatement.prototype = new Statement();
HtmlStatement.prototype.headerString = function(aCustomer){
        returnRental Record for ” + aCustomer.getName() + “. “;
}
HtmlStatement.prototype.eachRentalString = function(aRental){
        return aRental.getMovie().getTitle() + “ ” + aRental.getCharge() + “ Euro. ”
}
HtmlStatement.prototype.footerString = function(aCustomer){
        returnAmount owed is ” + aCustomer.$getTotalCharge() + “ Euro. ”
        + “You earned ” + aCustomer.$getTotalFrequentRenterPoints() + “ frequent renter points.“;
}

// example
FightClub = new Movie(”Fight Club“, Movie.NEW_RELEASE);
Memento = new Movie(”Memento“, Movie.REGULAR);
PalpFiction = new Movie(”Palp Fiction“, Movie.CHILDRENS);

Simon = new Customer(”Simon“);
Simon.addRental(FightClub, 3);
Simon.addRental(Memento, 1);
Simon.addRental(PalpFiction, 8);
trace(Simon.statement() == “Rental Record for Simon. Fight Club 9 Euro. Memento 2 Euro. Palp Fiction 9 Euro. Amount owed is 20 Euro. You earned 4 frequent renter points.“);

2 Responses to “Refactoring: Improving The Design Of Existing Code [Chapter 1]”

  1. Marpfei

    Hi simon,

    it is funny to see the code. I am just reading the fowler too. A fascinating book!! I also started with ActionScript and try to begin with Java now. A few days ago I started to transcribe Fowlers Java-Examples into Actionscript-Code. When I am through the first capter we should compare and discuss our code !!!!

    See you,

    marpfei

  2. Simon

    Hi marpfei,
    when you have finished reading, write me a mail. It would be nice to talk about the code with another programmer. I’m looking forward to hear from you.