假设一个团队使用API将数据返回到浏览器中的SPA。
返回专门为SPA的UI准备的数据是RESTful吗?
相反,客户端可以使用JS特别准备数据,许多人都希望避免这种情况。
什么意思重塑? =>
public async Task<IEnumerable<SchoolclassCodeDTO>> GetSchoolclassCodesAsync(int schoolyearId)
{
var schoolclassCodes = await schoolclassCodeRepository.GetSchoolclassCodesAsync(schoolyearId);
var allPupils = schoolclassCodes.SelectMany(s => s.Pupils).Distinct<Pupil>(new PupilDistinctComparer());
var allPupilsDTOs = allPupils.Select(p => p.ToPupilDTO());
var schoolclassCodeDTOs = schoolclassCodes.Select(s => s.ToSchoolclassDTO());
// Prepare data specially for UI DataGrid with checkboxes
foreach (var s in schoolclassCodeDTOs)
{
foreach (var p in allPupilsDTOs)
{
var targetPupil = s.Pupils.SingleOrDefault(pupil => pupil.Id == p.Id);
if(targetPupil == null)
{
p.IsSelected = false;
s.Pupils.Add(p);
}
else
{
targetPupil.IsSelected = true;
}
}
}
return schoolclassCodeDTOs;
}
答案 0 :(得分:1)
这是一个很好的问题。问题是,很可能只有你有答案。
tl; dr 古老的“它是特定于应用程序的”。
您可能需要将此视为连续统一体,而非二元决策。在一个极端,你有服务器生成HTML视图,因此负责很多UI问题,另一方面,你有服务器公开具有非常通用的CRUD功能的数据模型,因此不负责任何UI问题。在中间的某个地方,您还可以找到一个设计,其中服务器接口是特定于应用程序但不一定暴露HTML(尽管具有连接的魔力一切都到位)可能是非常明显的原因(当涉及到所谓的SPA。)。
那么,您应该选择什么?
我希望有些人建议你尽可能地分离客户端和服务器,但我个人认为没有这样的终极“良好做法”。事实上,这可能为时过早。首先设计逻辑组件,然后决定它们应该在何处以及如何运行。
记住:
良好的架构允许推迟重大决策并最大化未做出的决策数量。
(鲍勃叔叔)
为什么呢?好吧,因为这些(域逻辑和执行环境)是真正独立的问题:它们可能会独立地发展 。例如,如果应用程序是计算密集型的(例如,为了节省电池电量),您可能决定为移动设备创建更薄的客户端,为桌面设置更厚的客户端。或者,如果应用程序是网络密集型的(例如,当连接性较差时保存往返,也可以考虑“离线优先”),则可能完全相反。也许您将提供所有变体并让用户选择,或者根据可用资源自动选择 - 无论要求是什么,但它们可能会发生变化。
我认为这些是更合适的问题和架构决策(但同样:只有在您已经设计了逻辑组件的边界之后)。这些更清晰的要求将帮助您确定应用程序的哪些组件应在哪里运行。他们 以代表您的界限(无论是内部API还是远程API,私有或公共),而不是形成它们的方式<那已经完成了)。您的RESTful API(如果您确定需要一个并且REST样式的架构是合适的)只是任意边界的表示。
这就是你最终会在你的场景环境中回答你自己的问题的方法 - 到那时应该会变得非常直观。
结束注意:虽然域逻辑严格地塑造了你的界限是好的和纯粹的,但是与执行环境有关的一些问题(比如谁控制某些网络主机,数据应该驻留在哪里等)将不可避免地反馈到域名设计。我不认为这是一个矛盾;您的应用程序 会影响您正在建模的任何活动,因此其自身的关注点也必须建模。工具也会影响您的思考方式,因此如果HTTP是一个工具而您非常擅长使用它,那么您可能会开始在任何地方使用它。这并不一定是坏事(例如,评审团仍然在“微服务”上),但是应该意识到知道太少的工具经常(并不总是)将开发人员推向尴尬的角落。我怎么可能没有完成:“使用正确的工具 - ”啊,它变老了,不是吗;)。