V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  FrankHB  ›  全部回复第 32 页 / 共 92 页
回复总数  1830
1 ... 28  29  30  31  32  33  34  35  36  37 ... 92  
2020-02-25 13:02:13 +08:00
回复了 mlgmxyysd 创建的主题 Android 浅谈 Xposed 新概念 [模块作用域]
@mlgmxyysd 兼容的问题,我理解的现状是没法排除风险(操作不当极端可能变砖,虽然不算直接是框架的原因)。
技术上,这也不是单一框架能决定的东西(验证其它框架的侵入式修改不存在冲突,在计算复杂度上就不切实际)。
因为许可证的 AS-IS/NO WARRANTY 条款,这里的后果是没法有谁兜底的。
所以我至少想还要一个全局的非担保性描述:在不排除多个框架的影响的前提下,框架的开发者如何提示风险来明确界定到底某种共存的用法算不算是受到支持地兼容?
缩进乱了……算了还是转 md 吧: https://gist.github.com/FrankHB/11d3d3e2fdab0bc773c2ece954c641aa
@ishowman 实现上我很难给出精确的具体标准。
但对适合“项目”维护和运营的基准,首先可以有一些普适的基本原则。
评价工具的理想程度,可以通过作为项目的主要产出而间接地适用。

* 尊重用户。
* 明确服务的对象和应该解决的问题。不要让非目标用户浪费时间去了解本不需要解决的问题。
* 预测并权衡新用户和已有用户的冲突。避免突然改变目的。
* 尊重用户对自身需求的理解。避免让用户无原则地变蠢。
* 支持用户选择的自由。如果可能,遵循公开的惯例,包括公开的技术规范和事实标准。避免不必要的路径依赖(尤其是 vendor lock-in )。
* 避免介入用户的主观立场。避免制造无谓的社区争端。
* 从设计开始,做正确的事( MIT approach )。
* 在可行的前提下,明确设计的正确性先于简单性。正确性蕴含完整性和一致性。
* 设计者应当为设计决策承担风险和失败后果。避免归咎错误的选择到用户。
* 设计者应当明确清楚,有些东西是妥协,即便被忍受,从用户反馈上一时看不出来,也迟早需要改进。
* 设计者应当清楚形势。避免缺乏技术理由支撑的主观阵营判断。避免以一时的市场占有、流行趋势和垄断地位来提升项目和项目产出的质量的评价。
* 设计和实现者应当在用户接口以下层次的实现上同等重视地保持质量。注意,这不只是技术问题,因为一般意义上,开发者和维护者也是用户。越是有生命力的项目的可维护性越重要的,特别是对有能力定制和二次开发的用户而言, 金玉其外败絮其中是最浪费的做法。

基于这些原则,能衍生一些稍加具体的理想目标:

* 尊重变化的自由。在明确需求的前提下,尽可能保证对现状按需进行改变的可行性和便利性。
* 避免不必要付出的代价。尽可能消除对满足需求无意义的代价,减少影响需求实现的整体成本。
* 最小接口原则。(最小特权原则、最小依赖原则、……)
* 关注点分离原则。……
* 避免抽象泄漏。……
* ……

注意,不理想并非是指不符合用户预期。不经过具体分析,很难说用户看到的非预期情况就一定算得上不理想——可能是用户自己偶然没用对,而不能算到工具的问题。
但追溯原因仍然是困难的。
而说到底,为什么难以直接界定什么是理想的工具?不说界定什么叫理想的困难,光是因为“不理想”的情况太多,就足够成为障碍。
反过来,从现有的不理想属性来推断,倒是容易一些。根本问题总是能归结到缺少对原则的一贯遵循,虽然具体原因有多个(违反了多条原则)。不过这也只是相对容易一点。

这类不理想属性中,比较容易分析的是实现可用性缺陷。例如,一个工具用起来被用户发现内存占用太高了而用不了。可能有这样几个原因:

* 因为已知的技术限制,这个工具在这个场景下确实就应该用那么高的内存,否则根本不可行。但设计者没有成功让用户注意到最小的资源配置。
* 实际上内存就不应该占用那么多(没有可行性问题),这就是产品缺陷。造成这样的缺陷的原因有……
* 可能设计的质量太差,因为设计者根本就没考虑有这个问题,或者没能力在设计中解决这个问题。
* 可能有总体设计,但详细设计选型太差,实现效果不好。
* 可能设计预期使用某种优化方案,但实现根本没用上。
* 可能有正确的设计,也都实现了,但是单纯实现得太蠢。
* 可能设计和实现都是符合预期的,但测试不充分,刚好就在这个场景下不可预测地那么差,也没有变通。
* 可能什么都能做对,但就是来不及做,先赶鸭子上架交付原型再说。
* ……

可以看到即便对这样的具体问题,也需要根据具体情况调整应对,都没有万能的做法来避免重蹈覆辙。

需求决策上的问题则远远更难,因为很可能涉及不同用户群体之间的博弈和对有限资源的争用。

如果所有原则性的选择都根本做对了,不管是容易分析的问题,还是更困难的问题,翻车的可能性都会大大减少。
想要总体上理想,不可能靠枚举避免不理想的情况,头痛医头脚痛医脚地回避原则问题。方法论上这里就没有其它可行的选择。

就这里之前讨论的问题举例讲,“是否依赖浏览器”是需求决策和实现策略的混合问题。(是否依赖浏览器的决策已经影响到筛选最终用户群体了。)
不过,在实现的意义上,浏览器具有的恶劣质量名声在外,想要辨明风险反倒不那么困难了——凡是能不用浏览器容易实现却还是用浏览器实现了的供单用户使用的工具,通常不会好到哪去,太容易找到只会在浏览器上发现的毛病,离“理想”总是差得远。

这样的毛病具体有很多:

* 要求用户具有打开浏览器使用一般应用的习惯,不管这样的应用是否在逻辑和实现质量上都和浏览器匹配得够好。
* 运行时用户体验问题。
* 不必要的资源占用,以及因此导致的延迟问题。
* 冷启动慢。
* 即便原则上可以跨平台,仍然不能避免兼容性问题。开发者可以减少兼容性问题,但一般会让作为非开发者的用户更麻烦。
* 考虑到用户没有浏览器的情形,部署方案会更复杂。

有的用户可能不在乎这些毛病,但不是所有的用户都乐意接受。(至少用户体验的问题很难被无视。)这是筛选用户的直接表现。

光是因为一些技术演进上原因,浏览器可用性差在可预见的未来就会是业界共识。除非你是能改变技术困难现状的业界大手子,最好不要去指望这个状况容易变化。

至于为啥有时候明明不需要用浏览器实现的方案,用浏览器看起来为啥好用呢……说来惭愧,主要真是因为友商衬托。
现代浏览器本身就是一个复杂的本机运行时解决方案——类比 Emacs 是 ELisp 运行时,基本上浏览器就是个捆绑了一大票专有扩展的 JS 运行时。
而其它本机框架虽然可能根本上更正确(例如,不强行钦定一个要求 GC 的运行时而本质上更适合强调响应的 GUI 程序),因为投入的资源的关系,实现的质量未必有浏览器好,效果可能也真不咋地。
(这个意义上我要再次 diss 各大浏览器厂商。明明它们有这个资源和经验做得更好——至少能出个不捆绑只适合当浏览器的扩展的运行时——却非得在毒害业界生态半吊子的复杂方案上走得越来越远,也是醉了。)
还有,一人项目还好说,否则从开发商和运营的角度,你会不得不考虑是不是找得到开发者……
开发基于浏览器的应用使用的技术栈本身就相当具有 vendor lockin 的风险,浏览器应用越流行,其它方案的开发资源选择余地就越小。(具体来讲,现在找桌面开发者都很麻烦了。这当然不能都说是 Web 开发的问题,但开发浏览器应用会让这里更加麻烦。)
既然浏览器不可能面面俱到到取代其它技术(搞得再复杂,想当操作系统仍然是做梦),这对整个市场就是有害的。
2020-02-25 11:04:32 +08:00
回复了 uechris 创建的主题 程序员 为什么挖矿脚本人人喊打?
Firefox 这种扯虎皮拉大旗的姿势比起 RMS 就是弟弟。
页面内嵌挖矿脚本跟隐私无关,而是侵犯用户知情和选择的权利,以此为基础剥夺用户的计算资源。实际上,这不是偷,而是抢,即便许多用户对自己的计算资源被抢持续保持得稀里糊涂;不论如何在用户体验上粉饰,都不应该减弱其危害的定性。
(当然,前提是真的只是挖矿脚本。)
2020-02-22 13:42:27 +08:00
回复了 hua123s 创建的主题 C++ C++ 疑惑
@hua123s 首先清楚大多数 C++ 用户不应该直接使用 new 和 delete 就够了。
具体原因么……替代的东西多了去了,没必要用;正常都是直接创建对象或者带所有权的智能指针( std::unique_ptr 和 std::shared_ptr )+不带所有权的引用 /视图( std::reference_wrapper/observer_ptr/string_view/span/...)。
两者的区别是,前者是非常底层的东西,必须自觉才能保证 no resource leak,并且还得小心才能保证 basic exception safety ;后者只要实现对(不滥用前者)默认就不会有这个问题。这种基本的 invariant guarantee 是在任何程序设计中都应当是普遍的重要的默认应该保持的东西,只不过不少语言根本不提供像 new 和 delete 这种依赖自觉不手贱才能维护 invariant 的危险操作,才让你看不出来这种保证的重要性。
要是几十年前古董代码用户水平又不够只会 new/delete 还能理解,现在正常情况一般代码根本不应该直接用这种底层而危险的东西。就算 new/delete 用对了不会导致功能问题,出现 new 而不能保证排除漏 delete 这种会导致最终用户直接受到影响(资源泄漏)的 invariant breakage,放任这种代码导致每个出现 new 的地方都要人肉找一遍 delete (因为这方面工具不保证完全靠谱)才能最终确保正确,这直接就是可维护性灾难。所以正常的 code review 就不应该放过这种低级问题,应用代码看到 new 和 delete 就直接回炉重造基本不会有错。
需要打死的还有一个理由是因为历史原因这方面实践普遍比较差,所以替代虽然理由应该明确,风格上也很混乱。很多大的项目可能自己有一套 API 做专门的封装。相比之下 Rust 就没 C++ 那么糟烂(但是也并不容易上手)。

另外不是给你看的,不过也算是基础内容(虽然大多数 C++ 用户这方面基础完全不合格,麻烦知耻):
1. new 不一定从 heap 上分配。new 底层实现的 operator new 作为 allocation function 且没被用户自定义时,分配的是 free store,而 heap 是 free store 在 hosted implementations 的一种普遍实现。这不是必要的。
2. 标准库提供默认的 placement new 就不分配。与此相对应该注意不遗漏是析构函数调用语法(……以及 std::launder 什么乱七八糟的),而不是 delete ; placement delete 仅在异常时被调用。
2020-02-22 13:22:49 +08:00
回复了 neurocomputing 创建的主题 云计算 云游戏有出路吗?
有也不是现在,基础设施普遍跟不上。
相关的另一个问题今天刚好在另一个主题里用过:
www.gnu.org/philosophy/who-does-that-server-really-serve.en.html
云游戏这方面问题并不算十分突出,但也显然不会利好。
等基础设施跟上来了,软件应该也会跟上,真成熟的情况下配置选择的余地会更多。大趋势应该是 IaaS/PaaS > SaaS。云游戏这种细分领域用户口味又难调和的市场终端解决方案想要大众化很难,公共设施就会容易点。
2020-02-22 13:07:48 +08:00
回复了 23571113 创建的主题 C++ 如果读文件的速度比处理的快怎么办
Content-agnostic target deduplication... 没做过不清楚细节,之前找到过的也是文件系统级的。不过这种需求如果不是服务商给特别的支持,可以考虑用户侧自己把要传输的文件都压缩了,顺便也会 dedup。
恢复数据是指什么?你这备份数据的时候不会把原件给扔了吧。如果是指传输中断可以恢复进度,做日志实现事务。
当然,有些工具的确是适合服务端直接提供的,用浏览器和不用浏览器的差距因此会小一点,而更接近“理想”情况。这个意义上,直接在整个生命周期中只提供在线部署的版本,也未必不合理。
不过,这方面仍然有老生常谈,然而绝大多数用户大概还是没有思考过的问题:
https://www.gnu.org/philosophy/who-does-that-server-really-serve.en.html
简而言之,因为满足的需求的特点不同,并不是所有的工具天然地适合以在线服务的形式使用。使用在线版本替代应用,用户可能需要承担原本不必要的风险,得具体分析(像转存之类本来就要用远程资源的就是合理的,但预期结果一定要下载后才有意义的应用就未必了)。提供更多的选择原则上是好事,前提是用户有能力清楚这些选择确实是合适的。
@zhaoolee 就你实现工具的目的来说,浏览器只能说是差强人意,是实现成本上的偷懒妥协罢了。
要说理想,漏洞实在过于明显。光是一个资源占用导致可移植性限制就能让人疯掉,于是不把工具做的做够重量级,用浏览器看上去就比较浪费,对用户来说就是鸡肋。技术上这种问题很大程度可以避免,即便非要复用类似浏览器的技术实现这样的工具,需要的也不是整个浏览器,而是更灵活的运行时。更关键的是,这里的案例中纯粹的浏览器的缺陷虽然还没明显到不可接受,但又不得不承认也就当前是这样——你不负责自己维护一个浏览器的实现,就没法保证哪天突然就因为你完全不能控制的客观因素体验烂到忍不了了。这时候就不止对用户来讲是鸡肋的问题了。
很遗憾,实际主导这些问题的浏览器厂商在这里基本上是开○车……(炒肉末一桶浆糊、Mozilla 砍掉 XUL 之类。)
……理想的工具不是应该避免依赖浏览器这种玩意儿么。
2020-02-22 10:13:08 +08:00
回复了 hua123s 创建的主题 C++ C++ 疑惑
八成得把写这代码的拉过来扁一顿。
合格的 C++ 程序员最起码不应该“经常”整出来这种代码让你看到。

@neroransom LP64/ILP64/LLP64: ?
@levelworm free store: ??
[[fallthrough]];
@stephenyin @ipwx @shilyx placement new: ???
2020-02-22 08:18:30 +08:00
回复了 mightofcode 创建的主题 程序员 3 分钟让你拥有一个跟王垠一样的博客
有评论的还好意思叫 yinwang 么。。。
2020-02-22 07:49:52 +08:00
回复了 23571113 创建的主题 C++ 如果读文件的速度比处理的快怎么办
@laminux29 要先设计是没错,但设计跟编程不冲突。只要是自己的设计,本质上总是可编程的。你看来只是要强调先不去拿代码实现罢了;然而画图真的就是给没有编程能力的外行人展示用的低效方法。
(严格意义上,图是可编程的,但拿 Visio 这种本来就不是为了这个目的设计的工具的方案,还不配实用。)
2020-02-22 07:28:32 +08:00
回复了 mlgmxyysd 创建的主题 Android 浅谈 Xposed 新概念 [模块作用域]
什么商业化不商业化的,功能残废还没给源码给用户改的余地就是无能,哪来那么多废话。
是 idea 的实现更有价值还是 idea 更有价值这个依赖三观的问题暂且不论,防止手贱 /用户友好的附加功能和项目存在的意义的来源哪个更重要,奉劝某些人分清主次。
@zunceng 原文是低级(low-level) ,指的是设计有意排除“高级”的抽象特性,不一定是底层。
低级语言可能因为缺乏抽象能力而直接让人读写,但不一定只能在底层发挥作用,比如当作 transpiler 的输入。门槛高了点罢了。
虽然现在的设计似乎是彻底偏向怂到传统路线上了。
@Hoshinokozo 字节码具有可编程性,为什么不算编程语言?就因为会的人少?照这样说,汇编和机器码是不是也顺带开除出编程语言了?
更不用说 WASM 也不限一种表示,早期还有对应的高级 AST 表示了。
2020-01-15 22:00:48 +08:00
回复了 lvsemi1 创建的主题 程序员 长文件名在 Linux 上有没有解?
@lvsemi1 对普通人来讲,文件名就是文件名,只是访问文件的入口的一种。
文件名作为路径的组成部分,历史上起到的主要作用是唯一键(算上链接,在文件系统里也不唯一了,只是目录下唯一),而不是索引。键的名字上还可能有各种乱七八糟的约束……根本不适合当一般意义的标签。
文件名的本质其实就是一种元数据,只不过具有历史显著性而不方便随便扔掉——为了兼容构成路径这种 VFS 遗留 API 要求的输入才一概保留的( shell 这样的 CLI 在这个意义上也是 API ),因此很多时候相当鸡肋(特别不能指望兼容性)。而在现代文件系统内部作为键的作用,也已经被 inode 里的特定具体文件系统设计的元数据取代了。
普通用户基本不会有这些概念。作为开发者,你需要引导他们绕过坑,而不是推进坑里。不保险就跑。

至于能多坑的例子么……比如:
https://www.mercurial-scm.org/wiki/EncodingStrategy#The_.22makefile_problem.22
我就不多说脏话了(这里还好就是专坑开发者)。
1 ... 28  29  30  31  32  33  34  35  36  37 ... 92  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1082 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 37ms · UTC 18:57 · PVG 02:57 · LAX 11:57 · JFK 14:57
Developed with CodeLauncher
♥ Do have faith in what you're doing.