25种代码坏味道总结

news/2024/5/16 16:22:19/文章来源:https://blog.csdn.net/t194978/article/details/129769222

前言

什么样的代码是好代码呢?好的代码应该命名规范、可读性强、扩展性强、健壮性......而不好的代码又有哪些典型特征呢?这25种代码坏味道大家要注意啦

1. Duplicated Code (重复代码)

重复代码就是不同地点,有着相同的程序结构。一般是因为需求迭代比较快,开发小伙伴担心影响已有功能,就复制粘贴造成的。重复代码很难维护的,如果你要修改其中一段的代码逻辑,就需要修改多次,很可能出现遗漏的情况。

如何优化重复代码呢?分三种情况讨论:

  1. 同一个类的两个函数含有相同的表达式
class A {public void method1() {doSomething1doSomething2doSomething3}public void method2() {doSomething1doSomething2doSomething4}
}
复制代码

优化手段:可以使用Extract Method(提取公共函数) 抽出重复的代码逻辑,组成一个公用的方法。

class A {public void method1() {commonMethod();doSomething3}public void method2() {commonMethod();doSomething4}public void commonMethod(){doSomething1doSomething2}
}
复制代码
  1. 两个互为兄弟的子类内含相同的表达式
class A extend C {public void method1() {doSomething1doSomething2doSomething3}
}class B extend C {public void method1() {doSomething1doSomething2doSomething4}
}复制代码

优化手段:对两个类都使用Extract Method(提取公共函数),然后把抽取出来的函数放到父类中。

class C {public void commonMethod(){doSomething1doSomething2}
}
class A extend C {public void method1() {commonMethod();doSomething3}
}class B extend C {public void method1() {commonMethod();doSomething4}
}
复制代码
  1. 两个毫不相关的类出现重复代码

如果是两个毫不相关的类出现重复代码,可以使用Extract Class将重复代码提炼到一个类中。这个新类可以是一个普通类,也可以是一个工具类,看具体业务怎么划分吧。

2 .Long Method (长函数)

长函数是指一个函数方法几百行甚至上千行,可读性大大降低,不便于理解。反例如下:

public class Test {private String name;private Vector<Order> orders = new Vector<Order>();public void printOwing() {//print bannerSystem.out.println("****************");System.out.println("*****customer Owes *****");System.out.println("****************");//calculate totalAmountEnumeration env = orders.elements();double totalAmount = 0.0;while (env.hasMoreElements()) {Order order = (Order) env.nextElement();totalAmount += order.getAmout();}//print detailsSystem.out.println("name:" + name);System.out.println("amount:" + totalAmount);......}
}
复制代码

可以使用Extract Method,抽取功能单一的代码段,组成命名清晰的小函数,去解决长函数问题,正例如下:

public class Test {private String name;private Vector<Order> orders = new Vector<Order>();public void printOwing() {//print bannerprintBanner();//calculate totalAmountdouble totalAmount = getTotalAmount();//print detailsprintDetail(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);}}
复制代码

3. Large Class (过大的类)

一个类做太多事情,维护了太多功能,可读性变差,性能也会下降。举个例子,订单相关的功能你放到一个类A里面,商品库存相关的也放在类A里面,积分相关的还放在类A里面...反例如下:

Class A{public void printOrder(){System.out.println("订单");}public void printGoods(){System.out.println("商品");}public void printPoints(){System.out.println("积分");}
}复制代码

试想一下,乱七八糟的代码块都往一个类里面塞,还谈啥可读性。应该按单一职责,使用Extract Class把代码划分开,正例如下:

Class Order{public void printOrder(){System.out.println("订单");}
}Class Goods{public void printGoods(){System.out.println("商品");}
}Class Points{   public void printPoints(){System.out.println("积分");}}
}复制代码

4. Long Parameter List (过长参数列)

方法参数数量过多的话,可读性很差。如果有多个重载方法,参数很多的话,有时候你都不知道调哪个呢。并且,如果参数很多,做新老接口兼容处理也比较麻烦。

public void getUserInfo(String name,String age,String sex,String mobile){// do something ...
}
复制代码

如何解决过长参数列问题呢?将参数封装成结构或者类,比如我们将参数封装成一个DTO类,如下:

public void getUserInfo(UserInfoParamDTO userInfoParamDTO){// do something ...
}class UserInfoParamDTO{private String name;private String age; private String sex;private String mobile;
}
复制代码

5. Divergent Change (发散式变化)

对程序进行维护时, 如果添加修改组件, 要同时修改一个类中的多个方法, 那么这就是 Divergent Change。举个汽车的例子,某个汽车厂商生产三种品牌的汽车:BMW、Benz和LaoSiLaiSi,每种品牌又可以选择燃油、纯电和混合动力。反例如下

/***  公众号:捡田螺的小男孩*/
public class Car {private String name;void start(Engine engine) {if ("HybridEngine".equals(engine.getName())) {System.out.println("Start Hybrid Engine...");} else if ("GasolineEngine".equals(engine.getName())) {System.out.println("Start Gasoline Engine...");} else if ("ElectricEngine".equals(engine.getName())) {System.out.println("Start Electric Engine");}}void drive(Engine engine,Car car) {this.start(engine);System.out.println("Drive " + getBrand(car) + " car...");}String getBrand(Car car) {if ("Baoma".equals(car.getName())) {return "BMW";} else if ("BenChi".equals(car.getName())) {return "Benz";} else if ("LaoSiLaiSi".equals(car.getName())) {return "LaoSiLaiSi";}return null;}}
复制代码

如果新增一种品牌新能源电车,然后它的启动引擎是核动力呢,那么就需要修改Car类的startgetBrand方法啦,这就是代码坏味道:Divergent Change (发散式变化)

如何优化呢?一句话总结:拆分类,将总是一起变化的东西放到一块

  • 运用提炼类(Extract Class) 拆分类的行为。
  • 如果不同的类有相同的行为,提炼超类(Extract Superclass) 和 提炼子类(Extract Subclass)。

正例如下:

因为Engine是独立变化的,所以提取一个Engine接口,如果新加一个启动引擎,多一个实现类即可。如下:

//IEngine
public interface IEngine {void start();
}public class HybridEngineImpl implements IEngine { @Overridepublic void start() {System.out.println("Start Hybrid Engine...");}
}
复制代码

因为drive方法依赖于Car,IEngine,getBand方法;getBand方法是变化的,也跟Car是有关联的,所以可以搞个抽象Car的类,每个品牌汽车继承于它即可,如下

public abstract class AbstractCar {protected IEngine engine;public AbstractCar(IEngine engine) {this.engine = engine;}public abstract void drive();
}//奔驰汽车
public class BenzCar extends AbstractCar {public BenzCar(IEngine engine) {super(engine);}@Overridepublic void drive() {this.engine.start();System.out.println("Drive " + getBrand() + " car...");}private String getBrand() {return "Benz";}
}//宝马汽车
public class BaoMaCar extends AbstractCar {public BaoMaCar(IEngine engine) {super(engine);}@Overridepublic void drive() {this.engine.start();System.out.println("Drive " + getBrand() + " car...");}private String getBrand() {return "BMW";}
}复制代码

细心的小伙伴,可以发现不同子类BaoMaCar和BenzCar的drive方法,还是有相同代码,所以我们可以再扩展一个抽象子类,把drive方法推进去,如下:

public abstract class AbstractRefinedCar extends AbstractCar {public AbstractRefinedCar(IEngine engine) {super(engine);}@Overridepublic void drive() {this.engine.start();System.out.println("Drive " + getBrand() + " car...");}abstract String getBrand();
}//宝马
public class BaoMaRefinedCar extends AbstractRefinedCar {public BaoMaRefinedCar(IEngine engine) {super(engine);}@OverrideString getBrand() {return  "BMW";}
}复制代码

如果再添加一个新品牌,搞个子类,继承AbstractRefinedCar即可,如果新增一种启动引擎,也是搞个类实现IEngine接口即可

6. Shotgun Surgery(散弹式修改)

当你实现某个小功能时,你需要在很多不同的类做出小修改。这就是Shotgun Surgery(散弹式修改)。它跟发散式变化(Divergent Change) 的区别就是,它指的是同时对多个类进行单一的修改,发散式变化指在一个类中修改多处。反例如下

public class DbAUtils {@Value("${db.mysql.url}")private String mysqlDbUrl;...
}public class DbBUtils {@Value("${db.mysql.url}")private String mysqlDbUrl;...
}
复制代码

多个类使用了db.mysql.url这个变量,如果将来需要切换mysql到别的数据库,如Oracle,那就需要修改多个类的这个变量!

如何优化呢?将各个修改点,集中到一起,抽象成一个新类。

可以使用 Move Method (搬移函数)和 Move Field (搬移字段)把所有需要修改的代码放进同一个类,如果没有合适的类,就去new一个。

正例如下:

public class DbUtils {@Value("${db.mysql.url}")private String mysqlDbUrl;...
}
复制代码

7. Feature Envy (依恋情节)

某个函数为了计算某个值,从另一个对象那里调用几乎半打的取值函数。通俗点讲,就是一个函数使用了大量其他类的成员,有人称之为红杏出墙的函数。反例如下:

public class User{private Phone phone;public User(Phone phone){this.phone = phone;}public void getFullPhoneNumber(Phone phone){System.out.println("areaCode:" + phone.getAreaCode());System.out.println("prefix:" + phone.getPrefix());System.out.println("number:" + phone.getNumber());}
}
复制代码

如何解决呢?在这种情况下,你可以考虑将这个方法移动到它使用的那个类中。例如,要将 getFullPhoneNumber() User 类移动到Phone 类中,因为它调用了Phone 类的很多方法。

8. Data Clumps(数据泥团)

数据项就像小孩子,喜欢成群结队地呆在一块。如果一些数据项总是一起出现的,并且一起出现更有意义的,就可以考虑,按数据的业务含义来封装成数据对象。反例如下:

public class User {private String firstName;private String lastName;private String province;private String city;private String area;private String street;
}复制代码

正例:

public class User {private UserName username;private Adress adress;
}class UserName{private String firstName;private String lastName;
}
class Address{private String province;private String city;private String area;private String street;
}
复制代码

9. Primitive Obsession (基本类型偏执)

多数编程环境都有两种数据类型,结构类型和基本类型。这里的基本类型,如果指Java语言的话,不仅仅包括那八大基本类型哈,也包括String等。如果是经常一起出现的基本类型,可以考虑把它们封装成对象。我个人觉得它有点像Data Clumps(数据泥团) 举个反例如下:

// 订单
public class Order {private String customName;private String address;private Integer orderId;private Integer price;
}
复制代码

正例:

// 订单类
public class Order {private Custom custom;private Integer orderId;private Integer price;
}
// 把custom相关字段封装起来,在Order中引用Custom对象
public class Custom {private String name;private String address;
}复制代码

当然,这里不是所有的基本类型,都建议封装成对象,有关联或者一起出现的,才这么建议哈。

10. Switch Statements (Switch 语句)

这里的Switch语句,不仅包括Switch相关的语句,也包括多层if...else的语句哈。很多时候,switch语句的问题就在于重复,如果你为它添加一个新的case语句,就必须找到所有的switch语句并且修改它们。

示例代码如下:

    String medalType = "guest";if ("guest".equals(medalType)) {System.out.println("嘉宾勋章");} else if ("vip".equals(medalType)) {System.out.println("会员勋章");} else if ("guard".equals(medalType)) {System.out.println("守护勋章");}...
复制代码

这种场景可以考虑使用多态优化:

//勋章接口
public interface IMedalService {void showMedal();
}//守护勋章策略实现类
public class GuardMedalServiceImpl implements IMedalService {@Overridepublic void showMedal() {System.out.println("展示守护勋章");}
}
//嘉宾勋章策略实现类
public class GuestMedalServiceImpl implements IMedalService {@Overridepublic void showMedal() {System.out.println("嘉宾勋章");}
}//勋章服务工厂类
public class MedalServicesFactory {private static final Map<String, IMedalService> map = new HashMap<>();static {map.put("guard", new GuardMedalServiceImpl());map.put("vip", new VipMedalServiceImpl());map.put("guest", new GuestMedalServiceImpl());}public static IMedalService getMedalService(String medalType) {return map.get(medalType);}
}复制代码

当然,多态只是优化的一个方案,一个方向。如果只是单一函数有些简单选择示例,并不建议动不动就使用动态,因为显得有点杀鸡使用牛刀了。

11.Parallel Inheritance Hierarchies( 平行继承体系)

平行继承体系 其实算是Shotgun Surgery的特殊情况啦。当你为A类的一个子类Ax,也必须为另一个类B相应的增加一个子类Bx。

 

解决方法:遇到这种情况,就要消除两个继承体系之间的引用,有一个类是可以去掉继承关系的。

12. Lazy Class (冗赘类)

把这些不再重要的类里面的逻辑,合并到相关类,删掉旧的。一个比较常见的场景就是,假设系统已经有日期工具类DateUtils,有些小伙伴在开发中,需要用到日期转化等,不管三七二十一,又自己实现一个新的日期工具类。

13. Speculative Generality(夸夸其谈未来性)

尽量避免过度设计的代码。例如:

  • 只有一个if else,那就不需要班门弄斧使用多态;
  • 如果某个抽象类没有什么太大的作用,就运用Collapse Hierarchy(折叠继承体系)```
  • 如果函数的某些参数没用上,就移除。

14. Temporary Field(令人迷惑的临时字段)

某个实例变量仅为某种特定情况而定而设,这样的代码就让人不易理解,我们称之为 Temporary Field(令人迷惑的临时字段)。 反例如下:

public class PhoneAccount {private double excessMinutesCharge;private static final double RATE = 8.0;public double computeBill(int minutesUsed, int includedMinutes) {excessMinutesCharge = 0.0;int excessMinutes = minutesUsed - includedMinutes;if (excessMinutes >= 1) {excessMinutesCharge = excessMinutes * RATE;}return excessMinutesCharge;}public double chargeForExcessMinutes(int minutesUsed, int includedMinutes) {computeBill(minutesUsed, includedMinutes);return excessMinutesCharge;}
}复制代码

思考一下,临时字段excessMinutesCharge是否多余呢?

15. Message Chains (过度耦合的消息链)

当你看到用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象...这就是消息链。实际代码中,你看到的可能是一长串getThis()或一长串临时变量。反例如下:

A.getB().getC().getD().getTianLuoBoy().getData();
复制代码

A想要获取需要的数据时,必须要知道B,又必须知道C,又必须知道D...其实A需要知道得太多啦,回头想下封装性,嘻嘻。其实可以通过拆函数或者移动函数解决,比如由B作为代理,搞个函数直接返回A需要数据。

16. Middle Man (中间人)

对象的基本特征之一就是封装,即对外部世界隐藏其内部细节。封装往往伴随委托,过度运用委托就不好:某个类接口有一半的函数都委托给其他类。可以使用Remove Middle Man优化。反例如下:

A.B.getC(){return C.getC();
}
复制代码

其实,A可以直接通过C去获取C,而不需要通过B去获取。

17. Inappropriate Intimacy(狎昵关系)

如果两个类过于亲密,过分狎昵,你中有我,我中有你,两个类彼此使用对方的私有的东西,就是一种坏代码味道。我们称之为Inappropriate Intimacy(狎昵关系)

建议尽量把有关联的方法或属性抽离出来,放到公共类,以减少关联。

 

18. Alternative Classes with Different Interfaces (异曲同工的类)

A类的接口a,和B类的接口b,做的的是相同一件事,或者类似的事情。我们就把A和B叫做异曲同工的类。

可以通过重命名,移动函数,或抽象子类等方式优化

19. Incomplete Library Class (不完美的类库)

大多数对象只要够用就好,如果类库构造得不够好,我们不可能修改其中的类使它完成我们希望完成的工作。可以酱紫:包一层函数或包成新的类

20. Data Class (纯数据类)

什么是Data Class? 它们拥有一些字段,以及用于访问(读写)这些字段的函数。这些类很简单,仅有公共成员变量,或简单操作的函数。

如何优化呢?将相关操作封装进去,减少public成员变量。比如:

  • 如果拥有public字段-> Encapsulate Field
  • 如果这些类内含容器类的字段,应该检查它们是不是得到了恰当地封装-> Encapsulate Collection 封装起来
  • 对于不该被其他类修改的字段-> Remove Setting Method ->找出取值/设置函数被其他类运用的地点-> Move Method 把这些调用行为搬移到Data Class来。如果无法搬移整个函数,就运用 Extract Method产生一个可被搬移的函数->Hide Method把这些取值/设置函数隐藏起来。

21. Refused Bequest (被拒绝的馈赠)

子类应该继承父类的数据和函数。子类继承得到所有函数和数据,却只使用了几个,那就是继承体系设计错误,需要优化。

  • 需要为这个子类新建一个兄弟类->Push Down MethodPush Down Field把所有用不到的函数下推给兄弟类,这样一来,超类就只持有所有子类共享的东西。所有超类都应该是抽象的。
  • 如果子类复用了超类的实现,又不愿意支持超类的接口,可以不以为然。但是不能胡乱修改继承体系->Replace Inheritance with Delegation(用委派替换继承).

22. Comments (过多的注释)

这个点不是说代码不建议写注释哦,而是,建议大家避免用注释解释代码,避免过多的注释。这些都是常见注释的坏味道:

  • 多余的解释
  • 日志式注释
  • 用注释解释变量等
  • ...

如何优化呢?

  • 方法函数、变量的命名要规范、浅显易懂、避免用注释解释代码。
  • 关键、复杂的业务,使用清晰、简明的注释

23. 神奇命名

方法函数、变量、类名、模块等,都需要简单明了,浅显易懂。避免靠自己主观意识瞎起名字。

反例:

boolean test = chenkParamResult(req);
复制代码

正例:

boolean isParamPass = chenkParamResult(req);
复制代码

24. 神奇魔法数

日常开发中,经常会遇到这种代码:

if(userType==1){//doSth1
}else If( userType ==2){//doSth2
}
...
复制代码

代码中的这个1和2都表示什么意思呢?再比如setStatus(1)中的1又表示什么意思呢?看到类似坏代码,可以这两种方式优化:

  • 新建个常量类,把一些常量放进去,统一管理,并且写好注释;
  • 建一个枚举类,把相关的魔法数字放到一起管理。

25. 混乱的代码层次调用

我们代码一般会分dao层service层controller层

  • dao层主要做数据持久层的工作,与数据库打交道。
  • service层主要负责业务逻辑处理。
  • controller层负责具体的业务模块流程的控制。

所以一般就是controller调用serviceservicedao。如果你在代码看到controller直接调用dao,那可以考虑是否优化啦。反例如下

@RestController("user")
public class UserController {Autowiredprivate UserDao userDao;@RequestMapping("/queryUserInfo")public String queryUserInfo(String userName) {return userDao.selectByUserName(userName);}
}复制代码

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

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

相关文章

为什么保存按钮那么像自动售货机?

高中生 Every Highschool Senior: I can’t wait to move out and go to college and Be on my Own. 每一个高中毕业生&#xff1a; 我等不及离开去大学&#xff0c;独立自我。 Everyone in College: 大学里的每个人&#xff1a; 评论区 Stoovin: The real world sucks. But…

LD_PRELOAD劫持(超详细篇)

目录 前提知识 环境变量 链接 LD_PRELOAD LD_LIBRARY_PATH ELF文件 /bin、/sbin、/usr/sbin、/usr/bin 漏洞复现 案例一(随机数劫持) 案例二(ls的劫持) 案例三(__attribute__&LD_PRELOAD劫持) 案例四(利用 LD_PRELOAD 绕过 Disable_Functions) 案例五(利用 er…

小白学Pytorch系列--Torch.nn API Pooling layers(3)

小白学Pytorch系列–Torch.nn API (3) 方法注释nn.MaxPool1d对由多个输入平面组成的输入信号应用1D最大池化。nn.MaxPool2d对由多个输入平面组成的输入信号应用二维最大池化。nn.MaxPool3d在由多个输入平面组成的输入信号上应用3D最大池化。nn.MaxUnpool1d计算MaxPool1d的偏逆。…

Zookeeper3.5.7版本—— Curator框架实现分布式锁案例

目录一、Zookeeper原生的 Java API 存在的问题二、Zookeeper原生的 Java API 存在问题的解决方式三、Curator框架实现分布式锁示例代码3.1、pom文件添加依赖3.2、示例代码3.3、Curator框架实现分布式锁测试一、Zookeeper原生的 Java API 存在的问题 会话连接是异步的&#xff…

Kubernetes为容器和 Pods 分配 CPU 资源

Kubernetes为容器和 Pods 分配 CPU 资源 一、指定CPU请求和CPU限制 1、创建一个命名空间&#xff08;namespace&#xff09; [rootmaster ~]# kubectl create namespace cpu-example namespace/cpu-example created2、编写yaml文件 要为容器指定CPU请求&#xff0c;需要在容…

STC32G 比较器及其应用编程

一 STC32G系列单片机寄存器简介STC32G系列单片机内部集成了一个比较器&#xff0c;其正极可以在P3.7、P5.0、P5.1、或者ADC的模拟输入通道间切换&#xff1b;而负极可以是P3.7或者内部BandGap经过OP的REF电压。通过配置分时复用可以实现多个比较器的应用。STC32G系列单片机的比…

MySQL数据库基础到进阶笔记整理包含事务、SQL优化、锁等内容

写在前面 本文是在学习MySQL数据库时整理的笔记&#xff0c;可供初学者学习 是在https://dhc.pythonanywhere.com/entry/share/?key12e4a7324f68371db3984d93e26e458962a4f0bc188ec23ec70637a4f3b4d58f 笔记基础上增加了一些内容以及后续的锁、InnoDB引擎等内容 课程参考b站黑…

Java数据结构与算法----搜索篇(DFS与BFS)

一.概念DFS&#xff08;Depth First Search&#xff09;深度优先搜索 和BFS&#xff08;Breadth First Search&#xff09;广度优先搜索 是两种广泛应用于搜索和遍历算法中的基本技术。这两种算法都涉及到搜索数据结构中的节点 。这里我们以二叉树为例&#xff0c;简单地图解一…

实验九 TSP问题

《算法设计与分析》实验报告 所在院系 计算机与信息工程学院 学生学号 学生姓名 年级专业 2020级计算机科学与技术 授课教师 彭绪富 学 期 2022-2023学年第一学期 提交时间 2022年10月26日 目 录 实验九-1&#xff1a;TSP问题 一、实验目的与要求 二…

【图解http】

目录了解web及网络基础TCP/IP协议族与HTTP关系密切的协议&#xff1a;IP、TCP和DNS各种协议与HTTP协议的关系URI和URLhttp协议HTTP是不保存状态的协议请求URI定位资源告知服务器意图的HTTP方法持久连接节省通信量HTTP报文编码提升传输速率压缩传输的内容编码分割发送的分块传输…

关于参加新星计划的收获

目录 作者简介 前言 一、新星计划介绍 二、新星计划创作目标 &#xff08;一&#xff09;创作打卡阶段第1周&#xff08;3/13-3/19&#xff09; &#xff08;二&#xff09;创作打卡阶段第2周&#xff08;3/20-3/26&#xff09; 三、参赛文章的构思与创作 &#xff08…

Go map 内存泄露

前言 在Go中, map这个结构使用的频率还是比较高的. 其实在所有的语言中, map使用的频率都是很高的. 之前在使用中, 一直都知道map的内存在元素删除的时候不会回收, 但一直没有仔细的研究为什么. 今天就来好好揣摩揣摩. func main() {m : make(map[int][128]byte)for i : 0; …

2023热门抖音权重查询小程序源码

2023热门抖音权重查询小程序源码 跟抖音上很火的一模一样&#xff0c;小程序适配优化。接口免费。小程序不是网页 修改教程: 1&#xff0c;如果想修改或者去除水印&#xff0c;直接删除或修改“index.html”12&#xff5e;22行 2&#xff0c;如果想修改logo&#xff0c;直接…

“全球首款旗舰”填补行业空白,两轮电动车技术创新为何只看绿源?

作者 | 曾响铃 文 | 响铃说 乒乓作为我们的“国球”&#xff0c;在数不清的体育赛事里书写辉煌战绩&#xff0c;也进一步被国人熟知、热爱。更难能可贵的是“国球”精神&#xff1a;“别人可能练了一千次&#xff0c;而我们却练了一万次”&#xff0c;冠军品质&#xff0c;奋…

MYSQL【基础篇】MYSQL 主要函数

MySQL中的函数主要分为以下四类&#xff1a; 字符串函数、数值函数、日期函数、流程函数 ​MySQL函数是MySQL数据库提供的内部函数。这些内部函数可以帮助用户更加方便的处理表中的数据 MySQL函数可以对表中数据进行相应的处理&#xff0c;以便得到用户希望得到的数据。这些函…

JAVA Session会话 Thymeleaf - 视图模板技术配置步骤

JAVAWebSession会话会话跟踪技术session保存作用域Thymeleaf - 视图模板技术配置过程Session会话 HTTP是无状态的&#xff1a;服务器无法区分这两个请求是同一个客户端发过来的&#xff0c;还是不同的客户端发过来的 现实问题&#xff1a;第一次请求是添加商品到购物车&#x…

C++中的string类【详细分析及模拟实现】

string类 目录string类一、stirng的介绍及使用1.为什么学习string类&#xff1f;2.标准库中的string类2.1 引入&#xff1a;编码2.2 basic_string3.string类的使用3.1 构造函数3.2 遍历string方式1&#xff1a;for循环方式2&#xff1a;范围for4.迭代器4.1 正向迭代器4.2反向迭…

Golang流媒体实战之二:回源

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 今天的实战是流传输过程中的常见功能&#xff1a;回源如下图&#xff0c;lal(源站)和lal(拉流节点)代表两台电脑&#xff0c;上面都部署了lalVLC在…

【蓝桥杯】巧克力

问题描述&#xff1a; 题解分析&#xff1a; 错误思想&#xff1a;本来的想法是先使用低价格的巧克力&#xff0c;并且判断需要吃几块【其中内容比较细】&#xff0c;直接计算即可&#xff0c;但是本题好像不可以用简单的最小价格的贪心来做 正确思路&#xff1a;创建一个结…

【内网安全】 横向移动IPCATSC命令Impacket套件CS插件全自动

文章目录域信息收集-目标&用户&凭据&网络域横向移动-IPC-命令版-AT&schtasks上线配置at < Windows2012 (该版本之前的操作系统使用at命令)补充反向连接上线效果图schtasks >Windows2012(适用于windows2012后的操作系统版本)建立IPC常见的错误代码域横向移…