项目组入职一个阿里的大 牛,看他写代码真的太优雅了

引言

很多同学在工作一段时间之后可能都有这样的困境,大家觉得自己总是在写业务代码,技术上感觉好像没有多大的长进,不知不觉就成为了CURD Boy或者Girl,自己想要去改变但是又不知道该从何处进行入手。

有的同学会去学习如何做架构、有的同学可能会去学习各种新技术还有的同学甚至转产品经理来试图解除困境。但是我觉得找到跨出这种困境的途径反而还是要从我们每天写的代码入手。

**即便当前每天做着CRUD的事情,但是我们自己不能把自己定义为只会CURD的工具人。**那么我们到底如何从代码层面入手改变困境呢?我们可以回过头看看自己以前写的代码,或者是当前正在实现的各种各样的需求,反问自己以下5个问题。

  • 1、有没有使用设计模式优化代码结构?
  • 2、有没有利用一些高级特性来简化代码实现?
  • 3、有没有借助框架的能力来扩展应用能力?
  • 4、自己设计的业务模型够不够抽象?
  • 5、代码扩展性强不强,需求如果有变化模块代码能不能做到最小化修改?

通过这样的反问和思考,我们可以不断自我审视自己写的代码。通过在代码上的深耕细作,我们所负责的模块的质量就会比别人更高,出现Bug的概率就会更低,稳定性就会更高,那么未来负责更多业务模块的机会也就会更多,只有这样我们才能真正跨出困境,实现突破。

因此本文主要从优化日常工作中经常遇到的重复代码入手,和大家探讨下如何通过一些技巧来消除平台中的重复代码,以消除系统中的重复代码为切入点,提升系统稳定性。

为什么要消除重复代码

在程序猿的日常工作中,不仅要跟随业务侧的发展不断开发新的需求,同时也需要维护老的已有平台。无论是开发新需求还是维护老系统,我们都会遇到同样一个问题,系统中总是充斥着很多重复的代码。

可能是由于工期很赶没时间优化,也有可能是历史原因欠下的技术债。无论是什么原因,系统中大量的重复代码非常影响平台整体的可维护性。大神们的谆谆教导Don’t Repeat Yourself 言犹在耳。那么平台中的重复代码会带来怎样的稳定性风险呢?

系统维护成本高

如果项目中出现大量的重复代码,说明系统中这部分业务逻辑并没有进行很好的抽象,因此会导致后期的代码维护面临很多问题。无论是修改原有逻辑还是新增业务逻辑可能需要在不同的文件中进行修改,项目维护成本相当高。另外后期维护的同学看到同样的逻辑写了多遍,不明白这到底是代码的坏味道还是有什么特殊的业务考虑,这也在无形中增加了后期维护者的代码逻辑理解难度。

程序Bug概率高

大家都知道重复代码意味着业务逻辑相同或者相似,假如这些相同或者相似的代码出现了Bug,在修复的过程中就需要修改很多地方,导致一次上线变更的内容比较多,存在一定的风险,毕竟线上问题70%-80%都是由于新的变更引起的。另外如果重复的地方比较多,很有可能出现漏改的情况。因此重复的代码实际就是隐藏在工程中的老炸弹,可能一直相安无事,也可能不知道什么时候就会Bom一声给你惊喜,因此我们必须要进行重复代码消除。

如何优雅的消除重复代码

在消除重复代码之前,我们首先需要确定到底什么是重复代码,或者说重复代码的特征到底是什么。有的同学可能会说,这还不简单嘛,重复代码不就是那些一模一样的但是散落在工程不同地方的代码嘛。

当然这句话也没错,但是不够全面,重复代码不仅仅指那些不同文件中的完全相同的代码,还有一些代码业务流程相似但是并不是完全相同,这类代码我们也把它称之为重复代码。重复代码的几个特性:

1、代码结构完全相同

比如工程中好几个地方都有读取配置文件的逻辑,代码都是相同的,那么我们可以把不同地方读取配置文件的逻辑放到一个工具类中,这样今后再有读取配置文件的需要的时候可以直接调用工具类中方法即可,不需要再重复写相同的代码,这也是我们日常工作中最常见的使用方式。

2、代码逻辑结构相似

在项目中经常遇到虽然代码并不是完全相同,但是逻辑结构却非常相似。比如电商平台在进行营销活动的时候,常常通过邀请的方式来进行用户红包领取的活动,但是对于新老用户的红包赠予规则是不同的,同时也会根据邀请用户的数量的不同给予不同的红包优惠。

但是无论新老用户都会经历根据用户类型获取红包计算规则,根据规则计算减免的红包,最后付款的时候减去红包数额这样一个业务逻辑。虽然表面看上去代码并不相同,但是实际上逻辑基本是一样的,因此也属于重复代码。

下面就和大家分享几种比较实用的消除重复的代码的技巧,考虑到安全性,代码都进行了脱敏以及简化处理。

统一参数校验

当我们进行项目开发的时候,会编写一些类的实现方法,不可避免的会进行一些参数校验或者业务规则校验,因此会在实现方法中写一些判断参数是否有效或者返回结果是否有效的的的代码。

public OrderDTO queryOrderById(String id) {if(StringUtils.isEmpty(id)) {return null;}OrderDTO order = orderBizService.queryOrder(id);if(Objects.isNull(Order)) {return null;}...
}public List<UserDTO> queryUsersByType(List<String> type) {if(StringUtils.isEmpty(id)) {return null;}...
}

这种参数校验的方式,很多人会喜欢使用@Valid这种注解来进行参数有效性的判断,但是我觉得还是不够方便,它只能进行一些参数的校验,并不能进行业务结果的有效性判断。那么对于这种校验类的代码如何才能消除重复if…else…判断代码呢?

因此我一般会统一定义一个Assert断言来进行参数或者业务结果的校验,当然也可以使用Spring框架提供的Assert抽象类来进行判断,但是它抛出的异常是IllegalArgumentException,我习惯抛出自己定义的全局统一的异常信息,这样可以通过全局的异常处理类来进行统一处理。因此我们首先定义一个业务断言类,主要针对biz层出现的参数以及业务结果进行断言,这样可以避免重复写if…else…判断代码。

public class Assert {public static void notEmpty(String param) {if(StringUtils.isEmpty(param)) {throw new BizException(ErrorCodes.PARAMETER_IS_NULL, "param is empty or null");}}public static void notNull(Object o) {if (Objects.isNull(o)) {throw new BizException(ErrorCodes.PARAMETER_IS_NULL, "object is null");}}public static void notEmpty(Collection collection) {if(CollectionUtils.isEmpty(collection)) {throw new BizException(ErrorCodes.PARAMETER_IS_NULL, "collection is empty or null");}}}

我们看下优化后的代码是不是看上去清爽许多。

public OrderDTO queryOrderById(String id) {Assert.notEmpty(id);OrderDTO order = orderBizService.queryOrder(id);Assert.notNull(order);...
}public List<UserDTO> queryUsersByType(List<String> type) {Assert.notEmpty(type);...
}

统一异常处理

以下这类Controller代码在项目中是不是很常见?大家可以翻翻自己的项目工程代码,可能很多工程中Cotroller层都充斥着这样的try{}catch{}逻辑处理,相当于每个接口实现都要进行异常处理,看起来非常冗余写起来也麻烦。实际上我们可以通过定义统一的全局异常处理器来进行优化,避免重复的进行异常捕获。

@GetMapping("list")
public ResponseResult<OrderVO> getOrderList(@RequestParam("id")String userId) {try {OrderVO orderVo = orderBizService.queryOrder(userId);    return ResponseResultBuilder.buildSuccessResponese(orderDTO);} catch (BizException be) {// 捕捉业务异常return ResponseResultBuilder.buildErrorResponse(be.getCode, be.getMessage());} catch (Exception e) {// 捕捉兜底异常return ResponseResultBuilder.buildErrorResponse(e.getMessage());}
}

那么我们应该怎么优化这些重复的异常捕捉处理代码呢?首先我们需要定义一个统一的异常处理器,通过它来对Controller接口的异常进行统一的异常处理,包括异常捕获以及异常信息提示等等。这样就不用在每个实现接口中编写try{}catch{}异常处理逻辑了。示意代码只是简单的说明实现方法,在项目中进行落地的时候,大家可以定义处理更多的异常类型。

@ControllerAdvice
@ResponseBody
public class UnifiedException {@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)@ExceptionHandler(BizException.class)@ResponseBodypublic ResponseResult handlerBizException(BizException bizexception) {return ResponseResultBuilder.buildErrorResponseResult(bizexception.getCode(), bizexception.getMessage());}@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)@ExceptionHandler(Exception.class)@ResponseBodypublic ResponseResult handlerException(Exception ex) {return ResponseResultBuilder.buildErrorResponseResult(ex.getMessage());}   
}

优化后的Controller如下所示,大量的try…catch…不见了,代码结构变得更加清晰直接。

@GetMapping("list")
public ResponseResult<OrderVO> getOrderList(@RequestParam("id")String userId) {List<OrderVO> orderVo = orderBizService.queryOrder(userId);    return ResponseResultBuilder.buildSuccessResponese(orderVo);
}

优雅的属性拷贝

在实际的项目开发中我们所开发的微服务都是分层的有的是MVC三层,有的按照DDD领域分层是四层。无论是三层还是四层都会涉及不同层级的之间的调用,而每个层级都有自己的数据对象模型,比如biz层是dto,domain层是model,repo层是po。因此必然会涉及到数据模型对象之间的相关转换。

在一些场景下模型之间的字段很多都是一样的,有的甚至是完全一模一样。比如将DTO转化为业务模型Model,实际上他们之间很多的字段都是一样的,所以经常会出现以下的这种代码,会出现大量的属性赋值 的操作来达到模型转换的需求。实际上我们可以通过一些工具包或者工具类进行属性的拷贝,避免出现大量的重复赋值代码。

public class TaskConverter {public static TaskDTO taskModel2DTO(TaskModel taskModel) {TaskDTO taskDTO = new TaskDTO();taskDTO.setId(taskModel.getId());taskDTO.setName(taskModel.getName());taskDTO.setType(taskModel.getType());taskDTO.setContent(taskModel.getContent());taskDTO.setStartTime(taskModel.getStartTime());taskDTO.setEndTime(taskModel.getEndTime());return taskDTO;}
}

使用BeanUtils的进行属性赋值,很明显不再有那又长又没有感情的一条又一条的属性赋值语句了,整个任务数据模型对象的转换代码看上去立马舒服很多。

public class TaskConverter {public static TaskDTO taskModel2DTO(TaskModel taskModel) {TaskDTO taskDTO = new TaskDTO();BeanUtils.copyProperties(taskModel, taskDTO);return taskDTO;}}

当然很多人会说,BeanUtils会存在深拷贝的问题。但是在一些浅拷贝的场景下使用起来还是比较方便的。另外还有Mapstruct工具,大家也可以试用一下。

核心能力抽象

假设有这样的业务场景,系统中需要根据不同的用户类型计算商品结算金额,大致的计算逻辑有三个步骤,分别是计算用户商品总价格,计算不同用户对应的优惠金额,最后计算出用户的结算金额。我们先来看下原有系统中的实现方式。

普通用户结算逻辑:

public Class NormalUserSettlement {//省略代码...public Bigdecimal calculate(String userId) {//计算商品总价格List<Goods> goods = shoppingService.queryGoodsById(userId);Bigdecimal total = goods.stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add);//计算优惠Bigdecimal discount = total.multiply(new Bigdecimal(0.1));          //计算应付金额Bigdecimal payPrice = total - dicount;return payPrice;}//省略代码...
}

VIP用户结算逻辑:

public Class VIPUserSettlement {//省略代码...public Bigdecimal calculate(String userId) {//计算商品总价格List<Goods> goods = shoppingService.queryGoodsById(userId);Bigdecimal total = goods.stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add);//计算优惠Bigdecimal discount = total.multiply(new Bigdecimal(0.2));          //计算应付金额Bigdecimal payPrice = total - dicount;   return payPrice;}//省略代码...
}

黑卡用户结算逻辑:

public Class VIPUserSettlement {//省略代码...public Bigdecimal calculate(String userId) {//计算商品总价格List<Goods> goods = shoppingService.queryGoodsById(userId);Bigdecimal total = goods.stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add);//计算优惠Bigdecimal discount = total.multiply(new Bigdecimal(0.2));          //计算应付金额Bigdecimal payPrice = total - dicount;       return payPrice;   }    //省略代码...
}

在这样的场景下,我们可以发现,在三个类中计算商品总额以及计算最后的应付金额逻辑都是一样的,唯一不同的是每个用户类型对应的优惠金额是不同的。

因此我们可以把逻辑相同的部分抽象到AbstractSettleMent中,然后定义计算优惠金额的抽象方法由各个不同的用类型子类去实现。这样各个子类只要关心自己的优惠实现就可以了,重复的代码都被抽象复用大大减少重复代码的使用。

public Class AbstractSettlement {//省略代码...public abstact   Bigdecimal calculateDiscount();public Bigdecimal calculate(String userId) {//计算商品总价格List<Goods> goods = shoppingService.queryGoodsById(userId);Bigdecimal total = goods.stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add);//计算优惠Bigdecimal discount = calculateDiscount();          //计算应付金额Bigdecimal payPrice = total - dicount;     return payPrice; }//省略代码...
}

图片

自定义注解和AOP

用过Spring框架的同学都知道,AOP是Spring框架核心特性之一,它不仅是一种编程思想更是实际项目中可以落地的技术实现技巧。通过自定义注解和AOP的组合使用,可以实现一些通用能力的抽象。比如很多接口都需要进行鉴权、日志记录或者执行时间统计等操作,但是如果在每个接口中都编写鉴权或者日志记录的代码那就很容易产生很多重复代码,在项目后期不好维护。针对这种场景 我们可以使用AOP同时结合自定义注解实现接口的切面编程,在需要进行通用逻辑处理的接口或者类中增加对应的注解即可。

假设有这样的业务场景,需要计算指定某些接口的耗时情况,一般的做法是在每个接口中都加上计算接口耗时的逻辑,这样各个接口中就会有这样重复计算耗时的逻辑,重复代码就这样产生了。那么通过自定义注解和AOP的方式可以轻松地解决代码重复的问题。首先定义一个注解,用于需要统计接口耗时的接口方法上。

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeCost {}

定义切面实现类:

@Aspect 
@Component
public class CostTimeAspect {@Pointcut(value = "@annotation(com.mufeng.eshop.anotation.CostTime)") public void costTime(){ }@Around("runTime()") public Object costTimeAround(ProceedingJoinPoint joinPoint) {Object obj = null;try {long beginTime = System.currentTimeMillis();obj = joinPoint.proceed();//获取方法名称String method = joinPoint.getSignature().getName();//获取类名称String class = joinPoint.getSignature().getDeclaringTypeName();//计算耗时long cost = System.currentTimeMillis() - beginTime;log.info("类:[{}],方法:[{}] 接口耗时:[{}]", class, method, cost + "毫秒");} catch (Throwable throwable) {throwable.printStackTrace();}return obj;}
}

优化前的代码:

@GetMapping("/list")
public ResponseResult<List<OrderVO>> getOrderList(@RequestParam("id")String userId) {long beginTime = System.currentTimeMillis();List<OrderVO> orderVo = orderBizService.queryOrder(userId);  log.info("getOrderList耗时:" + System.currentTimeMillis() - beginTime + "毫秒");return ResponseResultBuilder.buildSuccessResponese(orderVo);
}@GetMapping("/item")
public ResponseResult<OrderVO> getOrderById(@RequestParam("id")String orderId) {long beginTime = System.currentTimeMillis();OrderVO orderVo = orderBizService.queryOrderById(orderId);log.info("getOrderById耗时:" + System.currentTimeMillis() - beginTime + "毫秒");return ResponseResultBuilder.buildSuccessResponese(orderVo);
}

优化后的代码:

@GetMapping("/list")
@TimeCost
public ResponseResult<List<OrderVO>> getOrderList(@RequestParam("id")String userId) {List<OrderVO> orderVo = orderBizService.queryOrder(userId);    return ResponseResultBuilder.buildSuccessResponese(orderVo);
}@GetMapping("/item")
@TimeCost
public ResponseResult<OrderVO> getOrderList(@RequestParam("id")String orderId) {OrderVO orderVo = orderBizService.queryOrderById(orderId);    return ResponseResultBuilder.buildSuccessResponese(orderVo);
}

引入规则引擎

大家在做业务开发的时候,可能会遇到这样的场景,业务中充斥着各种各样的规则判断,同时这些业务规则还可能经常发生变化。即便是我们用了策略模式等设计模式来优化代码结构,但是还是不能避免代码中出现大量的if…else…判断代码,一旦增加或者修改规则都需要在原来的业务规则代码中进行修改,维护起来非常不方便。

图片

假设设有这样的业务,销售人员的奖励根据实际的利润进行计算,不同的利润计算奖励的规则并不相同。使用规则引擎之前,可能会有这样的代码结构,需要根据实际利润所处的区间来计算最终的奖励金额,不同区间范围对应的返点规则是不一样的,因此会有很多的if…else…判断。另外规则有可能随着业务的发展还会经常变化,因此后期可能面临不断修改这部分的计算奖励的代码的情况。

public double calculate(int profit) {if(profit < 1000) {return profit * 0.1;} else if(1000 < profit && profit< 2000) {return profit * 0.15;} else if(2000 < profit && profit < 3000) {return profit * 0.2;} return  profit * 0.3;}

如果遇到这种业务场景,我们就可以考虑使用规则引擎。通过引入规则引擎,我们可以实现业务代码与业务规则相分离,将各种业务判断规则从原有的平台代码中抽离出来,以后规则的修改都在规则文件中直接修改就可以了,避免代码本身的变更,从而大大提升代码的扩展性。这里简单介绍下常用的规则引擎Drools是如何实现规则扩展管理的。

使用Drools之后:

使用规则引擎优化之后,所有的规则也就是所有的if…else…都会放在规则文件reward.drl中,因此代码中不会再有各种重复的if…else…代码,真正实现了业务规则与业务数据相分离。

// 奖励规则
package reward.rule
import com.mufeng.eshop.biz.Reward// rule1:如果利润小于1000,则奖励计算规则为profit*0.1
rule "reward_rule_1"when$reward: Reward(profit < 1000) then$reward.setReward($reward.getProfit() * 0.1);System.out.println("匹配规则1,奖励为利润的1成");
end// rule2:如果利润大于1000小于2000,则奖励计算规则为profit*0.15
rule "reward_rule_2"when$reward: Reward(profit >= 1000 && profit < 2000)then$reward.setReward($reward.getProfit() * 0.15);System.out.println("匹配规则2,奖励为利润的1.5成");
end// rule3:如果利润大于2000小于3000,则奖励计算规则为profit*0.2
rule "reward_rule_3"when$order: Order(profit >= 2000 && profit < 3000)then$reward.setReward($reward.getProfit() * 0.2);System.out.println("匹配规则3,奖励为利润的2成");
end//  rule4:如果利润大于等于3000,则奖励计算规则为profit*0.3
rule "reward_rule_4"when$order: Order(profit >= 3000)then$reward.setReward($reward.getProfit() * 0.3);System.out.println("匹配规则4,奖励为利润的3成");
end

在代码中只要将待判断的数据插入到规则引擎的工作内存中,然后执行规则就可以获取到最终的结果,是不是很方便的实现业务规则的解耦,在实际的Java代码中也不用看到各种if…else…判断。

定义规则引擎实现:

public class DroolsEngine {private KieHelper kieHelper;public DroolsEngine() {this.kieHelper = new KieHelper();}public void  executeRule(String rule, Object unit, boolean clear) {kieHelper.addContent(rule, ResourceType.DRL);KieSession kieSession = kieHelper.getKieContainer().newKieSession();//插入判断实体kieSession.insert(unit);//执行规则kieSession.fireAllRules();if (clear) {kieSession.dispose();}}
}
public class Profit {public double  calculateReward(Reward reward) {String rule = "classpath:rules/reward.drl";File rewardFile = new File(rule);String rewardDrl = FileUtils.readFile(rewardFile, "utf-8");DroolsEngine engine = new DroolsEngine();engine.executeRule(rewardDrl, reward, true);return  reward.getReward();    }
}

通过引入Drools规则引擎,代码中不再有各种规则判断的重复的if…else…判断语句,而且如果后期要修改奖励规则,代码不用修改,直接更改规则即可,系统的扩展性以及可维护性进一步提升。

消除重复代码方法论

上文中给大家介绍了几种消除重复代码的实战小技巧,不知道大家有没有发现虽然具体落地实操的手段各不相同,无论是提取公用逻辑作为工具类、使用AOP进行面向切面编程还是进行通用逻辑抽象,又或者是借助规则引擎分离实现与规则。

实际它们的核心思想本质上都是一致的,都是通过抽离或者抽象相似代码逻辑后进行统一处理。将这种核心思想放在微服务内部就是在系统中的消除重复业务逻辑,如果放在架构层面来看其实和中台思想的本质也是相通的,将用户、支付这种各个平台都会用到的服务抽象为中台,实际就是一种混乱到有序的软件复杂度治理过程以及一种万物归一的思想。

图片

那么在日常的实际项目中我们应该怎么落地实践消除重复代码呢?这里总结了通过上述文章对于重复代码的处理,我们来试图来提炼消除重复代码的方法论。

图片

**Find:**技术同学需要有一双可以发现重复代码的眼睛,能够将表面上的重复我代码以及隐藏的重复代码识别出来。重复代码不仅仅是表示长得一模一样的代码,那些核心业务逻辑一样实际也是一种重复代码。

Analysis:当我们找到了重复代码之后,就要考虑该如何进行优化了,如果只是工具类型的重复代码,那么直接提取作为一个工具类就可以了,也不用考虑太多。但是如果是涉及业务流程可能需要进一步的进行抽象

**Action:**根据不同的重复代码的类型,我们需要制定不通过的优化重复代码的方案。根据不同的方案实现通过引入规则引擎还是模板方法进行抽象。

总结

不知不觉又到凌晨12点了,每次在这种夜深人静的时候写文章,也是自己最享受的时光。白天工作很忙,晚上又是各种加班,每天能留给自己的时间真的是少之又少。在睡觉前的这一个小时左右的时间,能够将自己的总结和思考沉淀下来其实一件非常值得开心的事情,如果可以给看到文章的同学一点点启发,那更是善莫大焉。

今天和大家主要分享了几种项目中消除重复代码的实践方案,同时沉淀了如何优雅消除代码重复的方法论,希望通过这样的沉淀以及总结可以在大家遇到同样的问题的时候可以有所帮助,通过实际的优化代码落地来提升平台的可维护性。大家有没有在项目中实战过的其他消灭重复代码的实践案例呢?欢迎一起分享讨论交流哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/56210.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数学建模——论文(latex写作)

LaTeX 前言一、texlive 安装与Texstudio编辑器二、开始编辑基础编写文档1.设置文档类型:*宏包导入处&#xff1a; 2.开始正文 命令标题注释段落设置&#xff08;顶格与不顶格&#xff09; 图片表格公式行内公式行间公式行间公式之无编号行间公式之有编号 多行公式不带编号带编号…

他是阿里P11,靠写代码写成合伙人,身家几十亿,没有他,我们可能刷不了淘宝!...

点击“技术领导力”关注∆ 每天早上8:30推送 作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 他是阿里的“扫地僧”&#xff0c;写代码级别最高的人&#xff0c;一等一的技术高手&#xff0c;他非科班出身&#xff0c;用近20年的时间&#xff0c;修…

阿里巴巴数学大赛赛题公布,你敢来挑战吗?(含参考答案)

9月中旬&#xff0c;阿里巴巴在全球范围内发起一场数学比赛&#xff0c;旨在让全社会看到基础科学尤其是数学的价值&#xff0c;理解数学之美。目前&#xff0c;组织方正在紧张地阅卷中&#xff0c;AI会辅助阅卷。 这次数学大赛引发社会强烈关注。活动公开不到一周&#xff0c;…

大淘宝技术提出TTNet算法荣获“最佳工业论文奖”奖项

大淘宝技术商家赋能算法团队联合浙江大学提出的TTNet算法荣获“最佳工业论文奖”奖项。 由IEEE计算机学会、国际网络智能协会、美国计算机学会主办&#xff0c;牛津大学、昆士兰大学、迪肯大学、中国医学科学院、东南大学、南京财经大学、PIESAT、大淘宝技术部、IOS Press协办的…

今天,阿里巴巴报告厅里只谈快乐的数学

3月29日下午&#xff0c;伴随着巴赫的经典G大调小步舞曲&#xff0c;第一届阿里巴巴全球数学竞赛颁奖典礼在杭州举办。在阿里巴巴报告厅里&#xff0c;马老师为数十位年轻选手一一颁奖。这些来自全球各地的数学顶尖高手相聚一堂&#xff0c;谈论着快乐数学和数学之美。 马老师为…

【技术大牛招募】-- 阿里巴巴 南京研发中心

大家好&#xff0c;相信大家这段实际的的朋友圈都被阿里江苏总部的文章刷屏了&#xff0c;作为先遣部队&#xff0c;阿里巴巴集团客户体验事业群-智能创新中心-南京研发中心&#xff08;目前办公地点坐标江宁九龙湖&#xff09;&#xff0c;上图是同事拍的办公楼。现招募岗位如…

阿里巴巴人工智能实验室(Ali A.I. Labs)负责人浅雪近期问答整理

目前开发者平台成为大厂兵家必争之地。谷歌开发者平台&#xff0c;紧随其后百度的AI开发者平台&#xff0c;科大讯飞开放平台&#xff08;挑了一个1024大吉大利的日子发布&#xff09;。人工智能时代&#xff0c;连硬件厂商曙光都开始做开发者平台了&#xff08;10月24日&#…

连载:阿里巴巴大数据实践—数据开发平台

阿里数据人都在用的内部技术经验 关注数智化转型俱乐部&#xff0c;数智化不迷路 摘要介绍MaxCompute和阿里巴巴内部基于MaxCompute的大数据开发套件&#xff0c;并对在数据开发过程中经常遇到的问题和相关解决方案进行介绍。 数据只有被整合和计算&#xff0c;才能被用于洞察商…

语音聊天机器人

这个机器人有点智障&#xff0c;主要是免费的图灵机器人接口&#xff0c;就是前些日子没回家休假的雪轩的弟弟雪桐&#xff0c;一个微信聊天机器人&#xff0c;他可能没她姐姐功能多但还是可以使用的。 为什么写一个语音聊天机器人呢&#xff1f;还是上周六中午吃饭的时候&…

chatgpt赋能python:Python人脸对比技术介绍

Python人脸对比技术介绍 人脸识别技术在现代社会中得到了广泛的应用&#xff0c;具有便捷、高效和精度高等优点。Python作为一种高级编程语言&#xff0c;具有方便、易用的特点&#xff0c;受到了越来越多的人的青睐。Python人脸对比技术就是Python在人脸识别技术领域的一种重…

chatgpt赋能Python-python2下载安装教程

Python2下载安装教程 Python是一种高级编程语言&#xff0c;由于其易于学习和使用的特点&#xff0c;在全球范围内受到了广泛的欢迎和使用。Python2是Python语言的早期版本&#xff0c;虽然已经逐渐被Python3所取代&#xff0c;但仍有许多项目在使用Python2。因此&#xff0c;…

chatgpt赋能python:Python宏替换:让你的代码更高效

Python宏替换&#xff1a;让你的代码更高效 Python是一种高级编程语言&#xff0c;它将程序员从繁琐的底层实现细节中解放出来。Python宏替换是一种强大的编程技术&#xff0c;可以加速开发过程并提高代码的可读性。在本文中&#xff0c;我们将介绍Python宏替换&#xff0c;包…

类似于ChatGPT的优秀应用notion

notion 是一款流行的笔记应用。不过功能实际远超笔记&#xff0c;官方自己定义是&#xff1a;“将笔记、知识库和任务管理无缝整合的协作平台”。其独特的 block 概念&#xff0c;极大的扩展了笔记文档的作用&#xff0c;一个 block 可以是个数据库、多媒体、超链接、公式等等。…

陶哲轩的10岁与30岁

Terence Tao&#xff08;陶哲轩&#xff09;&#xff0c;1975年7月17日出生于澳大利亚Adelaide&#xff08;阿德莱德&#xff09;。本讲话作于1985年上半年&#xff0c;即陶哲轩尚未满10周岁时所作&#xff0c;一个稚气儿童&#xff0c;给大学生和教授们作报告&#xff0c;少见…

三位物理学家与陶哲轩证明的惊天定理,原来早在教科书里吗?

陶哲轩菲尔兹奖得主,著名华裔数学家,号称地表最强大脑的拥有者, 近日他与三位物理学家共同发表了一篇论文发现了特征值与特征向量之间的全新关系,在业内引起了不小的反响。 特征值与特征向量 特征值是线性代数中的一个重要概念。其实简单的理解特征值与特征向量就要从线性…

华裔天才数学家-陶哲轩

&#xfeff;&#xfeff; 陶哲轩 当代最年轻的天才数学家&#xff0c;他的才学、人格魅力和治学风范值得我们尊敬和学习。 陶哲轩&#xff0c;男&#xff0c;1975年7月17日出生于澳大利亚阿德莱德&#xff0c; 华裔数学家&#xff0c;任教于美国 加州大学洛杉矶分校&#xff0…

身份证号归属地 在线查询服务 api

目的&#xff1a;提供api, 获取身份证号归属地区(非户籍所在地) 环境ubuntu 18.04 &#xff11;. apihttp://api.online-service.vip/idcard?idNumber370125199007314 idNumber 是对应的身份证号码&#xff0c;身份证一般填写前六位即可 返回的数据为json 2. 备注, 服务器不提…

身份证信息泄露的危险,你知道吗?简单一招就能查询

我们的微信号根据网络的实名制的要求都做了实名认证&#xff0c;可是我们的身份证会不会被别人偷偷绑定微信号呢&#xff1f;其实只要简单一招&#xff0c;就能够查看我们的身份证是否安全。​ 现在身份证信息泄露的危险层出不穷&#xff0c;我们的信息是否安全谁也说不准&…

身份证号码识别(golang)

身份证号码识别&#xff08;golang&#xff09; 使用golang写一个简单的身份证号码识别 基本思路 拿到一张身份证图片&#xff0c;先确定身份证号码的位置将该部分取出&#xff0c;然后进行二值化&#xff0c;比如将数字变成白色&#xff0c;背景变为黑色按照第二步数字的颜…