gpt4 book ai didi

wcf - 在 WCF 服务中重构上帝对象

转载 作者:行者123 更新时间:2023-12-04 03:57:31 24 4
gpt4 key购买 nike

我们遇到了 god object在我们的系统中。该系统由public service组成暴露给我们的客户,middle office serviceback office service .

流程如下:用户在public service中注册了一些事务。 ,然后是 middle office service 的经理检查交易并批准或拒绝交易,最后经理来自back office service完成或拒绝交易。

我正在使用 transaction 这个词,但实际上这些是不同类型的操作,例如 CRUD on entity1 , CRUD on entiny2 ... 不仅 CRUD操作,但还有许多其他操作,例如 approve/send/decline entity1 , make entity1 parent/child of entity2等等等等……

现在WCF服务契约(Contract)只是根据系统的那些部分分开。所以我们有3个服务契约(Contract):

PublicService.cs
MiddleOfficeService.cs
BackOfficeService.cs

和巨额的运营契约(Contract)在每个:
public interface IBackOfficeService
{
[OperationContract]
void AddEntity1(Entity1 item);

[OperationContract]
void DeleteEntity1(Entity1 item);

....

[OperationContract]
void SendEntity2(Entity2 item);

....
}

所有 3 项服务的运营契约(Contract)数量已经达到 2000 个,每个服务契约(Contract)大约有 600 个。这不仅破坏了最佳实践,而且由于需要很长时间才更新服务引用是一个巨大的痛苦。并且系统每天都在增长,并且在每次迭代中向这些服务添加越来越多的操作。

而现在我们面临着两难境地,我们如何将这些上帝服务拆分成逻辑部分。有人说一个服务不应该包含超过 12~20 个操作。其他人说一些不同的话。我意识到没有黄金法则,但我只是希望听到一些关于此的建议。

例如,如果我只是按实体类型拆分这些服务,那么我可以在项目中获得大约 50 个服务端点和 50 个服务引用。在这种情况下,可维护性如何?

还有一件事要考虑。假设我选择将这些服务拆分为每个实体的方法。例如:
public interface IEntity1Service
{
[OperationContract]
void AddEntity1(Entity1 item);

[OperationContract]
void ApproveEntity1(Entity1 item);

[OperationContract]
void SendEntity1(Entity1 item);

[OperationContract]
void DeleteEntity1(Entity1 item);
....

[OperationContract]
void FinalizeEntity1(Entity1 item);

[OperationContract]
void DeclineEntity1(Entity1 item);
}

现在发生的事情是我应该在 public client 中都添加对此服务的引用。和 back office client .但是 back office只需要 FinalizeEntity1DeclineEntity1操作。所以这是一个经典的违反 Interface segregation principleSOLID .因此,我必须将其进一步拆分为 3 个不同的服务,例如 IEntity1FrontService , IEntity1MiddleService , IEntity1BackService .

最佳答案

这里的挑战是在不更改大部分代码的情况下重构代码以避免潜在的回归。

避免包含数千行的大型业务代码的一种解决方案是将您的接口(interface)/实现拆分为多个部分,每个部分代表一个给定的业务域。

例如,您的 IPublicService接口(interface)可以写成如下(使用接口(interface)继承,每个业务域一个接口(interface)):
IPublicService.cs :

[ServiceContract]
public interface IPublicService : IPublicServiceDomain1, IPublicServiceDomain2
{
}
IPublicServiceDomain1.cs :
[ServiceContract]
public interface IPublicServiceDomain1
{
[OperationContract]
string GetEntity1(int value);
}
IPublicServiceDomain2.cs :
[ServiceContract]
public interface IPublicServiceDomain2
{
[OperationContract]
string GetEntity2(int value);
}

现在对于服务实现,您可以使用部分类将其拆分为多个部分( 每个业务域的一个部分类 ):
Service.cs :
public partial class Service : IPublicService
{
}
Service.Domain1.cs :
public partial class Service : IPublicServiceDomain1
{
public string GetEntity1(int value)
{
// Some implementation
}
}
Service.Domain2.cs :
public partial class Service : IPublicServiceDomain2
{
public string GetEntity2(int value)
{
// Some implementation
}
}

对于服务器配置,仍然只有一个端点:
<system.serviceModel>
<services>
<service name="WcfServiceLibrary2.Service">
<endpoint address="" binding="basicHttpBinding" contract="WcfServiceLibrary2.IPublicService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary2/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

客户也一样:仍然是一个服务引用:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IPublicService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary2/Service1/"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IPublicService"
contract="ServiceReference1.IPublicService" name="BasicHttpBinding_IPublicService" />
</client>
</system.serviceModel>

这允许通过将大型服务拆分为多个逻辑部分(每个部分与给定的业务域相关联)来重构服务器端。

这不会改变您的 3 个服务中的每一个仍然有 600 个操作的事实,因此客户端代理生成仍然需要很长时间。至少您的代码会在服务器端组织得更好,并且重构会便宜且风险不大。

这里没有 Elixir ,这只是代码重组以提高可读性/维护性。

200 个服务每个 10 个操作与 20 个服务每个 100 个操作是另一个主题,但可以肯定的是重构需要更多时间, 你仍然有 2000 次操作 .除非你重构整个应用程序并减少这个数字(例如通过提供更“高级”的服务(并非总是可能的))。

关于wcf - 在 WCF 服务中重构上帝对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31047845/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com