这是最近面试遇到的技术题目,虽然已经以失败告终,但是还是想听听大家对这样的代码的看法。
题目是这样的:
使用Python开发个命令行工具用于持久化一些个人信息(姓名、地址电话号码之类的)。支持至少两种持久话格式,其中一种为XML。然后通过两种方式显示他们(不需要使用图形界面)。不需要支持手动数据输入,可自行选择格式和测试数据。
此外还要让开发者能够简单的:1)添加其他的存储格式;2)查询当前支持的格式;3)提供其他的XML reader或writer。
要展示OO设计和设计模式知识。
这里是代码:https://github.com/popbones/CodeSample.Python.Serializer
对方的反馈:
代码太长,有点过于复杂了。建议简洁一些,例如少一些继承。避免在serializers中使用递归的__pack, __upack方法。
为了提高希望大家能给写建议。比如如何设计更好,哪里需要修改,哪里写的就是垃圾等等。
1
virusdefender 2015-07-30 09:57:27 +08:00
大致看了下代码,没看懂用户输入的是什么,能否给个例子?觉得应该没有你写的这么复杂
|
2
popbones OP @virusdefender 命令行本身来说是不需要这么复杂。但是也要能当作库使用。CLI例子: ./main.py -i xml -o json file.xml file.json
|
3
nooper 2015-07-30 10:22:00 +08:00 1
看了一些,按照TDD的思想,应该避免过多的if else 逻辑,但是if else 的判断过多会造成测试编写的困难,代码过于臃肿了,避免import * 这种,没有具体细看。
|
4
datou552211 2015-07-30 11:47:58 +08:00 via iPhone
添加格式可以使用多态来解决
|
5
ljcarsenal 2015-07-30 11:55:02 +08:00
这让你多长时间写出来?可以查资料么?感觉有点难度的样子
|
6
lilydjwg 2015-07-30 13:21:25 +08:00
文件命名好非主流啊。一般叫 src、docs、build 的,然后,build 目录是不放在仓库里的。
测试应该单独分个目录。源码文件还不少,为什么没有 setup.py 呢?也没有组织成一个 package,别人怎么安装呢?遇到模块命名冲突怎么办(反正它在我这里肯定跑不起来,因为我有个模块叫 serializer)? |
7
saber000 2015-07-30 15:24:25 +08:00 1
代码没仔细看,因为我其实没看懂题目,不过建议楼主看下django的序列化实现:
https://github.com/django/django/tree/master/django/core/serializers |
8
popbones OP @ljcarsenal 一个星期,可以查资料。不过明显不是要写通用持久化程序所以并不算很难。
@lilydjwg 因为只是个trial的小程序,所以没有搞成模块,目录也比较随便。 @datou552211 请详述 |
9
czheo 2015-07-30 22:06:52 +08:00 1
第一感觉,目录结构的问题。文件夹首字母大写不能忍。
第二感觉,I/F的设计略晦涩。感觉lz应该是有java经验,在用java思维写python。 另外有些小细节。比如 命名晦涩缺乏一致性。 https://github.com/popbones/CodeSample.Python.Serializer/blob/master/Source/main.py#L5 if key in dict是合法的python语法,不用keys()。 https://github.com/popbones/CodeSample.Python.Serializer/blob/39dc43733314ceff47d262aa1069b1778c58f9d8/Source/serialization.py#L36 |
10
czheo 2015-07-30 22:32:58 +08:00
这么个课题,lz实现的东西倒是不少,但是有over design之嫌,吃力不讨好。
这种考核考察的主要还是代码结构,代码风格和代码习惯。 |
11
popbones OP @czheo 一眼就被你看出来了,OO我确实是Java出身的。虽然这样,工作中Python也不会设计成这个样子,反而是被哪个展现OO知识的要求弄糊涂了。
你觉得Java和Python在面向对象设计方面最大的区别是什么? |
12
czheo 2015-07-31 09:52:04 +08:00 2
Java程序员往往喜欢套一堆pattern,factory啊manager啊proxy啊什么的。
然后就是过渡的继承,又是爷爷又是爸爸又是儿子,不设计一个interface就不舒服。 Java的设计思想是class是最高级公民,所有东西必须定义在class里面,对于一些task往往是过度设计的,最简单的比如print这种其他语言基本都一行可以搞定的事情,java里面要写一堆没用的东西。 python里面variable,function和class/object都是平等的,该用哪个用哪个。 比如xml/json解析其实不需要什么serializer的概念,json.load/dump, xml.load/dump就够了,当你引入serializer的概念,就应该是serializer.serialze/deserialize,而你现在写的的I/F设计有点不伦不类。 又比如python下其实很多静态的helper method没必要在某个class下面,完全可以独立成function。 再比如很多不需要object的数据结构存dict/list/tuple就够解决问题了,像你的person_data,如果将来不在getter/setter里面做validation也没有其他的method,做一个class没太多必要;相反直接存dict/list,用现成的dicttoxml,json的包encode/decode就可以解决大多数问题,也不用自己再写轮子写递归这么复杂。 Java程序员很多说辞是,我这样写以后扩张性好。但实际上更多时候其实是过度的设计大大加大了代码复杂度,降低了代码可维护性。吃多少饭用多大的碗,没必要一上来就端个脸盆吃饭。 推荐看看这个视频,stop writing classes |
13
popbones OP @czheo 感谢你的回复
我跟你的想法一样,这也是拿到这个题目最令我纠结的地方。我的第一反应是感觉没什么可写的,如果实际工作中的代码,这样的需求,我觉得连继承都不是必须的。写的过程中我就一直纠结“要展示OO设计和设计模式知识。”这个要求,自己也是觉得越写越奇怪。 你觉得对于这样的一个题目,应该什么样的设计比较能满足它的要求呢? |
14
czheo 2015-07-31 16:44:52 +08:00 1
主要还是看你的代码风格,工作中让人一眼就看的懂很重要。招聘者是在选择自己将来的同事,一看这代码理解起来就费劲,谁会愿意和这样的人共事呢?“展示“OO和设计模式又不是问你会多少pattern,而是看你是不是在合理的地方用了合理的继承和pattern,不必要的地方就不要写么。
其实,你的大的设计思路还是不错的,只是一些细节上写的繁琐了。这样的项目用一个类似Registry pattern控制用户添加的plugin的加载,顶多用个singleton控制plugin的单一实例就差不多了。其他也用不来太多的设计。 还有一个小tip,你写的serialization.py其实就是registry pattern的想法,只是你需要主动register,而其实可以通过metaclass或者是decorator做到auto registering。参考下面这个。 https://github.com/faif/python-patterns/blob/master/registry.py |