Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|
Thanks, Peter, I’m glad you liked my article.
Taking my best guess at what your example does, it looks like there are a few misconceptions:
1. Nullable Infrastructure is a pattern used within production code to make that code testable. It looks like you’re trying to apply it to test code.
2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
Taking my best guess at what this example is supposed to do, I would rewrite ShopShould as follows:
@Test void calculateTotalPrice_ViaCalculator() { ? Shop testee = new Shop( ? ? RebateServiceAdapter.createNull(), ? ??//?‘1’ is the desired response from the StateTaxesServiceAdapter. ? ? // A real system would have more sophisticated response configuration. ? ? StateTaxesServiceAdapter.createNull(1), ? ? // NotificationServiceAdapter might use SlowLDAPImplementationAdapter, via ? ? // composition rather than inheritance, under the hood. ? ? NotificationServiceAdapter.createNull() ? );
? double totalPrice = testee.getTotalPrice(1, 2,?“any ignored”);
? assertThat(totalPrice).isEqual(2); }
All the classes inside ShopShould would go away, as would the Port interfaces. The various Adapters would get an Embedded Stub to support their new createNull() methods.
Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations. (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.) They aren’t needed for testing purposes when using Nullable Infrastructure.
(As an aside, my naming would typically be “RebateServiceClient,” not “RebateServiceAdapter,” but I wanted to stay close to your naming convention.)
Cheers, James
toggle quoted message
Show quoted text
On Mar 26, 2021, at 3:16 AM, Peter Gfader < peter@...> wrote:
Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
<image.png>
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|
Thanks James
Your response was exactly what I was looking for!
>> 2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
I like that approach since it feels more normal to me. Thanks
>> Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations.? >> (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.)? >> They aren’t needed for testing purposes when using Nullable Infrastructure.
The current team is relying on Ports and Adapters Architecture heavily and take this approach.? I am using this playground to practice and learn and think about these things.
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
THANKS ? Peter Gfader Sent from a mobile device. Tiny keys => Tiny emails
On Fri, Mar 26, 2021 at 7:31 PM Jim Shore < jshore@...> wrote: Thanks, Peter, I’m glad you liked my article.
Taking my best guess at what your example does, it looks like there are a few misconceptions:
1. Nullable Infrastructure is a pattern used within production code to make that code testable. It looks like you’re trying to apply it to test code.
2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
Taking my best guess at what this example is supposed to do, I would rewrite ShopShould as follows:
@Test void calculateTotalPrice_ViaCalculator() { ? Shop testee = new Shop( ? ? RebateServiceAdapter.createNull(), ? ??//?‘1’ is the desired response from the StateTaxesServiceAdapter. ? ? // A real system would have more sophisticated response configuration. ? ? StateTaxesServiceAdapter.createNull(1), ? ? // NotificationServiceAdapter might use SlowLDAPImplementationAdapter, via ? ? // composition rather than inheritance, under the hood. ? ? NotificationServiceAdapter.createNull() ? );
? double totalPrice = testee.getTotalPrice(1, 2,?“any ignored”);
? assertThat(totalPrice).isEqual(2); }
All the classes inside ShopShould would go away, as would the Port interfaces. The various Adapters would get an Embedded Stub to support their new createNull() methods.
Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations. (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.) They aren’t needed for testing purposes when using Nullable Infrastructure.
(As an aside, my naming would typically be “RebateServiceClient,” not “RebateServiceAdapter,” but I wanted to stay close to your naming convention.)
Cheers, James
On Mar 26, 2021, at 3:16 AM, Peter Gfader < peter@...> wrote:
Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
<image.png>
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|
Glad it helped!
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
Yes, that’s my favorite part. There’s some ugliness, to be sure, but overall it’s made my code simpler and tests easier to write.
Cheers, James On Mar 29, 2021, at 12:29 AM, Peter Gfader < peter@...> wrote:
Thanks James
Your response was exactly what I was looking for!
>> 2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
I like that approach since it feels more normal to me. Thanks
>> Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations.? >> (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.)? >> They aren’t needed for testing purposes when using Nullable Infrastructure.
The current team is relying on Ports and Adapters Architecture heavily and take this approach.? I am using this playground to practice and learn and think about these things.
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
THANKS ? Peter Gfader Sent from a mobile device. Tiny keys => Tiny emails
On Fri, Mar 26, 2021 at 7:31 PM Jim Shore < jshore@...> wrote: Thanks, Peter, I’m glad you liked my article.
Taking my best guess at what your example does, it looks like there are a few misconceptions:
1. Nullable Infrastructure is a pattern used within production code to make that code testable. It looks like you’re trying to apply it to test code.
2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
Taking my best guess at what this example is supposed to do, I would rewrite ShopShould as follows:
@Test void calculateTotalPrice_ViaCalculator() { ? Shop testee = new Shop( ? ? RebateServiceAdapter.createNull(), ? ??//?‘1’ is the desired response from the StateTaxesServiceAdapter. ? ? // A real system would have more sophisticated response configuration. ? ? StateTaxesServiceAdapter.createNull(1), ? ? // NotificationServiceAdapter might use SlowLDAPImplementationAdapter, via ? ? // composition rather than inheritance, under the hood. ? ? NotificationServiceAdapter.createNull() ? );
? double totalPrice = testee.getTotalPrice(1, 2,?“any ignored”);
? assertThat(totalPrice).isEqual(2); }
All the classes inside ShopShould would go away, as would the Port interfaces. The various Adapters would get an Embedded Stub to support their new createNull() methods.
Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations. (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.) They aren’t needed for testing purposes when using Nullable Infrastructure.
(As an aside, my naming would typically be “RebateServiceClient,” not “RebateServiceAdapter,” but I wanted to stay close to your naming convention.)
Cheers, James
On Mar 26, 2021, at 3:16 AM, Peter Gfader < peter@...> wrote:
Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
<image.png>
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|
I'm curious why you chose a createNull function instead of a null representative base class.?
toggle quoted message
Show quoted text
On Mon, 29 Mar 2021, 22:15 Jim Shore, < jshore@...> wrote: Glad it helped!
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
Yes, that’s my favorite part. There’s some ugliness, to be sure, but overall it’s made my code simpler and tests easier to write.
Cheers, James On Mar 29, 2021, at 12:29 AM, Peter Gfader < peter@...> wrote:
Thanks James
Your response was exactly what I was looking for!
>> 2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
I like that approach since it feels more normal to me. Thanks
>> Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations.? >> (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.)? >> They aren’t needed for testing purposes when using Nullable Infrastructure.
The current team is relying on Ports and Adapters Architecture heavily and take this approach.? I am using this playground to practice and learn and think about these things.
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
THANKS ? Peter Gfader Sent from a mobile device. Tiny keys => Tiny emails
On Fri, Mar 26, 2021 at 7:31 PM Jim Shore < jshore@...> wrote: Thanks, Peter, I’m glad you liked my article.
Taking my best guess at what your example does, it looks like there are a few misconceptions:
1. Nullable Infrastructure is a pattern used within production code to make that code testable. It looks like you’re trying to apply it to test code.
2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
Taking my best guess at what this example is supposed to do, I would rewrite ShopShould as follows:
@Test void calculateTotalPrice_ViaCalculator() { ? Shop testee = new Shop( ? ? RebateServiceAdapter.createNull(), ? ??//?‘1’ is the desired response from the StateTaxesServiceAdapter. ? ? // A real system would have more sophisticated response configuration. ? ? StateTaxesServiceAdapter.createNull(1), ? ? // NotificationServiceAdapter might use SlowLDAPImplementationAdapter, via ? ? // composition rather than inheritance, under the hood. ? ? NotificationServiceAdapter.createNull() ? );
? double totalPrice = testee.getTotalPrice(1, 2,?“any ignored”);
? assertThat(totalPrice).isEqual(2); }
All the classes inside ShopShould would go away, as would the Port interfaces. The various Adapters would get an Embedded Stub to support their new createNull() methods.
Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations. (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.) They aren’t needed for testing purposes when using Nullable Infrastructure.
(As an aside, my naming would typically be “RebateServiceClient,” not “RebateServiceAdapter,” but I wanted to stay close to your naming convention.)
Cheers, James
On Mar 26, 2021, at 3:16 AM, Peter Gfader < peter@...> wrote:
Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
<image.png>
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|
I also was thinking about that. I can imagine that the motivation is to have everything about the adapter encapsulated in one place, one file. So there are not several classes laying around that you have to find and organize. There is just one thing, and if you want to test it, there's a createNull function in place. Yes, the thing becomes bigger, yes the thing contains test-code. But it is cohesive. Avi Kessner < akessner@...> schrieb am Di., 30. M?rz 2021, 09:23:
toggle quoted message
Show quoted text
I'm curious why you chose a createNull function instead of a null representative base class.?
On Mon, 29 Mar 2021, 22:15 Jim Shore, < jshore@...> wrote: Glad it helped!
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
Yes, that’s my favorite part. There’s some ugliness, to be sure, but overall it’s made my code simpler and tests easier to write.
Cheers, James On Mar 29, 2021, at 12:29 AM, Peter Gfader < peter@...> wrote:
Thanks James
Your response was exactly what I was looking for!
>> 2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
I like that approach since it feels more normal to me. Thanks
>> Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations.? >> (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.)? >> They aren’t needed for testing purposes when using Nullable Infrastructure.
The current team is relying on Ports and Adapters Architecture heavily and take this approach.? I am using this playground to practice and learn and think about these things.
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
THANKS ? Peter Gfader Sent from a mobile device. Tiny keys => Tiny emails
On Fri, Mar 26, 2021 at 7:31 PM Jim Shore < jshore@...> wrote: Thanks, Peter, I’m glad you liked my article.
Taking my best guess at what your example does, it looks like there are a few misconceptions:
1. Nullable Infrastructure is a pattern used within production code to make that code testable. It looks like you’re trying to apply it to test code.
2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
Taking my best guess at what this example is supposed to do, I would rewrite ShopShould as follows:
@Test void calculateTotalPrice_ViaCalculator() { ? Shop testee = new Shop( ? ? RebateServiceAdapter.createNull(), ? ??//?‘1’ is the desired response from the StateTaxesServiceAdapter. ? ? // A real system would have more sophisticated response configuration. ? ? StateTaxesServiceAdapter.createNull(1), ? ? // NotificationServiceAdapter might use SlowLDAPImplementationAdapter, via ? ? // composition rather than inheritance, under the hood. ? ? NotificationServiceAdapter.createNull() ? );
? double totalPrice = testee.getTotalPrice(1, 2,?“any ignored”);
? assertThat(totalPrice).isEqual(2); }
All the classes inside ShopShould would go away, as would the Port interfaces. The various Adapters would get an Embedded Stub to support their new createNull() methods.
Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations. (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.) They aren’t needed for testing purposes when using Nullable Infrastructure.
(As an aside, my naming would typically be “RebateServiceClient,” not “RebateServiceAdapter,” but I wanted to stay close to your naming convention.)
Cheers, James
On Mar 26, 2021, at 3:16 AM, Peter Gfader < peter@...> wrote:
Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
<image.png>
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|
And, most importantly: When you are in a weekly typed language like JavaScript, where you cannot easily find a fake by its port interface, finding is not a problem anymore. Gregor Riegler via <rieglerg85= [email protected]> schrieb am Di., 30. M?rz 2021, 09:38:
toggle quoted message
Show quoted text
I also was thinking about that. I can imagine that the motivation is to have everything about the adapter encapsulated in one place, one file. So there are not several classes laying around that you have to find and organize. There is just one thing, and if you want to test it, there's a createNull function in place. Yes, the thing becomes bigger, yes the thing contains test-code. But it is cohesive.
Avi Kessner < akessner@...> schrieb am Di., 30. M?rz 2021, 09:23: I'm curious why you chose a createNull function instead of a null representative base class.?
On Mon, 29 Mar 2021, 22:15 Jim Shore, < jshore@...> wrote: Glad it helped!
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
Yes, that’s my favorite part. There’s some ugliness, to be sure, but overall it’s made my code simpler and tests easier to write.
Cheers, James On Mar 29, 2021, at 12:29 AM, Peter Gfader < peter@...> wrote:
Thanks James
Your response was exactly what I was looking for!
>> 2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
I like that approach since it feels more normal to me. Thanks
>> Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations.? >> (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.)? >> They aren’t needed for testing purposes when using Nullable Infrastructure.
The current team is relying on Ports and Adapters Architecture heavily and take this approach.? I am using this playground to practice and learn and think about these things.
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
THANKS ? Peter Gfader Sent from a mobile device. Tiny keys => Tiny emails
On Fri, Mar 26, 2021 at 7:31 PM Jim Shore < jshore@...> wrote: Thanks, Peter, I’m glad you liked my article.
Taking my best guess at what your example does, it looks like there are a few misconceptions:
1. Nullable Infrastructure is a pattern used within production code to make that code testable. It looks like you’re trying to apply it to test code.
2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
Taking my best guess at what this example is supposed to do, I would rewrite ShopShould as follows:
@Test void calculateTotalPrice_ViaCalculator() { ? Shop testee = new Shop( ? ? RebateServiceAdapter.createNull(), ? ??//?‘1’ is the desired response from the StateTaxesServiceAdapter. ? ? // A real system would have more sophisticated response configuration. ? ? StateTaxesServiceAdapter.createNull(1), ? ? // NotificationServiceAdapter might use SlowLDAPImplementationAdapter, via ? ? // composition rather than inheritance, under the hood. ? ? NotificationServiceAdapter.createNull() ? );
? double totalPrice = testee.getTotalPrice(1, 2,?“any ignored”);
? assertThat(totalPrice).isEqual(2); }
All the classes inside ShopShould would go away, as would the Port interfaces. The various Adapters would get an Embedded Stub to support their new createNull() methods.
Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations. (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.) They aren’t needed for testing purposes when using Nullable Infrastructure.
(As an aside, my naming would typically be “RebateServiceClient,” not “RebateServiceAdapter,” but I wanted to stay close to your naming convention.)
Cheers, James
On Mar 26, 2021, at 3:16 AM, Peter Gfader < peter@...> wrote:
Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
<image.png>
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|
Avi, I’m not sure what you meant by a null representative base class, but encapsulation is basically it, as Gregor said. But there may be another part you’re missing: the whole point of Nullable Infrastructure is that the null version runs the same code as the production version. The only difference is that, in the null version, the outside world is short-circuited.
How that is done is an implementation detail. It could be done with if statements, but in practice, I find an embedded stub of third-party code to be cleanest. There’s an example at?.
Cheers,
toggle quoted message
Show quoted text
I also was thinking about that. I can imagine that the motivation is to have everything about the adapter encapsulated in one place, one file. So there are not several classes laying around that you have to find and organize. There is just one thing, and if you want to test it, there's a createNull function in place. Yes, the thing becomes bigger, yes the thing contains test-code. But it is cohesive. Avi Kessner < akessner@...> schrieb am Di., 30. M?rz 2021, 09:23: I'm curious why you chose a createNull function instead of a null representative base class.?
On Mon, 29 Mar 2021, 22:15 Jim Shore, < jshore@...> wrote: Glad it helped!
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
Yes, that’s my favorite part. There’s some ugliness, to be sure, but overall it’s made my code simpler and tests easier to write.
Cheers, James On Mar 29, 2021, at 12:29 AM, Peter Gfader < peter@...> wrote:
Thanks James
Your response was exactly what I was looking for!
>> 2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
I like that approach since it feels more normal to me. Thanks
>> Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations.? >> (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.)? >> They aren’t needed for testing purposes when using Nullable Infrastructure.
The current team is relying on Ports and Adapters Architecture heavily and take this approach.? I am using this playground to practice and learn and think about these things.
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
THANKS ? Peter Gfader Sent from a mobile device. Tiny keys => Tiny emails
On Fri, Mar 26, 2021 at 7:31 PM Jim Shore < jshore@...> wrote: Thanks, Peter, I’m glad you liked my article.
Taking my best guess at what your example does, it looks like there are a few misconceptions:
1. Nullable Infrastructure is a pattern used within production code to make that code testable. It looks like you’re trying to apply it to test code.
2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
Taking my best guess at what this example is supposed to do, I would rewrite ShopShould as follows:
@Test void calculateTotalPrice_ViaCalculator() { ? Shop testee = new Shop( ? ? RebateServiceAdapter.createNull(), ? ??//?‘1’ is the desired response from the StateTaxesServiceAdapter. ? ? // A real system would have more sophisticated response configuration. ? ? StateTaxesServiceAdapter.createNull(1), ? ? // NotificationServiceAdapter might use SlowLDAPImplementationAdapter, via ? ? // composition rather than inheritance, under the hood. ? ? NotificationServiceAdapter.createNull() ? );
? double totalPrice = testee.getTotalPrice(1, 2,?“any ignored”);
? assertThat(totalPrice).isEqual(2); }
All the classes inside ShopShould would go away, as would the Port interfaces. The various Adapters would get an Embedded Stub to support their new createNull() methods.
Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations. (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.) They aren’t needed for testing purposes when using Nullable Infrastructure.
(As an aside, my naming would typically be “RebateServiceClient,” not “RebateServiceAdapter,” but I wanted to stay close to your naming convention.)
Cheers, James
On Mar 26, 2021, at 3:16 AM, Peter Gfader < peter@...> wrote:
Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
<image.png>
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|
Thanks.? I meant something like the NullIOServer (D'oh!) Didn't realize it was already doing that just another level deeper. I was expecting something like? NullTaxesServiceAdapter.create()?brought to you by the letters A, V, and I and the number 47
toggle quoted message
Show quoted text
On Tue, Mar 30, 2021 at 6:55 PM Jim Shore < jshore@...> wrote: Avi, I’m not sure what you meant by a null representative base class, but encapsulation is basically it, as Gregor said. But there may be another part you’re missing: the whole point of Nullable Infrastructure is that the null version runs the same code as the production version. The only difference is that, in the null version, the outside world is short-circuited.
How that is done is an implementation detail. It could be done with if statements, but in practice, I find an embedded stub of third-party code to be cleanest. There’s an example at?.
Cheers, James
I also was thinking about that. I can imagine that the motivation is to have everything about the adapter encapsulated in one place, one file. So there are not several classes laying around that you have to find and organize. There is just one thing, and if you want to test it, there's a createNull function in place. Yes, the thing becomes bigger, yes the thing contains test-code. But it is cohesive. Avi Kessner < akessner@...> schrieb am Di., 30. M?rz 2021, 09:23: I'm curious why you chose a createNull function instead of a null representative base class.?
On Mon, 29 Mar 2021, 22:15 Jim Shore, < jshore@...> wrote: Glad it helped!
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
Yes, that’s my favorite part. There’s some ugliness, to be sure, but overall it’s made my code simpler and tests easier to write.
Cheers, James On Mar 29, 2021, at 12:29 AM, Peter Gfader < peter@...> wrote:
Thanks James
Your response was exactly what I was looking for!
>> 2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
I like that approach since it feels more normal to me. Thanks
>> Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations.? >> (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.)? >> They aren’t needed for testing purposes when using Nullable Infrastructure.
The current team is relying on Ports and Adapters Architecture heavily and take this approach.? I am using this playground to practice and learn and think about these things.
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
THANKS ? Peter Gfader Sent from a mobile device. Tiny keys => Tiny emails
On Fri, Mar 26, 2021 at 7:31 PM Jim Shore < jshore@...> wrote: Thanks, Peter, I’m glad you liked my article.
Taking my best guess at what your example does, it looks like there are a few misconceptions:
1. Nullable Infrastructure is a pattern used within production code to make that code testable. It looks like you’re trying to apply it to test code.
2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
Taking my best guess at what this example is supposed to do, I would rewrite ShopShould as follows:
@Test void calculateTotalPrice_ViaCalculator() { ? Shop testee = new Shop( ? ? RebateServiceAdapter.createNull(), ? ??//?‘1’ is the desired response from the StateTaxesServiceAdapter. ? ? // A real system would have more sophisticated response configuration. ? ? StateTaxesServiceAdapter.createNull(1), ? ? // NotificationServiceAdapter might use SlowLDAPImplementationAdapter, via ? ? // composition rather than inheritance, under the hood. ? ? NotificationServiceAdapter.createNull() ? );
? double totalPrice = testee.getTotalPrice(1, 2,?“any ignored”);
? assertThat(totalPrice).isEqual(2); }
All the classes inside ShopShould would go away, as would the Port interfaces. The various Adapters would get an Embedded Stub to support their new createNull() methods.
Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations. (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.) They aren’t needed for testing purposes when using Nullable Infrastructure.
(As an aside, my naming would typically be “RebateServiceClient,” not “RebateServiceAdapter,” but I wanted to stay close to your naming convention.)
Cheers, James
On Mar 26, 2021, at 3:16 AM, Peter Gfader < peter@...> wrote:
Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
<image.png>
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|
Yeah, it’s a level deeper. It’s very different than normal test doubles—normally, the advice is to “never mock what you don’t own,” but with Nullable Infrastructure, you “only [stub] what you don’t own.” By doing this, it ensures that the logic in your adapter (infrastructure wrapper) runs in your tests. That way, if you make a change to the adapter that breaks an assumption somewhere up the call chain, your tests catch it.
The whole "Testing Without Mocks” pattern language centers around using sociable tests rather than solitary tests, thereby simplifying your test code and eliminating the need for broad / end-to-end tests.
Cheers,
toggle quoted message
Show quoted text
On Mar 30, 2021, at 9:08 AM, Avi Kessner < akessner@...> wrote:
Thanks.? I meant something like the NullIOServer (D'oh!) Didn't realize it was already doing that just another level deeper. I was expecting something like? NullTaxesServiceAdapter.create()?brought to you by the letters A, V, and I and the number 47 On Tue, Mar 30, 2021 at 6:55 PM Jim Shore < jshore@...> wrote: Avi, I’m not sure what you meant by a null representative base class, but encapsulation is basically it, as Gregor said. But there may be another part you’re missing: the whole point of Nullable Infrastructure is that the null version runs the same code as the production version. The only difference is that, in the null version, the outside world is short-circuited.
How that is done is an implementation detail. It could be done with if statements, but in practice, I find an embedded stub of third-party code to be cleanest. There’s an example at?.
Cheers, James
I also was thinking about that. I can imagine that the motivation is to have everything about the adapter encapsulated in one place, one file. So there are not several classes laying around that you have to find and organize. There is just one thing, and if you want to test it, there's a createNull function in place. Yes, the thing becomes bigger, yes the thing contains test-code. But it is cohesive. Avi Kessner < akessner@...> schrieb am Di., 30. M?rz 2021, 09:23: I'm curious why you chose a createNull function instead of a null representative base class.?
On Mon, 29 Mar 2021, 22:15 Jim Shore, < jshore@...> wrote: Glad it helped!
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
Yes, that’s my favorite part. There’s some ugliness, to be sure, but overall it’s made my code simpler and tests easier to write.
Cheers, James On Mar 29, 2021, at 12:29 AM, Peter Gfader < peter@...> wrote:
Thanks James
Your response was exactly what I was looking for!
>> 2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
I like that approach since it feels more normal to me. Thanks
>> Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations.? >> (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.)? >> They aren’t needed for testing purposes when using Nullable Infrastructure.
The current team is relying on Ports and Adapters Architecture heavily and take this approach.? I am using this playground to practice and learn and think about these things.
With "Nullable Infrastructure" there is a lot of code that gets simpler... I ? that!
THANKS ? Peter Gfader Sent from a mobile device. Tiny keys => Tiny emails
On Fri, Mar 26, 2021 at 7:31 PM Jim Shore < jshore@...> wrote: Thanks, Peter, I’m glad you liked my article.
Taking my best guess at what your example does, it looks like there are a few misconceptions:
1. Nullable Infrastructure is a pattern used within production code to make that code testable. It looks like you’re trying to apply it to test code.
2. I only use the Nullable Infrastructure pattern on “Infrastructure” objects, which are specifically wrappers/adapters for external systems and state. In your example, I’m not sure where the external system is. I’m guessing it’s “SlowLDAPImplementationAdapter.”
Taking my best guess at what this example is supposed to do, I would rewrite ShopShould as follows:
@Test void calculateTotalPrice_ViaCalculator() { ? Shop testee = new Shop( ? ? RebateServiceAdapter.createNull(), ? ??//?‘1’ is the desired response from the StateTaxesServiceAdapter. ? ? // A real system would have more sophisticated response configuration. ? ? StateTaxesServiceAdapter.createNull(1), ? ? // NotificationServiceAdapter might use SlowLDAPImplementationAdapter, via ? ? // composition rather than inheritance, under the hood. ? ? NotificationServiceAdapter.createNull() ? );
? double totalPrice = testee.getTotalPrice(1, 2,?“any ignored”);
? assertThat(totalPrice).isEqual(2); }
All the classes inside ShopShould would go away, as would the Port interfaces. The various Adapters would get an Embedded Stub to support their new createNull() methods.
Technically, you could keep the Port interfaces, if you wanted, but I find them to be unnecessary noise, except in the rare case that they actually have multiple production implementations. (Even then, I prefer to abstract the multiple implementations behind a higher-level adapter that uses composition and has the “smarts” to delegate to the appropriate service.) They aren’t needed for testing purposes when using Nullable Infrastructure.
(As an aside, my naming would typically be “RebateServiceClient,” not “RebateServiceAdapter,” but I wanted to stay close to your naming convention.)
Cheers, James
On Mar 26, 2021, at 3:16 AM, Peter Gfader < peter@...> wrote:
Hi Group
I am playing around with the concept of Nullable Infrastructure and Embedded Stub
Thanks James for publishing this. I really enjoyed it!
Could be a question to James but maybe someone else has also a good tips for the below:
Where would you put the createNull() method? ? 1. on the interface? ? 2. on 1 of the implementations of the interface?
createNull() would create this class "NotificationPort" that does nothing.
Or am I missing here something bigger? THANKS for help!
<image.png>
Yes, the code is a total over engineered piece to teach different concepts :) Any feedback is appreciated?
? ?Peter Gfader?
|