Stan Belen wrote:
One of the problems with this implementation is that we can't unit test the various conditions and their outcomes without having to not worry about the functionality that follows in this method.
how to go about implementing these various functionalities to meet best practices (SOLID principles, etc.)? For example, one thing that stands out is the violation of the Single Responsibility principle.
Junilu Lacar wrote:To me, I don't look at a functionality as having to do anything other than to make sense where it belongs, and for it to make sense to be exercised the way I design it.
Stan Belen wrote:
That looks like a Map of some sort. Please consider whether you can design such a Map.Stan Belen wrote: . . . A Person's address is stored as one of the attributes . . .
Decide how many attributes are essential, remembering some People lack some attributes, LandLinePhoneNumber being a common one.
might be null might not be null but it might not contain an address might not be null and it might contain an address
I am afraid, that looks wrong in two ways. That method should be called on the object and should therefore not need the Person parameter. What you wrote could readily be converted to a static method, which makes me suspicious about it.. . .. . .
Of course: Junilu said it long before I did.Junilu Lacar wrote:. . . Why isn't the design such that we can just write this:
?
Junilu Lacar wrote:
Stan Belen wrote:
One of the problems with this implementation is that we can't unit test the various conditions and their outcomes without having to not worry about the functionality that follows in this method.
Please explain what you mean by the italicized part of what I quoted above. What functionality are you referring to that you don't want to worry about? Because when you're unit testing something, you are worrying about the functionality that you're testing.
Junilu Lacar wrote:
Stan Belen wrote:how to go about implementing these various functionalities to meet best practices (SOLID principles, etc.)? For example, one thing that stands out is the violation of the Single Responsibility principle.
Again, what are these various functionalities you're referring to? And what do you mean when you say they have to "meet best practices"?
To me, I don't look at a functionality as having to do anything other than to make sense where it belongs, and for it to make sense to be exercised the way I design it.
Junilu Lacar wrote:
Junilu Lacar wrote:To me, I don't look at a functionality as having to do anything other than to make sense where it belongs, and for it to make sense to be exercised the way I design it.
For example, I don't think this proposed design makes sense from an object-oriented programming perspective:
Why don't I think it makes sense? Because it smells of broken encapsulation. Why would the logic to update a person's address be separate from the address and the person objects?
Why isn't the design such that we can just write this:
?
Junilu Lacar wrote:Also, what's with this line in the example code?
Stan Belen wrote:
If you're looking to follow "best practice", you would NOT be thinking about adding a bunch of other stuff into an already big method like that and make it even bigger.
The idea of encapsulation and loose coupling is that you can change the implementation of the object without affecting how it is perceived by other code via its interface.Stan Belen wrote:. . . this is a legacy DTO.
So, suppose it's used in a lot of places. . . .
Campbell Ritchie wrote:The idea of encapsulation and loose coupling is that you can change the implementation of the object without affecting how it is perceived by other code via its interface.
Writing a static method and disguising it as an instance method does, of course, make that result so much harder to achieve.
Campbell Ritchie wrote:That looks so very complicated. You can probably dispense with the Stream altogether. If you have a Map, you can simply call put(...) onit. Remember there are methods like putIfEmpty(...) or similar in Map.
Junilu Lacar wrote:When something is difficult to test, you refactor it so that it's easy to test.
Junilu Lacar wrote:Mixing in a API call inside a method like updateAddress seems like a poor choice. I would separate those two concerns.
Stan Belen wrote:
I am trying to implement functionality, ...
Suppose we have a legacy DTO that we cannot change, Person:
...
I need to create a method that will update a person's address and then do some other stuff, for example, call a Human Resources System API.
Stan Belen wrote:How can I restructure this code to be able to unit test it?
Junilu Lacar wrote:
Stan Belen wrote:How can I restructure this code to be able to unit test it?
Ironically, you'd write a unit test that would show you the ideal structure of the code so that it can be tested in isolation.
Let's see how you react to this first before I explain further.
Stan Belen wrote:is it okay if I'll create a public github project for the purpose
Junilu Lacar wrote:That is an excellent idea. And yes, I'm saying that you would test-drive the refactoring of the code.
Stan Belen wrote:
Questions
Question 1: is it fine how I used TDD to implement Person::setAddress?
Question 2: how would you go about in implementing the requirements, described in the README.md of the project?
Suppose we are given the following assignment: Implement a service that takes as input a person ID and an address, and updates the person's address in DB and calls the HRService::updatePersonInfo
Stan Belen wrote:Question 1: is it fine how I used TDD to implement Person::setAddress?
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime. |