Sadly Dave is right here - the contents of a closure are, well,
closed. Hence the name.
Luckily Crockford's Module Pattern is a rare sight these days, I can
count on the fingers of one mouse the number of times I've seen it in
the wild in the last ten years. These days the focus tends to be far
more on 'faux-O' Javascript, 'Haskell-wannabe Typescript', or some
functional-style code that looks like a mashup of Clojure, Ruby &
Absinthe.
If the Module Pattern _is_ your problem, then a refactoring like
'extract method to helper object' is a reasonable choice, and the path
you'd take would be very similar to that in a typical OO language
environment.
Fox
---
toggle quoted message
Show quoted text
On Sun, 5 Jun 2022 at 17:42, Dave Foley <davidmfoley@...> wrote:
I don't believe that using the prototype chain quite accomplishes what is being asked for.
"Objects, but not classes" implies the usage of closures to encapsulate data, and I *think* that what is being asked for is to have access to the bits that are "closed" similar to how one might access protected members in a class in java.
The closed values are not accessible to "subclasses" on the prototype chain.
I'm imagining that the legacy code you are talking about is structured something like this:
// a function that returns an object
function Product(sku) {
// these values are "closed" aka "private"
let quantity, sku;
// this is also "private" / closed
function calculatePrice() {
// ... some logic here that we want to either:
// 1. test directly or
//. 2. stub to allow us to test other parts of this object
// this function's behavior depends on the closed values
}
// the object returned
return {
setQuantity(val) {
quantity = val
}.
getPrice() {
calculatePrice()
}
}
}
In this case, there is not a good way to get access to the "innards" without modifying the SUT.
On Sun, Jun 5, 2022 at 8:41 AM Sleepyfox <sleepyfox@...> wrote:
Hi JB,
This is trivially simple in JS, simply create a new object (your "subclass to test") that has its prototype set to your SUT object.
All of your SUT methods and attributes will now be accessible in your child object.
Simples!
---
a = {
f: (x) => x + 1,
z: 2
}
b = {}
b.__proto__ = a
console.log(b.z) // 2
console.log(b.f(4)) // 5
On Sun, 5 Jun 2022, 13:43 J. B. Rainsberger, <me@...> wrote:
Hi, folks. I embarrassed myself in a Surviving Legacy Code training course recently by fumbling with Subclass to Test in front of a bunch of JavaScript programmers. It occurred to me that I don't know the object-based analog to this approach. I waved my hands a little, then thankfully, I ran the clock out without much of a resolution.
I'd like to make it up to them and I need your help.
What is the corresponding technique when working in a language with objects but not classes? In JavaScript, for example, how do I achieve the same effect of being able to create a "testable" (more-inspectable) object in my test with minimal changes to the legacy code object definition? In JavaScript, can I do the equivalent of making a property visible to "subclasses" without making it widely-visible to all legacy clients? Or should I think about it a different way?
My goal is to make minimally-disruptive changes to the existing code, while adding tests for it that would support refactoring. I want the equivalent of overriding _this small part_ so that I can simulate/control it in order to test that other part of the same object.
I feel like I'm missing something obvious, since I'm barely functionally literate in JavaScript.
Thanks.
J. B. Rainsberger :: :: ::
--
J. B. (Joe) Rainsberger :: :: ::
Teaching evolutionary design and TDD since 2002