成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

煩死了,業務代碼老寫不好...

開發 前端 開發工具
本文舉一個非常簡單的例子,以案例的業務實現來分析如何寫好業務代碼。

 [[401825]]

圖片來自 Pexels

本案例只是簡單的模擬,可能與真實的情況有出入,這里只是為了舉例使用。

案例:用戶挑選商品放入購物車,然后下單結算。

流程如下:挑選商品→下單→結算→生成訂單→通知。

提交下單的業務邏輯如下:驗證賬號是否合法→調用第三方接口查看商品的打折價格→錢包金額扣除→生成訂單信息→通知用戶下單成功,等待收貨。

代碼實現:

  1. @Service 
  2. public class OrderServiceImpl implements OrderService { 
  3.     @Autowired 
  4.     private UserMapper userMapper; 
  5.     @Autowired 
  6.     private ProductMapper productMapper; 
  7.     @Autowired 
  8.     private OrderMapper orderMapper; 
  9.     @Autowired 
  10.     private KafkaTemplate kafkaTemplate; 
  11.  
  12.     /** 
  13.      *  購買商品,提交訂單 
  14.      * @param userId      用戶ID 
  15.      * @param productId   商品ID 
  16.      * @return 
  17.      */ 
  18.     public Result submit(Long userId, Long productId) throws BizException { 
  19.         // 驗證賬號 
  20.         UserDO userDO = userMapper.findById(userId); 
  21.         if (userDO == null) { 
  22.             throw BizException(USER_NOT_EXISTS); 
  23.         } 
  24.         // 查看商品信息及打折信息 
  25.         ProductDO productDO = productMapper.findById(productId); 
  26.         Double delta = HttpUtils.getDiscount(productId); 
  27.         double actualPayment = productDO.getPrice() - delta; 
  28.         Money money = userDO.getMoney(); 
  29.         if (actualPayment > money.getRemain()) { 
  30.             // 如果商品價格 - 優惠價格 > 用戶錢包,則說明不夠付 
  31.             return Result.fail("余額不足"); 
  32.         } 
  33.         // 錢包夠付,扣除金額 
  34.         double remain = money.getRemain() - actualPayment; 
  35.         money.setRemain(remain); 
  36.         // 更新賬號錢包余額 
  37.         userMapper.update(userDO); 
  38.         // 生成訂單信息 
  39.         OrderDO orderDO = new OrderDO(); 
  40.         orderDO.setUserId(userId); 
  41.         orderDO.setProductId(productId); 
  42.         orderMapper.save(orderDO); 
  43.         // 通知用戶訂單已生成,等待收貨 
  44.         kafkaTemplate.send("orderTopic", orderDO); 
  45.         return Result.ok(); 
  46.     } 

上面代碼寫好了,而且可以實現相關功能,但是隨著業務的迭代,可能會出現很多問題。

①可維護性差

XxMapper 是基于 Mybatis 實現數據操作層,也就把技術細節帶入業務邏輯中了,如果技術實現變了(改為使用 Hibernate,或 Mybatis 版本升級造成用法改變等),業務代碼就得改變。

XxDO 是和數據表綁定的,數據表結構變更等也會影響業務代碼。

調用第三方 API,直接在業務代碼中調用 HttpUtils 完成,未來第三方 API 修改了方法簽名或返回值,或改為了 RPC 接口,那么業務代碼也會隨著改變。

發送消息直接使用 KafkaTemplate,如果技術選型變了要改為使用 RocketMQ,那么業務代碼還得變。

②可擴展性差

如果商品因為做活動又加了其他的優惠,或商品某一段時間不打折了,那么原有的代碼就會重新改來改去。

業務邏輯和數據存儲結構是強依賴的,數據存儲結構的變化對業務的影響可想而知。

③可測試性差

因為直接依賴了數據庫,第三方接口,中間件,所以需要所有技術實現后才能進行測試,測試成本和時間都比較大。

代碼優化一

我們上面說了,數據庫操作不應該直接暴露在業務邏輯中,因此把數據庫操作“隔離”開。

  1. public interface UserRepository { 
  2.     User findById(Long userId); 

新增 XxRepository 接口,業務邏輯直接依賴接口/抽象,而不應該直接依賴實現。

Repository 是數據倉庫,不一定非得是 DB,也可以是其他的數據操作。

Repository 返回的對象也不是 DO,與數據庫結構無關。

代碼優化二

DO 對象是只有 set、get 操作,沒有其他行為,我們說這有時是一種貧血現象,會導致本該在業務領域實體中完成的事情散落到各個 Service 中,低內聚而且也不好維護。

增加領域實體,相關行為直接在實體內完成(高內聚):

  1. public class Money { 
  2.     private double remain; 
  3.     public double getRemain() { 
  4.         return remain; 
  5.     } 
  6.     public void setRemain(double remain) { 
  7.         this.remain = remain; 
  8.     } 
  9.     /** 
  10.      * 扣費 
  11.      * @param delta 
  12.      * @return 
  13.      */ 
  14.     public boolean charge(double delta) { 
  15.         if (remain < delta) { 
  16.             return false
  17.         } 
  18.         this.remain -= delta; 
  19.         return true
  20.     } 

代碼優化三

第三方接口是不可靠的,方法簽名或返回值或調用方式都有可能會變的,如果直接在業務中依賴,會對業務造成“腐蝕”,所以應該加一層適配層(也叫防腐層 ACL)。

  1. /** 
  2.  * 防腐層/適配層 
  3.  */ 
  4. @Service 
  5. public class PayServiceImpl implements PayService { 
  6.  
  7.     @Autowired 
  8.     private DiscountFacade discountFacade; 
  9.  
  10.     /** 
  11.      *  支付 
  12.      * @param money 
  13.      * @param product 
  14.      * @return 
  15.      */ 
  16.     public boolean pay(Money money, Product product) { 
  17.         // 獲取優惠 
  18.         Double delta = discountFacade.getDiscount(product.getId()); 
  19.         // 扣除費用 
  20.         return money.charge(product.getPrice() - delta); 
  21.     } 

代碼優化四

抽象中間件,不直接依賴具體的 MQ 實現:

  1. public interface MessageProducer<T, R> { 
  2.     Result<R> send(T message); 

總結

優化后的代碼如下:

  1. @Autowired 
  2. private UserRepository userRepository; 
  3. @Autowired 
  4. private ProductRepository productRepository; 
  5. @Autowired 
  6. private OrderRepository orderRepository; 
  7. @Autowired 
  8. private MessageProducer<Order,Result> messageProducer; 
  9. @Autowired 
  10. private PayService payService; 
  11.  
  12. /** 
  13.  * 購買商品,提交訂單 
  14.  * @param userId      用戶ID 
  15.  * @param productId   商品ID 
  16.  * @return 
  17.  */ 
  18. public Result submit(Long userId, Long productId) throws BizException { 
  19.     // 驗證 
  20.     User user = userRepository.findByUserId(userId); 
  21.     if (user == null) { 
  22.         throw BizException(USER_NOT_EXISTS); 
  23.     } 
  24.     // 支付 
  25.     Product product = productRepository.findById(productId); 
  26.     boolean f = payService.pay(user.getMoney(), product); 
  27.     if (!f) { 
  28.         return Result.fail("費用扣除失敗"); 
  29.     } 
  30.     // 更新賬戶 
  31.     userRepository.update(user); 
  32.     // 生成訂單信息 
  33.     Order order = OrderFactory.create(user, product); 
  34.     orderRepository.add(order); 
  35.     // 通知用戶訂單已生成,等待收貨 
  36.     messageProducer.send(order); 
  37.     return Result.ok(); 

代碼不一定非常嚴謹,只是通過這一個簡單的例子告訴大家實際工作中代碼該怎么寫,該遵循哪些目標。

①獨立于框架:架構不應該依賴某個外部的庫或框架,不應該被框架的結構所束縛。

②獨立于 UI:前臺展示的樣式可能會隨時發生變化(今天可能是網頁、明天可能變成 console、后天是獨立 app),但是底層架構不應該隨之而變化。

③獨立于底層數據源:無論今天你用 MySQL、Oracle 還是 MongoDB、CouchDB,甚至使用文件系統,軟件架構不應該因為不同的底層數據儲存方式而產生巨大改變。

④獨立于外部依賴:無論外部依賴如何變更、升級,業務的核心邏輯不應該隨之而大幅變化。

⑤可測試:無論外部依賴了什么數據庫、硬件、UI 或者服務,業務的邏輯應該都能夠快速被驗證正確性。

作者:構即人生

編輯:陶家龍

出處:toutiao.com/i6903053083555807752/

 

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2021-01-29 08:52:10

App微信移動應用

2020-11-08 14:34:31

小視頻瀏覽器

2020-11-09 14:15:23

代碼菜鳥老司機

2021-08-18 15:23:42

SDNSD-WAN軟件定義網絡

2019-12-27 14:00:43

傳統IT商業模式

2009-08-25 09:32:31

2021-11-12 08:07:40

競品分析數據分析 大數據

2009-11-20 12:54:42

2024-02-26 00:00:00

RAGGeminiLLM

2022-12-26 09:00:07

2023-10-25 16:36:06

數字化轉型IT系統

2019-01-22 08:58:41

代碼耦合業務

2025-02-24 10:10:20

ChatGPTC#代碼

2020-11-26 06:29:20

代碼非業務程序員

2019-08-14 08:52:40

業務代碼運營

2020-09-21 05:57:11

代碼編程語言開發

2016-04-20 11:08:57

代碼歷史新功能

2010-11-01 16:00:00

2021-10-18 17:54:13

論文博士數據

2012-07-03 09:59:03

程序員
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 激情91| 国产精品成人一区二区三区吃奶 | 午夜视频在线 | 日韩欧美三级 | 欧美日韩福利 | 日日操日日干 | 欧美日韩一区二区视频在线观看 | 国产精品一级在线观看 | 日本黄色片免费在线观看 | 亚洲成人免费电影 | 久久久一二三区 | 国产农村一级国产农村 | 久久精品欧美电影 | 日韩欧美国产一区二区三区 | 成人av大全 | 北条麻妃99精品青青久久 | 欧美日韩在线免费观看 | 99精品国产一区二区青青牛奶 | 亚洲成人免费av | 亚洲免费视频一区 | www.狠狠干 | 亚洲国产精品成人久久久 | 国产观看| 日日天天 | 欧美综合一区二区三区 | 精品一区二区电影 | 欧美日韩国产一区二区 | 精品一级 | 在线成人免费视频 | 欧美日韩视频在线 | 色综合av | 亚洲一区在线日韩在线深爱 | 91在线一区二区三区 | 天天操天天插 | 国产精品视频在线观看 | 久久精品97 | 亚洲国产精品va在线看黑人 | 永久看片 | 色婷婷亚洲国产女人的天堂 | 国产精品久久久久久亚洲调教 | 国产露脸国语对白在线 |