从一个编辑校验问题谈接口设计的边界

奇怪的校验(城市和图片配置的校验)

我们反思一个问题。在入参的不变的情况下。不断的增加if-else。能够实现所有的校验吗?如果意识到这个问题,我们就能够知道什么情况下我们必须裂变某些方法以便覆盖业务中的某些场景。

题主先从一个亲身经历的业务开发聊起。想象这么一个场景。前端会给你后端传回一个对象。这个对象呢有两个字段。城市名和图片。

产品的要求是不能够在数据库中同时存在一个城市对应多张图片。但是对图片是否可以重复则没有提要求。

现在你不确定数据库有没有做唯一判断的基础建设。你只能利用一个根据城市名查询相关记录是否存在的方法。且你不能要求新增其他的数据库交互手段以及和前端的动作。你必须要在应用层尽可能通过一个接口,一个方法来解决这个问题。

整套需求的难点在于有这么一个编辑的场景。

支持三种场景。

1更改现有城市的图片

2不更改图片更改城市

3既更改城市又更改图片

我们考虑几种必然出现异常(不发生数据库变更)的情景

4用户如果什么都不做。return一个未发生任何更改的提示。

5用户试图更改城市名。导致会发生数据库会出现一个城市对应两个图片。这种应该抛出异常

然后题主在实际编码的过程中发现怎么都写不出来的对应的校验逻辑。最矛盾是2 和1和5。如果题主要校验入参中的城市名是否存在于数据库。然后根据这个结果的有无拒绝操作。那么就会导致产场景5保证了。但是场景2就不能够满足了。比如说数据库有两条记录。广州 链接a 。上海 链接b。 我现在需要编辑上海 链接b这个 数据。我们希望吧上海改成广州。这个违反了场景5应该拒绝。

例如我们写

如果 入参.城市名 =数据库.存在的城市名 直接拒绝。

但是我们会发现这样的写法。就会导致场景1也会被拒绝。

因为场景1 的情况下。这个时候 入参.城市名 =数据库.存在的城市名 是必然需要放行的。

我们当然可以像什么都不变场景4。引入当数据库的名字和链接都完全的等于入参进来的城市名和链接。给他retrurn。

但是这些操作真正能够解决问题吗?

(读后注 :这已经暗示了一个结论:这是一个"非函数性问题"

我们发现如果能够转移矛盾有很多解决方案?比如说限制接口的行为啊?数据库和持久层做一些兜底的工作向上抛异常啊。做一次前置校验等等。我们先不讨论某些方案能否真正解决这类问题。但是直觉上存在着很多这样自然的直觉。

我们也能够意识到很多问题?

比如说我们意识到传参对于一些动机的感知似乎不是完全且覆盖的?我们从传参去做个校验操作似乎是不能够满足一些场景和需求的。我们会意识到传参和需求是分离的....我们还会意识到如果数据库层和持久层能够给我提供更多的校验甚至有什么预插入然后返回一个什么样的结果。或者是插入之后再去查一次做个兜底然后可以支持回滚啊什么样的行为似乎也能够提升在业务开发中的一些灵活度。我们也会意识到分层这种架构风格可能会导致某些计算的复杂度的提升以及所能够带来的一些计算的兼容的可能。

但是题主想要描述的是,我是如何发现这个案例有问题,或者说我是如何意识到存在某些矛盾。

首先是从代码的层面。一段代码其实只有执行和不执行两种结果。所有的代码分支也最终只能够收敛到这个二元的范畴。所以题主意识到这种推理和离散数学中的真值计算具备十分相似的结构。如果是一个真值计算。我们很容易想到一些离散相关的方法。比如说枚举对象。描述状态空间,描述状态转移。在我们这个场景就两个变量。各自也是要不存在于数据库要不不存在于数据库。所以就是一个2x2的一个组合。然后根据这个组合我们最多只能写出四个有限代码分支。然后自下而上我们很容易发现在这个接口中无论怎么操作都无法覆盖到所有的业务场景。而更加深刻的洞见在于无论我们写再多的if-else操作都无法突破这个理论极限。

(即 : 状态空间的维度 < 语义空间的维度 )

如果只是以这个范畴作为反驳的支点。以寻求可以要求资源的切入口,自然是难以说服不从事实施工作和代码的同学。

题主有着更大的野心。为什么我们的枚举所有的离散空间无法覆盖所有的业务场景。这是否意味着我们的离散系统是否存在某种隐性的机制和矛盾。导致我们无法覆盖所有的场景。而我们的解决方案。都是这个2乘2的状态内在的矛盾去发散开来的。重点是我们如何发现这种内在的矛盾。然后怎么解决。这样解决破坏了这种机制的什么东西。使得枚举是有效的。

最简单的方法有3个:一个呢是限制接口的行为,一个呢则是在流程上能否我们执行一次预编辑然后做异常处理驱使用户再传入新的组合。最后就是引入版本号这样的机制和oldcity和newcity这样的字段。

我们进一步问这些方案如何被描述,又如何理解他们解决问题的路径?

我们可以归纳出来。无非是增加新的变量,引入新的校验维度。要不就是区分函数和接口。限制单个接口不能够执行类似于新增这样的场景。

而导致我们不得不必须做出更改的似乎是某种确定性的确立,以及某种一对一关系的建立。

这里没有什么推理,纯粹是一种知识上的理解。我们发现这些要求和一个属性和特征具备关联关系。即公理系统中要求的自反性。而自反性抽象一层就是原子性。如果从原子性的角度反思这种类似于从系统给出回馈的操作就真的好像是事务一样的解决方案?

我们基于这个特性,我们又可以发现另外一个相关联特别强的词即理论上完全独立的概念---正交性。而围绕着正交性,我们可以讨论到我们这样的运算符操作。离散的图灵机式的校验。本质上依赖或者受到一种线性组合的约束。

我们要如何证明一个命题不存在,常见的方式就是描述状态转移方程?或者是反证法。从方法的范畴上我们可以观察到一个更加有意思的现象。

违反了自反推导的命题和状态似乎就会影响反证法矛盾的产生。而自反本质是因为语义坍缩?什么是语义坍缩?这里还要讨论函数上的定义?我们都知道反证法是用数学归纳法证明的。但是从这个角度我们窥见,反证法不仅仅可以从自下而上去理解。也暴漏出一些自上而下的特征。比如说枚举不完备?这似乎在说明反证法是一个可以证明检查语义坍缩说明矛盾的机制?

(查阅资料:这个现象叫做当输入到语义的映射不可逆时,不存在完备校验函数 )

我们现在已经走的很远了。我们再回过头来看,我们发现了什么东西?我们又是如何发现。依赖问题关联到数学。从数学回顾到解决方案。反思这些方案到底做了什么达到另外一个数学上的关联。最后我们似乎可以想要对某些还未发生的东西似乎是某个未知的定理。比如说一个函数如果映射不可逆会导致什么样的问题又所预见。我们回顾我们是如何不被其他东西影响得出这个结论的。穷举逼出来隐性的矛盾。从原子性和正交性出发可以提出来的一系列解决方案?

相关推荐
消失的旧时光-19435 小时前
Java 线程通信:彻底理解 wait / notify(原理 + 图解 + 实战)
java·开发语言
VX:Fegn08955 小时前
计算机毕业设计|基于springboot + vue非遗传承文化管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
hd51cc5 小时前
MFC基础知识
笔记·学习·mfc
纪伊路上盛名在5 小时前
文献阅读自动化1-批量检索、更新文献
python·自动化·文献阅读·科研日常·流程化
Warren985 小时前
面试和投简历闲聊
网络·学习·docker·面试·职场和发展·eureka·ansible
徐子元竟然被占了!!5 小时前
Linux-chown
java·linux·运维
梦白.5 小时前
Python字符串类型
linux·python
gf13211115 小时前
python_图片、字幕文本、音频一键组合
python·音视频·swift
幻云20105 小时前
Python机器学习:从零基础到项目实战
人工智能·学习·机器学习