Рефакторинг: обнаружение паттернов состояний из заказов kfc

JavaScript
Рефакторинг: обнаружение паттернов состояний из заказов kfc

что такое режим состояния

Поведение объекта зависит от его состояния (атрибутов), что позволяет объекту изменять свое внутреннее состояние и связанное с ним поведение в соответствии с изменением своего состояния.

Режим состояния очень похож на режим стратегии, он также инкапсулирует «состояние» класса и выполняет автоматические переходы при выполнении действий, чтобы понять, что одно и то же действие класса в разных состояниях дает разные результаты. Разница между ним и режимом стратегии заключается в том, что это преобразование является «автоматическим» и «бессознательным». Режим стратегии заключается в поиске нескольких решений одной и той же проблемы, и эти разные решения не имеют никакого отношения; режим Требуется, чтобы существовала связь между различными состояниями для достижения перехода между состояниями.

текст

Когда я вернулся с Национального дня, я решил провести рефакторинг важных проектов нашей компании.Из-за его сложной логики я не мог найти хороший угол, чтобы разобраться в коде.Однажды ночью, когда ночь была темной и ветреной, я пришел в kfc. Когда я увидел ослепительный контент в меню, я задумался...

image

Вот формальный код, не вникайте в него

    此时一份点单的内心独白
    
    if (我的钱>50) {
        if (饿) {
          我好富有啊随便点,点2个我最喜欢的原味鸡,再来个套餐
        } else {
          自己喜欢的单品都来一样好了
        }
    } else if (30<我的钱<50) {
        if (饿) {
          低于50的套餐
        } else {
          自己喜欢的单品累加不能超过50
        }
    } else if (15<我的钱<30) {
        if (饿){
            低于30的套餐
        }else{
            自己喜欢的单品累加不能超过30
        }
        ......
    } else if (5<我的钱<15) {
        只能根据价格来不能追求喜好了..
    } else {
        做洗碗工 || 饿肚子
    }

В случае изменения суммы денег или цены на еду (статус)

1. Необходимо изменить условия покупки: возможно, потребуется переписать условия оценки кода.

2. Необходимо углубиться в условия покупок: добавление условий на более глубокий уровень становится сложным и утомительным.

image

Дебют режима статуса

Шаг 1: выйти из состояния

Шаблон состояния сначала должен суммировать элементы, которые будут влиять на поведение.

Мы перечисляем текущее состояние и оборачиваем его объектом состояния:

    {
        hungry: true/false,
        money:  40,
        single:   [ 原味鸡, 鸡米花, 土豆泥, 薯条,汉堡...],
        setMeal:[ 高调奢华套餐(50¥)、性价比套餐(40¥)、不管饱套餐(25¥) ],
    }

Советы: в реальном бизнесе можно использовать различные интеллект-карты для обобщения состояния текущих потребностей.


Шаг 2: Планирование таблицы конфигурации

Инкапсулируйте взаимосвязь между состоянием и поведением в таблице и управляйте поведением посредством изменений состояния.

В соответствии с текущим состоянием конфигурационная таблица вариантов покупки суммируется:

    抽象出俩个单位即手上的钱和自身饥饿情况,同时他们都有自己的触发条件,也就是不同的状态。
    
     {
        money: { 
        
            money> 50: [...single, ...setMeal], // 喜爱的单品和套餐都能选择
            
            30 < money < 50: [...single, setMeal[0], setMeal[1]], // 价格允许的套餐和所有单品
            
            15 < money < 30: [...single, setMeal[2]], // 价格允许的套餐和所有单品
            
            5 < money < 15: [single[1], single[2], single[3]],// 价格允许的单品
            
            money < 5: 做洗碗工 || 饿肚子,
        },
        hungry: true / false,  //饿就选套餐/不饿选择单品
    }
    
    最后的购买行为:当前金钱数量决策出对应价位的菜品,再根据饥饿情况选出套餐还是单品组合

Мы можем понимать таблицу конфигурации как конечный автомат.Согласно изменению состояния, я могу повлиять на свое покупательское поведение.Если состояние (деньги) изменится (купоны, 50 юаней, найденные на земле...), также могу совершать предсказуемые покупки Действие (в конце концов, поведение было разделено в зависимости от количества денег).

Таблица конфигурации может больше фокусироваться на изменениях состояния при аварийном восстановлении кода или последующем обслуживании несколькими людьми.


Третий шаг (расширение): разделение на меньшую гранулярность

Добавить спрос: на кухне сказали, что оригинальная курица распродана и нужны только цветы с курицей и рисом, и необходимо разместить уведомление, а оригинальную курицу в наборе необходимо заменить на цветы с курицей и рисом.

Что касается детализации разделенной конфигурации, внимательно рассмотрите влияние внешних факторов на продукты питания, что приводит к изменениям в покупательском поведении, и возможность реконфигурации поведения в настраиваемый контент управления. Почему kfc — это блюдо и контейнер?

  
    single:   [ 原味鸡, 鸡米花, 土豆泥, 薯条,汉堡...],
    setMeal:[ 高调奢华套餐(50¥)、性价比套餐(40¥)、不一定管饱套餐(25¥) ],
    
    改造一下整体结构,每一个单品都有它的状态,方便我们根据状态组合(万一需求又改了呢?)
    
    single:   [
       // 想想为什么我要多加价格,万一之后售价(需求)变动了呢?
        {
          name:原味鸡,
          price:12,
          stock:false, // 没货啦
        }, 
        { name:鸡米花,
          price:10,
          stock:true,
        },
        ....
        ....
        ....
    ],
    setMeal:[ 
    // 把菜单和单品之间的联系挂起来
    {
        name:高调奢华套餐:
        price:50,  
        single[0], //原味鸡
        single[1], //鸡米花
        single[2], //土豆泥
        single[3], //薯条
        single[4]  //汉堡
    },{
        name:性价比套餐,
        price:40,
        .... // 单品组合
    }{
        name:不管饱套餐
        price:25
        .... // 单品组合
    } ],
    
    

Полные требования: Таким образом, вы можете напрямую заменить оригинальную курицу куриным попкорном.

   now: single[0] = single[1]

кейс

В проекте, который мне нужно рефакторить, много разных блоков. Часть содержимого форм, которые они отображают, одинакова, а часть отличается. В настоящее время я могу настроить его через режим состояния.

Оригинальный код:

    <el-form-item label="应用名称">
        <el-input v-model="form.name"/>
    </el-form-item>
    <el-form-item label="发部分支">
        <el-input v-model="form.branch"/>
    </el-form-item>
    <el-form-item v-if="env" label="发布环境">
        <el-input v-model="form.env"/>
    </el-form-item>
    <el-form-item v-if="appType==='node'|| appType==='static'" label="npm install">
        <el-input v-model="form.npm"/>
    </el-form-item>
    <el-form-item v-if="appType==='android'" label="打包加固">
        <el-input v-model="form.package"/>
    </el-form-item>
    <el-form-item v-if="appType!=='static'&& env!='dev'" label="发布暂停">
        <el-input v-model="form.isStop"/>
    </el-form-item>
    
    ..... // 省略各种条件

Улучшенный код:

    1.抽取状态: 
    
        环境:env:['prod', 'dev', 'test'], 应用:appType:['node','android','static']
    
    2.配置状态机:
    
        // configState.js
        
        const configState = {
            env:{
                env:['env','dev','test'],
                appType:['node','android','static'],
            },
            npm:{
                env:['env'],
                appType:['node','static'],
            },
            package:{
                env:['env','dev','test'],
                appType:['android'],
            },
             isStop:{
                env:['env','test'],
                appType:['android','node'],
            },
        }
        
        
    3.抽象行为:
        
        import { configState } from "./configState";
        
        // 抽象当前展示行为
        
        const state = fn(env, appType) {
            
            /*
            * 此处代码省略!!!
            * 遍历configState,若env和appType数组中均含有则为true
            */
            
            return {
                env:true,
                npm:true,
                package:false,
                isStop:true,
            },
        }
        
        
        <el-form-item label="应用名称">
            <el-input v-model="form.name"/>
        </el-form-item>
        <el-form-item label="发部分支">
            <el-input v-model="form.branch"/>
        </el-form-item>
        <el-form-item v-if="state.env" label="发布环境">
            <el-input v-model="form.env"/>
        </el-form-item>
        <el-form-item v-if="state.npm" label="npm install">
            <el-input v-model="form.npm"/>
        </el-form-item>
        <el-form-item v-if="state.package" label="打包加固">
            <el-input v-model="form.package"/>
        </el-form-item>
        <el-form-item v-if="state.isStop" label="发布暂停">
            <el-input v-model="form.isStop"/>
        </el-form-item>

Суммировать

Сцены

  1. Код содержит множество условных операторов, связанных с состоянием объекта, таких как if...else, switch..case и т. д.
  2. Путаница между логиками далеко друг от друга, и ее нужно абстрагировать и управлять ею в одном месте.
  3. Условия бизнеса часто меняются (программисты не берут на себя вину)

преимущество:

  1. При изменении или увеличении сцены логика переключения состояний распределяется по классам состояний.Добавляя новые классы состояний, легко добавлять новые состояния и переходы.

  2. Разделение, поведение в классах состояний и действий могут легко изменяться независимо друг от друга, не влияя друг на друга.

  3. Сплоченность, наличие государственной машины позволяет больше сосредоточиться на управлении государством.

недостаток:

  1. Существует столько одноэлементных методов, сколько и состояний, что создает много связанного поведения.

  2. Структура кода становится сложной, и необходимо предоставить специальный файл конечного автомата.

выполнить

  1. Сущностная модель государства-владельца.

  2. Интерфейс состояния (можно также использовать абстрактные классы), определяющий бизнес-методы.

  3. Каждый конкретный класс реализации состояния соответственно реализует бизнес-методы.


Ключ заключается в связи абстрактного состояния и поведения, обобщающей изменяемый и изменяемый код.

Все шаблоны проектирования имеют место в жизни,life is design

В конце концов, меня выгнала кассирша, потому что я был слишком испачкан чернилами и ничего не ел...