试了下,代码写的越来越慢了嗯。。。看来1.5小时对我来说确实很紧张。。。这速度要是去面试估计是被刷死的节奏吧。

2014-01-07 21:43:20 +08:00
 raincious
嗯,事由是楼主之前看了@!dexter的帖子,https://www.v2ex.com/t/95335,求PHP招聘什么的。 @!Sunyanzi 在里面说到做个Blog什么的,顺便实现个权限系统。然后 @!Ever 说1.5小时嗯,算算看面试也差不多这时间。

楼主一想,嗯?我最近不是要做这个么。。于是就想用这个机会去试试看嗯,心里想的很简单很简单,转换一个数组嘛,太简单了哇哈哈。。

我的需求是这样的:

权限储存在一个多维数组中。就像这样:

https://gist.github.com/raincious/8299003

true==允许,false==不允许

然后需要将这个数组Shadow出一份存成平坦数组,用来做权限比较,以及输出给模板做权限判断什么的。这就需要将上面的例子变成。

array(
'setting.general' => false,
.....
'user.banned' => false,
);

同时还要允许变更其中的权限,因为用户组和用户可能会使用不同的权限之类。

需求定下来之后,心想,哇勒格X,这是小学生都会的嘛,给我15分钟搞定嗯~

于是欢快的打开了Sublime……





四小时后。。。





我已经不知道用啥心情写代码了,发现即使这么简单的模块也是坑巨多啊。

很明显的比如,其实光有'setting.general','setting.register'这些项是不够的,你还得有'setting'这个根项来判断用户是不是有权限访问下面的子项,否则输出给模板之后仍然得多次判断('setting.general' || 'setting.register' || ....)来确定用户是否能访问某个页面,以便显示或隐藏对应链接。

补好了上面的坑,发现这简直就是更大坑的入口。。。比如权限修改之后需要动态维护上面的关系。。。。



当然,好像我把事情给弄复杂了恩。。。

不过好在搞出了一个实(Bu)验(An)性(Quan)的模块,时间也没白浪费嗯。。。

实现的功能包括:
* 转换多维权限表到分级的平坦表。
* 可以导出权限以便保存。

代码:https://github.com/raincious/could



== 重点来了 ==

说到这里,楼主开始担心如果去其他公司面试,到时给来一题Blog,我自己就把自己坑不知道哪儿了。

所以,想问问有面试经验的,如果你是面试官,遇到我这样写程序的,请问你还要我么?
5027 次点击
所在节点    程序员
9 条回复
cxe2v
2014-01-07 22:50:11 +08:00
看你最后对你自己的坑有些什么想法,如果能清楚认识到一些关键坑,还是会收下你的
zts1993
2014-01-07 22:51:33 +08:00
php的嘛。

rbac之前做过,一个把权限写在数据库中的~~

说真的如果之前没有研究过权限控制的话还行吧、
raincious
2014-01-07 23:07:11 +08:00
@zts1993 其实这不是权限控制嗯。只是权限控制的一个模块功能。具体的东西涉及到会话、用户、数据库、然后才是这个用来将权限数据真正利用起来的小模块。

之前的东西我都写好了,今天写完最后这个模块我就可以继续慢慢实现我的项目了。

只是没想到本来准备好小写一下的东西竟然是这么大的坑罢了,看来以后安排需求什么的得小心了。
otakustay
2014-01-08 01:10:08 +08:00
暴力法,每次权限变更后全部重新生成一遍就完了
如果只是文中描述的功能外加后面的2个坑,如果我是面试官,普通的校招这题我最多给1小时,社招最多给半小时……
另外我建议设计成permission.has('setting.general')这种方法形式,这样根本不用转数组,转数组你还要考虑变更时的同步,不转每次都运算一下,顶多加个缓存层一有变更就清掉缓存,效果好多了,还方便后人有需求的时候重写你的has方法不至于一个属性绑死没法改
Ryannnnnnn
2014-01-08 06:29:23 +08:00
看了一下lz代码
1.同@otakustay的想法,不一定需要转flat,而且它大概不需要缓存我觉得(基本没效率提升)。。
2.维护的话,大概就是raw是master用来写,flat是slave用来读,然后设个dirty bit,初始是true,每次想读的时候查查dirty bit...读时生成可以省掉你每次写`$this->makeFlattenLink`
3.对于`setting`这样的根项,大概可以直接在setting底下挂个项来表示其权限,比如`setting.permission`之类的,在修改的时候可以去给它赋值。不过这个看着不美观,无视吧。
raincious
2014-01-08 13:10:23 +08:00
@otakustay
@Ryannnnnnn

感谢审阅。

好吧,其实我这样写也是有缘由的。因为一个用户的权限需要同 用户权限 + 用户组权限 + 角色权限 混合。系统中的每一个模块都有独立的权限设定。权限系统根据用户的ID、所在的用户组ID以及角色ID决定用户应该有什么样的权限。这样可以最大灵活的决定一个用户最终能够进行怎样的操作。

关于权限缓存,我确实是有计划做的。简单权限可以根据一定的时间更新数据库中的权限缓存表,这样也就不需要每次都跑递归了。而且这样做结构上也更加简单。

转换成Flat也就是为了性能。转换好之后导出,之后就能用true/false比较来进行权限判断了。而且由于权限表模板的存在,可以很大程度上避免变量未初始化的问题,这样对之后前端模板操作也有很大简化(不需要isset了嗯)。

所以嗯,我慢慢研究has的方式,目前就先用自己这个好了。花了这么多时间写出来的模块,不用怪可惜的嗯。。。
Sunyanzi
2014-01-08 22:18:55 +08:00
Nice try ... 至少能够有想要动手试试看的这个想法 ...

这已经比那些看完我的发言转过脸就忘掉的人让我感动多了 ...

不过感动归感动 ... 在这里我还是要不请自来的指出一些你的问题 ... 如有冒犯还望包涵 ...

其一 ... 两个字 ... 也是最重要的事情 ... 审题 ...

首先我说了我要你实现的是一个 Simple Blog ... 不是写一个 WordPress 的替代品 ...

换言之 ... 假如在你面试的时候我要求你上机在很短时间内完成一个成熟的商业作品 ...

你大可以键盘都不碰扭头就走 ...

因为这不可能 ... 能提出这种需求说明我一定是个外行 ... 你的时间不值得浪费在这里 ...

我的题目简单到一目了然 ... 没有任何长篇大论的文档只有两个单词 ...

Simple 说明了项目规格 ... Blog 说明了项目类型 ... 一言以蔽之就是一个不太复杂的博客系统 ...

仅此而已 ... 题目中并未涉及权限系统 ... 而你的切入点直接就是权限系统 ...

题目涉及了不太复杂 ... 而你的权限系统从诞生起就很复杂 ... 这很奇怪 ...

这直接引出了你的第二个问题 ... 没有一个良好的自我认知 ...

这里我们不得不谈的就是时间 ...

不管你在面试也好 ... 真正入职之后也罢 ... 时间都是有限的 ...

你承诺要完成的每一个功能都要在其对应的 deadline 之前完成 ... 这是立世之本 ...

面试只是对你的第一次考量 ... 短短的时间内 ... 你必须让我看到一个 Blog ...

不要求完善 ... 不要求功能有多么全 ... 只要求两点 ... 它必须是个 Blog ... 它必须安全 ...

而你在一开始就给自己定了一个很宏伟的目标 ... 准备要做出个闪亮的作品当场把我震了 ...

这个出发点很好 ... 只是很可惜你并没有那么快的开发速度 ... 这就叫心比天高 ... 命比纸薄 ...

根本原因是你自己没有一个概念在规定时间内能完成什么 ...

想得很好 ... 做得很少 ... 一点都不得力 ... 得到这样一个驴唇不对马嘴的结果也是理所当然 ...

我知道这么说你可能有意见 ... 这样 ... 你想象一个场景 ...

公司说一周之后有几百万的广告投放 ... 你要做一个活动出来留住这些撞进来的用户 ...

一周后你写出了一个前无古人后无来者的巨匠级 ORM ... 放上 Github 瞬间破千 fork 那种 ...

但你把大量的时间花在这个工具上 ... 活动没出来 ... 用户留不住 ... 几百万就水漂了 ...

提出需求的人不会关心你写了什么 ... 规定日子活动没出来 ... 你就不用再来上班了 ...

虽然实际上有项目管理所以这种事情不会发生 ... 但脱离项目管理之后你自己能够管理自己么 ..?

我要的 Blog 呢 ..? 在哪里 ..?

如果你能力足够 ... 大可以自己先做框架再做模板引擎最后让我跪在一个光芒四射的 Blog 面前 ...

但如果你是个一般人 ... 那么破题的顺序如下 ...

首先做一个 dispatcher ... 直接用判断文件然后引用并实例化即可 ... 最多不过十分钟 ...

然后做一个 DB 的封装 ... 能用 PDO 或者 MySQLi 最好 ...

最不济也要往 mysql_real_escape_string / mysql_query 外面套一层 ... 最多一刻钟 ...

有闲工夫再做个模板引擎 ... 直接 require php 的那种 ... 逻辑都内嵌 ... 最多不过五分钟 ...

半小时之内 ... 完成了所有需要的功能 ... 我至少会知道你对面向对象和 MVC 的使用习惯 ...

然后建表写逻辑 ... 最简单的 ... 一个展示一个发布 ... 这些有一刻钟够了吧 ...

如果你觉得我上面说的这些都还是太难 ... 你做不到 ... 也没关系 ...

直接面向过程 ... 把代码和模板掺杂在一起 ...

一开始什么都不管 ... 上手就建表然后开始写 new.php ...

内容就是显示表单或者直连数据库插记录 ... 然后做个 index.php 把内容读出来 ...

我要是提前来看 ... 至少这两种方式都可以让我看到项目在向着正确的方向发展 ...

基本上最慢最慢这两个功能一个小时也完成了 ... 时间还剩不少 ... 做权限系统 ...

权限系统唯一的作用 ... 控制发表文章的权限 ... 用户名和密码直接写死在文件里就好 ...

这个功能也算半小时 ... 足够了吧 ..?

一个半小时 ... 虽然结构上丑陋无比 ... 但我至少看到了一个可用的 Blog ... 能写能看 ...

如果时间更长一些或者你手更快一些 ... 继续做编辑和删除 ... 能删能改 ...

这些功能完成 ... 你的代码就已经是一个能交作业的 Simple Blog 了 ...

我在接下来的任何时间中止你的开发都不会影响已经成型的系统 ...

唯一的区别只是如果我给你多一些时间可能会有评论功能 ... 修改设置功能 ... 静态化等等 ...

而事实上这些都不用写 ... 只要讲给我听 ... 说说你想怎么做这些功能就好了 ...

顺便再抱怨一下时间不够不然可以写得更漂亮一类的 ... 我想要的 ... 是这样的结果 ...

上机的部分终归只是面试的一部分 ... 你面试时写的代码永远不会有机会上生产环境 ...

关键点还是在考核你的综合实力 ... 包括程序思想的实际应用 ... 时间的把控等等 ...

力臻完美不是坏事 ...

我作为一只无比拧巴的完美主义天蝎看到你的变量命名和注释就能明白你的想法 ...

但公司不是你家开的 ... 有些时候 ... 往往需要牺牲自己的品位去迎合需求 ...

至于你最关心的那个问题 ... 我们还是来假设一个场景吧 ...

你下午一点半的时候面试 ... 简单的寒暄和过场之后两点整我给你需求让你上机 ...

然后我回去忙我的 ... 一下午没抽开身 ... 就这样四个小时过去 ... 六点钟天黑了大家下班 ...

于是我过去看你 ... 结果发现你写出了 could.php ... 你觉得我会是怎样的心情 ..?

虽然现实中这种情况不太会发生 ... 如果我中途跑过去看你会直接说上面的话把你引向正途 ...

但如果真的就发生了这种极限情况 ... 我认真的想了一下 ... 我还是会给你发 offer ...

从 could.php 里我能看出你的基础和思想 ... 薪水可以开 3 ~ 4 ... 但这并不代表你成功了 ...

在试用期内如果依然是我让你实现某个东西你非坚持要先做完另外一个再来做 ...

那么这就出离技术了 ... 这属于无法沟通的范畴 ... 罪无可恕 ...

最后 ... 我们抛开 Blog 这个事情不谈 ... 单纯从代码的角度讲 ... could.php 写的还可以 ...

但如果让我做这样的一个权限系统 ... 我一定用二进制实现 ...

先不说太多 ... 算是一个小提示吧 ... 你自己想想看如何优化你的权限系统 ..?
Sunyanzi
2014-01-08 23:01:32 +08:00
一口气写完就发了 ... 发完完自己读了一下 ... 感觉像居高临下的说教一样 ... 很讨厌呀 ...

嘛 ... 对不起对不起 ... 我也不知道怎么回事写着写着就变成这样了 ...

如果有的话说重了也不要太往心里去 ... 我想我大概是在凶过去的自己 ...

我曾经是一个很严重的拖延症患者 ... 再加上我有非常扭曲的完美主义倾向 ...

这两点导致我吃了很多很多亏 ... 惨痛的程度和造成的影响应该远远超出你的想象 ...

后来被捡走做了管理 ... 眼界也放宽了 ... 再加上年纪渐长 ... 吃亏也算吃出经验了 ...

这些因素纠缠在一起才慢慢板过来 ...

总觉得不想看到你走我走过的弯路 ... 如何驾驭时间是一门大学问 ... 希望你会认真对待 ...

字写得挺乱的错了俩地方 ... 顺便勘误吧 ...

Line 63 ... 「直接判断文件然后引用并实例化即可」 ...

Line 71 ... 「我至少会知道你对面向对象的理解和 MVC 的使用习惯」 ...
raincious
2014-01-08 23:52:42 +08:00
@Sunyanzi 嗯。。。。那个。。。好。。多。。字。。。

是这样的。。。

我原来计划很短时间就能完成的权限容器(一小时足以),被拖到了四小时,感觉这样太慢了。心理落差就出现了。。。

现在想想是一开始策划模块的时候出的问题嗯。代码没有规划好,造成了一些本来不存在的问题嗯。

当然也怪我没说明白嗯。。。。这个东西确实是要用在一个(自以为)很宏大的东西上的。。。。所以我才花了时间把它做完嗯,也不完全就为了写个分级权限来玩(而是来用嗯,这算是最后一个基础模块了),否则会给自己一个简单的模块用用拉倒。。。

不过话说,你说的问题。。。。我还真有。。。。不过还好都发生在自己的项目上。。。公司的项目如果deadline来了。。。我也不管三七二十一直接拿现成的或者拿手的来用了,而不是研究新方法什么的。

另。。每行字符数好准。。。

另。。。嗯。。二进制的话,我估计到时候模板上判断就麻烦了,于是才不去用的嗯,否则HTML预备文件里一堆|&^,前端估计要疯了。目前这个。。看似更易读嗯。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/96066

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX