Мир такой большой и в нем так много достопримечательностей. Иногда изменение пути, изменение угла зрения, изменение компании будет иметь другое ощущение и выгоду. То же самое касается написания кода.
1. Введение
Я считаю, что у многих есть такой опыт.Когда проект загружен, они всегда думают о реализации в первую очередь, и реализуют план наилучшим образом на данный момент.Когда проект не занят, смотрят на предыдущий код и думают, что Хороший план реализации или план оптимизации. Автор не исключение.Позвольте мне поделиться с читателями решением, которое я недавно использовал для замены if-else и переключения в определенных случаях. Если у вас есть какие-либо идеи, пожалуйста, оставьте сообщение в области комментариев, и мы будем общаться больше.
2. Таблица поиска вместо if-else
Например, вы можете столкнуться с требованиями, подобными следующим: например, рейтинг кредитоспособности определенной платформы, более 700-950, означает отличную кредитоспособность, кредит 650-700 отлично, кредит 600-650 хорошо, кредит 550- 600 кредитов средний, 350-550 плохой кредит.
Реализация проста
function showGrace(grace) {
let _level='';
if(grace>=700){
_level='信用极好'
}
else if(grace>=650){
_level='信用优秀'
}
else if(grace>=600){
_level='信用良好'
}
else if(grace>=550){
_level='信用中等'
}
else{
_level='信用较差'
}
return _level;
}
Работает нормально, но есть проблемы
1. В случае будущего спроса, изменение, например, 650-750 является отличным кредитом, 750-950 является отличным кредитом. Это меняет весь метод.
2. Методы Существуют различные волшебные числа: 700, 650, 600, 550. Могут возникнуть проблемы с дальнейшим обслуживанием.
3. Слишком много if-else, выглядит немного навязчиво
Таким образом, справочная таблица используется ниже для реализации разделения конфигурации данных конфигурации и бизнес-логики.
function showGrace(grace) {
let graceForLevel=[700,650,600,550];
let levelText=['信用极好','信用优秀','信用良好','信用中等','信用较差'];
for(let i=0;i<graceForLevel.length;i++){
if(grace>=graceForLevel[i]){
return levelText[i];
}
}
//如果不存在,那么就是分数很低,返回最后一个
return levelText[levelText.length-1];
}
Преимущество такой модификации в том, что если есть необходимость ее модифицировать, то нужно модифицировать только graceForLevel и levelText. Бизнес-логику менять не нужно.
Почему здесь рекомендуется разделять конфигурацию данных конфигурации и бизнес-логику?
1. Изменение данных конфигурации менее затратно и менее рискованно, чем изменение бизнес-логики.
2. Источник данных конфигурации и модификация могут быть очень гибкими.
3. Рекомендуемая конфигурация и бизнес-логика разделены, и код, который необходимо изменить, можно найти быстрее
Если вы хотите быть более гибким, вы можете инкапсулировать несколько более общую функцию поиска.
function showGrace(grace,level,levelForGrace) {
for(let i=0;i<level.length;i++){
if(grace>=level[i]){
return levelForGrace[i];
}
}
//如果不存在,那么就是分数很低,返回最后一个
return levelForGrace[levelForGrace.length-1];
}
let graceForLevel=[700,650,600,550];
let levelText=['信用极好','信用优秀','信用良好','信用中等','信用较差'];
Есть еще одно преимущество использования рекомендуемых данных конфигурации и бизнес-логики для разделения разработки, которое не отражено в приведенном выше примере, поэтому кратко расскажем о нем ниже. Например, введите живописное место и укажите город, в котором находится живописное место.
function getCityForScenic(scenic) {
let _city=''
if(scenic==='广州塔'){
_city='广州'
}
else if(scenic==='西湖'){
_city='杭州'
}
return _city;
}
Войдите в Кантонскую башню, чтобы вернуться в Гуанчжоу. Войдите в Западное озеро, чтобы вернуться в Ханчжоу. Но в городе есть не одно живописное место, поэтому некоторые привыкли так писать.
if(scenic==='广州塔'||scenic==='花城广场'||scenic==='白云山'){
_city='广州'
}
Если достопримечательностей много и данные очень длинные, неудобно смотреть.Некоторым нравится так писать
let scenicOfHangZhou=['西湖','湘湖','砂之船生活广场','京杭大运河','南宋御街']
if(~scenicOfHangZhou.indexOf(scenic)){
_city='杭州'
}
Это правда, но написанный код может выглядеть следующим образом:непоследовательный стиль.
function getCityForScenic(scenic) {
let _city='';
let scenicOfHangZhou=['西湖','湘湖','砂之船生活广场','京杭大运河','南宋御街'];
if(scenic==='广州塔'||scenic==='花城广场'||scenic==='白云山'){
_city='广州'
}
else if(~scenicOfHangZhou.indexOf(scenic)){
_city='杭州'
}
return _city;
}
Даже с переключателем это может случиться
function getCityForScenic(scenic) {
let _city='';
let scenicOfHangZhou=['西湖','湘湖','砂之船生活广场','京杭大运河','南宋御街'];
switch(true){
case (scenic==='广州塔'||scenic==='花城广场'||scenic==='白云山'):_city='广州';break;
case (!!~scenicOfHangZhou.indexOf(scenic)):return '杭州';
}
return _city;
}
Хотя вероятность появления вышеуказанного кода очень мала, он все-таки появится. Такой код может вызвать ослепление глаз в будущем. Этой проблемы можно избежать, если использовать разделение данных конфигурации и бизнес-логики.
function getCityForScenic(scenic) {
let cityConfig={
'广州塔':'广州',
'花城广场':'广州',
'白云山':'广州',
'西湖':'杭州',
'湘湖':'杭州',
'京杭大运河':'杭州',
'砂之船生活广场':'杭州',
'南宋御街':'杭州',
}
return cityConfig[scenic];
}
Некоторые люди не привыкли к тому, что ключевое название объекта китайское. также можно гибко управлять
function getCityForScenic(scenic) {
let cityConfig=[
{
scenic:'广州塔',
city:'广州'
},
{
scenic:'花城广场',
city:'广州'
},
{
scenic:'白云山',
city:'广州'
},
{
scenic:'西湖',
city:'杭州'
},
{
scenic:'湘湖',
city:'杭州'
},
{
scenic:'京杭大运河',
city:'杭州'
},
{
scenic:'砂之船生活广场',
city:'杭州'
}
]
for(let i=0;i<cityConfig.length;i++){
if(cityConfig[i].scenic===scenic){
return cityConfig[i].city
}
}
}
Таким образом, если вы хотите добавить какие-либо достопримечательности и соответствующие города в будущем, вы можете только изменить приведенный выше файл cityConfig, а бизнес-логику изменять не нужно, и ее нельзя изменить. Стиль кода унифицирован выше.
Вот краткое резюме, преимущества использования формы разделения данных конфигурации и бизнес-логики
- Изменение данных конфигурации менее затратно и менее рискованно, чем изменение бизнес-логики.
- Источник данных конфигурации и модификация могут быть очень гибкими
- Конфигурация и бизнес-логика разделены, и код, который необходимо изменить, можно найти быстрее.
- Данные конфигурации и бизнес-логика могут сделать стиль кода согласованным.
Но не все if-else рекомендуют это преобразование, а некоторые требования не рекомендуют использовать преобразование поиска. Например, не так много if-else, логика if-else неоднородна, рекомендуется использовать метод if-else. Но волшебные числа должны быть очищены.
Например, следующее стирание входящей метки времени, показывающее необходимость отображения времени комментария,
Разместил комментарий менее 1 часа: x минут назад
Написал комментарий от 1 часа до 24 часов: x часов назад
Отправлено 24 часа ~ 30 дней комментариев: x дней назад
Опубликовать 30+ дней комментариев: месяц/день
Комментарии, опубликованные в прошлом году и старше 30 дней: год/месяц/день
Это не сложно реализовать, всего несколько if-else
function formatDate(timeStr){
//获取当前时间戳
let _now=+new Date();
//求与当前的时间差
let se=_now-timeStr;
let _text='';
//去年
if(new Date(timeStr).getFullYear()!==new Date().getFullYear()&&se>2592000000){
_text=new Date(timeStr).getFullYear()+'年'+(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日';
}
//30天以上
else if(se>2592000000){
_text=(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日';
}
//一天以上
else if(se>86400000){
_text=Math.floor(se/86400000)+'天前';
}
//一个小时以上
else if(se>3600000){
_text=Math.floor(se/3600000)+'小时前';
}
//一个小时以内
else{
//如果小于1分钟,就显示1分钟前
if(se<60000){se=60000}
_text=Math.floor(se/60000)+'分钟前';
}
return _text;
}
Ходовой результат не проблема, но есть и проблема, то есть у этого запроса сказочные числа: 2592000000, 86400000, 3600000, 60000. Для последующего обслуживания вы можете не знать, что это за номер в начале.
Таким образом, следующее устранит волшебные числа и сделает их постоянными.
function formatDate(timeStr){
//获取当前时间戳
let _now=+new Date();
//求与当前的时间差
let se=_now-timeStr;
const DATE_LEVEL={
month:2592000000,
day:86400000,
hour:3600000,
minter:60000,
}
let _text='';
//去年
if(new Date(timeStr).getFullYear()!==new Date().getFullYear()&&se>DATE_LEVEL.month){
_text=new Date(timeStr).getFullYear()+'年'+(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日';
}
//一个月以上
else if(se>DATE_LEVEL.month){
_text=(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日';
}
//一天以上
else if(se>DATE_LEVEL.day){
_text=Math.floor(se/DATE_LEVEL.day)+'天前';
}
//一个小时以上
else if(se>DATE_LEVEL.hour){
_text=Math.floor(se/DATE_LEVEL.hour)+'小时前';
}
//一个小时以内
else{
//如果小于1分钟,就显示1分钟前
if(se<DATE_LEVEL.minter){se=DATE_LEVEL.minter}
_text=Math.floor(se/DATE_LEVEL.minter)+'分钟前';
}
return _text;
}
Ходовой результат тоже правильный, кодов стало больше, а сказочных цифр уже нет. Читабельность тоже не плохая.
Кстати, если вы настаиваете на том, чтобы изменить приведенные выше требования на поиск, код выглядит следующим образом. Таким образом, модификация кода будет более масштабируемой, а стоимость будет меньше, но читабельность будет не такой хорошей, как указано выше. Отношения компромисса, реальная ситуация, фактический анализ.
function formatDate(timeStr){
//获取当前时间戳
let _now=+new Date();
//求与当前的时间差
let se=_now-timeStr;
let _text='';
//求上一年最后一秒的时间戳
let lastYearTime=new Date(new Date().getFullYear()+'-01-01 00:00:00')-1;
//把时间差添加进去(当前时间戳与上一年最后一秒的时间戳的差)添加进去,如果时间差(se)超过这个值,则代表了这个时间是上一年的时间。
//DATE_LEVEL.unshift(_now-lastYearTime);
const DATE_LEVEL={
month:2592000000,
day:86400000,
hour:3600000,
minter:60000,
}
let handleFn=[
{
time:DATE_LEVEL.month,
fn:function(timeStr){
return (new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日';
}
},
{
time:DATE_LEVEL.day,
fn:function(timeStr){
return Math.floor(se/DATE_LEVEL.day)+'天前';
}
},
{
time:DATE_LEVEL.hour,
fn:function(timeStr){
return Math.floor(se/DATE_LEVEL.hour)+'小时前';
}
},
{
time:DATE_LEVEL.minter,
fn:function(timeStr){
return Math.ceil(se/DATE_LEVEL.minter)+'分钟前';
}
}
];
//求上一年最后一秒的时间戳
let lastYearTime=new Date(new Date().getFullYear()+'-01-01 00:00:00')-1;
//把时间差(当前时间戳与上一年最后一秒的时间戳的差)和操作函数添加进去,如果时间差(se)超过这个值,则代表了这个时间是上一年的时间。
handleFn.unshift({
time:_now-lastYearTime,
fn:function(timeStr){
if(se>DATE_LEVEL.month){
return new Date(timeStr).getFullYear()+'年'+(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日';
}
},
});
let result='';
for(let i=0;i<handleFn.length;i++){
if(se>=handleFn[i].time){
result=handleFn[i].fn(timeStr);
if(result){
return result;
}
}
}
//如果发布时间小于1分钟,之际返回1分钟
return result='1分钟前'
}
3. Конфигурационный объект вместо переключателя
Например, есть требование: входящие наличные, чек, черновик, zfb, wx_pay, соответствующий вывод: наличные, чек, денежный перевод, платеж Alipay, WeChat.
Требования также очень просты, достаточно переключателя.
function getPayChanne(tag){
switch(tag){
case 'cash':return '现金';
case 'check':return '支票';
case 'draft':return '汇票';
case 'zfb':return '支付宝';
case 'wx_pay':return '微信支付';
}
}
Но этот недостаток все тот же, что и выше, на тот случай, если в следующий раз вам понадобится добавить еще один, например: bank_trans соответствует выходному банковскому переводу, и код нужно будет снова изменить. Аналогичная проблема, такое же решение, разделение данных конфигурации и бизнес-логики. код показывает, как показано ниже.
function getPayChanne(tag){
let payChanneForChinese = {
'cash': '现金',
'check': '支票',
'draft': '汇票',
'zfb': '支付宝',
'wx_pay': '微信支付',
};
return payChanneForChinese[tag];
}
Точно так же, если вы хотите инкапсулировать общий, вы также можете
let payChanneForChinese = {
'cash': '现金',
'check': '支票',
'draft': '汇票',
'zfb': '支付宝',
'wx_pay': '微信支付',
};
function getPayChanne(tag,chineseConfig){
return chineseConfig[tag];
}
getPayChanne('cash',payChanneForChinese);
Преимущество использования объекта вместо переключателя в том, что
- Использование объектов не требует переключения на обход в каждом конкретном случае.
- Используя объекты, написание бизнес-логики может быть более гибким
- Использование объектов позволяет разделить данные конфигурации и бизнес-логику. Преимущества относятся к предыдущему разделу.
4. Резюме
В наши дни существует так много решений для замены if-else и переключения в определенных ситуациях. Если-иначе, сам переключатель правильный, в основном думает о том, как оптимизировать код, чтобы сделать код более читабельным и расширяемым. Если у вас есть какие-либо другие оптимизированные решения или лучшие решения для реализации других аспектов. Добро пожаловать, чтобы оставить сообщение в области комментариев.
------------------------- Великолепная разделительная линия --------------------
Хотите узнать больше, обратите внимание на мой публичный аккаунт WeChat: В ожидании книжного магазина