《代码整洁之道》阅读笔记(四)——迭进

《代码整洁之道》阅读笔记(四)——迭进本次分享主要是第十一章 迭进 通过跌进设计达到整洁的目的

大家好,欢迎来到IT知识分享网。

前言

1.运行所有测试

代码编写首先得保证它是能按照需求实现功能的,而检验这一标准的方法就是测试。测试编写得越多,越能帮助我们创建更好的设计。

2.重构

提升内聚性,降低耦合度,切分关注面,模块化系统性关注面,缩小函数和类的尺寸,选用更好的名称,如此等等。

3.不可重复

它代表着额外的工作、额外的风险和额外且不必要的复杂度。在遇到这种情况我们一般首先会想到共性抽取,抽出公用的方法。

4.表达力

5.尽可能减少类和方法

这条规则优先级最低,但也很重要

6.代码分析

源码:

 ** * 根据条件进行渠道路由,并记录在transfer的extraParams中 * @param transfer */ private void routeMethod(Transfer transfer) { 
    BaseTransferParam transferParam; BankAccountInfo bankAccountInfo; if (TransferTypeEnum.WITHDRAW == transfer.getTransferType() || TransferTypeEnum.DISTRIBUTE == transfer.getTransferType()) { 
    transferParam = JSON.parseObject(transfer.getExtraParams(), WithdrawTransferParam.class); WithdrawTransferParam withdrawParam = (WithdrawTransferParam) transferParam; bankAccountInfo = convert2BankAccountInfo(withdrawParam); // 转账参数有cardToken,并且参数中没有收款银行信息时,通过pci查询卡资产 if (StringUtils.isNotBlank(withdrawParam.getCardToken()) && StringUtils.isBlank(bankAccountInfo.getBankCode()) && StringUtils.isBlank(bankAccountInfo.getSwiftCode())) { 
    FundResult<BankAccountInfoDTO> result = pciExternalService.queryBankAccountInfo(withdrawParam.getCardToken(), transfer.getUserId()); AssertUtil.isTrue(result.isSuccess(), FinResultCode.ACCOUNT_NOT_EXIST, "queryBankAccountInfo failed,cardToken:%s,errorMsg:%s", withdrawParam.getCardToken(), result.getErrorMessage()); bankAccountInfo = convert2BankAccountInfo(result.getModule()); transferParam.setBankCode(bankAccountInfo.getBankCode()); transferParam.setSwiftCode(bankAccountInfo.getSwiftCode()); transfer.setExtraParams(JSON.toJSONString(transferParam)); } } else if (TransferTypeEnum.ALLOCATE == transfer.getTransferType()) { 
    transferParam = JSON.parseObject(transfer.getExtraParams(), AllocateTransferParam.class); bankAccountInfo = convert2BankAccountInfo(transferParam); } else { 
    throw FundException.build(FinResultCode.BUSINESS_NOT_SUPPORT, "unknown transferType={}", transfer.getTransferType()); } / * 1. 根据收款账号信息,寻找同行的serviceChannel */ if(StringUtils.isBlank(transfer.getServiceChannel())) { 
    String beneficiaryBankName = transferParam.getBankName(); List<String> serviceChannels = serviceChannelRoutingEngine.getServiceChannels( beneficiaryBankName, transferParam instanceof WithdrawTransferParam? ((WithdrawTransferParam) transferParam).getCardToken() : null ); if(serviceChannels.size() == 1) { 
    transfer.setServiceChannel(serviceChannels.get(0)); } } /2. 通过serviceChannel、转账条件,筛选可用的paymentMethod */ if(IPAY_SERVICE_CHANNEL.equals(transfer.getServiceChannel())) { 
    / citi.transfer.001固定使用ipay.Promptpay */ transfer.setPaymentMethod(PayMethodType.PromptPay); transfer.setExchangeType(ExchangeType.RT_BRIDGE); } else if (TransferTypeEnum.DISTRIBUTE == transfer.getTransferType() && StringUtils.isNotBlank(transfer.getUserId()) && FluxTransferDiamondCache.getTransferDftMidList().contains(transfer.getUserId())) { 
    / 开环针对提现代发商户userId进行判断,如果是白名单内的商户,都走DFT */ transfer.setPaymentMethod(PayMethodType.DFT); transfer.setExchangeType(ExchangeType.FLUX_BATCH); } else { 
    boolean isBkt = serviceChannelRoutingEngine.isBkt(bankAccountInfo.getSwiftCode()); int promptPayStatus = serviceChannelRoutingEngine.promptPayStatus(transfer.getUserId(), transfer.getServiceChannel(), bankAccountInfo.getBankCode(), transfer.getTransferAmount()); int fastStatus = serviceChannelRoutingEngine.fastStatus(bankAccountInfo.getSwiftCode()); String paymentMethodRoute = serviceChannelRoutingEngine.paymentMethodRoute(); Money moneyBoundDFT = serviceChannelRoutingEngine.getDFTMoneyConfig(); if (isBkt) { 
    //同行转账优先 transfer.setPaymentMethod(PayMethodType.BKT); transfer.setExchangeType(ExchangeType.FLUX_BATCH); } else if(promptPayStatus >= 0) { 
    transfer.setPaymentMethod(PayMethodType.PromptPay); transfer.setExchangeType(ExchangeType.RT_BRIDGE); //通过开关判断promptPay是否在维护,需要hold if(promptPayStatus == 0) { 
    transfer.setStatus(TransferStatus.HOLD); } } else if (StringUtils.isNotEmpty(paymentMethodRoute)) { 
    transfer.setPaymentMethod(paymentMethodRoute); transfer.setExchangeType(ExchangeType.FLUX_BATCH); } else if (transfer.getTransferAmount().isGreaterThan(moneyBoundDFT)) { 
    //超过DFT阈值的使用DFT transfer.setPaymentMethod(PayMethodType.DFT); transfer.setExchangeType(ExchangeType.FLUX_BATCH); } else if(fastStatus >= 0){ 
    transfer.setPaymentMethod(PayMethodType.FAST); transfer.setExchangeType(ExchangeType.FLUX_BATCH); } else{ 
    //其他使用ACH transfer.setPaymentMethod(PayMethodType.ACH); transfer.setExchangeType(ExchangeType.FLUX_BATCH); } } String exchangeCode = serviceChannelRoutingEngine.getExchangeCode(transfer.getServiceChannel(), transfer.getPaymentMethod()); transfer.setExchangeCode(exchangeCode); transferRepository.update(transfer); transfer.setVersion(transfer.getVersion() + 1); } 
 @Test public void testCreateTransferIfRouteMethod1() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 
    MockitoAnnotations.initMocks(this); Transfer transfer = getTransfer(); transfer.setStatus(TransferStatus.ACCEPTED); transfer.setTransferId("test"); FundResult<BankAccountInfoDTO> mockResult = mock(FundResult.class); Mockito.doReturn(mockResult).when(pciExternalService).queryBankAccountInfo(any(String.class), any(String.class)); Mockito.when(transferDomainService.create(transfer)).thenReturn(any()); Mockito.when(serviceChannelRoutingEngine.isBkt("test")).thenReturn(true); Mockito.when(serviceChannelRoutingEngine.promptPayStatus("1", "2", "3", Money.ofMinorUnit("THB", 1))).thenReturn(1); Mockito.when(serviceChannelRoutingEngine.fastStatus("1")).thenReturn(1); Mockito.when(serviceChannelRoutingEngine.getDFTMoneyConfig()).thenReturn(Money.ofMinorUnit("THB", 1)); Mockito.when(serviceChannelRoutingEngine.getExchangeCode("1", "2")).thenReturn("any"); //convert2BankAccountInfo() CreateTransferRequest transferRequest = getCreateTransferRequest(); transferRequest.setTransferTypeEnum(TransferTypeEnum.DISTRIBUTE); String result = transferService.createTransfer(transferRequest); Assert.assertEquals(result, null); } @Test public void testCreateTransferIfRouteMethod2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 
    MockitoAnnotations.initMocks(this); Transfer transfer = getTransfer(); transfer.setStatus(TransferStatus.ACCEPTED); FundResult<BankAccountInfoDTO> mockResult = mock(FundResult.class); Mockito.doReturn(mockResult).when(pciExternalService).queryBankAccountInfo(any(String.class), any(String.class)); Mockito.when(transferDomainService.create(transfer)).thenReturn(any()); Mockito.when(serviceChannelRoutingEngine.isBkt("test")).thenReturn(true); Mockito.when(serviceChannelRoutingEngine.promptPayStatus("1", "2", "3", Money.ofMinorUnit("THB", 1))).thenReturn(1); Mockito.when(serviceChannelRoutingEngine.fastStatus("1")).thenReturn(1); Mockito.when(serviceChannelRoutingEngine.getDFTMoneyConfig()).thenReturn(Money.ofMinorUnit("THB", 1)); Mockito.when(serviceChannelRoutingEngine.getExchangeCode("1", "2")).thenReturn("any"); List<String> serviceChannels = new ArrayList<>(); serviceChannels.add("citi.transfer.001"); Mockito.when(serviceChannelRoutingEngine.getServiceChannels("BankName_test",null )).thenReturn(serviceChannels); CreateTransferRequest transferRequest = getCreateTransferRequest(); transferRequest.setServiceChannel(""); transferRequest.setTransferTypeEnum(TransferTypeEnum.ALLOCATE); String result = transferService.createTransfer(transferRequest); Assert.assertEquals(result, null); } @Test public void testCreateTransferIfRouteMethod3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 
    MockitoAnnotations.initMocks(this); Transfer transfer = getTransfer(); transfer.setStatus(TransferStatus.ACCEPTED); FundResult<BankAccountInfoDTO> mockResult = mock(FundResult.class); Mockito.doReturn(mockResult).when(pciExternalService).queryBankAccountInfo(any(String.class), any(String.class)); Mockito.when(transferDomainService.create(transfer)).thenReturn(any()); Mockito.when(serviceChannelRoutingEngine.isBkt("test")).thenReturn(true); Mockito.when(serviceChannelRoutingEngine.promptPayStatus("1", "2", "3", Money.ofMinorUnit("THB", 1))).thenReturn(1); Mockito.when(serviceChannelRoutingEngine.fastStatus("1")).thenReturn(1); Mockito.when(serviceChannelRoutingEngine.getDFTMoneyConfig()).thenReturn(Money.ofMinorUnit("THB", 1)); Mockito.when(serviceChannelRoutingEngine.getExchangeCode("1", "2")).thenReturn("any"); List<String> serviceChannels = new ArrayList<>(); serviceChannels.add("citi.transfer.001"); Mockito.when(serviceChannelRoutingEngine.getServiceChannels("BankName_test",null )).thenReturn(serviceChannels); CreateTransferRequest transferRequest = getCreateTransferRequest(); transferRequest.setServiceChannel(""); transferRequest.setTransferTypeEnum(mock(TransferTypeEnum.class)); try{ 
    transferService.createTransfer(transferRequest); }catch (FundException e){ 
    Assert.assertEquals("BUSINESS_NOT_SUPPORT", String.valueOf(e.getErrorCode())); } } @Test public void testCreateTransferIfRouteMethod4() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 
    MockitoAnnotations.initMocks(this); Transfer transfer = getTransfer(); transfer.setStatus(TransferStatus.CLEARED); FundResult<BankAccountInfoDTO> mockResult = mock(FundResult.class); Mockito.doReturn(mockResult).when(pciExternalService).queryBankAccountInfo(any(String.class), any(String.class)); Mockito.when(transferDomainService.create(transfer)).thenReturn(any()); Mockito.when(serviceChannelRoutingEngine.isBkt("test")).thenReturn(false); Mockito.when(serviceChannelRoutingEngine.promptPayStatus(null, "PAYMENT_WALLET_TMN_001", "BankCaode_test", Money.ofMinorUnit("THB", 1))).thenReturn(0); Mockito.when(serviceChannelRoutingEngine.fastStatus("1")).thenReturn(1); Mockito.when(serviceChannelRoutingEngine.getDFTMoneyConfig()).thenReturn(Money.ofMinorUnit("THB", 1)); Mockito.when(serviceChannelRoutingEngine.getExchangeCode("1", "2")).thenReturn("any"); //convert2BankAccountInfo() CreateTransferRequest transferRequest = getCreateTransferRequest(); String result = transferService.createTransfer(transferRequest); Assert.assertEquals(result, null); } @Test public void testCreateTransferIfRouteMethod5() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 
    MockitoAnnotations.initMocks(this); Transfer transfer = getTransfer(); transfer.setStatus(TransferStatus.CLEARED); FundResult<BankAccountInfoDTO> mockResult = mock(FundResult.class); Mockito.doReturn(mockResult).when(pciExternalService).queryBankAccountInfo(any(String.class), any(String.class)); Mockito.when(transferDomainService.create(transfer)).thenReturn(any()); Mockito.when(serviceChannelRoutingEngine.isBkt("test")).thenReturn(false); Mockito.when(serviceChannelRoutingEngine.promptPayStatus(any(), anyString(), anyString(), any())).thenReturn(-1); Mockito.when(serviceChannelRoutingEngine.fastStatus("1")).thenReturn(1); Mockito.when(serviceChannelRoutingEngine.getDFTMoneyConfig()).thenReturn(Money.ofMinorUnit("THB", 0)); Mockito.when(serviceChannelRoutingEngine.getExchangeCode("1", "2")).thenReturn("any"); //convert2BankAccountInfo() CreateTransferRequest transferRequest = getCreateTransferRequest(); String result = transferService.createTransfer(transferRequest); Assert.assertEquals(result, null); } @Test public void testCreateTransferIfRouteMethod6() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 
    MockitoAnnotations.initMocks(this); Transfer transfer = getTransfer(); transfer.setStatus(TransferStatus.CLEARED); FundResult<BankAccountInfoDTO> mockResult = mock(FundResult.class); Mockito.doReturn(mockResult).when(pciExternalService).queryBankAccountInfo(any(String.class), any(String.class)); Mockito.when(transferDomainService.create(transfer)).thenReturn(any()); Mockito.when(serviceChannelRoutingEngine.isBkt("test")).thenReturn(false); Mockito.when(serviceChannelRoutingEngine.promptPayStatus(any(), anyString(), anyString(), any())).thenReturn(-1); Mockito.when(serviceChannelRoutingEngine.fastStatus(anyString())).thenReturn(1); Mockito.when(serviceChannelRoutingEngine.getDFTMoneyConfig()).thenReturn(Money.ofMinorUnit("THB", 2)); Mockito.when(serviceChannelRoutingEngine.getExchangeCode("1", "2")).thenReturn("any"); //convert2BankAccountInfo() CreateTransferRequest transferRequest = getCreateTransferRequest(); String result = transferService.createTransfer(transferRequest); Assert.assertEquals(result, null); } @Test public void testCreateTransferIfRouteMethod7() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { 
    MockitoAnnotations.initMocks(this); Transfer transfer = getTransfer(); transfer.setStatus(TransferStatus.CLEARED); FundResult<BankAccountInfoDTO> mockResult = mock(FundResult.class); Mockito.doReturn(mockResult).when(pciExternalService).queryBankAccountInfo(any(String.class), any(String.class)); Mockito.when(transferDomainService.create(transfer)).thenReturn(any()); Mockito.when(serviceChannelRoutingEngine.isBkt("test")).thenReturn(false); Mockito.when(serviceChannelRoutingEngine.promptPayStatus(any(), anyString(), anyString(), any())).thenReturn(-1); Mockito.when(serviceChannelRoutingEngine.fastStatus(anyString())).thenReturn(-1); Mockito.when(serviceChannelRoutingEngine.getDFTMoneyConfig()).thenReturn(Money.ofMinorUnit("THB", 2)); Mockito.when(serviceChannelRoutingEngine.getExchangeCode("1", "2")).thenReturn("any"); //convert2BankAccountInfo() CreateTransferRequest transferRequest = getCreateTransferRequest(); String result = transferService.createTransfer(transferRequest); Assert.assertEquals(result, null); } 

如果routeMethod这个方法在逻辑不变且正常工作的前提下进行细化拆分,那么它的测试方法也可以简单很多,而全面测试并持续通过所有测试的系统,才是可测试的系统。在迭进设计的四条规则中,运行所有测试的优先级排在最前,说明程序保持可持续测试的重要性。

总结

书中介绍的规则均来自作者多年的实践经验,涵盖从命名到重构的多个编程方面,虽为一家之言,然诚有可资借鉴的价值。从《代码整洁之道》中可以学到:好代码和糟糕的代码之间的区别:如何编写好代码,如何将糟糕的代码转化为好代码:如何创建好名称、好函数、好对象和好类;如何格式化代码以实现其可读性的最大化:如何在不妨碍代码逻辑的前提下充分实现错误处理;如何进行单元测试和测试驱动开发。从书中收获良多,也意识到需要在今后的开发工作中不断实践不断学习。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/137541.html

(0)
上一篇 2025-06-19 19:15
下一篇 2025-06-19 19:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信