让我们假设我想设计一个REST api来讨论歌曲,专辑和艺术家(实际上我这样做,比如我之前的1312414人).
歌曲资源始终与其所属的专辑相关联.相反,专辑资源与其包含的所有歌曲相关联.关联通过链接在资源表示中表示.
因此,表示看起来像这样:
{
song: 'xyz',
links: [
{ rel: 'album', url: '.../albums/abc' }
]
}
{
album: 'abc',
links: [
{ rel: 'song', url: '.../songs/xyz' },
{ rel: 'song', url: '...' },
{ rel: 'song', url: '...' },
{ rel: 'song', url: '...' }
]
}
Run Code Online (Sandbox Code Playgroud)
鉴于,我希望这一点成立(也许问题在于"给定"),然后如何设计我的API,以便创建专辑或歌曲资源对以前存在的歌曲或专辑没有副作用资源?
这是某种鸡/蛋问题.如果我首先创建歌曲资源(POST/songs /)然后创建专辑资源(POST /专辑/),则歌曲资源会在专辑创建过程中被修改(根据REST原则这是不好的),因为该关联两个资源之间正在服务器上更新.同样,对于我首先创建专辑的场景,第二首歌曲.
我想我可以通过避免服务器上的副作用并将管理双向关系的负担传递给客户端来避免整个问题.
另外,我不希望作为一个整体原子地创建专辑和歌曲.
我现在唯一能想到的是,通过使用表示来响应资源创建,将上述副作用包含在我的API的语义中,该表示包含由于请求而被修改的资源的链接列表.这使副作用显而易见,但仍然不安宁.
在寻找一种方法来强制自定义类型的不变性并且没有找到满意的答案后,我想出了我自己的元类形式的解决方案:
class ImmutableTypeException( Exception ): pass
class Immutable( type ):
'''
Enforce some aspects of the immutability contract for new-style classes:
- attributes must not be created, modified or deleted after object construction
- immutable types must implement __eq__ and __hash__
'''
def __new__( meta, classname, bases, classDict ):
instance = type.__new__( meta, classname, bases, classDict )
# Make sure __eq__ and __hash__ have been implemented by the immutable type.
# In the case of __hash__ also make sure the …Run Code Online (Sandbox Code Playgroud)