让程序员崩溃的瞬间

28次阅读

共计 3709 个字符,预计需要花费 10 分钟才能阅读完成。

引言

华软第二版开发以来,要么在开发 JNA 调用 C++ 的功能,要么在学习 RealVNC 的文档,要么在 Github 上看别人的 VNC 客户端代码。

一直在看第三方的代码,我的内心是崩溃的。

今天我来教教大家,如何让程序员崩溃。

令人崩溃的操作

if十八层地狱

这是 JNA 的源码,我想问问,大家什么感受?

当然,这个还算逻辑简单的,如果逻辑复杂套 18if,爽不爽?

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 里找同步节点的方法,EnumImageNodeFirstEnumImageNodeNext

然后天真地以为还有一个 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!

官方也很认真地回复了我,解决了我的问题,很开心。但是最后因为这个软件太贵了,用不起正版,还是决定改用其它方式。

总结

  1. if多判断终止条件,减少嵌套。
  2. 用别人的代码难就难在你需要先去学习其思想,所以,请友好一些。
  3. 方法名尽量起得符合场景。
  4. 我们的英语其实都可以,不用怕,我们都可以和外国人交流。

正文完
 0