I have a design and am wondering what the appropriate way to access variables is. I'll demonstrate with this example since I can't seem to describe it better than the title.
Term
is an object representing a bunch of time data (a repeating duration of time defined by a bunch of attributes)Term
has some print functionality but does not implement the print functions itself, rather they are passed in as anonymous functions by the parent. This would be similar to how shaders can be passed to a renderer rather than defined by the renderer.- A container (let's call it
Box
) has aSchedule
object that can understand and useTerm
objects. Box
createsTerm
objects and passes them toSchedule
as required.Box
also defines theprint
functions stored inTerm
.- A
print
function usually takes an argument and uses it to return a string based on that argument andTerm
's internal data. Sometime theprint
function could also use data stored inSchedule
, though. I'm calling this datashared
.
So, the question is, what is the best way to access this shared
data. I have a lot of options since JS has closures and I'm not familiar enough to know if I should be using them or avoiding them in this case.
Options:
Create a local "reference" (term used lightly) to the
shared
data (data is not a primitive) when defining theprint
function by accessing theshared
data throughSchedule
fromBox
. Example:var schedule = function(){ var sched = Schedule(); var t1 = Term( function(x){ // Term.print() return (x + sched.data).format(); }); };
Bind it to
Term
explicitly. (Pass it inTerm
's constructor or something). Or bind it inSched
afterBox
passes it. And then access it as an attribute ofTerm
.- Pass it in at the same time
x
is passed to the print function, (from sched). This is the most familiar way for my but it doesn't feel right given JS's closure ability. - Do something weird like
bind
some context and arguments toprint
.
I'm hoping the correct answer isn't purely subjective. If it is, then I guess the answer is just "do whatever works". But I feel like there are some significant differences between the approaches that could have a large impact when stretched beyond my small example.
Edit
I'll post the solution I'm using but I'd still welcome criticism:
All print
functions take, as arguments, anything term
doesn't own. This way, term
is not coupled to schedule
in any way (obviously schedule
is still dependent on term
, though). This allows term
to be initialized/constructed anywhere without needing knowledge of schedule.
So, if term
had an init()
function it might take an object that looks something like this:
{
inc: moment.duration(1,"d"),
periods: 3,
class: "long",
text:"Weekly",
pRange: moment.duration(7,'d'),
//*...other attr*//
printInc: function(increments,period){
return moment(this.start).add(this.inc.product(increments)
.add(this.startGap))
.add(this.pRange.product(period))
.format(DATEDISPLAYFORMAT);
},
printLabel: function(datetime){
return (datetime).format(DATEDISPLAYFORMAT);
}
}
Where increment, period, datetime would all be passed from whatever is using term's print methods (schedule in this case).
Term
is essentially a data structure with minor functionality and is used elsewhere in the app. The print functions are specific to schedule though. I'll update the question with the solution I'm using atm.Schedule
, why isn't it in theSchedule
class rather thanTerm
?