Long Parameter List¶
Given following class Order:
class Order:
_id: str
_customer_id: str
_customer_address: str
_has_priority: bool
_product_ids: list[str]
def __init__(
self,
id: str,
customer_id: str,
customer_address: str,
product_ids: list[str],
is_premium_customer: bool,
) -> None:
self._id = id
self._customer_id = customer_id
self._customer_address = customer_address
self._product_ids = product_ids.copy()
self._has_priority = is_premium_customer
def get_product_ids(self):
return self._product_ids
def get_customer_id(self) -> str:
return self._customer_id
Issues¶
Make id parameter optional¶
This would require moving the parameter to the end breaking all client code.
Knowing too much¶
Initializer receives a set of arguments which characterize customer. This introduces strong coupling between customer details and order. What if we need to add another customer attribute?
This would break all client code.
Parameter order¶
Because the list of parameters is more than 2-3, it is very likely the client code to pass parameters in wrong order.
Solution 1
One possible approach is to make all parameters keyword parameters, by specifying asterisk ‘*’ after the self parameter. This will force the client code to always pass keyword arguments.
Further to address the knowledge about customer we create a Customer class and replace all customer-related parameters with a single parameter customer.
1from dataclasses import dataclass
2from uuid import uuid4
3
4@dataclass
5class Customer:
6 id: str
7 address: str
8 has_premium_subscription: bool = False
9
10class Order:
11 _id: str
12 _customer: Customer
13 _product_ids: list[str]
14
15 def __init__(
16 self,
17 *,
18 customer: Customer,
19 product_ids: list[str],
20 id: str = None
21 ) -> None:
22 self._id = id | uuid4()
23 self._customer = customer
24 self._product_ids = product_ids.copy()
25
26 def get_product_ids(self):
27 return self._product_ids
28
29 def get_customer_id(self) -> str:
30 return self._customer_id