I really appreciate our discussion (see the below except from the
README) as it has help me to clarify the goals and differences with
the standard mixin.

The reason I raised this JSMentor is to try to get some feedback on
this framework which is a bit different from standard mixin. I'm
hoping that you and others may feel compelled to try using this way of
doing things since I'm not sure, but I think there aren't other
frameworks for instance-level mixins lifecycle control!

It still mixes things in at a class level, but also provides instance
level initialize and destroy given that I couldn't really find a
mechanism or standard using Object.extend to do this. So I primarily
use this library as the standard mixin with instance-level initialize
and destroy which is why I called it mixin.js rather than
aspect.js...I'll open a question on the renaming and see what people
think.

Cheers,

Kevin

I've updated the README to try to help explain things:

****************************
Mixin.js brings "dynamic aspect-oriented programming" to Javascript.
"Dynamic" means you can add and remove independently encapsulated
functionality and data to your instances on-the-fly. "Aspect-oriented"
means you can flatten your class hierarchy and add/remove
functionality only where & when needed.

Classic object-oriented design can force you to regularly make
tradeoff decisions based on your evolving subclasses like deciding
between polluting common super classes  (eg. push common functionality
up the hierarchy whenever it needs to be reused) vs making un-DRY code
when only a subset of sub-classes require common functionality (eg.
cut/paste and maintain the code). Mixin.js provides you with a light
framework to avoid the decision altogether...make a mixin, use it
where & when you need it...decisions made, stay made.

****************
I bet you're asking yourself what made me I write this anyways
and...isn't it overkill?

The problem I had was that I was implementing Backbone.Views. Some of
them needed scrollable content areas (using iScroll), some of them
needed to be dynamically rendered based on Backbone.Models loading and
unloading whereas others needed to render collections, some of them
needed to have timers to change state after a specific timeout, all of
them had custom destroy methods to unbind jQuery events, some views
needed to subscribe to state changes on other views, etc. My base view
class was becoming a kitchen sink class and I thought, there's got to
be a better way!

So I started on the path of factoring out each aspect, providing
initialize and destroy code for each, and mixing-in functionality on
the fly. Now, I have a very simple view base class that only provides
the minimal & common view functionality (it actually doesn't even need
to be a Backbone.View anymore since all the functionality is now in
mixins) and a view hierarchy two deep. Each view is simple to read,
light on code, and customized to meet its unique needs.
****************************


On Oct 16, 1:11 pm, Jake Verbaten <rayn...@gmail.com> wrote:
> Have you considered renaming it to aspect.js ?
>
> Seriously, mixins are mixed into classes and I used that term and concept
> all the way through your code to judge it.
>
> Personally Ive never used aspects and I dont like changing the behaviour or
> meaning of objects at run time. i may need to look into your examples some
> more.
>
> I simply cant relate because thats not how I code
>
> On Oct 16, 2011 4:07 AM, "kmalakoff" <xmann.i...@gmail.com> wrote:
>
> Hi Jake,
>
> Thank you for the feedback! You raise some very important concerns and
> tradeoffs in the design of the API. My short answer is that most of
> the aspects you raised comes out of the goal of the library being in
> creating a dynamic-aspect-oriented framework and arose from the API
> evolved to solve real problem I encountered when developing and using
> the API, but I'll go into more detail, provide use cases, and you can
> judge whether there are better solutions to the problems!
>
> Comments (KM>) inline....
>
> On Oct 12, 5:19 pm, Jake Verbaten <rayn...@gmail.com> wrote: > I have no
> (big) problems with readi...
>
> > mixin method (pd.mixin <https://github.com/Raynos/pd#pd.mixin>)
> > > // use pd to make example simple :https://github.com/Raynos/pd>
>
> pd.extendNatives(); > > var Sup...
>
> > // yes Object.prototype.new -https://github.com/Raynos/pd#pd.extendNatives
> > // is awesome > var rockstar1 = RockStar.new(); > > var Fan = {}; > var
>
> fan1 = Fan.new(), fan2 = F...
>
> > Live Example <http://jsfiddle.net/nJbXW/1/>
>
> KM> I've looked at your library and examples. Unfortunately, I
> actually updated the Rockstar example in the README (https://
> github.com/kmalakoff/mixin) after posting it here to demonstrate the
> dynamic nature of the proposed system (basically dynamically adding/
> removing mixins to instances on the fly). Also, the example was design
> to demonstrate the API in a concise way, not to provide an advanced
> use case to justify the purpose of the library (classic disconnect
> between real-world problems and examples). I believe the problem you
> are trying to address is improving the OO nature of Javascript,
> whereas, the library I am proposing is trying to address a slightly
> different problem space that could be described as "dynamic aspect-
> oriented programming". In other words, allowing the library user to
> respond dynamically to situations and importantly, give them a
> convention for cleaning up.
>
> In some situations, what I propose is unnecessary/overkill and in some
> situations it fits the bill (but of course, there will always be
> different ways to solve the same problem) - I included the
> subscriptions mixin as a more advanced example. I'll try to explain
> these design considerations in responding to your points below.
>
> > Now let's take a moment to go back to the API methods you've shown in your
> > example. >
> > *Mixin.registerMixin *
> > > Why would you want to register a mixin by string name? A mixin should
>
> just > be an object.
> KM> Originally I was using objects. The problem I ran into was that I
> was using CommonJS that required a path to the object so when I
> packaged the library and sample mixins I needed to 1) find a way to
> provide users the flexibility to pick and choose which mixins they use
> and 2) to not force a specific directory and file structure for them
> but let them choose how they lay things out. The answer I came up with
> was "named loose coupling" but if there is a better solution, I'm
> happy to apply it - just let me know.
>
> KM> Use case: one user doesn't use CommonJS and all of their mixins
> are in the global namespace; another users uses CommonJS and layouts
> out their mixin files in "vendor", and a different user puts other
> people's mixins under "vendor/mixin" and their own mixins in a lib
> folder: "lib/my_mixins"
>
>
>
> > *Mixin.initialize*
> > > The object you "register" has properties like it's name (why should it
>
> have > a name, just use t...
> KM> Naming conventions aside, there are few reasons for this
> initialize and destroy being outside the object actually being mixed
> in:
>
> 1) The library is designed to flatten an OO hierarchy using aspects
> ("aspect" was another name I was considering for the library instead
> of "mixin") and each aspect can be mixed in and out by the library
> user when they need. Each time the mixin or mixout happens, the mixin
> has an opportunity to initialize and cleanup. For example, in much of
> my code, I use Backbone.Events and jQuery so I bind and unbind events
> on the fly when mixin in and out.
>
> 2) I decoupled the initialize method and put it outside the object was
> to avoid clobbering between mixins and to not have a fixed new/destroy
> call order, but something on-the-fly and dynamic.
>
> KM> Use cases: in the subscriptions mixin, an Observor can dynamically
> upgrade an object to have the Subscriber mixin so if their one is
> destroyed, they automatically cleanup their links to one another. So a
> Subscriber doesn't need to know beforehand that it will become a
> subscriber and not all instances of the subscriber class need this
> functionality and so the cleanup code is only the ones that actually
> subscribed to something during their lifetime (not all instances of
> the same "class").
>
>
>
> > *Mixin.in*
> > > Yes you need that, but why can't this just be `Mixin`.
>
> KM> I agree that it is not really an optimal decision for the most
> used function in the library, but I made this decision mainly because
> of API symmetry with Mixin.out but also to try to cleanly define
> namespaces and have everything hang off of one root called Mixin. Of
> course, the root could also be the mixin function itself.
>
> > Also why are you mixin it into instances of classes instead of the classes
> > themself. That's jus...
>
> KM> Same answer as to the difference between OO and dynamic aspect-
> oriented programming and why there is an initialize/destroy not in the
> actual object. You wouldt need to buy into the use cases for dynamic
> aspect composition over OO hierachy where each instance may have
> different compositions, nor the need to cleanup after each mixin.
> KM> Use case: on-the-fly I adapt Knockout dependent observables
> handlers based on the actual type of object being observed. To the
> library user, they are just creating a handler, but behind the scenes
> the handler is being adapted and cleaned up in a custom way with
> different dynamic mixins based on what is actually being observed.
>
>
>
> > *Mixin.instanceData
>
> > *Why? Seriously, what's wrong with `this.fans = []` why must I store some
> > data in your framework.
>
> KM> This was a decision to avoid property clashes among independent
> mixin library writers. It quickly became apparent that if the system
> is generalized and people independently write mixins, there will be an
> increased probability that their properties will clash. Of course,
> this doesn't *force* anyone to do anything, it just provides a
> mechanism for avoiding property clashes if a mixin author believes
> there is a high risk.
>
> Use case: you write a mixin for superstars and I write a mixin for
> building ventilation management. We both want to use a property called
> fans = []
>
> Thats verbose and frustrating.
> KM> There is also a shorter version of the API Mixin.iD()
>
>
>
> > *Mixin.out*
> > > Sorry, what. Why would you ever want to remove a mixin?
>
> KM> This function is the way you invoke destroy on a specific mixin
> (eg. the symmetry between Mixin.in <-> Mixin.out). I could have called
> it Mixin.destroy, but given that you and mixin and mixout, the naming
> seemed more self-evident and internally consistent. Also, in my own
> code, I use one of three life cycle models: "classes" that require no
> cleanup, new/clone/destroy or new/retain/release so Mixin.out is
> mainly useful for the last two, but you can cleanup a mixin manually
> in any case by calling Mixin.out on any instances (for example, those
> that don't follow one of the final two conventions).
>
> KM> Use case: you can mixin (Mixin.in) a specific set of user
> interface elements to a view, bind their jQuery events, etc; then
> remove and unbind them (Mixin.out) when the user chooses a sub menu,
> and then mix them back in when they return (Mixin.in), and finally
> when your view is destroyed at the end of its lifetime, clean up
> (Mixin.out).
>
> > Now basically, You have a lot of over engineered useless methods on your >
>
> library. > > I'm sure...
> KM> I'm not sure if my use cases have convinced you of the benefits of
> dynamic aspect-oriented programming. I think your criticisms really
> "hit many nails on the head" and properly raise the question of is
> this library over-engineered or at the right level of complexity given
> the problems it is designed to solve. I've been using it for 3 months
> on my personal project so I don't have the perspective and am a little
> enamored by the power and flexibility of the library, but (going back
> to the nails) - I might be in a situation of "a man with a hammer sees
> every problem as a nail"...many cases do not require this full
> functionality, but since it is here, I'm using it generally for
> classic Javascript mixins in addition to dynamic aspect-oriented
> programming.
>
> > > Normally the place where you "convince" people these methods have a real
> > purpose is in your (...
>
> KM> I think you can say "sparse", but "non-existant" is a little
> strong ;-)   Personally, I prefer to look at tests for examples on how
> to use a library so I really put my focus there and tried to draw the
> user in the readme to use the tests as reference, but I have also
> tried to provide various forms of documentation (1) the tests folder
> has both unit and integration tests (2) there is the README itself (3)
> there is a docs folder with the project (4) there is my 
> blog:http://braincode.tumblr.com/and (5) I set up an examples project
> (https://github.com/kmalakoff/examples-kmalakoff). What do people
> prefer in terms of documentation anyways?
>
> I really appreciate this feedback. Hopefully, I have been able to
> explain the goals of the library and the use cases it is trying to
> address. Are you convinced? Either way, I would really like to
> understand why or why not.
>
> Cheers,
>
> Kevin
>
> -- To view archived ...
>
> read more »

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/jsmentors@jsmentors.com/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/jsmentors@googlegroups.com/

To unsubscribe from this group, send email to
jsmentors+unsubscr...@googlegroups.com

Reply via email to