предисловие
Недавно я выполнил требования декабрьской версии, и есть некоторые коды, которые недостаточно глубоки, чтобы о них думать, поэтому я напишу резюме. Я надеюсь, что каждый будет больше думать и обобщать больше в своем ежедневном написании кода. В то же время, если что-то не так, пожалуйста, укажите на это.
гитхаб-адрес
1. Можно ли изменить порядок сложных логических условий, чтобы сделать программу более эффективной?
Предполагая, что бизнес-требование таково: участники, приземлившиеся впервые, должны отправить благодарственные письма. Если не думают, пишите код напрямую
if(isUserVip && isFirstLogin){
sendMsg();
}
Предположим, что всего 5 запросов, 3 запроса проходят через isUserVip, и 1 запрос проходит через isFirstLogin.Затем приведенный выше код isUserVip выполняется 5 раз, isFirstLogin выполняется 3 раза, как показано ниже:
Что если изменить порядок isUserVip и isFirstLogin?
if(isFirstLogin && isUserVip ){
sendMsg();
}
Количество выполнений isFirstLogin — 5 раз, а количество выполнений isUserVip — 1 раз, следующим образом:
Ваша программа более эффективна, Цзянцзы?
Во-вторых, ваша программа непреднамеренно создала ненужные объекты.
Чтобы дать просо, определите, являются ли участники пользователя, которые обычно имеют следующий аналогичный код:
//判断用户会员是否在有效期
public boolean isUserVIPValid() {
Date now = new Date();
Calendar gmtCal = Calendar.getInstance();
gmtCal.set(2019, Calendar.JANUARY, 1, 0, 0, 0);
Date beginTime = gmtCal.getTime();
gmtCal.set(2020, Calendar.JANUARY, 1, 0, 0, 0);
Date endTime= gmtCal.getTime();
return now.compareTo(beginTime) >= 0 && now.compareTo(endTime) <= 0;
}
Однако при каждом вызове метода isUserVIPValid создаются объекты Calendar и Date. На самом деле, кроме New Date, остальные объекты неизменны, мы можемИзвлечь глобальные переменные,Избегайте создания ненужных объектов, чтобы повысить эффективность программы, следующим образом:
public class Test {
private static final Date BEGIN_TIME;
private static final Date END_TIME;
static {
Calendar gmtCal = Calendar.getInstance();
gmtCal.set(2019, Calendar.JANUARY, 1, 0, 0, 0);
BEGIN_TIME = gmtCal.getTime();
gmtCal.set(2020, Calendar.JANUARY, 1, 0, 0, 0);
END_TIME = gmtCal.getTime();
}
//判断用户会员是否在有效期
public boolean isUserVIPValid() {
Date now = new Date();
return now.compareTo(BEGIN_TIME) >= 0 && now.compareTo(END_TIME) <= 0;
}
}
3. При запросе к базе данных вы проверили слишком много данных?
Все мы знаем, что запросы к базе данных — это трудоемкая операция, особенно когда объем данных велик. Поэтому при запросе к БД нам нужно просто взять то, что нам нужно, и нет необходимости делать все подряд.
Предположим, бизнес-сценарий таков: запросите, является ли пользователь участником. Видели код реализации, как это. . .
List<Long> userIds = sqlMap.queryList("select userId from user where vip=1");
boolean isVip = userIds.contains(userId);
Зачем сначала проверять все случаи, а затем определять, включен ли useId, чтобы определить, является ли useId членом? Передайте userId прямо в sql, разве это не ароматно? следующее:
Long userId = sqlMap.queryObject("select userId from user where userId='userId' and vip='1' ")
boolean isVip = userId!=null;
На самом деле, в дополнение к передаче всех условий запроса в прошлом, чтобы база данных не запрашивала избыточные данные, мы также можем передатьвыбрать определенные полязаменятьselect *
, тем самым делая программу более эффективной.
4. Плюс строка класса уведомлений, всегда влияет на основной процесс.
Предположим, бизнес-процесс такой: когда пользователь входит в систему, нужно добавить текстовое сообщение, чтобы уведомить его поклонников. Процесс реализации легко представить следующим образом:
Предполагая, что служба sendMsgNotify предоставляетсясистема зависает,илиНе удалось вызвать sendMsgNotify, то вход пользователя завершается ошибкой. . .
Функция уведомления сделала недоступным основной процесс входа в систему, очевидно собирая семена кунжута и бросая арбузы. Так есть ли способ получить и то, и другое? Да, для отправки смс интерфейсапоймать обработку исключений,илиОткройте другой поток для асинхронной обработки,следующее:
Поэтому, когда мы добавляем классы уведомлений и прочие неосновные, даунгрейд интерфейсы, нам стоит успокоиться и подумать, не повлияет ли это на основной процесс и как с этим лучше поступить.
5. Сохраняйте чутье на нулевые указатели, например, при использовании сравнения на равенство размещайте константы или определенные значения слева.
Исключение NullPointException уже давно стало обычным явлением в мире Java.Когда мы пишем код, мы можем дважды подумать о написании и попытаться избежать низкоуровневых проблем с нулевыми указателями.
Например, в следующих бизнес-сценариях для определения того, является ли пользователь участником, часто используется следующий код:
boolean isVip = user.getUserFlag().equals("1");
Если вы поместите эту строку кода в производственную среду, когда вы внезапно оглянетесь назад, возможно, ошибка нулевого указателя находится в тусклом свете. Очевидно, что это может сгенерировать исключение нулевого указателя, поскольку user.getUserFlag() может быть нулевым.
Как избежать проблемы с нулевым указателем? Просто поместите константу 1 слева, как показано ниже:
boolean isVip = "1".equals(user.getUserFlag());
6. Сопровождаются ли ваши ключевые бизнес-коды логами?
Критического для бизнеса кода должно быть достаточно, где бы он ни находился.бревноЭскорт.
Например:Вы реализуете трансферный бизнес, переводите несколько миллионов, потом перевод терпит неудачу, а потом клиент жалуется, а потом вы не напечатали это в журнале, подумайте о страшной дилемме, но вы ничего не можете с этим поделать. . .
Тогда ваш трансферный бизнесНужна эта информация журналаШерстяная ткань? По крайней мере, перед вызовом метода нужно вывести входные параметры, а после вызова интерфейса нужно поймать исключение и распечатать лог, относящийся к исключению, следующим образом:
public void transfer(TransferDTO transferDTO){
log.info("invoke tranfer begin");
//打印入参
log.info("invoke tranfer,paramters:{}",transferDTO);
try {
res= transferService.transfer(transferDTO);
}catch(Exception e){
log.error("transfer fail,cifno:{},account:{}",transferDTO.getCifno(),
transferDTO.getaccount())
log.error("transfer fail,exception:{}",e);
}
log.info("invoke tranfer end");
}
В дополнение к печати достаточного количества журналов, мы также должны отметить, чтоЗапутанное использование уровней журнала, не распечатывайте информационный журнал, но вы печатаете его как уровень ошибки, и будильник призывает вас встать посреди ночи, чтобы устранить проблему.
7. Можно ли оптимизировать функцию с большим количеством строк, разбив ее на мелкие функции?
Когда мы поддерживаем старый код, мы часто видим кучу кода, некоторыеСотни или даже тысячи строк функций, читать сложнее.
Предположим, теперь у вас есть следующий код
public class Test {
private String name;
private Vector<Order> orders = new Vector<Order>();
public void printOwing() {
//print banner
System.out.println("****************");
System.out.println("*****customer Owes *****");
System.out.println("****************");
//calculate totalAmount
Enumeration env = orders.elements();
double totalAmount = 0.0;
while (env.hasMoreElements()) {
Order order = (Order) env.nextElement();
totalAmount += order.getAmout();
}
//print details
System.out.println("name:" + name);
System.out.println("amount:" + totalAmount);
}
}
После разделения на небольшие функции с одной функцией:
public class Test {
private String name;
private Vector<Order> orders = new Vector<Order>();
public void printOwing() {
//print banner
printBanner();
//calculate totalAmount
double totalAmount = getTotalAmount();
//print details
printDetail(totalAmount);
}
void printBanner(){
System.out.println("****************");
System.out.println("*****customer Owes *****");
System.out.println("****************");
}
double getTotalAmount(){
Enumeration env = orders.elements();
double totalAmount = 0.0;
while (env.hasMoreElements()) {
Order order = (Order) env.nextElement();
totalAmount += order.getAmout();
}
return totalAmount;
}
void printDetail(double totalAmount){
System.out.println("name:" + name);
System.out.println("amount:" + totalAmount);
}
}
один слишкомдлинныйфункция или частьТребуются аннотации для пониманияДля целей кода вы можете разделить его на функциональный блок с четкой функцией и определить четкое и короткое имя функции, что сделает код более элегантным.
Восемь, некоторые переменные факторы, такие как красная кожа конверта и т. Д., Лучше будет создать конфигурацию.
Если продукт запрашивает красный конверт, на Рождество скин красного конверта связан с Рождеством, а во время Праздника Весны — красный скин конверта и т. д.
Если элемент управления жестко запрограммирован в коде, может быть код, подобный следующему:
if(duringChristmas){
img = redPacketChristmasSkin;
}else if(duringSpringFestival){
img = redSpringFestivalSkin;
}
......
Если во время Фестиваля фонарей у мисс Операции вдруг появится идея, и красный скин конверта изменится на фонарь, в это время вам нужно изменить код и переиздать его?
С самого начала внедрить таблицу конфигурации скинов красных конвертов и настроить скины красных конвертов? Чтобы заменить скин красного конверта, просто измените данные таблицы.
9. Следует ли удалять избыточные классы импорта, локальные переменные и ссылки?
Если в коде видно, что не используется класс импорта, не используются локальные переменные и т.д., то для его удаления выполняется следующее:
Это не локальные переменные, на которые ссылаются, если вы к ним не привыкли, удалите их, это не винтажная версия Nver, она будет более мягкой. Он по-прежнему будет скомпилирован вместе, пока это ресурсы Haozhe.
10. При запросе большой таблицы, добавить ли индекс, ваш sql имеет индекс.
При запросе таблицы с большим объемом данных нам необходимо подтвердить три момента:
- Ваша таблица проиндексирована?
- Ваш запрос sql попадает в индекс
- Есть ли у вашего sql место для оптимизации?
В целом, для таблиц с более чем 100 000 данных необходимо рассмотреть возможность добавления индексов к таблицам. При каких обстоятельствах индекс не удастся? Как подстановочные знаки, операции столбцов индекс и т. Д. Приведут провалиться индекс. Заинтересованные друзья могут прочитать мою статью.Бэкенд-программисты должны: десять самых разных симптомов сбоя индекса
11. Должен ли ваш метод возвращать пустую коллекцию или ноль?
Если возвращается значение null, вызывающий объект может сгенерировать исключение нулевого указателя, если забудет проверить. Возврат пустого набора спасает проблему.
При запросе mybatis, если возвращается коллекция, также будет возвращена пустая коллекция, если результат пустой, а не нулевой.
Положительный пример
public static List<UserResult> getUserResultList(){
return Collections.EMPTY_LIST;
}
12. Попробуйте указать размер коллекции при ее инициализации
Руководство по разработке Али рекомендует это
Предполагая, что количество элементов, которые будут храниться на вашей карте, составляет около 15, оптимальный способ записи выглядит следующим образом.
//initialCapacity = 15/0.75+1=21
Map map = new HashMap(21);
又因为hashMap的容量跟2的幂有关,所以可以取32的容量
Map map = new HashMap(32);
13. Если при запросе к базе данных возвращается слишком много данных, рассмотрите возможность выполнения этого в пакетном режиме.
Предположим, что в вашей таблице заказов содержится 100 000 данных для обновления статуса.Вы не можете запрашивать все необновленные заказы одновременно, а только пакетами.
Пример счетчика:
List<Order> list = sqlMap.queryList("select * from Order where status='0'");
for(Order order:list){
order.setStatus(1);
sqlMap.update(order);
}
Положительный пример:
Integer count = sqlMap.queryCount(select count(1) from Order where status ='0');
while(true){
int size=sqlMap.batchUpdate(params);
if(size<500){
break;
}
}
14. Учитывает ли ваш интерфейс идемпотентность и параллелизм?
Что такое идемпотентность?Запрос ресурса один и несколько раз должен иметь одинаковый результат для самого ресурса. Другими словами, любое его многократное выполнение будет иметь такое же влияние на сам ресурс, как и однократное выполнение.
Зачем нужна идемпотентность?
- Пользователь нажал несколько раз, чтобы отправить заказ в APP, поэтому невозможно создать несколько заказов.
- Если пользователь непрерывно нажимает для отправки сообщения из-за сетевой карты, получатель не может повторно получать одно и то же сообщение.
Предположим, есть бизнес-сценарий:
Когда пользователь нажимает кнопку загрузки, система начинает скачивать файл, а когда пользователь снова нажимает кнопку загрузки, появляется сообщение о том, что файл загружается.
Некоторые люди делают это так:
Integer count = sqlMap.selectCount("select count(1) from excel where state=1");
if(count<=0){
Excel.setStatus(1);
updateExcelStatus();
downLoadExcel();
}else{
"文件正在下载中"
}
Мы можем посмотреть, какие проблемы могут быть два запроса?
Процесс реализации:
- На первом этапе A запрашивает файлы, которые не загружаются.
- На втором этапе B запрашивает файлы, которые не загружаются.
- Третий шаг, А начинает скачивать файл
- Часть 4, B начинает загрузку файла
Очевидно, это проблема, пока два файла качать. Правильная реализация этого?
if(updateExcelStatus(1){
downLoadExcel();
}else{
"文件正在下载中"
}
В-пятых, укрепляйте ваши инструменты с частным конструктором, это не Miya?
Методы класса инструмента являются статическими методами, которые можно вызывать непосредственно через класс. Но некоторые вызывающие объекты могут сначала создавать экземпляры, а затем вызывать объект, а это нехорошо. Как избежать этой ситуации и позволить вашему инструментальному классу достичь управляемого состояния?Добавить частный конструктор
public class StringUtis{
private StringUtis(){} ///私有构造类,防止意外实例出现
public static bool validataString(String str){
}
}
16. Кэшируется ли производительность практически неизмененных пользовательских данных?
Предположим, что ваш интерфейс должен много раз запрашивать базу данных, получать данные в каждом, а затем выполнять различные сортировки и другие операции на основе данных.После этой серии жестких операций производительность интерфейса определенно не является хорошей. Типичные сценарии применения, такие как: список прямых трансляций.
Итак, как его оптимизировать? Проанализируйте каждую часть отсортированных вами данных, данные, которые меняются в режиме реального времени, продолжайте проверять БД, неизменяемые данные, такие как возраст пользователя, выполняйте запланированное задание, вытаскивайте их из БД в кеш, и перейти непосредственно к кешу.
Следовательно, эта точка зрения состоит в том, чтобы правильно использовать кеш в нужное время.
Быть добавленным...
Личный публичный аккаунт
- Если вы хороший ребенок, который любит учиться, вы можете подписаться на мой официальный аккаунт, чтобы учиться и обсуждать вместе.
- Если вы считаете, что в этой статье есть какие-либо неточности, вы можете прокомментировать или подписаться на мой официальный аккаунт, пообщаться со мной в частном порядке, и все смогут учиться и прогрессировать вместе.
- адрес гитхаба:GitHub.com/Я бы хотел 123/Java…