BulkLoader :: Refactor me

After a couple months of blind hacking, BulkLoader was in for a much neede refactor and test suite.

After BulkLoader was made public in November 2007, it really took of. From about 3 downloads a week, to around 30 daily, since November, totaling over 3 thousand downloads in about three months.

For me this came out as a big surprise. I'd expect coworkers at Gringo to use it, and maybe a few others, but I've never thought it would be that many.

Usage numbers are much harder to guess though, since most hackers would rather checkout from svn, and of course, the majority of people will download it, take a 20 seconds look and leave it at that.

Still, from the mailing list, email exchange and blog posts, I can see that there's a few programmers using it. This is a great reward.

Turns out, releasing BulkLoader was much, much more work than I'd figure. Documenting, replying to comments, wiki and general maintenance are many times more time consuming than coding actually. It's been a great exercise in learning how to communicate, write docs, and making sure that BulkLoader will help users getting work done.

When users started to write about it, I realized that there were far more use cases than I had planned for, and it showed. Many thoughtful feature requests came, bug reports. Also more than one person struggle with the same issue made it clear that the docs were either lacking, or that feature behave in a hard to grok manner.

As I started to push more and more updates, and many times, hacking features that were not in my regular usage pattern, sometimes I'd push broken updates, or sometimes break something that used to work.

The types mess

Somewhere in January, I realized that there were problems with the way BulkLoader was programmed. One was that, for various reasons, it was necessary to specify the type of an item being added (images, videos, text files, etc), because that would map to internal details regarding how to load them (NetStreams, Sound objects, Loader object and so forth). But I made a deep mess, confusing file extension, mime types and the classes used in BulkLoader to load them. The end result was a big mess of the "types" system, where it was very complex to change, or and understand that part of the code. This also impacted users heavily since types were used from the outside as well.

The anti OO, conditionals spread all over the place

The other issue, is that I always intend to not expose the LoadingItem instances, to keep them internal. It turns out, that it wasn't possible to do that, not without restricting some very fair needs. So with time, people would use more and more of LoadingItem objects directly. But LoadingItem was crafted hack after hack, the antithesis of Object Orientation, full of conditionals for each loading type. laid the plan.

Change but don't break

I wanted to get a major refactor done: properly create a class structure for LoadingItems and also clean up the whole types-are-extensions-and-classes mess. But there were so many people using it, and I didn't want to break things too much. I needed to go into that large refactor, with some assurance that most stuff would simply work: a needed a test suite. I started a new svn branch, the li-refactor branch, and have been hacking on it when time allows for the last month.

Testing is hard: let's go shopping!

I've used some Unit Testing in the past, but very little. Either toy examples for studding, or reading it like documentation. BulkLoader is hard to test. Most features are asynchronous, and very little of the code is reentrant. Also, because it is a singleton of sorts (not really, but all instances are kept in memory) it made it testing hell.

I chose to go with ASUnit, mostly because it looked less tied up to flex libraries and Flex Builder. BulkLoader is now proud to have over 170 test. I am pretty sure that there are more to come, but it is a great start. I've decided to keep test out of the main zip download, since most people will never need to touch those, but they are in the svn rep. I've kept a copy of ASUnit as well, since I had to patch it a bit to make testing for BulkLoader easier, mostly making sure that tests would run in a serial fashion, and not in parallel (because if it keeping all instances in memory, it made a mess).

Tests got many, many bugs that were lurking around. It's really impressive how useful they are. There is so much to gain in understanding, how things work, and what in the design promotes bad coupling. This is first real test suite I wrote, and I am sure I've made a lot of mistakes in it. But never the less, it has taught me a lot, on testing, BulkLoader design in general, and more importantly, gave me the confidence for a large, much needed refactor.

Breaking backwards compatibility

As much as I wished I didn't have too, some backwards compatibility was broken. Fixing the issues above implied in changing a few details, and since BulkLoader is such a young project, I am glad I have done so.

Avoiding bloat

One of the hardest issues with a public project is saying no to feature requests. Most are very sensible, and it is a natural impulse to just go ahead and implement them. But BulkLoader has become very large, borderline bloated for a project of it's scope. So unless something incredibly useful comes out, I am freezing new features and calling this merge a release candidate. I'll do a couple more of bug fixes releases and then called it a 1.0 day.

And many thanks

To all users who provided bug reports, feature requests and just general feedback. Those contributions are invaluable, and it is very rewarding seeing users begin more productive, doing less grunt work.

For a full list of changes: for the whole shebang.

getting a third opinion

1.
P. says at

Great work.

Very much appreciated.

2.
John says at

Super big thanks to all your hard work.

3.
Ryan says at

I agree open source, automatically makes you another level developer due to the intricacies that you don't' see and community feedback. The best testing is real-world use.

One other thing, I agree Google code needs to extend SVN downloads (although this would have to be on their and exposing the stats). I don't know that I have ever downloaded the files directly from any Google code projects. SVN is all you need with the little Tortoise (I use for CVS, SVN and Hg now (mercurial)).

Anyways I digress, this is such a great kit really it has helped to standardize some of the loaders with lots of projects teams I work on have to work with.

Good points on simplification and bloat. That is key to a successful project I think. It needs to be a simple component that other structures and more complexity can be built from. In the end the best systems are complex systems but broken down into small message based or event based coupling. Which allows for the greatest upside.

4.
Bobby says at

The BulkLoader class is awesome. I'll be using it a lot more of my projects now that I found it. Thanks for working on this an releasing it out there. It's done much more much better then the loaders i have written. It would be nice if you had quick method to get resources out of the library. something like getContent("id").getLibraryItem("name") as Bitmap or something like that

5.
says at

Is it possible to access Symbols from a swf file which is loaded using BulkLoader ? Like using Loader class I do var abc:Class = event.target.applicationDomain.getDefinition("MySymbol") as Class; var mySquare:MovieClip = new abc() as MovieClip; addChild(mySquare);

6.
says at

Hi Arthur, I found a way of getting symbols, i tried the below one and it works. var mainMovie : MovieClip = bulkLoader.getMovieClip("myswf.swf"); addChild(mainMovie); var Square:* = mainMovie.loaderInfo.applicationDomain.getDefinition("mymovie") as Class; var mySquare:MovieClip = new Square() as MovieClip; addChild(mySquare);

Is this the right way of doing this ? or You have some other function defined in BulkLoader class to access symbols inside a movie clip.

Please reply back.

Its urgent

Thanks

7.
tasovi says at

Hi Arthur, as I see everybody asks teh same question. How can you acces Symbols from a SWF Library. i would be great if you could answere to that question! thx

8.
Patrick Jankun says at

[ part1 ] I founded another way to get the .SWF's out of the Library, even Simplier then the cksachdev approach, still i dunno if that's the right approach: var myClip:MovieClip = new MovieClip(); this will get instance a new MovieClip to assign one from your library myClip = bulkLoader.getMovieClip("Library.swf").getChildAt(0) as MovieClip; this will assign that mc from Library.swf to myClip

VERY IMPORTANT! You have to put the MovieClips in your Library.swf on Stage and not export them as an Class, simply because it's not needed, as you load the entire Library, and access the Clips children (MovieClips you put on stage)You can make it even simplier, put your clips in each layer and then you can exectly get the clip you wanted by index, meaning:

clip at layer1 = index 0
clip at layer2 = index 1
clip at layer3 = index 2
clip at layer4 = index 3

9.
Patrick Jankun says at

[ part 2 ] and so on, the good thing is you dont have to export the clips as classes to access them with Class constructors, as they are already in Library.swf display List, and you dont have to addChild(Library), so it will be outside your main stage display list

I hope this will help, still im a newb, so dunno if that approach is the right one, hence it's a lot of easier to operate with 2 rows of code I tried to access Children of my Library.swf with getChildbyName with their instance name, but this seem's not to work, dunno why, was logic to me. Still you can put your clips in an order on stage in layers, so you will know which clip is where, and get it with the right index.

10.
Patrick Jankun says at

[ part 3 ] I finally founded a way how to get an MovieClip by it's INSTANCE NAME from your loaded .swf, that is quite simple, so forget about the prior 2 posts: var ldr:BulkLoader = new BulkLoader("my bulkloader");

[ onCompleteHandler ] yourClip = new MovieClip(); yourClip = ldr.getMovieClip("Library.swf").instanceNameOfClipInLibrary addChild(yourClip);

Hopefully i got this right as for now :)

11.
Arthur Debert says at

Hi Patrick.

I am glad you could get your code working.

Comments on this post are a poor way to get help or exchange usage information. As posted repeately, please use the for such issues, since you are more likely to get a useful response, and you can post a pretty long message over there as well.

Thanks Arthur Debert

12.
yojo says at

Hi great job, do you have any sugestions about loading external swf with Bulk. I mean my external swf is a whole page with classes attached in Document class, problem is that after movie is loaded none of the code inside works (errors and so on), movie runed as it is works fine.

13.
Arthur Debert says at

Hi Yojo.

This is a very common misunderstanding.

Nothing in particular about BulkLoader, just the way that the AVM2 handles code execution from different swfs.

More info here:

This is also mentioned on the documentation and on the project's wiki.

Cheers Arthur Debert

14.
Kris says at

Thank you so much. BL is the best loading manager ever. I singer your praises to all the other flash developers I meet.

You've made me look like a superstar on my last project. It only took 2 days to implement a sophisticated polite loader - I research but nothing but BL could do that for me.

15.
David Bardos says at

Hi,

I use your code too, and it's very useful!

thanks a lot and keep on working :) - David

16.
jp says at

Your bulkloader can be difficult to test (TDD) and it can help with testing. Yeah, the static method access to a particular bulkloader can be difficult to deal with (you often need to at least removeAllLoaders in the teardown), but using the bulkloader for dependency injection can be very useful. i supply the bulkloader instance (hiding under an interface...IBulkLoader) to the SUT and both the test case and the SUT can have access to the DOC via getContent(). If I want to use a mock object i can load a mock object into the bulkloader, send it to the SUT and my test case can refer to it as a mock object and the SUT can refer to it through an interface. very useful.

now let's see how easy it is to extend BulkLoader so I can load Flex apps and dispatch the complete event when the application is created (not just the swf loaded).

btw, you can use flexunit for AS only projects, but I'm sure asUnit is fine.

17.
Viktor says at

Hi,

very useful indeed.

Some of the resource files we use in our server side need encoding/decoding time that means the server sends back a percentage and if it's 100% I'm able to fetch the item.

Is there any easy way to handle this kind of polling stuff with this library?

thanks Viktor

18.
Roma says at

Hello! Sorry for the desperetly offtopic comment, but... I am a flash-developer that, like thousands of others, use your amazing Tweener library. I just wonder, how come you haven't left the possibility for the "users" of Tweener to donate to your project? I have a good habit to donate (may be not much) to each opensource tool that was usefull for me, during any kind of development.

Thank you for the Tweener once again!

Greetings from Ukraine.

19.
Arthur Debert says at

Hi Roma.

Thanks for the kind words.

My contributions to Tweener are very, very tiny. Zeh really did the whole thing, it is his baby ;) .

Zeh answered this question .

Cheers Arthur Debert

20.
Bryn Bowman says at

Hi Arthur,

Thanks for an amazing tool!

I have one question, and I am not sure where to post it, so here it goes. I want to load an item by refrencing a variable, not a string. Is this possible?

ie: imgPath:String = "img/" myVarToLoad:String = imagePath + "01.jpg"; bulkLoader.add(myVarToLoad")

I hope this makes sense. I have searched the internet, but there is not much out there about BulkLoader.

Thanks for all your hard work!

21.
Mark says at

Hi, I am pretty new to AS3. I have a version of the simpleLoaderMain.as supplied in the docs happily loading my site. It loads the guts of the site. I want to have buttons launch the load of site sections. can I set up BulkLoader to take care of this?

How do I set up a different bulkLoader for each button and start it from my button?

thanks really dig this class but need some friendly guidance

22.
NoriSte says at

Thanks for your great work :-) I have s small problem, calling pause(... methiod the loading does not stop but continue... why? :-(

23.
dropy says at

Yes thank a lot for bulkloader.

24.
Sanbor says at

Great library, I been searching for a long time. Thanks for sharing your work!!!

25.
Oliver says at

Hey Arthur

Just wanted to say a big thank you for the hard work: you did a great job.

Oliver

Have the last word





posted by
Arthur Debert

on


Tagged with:

25 comments so far.
Say something

Other months availabe in 2008

The complete blog archive

The latest entries

Subscribe to comments on this entry: rss feed

Cloud me:

Feeds: Entries rss feed Linksrss feed Worksrss feed

A Django joint. hosted on Slicehost