-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Val - Edges - Hotel #36
base: master
Are you sure you want to change the base?
Conversation
…tr_reader for all with corresponding tests
…ervation method and tests, update Reservation#get_all_dates method
…s and tests, update Calendar#add_reservation method and tests
…print_available_rooms
…servation_list to Calendar
HotelWhat We're Looking For
Great work overall! I really like the way you split the booking manager and the calendar into two separate classes. This split isn't quite as clean as it could be, but the idea of it makes a lot of sense. I do want to call out the way your code uses the
That being said, I'm quite happy with what I see here - you're clearly exploring different techniques of object-oriented design, which is the big goal for this assignment. The specific code you're writing and your tests are very solid. Keep up the hard work! |
|
||
if nights.numerator <= 0 | ||
raise StandardError, "Invalid date range." | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would probably put this check in the constructor, rather than in this other method. That makes it more obvious when the check happens, and what it means for a reservation to be invalid.
lib/reservation.rb
Outdated
def initialize(check_in, check_out) | ||
@check_in = date_format(check_in) | ||
@check_out = date_format(check_out) | ||
@number_of_nights = number_of_nights |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of storing number_of_nights
in an instance variable and having an attr_reader
, I would probably keep it as a method. The program will have to do slightly more work whenever you need the number, but it means that if you change the dates on the reservation the number of nights will update automatically. From the outside it won't look any different (you call a method and get back a number), but it makes this class more resilient to change.
lib/calendar.rb
Outdated
def reservations(date) | ||
date = Date.parse(date) | ||
reservations = room_assignments.select { |room, dates| dates.flatten.include? (date) }.keys | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good use of enumerables here.
lib/booking_manager.rb
Outdated
def add_reservation(reservation) | ||
room = calendar.available_rooms(reservation).first | ||
|
||
raise StandardError, "No availability." if room.nil? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of raising a StandardError
, best practice is to define your own appropriately named exception type that inherits from StandardError
and raise that. The reason is that StandardError
is very broad, and if the code that calls this method has to rescue StandardError
, that will catch things like ArgumentError
s and NameError
s that indicate true bugs.
lib/block.rb
Outdated
case number_of_rooms | ||
when 2 | ||
discount = 0.05 * PRICE | ||
when 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might make sense to store the mapping from number of nights to discount in a hash. That way if you needed the info elsewhere in the program it would be relatively easy to access.
|
||
reservation.get_all_dates.each do |date| | ||
calendar.room_assignments[room] << date | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an example of tight coupling. Instead of the BookingManager
directly touching the Calendar
's list of dates, it should call a method on the calendar (something like add_reservation
), and the calendar should do that work.
That way if the calendar's internal system of keeping track of rooms and dates changes, this code won't have to.
lib/booking_manager.rb
Outdated
end | ||
|
||
block_rooms = available_rooms[0..(block_size - 1)] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could also say .first(block_size)
block_rooms.each do |room| | ||
calendar.room_assignments[room] << block.get_all_dates | ||
block.rooms[room] = :available | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two more examples of tight coupling, both with the calendar and with the block
spec/booking_manager_spec.rb
Outdated
it "raises exception if no rooms available" do | ||
17.times do | ||
manager.add_reservation(reservation1) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work catching this edge-case
lib/booking_manager.rb
Outdated
|
||
def initialize(calendar) | ||
@calendar = calendar | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good use of dependency injection.
Hotel
Congratulations! You're submitting your assignment!
Comprehension Questions