Eric Graysman

Greenhorn
+ Follow
since Sep 11, 2019
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
2
Given in last 30 days
2
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Eric Graysman

Ok so I have read a bit more since yesterday about Anemic vs Rich domain models, and Application Services vs Domain services. And Controllers.

Now there seems to be quite a bit of confusion and differences in this regards. Some would say my "orchestrator" is an application service. Others would say its an Controller. My personal view is tainted by the fact that ive been doing MVC for many years in the old days. So for me a Controller is an MVC thing.
What would you say is the reasons behind you wanting it to be called a Controller and not an Application Service?

Junilu Lacar wrote:

Eric Graysman wrote:Yes the PricingService might be a God class, so im happy to hear other suggestions on how to design it
But its not really doing anything but orchestrating the flow of calls to other components. So it does not contain any other logic than that.
How would you design it?


Well, I'd start with names. If PricingService is, as you say, only orchestrating the flow of calls to other components, it sounds to me like it's a Controller of some sort. That's what controllers do. They know the flow and they know about dependencies between different parts of the system. So I'd separate the flow control logic out to a PricingRequestController or some similarly-named class. Then I'd write my first test.


Then I'd see if that test code told a good, sensible story. If not, then I'd look at a different design option and experiment with that.

Assuming I feel good so far, I'd write another test, to extend the story told by the tests so that we're testing the next step in the process flow. And so on and so forth, over and over again, experimenting, learning, evaluating options, then either continuing or pivoting to a different design option. All the while, I have tests that tell me everything I believe so far about the system and how it works is correct (assuming my tests are all passing).



Thanks! I really appriciate your input This is a good start. I think PricingRequestController is a great name.
I completly agree with you on the testing bit. I will try your suggestions around this and see how i manage.
Im also chewing a bit on your rich domain model stuff from above. Maybe the DTOs could really just be Domain objects. And the API can translate directly to domain objects. That does sound kind of good. Altough im a bit afraid that would make the domain objects really big with lots of responsibility. I must read a bit more about this subject to understand it i think.

Junilu Lacar wrote:That description just makes me think "God class" -- you're say "still inside PricingService.getPrice()" waay too much, even for things that really have to do with Customer, like customer validation.

The other thing that jumps out at me about your description is this: "How the hell are you going to test that?" and I'm guessing the answer is going to be something along the lines of "Well, it's complicated."  The way you described it, you bet your bottom it's going to be complicated to test. I'm guessing that currently, any testing you're doing needs a full environment, maybe submitting requests through PostMan or a similar tool, looking at log files, and a whole lot of other tedious and time-consuming things. Is that a good ballpark estimate or did I hit it right on the money and out of the park?



Yes the PricingService might be a God class, so im happy to hear other suggestions on how to design it
But its not really doing anything but orchestrating the flow of calls to other components. So it does not contain any other logic than that.
How would you design it?

As for testing, its not been built yet, still just in early design/testing/proof of concept phase so thats why i need some solid advice
But im planning that each of the components called by the PricingService can be tested in isolation, and the api layer can be tested in isolation. But to test it the PricingService in full with all its dependencies there would need to be loaded quite a bit of the context yes.

Thanks for all your helpful input!
Ok, so let me first adress a couple of questions:

Junilu Lacar wrote:

Eric Graysman wrote: ... But im not really liking this, because the Product and the PriceRequest are actually just immutable DTOs, and it dont feel right to but business logic into them.
Also it wouldnt feel natural to inject the necessary dependencies to external services into the Product.


Make sure you are clear on the difference between DTOs vs Domain Objects -- DTOs have their use but people often misuse them. I have a feeling you are misusing them. See https://martinfowler.com/bliki/LocalDTO.html


Thanks for this tip. I just read the article by Martin Fowler, and the reason we are doing this is the same reason he states in his last paragraph. "When there is a significant mismatch between the presentation layer and the underlaying domain-model". For us, the presentation-layer is dictated by WSDLs of witch we have no control over, so we need to map over to a DTO with a guaranteed valid and immutable state.
This is our PriceRequest object, and the collection of Products that it contains.

As another one pointed out, PriceRequest might not be the best name of this object, maybe PricingContext is more suitable.

Yes, the price depends on the Customer and the Product, so it would make sense to have those two objects as input to the pricingService. But we also need another step as you will see below. (See step 3)

First of all, lets assume we have 4 different Products. WindowProduct, DoorProduct, BalconyProduct and SofaProduct. (This is not real products btw. just using random names for anonymity). Each of these products naturally have really different attributes/variables, and they are all custom products.

Now let me rewind back a bit and explain briefly our current flow:
1. Incomming request to API. Authorization, input validation and transformation to PriceRequest happens here. PriceRequest is immutable and contains enough information to fetch the Customer, although not the Customer object itself. It also contains a List of something that extends BaseProducts.
2. API layer calls Business layers PricingService.getPrice(priceRequest).
3. Inside PricingService.getPrice: Fetch Customer and do customer validation-checks
4. Still inside PricingService.getPrice: Then for-each product do: product-specific-stuff (input is product and customer). And do fetch price from external service (input is product and customer)
5. Still inside PricingService.getPrice: Collect all prices and return PriceResponse to API-layer
6. API layer transform PriceResponse to API presentation model.

Currently the PricingService is our Orchestrator, that orchestrates which steps is necessary to fetch the price. The PricingService will fetch the Customer, validate the customer, and orchestrate which product specific rules are run and what external service is called.
Im specially interested in how to best design our step 3 and 4.

We need someone to fetch the Customer and validate the Customer based upon the PriceRequest / PricingContext. Maybe PriceService is not the right name?
We do have a CustomerService that can fetch and validate the Customer, but we need someone to orchestrate the calls to this service.
We need to design some inheritance / composition aroundt the Products so we can iterate them and do product-specific checks and product-specific price fetching in an elegant way. Preferably not using instance-of, and preferably not by adding business logic into the Product objects.

The best i have come up with so far is:
1. PriceService.getPrice(PricingContext/PriceRequest) - Orchestrator
2. Inside PriceService.getPrice, fetch Customer and validate customer
3. Inside PriceService.getPrice, for each product do instance-of checks and call product specific service e.g. WindowProductService.productValidation(product) and WindowProductService.getExternalPrice(customer, product).

This feels sub-optimal.

I would prefer to remove the instance-of checks, but i cant see how at the moment. The only way i can see is to have the specific Products themself have a reference to the correct productValidationService and the correct externalProductPriceService. But in order to achive that i would have to put that into an Object i have though of as a DTO. But maybe its not really a DTO? Maybe thats ok?
Im currently designing a solution where I need some input. Im programming in Java.

There is an incomming request, containing personal information, and a list of products that the person wants prices on.
There is multiple different input API`s. But every API validates and transforms the input to PriceRequest object.
This PriceRequest object contains the personal information, and also the list of Products the person wants prices on.
Each Product can be one of about 8 different Products. And each of those 8 different Products have different properties that the customer is setting for customizing the product. They share no common properties expect they all are a Product.

When processing the incomming request we pass the PriceRequest to a PriceService.getPrice.
The PriceService validates customer and does a number of required steps.
Then for each Product in the PriceRequest, we must do product specific validation, apply product specific rules and call an external pricing service. The external pricing service is different for each Product. So again, the Products share not much, but they do share a common way of being processed, but the processing differs for each Product.

So im thinking about how to best design this in our system.
At first i was thinking that each Product can inherit from a BaseProduct, and the BaseProduct has abstract methods for validating product , running product rules and getting price from external service. This would make code simple, as PriceService can then for each product just call these methods in the correct order.
But im not really liking this, because the Product and the PriceRequest are actually just immutable DTOs, and it dont feel right to but business logic into them.
Also it wouldnt feel natural to inject the necessary dependencies to external services into the Product.

Next i was thinking that in PriceService i can, for each product, have if-instanceof statements and hard code different instances to do different kind of things. But now it feels like im putting to much into the PriceService, also it feels a bit akward.

Next i was think Template Method Pattern, creating an abstract ProductService with abstract methods, and then implementing product specific ProductServices. This feels better, but still it would require me to have those ugly if-instance-of statements inside the PriceService and delegating to the corrrect product specific service.

Does anyone have any better ideas for me? I would be really happy if anyone would have some tips on a Pattern or way of doing this that would be more natural and better suited.
Or just confirm if im on the right track or not.

Happy for all feedback!
Let me know if i need to clarify something.