Skip to content

Instantly share code, notes, and snippets.

@basketofsoftkittens
Created June 25, 2012 22:41
Show Gist options
  • Save basketofsoftkittens/2991907 to your computer and use it in GitHub Desktop.
Save basketofsoftkittens/2991907 to your computer and use it in GitHub Desktop.
<!--
After talking to drew, we decided that we would need more precision in creating widgets. Making so many resources private poses the problem of interchangeability. I propose we allow variables in our dependency code to determine which level of resource use when we create the widget. for example -->
<script type="text/mint-customer-something">
{
dependencies:{
model:{
Base: "$mint/src/models/model.Base.js",
Address: "$global/src/model/model.Base.js",
CustomerSomething: "$module/model/model.CustomerSomething.js"
}
}
}
</script>
<!-- thoughts? -->
'proposed module structure
1. widgets are modules
2. widgets have resources(models/views/controllers) that are owned by the widget (other modules cant access because they are declared privately)
3. widgets can share resources when they are declared and registered via a "manager" (mint.widget,mint.model). shared resources are declared outside of the scope of the module
4. dependency management can include modules which include their resources and their resources dependencies
5. at the mint level, each store has a directory which holds widget overrides for a widget, or a widget resource.'
proposed structure:
.. src
`-- models // shared resources
`-- store_widgets
| `-- homemint
| `--checkout_form
| `-- models
| `-- model.coupon.js
|
`-checkout_form
`--models
`--- model.coupon.js
`--views
`-- view.coupon.js
`--controllers
`forms.js
// src/widgets/checkout_form/models/model.coupon.js
exp.CouponModel = ready.model.Base.extend({
initialize:function(){}
});
// src/store_widgets/homemint/checkout_form/models/model.coupon.js
exp.CouponModel = CouponModel.extend({
initialize:function(){ alert("hello world")}
});
// src/widgets/checkout_form/form.js
mint.widget.register('checkout-form',{
dependencies:{
model:{
Base:"model/model.Base.js"
}
},
init:function(){ this.loadDependencies();}
ready:function(errors,data){
var resources = populate(data);
this.CouponModel = new resources.CouponModel();
}
});
// js.php turns a modules directory into something like.
(function(){
var populate = function(ready){
var exp = {};
exp.CouponModel = ready.model.Base.extend({ ...
....
exp.CouponView = Backbone.View.extend({...
....
// start store specific loading of resources
exp.CouponModel = CouponModel.extend({ ...
....
return exp;
}
mint.widget.register('checkout-form',{ .....
.....
ready:function(errors,data){
var resources = populate(this,data);
// should alert "hello world" from mint specific overwritten resource
this.CouponModel = new resources.CouponModel();
}
.....
});
@dstokes
Copy link

dstokes commented Jun 25, 2012

What's the benefit in creating these private (scoped) modules? Feels like a lot of magic that we could supplant with a proper module naming convention.

Also, truly modularizing mintjs would involve exporting a public api from the IIFE that could be dynamically assigned / included in any environment (i.e. testing checkout form w/o mint.register). The code is really clean, but there might be a more flexible way to take advantage of a modular pattern.

@basketofsoftkittens
Copy link
Author

pros:
*removes inline declaration of private modules
*allows true privacy for private modules
*promotes a DRY structure for modules.
*easy to navigate
*1 mint push for mint specific module changes (just mintjs instead of mintjs + mint)
cons:
more verbose.
others?

@dstokes
Copy link

dstokes commented Jun 25, 2012

These are the pros for inlined, private modules right?

@juyeno-bm
Copy link

I think I missed a step.... could you elaborate on

exp.CouponModel = ready.model.Base.extend(

for the store specific code?

@jrylan
Copy link

jrylan commented Jun 25, 2012

The only thing I would be curious about is if we could store the mint-specific overrides in the repo for that specific mint instead of mint-js.

For local development we could send the full path to the mint-specific js directory as a param in the GET request, and then omit (and ignore) that param in production in order to fallback to static configured values.

I just personally like the idea of keeping all specific mint code together...

@basketofsoftkittens
Copy link
Author

@JeremyRylan: We currently have mints with models/widgets/collection in the specific mints that override their mintjs counterparts. i believe our development lifecycle discourages using these mint-specific resources ( mintjs -> wait -> merge -> pass -> homemint -> wait -> merge -> pass). i also think that having mint-specific code easily browse able will allow for better breaking up for concerns as we aim to move mintjs widgets to be more configuration based. we try to make the widgets catch every case for every mint which often leaves it bloated and error prone. hopefully the ease of development with this new structure will help solve this.

@basketofsoftkittens
Copy link
Author

@juyeno-bm. the ready variable is the data being passed back from the dependency management. needed for resources dependencies.

@basketofsoftkittens
Copy link
Author

@dstokes yes, those are the pros for private modules. as far as flexibility, i think it depends on how we implement the privacy glue code. i think this module structure provides flexibility in its cleary defined dependecy and export vars and by promoting a real separation of concerns (since you cant talk to what you dont know about). in the future, if we wanted to use a real dependency loader we could still keep this same structure and alter our glue code. thoughts?

@jrylan
Copy link

jrylan commented Jun 25, 2012

Yeah, hopefully in the long-term we'd have very few mint-specific overrides and it would be feature/config based.

Ex:
product detail -> use breadcrumbs (bool)
account settings -> orders can be processed in multiple shipments (bool)

@juyeno-bm
Copy link

agreed, although I ideally I'd really rather see a common model so we could just decide which widgets to render and not worry about setting parameters on a monster widget, some widgets which might be good candidates:

breadcrumbs
product blurb
add.js

That way we can keep files smaller and encapsulate logic to data requests to the models instead

@basketofsoftkittens
Copy link
Author

@JeremyRylan: definietly. what i am hoping to accomplish with this structure is more code like

// src/widgets/checkout_form/models/model.coupon.js
exp.CouponModel = ready.model.Base.extend({
  options:{
    showCoupons:true
  }
});

// src/store_widgets/homemint/checkout_form/models/model.coupon.js
exp.CouponModel = CouponModel.extend({
  options:{
    showCoupon:false
  }
});

@8bitDesigner
Copy link

👍 on private module scoping. That's a good way to cut down on cookie jar violations, where one module depends on another module's functionality. This is pretty innocuous right now, but also part of the reason we can't easily break our ish out into separate modules.

@juyeno-bm: how would this play with your decorator pattern?

@dstokes
Copy link

dstokes commented Jun 25, 2012

@basketofsoftkittens to promote DRY modules we should be making as many of them globally available as possible, and handle mint specific logic with feature checking. Doing so allows us to do things like add coupon code information to the customer bar without having to create a new private module based on the private model in the checkout widget.

The only modules that should really be 100% privatized are models that would never be applicable to any other view. This would be true in most cases for widget state models, but even that is debatable.

Also, something feels dangerous to me about defining module dependencies (private modules) in the file system..

@dstokes
Copy link

dstokes commented Jun 25, 2012

That's not to say that an instantiated module from the manager could not be registered privately in the widgets closure, btw

@juyeno-bm
Copy link

@8bitDesigner would likely play out very differently depending on how we implemented decorators and / or widgets on a page... I was envisioning a view file looking something like:

<script type="mint-catalog-product-breadcrumbs">
  {
    mintSpecificSettings : false  
  }
</script>

<script type="mint-xmint-util-carousel">
  { images : <?php echo $this->images ?> }
</script>

<script type="mint-catalog-product-details_portrait_layout">
  {
    titleDecorator: 
      [ 'views-util-label'
      , mint.decorator( 'text', { content: 'Buy Now!' } )
      ]
  }
</script>

// omit product blurb script here since we don't want to show it
<!--script type="mint-xmint-catalog-product-blurb"></script-->

And in xmint/util/carousel.js:

...
options: {
  decorators: {
     imageThumbDecorator :
       [ 'views-util-carousel-imageThumb',
       , mint.decorator('tag',
            { 'class' : 'blah minty-blah'
            , 'tag' : 'caption'
            }
         )
       , 'views-util-row'
       ]

}
...

Which I realize seems verbose, but also means that we can mix and match features by mint without having to modify code too much, and common views like a row or image caption could be reused. Also what we wouldn't see any more are essentially duped templates for every mint (though Jeremy probably already helped quite a bit with that).

@basketofsoftkittens
Copy link
Author

@dstokes. i think it promotes DRY modules by making it easier to develop DRY modules. a good example of this is https://github.com/beachmint/mint-js/blob/master/src/models/model.Address.js and https://github.com/beachmint/mint-js/blob/master/src/widgets/customer/address.js. if you look at the content and directory structure of the two files, it speaks volumes to what is a natural inclination of devs.
the private vars in a file system do seem scary without the proper glue code, the inherit import/export structure alleviates the worry of the timing/scoping issues that happen with privat vars. i also believe that knowing that all you have access to is the variables in the file itself promotes a better separation of concerns. we have invested heavily in a framework that uses these separation of concerns, i think that this helps create code that utilizes the work we have done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment