我当前的项目被分成多个类,正确地表示了我们对系统中实体的看法。然而,这需要一个性能价格,所以我试图想出一种提高性能的方法,同时保持我们现有的类结构。
我认为一个例子最能说明问题:假设我有一个包含多个Order
的{{1}}类。运送Item
的天真实施正在发送其所有Order
:
Item
发送class Order
{
private List<Item> m_items;
public void Ship()
{
foreach (Item item in m_items)
{
item.Ship();
}
}
}
是一个多阶段过程:
Item
事实证明,将class Item
{
public void Ship()
{
var receipt = m_boat.ShipToDestination(this);
ProcessReceipt(receipt);
}
}
发送到Item
需要很长时间。幸运的是,Boat
可以同时发送多个Boat
(Item
)。但是,要使用此方法,我必须重写List<Receipt> Boat.ShipToDestination(List<Item> items)
,如下所示:
Order.Ship()
这意味着class Order
{
public void Ship()
{
var receipts = m_boat.ShipToDestination(m_items);
foreach (Receipt receipt in receipts)
{
ProcessReceipt(receipt);
}
}
}
现在是ProcessReceipt
(而不是Order
)的一部分,并且Item
不再负责其所有的运输物流。
在我的真实代码中,有许多方法可以解决这个问题,因此有效地使用此解决方案意味着大多数Item
逻辑将进入Item
类。然而,这似乎是错误的地方有这个逻辑 - 它应该在Order
。
我考虑过使用多个线程(例如,每Item
使用一个Task
),但这似乎太浪费了,特别是因为Item
可以有几十个Order
。
我考虑的另一种方法是使用Items
方法和QueuedBoat
方法创建QueueForShipping(Item item)
。现在ShipQueuedItems()
可以致电Order
而ShipQueuedItems
可以致电Item
。这种方法的问题在于,在我的实际代码中,QueueForShipping
仅在Receipt
发布后返回,因此代码必须如下所示:
Item
这感觉它正朝着正确的方向发展(因为class Order
{
private List<Item> m_items;
public void Ship()
{
foreach (Item item in m_items)
{
item.Ship();
}
m_queuedBoat.ShipQueuedItems();
foreach (Item item in m_items)
{
item.FinalizeShipping();
}
}
}
class Item
{
public void Ship()
{
m_queuedBoat.QueueForShipping(this);
}
public void FinalizeShipping()
{
ProcessReceipt(m_queuedBoat.GetReceiptForItem(this));
}
}
知道它有多少Order
,它必须是知道何时一切都在Item
上的组件,但是它将Boat
分为两个阶段。在我的真实代码中,我有多个阶段(每个阶段可以单独矢量化),因此该方法将分为3-4个部分,这不是一个很好的视线。
有人可以提出一种向Ship
进行矢量化的方法,同时将业务逻辑保留在Item.Ship()
类中,或者我是否必须放弃订单/项目分离才能利用矢量化?
修改
另一种方法可能是:
Item
class Order
{
private List<Item> m_items;
public void Ship()
{
for (int i = 0; i < m_items.Count; ++i)
{
bool isLast = (i == (m_items.Count - 1));
item.Ship(isLast);
}
}
}
class Item
{
public void Ship(bool isLast)
{
m_queuedBoat.QueueForShipping(this, FinalizeShipping);
if (isLast) m_queuedBoat.ShipQueuedItems();
}
private void FinalizeShipping(Receipt receipt)
{
ProcessReceipt(receipt);
}
}
类使用QueuedBoat
为每个项调用回调。
答案 0 :(得分:2)
嗯,无论如何Ship
是一种异步操作:必须同时运行几个。所以必须是两阶段:PrepareShipping
(无效)和PerformShipping
(等待实际运输完成,返回处理其收据)。
我会这样:
class Item
{
public void PrepareShiping()
{
m_queuedBoat.QueueForShipping(this);
}
public void PerformShipping()
{
m_queuedBoat.StartActualShippingIfNotAlreadyStarted();
m_queuedBoat.WaitForShippingEnd();
ProcessReceipt(m_queuedBoat.GetReceiptForItem(this));
}
}
所以Order可以是这样的:
class Order
{
public void PrepareShipping()
{
foreach (Item item in m_items)
item.PrepareShiping();
}
public void PerformShipping()
{
foreach (Item item in m_items)
item.PerformShipping();
}
// and for those who don't need asynchronity
public void Ship()
{
PrepareShipping();
PerformShipping();
}
}
该程序可以在运送过程中执行其他操作,即Order.PrepareShipping()
和Order.PerformShipping()
之间(例如,也可以在同一条船上运送其他订单)。