Do they belong to you? Claim these comments.
Unregistered
aliases
- Thomas Kjeldahl Nilsson
- Thomas Kjeldahl Nilsson
- Thomas Kjeldahl Nilsson
Thomas Kjeldahl Nilsson
Is this you? Claim Profile »
2 weeks ago
in Unit testing tricks: Look ma, no setters! on Thinking inside a bigger box
Two small additional points:
- I'd also be a little thrown off if I was reading the domain object code and seeing a bunch of fields set to protected instead of private for no apparent reason. Yes, tests are supposed to function as documentation but I don't always start reading unknown code from that direction.
- Position of arguments in the factory methods wouldn't be an issue if the desired object state was passed as a single struct / DTO instead. Of course, at this point you start to accumulate some noticeable infrastructure in the domain logic just to support tests, but I'd still prefer one/few factory objects over a lot of ad hoc object initialization all over the test cases. Again, personal preference. :)
- I'd also be a little thrown off if I was reading the domain object code and seeing a bunch of fields set to protected instead of private for no apparent reason. Yes, tests are supposed to function as documentation but I don't always start reading unknown code from that direction.
- Position of arguments in the factory methods wouldn't be an issue if the desired object state was passed as a single struct / DTO instead. Of course, at this point you start to accumulate some noticeable infrastructure in the domain logic just to support tests, but I'd still prefer one/few factory objects over a lot of ad hoc object initialization all over the test cases. Again, personal preference. :)
1 reply
2 weeks ago
in Unit testing tricks: Look ma, no setters! on Thinking inside a bigger box
Neat solution!
However, I think (and this is just a personal preference) that encurring the resulting WTF moment for all subsequent maintainers of the code can be a steep price to pay just to be able to set a bunch of methods protected instead of public. I guess it depends how much of a OO purist you are vs what sort of people are going to maintain that code.
Related question: would you be violently opposed to adding a function Account.getTestAccountInstance([state representation]) and set the domain object state for tests in that way? Not elegant, adds ugly non-domain-logic to the domain objects API but more readable and less WTF factor - at least to my eyes.
However, I think (and this is just a personal preference) that encurring the resulting WTF moment for all subsequent maintainers of the code can be a steep price to pay just to be able to set a bunch of methods protected instead of public. I guess it depends how much of a OO purist you are vs what sort of people are going to maintain that code.
Related question: would you be violently opposed to adding a function Account.getTestAccountInstance([state representation]) and set the domain object state for tests in that way? Not elegant, adds ugly non-domain-logic to the domain objects API but more readable and less WTF factor - at least to my eyes.
1 reply
jhannes
This is indeed a tricky tradeoff. (However, I don't think I'd set the *fields* public to support tests!)
We use Account.createAccountWithBalance() for similar cases. But when we found that each test needed to setup about 5 of 10 possible fields (different 5 for different tests), factory methods started to become confusing as well.
The tradeoff between a complex factory method and this trick is that the {{}}-trick is harder to understand the first time, but it's usually easier to read when a number of fields are being initialized (as opposed to remembering the position of each factory method argument).
Then there's the inner builder pattern....
We use Account.createAccountWithBalance() for similar cases. But when we found that each test needed to setup about 5 of 10 possible fields (different 5 for different tests), factory methods started to become confusing as well.
The tradeoff between a complex factory method and this trick is that the {{}}-trick is harder to understand the first time, but it's usually easier to read when a number of fields are being initialized (as opposed to remembering the position of each factory method argument).
Then there's the inner builder pattern....
11 months ago
in [link] Package by feature on Thinking inside a bigger box
As to the original request of your blog post: "stand up and be counted:" You'll have to count me twice.
We implement a proprietary technology stack in-house, this code is packaged by layer. Services / features running on top of that however are packaged by "service" as much as possible... except for some small util bits which I can't be bothered to put in their own projects. ;)
I guess I really just have trouble with the either-or tone of the referenced article. There are no "best practices", only good ones in a given situation.
We implement a proprietary technology stack in-house, this code is packaged by layer. Services / features running on top of that however are packaged by "service" as much as possible... except for some small util bits which I can't be bothered to put in their own projects. ;)
I guess I really just have trouble with the either-or tone of the referenced article. There are no "best practices", only good ones in a given situation.
11 months ago
in [link] Package by feature on Thinking inside a bigger box
Let's say both "product" and "order" use the same bit of util code for authorization before running any given function?
I suppose I was thinking about crosscutting concerns/"infrastructure code" here, not domain logic. I'm having trouble coming up with a domain class that can't be its own feature. :)
Anyway. Unless everything in the project problem space is covered exactly by a specific function call to some external library or service - where do I put things like util classes, wrappers, adapters, bridge code ...?
If package-by-layer is completely verboten (like the tone of the article implies, e.g no com.app.util package), then doesn't it follow that every bit of util/infrastructure code (which is used by more than one feature) will have to go into a separate library - giving me more cruft to worry about in my build environment etc?
I suppose I was thinking about crosscutting concerns/"infrastructure code" here, not domain logic. I'm having trouble coming up with a domain class that can't be its own feature. :)
Anyway. Unless everything in the project problem space is covered exactly by a specific function call to some external library or service - where do I put things like util classes, wrappers, adapters, bridge code ...?
If package-by-layer is completely verboten (like the tone of the article implies, e.g no com.app.util package), then doesn't it follow that every bit of util/infrastructure code (which is used by more than one feature) will have to go into a separate library - giving me more cruft to worry about in my build environment etc?
11 months ago
in [link] Package by feature on Thinking inside a bigger box
From the article:
"Let's see. I wonder where this item is located....Oh, here it is. And everything else I am going to need is right here too, all in the same spot. Excellent."
I wonder; where in the package structure does the author of the article propose I put domain classes/functions which are used by more than one feature? :)
"Let's see. I wonder where this item is located....Oh, here it is. And everything else I am going to need is right here too, all in the same spot. Excellent."
I wonder; where in the package structure does the author of the article propose I put domain classes/functions which are used by more than one feature? :)
2 years ago
in A Hopeful Idea: The End of Checked Exceptions? on Thinking inside a bigger box
*Voted*
Checked exceptions = one of the more annoying java quirks after I got back into other languages on a daily basis. "Why do I have to deal with this crap?"
Checked exceptions = one of the more annoying java quirks after I got back into other languages on a daily basis. "Why do I have to deal with this crap?"
When the problem starts to scale, I might consider builders, structs, introducing setters or something else. But it seems like a lot of extra code to write for the size of the problem.
There's a lot of tools in the "object initialization in test" toolbox. I'm still not thrilled with any of them.