Skip to content
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

Spruce - Reid #83

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Spruce - Reid #83

wants to merge 8 commits into from

Conversation

reidhowdy
Copy link

No description provided.

Copy link

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job!

All required waves are complete and all required tests are passing! Your code is well organized, and you are generally using good, descriptive variable names. Your general approaches are good, and you're off to a good start with OOP.

Be a little careful of where certain instance members "live". For instance, if the condition member is defined only in the child classes of Item, then we shouldn't try to access it within Item itself. If we want to do that (which made sense in this project), then we should move the condition member itself up to the parent class Item.

Also, be sure to be reading the tests carefully to understand what they're testing, as well as what they're not. Be sure to think about other situations that our code might need to handle (especially situations that show up in other tests, but which might not themselves be tested). The supplied tests are an important baseline, but we should still think about the overall behavior of our code and how it handles a variety of situations.

Also, we can continue to work on making our python code more idiomatic. Avoiding unnecessary indenting (by using guard clauses), and checking conditions making use of pythons ideas about truthy and falsy can communicate your intent to other python developers very quickly (even if it might not be so clear to new developers).

Overall, well done.

Comment on lines +4 to +5
def __init__(self, category = ""):
self.category = category

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice this requirement in the project description:

All three classes and the Item class have an attribute called condition, which can be optionally provided in the initializer. The default value should be 0.

Rather than each of the child classes defining it condition on its own, we can add the condition to the Item constructor, like

    def __init__(self, category="", condition=0):
        self.category = category
        self.condition = condition

def __str__(self):
return "Hello World!"

def condition_description(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job putting this implementation in the parent class, but also notice that this method is expecting the instance to have an instance member called condition, but currently Item doesn't have that. So if we created an Item and then tried calling its condition_description method, Python would crash with an AttributeError. The child classes derived from Item do have this attribute (although, think about what would happen if we forgot to in one), but in general we shouldn't make assumptions about a class having attributes that aren't defined in the class itself (although this can be used for a pattern called the Template Method pattern). So trying to access the condition method here in Item should also give us a hint that initializing the condition in our constructor is a good idea.

return "Ew."
elif self.condition == 2:
return "Um."
elif self.condition == 3:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if we tried to get the description for an Item with a condition of 3.5 (there are tests that set the condition to 3.5, but don't try to read the description). The description test checks for a condition of 1 and a description of 5, but we should still make sure our code covers any other reasonable conditions, including floating point values (since we've seen them used in other tests).

How could we modify this (slightly) to cover the values between the whole numbers?

Comment on lines +5 to +6
super().__init__(category = "Clothing")
self.condition = condition

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we added support for the condition attribute to Item itself (and updated the constructor to match, see below) then we could make use of the constructor argument to pass through the condition parameter here.

        super().__init__(category="Clothing", condition=condition)

Also, good call on removing category from the Clothing constructor. We don't want to allow the creation of a Clothing instance for which the category isn't "Clothing". (Of course, since this is Python, we could simply reassign it later on. But there are other Python features that could help us prevent that if we really needed to!)

Comment on lines +5 to +6
super().__init__(category = "Decor")
self.condition = condition

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same situation applies here as for the Clothing constructor.

Comment on lines +53 to +57
for item in self.inventory:
if ((item.category == category) and
(item.condition > best_condition)):
best_item = item
best_condition = item.condition

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is doing two things: 1. restricting to items of a certain category, and 2. looking for the best condition. Do we have a method that filters to a category that we could reuse here?

Comment on lines +64 to +68
if not self_best or not other_best:
return False
else:
self.swap_items(other, self_best, other_best)
return True

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of how swap_items is implemented, the empty checks here aren't necessary. So long as we make use of the return value from swap_items, we could get away with

        return self.swap_items(other, self_best, other_best)


return True

def get_best_by_category(self, category = ""):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description of this function didn't ask for a default value for the category parameter. And arguably, it makes sense to require the caller to provide a value. Since the function is called get_best_by_category, I would expect to need to have a particular category in mind, and it might read a little strangely to see a call like some_vendor.get_best_by_category() where the category isn't stated.

best_condition = item.condition
return best_item

def swap_best_by_category(self, other = None, my_priority = "", their_priority = ""):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description of this function didn't ask for a default value for the parameters. And in cases where a default is supplied, it's a little surprising that it can lead to an error. Notice that if None is used for other, line 62 will crash when it tries to access get_best_by_category for a NoneType. If instead we lead off the default values, then if we tried to call the method without the needed parameters we would get an error about some required parameters being missing.

Comment on lines +21 to +32












Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly a nit pick, but try to not leave big chunks of unnecessary whitespace in your files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants