神理论 | 我面向淘宝编程,而你面向什么编程?(文末赠书5本)
Posted 架构师李肯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了神理论 | 我面向淘宝编程,而你面向什么编程?(文末赠书5本)相关的知识,希望对你有一定的参考价值。
神理论 | 我面向淘宝编程,而你面向什么编程?
陌生人一定会疑问,嵌入式跟taobao有半毛钱关系啊?那么本文,博主就跟你聊聊,如何面向淘宝学习嵌入式!
文章目录
1 写在前面
大家好,我是架构师李肯,一个在嵌入式研发领域摸爬打滚了10年,目前专注于嵌入式物联网系统架构设计的攻城狮。
当你看到我这个标题的时候,一定会非常差异,这到底是什么深理论啊,通过各种 面向XXX编程,就是没听过你这个 面向淘宝学习嵌入式。
那么,本期的议题究竟是一个什么样的结论呢?下面李肯会结合自己的实际从业经验,给你娓娓道来,讲述一段在taobao中学习嵌入式的神级理论。
2 面向XXX编程
这个话题有点大,我们聚焦一下,分分类。
先说一下 正经一点 的:
- 面向过程编程:(procedure oriented Programming)(POP),它是一种以过程为中心的编程思想。这些都是以什么正在发生为主要目标进行编程,比较典型的编程语言就是:C语言。它就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
- 面向对象编程:(object oriented programming)(OOP),它是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。比较典型的编程语言是:C++语言、Java语言 等。
- 面向接口编程:(Interface Oriented Programming)(OIP),它是一种编程思想,接口作为实体抽象出来的一种表现形式,用于抽离内部实现进行外部沟通,最终实现内部变动而不影响外部与其他实现交互。
- 面向实现编程:在面向对象编程设计中有,面对接口编程和面向实现编程之分;面向实现表示继承普通类,面向接口表示子类是实现接口或者抽象类。面向接口的耦合比较低,因修改代码比较低,因为接口和抽象类本身有的方法不干事情,而是子类去去实现。所以面向实现编程,在一定程度上,不是一种推崇的编程方式。
- 面向服务编程:(Service-Oriented Architecture)(SOA),它是一种进行系统开发的新的体系架构。在基于SOA架构的系统中,具体应用程序的功能是由一些松耦合并且具有统一接口定义方式的组件(也就是Service)组合构建起来的,它对迅速变化的业务环境具有良好适应力。
以上几种都是比较经典的编程方法,如有需要深入编程领域,还是要对各项编程方法有比较好的认识和理解,至少能够理解什么情景下改用什么编程方式。
再来几个 不那么正经 的,相信这些梗,你一定听过:
- 面向CV编程:这个指的就是那些只会 CTRL+C 和 CTRL+V 的攻城狮使用的编程方法,这个一般代指从事的编程工作没有实际内涵或者该攻城狮不愿上进只会拷贝代码来实现功能。一般来说,这种是不太可取的。
- 面向百度编程:这种一般就是调侃,有些攻城狮一有问题就百度、bing、google等各大搜索引擎用个遍,而缺少自己对问题的深度思考在里面;这种方式也是不利于攻城狮编码的成长的。
- 面向github编程:这种特指那些专从github上面找各种各样的开源代码,左右一拼接,就形成自己的代码的那帮攻城狮;当然,github的确有非常多优秀的开源代码值得我们去学习,但是我们要取之精华,取其糟粕,最大化地为我所用。把优秀的代码,深入理解消化了,逐步转换为自己的知识,这才是学习优秀代码的上上策。
- 面向薪资编程:这种就更是吐槽式的行为了,换句话说就是,东家给多少钱,写多少代码。虽然短期内好像是自己占了便宜,但从长远的角度来说,真正困于成长的、吃亏的还是你自己;因为你可能浪费了最宝贵的学习上升的时间机会。
- 面向ChatGPT编程:这是最近非常流行的一种编程方式,你只需要把你要的代码逻辑告诉ChatGPT,一段带优美注释的可运行代码就呈现在你面前了。你可能会说,这简直太棒了,但我想说的是,这样的话,我们编程攻城狮的意义何在呢?
以上几种都是调侃式的编程,实际从业操作中,切不可陷入太深,否则可能导致自己无法自拔。
3 面向淘宝学习嵌入式
大家都知道淘宝是一个国民级的电商平台,不敢说常年第一,至少说 稳坐第一批队 应该没有人敢反对。
而就这样的一个体量巨大的电商平台,你要找嵌入式相关的东西,简直不要太方便了。不然的话,你去jingdong试试看?
有了嵌入式的东西,那还得要看你学习嵌入式的什么内容,下面简单介绍下我是如何利用淘宝来学习嵌入式的。
3.1 入门篇
这里说的入门,我个人觉得你至少得有修过电子相关专业课程,比如基础的模电、数电、电路分析等。有了这些电子基础,如果你对嵌入式开发有这浓厚的兴趣,相信你很快就会踏入嵌入式开发的大门。
很多入门嵌入式软件开发都是先走51单片机的老路子,我也不例外。当年还在大三的时候,硬着头皮,省了几天的饭钱,在淘宝上搜索,买了一块需要自己焊接插件的51开发板。至于为了没有选别人焊好的,因为别人焊好的,要贵8块钱。
就这样,我开始拥有了我的第1块开发板;然后自从有了第一块开发板,各种小板子小器件的需求就接踵而来。于是乎,我的淘宝订单逐渐都被嵌入式的各种小东西填满了。当然,有时候还是出点小困惑,比如你要买一个小器件,淘宝上找不到,那就只去附近线下的电子相关的店铺里买。虽然贵一些,但好歹有货。但就现在淘宝如此发达的情况下,这种情况应该很少见了。
51单片机可以说伴随了我嵌入式开发很长的时间,就去年的时候,我都还在使用51单片机,不过已经不是入门级的那种51单片机了;我更倾向于买类似下图这种的核心板,小巧精悍,外设可以灵活搭配,学习做项目的好帮手。这个也是购于 淘宝。
去年我还拿它来做一个智能项目呢,感兴趣的可以去看看。【IoT智能单品设计】一款基于涂鸦智能IoT云平台的新型智能蓝牙水杯_架构师李肯的博客
3.2 进阶篇
到了嵌入式开发进阶了,你可能就不会局限于51单片机了,怎么得也得上stm32。
要学stm32相关的开发,自然要去 淘宝 找开发板。要说这种主流的stm32板子,真的是不要太多,就是受困于之前进口芯片紧缺的问题,stm32普遍比之前贵了不少。
学习stm32,我的观点是不需要一下子上性能太高的板子,稍微在淘宝上找一个比较主流的板子,性价比高的就行。一来,多人玩的板子,自然大家踩的坑也比较多,遇到问题也比较多解决的方案;二来,单纯买来学习,价格的确是需要重点考虑的。
在这里,我比较推荐正点原子的板子,玩的人非常多,他们的教程、源码、售后、名气各方面都占优势,是学习stm32不错的选择。
一开始学习stm32,最重要的还是要能从学习51单片机的思维中迁移过来,学会使用stm32官方的一些开发工具,比如 STM32CubeIDE - STM32的集成开发环境
熟练掌握它的基础寄存器、各种外设是必须的。这个对不必51单片机那是量的碾压,一开始学肯定会吃力不少,但是可以分模块来一个个啃,各个击破。
当这些掌握得差不多了,可以考虑上RTOS实时操作系统,这里我比较推荐上RT-Thread,因为它在stm32的移植和使用已经非常多人玩,非常成熟了,基本不需要自己多踩坑,可以很快就做成一些实战应用。
同时RT-Thread有很好的社区资源,活跃的技术支持,使得初学者有很好的开发体验。
3.3 课外篇
要是工作中,没有相关的嵌入式实战项目联系,我推荐你去参加一个课外设计大赛,这是一个很好的学习提高的方式。
比如我最近在参加的一个 【社区大赛】瑞萨RA4M2(Cortex-M33内核MCU)物联网网关设计挑战赛。挺有意思的一个比赛,有幸在这次比赛中拿了一个三等奖,奖金1K,当做补贴饭钱了。对这个项目感兴趣的,可以联系我。
在参赛前期,我快速地确认了参赛主题,然后由于工作时间比较忙,直到临近项目提交才开始动手。
急急忙忙去 淘宝 买了一些外设模块搭建自己的项目,除了芯片上的踩的一些坑外,项目应用逻辑上,还是比较顺利的,得益于RT-Thread做了很多比较成功的软件包,加速了开发者的开发进程。
至于在业务比赛上淘宝买外设器件这一块上,淘宝的确没让我失败。不过,最好还是要提前买好这些器件,最怕的就是发货赶不及时,耽误了比赛就比较麻烦。
3.4 付费篇
还有一部分需求,其实淘宝真的是一个 资源宝藏库,撇开版权不说,你可能可以在这里找到1块钱的资料,也许这资料你在外面的网站找好久好久也不见得能找到。这大概就是钞能力!
所以提醒一个大家,如果你发现在学习过程中,遇到一些不好找的嵌入式学习资料,不妨来淘宝看看,兴许你能发现宝藏。
4 想在淘宝上干一番事业
每个人都有一个 开店梦,我也不例外。
去年底的时候在家里打扫卫生,突然发现其实家里有很多零零散散、各式各样的开发板、小模块之类的;还有参加各种社区平台获得的大大小小的礼品,堆积在那里。
很多都是一开始收到的时候,兴奋一下,然后热度一过,就在那里吃灰中。
还有,去年年末参加国民技术N32的一个在线直播,感兴趣可以戳这里,主办方也比较大方,直接给每一位参加直播的老师朋友每人赠送了1k等值的芯片。
原本我是想着,看看有没有公司渠道转手卖掉,换点零花钱;后面结合上面那一堆嵌入式的板子,我有了一个新的想法,我想开一个淘宝店,然后店里就买各种各样的板子、期间,同时提供技术支持,顺带还能扶持一些有潜力成长的攻城狮,何乐而不为呢?
至于,我那1K的芯片,我想我可能会layout一块新的开发板,作为特殊福利送给那些支持我的攻城狮?
具体怎么操作呢?我现在还没有完全想好,也请大家可以期待一下。
5 友情推荐
今天给大家推荐一本软件交付领域的大成之作:《淘宝交付之道》。
全面个性化、内容化的淘宝天猫,构造了基于内容的丰富的导购场景,包括猜你喜欢、有好货、每日好店、必买清单、哇哦视频、微淘、买家秀、 头条、洋葱盒子等。个性化为消费者带来了更精准的货品分发服务,内容化为消费者带来了更多惊喜和更好的服务体验。好的商品应该以更好的形式展现给消费者。
不同于传统测试业务,面对海量的 feed 流(即持续更新并呈现给用户内容的信息流)内容、个性化推荐分发、庞大的用户群体等挑战,如何构建整体内容导购质量 体系?如何发现问题、度量体验并丰富和提效测试手段?构建整体内容导购质量体系,主要可从以下两个方面进行考虑。
- 用户侧:如何评估千人千面导购推荐系统?
- 平台侧:多来源、多类型、高标准下,如何高效管控素材质量?
对本书感兴趣的,可以到我的社区,查看本书的详细介绍。
6 文末福利
为了感谢广大粉丝朋友的支持,特在本文举办赠书答谢活动,详细内容可参加我的社区活动:【第14期社区福利赠书活动】只为最美,淘宝“千人千面”导购智能评测与素材巡检(文末赠书《淘宝交付之道》5本)-CSDN社区,一共赠书5本,欢迎大家踊跃参加。
Spring框架AOP面向切面编程
一.前言
在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnblogs.com/xrq730/p/4919025.html
AOP
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
AOP核心概念
1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut)
对连接点进行拦截的定义
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象
代理的目标对象
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
Spring对AOP的支持
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:
1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了
2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB
AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:
1、定义普通业务组件
2、定义切入点,一个切入点可能横切多个业务组件
3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作
所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。
下面给出一个Spring AOP的.xml文件模板,名字叫做aop.xml,之后的内容都在aop.xml上进行扩展:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> </beans>
基于Spring的AOP简单实现
注意一下,在讲解之前,说明一点:使用Spring AOP,要成功运行起代码,只用Spring提供给开发者的jar包是不够的,请额外上网下载两个jar包:
1、aopalliance.jar
2、aspectjweaver.jar
开始讲解用Spring AOP的XML实现方式,先定义一个接口:
public interface HelloWorld { void printHelloWorld(); void doPrint(); }
定义两个接口实现类:
public class HelloWorldImpl1 implements HelloWorld { public void printHelloWorld() { System.out.println("Enter HelloWorldImpl1.printHelloWorld()"); } public void doPrint() { System.out.println("Enter HelloWorldImpl1.doPrint()"); return ; } }
public class HelloWorldImpl2 implements HelloWorld { public void printHelloWorld() { System.out.println("Enter HelloWorldImpl2.printHelloWorld()"); } public void doPrint() { System.out.println("Enter HelloWorldImpl2.doPrint()"); return ; } }
横切关注点,这里是打印时间:
public class TimeHandler { public void printTime() { System.out.println("CurrentTime = " + System.currentTimeMillis()); } }
有这三个类就可以实现一个简单的Spring AOP了,看一下aop.xml的配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" /> <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" /> <bean id="timeHandler" class="com.xrq.aop.TimeHandler" /> <aop:config> <aop:aspect id="time" ref="timeHandler"> <aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" /> <aop:before method="printTime" pointcut-ref="addAllMethod" /> <aop:after method="printTime" pointcut-ref="addAllMethod" /> </aop:aspect> </aop:config> </beans>
写一个main函数调用一下:
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml"); HelloWorld hw1 = (HelloWorld)ctx.getBean("helloWorldImpl1"); HelloWorld hw2 = (HelloWorld)ctx.getBean("helloWorldImpl2"); hw1.printHelloWorld(); System.out.println(); hw1.doPrint(); System.out.println(); hw2.printHelloWorld(); System.out.println(); hw2.doPrint(); }
运行结果为:
CurrentTime = 1446129611993 Enter HelloWorldImpl1.printHelloWorld() CurrentTime = 1446129611993 CurrentTime = 1446129611994 Enter HelloWorldImpl1.doPrint() CurrentTime = 1446129611994 CurrentTime = 1446129611994 Enter HelloWorldImpl2.printHelloWorld() CurrentTime = 1446129611994 CurrentTime = 1446129611994 Enter HelloWorldImpl2.doPrint() CurrentTime = 1446129611994
看到给HelloWorld接口的两个实现类的所有方法都加上了代理,代理内容就是打印时间
基于Spring的AOP使用其他细节
1、增加一个横切关注点,打印日志,Java类为:
public class LogHandler { public void LogBefore() { System.out.println("Log before method"); } public void LogAfter() { System.out.println("Log after method"); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" /> <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" /> <bean id="timeHandler" class="com.xrq.aop.TimeHandler" /> <bean id="logHandler" class="com.xrq.aop.LogHandler" /> <aop:config> <aop:aspect id="time" ref="timeHandler" order="1"> <aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.*(..))" /> <aop:before method="printTime" pointcut-ref="addTime" /> <aop:after method="printTime" pointcut-ref="addTime" /> </aop:aspect> <aop:aspect id="log" ref="logHandler" order="2"> <aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.*(..))" /> <aop:before method="LogBefore" pointcut-ref="printLog" /> <aop:after method="LogAfter" pointcut-ref="printLog" /> </aop:aspect> </aop:config> </beans>
测试类不变,打印结果为:
CurrentTime = 1446130273734 Log before method Enter HelloWorldImpl1.printHelloWorld() Log after method CurrentTime = 1446130273735 CurrentTime = 1446130273736 Log before method Enter HelloWorldImpl1.doPrint() Log after method CurrentTime = 1446130273736 CurrentTime = 1446130273736 Log before method Enter HelloWorldImpl2.printHelloWorld() Log after method CurrentTime = 1446130273736 CurrentTime = 1446130273737 Log before method Enter HelloWorldImpl2.doPrint() Log after method CurrentTime = 1446130273737
要想让logHandler在timeHandler前使用有两个办法:
(1)aspect里面有一个order属性,order属性的数字就是横切关注点的顺序
(2)把logHandler定义在timeHandler前面,Spring默认以aspect的定义顺序作为织入顺序
2、我只想织入接口中的某些方法
修改一下pointcut的expression就好了:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" /> <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" /> <bean id="timeHandler" class="com.xrq.aop.TimeHandler" /> <bean id="logHandler" class="com.xrq.aop.LogHandler" /> <aop:config> <aop:aspect id="time" ref="timeHandler" order="1"> <aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.print*(..))" /> <aop:before method="printTime" pointcut-ref="addTime" /> <aop:after method="printTime" pointcut-ref="addTime" /> </aop:aspect> <aop:aspect id="log" ref="logHandler" order="2"> <aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.do*(..))" /> <aop:before method="LogBefore" pointcut-ref="printLog" /> <aop:after method="LogAfter" pointcut-ref="printLog" /> </aop:aspect> </aop:config> </beans>
表示timeHandler只会织入HelloWorld接口print开头的方法,logHandler只会织入HelloWorld接口do开头的方法
3、强制使用CGLIB生成代理
前面说过Spring使用动态代理或是CGLIB生成代理是有规则的,高版本的Spring会自动选择是使用动态代理还是CGLIB生成代理内容,当然我们也可以强制使用CGLIB生成代理,那就是<aop:config>里面有一个"proxy-target-class"属性,这个属性值如果被设置为true,那么基于类的代理将起作用,如果proxy-target-class被设置为false或者这个属性被省略,那么基于接口的代理将起作用
以上是关于神理论 | 我面向淘宝编程,而你面向什么编程?(文末赠书5本)的主要内容,如果未能解决你的问题,请参考以下文章