재구성된 숭고한 예술 - 제0부분

만약 당신이 이 스페인어 문장을 읽는 것에 흥미가 있다면, 나의 블로그The Developer's Dungeon를 보십시오
일반적으로 우리가 프로그래밍을 배우거나 자신의 프로젝트를 개발할 때 우리는 팀의 일부로서 여러 해 동안 개발된 프로젝트에서 일할 때 이것은 우리가 따라야 할 일반적인 절차가 아니다. 90%의 시간을 우리는 이미 존재하는 코드에서 일할 것이다. 원시 개발자는 더 이상 팀에 있지 않을 수도 있고 문서가 없을 수도 있다.테스트가 없을 수도 있습니다. 여기는 다양한 가능성이 있지만, 우리가 이 환경에 참여할 것이기 때문에 기존 코드를 어떻게 개선하는지 아는 것이 매우 중요합니다. 이 과정을 재구성이라고 합니다.

소개하다.
먼저 정의부터 시작하겠습니다.

A change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior. -- Martin Fowler


간단하게 말하면 재구성은 출력을 바꾸지 않고 기존 코드를 재구성하는 것을 의미한다.기존 코드에 대한 수정을 모호하게 가리키는 '재구성' 이라는 용어를 들어보셨을 수도 있습니다.그러나 재구성은 사실상 전환을 바탕으로 하는 기술로 행위에 영향을 주지 않는 상황에서 코드를 개선할 수 있다.
중요한 고려 요소 중 하나는 재구성이 고의로 버그를 복구하거나 어떤 기능도 바꾸거나 성능을 직접적으로 향상시키지 않는다는 것이다.시작하기 전에 코드가 작업 상태에 있다고 가정합니다.
이것은 순수하고 실용적인 시리즈가 될 것이다. 우리는 기존 코드를 깊이 연구하고, 이를 재구성한 다음에 새로운 기능을 추가할 것이다.

이 예
우리의 연습에 대해 우리는 Gilded Rose Refactoring Kata을 사용할 것이다.우리의 예에서 우리는 C#로 작성된 원시적인 실현을 사용하지 않을 것이다. 나는 C# 개발자이기 때문에 전단으로 옮기고 있기 때문에 다른 것을 시도하고 this repository 중의 자바스크립트 버전을 사용하기로 결정했다. 우리가 사용할 테스트 프레임워크Jest로 사용하기로 했다. 그래서 우리는 계속합시다.

요구 사항
다행히도 이번에는 우리의 코드가 무엇을 해야 하는지에 관한 문서가 있었다.

Gilded Rose Refactoring Kata

Hi and welcome to team Gilded Rose. As you know, we are a small inn with a
prime location in a prominent city ran by a friendly innkeeper named
Allison. We also buy and sell only the finest goods. Unfortunately, our
goods are constantly degrading in quality as they approach their sell by
date. We have a system in place that updates our inventory for us. It was
developed by a no-nonsense type named Leeroy, who has moved on to new
adventures. Your task is to add the new feature to our system so that we
can begin selling a new category of items. First an introduction to our
system:

  • All items have a SellIn value which denotes the number of days we have to sell the item
  • All items have a Quality value which denotes how valuable the item is
  • At the end of each day our system lowers both values for every item

Pretty simple, right? Well, this is where it gets interesting:

  • Once the sell-by date has passed, Quality degrades twice as fast
  • The Quality of an item is never negative
  • "Aged Brie" actually increases in Quality the older it gets
  • The Quality of an item is never more than 50
  • "Sulfuras", being a legendary item, never has to be sold or decreases in Quality
  • "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert

We have recently signed a supplier of conjured items. This requires an
update to our system:

  • "Conjured" items degrade in Quality twice as fast as normal items

Feel free to make any changes to the UpdateQuality method and add any
new code as long as everything still works correctly. However, do not
alter the Item class or Items property as those belong to the goblin
in the corner who will insta-rage and one-shot you as he doesn't
believe in shared code ownership (you can make the UpdateQuality
method and Items property static if you like, we'll cover for you).

Just for clarification, an item can never have its Quality increase
above 50, however "Sulfuras" is a legendary item and as such its
Quality is 80 and it never alters.



비밀 번호
class Item {
  constructor(name, sellIn, quality){
    this.name = name;
    this.sellIn = sellIn;
    this.quality = quality;
  }
}

class Shop {
  constructor(items=[]){
    this.items = items;
  }
  updateQuality() {
    for (let i = 0; i < this.items.length; i++) {
      if (this.items[i].name != 'Aged Brie' && this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') {
        if (this.items[i].quality > 0) {
          if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') {
            this.items[i].quality = this.items[i].quality - 1;
          }
        }
      } else {
        if (this.items[i].quality < 50) {
          this.items[i].quality = this.items[i].quality + 1;
          if (this.items[i].name == 'Backstage passes to a TAFKAL80ETC concert') {
            if (this.items[i].sellIn < 11) {
              if (this.items[i].quality < 50) {
                this.items[i].quality = this.items[i].quality + 1;
              }
            }
            if (this.items[i].sellIn < 6) {
              if (this.items[i].quality < 50) {
                this.items[i].quality = this.items[i].quality + 1;
              }
            }
          }
        }
      }
      if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') {
        this.items[i].sellIn = this.items[i].sellIn - 1;
      }
      if (this.items[i].sellIn < 0) {
        if (this.items[i].name != 'Aged Brie') {
          if (this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') {
            if (this.items[i].quality > 0) {
              if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') {
                this.items[i].quality = this.items[i].quality - 1;
              }
            }
          } else {
            this.items[i].quality = this.items[i].quality - this.items[i].quality;
          }
        } else {
          if (this.items[i].quality < 50) {
            this.items[i].quality = this.items[i].quality + 1;
          }
        }
      }
    }

    return this.items;
  }
}

나는 종교를 믿지 않는다. 그러나 이것은 예수 그리스도가 필요하다.최초의 충격 후에 우리는 먼저 무엇을 수정합니까?
WRONNNNGGGG!
우리는 어떤 것도 수정하지 않는다. 우리가 이런 상황에서 코드를 직접 수정하는 것은 우리가 할 수 있는 최악의 일 중 하나이다. 왜냐하면 우리가 원래의 행동을 유지한다면, 코드가 거대한 오류구로 변할 것이라는 것을 진정으로 알기 어렵다.따라서, 우선 우리는 업무 행위를 포착하기 위해 몇 가지 테스트를 작성한 다음에, 우리는 계속 수정을 진행한다.

작성 테스트
여기서 우리는 두 가지 방법이 있다. 우리는 모든 예상된 행동에 대해 다음 테스트를 시작할 수 있다. 단지 문서가 있거나 텍스트 기반의 테스트를 할 수 있기 때문이다.이런 종류의 테스트는 코드의 기존 출력을 포획하고 수정할 때마다 그것을 사용해서 검사하는 것에 불과하다. 이것은 골든 마스터라는 용어이다.
이것부터 시작합시다.
  it("should return correct result", () => {
    // The original items passed to the method
    const storeItems = [
      new Item("+5 Dexterity Vest", 10, 20),
      new Item("Aged Brie", 2, 0),
      new Item("Elixir of the Mongoose", 5, 7),
      new Item("Sulfuras, Hand of Ragnaros", 0, 80),
      new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20)
    ];
    // The result the code returned
    const expectedResult = [
      new Item("+5 Dexterity Vest", 9, 19),
      new Item("Aged Brie", 1, 1),
      new Item("Elixir of the Mongoose", 4, 6),
      new Item("Sulfuras, Hand of Ragnaros", 0, 80),
      new Item("Backstage passes to a TAFKAL80ETC concert", 14, 21)
    ];
    const gildedRose = new Shop(storeItems);
    const items = gildedRose.updateQuality();

    expect(items).toStrictEqual(expectedResult);
  });
이 테스트는 작업 코드에 전달된 원시 항목과 코드가 제시한 결과를 비교합니다. 이 테스트를 통해 우리는 기존 행위가 유지보수되었는지 시종 검증할 수 있습니다.
나의 변경이 행동을 바꾸지 않을 것이라고 더욱 확신하기 위해서, 나는 현재 입력한 상황을 정확하게 표시하지 않은 상황을 위해 테스트를 작성할 것이다. 그래서 나는 이러한 상황을 표시하는 몇 가지 테스트를 계속 추가할 것이다.
 it("for normal items quality should never be below 0", () => {
    const storeItems = [new Item("+5 Dexterity Vest", 10, 0)];
    const expectedResult = [new Item("+5 Dexterity Vest", 9, 0)];
    const gildedRose = new Shop(storeItems);
    const items = gildedRose.updateQuality();

    expect(items).toStrictEqual(expectedResult);
  });

  it("when the sellIn date passes, quality should degrade twice as fast", () => {
    const storeItems = [new Item("+5 Dexterity Vest", 0, 4)];
    const expectedResult = [new Item("+5 Dexterity Vest", -1, 2)];
    const gildedRose = new Shop(storeItems);
    const items = gildedRose.updateQuality();

    expect(items).toStrictEqual(expectedResult);
  });

  it("the quality of an item can never be more than 50", () => {
    const storeItems = [new Item("Aged Brie", 1, 50)];
    const expectedResult = [new Item("Aged Brie", 0, 50)];
    const gildedRose = new Shop(storeItems);
    const items = gildedRose.updateQuality();

    expect(items).toStrictEqual(expectedResult);
  });

  it("the quality of an aged brie should increase by 1", () => {
    const storeItems = [new Item("Aged Brie", 1, 0)];
    const expectedResult = [new Item("Aged Brie", 0, 1)];
    const gildedRose = new Shop(storeItems);
    const items = gildedRose.updateQuality();

    expect(items).toStrictEqual(expectedResult);
  });

  describe("Backstage passes", () => {
    it("increases in Quality as it's SellIn value approaches", () => {
      const storeItems = [
        new Item("Backstage passes to a TAFKAL80ETC concert", 14, 0)
      ];
      const expectedResult = [
        new Item("Backstage passes to a TAFKAL80ETC concert", 13, 1)
      ];
      const gildedRose = new Shop(storeItems);
      const items = gildedRose.updateQuality();

      expect(items).toStrictEqual(expectedResult);
    });

    it("Quality increases by 2 when there are 10 days or less", () => {
      const storeItems = [
        new Item("Backstage passes to a TAFKAL80ETC concert", 10, 0)
      ];
      const expectedResult = [
        new Item("Backstage passes to a TAFKAL80ETC concert", 9, 2)
      ];
      const gildedRose = new Shop(storeItems);
      const items = gildedRose.updateQuality();

      expect(items).toStrictEqual(expectedResult);
    });

    it("Quality increases by 3 when there are 5 days or less", () => {
      const storeItems = [
        new Item("Backstage passes to a TAFKAL80ETC concert", 5, 0)
      ];
      const expectedResult = [
        new Item("Backstage passes to a TAFKAL80ETC concert", 4, 3)
      ];
      const gildedRose = new Shop(storeItems);
      const items = gildedRose.updateQuality();

      expect(items).toStrictEqual(expectedResult);
    });

    it("Quality drops to 0 after concert", () => {
      const storeItems = [
        new Item("Backstage passes to a TAFKAL80ETC concert", 0, 30)
      ];
      const expectedResult = [
        new Item("Backstage passes to a TAFKAL80ETC concert", -1, 0)
      ];
      const gildedRose = new Shop(storeItems);
      const items = gildedRose.updateQuality();

      expect(items).toStrictEqual(expectedResult);
    });
  });
일부 코드를 수정하기 위해 많은 준비를 한 것처럼 보이지만, 진정으로 수정하기 전에 적당한 준비를 해야 재구성에 오류가 발생하지 않는다는 것을 확인할 수 있다.
나는 네가 바로 재구성을 시작하고 싶을 수도 있다는 것을 알고 있지만, 한 문장에서 너무 많이 했다. 며칠 후에 우리는 다시 시작하고, 처음부터 모든 코드를 재구성할 것이다. 동시에, 나는 네가 이 코드와 우리가 오늘 한 테스트를 한쪽에 놓고, 너 자신의 재구성을 해서, 다음 문장에서 나의 해결 방안과 비교할 것을 건의한다😃.
우리가 재구성을 완성한 후에, 우리는 규범에 그들이 요구하는 기능을 추가할 것이다. 나는 이것이 식은 죽 먹기가 될 것이라고 보장한다.
만약 당신이 이것을 좋아한다면 댓글에서 저에게 알려주세요. 공유를 잊지 마세요. 이 예를 어떻게 처리하는지에 대한 평론이나 건의가 있다면 댓글도 잊지 마세요.

좋은 웹페이지 즐겨찾기