终极防御性编程神器

终极防御性编程神器

-- 楼兰

​ 现在IT大环境下滑,开始催生出了一个程序员极地求生新技能:防御性编程。

​ 原本防御性编程的意思是在写业务代码时应该要更多的考过各种可能出现的边界情况,做更多防御性的考量。但是,现在大环境对程序员确实不太友好,防御性编程有了新的含义。那就是让我的代码只有我能看懂,别人都看不懂。这样,别人就无法抢我的饭碗了。老板裁员时自然也要掂量掂量了。

​ 这要怎么做呢?我还真去互联网上搜索学习了一番。但是,大部分都是一些跟标准代码规范反着来的小套路。比如命名用a,b,c,d;不打日志,不加注释;不拆方法,一个方法上千行代码等等。

​ 这些方法有用吗?No!No!No!这些方法都太low了,根本就过不了代码评审的。高端的程序员当然要用高端的套路。

​ 高端的防御性编程就是要让这些代码所有人都能看明白,但是,却只有你明白其中的套路,未来也只有你能够维护代码中的业务逻辑。


一、做一个高端的聊天机器人


​ 随着AI大模型越来越火爆,聊天机器人也跟着越来越火了。接下来,楼兰老师带大家做一个非常高端的聊天机器人。并以此为契机,看看如何把聊天机器人的代码用高端的防御性编程思路,给隐藏起来。所有源码免费提供,拿走不谢。只要不说是我教的就行。

​ 面向接口编程,是每个程序员的基本素质。所以,我们的程序也从一个接口开始:

package com.roy.chat;
// 智能聊天机器人
public interface ChatRobot {
    /**
     * 根据用户的问题,给出贴心的回答
     * @param question 用户的问题
     * @return 机器人的贴心回答
     */
    String chat(String question);
}

​ 注意代码规范哦。注释一个不能少。

​ 接下来,我们就按照把大象放冰箱的步骤来完成这个聊天机器人。

​ 第一步:先准备一些简单的配置信息。

// 智能机器人产品码。使用前请找本人申请。
public static final String CHAT_ROBOT_CODE = "yv66vgAAAD0AOgoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWBQAAAAAAAAPoCgAKAAsHAAwMAA0ADgEAEGphdmEvbGFuZy9UaHJlYWQBAAVzbGVlcAEABChKKVYSAAAAEAwAEQASAQAXbWFrZUNvbmNhdFdpdGhDb25zdGFudHMBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwcAFAEAHmphdmEvbGFuZy9JbnRlcnJ1cHRlZEV4Y2VwdGlvbgcAFgEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uCgAVABgMAAUAGQEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgcAGwEAGGNvbS9yb3kvY2hhdC9NeUNoYXRSb2JvdAcAHQEAFmNvbS9yb3kvY2hhdC9DaGF0Um9ib3QBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAGkxjb20vcm95L2NoYXQvTXlDaGF0Um9ib3Q7AQAEY2hhdAEAAWUBACBMamF2YS9sYW5nL0ludGVycnVwdGVkRXhjZXB0aW9uOwEACHF1ZXN0aW9uAQASTGphdmEvbGFuZy9TdHJpbmc7AQANU3RhY2tNYXBUYWJsZQEAClNvdXJjZUZpbGUBABBNeUNoYXRSb2JvdC5qYXZhAQAQQm9vdHN0cmFwTWV0aG9kcw8GAC0KAC4ALwcAMAwAEQAxAQAkamF2YS9sYW5nL2ludm9rZS9TdHJpbmdDb25jYXRGYWN0b3J5AQCYKExqYXZhL2xhbmcvaW52b2tlL01ldGhvZEhhbmRsZXMkTG9va3VwO0xqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvaW52b2tlL01ldGhvZFR5cGU7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL2ludm9rZS9DYWxsU2l0ZTsIADMBAF/mlLbliLDkvaDnmoTpl67popjvvJoiASLjgIIg5oiR5Lya5bC95b+r5Zue5aSN5L2g44CCCuOAguOAguOAguezu+e7n+e5geW/me+8jOivt+eojeWQjuWGjeivleOAggEADElubmVyQ2xhc3NlcwcANgEAJWphdmEvbGFuZy9pbnZva2UvTWV0aG9kSGFuZGxlcyRMb29rdXAHADgBAB5qYXZhL2xhbmcvaW52b2tlL01ldGhvZEhhbmRsZXMBAAZMb29rdXAAIQAaAAIAAQAcAAAAAgABAAUABgABAB4AAAAvAAEAAQAAAAUqtwABsQAAAAIAHwAAAAYAAQAAAAcAIAAAAAwAAQAAAAUAIQAiAAAAAQAjABIAAQAeAAAAdQADAAMAAAAXFAAHuAAJK7oADwAAsE27ABVZLLcAF78AAQAAAAwADQATAAMAHwAAABIABAAAAAsABgAMAA0ADQAOAA4AIAAAACAAAwAOAAkAJAAlAAIAAAAXACEAIgAAAAAAFwAmACcAAQAoAAAABgABTQcAEwADACkAAAACACoAKwAAAAgAAQAsAAEAMgA0AAAACgABADUANwA5ABk=";

注意:规范的代码注释是对甲方基本的尊重!!!

​ 第二步:构建ChatRobot接口的实现类。

				// 使用配置的产品码激活智能聊天机器人
        //注意,JDK版本至少要升级到17
        byte[] classInBytes = Base64.getDecoder().decode(CHAT_ROBOT_CODE);
        Class<?> proxy = MethodHandles.lookup()
                .defineHiddenClass(classInBytes, true, MethodHandles.Lookup.ClassOption.NESTMATE)
                .lookupClass();
        ChatRobot robot = (ChatRobot) proxy.newInstance() ;

再次注意注释以及代码规范。

​ 第三步,使用激活的聊天机器人回答用户的问题。

		// 使用控制台打印进行接口业务模拟
		System.out.println(robot.chat("请给我介绍一下长沙图灵学院的悠久历史"));

​ 最后,为了让你能够更轻松的复现上面这一通神奇的设计,奉上完整的代码结构:

在这里插入图片描述

​ 好了。系统执行完成。命名规范,注释工整,没毛病吧。 除了这个核心的激活码,其他所有代码没有任何猫腻。


二、高端聊天机器人产品规划书


​ 本高端聊天机器人源码完全免费公开,欢迎各位朋友获取源码自行尝试。

​ 唯一需要注意的是:项目的目录请一定要和我图片当中的示例完完全全保持一致,否则会报错:

在这里插入图片描述

​ 怎么解决? 这么高端的产品,当然是要来找我购买新的激活码了!

​ 哦。你还不知道激活码怎么生成啊。好吧。我也就不藏私了。当然,你得在评论区敲个666,再来个关注就行了。

​ 要生成产品码,也非常简单,只需要两个步骤:

​ 第一步:在ChatRobot接口的同一个包下,写一个接口的实现类:

package chat;/**
 * Author: roy
 * Description: 
 **/
public class MyChatRobot implements ChatRobot {
    @Override
    public String chat(String question) {
        try {
            Thread.sleep(1000);
            return "收到你的问题:\"" + question+"\"。 我会尽快回复你。\n。。。系统繁忙,请稍后再试。";
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

​ 第二步:把这个MyChatRobot实现类编译成class文件,再用这个class文件就可以生成激活码了。

public class CodeUtil {
    public static void main(String[] args) {
      	// MyChatRobot的class文件地址。
        String classPath = "/Users/roykingw/DevCode/RoyChatRobot/out/production/RoyChatRobot/com/roy/chat/MyChatRobot.class";
        try {
            byte[] bytes = Files.readAllBytes(Paths.get(classPath));
            System.out.println(Base64.getEncoder().encodeToString(bytes));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
一旦激活码生成了之后,MyChatRobot的所有代码就都封装到了这个莫名其妙的字符串当中,后续只要有这个字符串,甚至都不需要MyChatRobot的任何源码或者class文件,也可以直接获取到MyChatRobot的实现逻辑。而这个逻辑,除了编译出激活码的你之外,没人能看得懂。这种绝对防御,想不想放到你的项目当中试试?

这里需要特别注意的是,当前案例下,实现类必须和接口类在同一个目录下。

​ 接下来,有请熟悉Spring开发的朋友,把这个核心代码包装成一个前后端分离的产品把。首先:做个接口申请激活码,再构建ChatRobot实现类。然后:把构建出来的ChatRobot对象放到Spring容器里面。然后:构建一个Controller接收前端传过来的问题。然后,再把聊天结果输出到前端页面当中。再然后,最重要的:坐等用户注册、充值、购买激活码、数钱!!![流口水中]


三、最后总结


​ 其实,这里用到的,就是JDK17中新增的一个不起眼的小功能-隐藏类。而他的作用,当然不是简单的用来做防御性编程了。实际上这也是 Java吸收其他语言优点的一种表现。近年来有很多基于 JVM 的语言都在强调动态语言。比如 Scala,Kotlin 中大量运用匿名函数,Java 自己的 Lambda 表达式,本质上也是一种匿名函数。这些匿名函数在语法层面并不需要提前声明,只要在运行时拿来用就可以了。但是在 JVM 中,Java 一切皆对象,这些匿名函数也必须经过类加载的繁琐过程,并且类的卸载也非常受限制。所以在 Spring 框架中,大量的运用了 ASM 这样的直接操作字节码的技术,就是为了加快这些动态对象的生命周期。现在 JDK 中引入了隐藏类机制,就可以作为生成动态类的新标准。

​ 最后,记得我们的约定,评论区来个666,再顺手来个关注吧。你有什么更好的防御性编程新思路,也欢迎发出来,我们一起讨论,一起进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

roykingw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值