On Mon, Oct 17, 2011 at 10:04 AM, kmalakoff <xmann.i...@gmail.com> wrote:
> 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. > One should never make un-DRY code so any code that something needs should be inherited, can you give concrete examples of when inheritance won't work and I should be using an aspect for behaviour at the object level? > > **************** > 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! > Yes there is a better way, don't dump methods in your "base class" build up inheritance chains, make a Backbone.views.scrollableView, Make a Backbone.views.dynamicView > > 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, > Why is a deep hierachy bad? You realise that the prototype chain is a heavily optimised beast, there is very little overhead in walking the prototype chain, and even that overhead dissappears with the JIT. > 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 > -- 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