В предыдущей статье я рассказывал как провести рефакторинг кода GildedRose с целью снижения Time2Market.
В результате из кода с цикломатической сложностью 19 получился код с цикломатической сложностью 5, при этом сам код изменился до неузнаваемости.
Было
#gilded_rose_cyclomatic_complexity_19.py class GildedRose(object): ... def update_quality(self): for item in self.items: if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert": if item.quality > 0: if item.name != "Sulfuras, Hand of Ragnaros": item.quality = item.quality - 1 else: if item.quality < 50: item.quality = item.quality + 1 if item.name == "Backstage passes to a TAFKAL80ETC concert": if item.sell_in < 11: if item.quality < 50: item.quality = item.quality + 1 if item.sell_in < 6: if item.quality < 50: item.quality = item.quality + 1 if item.name != "Sulfuras, Hand of Ragnaros": item.sell_in = item.sell_in - 1 if item.sell_in < 0: if item.name != "Aged Brie": if item.name != "Backstage passes to a TAFKAL80ETC concert": if item.quality > 0: if item.name != "Sulfuras, Hand of Ragnaros": item.quality = item.quality - 1 else: item.quality = item.quality - item.quality else: if item.quality < 50: item.quality = item.quality + 1
Стало
#gilded_rose_cyclomatic_complexity_5.py class GildedRose(object): ... def update_quality(self): self.items = [EntityFactory.create(item=item).update_quality().to_item() for item in self.items] ... class ItemEntity: def __init__(self, item): name = item.name self.name = name self.sell_in = item.sell_in self.quality = item.quality self.is_conjured = name.startswith("Conjured ") self.quality_increase_factor = 1 def increase_quality(self): self.quality = min(self.quality + 1 * self.quality_increase_factor, 50) def decrease_quality(self): self.quality = max(self.quality - 1 * self.quality_increase_factor, 0) def decrease_sell_in(self): self.sell_in = self.sell_in - 1 def change_quality(self): self.decrease_quality() def change_quality_after_sell_in(self): self.decrease_quality() def update_quality(self): self.change_quality() self.decrease_sell_in() if self.sell_in < 0: self.change_quality_after_sell_in() return self def to_item(self): return Item(name=self.name, sell_in=self.sell_in, quality=self.quality) class EntityFactory: def remove_conjured_if_exists(name): if name.startswith("Conjured "): return name[9:] else: return name def create(item): stripped_name = EntityFactory.remove_conjured_if_exists(item.name) if stripped_name == "Aged Brie": return AgedBrie(item=item) elif stripped_name == "Backstage passes to a TAFKAL80ETC concert": return BackstagePasses(item=item) elif stripped_name == "Sulfuras, Hand of Ragnaros": return Sulfuras(item=item) else: return ItemEntity(item=item) class AgedBrie(ItemEntity): def change_quality(self): self.increase_quality() def change_quality_after_sell_in(self): self.increase_quality() class BackstagePasses(ItemEntity): def change_quality(self): self.increase_quality() def change_quality_after_sell_in(self): self.quality = 0 def decrease_quality(self): super().decrease_quality() def increase_quality(self): super().increase_quality() if self.sell_in < 11: super().increase_quality() if self.sell_in < 6: super().increase_quality() class Sulfuras(ItemEntity): def decrease_quality(self): pass def decrease_sell_in(self): pass
Мне стало любопытно сможет ли ChatGPT описать что делает этот код и реализовать в нем новое требование:
-
Сотворенные элементы изменяют качество в 2 раза быстрее, чем не сотворенные
Важное уточнение: рефакторинг кода я делал самостоятельно и опубликовал на GitHub в феврале 2023 года. Данная статья написана в марте 2023 года, а ChatGPT, обученный на данных 2021 года, никоим образом не мог видеть этот код и не мог знать о правильном решении.
Начало диалога с ChatGPT.
Я: Привет. Вот код ката Позолоченная роза <код программы под спойлером>
Спойлер
#gilded_rose_cyclomatic_complexity_5.py class GildedRose(object): def __init__(self, items): self.items = items def update_quality(self): self.items = [EntityFactory.create(item=item).update_quality().to_item() for item in self.items] class Item: def __init__(self, name, sell_in, quality): self.name = name self.sell_in = sell_in self.quality = quality def __repr__(self): return "%s, %s, %s" % (self.name, self.sell_in, self.quality) class ItemEntity: def __init__(self, item): name = item.name self.name = name self.sell_in = item.sell_in self.quality = item.quality self.is_conjured = name.startswith("Conjured ") self.quality_increase_factor = 1 def increase_quality(self): self.quality = min(self.quality + 1 * self.quality_increase_factor, 50) def decrease_quality(self): self.quality = max(self.quality - 1 * self.quality_increase_factor, 0) def decrease_sell_in(self): self.sell_in = self.sell_in - 1 def change_quality(self): self.decrease_quality() def change_quality_after_sell_in(self): self.decrease_quality() def update_quality(self): self.change_quality() self.decrease_sell_in() if self.sell_in < 0: self.change_quality_after_sell_in() return self def to_item(self): return Item(name=self.name, sell_in=self.sell_in, quality=self.quality) class EntityFactory: def remove_conjured_if_exists(name): if name.startswith("Conjured "): return name[9:] else: return name def create(item): stripped_name = EntityFactory.remove_conjured_if_exists(item.name) if stripped_name == "Aged Brie": return AgedBrie(item=item) elif stripped_name == "Backstage passes to a TAFKAL80ETC concert": return BackstagePasses(item=item) elif stripped_name == "Sulfuras, Hand of Ragnaros": return Sulfuras(item=item) else: return ItemEntity(item=item) class AgedBrie(ItemEntity): def change_quality(self): self.increase_quality() def change_quality_after_sell_in(self): self.increase_quality() class BackstagePasses(ItemEntity): def change_quality(self): self.increase_quality() def change_quality_after_sell_in(self): self.quality = 0 def decrease_quality(self): super().decrease_quality() def increase_quality(self): super().increase_quality() if self.sell_in < 11: super().increase_quality() if self.sell_in < 6: super().increase_quality() class Sulfuras(ItemEntity): def decrease_quality(self): pass def decrease_sell_in(self): pass
ChatGPT: Привет! Чем я могу помочь по этому коду?
Я: Опиши что он делает
ChatGPT: Данный код реализует систему управления качеством товаров магазина, представленных в виде списка объектов класса Item. Каждый объект этого класса характеризуется названием товара (name), количеством дней до окончания срока годности (sell_in) и текущим качеством (quality).
Класс GildedRose содержит метод update_quality(), который обновляет состояние всех товаров в списке items в соответствии с правилами, определенными в классах-ItemEntity`.
Классы-наследники представляют конкретные типы товаров и определяют особенности изменения их качества во времени. Например, класс AgedBrie представляет товар «Сыр Пармезан», качество которого увеличивается со временем, а класс BackstagePasses представляет билеты на концерты, качество которых увеличивается более быстро, когда остается мало времени до концерта.
Класс EntityFactory используется для создания объектов классов-наследников на основе названия товара.
Также в классе ItemEntity определены методы для изменения качества, уменьшения срока годности и проверки состояния товара (например, если срок годности закончился, качество должно ухудшиться быстрее). Метод to_item() используется для преобразования объекта класса ItemEntity обратно в объект класса Item.
Моя реакция: Поразительно! Все описано совершенно точно.
Я: Можешь реализовать требование: сотворенные элементы изменяют качество в 2 раза быстрее, чем не сотворенные?
ChatGPT: Да, конечно! Для реализации этого требования необходимо внести изменения в класс ItemEntity. Вместо фиксированного коэффициента 1 для изменения качества, мы будем использовать переменную quality_increase_factor, которая будет равна 2 для сотворенных товаров и 1 для обычных товаров.
Измененный код будет выглядеть так:
class ItemEntity: def __init__(self, item): name = item.name self.name = name self.sell_in = item.sell_in self.quality = item.quality self.is_conjured = name.startswith("Conjured ") self.quality_increase_factor = 2 if self.is_conjured else 1 def increase_quality(self): self.quality = min(self.quality + 1 * self.quality_increase_factor, 50) def decrease_quality(self): self.quality = max(self.quality - 1 * self.quality_increase_factor, 0) def decrease_sell_in(self): self.sell_in = self.sell_in - 1 def change_quality(self): self.decrease_quality() def change_quality_after_sell_in(self): self.decrease_quality() def update_quality(self): self.change_quality() self.decrease_sell_in() if self.sell_in < 0: self.change_quality_after_sell_in() return self def to_item(self): return Item(name=self.name, sell_in=self.sell_in, quality=self.quality)
Теперь при создании объекта класса ItemEntity переменная quality_increase_factor будет равна 2, если товар является сотворенным (is_conjured), и 1 в противном случае. Это позволит изменять качество сотворенных товаров в 2 раза быстрее, чем обычных товаров.
Моя реакция: Потрясающе! ChatGPT никак не мог знать заранее о переменной quality_increase_factor: ее нет в исходной головоломке, описанной в Интернет и в других решениях, которые я видел. По правде говоря, я добавил ее специально, чтобы заставить ChatGPT поломать голову — но она справилась с этой задачей.
Я: Спасибо за помощь, ты сделал это правильно и потратил меньше минуты там, где человек разбирался бы 5 минут.
ChatGPT: Пожалуйста, рад был помочь! Я всегда готов помочь с любыми вопросами, связанными с программированием или компьютерными технологиями. Если у вас есть другие вопросы, не стесняйтесь спрашивать!
Заключение
Несмотря на то, что ChatGPT не мог видеть эту версию кода ранее, он верно описал логику его работы кода и верно нашел то место, в котором нужно внести изменение.
Изменение было внесено в 5 раз быстрее, чем это мог бы сделать человек.
Удачи в исследованиях!
ссылка на оригинал статьи https://habr.com/ru/post/720294/
Добавить комментарий