How to design my code so that it can use alternative information to help create an object

I have a class named Product, which takes a product model number and number of wheels for that product as part of its creation information, and then it instantiates the product by doing a computation on the number of wheels and on various base parameters

For example, Product(5, 22) creates a model 5 product with 22 wheels on it, where that particular product’s weight and dimensions are computed from the number of wheels and from the base specifications for that model number. Right now base specifications are part of the class itself and are hardcoded into the class, along with the computation formulas.

My Issue: in the (legacy) code I am working with, I cannot always use the model number directly. It may not be available. Instead, an unrelated product_id is given, where the link between product_id and model_number is in the database.

I want to keep my class as simple as possible. As such I do not want to introduce another constructor that allows product_id as an input parameter, in addition to the existing model_number, as it will be duplication of code. Also, I am not too keen on putting database logic inside the class, but maybe I can, as thinking about it now, this may be a good candidate for a database-wrapper class, i.e. active record (where my base specifications can be moved off from the code and into the database).

Question: How do I create and return the object while following good object oriented principles when the model_number I typically use for its creation is not available, but another parameter is available instead (product_id in this case), which links 1:1 to model_number?

Sample solutions that I don’t quite like:

  • Do not involve the database — since I am working with just a few Products at this time, and Products do not change often, I can create a “conversion function” that serves as a map between product_id and model_number and not touch the database. Similarly, create a Convert object that has same functionality and use it before creating the object. Problem: duplicating DB functionality in the code.
  • Put DB functionality inside code and add alternate constructor. Problem: multiple entry-points of Product creation for the class create code duplication.

Update:

There basically are 3 aspects here:

  • base data (whether hardcoded or part of the database)
  • finding base data by various parameters be it model number or other identifying information
  • doing computation using base data as per model number

I’d like to build upon the solution @TMN is presenting and take it a little further to answer your SRP problem. Putting database code inside the ProductFactory would be non-sensical so to encapsulate this responsibility you can create a separate class ProductModelNumberProvider with just one method findByProductId(int productId).

The ProductFactory should provide a setter setProductModelNumberProvider(ProductModelNumberProvider lookupProvider) which will assign the provider internally and call findByProductId() when appropriate.

You will have a ProductFactory which is responsible for building the product and a ProductModelNumberProvider which will do the database interaction if needed.

Have a look at your StackOverflow question for a more concrete example.

4

Maybe create a ProductFactory, with methods to create a Product given a number of wheels and either a product ID or a model number. Given a model number it defers to the class’ constructor, and if given a product ID it performs the DB lookup, gets the model number, then defers to the class constructor.

2

You don’t want to duplicate the DB mapping product_id -> model_number by hardcoding the logic, that makes sense. So the first thing you need is a function like

int mapProductIdToModelNumber(int product_id)

which does this mapping by getting the information from the database (consider caching when this function is used very often).

What remains is how to make this function available to your Product class without tight coupling. You have the following alternatives:

  • pass the function directly to the code blocks whereever Product objects are created (depends on your programming language how to accomplish that)

  • implement the function in a ProductFactory class. Derive ProductFactory from an interface IProductFactory and pass an object of this type to the code areas where you currently want a new Product(). Use the factory the way @TMN suggested.

That way, your legacy code stays decoupled from the database, since it won’t depend directly from a database-bound ProductFactory, only from IProductFactory, which can be easily mocked out (for example, for testing purposes).

9

Maybe this — give up the idea of a Product class and create a DB-wrapper where I will say $pf = ProductFinder(), then do $pf->findById() and $pf->findByModel() as needed. Problem: Where do I put my computation code? It can’t be in the same place, as it it will violate Single Responsibility Principle. aka, computation and data handling should be separate. Then maybe Product class can be the computational part, and ProductFinder be the database pulling part.

What I actually ended up doing:

At first I was wondering if I am better off with such complexity.

Simpler way was:

There is another pattern here that I could use that keeps things in one class: https://stackoverflow.com/a/2175213/2883328. Breaks SRP.

$product = Product::fromProductId($productId, $wheels);

SRP way (chosen)

  • ProductData class that just has the data (can be swapped by database later)
  • ProductFactory class that uses Provider class to look up the model number
  • ProductNumberProvider class that provides model number when given product id
  • Product class that does loads ProductData and does computations

Code:

$provider = new ProductModelNumberProvider();
$factory = new ProductFactory($provider);
$product = $factory->constructFromProductId($productId, $wheels);

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật