共计 3709 个字符,预计需要花费 10 分钟才能阅读完成。
引言
华软第二版开发以来,要么在开发 JNA
调用 C++
的功能,要么在学习 RealVNC
的文档,要么在 Github
上看别人的 VNC
客户端代码。
一直在看第三方的代码,我的内心是崩溃的。
今天我来教教大家,如何让程序员崩溃。
令人崩溃的操作
if
十八层地狱
这是 JNA
的源码,我想问问,大家什么感受?
当然,这个还算逻辑简单的,如果逻辑复杂套 18
层if
,爽不爽?
public static int getNativeSize(Class<?> cls) {if (NativeMapped.class.isAssignableFrom(cls)) {cls = NativeMappedConverter.getInstance(cls).nativeType();}
if (cls != Boolean.TYPE && cls != Boolean.class) {if (cls != Byte.TYPE && cls != Byte.class) {if (cls != Short.TYPE && cls != Short.class) {if (cls != Character.TYPE && cls != Character.class) {if (cls != Integer.TYPE && cls != Integer.class) {if (cls != Long.TYPE && cls != Long.class) {if (cls != Float.TYPE && cls != Float.class) {if (cls != Double.TYPE && cls != Double.class) {if (Structure.class.isAssignableFrom(cls)) {return ByValue.class.isAssignableFrom(cls) ? Structure.size(cls) : POINTER_SIZE;
} else if (!Pointer.class.isAssignableFrom(cls) && (!Platform.HAS_BUFFERS || !Native.Buffers.isBuffer(cls)) && !Callback.class.isAssignableFrom(cls) && String.class != cls && WString.class != cls) {throw new IllegalArgumentException("Native size for type \"" + cls.getName() + "\" is unknown");
} else {return POINTER_SIZE;}
} else {return 8;}
} else {return 4;}
} else {return 8;}
} else {return 4;}
} else {return WCHAR_SIZE;}
} else {return 2;}
} else {return 1;}
} else {return 4;}
}
如果是我写这个方法,我会这样写:
这也是我一直推崇的编码风格,if
判断终止条件,正常情况再执行到最后,这样会减少嵌套。同样都是实现功能,为什么不把代码写得友好一点,让别人少骂两句呢?
public static int getNativeSize(Class<?> cls) {if (NativeMapped.class.isAssignableFrom(cls)) {cls = NativeMappedConverter.getInstance(cls).nativeType();}
if (cls == Boolean.TYPE || cls == Boolean.class) {return 4;}
if (cls == Byte.TYPE || cls == Byte.class) {return 1;}
if (cls == Short.TYPE || cls == Short.class) {return 2;}
if (cls == Character.TYPE || cls == Character.class) {return WCHAR_SIZE;}
if (cls == Integer.TYPE || cls == Integer.class) {return 4;}
if (cls == Long.TYPE || cls == Long.class) {return 8;}
if (cls == Float.TYPE || cls == Float.class) {return 4;}
if (cls == Double.TYPE || cls == Double.class) {return 8;}
if (Structure.class.isAssignableFrom(cls)) {return ByValue.class.isAssignableFrom(cls) ? Structure.size(cls) : POINTER_SIZE;
} else if (!Pointer.class.isAssignableFrom(cls) && (!Platform.HAS_BUFFERS || !Native.Buffers.isBuffer(cls)) && !Callback.class.isAssignableFrom(cls) && String.class != cls && WString.class != cls) {throw new IllegalArgumentException("Native size for type \"" + cls.getName() + "\" is unknown");
} else {return POINTER_SIZE;}
}
不健全的文档
从 JNA
获取系统状态信息,照着头文件开始拼结构体。
typedef struct {
DWORD rev;
DWORD kernel_memory_bytes;
LONGLONG disk_cache_memory_bytes;
DWORD host_online_count;
DWORD rev1;
DWORD rev2;
} PSA_SYSTEM_STATUS;
内存缓存容量:
1000010111011110101111(我获取的)100001011101(实际数据)
硬盘缓存容量:
1111001000000000000000000000000(我获取的)111100100000000000000(实际数据)
嗯?为什么我获取的数据就比实际的数据多 10
位呢?
再看看变量名,原来人家都告诉我了,kernel_memory_bytes
,单位不一样。无符号右移 10
位相当于除以 1024
,就将B
变成 KB
了。
其实在变量名声明的时候就已经告诉我单位了,但是编写结构体映射的时候,都是大致看看名字,怕自己打错,直接复制过来的,没关注着最后一个单词里还有单位。
假面向对象
这个是我当时写节点同步的时候遇到的问题。关系如下,一个节点下有多个计算机,同步的时候需要将节点和其下的所有计算机都同步过来。
设计的时候就去 api
里找同步节点的方法,EnumImageNodeFirst
、EnumImageNodeNext
。
然后天真地以为还有一个 EmunHostByImageNode
的方法,找啊找,也找不着。
后来发现该方法有一个 get_type
参数,你传什么参数,这个方法就是什么功能。
数据类型又是万恶的void *
,哪天你真把类型传错了都发现不了。
秉着写 if
不带 else
的宗旨,这样的方法我是写不出来。
没注释
我尝试学习一下 TightVNC Java Viewer
的代码,几千行代码,一条注释都没有。
对不起,打扰了。不写注释的都是牛人,惹不起惹不起。
神奇的方法名
不用我多说了吧?
百度翻译没毛病!
当然,瑕不掩瑜。还是要表扬潘佳琦的,在华软项目上贡献巨大,还有之前的选修课签到、评分都是交给他完成的。
不要怕,都能看懂
语言是用来交流的,外国人看你的英语就像你看老外的中文一样,虽然看着有点怪,但是还是能看懂的。
前天研究 VNC
的时候,需要启用 Direct TCP Connect
(TCP
直联)功能,需要传一个 add-on code
,我找了半天也不知道是啥,就拿着我六级还没过的英语就给RealVNC
官方发邮件。
Hello VNC! I'm a software developer.
I use vnc in my project. I'd like to try it myself using real vnc sdk, but i met some problems, i have to enable add on components. But i don't know the add-on code list.
I see the blog from https://www.realvnc.com/en/news/connect-devices-directly-instead-using-vnc-cloud/,it suggests me to email to you to obtain an add-on code.
Sincerely, Thank you very much!
官方也很认真地回复了我,解决了我的问题,很开心。但是最后因为这个软件太贵了,用不起正版,还是决定改用其它方式。
总结
-
if
多判断终止条件,减少嵌套。 - 用别人的代码难就难在你需要先去学习其思想,所以,请友好一些。
- 方法名尽量起得符合场景。
- 我们的英语其实都可以,不用怕,我们都可以和外国人交流。