V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sillydaddy
V2EX  ›  设计

[原创]4 千字长文,对原型工具的抽象分析

  •  
  •   sillydaddy · 2021-05-12 23:52:11 +08:00 · 1861 次点击
    这是一个创建于 1324 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想法由来

    前段时间研究了一阵子原型工具,有些自己的思考,想分享给大家。主要从抽象的角度研究一下:原型是什么?原型工具的能力边界在哪里?

    对于原型工具,每个人都会有自己的具体印象。但在这里,我想对原型工具作一番抽象的分析,然后希望,

    • 能解答上面的 2 个问题:原型是什么?原型工具的能力边界在哪里?
    • 可以将抽象出来的概念,投射到市面上的原型工具,发现其优点和不足
    • 进而能针对自己的需要,选择适合自己的原型工具

    原型的抽象

    原型用于展示产品的界面和交互,要素有 2 个,用户的操作(触发),不同的界面显示(状态切换)。

    所以,我对原型工具的抽象就是:触发+状态切换。

    这个抽象太普通了。不过你应该很难找出哪个原型不符合这个定义。

    但定义太抽象也有坏处,比如,真实的产品也符合“触发+状态切换”的抽象。那么真实产品也要算作原型吗?按直觉肯定不行。原型和产品应该是有一条分界线的。

    所以在这个抽象定义里面,还要加上一些条件,用来区分原型和产品。加什么呢?

    我考虑的是从制作原型的工具入手,给它加 2 个条件

    1. 不能引入编程
    2. 制作原型时,所需的元素数量与操作的数量,需要是线性增长的,不能组合爆炸

    第 2 条容易让人疑惑,先解释一下。它具体指的是原型包含的页面的数量、页面中显示元素的数量、元素属性的数量、制作过程作出的一些操作数量等等。这些数量一旦呈现爆炸性增长,工具本身也没法用了。

    这 2 条限制看起来很普通很符合直觉,让人没有啥可说的。所以,我就要下定义啦:

    原型的抽象就是,“触发+状态切换”,要求它可以被加了上述 2 个限制条件的原型工具制作出来。

    等等,
    Q. 为什么这就是原型的抽象定义呢? A. 首先这个抽象的定义肯定是涵盖了所有原型的,所有原型都符合这些条件。然后真实产品是不能被加上了上述的 2 个限制条件的原型工具制作出来的,也就是说这个定义将原型和产品区分开了。

    Q. 可是这定义太抽象太宽泛了吧,有什么用呢? A. 看下面的分析吧。。

    组合爆炸

    大家可能会对“数量组合爆炸”这个词耿耿于怀,它到底有啥特别的呢? 先来看看真正的产品有什么特征?首先,产品的数据量和交互路径组合起来的数量是会爆炸的。然后,为了解决这个爆炸数量,要用编程。最简单的例子,从“一个列表中搜索出包含指定文字的条目”,这个小产品,待所有的列表数据有无限种可能,输入的指定文字也是无限种可能。试问原型工具怎么能实现它呢?想实现它,要么加入编程的功能,要么允许原型组合爆炸。

    肯定有人会有疑问,界面上哪会出现组合爆炸的情形呢? 下面我就举个例子。假设页面 b 上有 10 个开关 switch,要求根据这些开关每个不同的状态组合,切换到另外一个不同的页面。那么页面 b 有多少个状态组合呢? 2^10=1024 个。

    消除组合爆炸

    如果觉得根据 10 个开关的状态切换到不同的页面显得太脱离实际,那让我们来考察一下“组件(Component)”这个概念的由来,你就会发现组合爆炸确实存在。

    一般认为定义组件(比如开关,复选框,下拉列表等)是为了复用,这点没错。但换个角度,从状态切换的角度来看,会有新的发现: 想象包含 10 个独立开关(switch)的某页面,在点击第一个 switch(以下简称 switch1)时,切换其开关的显示状态。如果不使用组件的概念,而是仅仅使用切换页面的方式来实现,会发生什么呢? 考虑到 10 个开关都是独立的,那么其他 9 个开关的状态可能是, 关,关,关,。。。 开,关,关,。。。 关,开,关,。。。 开,开,关,。。。 这 2^9=512 种情况中的任一种,所以如果要用切换页面的方式来改变 switch1 的显示状态,需要考虑这 512 种情形,对于每种情形都要各画 2 个页面,1 个页面上 switch1 是打开状态,另 1 个则是关闭状态,然后再给这 512 对页面添加点击 switch1 时的页面相互切换效果。

    这,就是所谓的组合爆炸。

    那么实际中为什么没有发生这么令人尴尬的情形呢?

    因为这些组合爆炸是可以消除的。比如 switch1 由关闭状态切换到打开状态时,其他 9 个开关状态任意组合,一共构成了 512 对不同页面的切换。但这所有 512 个页面切换中,其他 9 个开关状态都是保持不变的,所以这 512 个状态变换,可以合并为一个变换,用一句话来描述就是:switch1 由关闭状态切换到打开状态。512 个页面的全局状态变换,合并成了 switch1 的局部状态变换。

    源自于它自己,也只影响它自己,它是独立的。这就是从状态切换的角度观察,组件的定义和由来。而为了避免组合爆炸,组件也确实有存在的必要性。

    其实页面的抽象也是一个道理:其他页面的所有元素无论处于怎样的状态组合,本页面的初始状态和状态变换都是相对它们来说独立的。

    组合爆炸能被消除的原因

    一个页面切换到另一个页面,从状态切换的角度,很容易理解。比如从包含 10 个独立 switch 的页面 b 切换到页面 c,尽管切换时,页面 b 的状态可能是 1024 种组合状态中的任一种,页面 b 到页面 c 的切换,其实包含了 1024 种可能的状态到 1 个状态的切换,但显然,这 1024 种状态切换可以合并为 1 个:页面 b(无论在何种内部状态)切换到页面 c 。

    上面的例子看起来似乎有点说服力不足,但它很好的说明了组合爆炸能被消除的原因。不信换个例子看,

    还是从页面 b(包含 10 个 switch)切换到另一个页面 d,这次要求,页面 d 内包含着 20 个开关,与页面 b 内的 10 个开关是 2 对 1 的关系,每 2 个开关与页面 b 中对应的 1 个开关的状态保持一致。虽然从字面上看,仍然是页面到页面的切换,但显然,与 b 到 c 到切换是不同的:b 的 1024 个状态切换到 d 的对应状态,这些状态切换不能再简单的被合并为 1 个状态切换了。

    那么是否这 1024 个状态的切换就无法合并呢?仔细观察一下,因为页面 d 的 20 个开关与页面 b 的 10 个开关是 2 对 1 的独立对应关系。这意味着,可以像组件的剥离一样,将页面 b 中的每个开关的状态对页面 d 中对应开关的影响剥离出来。从而页面 b 到页面 d 的状态切换,就被分解成了 10 组独立的、局部的状态切换,从而消除了组合爆炸,

    从上面几个例子可以看出,组合爆炸能被消除的根本原因,就像前述的组件、页面、局部状态切换一样,是因为多个状态切换是可以合并为一个状态切换的。也只有在这种情况下,组合爆炸才能消除。

    再就页面切换举一个常见的例子:从某个页面切换到另一个页面后再返回原页面。 还拿上面的页面 b 切换到页面 c,然后再返回页面 b 。因为页面 b 本身可以有 1024 种开关组合状态,所以从页面 c 返回页面 b 时,要指定到底是返回哪个状态。这时如果原型工具本身不支持保存页面 b 切换时的状态,或者说从其他页面返回 b 页面时,会返回页面 b 的原始状态。在这种情况下,c 怎样才能返回 b 切换到 c 时的状态呢?似乎没有好的办法,我们只好手动建好页面 b 所有可能的 1024 种状态对应的页面,然后每个页面都切换到页面 c 的一个拷贝(也是 1024 个页面),这样就可以完美返回了。这同样是组合爆炸的情形——只是因为原型工具不支持!原型工具只要保存一下在离开某个页面时该页面的状态,就可以简单地避免组合爆炸。

    可见是否会出现组合爆炸,不仅仅在于多个状态切换是否能够合并成一个状态切换。即使状态切换能够合并,也需要原型工具本身能够支持定义合并后的状态,并且能处理合并后的状态切换。上面的“返回上一个页面离开时的状态”例子中,“离开时的状态”就是一个典型的合并后的状态定义,如果原型工具不支持这种定义,那么就会出现组合爆炸。

    处理连续状态对应的状态切换

    前面谈了离散的状态切换。比如点击、页面间的状态切换、组件内部状态切换。其实触发和状态,不只有离散,还有连续的。否则鼠标拖拽、滑动条、甚至时间动画,这些就都不能处理了,那些流畅的切换和动效也不复存在了。

    而连续则意味着有无数个状态,明显是数量爆炸了。怎样处理这么多数量的状态呢?做过动画的都知道制作动画可以用关键帧,对于线性动画,给定起点和终点,中间的无数个位置都是可以插值得到的。

    所以,处理连续导致的组合爆炸,一般来说也是用插值实现。

    举个例子,一个进度条,在 2s 的时段内从 0%加载到 100%。简单的几个数字,就定义好了无数个时间到状态的切换,这可以看作是无数的状态切换,被合并为了一个状态切换。

    类似的例子,拖拽页面的滑动条,页面随之上下滑动。实现这个效果,也只需要给定滑动条的坐标值与页面坐标值的一个映射。而定义这种映射,同样也只需要滑动条的起止位置、页面的起止位置这几个数字而已。

    看到这里,你可能会说,这种定义插值的方法,不就是定义了一个映射函数吗?不是说好不能加入编程功能吗?当然可以这么理解。不过一个更宽容的理解方法是:
    既然原型工具可以普遍定义离散的状态,并定义离散状态切换的起始状态和终止状态。那么为什么不允许它能定义一种连续状态的切换呢?而定义 2 个连续状态对应的切换,还有什么比线性映射更简单直接的呢?

    综上,在不引入编程的情况下,原型工具能否实现某些交互效果,一方面取决于交互效果涉及到的状态切换,能否简化成单对单的状态切换,从而避免数量的组合爆炸,另一方面取决于该原型工具是否支持对合并后的状态进行定义和操作。

    原型工具需要支持条件判断

    这里特别提一下条件判断。因为有时状态切换是有条件的,比如 10 个 switch 中某几个处于打开状态时,才允许跳转到其他页面。这时,因为这种条件可以简单的用一个状态来描述,不存在状态组合爆炸的问题,所以,只要原型工具支持,这种是很容易实现的。不过很遗憾的是,大部分原型工具都不支持条件判断。

    为什么说很遗憾呢?
    这就又要回到文章的主题:原型工具的能力边界。

    前面论证了,原型不是真实产品。因为原型工具无法处理真实产品的复杂逻辑(数量太大,组合爆炸),那么原型工具能够做到的最好效果,就是把产品的所有操作路径、业务逻辑都至少能走一遍,形象的说,真实的产品可以处理无穷的组合输入,并给出输出。而原型不能也不需要做到那样,它只需将某个场景下无穷个的输入组合中,选取一组,然后演示该场景的产品逻辑即可。

    要达到这个目的,只有使用预设的数据、预设的操作路径。这时候,条件判断就很重要了——虽然用户可以在界面上流畅无障碍地做各种界面操作,但一旦要触发执行某个业务逻辑,比如“删除”某条数据,那么由于业务的复杂性,我们不能允许用户任意删除数据,而只能是预设好的那条。然后再把预设好的处理过后的数据在界面上呈现出来。所以这里就要使用条件判断,确定用户是否执行的是指定的操作,如果不是,可能还要提醒用户。

    对一些原型工具的点评

    简单说下我尝试过的原型工具吧,把上面的抽象定义投射到具体的工具上:

    Figma ———— 有页面(Page)、帧(Frame)、局部覆盖层(Overlay)的概念。
    其中 Overlay 起到的作用,类似于前面说的组件的作用,即只是对单个页面的局部进行独立地修改,而不影响页面中的其他元素。
    但不支持单个触发事件定义多个动作。比如点击某个元素时,同时显示 /隐藏多个元素。这可能会导致状态的组合爆炸。比如 10 个 switch,每个 switch 都可以独立切换。但开关第 10 个 switch 时,会同步修改前 2 个 switch 的开关状态。这种情况下,由于不支持点击事件时同时定义多个动作,导致不得不另画单独的帧(Frame)并设置为切换后的状态。由于 switch 是可以独立切换的,这就意味着另画单独的帧会导致组合爆炸。

    也不支持连续触发、连续状态的定义。

    Principle ———— 有页面(Artboard)、组件(Component)、动画(Animate)、连续映射(Driver)的概念。
    其中动画、连续映射的概念,解决了连续状态的切换映射。可以非常好地制作复杂动效。
    不过让人困惑的是,Principle 也不支持单个触发事件定义多个动作。很遗憾地成为它的美中不足。

    Axure ———— 有页面(Page)、组件(动态面板)、动作(Action)、中继器(Repeater)、条件判断(Condition)等概念
    可以做比较复杂的交互。
    连续状态对应的功能没看到,可能中继器功能可以实现。

    FramerX ———— 有页面(Page)、帧(Frame)、组件(Component)等概念。
    引入了编程,且深度渗透到交互中。对设计师不友好。

    ProtoPie ———— 有页面(Scene)、组件(Component)、动作(Action)、条件(Condition)等概念。
    连续状态对应的功能没看到,可能变量(Variable)功能可以实现。

    Origami Studio ———— 有页面(Artboard)、组件(Component)、模组(Patch)等概念
    因为模组的就相当于是函数编程的概念,所以可以实现条件判断、动效等所有的功能。

    总体感觉就是,Origami Studio 是最让我满意的,它在能处理几乎所有复杂交互时,却不像 FramerX 一样强制过早地引入编程。也不像 ProtoPie 或 Axure 一样概念复杂。它的设计理念异常简洁清晰,而且对于原型工具非常适用,然后易用性也毫不逊色。从中你可以感受到它的简洁和美。

    Principle 是我非常满意的,它的设计理念也很简洁,巧妙统一了时间连续状态切换(Animation)和交互连续状态切换(Driver)的交互方式,页面和组件也通过递归简化了概念。而且对于设计师非常友好,非常易用。如果它支持单个触发事件定义多个动作的话,我可能不会在后面遇到 Origami 。

    ProtoPie 和 Axure,功能比其他一般的设计软件更全。但,感觉 ProtoPie 像是一个大杂烩,而 Axure 则显得太古板。都缺少美感。

    FramerX 似乎完全不在乎设计师的感受,它强调它适用于所有水平的设计师,我看未必,设计一个稍复杂的交互,就必须动用代码,我觉得它还不成熟。

    15 条回复    2021-05-13 19:21:25 +08:00
    no1xsyzy
        1
    no1xsyzy  
       2021-05-13 09:35:04 +08:00
    我不觉得需要搞这么复杂,借个术语,「贫血原型」和「充血原型」,指交互有多么丰富。

    我觉得充血原型工具不如直接搞 WYSIWYG 的界面编辑工具。

    其次:
    1. 不要在原型阶段考虑逻辑;
    2. 不要指望设计人员能写对复杂逻辑;
    3. 不要让前端自己猜或者自己从原型工具中挖掘逻辑
      —— 如果你的设计不能让前端一眼看过去就知道按钮相关逻辑是什么样的,那显然用户会更加迷惑,那这个设计就是个垃圾设计。
    sillydaddy
        2
    sillydaddy  
    OP
       2021-05-13 10:17:05 +08:00
    @no1xsyzy
    嗯。这篇主要是从原型工具的完备性的角度谈的。

    你说的“交互有多么丰富”,即使再丰富,也是有一个顶的,是能够达到的。

    原型工具本来就是各有侧重的。但有一个问题:
    比如说某个原型工具甚至支持连续触发。也支持组件,也支持动作。但却不支持一个触发对应多个动作。
    对,我说的就是 Principle 。

    其他有些原型工具也是这样的。本来是有实现某些东西的能力,但是这些能力却漏掉了一些情景。这就不是“贫血”和“充血”的选择问题了,而是不完备。
    no1xsyzy
        3
    no1xsyzy  
       2021-05-13 11:22:08 +08:00
    @sillydaddy 你的回复有点南辕北辙。
    首先澄清一下这句话的意思

    > - 指交互有多么丰富。
    > + 指交互丰富与否。

    我偏向「贫血原型」或「 WYSIWYG 工具」,拒绝具有丰富交互「充血」。
    打个比方,排版的时候,要么是 LaTeX 这种更抽象地描述的,要么是 Word 这种 WYSIWYG 的,你不太可能拿着 PostScript 这种拥有所有精确的底层功能的用。
    sillydaddy
        4
    sillydaddy  
    OP
       2021-05-13 12:07:26 +08:00
    其实我还是偏向你说的“充血原型”的,也就是能将真正产品的界面、交互、业务逻辑展现出来的。用设计界的术语叫“高保真”。

    1. 界面高保真: 这块太容易理解了,不多说了,也不在主题的讨论范围呢。
    2. 交互高保真:意思是,别管你底层的业务逻辑多复杂,原型上展现的界面,基本就是真实产品的界面。真实产品上能够交互的显示元素,也要能在原型上交互。当然,这个前提是,只是界面的交互,而不能涉及到产品的复杂逻辑。这点是原型完全可以做到的。
    3. 业务逻辑:原型不支持编程,肯定无法做到保真业务逻辑。在主题里也提到了原型怎样展现业务逻辑(这里的业务逻辑,在原型上的体现其实就是一连串的交互动作,可能涉及到多个页面的切换,多个页面是有复杂的因果影响的,背后是业务逻辑和数据在支撑。而原型到此应该止步了,它展现业务逻辑的方式,应该是针对某个业务场景从无数条操作路径中只取一条,来体现业务逻辑对应的页面逻辑)。

    > 1. 不要在原型阶段考虑逻辑;
    你说的这个逻辑是业务逻辑吗?如果是的话,原型阶段为啥不考虑呢?原型就是为了演示业务逻辑啊。

    > 2. 不要指望设计人员能写对复杂逻辑;
    没有复杂的逻辑,复杂的以至于需要编程才能实现的逻辑,是不能在原型工具上实现的。业务逻辑是一定会体现在界面的交互逻辑上的。复杂的业务逻辑要想体现为界面的交互逻辑,也只能拆解成一系列简单的业务操作。比如在原型上对数据任意的增删改查,哪怕是增删改查这 4 个操作各执行一遍,原型也是不可能做到的。原型能做到的是,分别针对增、删、改、查,提供一些交互,把这 4 种操作,演示一遍,而且还只能使用预设的数据。这已经是原型的能力极限了,但对于演示产品的业务逻辑,也已经足够保真了。

    > 3. 不要让前端自己猜或者自己从原型工具中挖掘逻辑
    你说的是从制作好的原型中挖掘交互逻辑吧?对于高保真原型,不存在这个问题啊,高保证原型展示的是真实产品的交互逻辑。页面怎么操作,是跟真实产品一样的。当然,原型想要做的好,需要对某个页面上可以执行哪些操作,要有必要的提示。现在的原型工具很多也能做到。可以看一下主题里“原型工具需要支持条件判断”那段描述。
    sillydaddy
        5
    sillydaddy  
    OP
       2021-05-13 12:24:34 +08:00
    @no1xsyzy #3 >“打个比方,排版的时候,要么是 LaTeX 这种更抽象地描述的,要么是 Word 这种 WYSIWYG 的,你不太可能拿着 PostScript 这种拥有所有精确的底层功能的用。”

    其实原型工具本身就是 mock(“假装”)实际产品的交互效果的。比如你真实产品在加载数据的时候,是根据互联网上获取的数据,来逐渐填充页面内容的。到了原型工具这里,会直接给不同的页面内容设置不同的延迟,就能做出这种效果了,而且仅仅从界面和互动上看,100%保真。这种其实是不需要抽象的底层功能的。或者说,所需的抽象,远远不如真实产品那样复杂。如主题中所提到的,仅仅一个线性映射(比如 Principle 所用),就可以 mock 绝大部分的界面交互效果。因此也不会带来更大的操作难度。
    no1xsyzy
        6
    no1xsyzy  
       2021-05-13 12:45:16 +08:00
    @sillydaddy 这三点其实原本是针对你上次提出的相对复杂的界面显隐逻辑的
    应该说是逻辑的实现细节
    什么是复杂逻辑?就是既支持 and 又支持 or (虽然不一定同时发生,可能这个控件的显隐是 and,另一个是 or ),就是复杂逻辑。
    在复杂的逻辑下,你要去发现某个 input 的逻辑是 check1 && check2 && check7 || check3 && check6,这显然强人所难。

    倒是针对性地提出用户故事,形成一个典型路线,这个真不建议用一个充血原型,而应当采用多个贫血原型,从时序上彻底分隔。
    (不过坏处是不够复用,都是复制粘贴)

    让我想起了有人做 PPT,只用了一张,显示一页然后用纯白去覆盖,再显示下一页,再纯白覆盖。
    不要这样。你应当做成多张简单朴素的 PPT,这样便于缩略图展现整个故事。
    不需要丰富交互,只需要一些注释表示「这时点击这个按钮」,换页「就会变成这样」,「然后再点击那个按钮」。
    sillydaddy
        7
    sillydaddy  
    OP
       2021-05-13 13:58:05 +08:00
    @no1xsyzy > “这三点其实原本是针对你上次提出的相对复杂的界面显隐逻辑的”
    哦。本来想着写完这篇主题再 @你一下的。但给忘记了。
    我比较怀疑界面的显隐逻辑能够变得复杂。上次主题说的复杂,主要是针对,界面在一系列操作之后,得到的结果数量可能非常多。比如我举的例子里面,N 多个显示元素都有各自的内部状态,而且可以自由操作,那么在一个页面上点击多次后,会形成复杂的组合。但界面本身的操作逻辑,并不复杂。之所以提到这个“数量组合爆炸”,是因为如果原型工具提供的功能本身不能消减这种组合爆炸,会导致有些原型制作不出来,而这些原型本身的逻辑很简单。
    最简单的一个例子,如果你尝试用 Figma 做一个界面上有很多个组件的页面,然后在页面上可以对每个组件独立交互,然后有个组件可以稍微影响某个其他的组件(也就是说界面的逻辑根本不复杂)。你会发现它用 overlay(覆盖层)来模拟组件状态变换的制作方式,会让人崩溃。所以 Figma 或者 Sketch 等工具,侧重点就在于界面的高保真设计,对于交互,它们只提供最基本的。

    我现在能想到的最复杂的界面逻辑,就是下面这个:
    1 个父 checkbox,下面有 2 个子 checkbox 。
    触发选中 /取消选中父 checkbox 时,子 checkbox 也随之选中 /取消选中,不管它们当前处于什么状态;
    而触发选中 /取消选中每个子 checkbox 时,该子 checkbox 也会切换选中 /取消选中,而不受父 checkbox 当时状态的影响。

    > “在复杂的逻辑下,你要去发现某个 input 的逻辑是 check1 && check2 && check7 || check3 && check6,这显然强人所难。”
    如果说某个 input 能否输入,受控于这 5 个 checkbox 的状态,那么,这个逻辑是可以很直接的得出的,或者说是很直观的,哪怕是对于设计师,不需要经过多次步骤的运算得出这个逻辑表达式,而是一步就能得到。这也有点类似主题里说的“条件判断”,在用户对某个页面随意操作后,用户想把页面上的填充或选择作为输入,做下一步的业务操作,这里原型工具可以判断一下各个填充或者选择是否符合预设的条件,这个条件也许比较复杂,但不需要设计师去计算,而是可以直观一步得出的。我是这样想的,因为实在想不到界面上会产生复杂的逻辑流,如果确实产生了,那大概率是因为牵涉到了底层的业务逻辑,由业务驱动产生的数据变化反映在了界面上,这种情况又回到原型本身的能力边界讨论上了。
    no1xsyzy
        8
    no1xsyzy  
       2021-05-13 14:47:47 +08:00
    @sillydaddy
    所以说这可能又要回到不要在原型阶段考虑更细致的逻辑。

    其实最复杂的是 Apply - Cancel - OK 按钮
    它需要状态保存和还原,这个让原型工具去做描述是真的疯了,恐怕大部分原型工具干脆不可能做到(哪怕只有一个 checkbox ),但逻辑本身清楚得很,不如说大家都常接触。

    所以说这里有就个问题:你的设计不符合直观,那就是糟糕设计;符合直观,就不需要搞充血原型。
    所以充血原型的工具,更多地像是用于向客户展示,而不是用于向实现者描述。

    另一方面就是其实和 WYSIWYG 一步之遥。这个原型写出来能不能直接编译到,比如说 Vue 或者 React,那样也能节约大量的工作量。
    sillydaddy
        9
    sillydaddy  
    OP
       2021-05-13 15:26:36 +08:00
    @no1xsyzy
    对于这个 Apply - Cancel - OK,我倾向于认为它是业务逻辑,而不是界面逻辑。

    界面逻辑就是界面元素之间如何互动。比如对于 7 楼提到的例子,就是父级 checkbox 与子级 checkbox 间的交互互动。再比如对于 PageScroll(滚动翻页)来说,业务数据已经完全交付在页面中的 Container(容器)里面了,然后后续的滑动、翻页这些交互都是界面范畴的交互,而不再涉及业务和数据的处理了。类似的例子还有很多。

    Apply-Cancel-OK,如果要演示的话,也只需要一条典型的演示路径就可以。比如我在原型的设置页面 A 里面,设置一些选项配置。然后点击 Apply-Cancel-OK,观察配置所引起的效果,就要切换到页面 B 。(页面 B 体现的是设置对后台数据的影响,哪怕只是这个产品的一些设置项,对于原型来说,也是产品的后台数据)。原型是不可能做到针对页面 A 里的每个不同的配置组合,都修改对应的产品数据的。所以原型能做的就是,在页面 A 中,允许自由交互,但在点击 Apply-Cancel-OK 时,提示只能应用预设的数据,然后再展示预设的页面 B 。这对于演示 Apply-Cancel-OK 的逻辑,完全没有问题。

    > “你的设计不符合直观,那就是糟糕设计;符合直观,就不需要搞充血原型”
    我还是觉得是一图胜千言。尤其是对于动效来说。

    >“另一方面就是其实和 WYSIWYG 一步之遥。这个原型写出来能不能直接编译到”
    这个我觉得 mock 出来某个效果,跟实际去做某个效果,工作量还是差不少的。首先 2 者依赖的工具或框架不同,你说的直接编译其实 FramerX 就在做,它的原型是基于 React 来做显示的,原型组件对应的 React 组件可以直接用在产品上。但像 Principle 或 Origami 这些工具,它们提供的交互效果依赖于它们自己提供的环境去运行,估计也很难脱离出来。再者,mock 时用的数据,以及呈现界面的方式,可以跟真实的代码逻辑有很大不同,虽然看起来一样,用起来一样,但总感觉少点啥,应该是因为复用比较难吧。
    sillydaddy
        10
    sillydaddy  
    OP
       2021-05-13 15:57:40 +08:00
    @no1xsyzy
    我刚想起了一个具体的例子。可以表达清楚我的想法。

    下面这个是 React 写的一个组件,可以交互式操作的。链接里面有动图,表现怎样以交互方式修改一棵树的结构。
    https://github.com/frontend-collective/react-sortable-tree

    虽然它看起来是纯界面的东西,但其实连续的多次操作涉及到了后面的数据结构(树状列表),在不编程的情况下,是非常难以用原型工具把它做出来的,正像你说的,如果能做出,那离 WYSIWYG 就一步远了。

    但是,原型工具是可以 mock(模拟)出它的单次操作的交互效果的,而且可以保证交互效果完全一致——甚至鼠标连续移动对应的连续状态变化也可以做出来,而不需要引入编程。这就是用前面说的,针对“拖拽条目排序”这种业务操作,选取一条预设的演示路径,拖拽预设的条目到预设的位置。什么是界面操作,什么是业务操作,也不是绝对的,这个例子可以给人很多启发。

    如果设计师想让开发做的就是这种效果,那用言语表达肯定是难以沟通的,而正好是原型发挥作用的地方。设计师 mock 出来的这个东西,因为不完整所以也不能编译后用在真实的产品中。
    no1xsyzy
        11
    no1xsyzy  
       2021-05-13 16:04:14 +08:00
    @sillydaddy
    父级 checkbox 和子级 checkbox 的关系也可以是业务逻辑,这一具有宏观明确表现的逻辑,很难说清是业务逻辑还是界面逻辑。

    容器类我觉得应当是原型工具的基本了,虽然不是所有原型工具都这么想。
    我觉得这是更多地是关于参考系及 overflow 变换,而不是逻辑。
    ( fixed 一类的另论)

    如果不是觉得一图胜千言的话就干脆不需要原型工具了。
    在此基础上,我觉得多图并不如一图一言,这里有边际效益递减的问题。

    所以 FramerX 其实是或者是想做 WYSIWYG 吗
    如果说从开头就想着 WYSIWYG 做肯定会让转模型容易得多。而且配合现成的设计框架大概会更好。
    可能让 antd 之类的 UI 库去附带做个 WYSIWYG 的类原型工具会更好。
    (另外,其实可能蕴含了职责划分、保护岗位的关系,虽然这显然 off-topic )
    no1xsyzy
        12
    no1xsyzy  
       2021-05-13 16:07:28 +08:00
    @sillydaddy 那其实也不需要充血原型,用多个贫血原型、以类似 Time Machine 的形式表示会更清楚
    为什么非要原型的观看者自己按指挥动下手呢……
    sillydaddy
        13
    sillydaddy  
    OP
       2021-05-13 17:37:53 +08:00
    @no1xsyzy
    想了一下,可能自己潜意识里一直想的是直接在原型上做产品概念的迭代,所以总想着要把原型一次做到位,后续把它作为迭代的基础,因为代表真实产品的样子嘛!想想其实大部分的原型应该只要示意图+说明,或者你说的多个贫血原型就足够了。毕竟涉及到交互的迭代还是占的比例很小,而产品设计的迭代占的比例更大,可以直接在低保真上面迭代。
    sillydaddy
        14
    sillydaddy  
    OP
       2021-05-13 17:42:13 +08:00
    @no1xsyzy
    高保真的交互,对于演示是最有帮助的,可以亲自体验,看视频和亲自操作肯定有差别。
    然后对于建立产品的完整感觉也有帮助,因为所有的交互都集成在一起了,切换体验不同的场景很方便。

    不过这些应该是到后面再做的。
    no1xsyzy
        15
    no1xsyzy  
       2021-05-13 19:21:25 +08:00
    @sillydaddy 这其实相比迭代反而让我想起了瀑布流。
    实际上我觉得你要从成品开始迭代的话,也有一种是「曳光弹开发」里面所说的原型,也就是比充血原型更进一步的(且让我命名为)「有效原型」(已经可以完整使用但在诸多方面不足以直接丢生产环境的原型,比如数据库很可能是 SQLite 甚至是 localStorage ),有些时候也有「 MVP 」之类的变体。
    (不过我目前接触到的演示都是现成的成品,欸)

    这也是我说充血原型更偏向面向客户的演示而非面向实现的演示,似乎原型的源发是这两方面的需求恰好撞上的结果。
    说起来这种有限交互感觉似乎在哪个 tutorial 看到过…… 说不定用于 2B 的培训材料也挺不错的。

    差不多这样,很愉快地讨论。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5366 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 05:57 · PVG 13:57 · LAX 21:57 · JFK 00:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.