So here you are, now, reading about code I'd rather move past. "Now" could be the day I posted this article, but it's more likely some months or years later. Admittedly, I promised to discuss Proxy, and my efforts to document it, in an earlier post. Now felt like a good time.
To be clear, Proxy is nothing new or unique. But that's because creating versions of objects - or proxy-like objects - is also not new or unique. If you were tasked to create proxy-like objects in code, it might go something like this. Define a function that makes an object literal that has methods to get and set properties of some source object. Here's an example, below.
Simple enough, and there is already a perceptible degree of repetition in the defined methods. If you had to do this for more than one property, you might refactor it like below.
Proxy takes this one step further, by identifying three phases of our getter and setter functions: get, vet, and set or GVS. The get and set phases isolate when a getter/setter retrieves or assigns a value. The vet phase isolates when a setter function is validating a value, before assigning it to the source object's property. With this abstraction, we can describe each phase of our getter/setter function with an object. Proxy uses an indexed array, called a GVS array, where each index corresponds to each phase - the first is the "get-index", and so on. Proxy accepts and compiles GVS arrays, so they execute like traditional getter/setter methods.
Each index can be a string, function, or any other truthy or falsy value. When the get and set indexes are strings, they reference the source object property to retrieve and assign, respectively. When the vet-index is a string, it specifies the object type required in order to set a value. [The next version of Proxy will accept an array of object types.] For the sake of comparison, below is a traditional proxy-like object, with a same-name setter/getter function that retrieves property "x" and accepts a number for property "y", and the same function described as a GVS array in a Proxy constructor.
There are many possibilities for defining simple to complex getter/setter functions via a Proxy GVS array. (The Proxy wiki will be updated to explain all of them.) Of course, Proxy doesn't limit you to GVS arrays, and can accept regular functions as well. However, the efficiency of the GVS pattern is the primary reason I use it, instead of defining proxy-like objects traditionally.
Learning to do it right (next time)
Open-sourcing takes work and a greater commitment than open-source advocates proselytize. Documenting Proxy, improving it, defending it, naming and explaining concepts like "GVS pattern" have destroyed my productivity. Before announcing Proxy, I spent a weeks documenting it (i.e., less than two-hundred lines of commented code). Now, a month later, I've finally come around to blogging about it directly, if not completely.
This post doesn't mark the end of anything regarding Proxy. I've resigned myself to the fact that this code is my baby and always will be. I've begun to integrate Proxy updates into the larger project it spawned from. I also have plans to improve it's documentation and packaging - which will finally include unit tests. I've filed tickets against myself (a highly recommended practice), and plan to add a roadmap to the wiki.
Though Proxy is more than I expected, it's just what I asked for: a trial run at open-sourcing my work. I've de-romanticized the notion of shared code equating to community-supported code. That kind of interest and support comes way down the line, after useful criticism and outright derision. By dragging Proxy (and myself) to higher levels of recognition and professionalism, I'm discovering what it might take to push larger projects, in the future.