Created
October 27, 2024 15:57
-
-
Save fahmifan/cd287bdfa1b2c87af7863ac72fc23bb7 to your computer and use it in GitHub Desktop.
Videostore from Martin Fowler Refactoring in Go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"refactoring/videostore" | |
) | |
func main() { | |
movieA := videostore.Movie{ | |
Title: "Wiro Sableng", | |
PriceCode: videostore.REGULAR, | |
} | |
movieB := videostore.Movie{ | |
Title: "Merapi 3", | |
PriceCode: videostore.NEW_RELEASE, | |
} | |
movieC := videostore.Movie{ | |
Title: "Si Unyil", | |
PriceCode: videostore.CHILDREN, | |
} | |
customer := videostore.Customer{ | |
Name: "John Doe", | |
} | |
customer.AddRental(videostore.Rental{ | |
Movie: movieA, | |
DaysRented: 2, | |
}) | |
customer.AddRental(videostore.Rental{ | |
Movie: movieB, | |
DaysRented: 3, | |
}) | |
customer.AddRental(videostore.Rental{ | |
Movie: movieC, | |
DaysRented: 5, | |
}) | |
statment := customer.MakeStatment() | |
fmt.Println(statment.PlainText()) | |
fmt.Println("=======") | |
fmt.Println(statment.HTML()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package videostore | |
import "fmt" | |
type PriceCode int | |
const ( | |
REGULAR PriceCode = iota | |
NEW_RELEASE | |
CHILDREN | |
) | |
type Movie struct { | |
Title string | |
PriceCode PriceCode | |
} | |
func (movie *Movie) OwedAmount(daysRented int) float64 { | |
switch movie.PriceCode { | |
case REGULAR: | |
return ChargeForRegular(daysRented) | |
case NEW_RELEASE: | |
return ChargeForNewRelease(daysRented) | |
case CHILDREN: | |
return ChargeForChildren(daysRented) | |
default: | |
return 0 | |
} | |
} | |
func ChargeForRegular(daysRented int) float64 { | |
amount := float64(2) | |
if daysRented > 2 { | |
amount += float64(daysRented-2) * 1.5 | |
} | |
return amount | |
} | |
func ChargeForNewRelease(daysRented int) float64 { | |
return float64(daysRented) * 3 | |
} | |
func ChargeForChildren(daysRented int) float64 { | |
amount := float64(1.5) | |
if daysRented > 3 { | |
amount += float64((daysRented)-3) * 1.5 | |
} | |
return amount | |
} | |
func (movie *Movie) FrequentPoints(daysRented int) int { | |
if movie.PriceCode == NEW_RELEASE { | |
return 2 | |
} | |
return 1 | |
} | |
type Rental struct { | |
Movie Movie | |
DaysRented int | |
} | |
func (rental *Rental) OwedAmount() float64 { | |
return rental.Movie.OwedAmount(rental.DaysRented) | |
} | |
func (rental *Rental) FrequentPoints() int { | |
return rental.Movie.FrequentPoints(rental.DaysRented) | |
} | |
type StatmentDetail struct { | |
MovieTitle string | |
OwedAmount float64 | |
} | |
type Customer struct { | |
Name string | |
rentals []Rental | |
} | |
func (cust *Customer) AddRental(rental Rental) { | |
cust.rentals = append(cust.rentals, rental) | |
} | |
type Statement struct { | |
CustomerName string | |
TotalOwedAmount float64 | |
FrequentRenterPoints int | |
Details []StatmentDetail | |
} | |
func (cust *Customer) MakeStatment() Statement { | |
totalAmount := float64(0) | |
frequentRenterPoints := 0 | |
statment := Statement{ | |
CustomerName: cust.Name, | |
Details: []StatmentDetail{}, | |
} | |
for _, rental := range cust.rentals { | |
frequentRenterPoints += rental.FrequentPoints() | |
owedAmount := rental.OwedAmount() | |
totalAmount += owedAmount | |
statment.Details = append(statment.Details, StatmentDetail{ | |
MovieTitle: rental.Movie.Title, | |
OwedAmount: rental.OwedAmount(), | |
}) | |
} | |
return statment | |
} | |
func (statement *Statement) PlainText() string { | |
result := fmt.Sprintf("Rental Record %s\n", statement.CustomerName) | |
for _, detail := range statement.Details { | |
result += "\t" + detail.MovieTitle + "\t" + fmt.Sprint(detail.OwedAmount) + "\n" | |
} | |
result += "Amount owed is " + fmt.Sprint(statement.TotalOwedAmount) + "\n" | |
result += "You earned " + fmt.Sprint(statement.FrequentRenterPoints) + " frequent renter points" | |
return result | |
} | |
// Just example | |
func (statement *Statement) HTML() string { | |
result := fmt.Sprintf("<html>Rental Record %s\n", statement.CustomerName) | |
for _, detail := range statement.Details { | |
result += "\t" + detail.MovieTitle + "\t" + fmt.Sprint(detail.OwedAmount) + "\n" | |
} | |
result += "Amount owed is " + fmt.Sprint(statement.TotalOwedAmount) + "\n" | |
result += "You earned " + fmt.Sprint(statement.FrequentRenterPoints) + " frequent renter points" | |
return result | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment