⚠️Эта статья является первой подписанной статьей сообщества Nuggets, и её перепечатка без разрешения запрещена.
причина события
В середине июня прекрасный продукт дал мне временный спрос, требуя от меня商品创建/更新业务中由开放平台对接而来的请求做一个Check,如果符合要求,则再做一段稍微复杂的逻辑处理
.
этоEasyКак требование уровня могло меня остановить?Менее чем за полдня я закончил Coding and Pushing одним махом.Как раз, когда я собирался заказать чашку HEYTEA и начать рыбалку, я получил электронное письмо.
В письме много китайских и английских иероглифов, но несколько слов выделяются:
您的代码已被驳回。
Когда я прошел через эмоциональные изменения, ошеломленные, шокированные, невероятные и, наконец, отказывающиеся принимать, я спросил своего коллегу по обзору, почему мой код был отклонен, и он сказал: "Общий бизнес исторического кода очень полный (так же, как Шишан...), поэтому, если есть новые требования, которые должны полагаться на него, как можно?
Делать — лучшее решение, чтобы код имел лучшую масштабируемость, вы когда-нибудь задумывались об этом?".
Я определенно не думал об этом, поэтому с небольшим чувством вины я нашел архитектора, надеясь, что он сможет дать мне какой-нибудь совет.
Найдите место, которое выглядит подходящим, чтобы поместить его.
яркая архитектура: Кервин, этот код ленивый?
try {
// 忽略历史业务代码,以下为新增内容
} catch (Exception) {
// TODO
} finally {
SkuMainBean retVal = skuMainBridgeService.updateSkuBridgeMainBean(skuMainBean);
if(retVal != null){
// 商品创建/修改异步处理逻辑
SimpleThreadPool.executeRunnable(SimpleThreadPool.ThreadPoolName.openSkuHandle, () -> {
skuOperateBusinessService.checkOpenSkuReview(retVal);
});
}
}
Я (хоть я и не считаю это правильным, но все равно притворяюсь спокойным): я не ленивый, вы можете видеть, что этот кусок бизнес-кода не влияет на исходную функцию, и использует пул потоков для асинхронной обработки, что не повлияет на общую эффективность интерфейса, а также инкапсулирует сложную логику вBusiness
Слой, это еще называется ленью?
яркая архитектура: Считаете ли вы этот процесс создания/модификации продукта важным? Это наш основной процесс? Следующий продукт выдвинет новые требования,继续 if 然后叠罗汉吗
? Насколько я помню, ты говорил, что больше всего ненавидишь видеть в коде?if
Шерстяная ткань?
я (тихо): Я ненавижу видеть чужие "если", но мое собственное приемлемо...
Яркая архитектура (газовый смех): Не будем с вами тупить, давайте вместе подумаем, как его поменять.
PS: [Найдите подходящее место для его размещения] Этот метод мы используем чаще всего, он оказывает относительно небольшое влияние и имеет самую высокую эффективность разработки, но проблема, которую он приносит, заключается в том, что его нелегко поддерживать позже. , а по мере увеличения спроса станет таким же, как стекирование Архатов.Изначально очень простой метод function станет "горой дерьма" с сотнями строк, поэтому его нужно использовать по назначению.
Прекращение приоритетной проверки
Я (начинает думать): Если требуется прекратить выполнение при невыполнении определенного условия, то эта ситуация слишком проста, поэтому я не буду о ней говорить.
яркая архитектура: На самом деле есть еще что сказать, типа你需要在不满足时返回标识符结果加细节原因,你怎么处理?
я: определить строку напрямую и вернуть ее, а затем определить, является ли строка NULL.
яркая архитектура: Что, если это просто не удалось, и причина также NULL или пустая строка? На самом деле мы используем泛型
Есть более элегантные решения, например определение кортежа следующим образом:
public class ValueMsgReturn<A, B> {
/** 结果 **/
private final A value;
/** 原因 **/
private final B msg;
public ValueMsgReturn(A value, B msg) {
this.value = value;
this.msg = msg;
}
// 省略Get方法
}
Преимущество этого в том, что он общий и простой, и вам не нужно определять повторяющиеся объекты. Вы можете увидеть, насколько это ароматно, попробовав его в коде. Общий код выглядит следующим образом:
// 省略干扰代码
ValueMsgReturn<Boolean, String> check = check();
if (check.getValue()) {
return check.getValue();
}
PS: Ситуация относительно простая, но навыки по оптимизации кода все же есть, подробнее в исторической статье:
Простой шаблон наблюдателя
Я (продолжаю думать): Ваша ситуация слишком проста, вернемся к теме, мы можем использовать это требование观察者模式解耦
Какие!
Яркая архитектура (колеблясь): Это не невозможно, но подумайте, какой код нам нужно изменить.
я: Ядром наблюдателя является通知方
+ 处理方
, если мы используем режим наблюдателя, поставляемый с JDK, изменения следующие:
- Нужно наследовать класс в историческом коде
Observable
своего рода - Новый метод обработки абстрагируется в отдельный класс по единому принципу, который реализует
Observer
интерфейс - Создайте отношение уведомления между ними при инициализации класса.
яркая архитектура: Если часть логики разработана с помощью шаблона наблюдателя, это нормально, но исторический код не подходит,因为它一个类里面包含大量的其他方法
, если возникнет вторая ситуация, о которой нужно уведомить в будущем, код будет сложнее поддерживать, ведь режим наблюдателя JDK нужно наследоватьObservable
Класс, конечно, невозможен как альтернатива.
PS: Описанный выше режим наблюдателя JDK соответствует версии JDK 1.8.Подробнее о режиме наблюдателя см. в исторической статье
[Серия «Учимся вместе»] Режим наблюдателя: я не слежу за вами
AOP
я (вдруг вспомнилось): яркая архитектура, говоришь используйAOP
Уместно ли иметь с ним дело?
яркая архитектура: В общем, для каких действий мы используем АОП?
я: В моем случае он обычно используется для обработки разрешений, печати журнала, синхронизации кеша, специального подсчета сцен и т. д.
яркая архитектура: Да, представьте, как бы это выглядело, если бы мы всю эту бизнес-логику свалили в аспекты? Одна точка разреза — это нормально, а как насчет двух и десяти? Когда все получат новый проект, они будут ссылаться на предыдущий стиль кода.Если вы плохо начнете, другие люди будут следовать тому же принципу, и вскоре код станет похож на паутину, поэтому этого пути следует избегать.
Развязка MQ
я (вдруг вспомнилось): Кстати, у наших новинок/модификаций будет MQ, я пользуюсь только监听MQ然后做业务处理
Достаточно.
яркая архитектура: Это определенно осуществимо, но это немного похоже на убийство цыплят ножом мясника.В конце концов, ситуация, с которой нам нужно иметь дело, — это лишь малая часть MQ, а что, если исторический код не отправляет MQ?
Spring Event
яркая архитектура: Вы зналиSpring Event
?
я: Я исследовал это раньше, и это действительно вполне уместно использовать здесь.
PS: Spring Event — это механизм уведомления о событиях в системе Spring, и его принцип можно понимать как режим наблюдателя, реализованный Spring.
Примечание. Приведенный выше простой шаблон наблюдателя относится к шаблону наблюдателя, реализованному JDK (1.8).
// 以下为Demo代码
@RestController
public class EventRequest implements ApplicationContextAware {
private ApplicationContext appContext;
@RequestMapping("/testEvent")
public String testEventSave(String name) {
appContext.publishEvent(new User(this, name));
return "ok";
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
appContext = applicationContext;
}
}
// 监听者
@Component
public class WebEventListener {
/**
* 仅监听字段值为 foo 时,类为 User.class 时
*/
@EventListener(classes = User.class, condition = "#event.name == 'foo'")
public void listen(User event){
// TODO
}
/**
* 监听 User.class 情况
*/
@EventListener(classes = User.class)
public void listen1(User event){
// TODO
}
}
яркая архитектура: Да, эта демонстрация может отражать его преимущества.
- Мы можем публиковать несколько событий в одном методе, не мешая друг другу
- Слушатели могут выполнять базовую фильтрацию на основе выражений
- Событие можно прослушивать повторно
я: Да, и он также может поддерживать асинхронную обработку событий!
Яркая архитектура (пауза): Считаете ли вы поддержку асинхронности уникальным преимуществом? Ха-ха-ха, даже если вы слушаете события синхронно, вам просто нужно использовать пул потоков для их асинхронной обработки. Возможность естественной асинхронности — это просто вишенка на торте, не запутайтесь. Конечно, у каждой технологии и функции есть свои уникальные сценарии использования, и вам нужно обращать внимание на их особые обстоятельства при их использовании, такие как:
- Разрешена ли асинхронная обработка в бизнесе (даже если она затягивается на долгое время)
- Можете ли вы полностью доверять параметрам в уведомлении о событии, нужно ли вам возвращаться и т.д.
Есть ли другой способ
Я счастлив): Если я использую Spring Event, то мне нужно только немного изменить его.Масштабируемость и ремонтопригодность кода всплывут сразу, а мы только что говорили о таком количестве методов и способов, как я чувствую, что это все观察者模式
А?
яркая архитектура: Да, будь то JDK или Spring, или AOP, MQ, это все идеи паттерна Observer,毕竟观察者模式的特点就是解耦
.
я: Разве мы не можем использовать другие идеи шаблонов проектирования?
яркая архитектура: Конечно можно, но изменений может быть чуть больше, ведь этот класс почти тысячи строк, так что старайтесь добавлять как можно меньше вещей.
я: Например, какие еще методы можно использовать?
яркая архитектура: Гм... если вы хотите это услышать, вот посмотрите на ваш исходный код:
finally {
SkuMainBean retVal = skuMainBridgeService.updateSkuBridgeMainBean(skuMainBean);
if(retVal != null){
// 商品创建/修改异步处理逻辑
SimpleThreadPool.executeRunnable(SimpleThreadPool.ThreadPoolName.openSkuHandle, () -> {
skuOperateBusinessService.checkOpenSkuReview(retVal);
});
}
}
В этом бизнес-методе это должно бытьskuMainBean
Object, потому что весь метод оперирует им, то мы можем абстрагировать один за другим класс стратегии, а затем использовать фабрику для работы с ним, например, изменить его на это:
// 修改后代码
finally {
skuMainBeanFactory.checkAndHandle(skuMainBean);
}
// 工厂方法
public void checkAndHandle (SkuMainBean skuMainBean) {
for (策略集合: 策略) {
if (check(skuMainBean)) {
// TODO
}
}
}
яркая архитектура: Как вы думаете, это также очень расширяемо?
я (взволнованно): Да я вдруг чувствую, что этот метод похож на SpringEvent!
Яркая архитектура (улыбается):孺子可教也,这种策略+工厂的方式是基于接口编程,通过check方法判断是否需要处理,而SpringEvent说白了是通过事件的传播,即方法直接调用来判断是否需要处理,本质都是一样的,那你知道未来的新需求你该怎么写了吗?
я (взволнованно): Я вижу, если вы хотите написать масштабируемый код, вы не сможете сделать это так, как код, который я изменил сегодня, это чушь!
Яркая архитектура (качает головой, встает и идет):Kerwin,你错了,你今天改的历史代码在当时可以说是最佳实践了,只是因为你遇到了之前的设计者未考虑到的问题而已。我们讲设计模式、讲七大原则,讲不要过度设计,就是为了你现在出现的情况,我们在编码过程中可能会遇到千奇百怪的代码,我们可以抱怨,可以吐槽,但记住,不要为了某些需求就把本来漂亮的代码变成屎山。所以你需要去学习编程的思想,学习设计的思想。
я (громко):Вот, архитектор! Что, если бы был кусок кода, который был настолько гнилым, что он не мог стать еще более гнилым!
"Тогда рефакторинг! Тогда запиши имя автора и разглагольствуй о нем! 🤪"
Наконец
Просмотрите полный текст, чтобы сделать резюме, если ваше требование состоит в том, чтобы разрешить возврат предварительной проверки, то проверьте и верните без колебаний! Однако, если ваши потребности совпадают с моими, рекомендуются следующие варианты:
- Развязка с MQ
- Разделение с SpringEvent
- Подумайте, нужен ли вам класс стратегии, исходя из ваших текущих потребностей и возможных будущих потребностей.
- Окончательное решение: по-настоящему понять семь принципов программирования и часто используемые шаблоны проектирования и соответствующим образом адаптироваться.
Поэтому позвольте мне порекомендовать предыдущую статью:Шаблоны проектирования в целом: от того, зачем нужны принципы, до фактической реализации
Если вы найдете этот контент полезным:
- Конечно, ставьте лайки и поддерживайте~
- Кроме того, вы можете искать и следить за официальной учетной записью "это Кервин», давайте вместе пойдем по дороге технологий~ 😋