Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like ShoppingService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ShoppingService, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
39 | class ShoppingService |
||
|
|||
40 | { |
||
41 | /** @var \Eccube\Application */ |
||
42 | public $app; |
||
43 | |||
44 | /** @var \Eccube\Service\CartService */ |
||
45 | protected $cartService; |
||
46 | |||
47 | /** @var \Eccube\Service\OrderService */ |
||
48 | protected $orderService; |
||
49 | |||
50 | /** @var \Eccube\Entity\BaseInfo */ |
||
51 | protected $BaseInfo; |
||
52 | |||
53 | /** @var \Doctrine\ORM\EntityManager */ |
||
54 | protected $em; |
||
55 | |||
56 | 29 | public function __construct(Application $app, $cartService, $orderService) |
|
63 | |||
64 | /** |
||
65 | * セッションにセットされた受注情報を取得 |
||
66 | * |
||
67 | * @param null $status |
||
68 | * @return null|object |
||
69 | */ |
||
70 | 6 | public function getOrder($status = null) |
|
91 | |||
92 | /** |
||
93 | * 非会員情報を取得 |
||
94 | * |
||
95 | * @param $sesisonKey |
||
96 | * @return $Customer|null |
||
97 | */ |
||
98 | 3 | public function getNonMember($sesisonKey) |
|
113 | |||
114 | /** |
||
115 | * 受注情報を作成 |
||
116 | * |
||
117 | * @param $Customer |
||
118 | * @return \Eccube\Entity\Order |
||
119 | */ |
||
120 | 7 | public function createOrder($Customer) |
|
135 | |||
136 | /** |
||
137 | * 仮受注情報作成 |
||
138 | * |
||
139 | * @param $Customer |
||
140 | * @param $preOrderId |
||
141 | * @return mixed |
||
142 | * @throws \Doctrine\ORM\NoResultException |
||
143 | * @throws \Doctrine\ORM\NonUniqueResultException |
||
144 | */ |
||
145 | 7 | public function registerPreOrder(Customer $Customer, $preOrderId) |
|
208 | |||
209 | /** |
||
210 | * 受注情報を作成 |
||
211 | * @param $Customer |
||
212 | * @return \Eccube\Entity\Order |
||
213 | */ |
||
214 | 7 | public function getNewOrder(Customer $Customer) |
|
221 | |||
222 | |||
223 | /** |
||
224 | * 受注情報を作成 |
||
225 | * @return \Eccube\Entity\Order |
||
226 | */ |
||
227 | 7 | public function newOrder() |
|
233 | |||
234 | /** |
||
235 | * 受注情報を作成 |
||
236 | * |
||
237 | * @param \Eccube\Entity\Order $Order |
||
238 | * @param \Eccube\Entity\Customer|null $Customer |
||
239 | * @return \Eccube\Entity\Order |
||
240 | */ |
||
241 | 7 | public function copyToOrderFromCustomer(Order $Order, Customer $Customer = null) |
|
275 | |||
276 | |||
277 | /** |
||
278 | * 配送業者情報を取得 |
||
279 | * |
||
280 | * @return array |
||
281 | */ |
||
282 | public function getDeliveriesCart() |
||
291 | |||
292 | /** |
||
293 | * 配送業者情報を取得 |
||
294 | * |
||
295 | * @param Order $Order |
||
296 | * @return array |
||
297 | */ |
||
298 | public function getDeliveriesOrder(Order $Order) |
||
307 | |||
308 | /** |
||
309 | * 配送業者情報を取得 |
||
310 | * |
||
311 | * @param $productTypes |
||
312 | * @return array |
||
313 | */ |
||
314 | 10 | public function getDeliveries($productTypes) |
|
336 | |||
337 | |||
338 | /** |
||
339 | * お届け先情報を作成 |
||
340 | * |
||
341 | * @param Order $Order |
||
342 | * @param Customer $Customer |
||
343 | * @param $deliveries |
||
344 | * @return Order |
||
345 | */ |
||
346 | 7 | public function getNewShipping(Order $Order, Customer $Customer, $deliveries) |
|
347 | { |
||
348 | 7 | $productTypes = array(); |
|
349 | foreach ($deliveries as $Delivery) { |
||
350 | if (!in_array($Delivery->getProductType()->getId(), $productTypes)) { |
||
351 | $Shipping = new Shipping(); |
||
352 | |||
353 | 7 | $this->copyToShippingFromCustomer($Shipping, $Customer) |
|
354 | 7 | ->setOrder($Order) |
|
355 | ->setDelFlg(Constant::DISABLED); |
||
356 | |||
357 | // 配送料金の設定 |
||
358 | $this->setShippingDeliveryFee($Shipping, $Delivery); |
||
359 | |||
360 | $this->em->persist($Shipping); |
||
361 | |||
362 | $Order->addShipping($Shipping); |
||
363 | |||
364 | $productTypes[] = $Delivery->getProductType()->getId(); |
||
365 | } |
||
366 | } |
||
367 | |||
368 | 7 | return $Order; |
|
369 | 7 | } |
|
370 | |||
371 | /** |
||
372 | * お届け先情報を作成 |
||
373 | * |
||
374 | * @param \Eccube\Entity\Shipping $Shipping |
||
375 | * @param \Eccube\Entity\Customer|null $Customer |
||
376 | * @return \Eccube\Entity\Shipping |
||
377 | */ |
||
378 | 8 | public function copyToShippingFromCustomer(Shipping $Shipping, Customer $Customer = null) |
|
379 | { |
||
380 | if (is_null($Customer)) { |
||
381 | 1 | return $Shipping; |
|
382 | } |
||
383 | |||
384 | 7 | $CustomerAddress = $this->app['eccube.repository.customer_address']->findOneBy( |
|
385 | 7 | array('Customer' => $Customer), |
|
386 | 7 | array('id' => 'ASC') |
|
387 | ); |
||
388 | |||
389 | if (!is_null($CustomerAddress)) { |
||
390 | $Shipping |
||
391 | ->setName01($CustomerAddress->getName01()) |
||
392 | ->setName02($CustomerAddress->getName02()) |
||
393 | ->setKana01($CustomerAddress->getKana01()) |
||
394 | ->setKana02($CustomerAddress->getKana02()) |
||
395 | ->setCompanyName($CustomerAddress->getCompanyName()) |
||
396 | ->setTel01($CustomerAddress->getTel01()) |
||
397 | ->setTel02($CustomerAddress->getTel02()) |
||
398 | ->setTel03($CustomerAddress->getTel03()) |
||
399 | ->setFax01($CustomerAddress->getFax01()) |
||
400 | ->setFax02($CustomerAddress->getFax02()) |
||
401 | ->setFax03($CustomerAddress->getFax03()) |
||
402 | ->setZip01($CustomerAddress->getZip01()) |
||
403 | ->setZip02($CustomerAddress->getZip02()) |
||
404 | ->setZipCode($CustomerAddress->getZip01() . $CustomerAddress->getZip02()) |
||
405 | ->setPref($CustomerAddress->getPref()) |
||
406 | ->setAddr01($CustomerAddress->getAddr01()) |
||
407 | ->setAddr02($CustomerAddress->getAddr02()); |
||
408 | } else { |
||
409 | $Shipping |
||
410 | ->setName01($Customer->getName01()) |
||
411 | ->setName02($Customer->getName02()) |
||
412 | ->setKana01($Customer->getKana01()) |
||
413 | ->setKana02($Customer->getKana02()) |
||
414 | ->setCompanyName($Customer->getCompanyName()) |
||
415 | ->setTel01($Customer->getTel01()) |
||
416 | ->setTel02($Customer->getTel02()) |
||
417 | ->setTel03($Customer->getTel03()) |
||
418 | ->setFax01($Customer->getFax01()) |
||
419 | ->setFax02($Customer->getFax02()) |
||
420 | ->setFax03($Customer->getFax03()) |
||
421 | ->setZip01($Customer->getZip01()) |
||
422 | ->setZip02($Customer->getZip02()) |
||
423 | ->setZipCode($Customer->getZip01() . $Customer->getZip02()) |
||
424 | ->setPref($Customer->getPref()) |
||
425 | ->setAddr01($Customer->getAddr01()) |
||
426 | ->setAddr02($Customer->getAddr02()); |
||
427 | 5 | } |
|
428 | |||
429 | 7 | return $Shipping; |
|
430 | 8 | } |
|
431 | |||
432 | |||
433 | /** |
||
434 | * 受注明細情報、配送商品情報を作成 |
||
435 | * |
||
436 | * @param Order $Order |
||
437 | * @return Order |
||
438 | */ |
||
439 | 7 | public function getNewDetails(Order $Order) |
|
463 | |||
464 | /** |
||
465 | * 受注明細情報を作成 |
||
466 | * |
||
467 | * @param Product $Product |
||
468 | * @param ProductClass $ProductClass |
||
469 | * @param $quantity |
||
470 | * @return \Eccube\Entity\OrderDetail |
||
471 | */ |
||
472 | 7 | public function getNewOrderDetail(Product $Product, ProductClass $ProductClass, $quantity) |
|
500 | |||
501 | /** |
||
502 | * 配送商品情報を作成 |
||
503 | * |
||
504 | * @param Order $Order |
||
505 | * @param Product $Product |
||
506 | * @param ProductClass $ProductClass |
||
507 | * @param $quantity |
||
508 | * @return \Eccube\Entity\ShipmentItem |
||
509 | */ |
||
510 | 7 | public function getNewShipmentItem(Order $Order, Product $Product, ProductClass $ProductClass, $quantity) |
|
559 | |||
560 | /** |
||
561 | * お届け先ごとの送料合計を取得 |
||
562 | * |
||
563 | * @param $shippings |
||
564 | * @return int |
||
565 | */ |
||
566 | 8 | public function getShippingDeliveryFeeTotal($shippings) |
|
576 | |||
577 | /** |
||
578 | * 商品ごとの配送料を取得 |
||
579 | * |
||
580 | * @param Shipping $Shipping |
||
581 | * @return int |
||
582 | */ |
||
583 | 8 | public function getProductDeliveryFee(Shipping $Shipping) |
|
592 | |||
593 | /** |
||
594 | * 住所などの情報が変更された時に金額の再計算を行う |
||
595 | * |
||
596 | * @param Order $Order |
||
597 | * @return Order |
||
598 | */ |
||
599 | 1 | public function getAmount(Order $Order) |
|
623 | |||
624 | /** |
||
625 | * 配送料金の設定 |
||
626 | * |
||
627 | * @param Shipping $Shipping |
||
628 | * @param Delivery|null $Delivery |
||
629 | */ |
||
630 | 7 | public function setShippingDeliveryFee(Shipping $Shipping, Delivery $Delivery = null) |
|
651 | |||
652 | /** |
||
653 | * 配送料無料条件(合計金額)の条件を満たしていれば配送料金を0に設定 |
||
654 | * |
||
655 | * @param Order $Order |
||
656 | */ |
||
657 | View Code Duplication | public function setDeliveryFreeAmount(Order $Order) |
|
673 | |||
674 | /** |
||
675 | * 配送料無料条件(合計数量)の条件を満たしていれば配送料金を0に設定 |
||
676 | * |
||
677 | * @param Order $Order |
||
678 | */ |
||
679 | View Code Duplication | public function setDeliveryFreeQuantity(Order $Order) |
|
695 | |||
696 | |||
697 | /** |
||
698 | * 商品公開ステータスチェック、在庫チェック、購入制限数チェックを行い、在庫情報をロックする |
||
699 | * |
||
700 | * @param $em トランザクション制御されているEntityManager |
||
701 | * @param Order $Order 受注情報 |
||
702 | * @return bool true : 成功、false : 失敗 |
||
703 | */ |
||
704 | 5 | public function isOrderProduct($em, \Eccube\Entity\Order $Order) |
|
743 | |||
744 | /** |
||
745 | * 受注情報、お届け先情報の更新 |
||
746 | * |
||
747 | * @param Order $Order 受注情報 |
||
748 | * @param $data フォームデータ |
||
749 | */ |
||
750 | 2 | public function setOrderUpdate(Order $Order, $data) |
|
792 | |||
793 | |||
794 | /** |
||
795 | * 在庫情報の更新 |
||
796 | * |
||
797 | * @param $em トランザクション制御されているEntityManager |
||
798 | * @param Order $Order 受注情報 |
||
799 | */ |
||
800 | 1 | public function setStockUpdate($em, Order $Order) |
|
825 | |||
826 | |||
827 | /** |
||
828 | * 会員情報の更新 |
||
829 | * |
||
830 | * @param Order $Order 受注情報 |
||
831 | * @param Customer $user ログインユーザ |
||
832 | */ |
||
833 | 1 | public function setCustomerUpdate(Order $Order, Customer $user) |
|
850 | |||
851 | |||
852 | /** |
||
853 | * 支払方法選択の表示設定 |
||
854 | * |
||
855 | * @param $payments 支払選択肢情報 |
||
856 | * @param $subTotal 小計 |
||
857 | * @return array |
||
858 | */ |
||
859 | 10 | public function getPayments($payments, $subTotal) |
|
877 | |||
878 | /** |
||
879 | * お届け日を取得 |
||
880 | * |
||
881 | * @param Order $Order |
||
882 | * @return array |
||
883 | */ |
||
884 | 2 | public function getFormDeliveryDates(Order $Order) |
|
922 | |||
923 | /** |
||
924 | * 支払方法を取得 |
||
925 | * |
||
926 | * @param $deliveries |
||
927 | * @param Order $Order |
||
928 | * @return array |
||
929 | */ |
||
930 | 3 | public function getFormPayments($deliveries, Order $Order) |
|
952 | |||
953 | /** |
||
954 | * お届け先ごとにFormを作成 |
||
955 | * |
||
956 | * @param Order $Order |
||
957 | * @return \Symfony\Component\Form\Form |
||
958 | */ |
||
959 | 1 | public function getShippingForm(Order $Order) |
|
985 | |||
986 | } |
||
987 |