tag:blogger.com,1999:blog-200966022024-02-28T00:26:50.312-08:00geeky ninjaProgrammer by day; ninja at night. The ninja part is NOT about programming, but about my martial arts skills (tae kwon do, martial arts tricks like the 540, aerial, etc.). Currently interested in clean code, BDD, and Ruby on Rails.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-20096602.post-4722559422880558662015-03-11T12:11:00.000-07:002015-03-11T17:26:50.368-07:00Dependency Inversion Principle in PracticeEver notice how the requirements of an API affect the design of your classes? Well, they shouldn't!<br />
<br />
Consider the requirements for using <a href="https://github.com/resque/resque" target="_blank">resque</a>. Please don't misunderstand; resque is a great library which abstracts away the details of asynchronous execution. In case you weren't aware, its #enqueue method accepts a class name followed by an arbitrary number of (zero to many) arguments.<br />
<br />
The fact that it does this should have <u>no</u> effect on the design of your classes. Yes, you need to make a #perform method that then takes zero to many args, but again the design of your class should not be affected by this requirement.<br />
<br />
For example, I've seen code where everything became a class method because of resque's requirements.<br />
<br />
To get around this, you'll write an adapter layer which translates between resque and your code. You don't have to be stuck with class methods. Design your own code without Resque in mind, then hook it up at the last possible moment. <br />
<br />
Another example is in Rails codebases: how many times have you seen -- or even written yourself --<br />
<br />
some_model.update_attributes(foo: 'bar', panda: 'bamboo')<br />
<br />
when something like:<br />
<br />
blog_post.publish<br />
<br />
would make more sense?<br />
<br />
You can hide the details of ActiveRecord's API behind domain-specific, intention-revealing method names that you choose.<br />
<br />
What are your thoughts on the Dependency Inversion Principle, especially when writing Ruby?<br />
<br />
<br />
The inspiration from this post came from several ideas:<br />
<br />
<ul>
<li>Uncle Bob on the <a href="http://www.objectmentor.com/resources/articles/dip.pdf" target="_blank">Dependency Inversion Principle</a></li>
<li><a href="https://wingman-sw.com/about" target="_blank">James Grenning</a> and his saying "write the code you wish you had", in reference to TDD</li>
<li>Alistair Cockburn : <a href="http://alistair.cockburn.us/Hexagonal+architecture" target="_blank">Hexagonal Architecture</a></li>
</ul>
<br />
<div>
<br /></div>
Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-26432462215097530542015-01-14T14:17:00.001-08:002015-02-12T12:51:01.391-08:00Ignore files without modifying .gitignoreBrief note: Thanks to<a href="http://devchat.tv/ruby-rogues/187-marketing-yourself-as-a-software-developer-with-john-sonmez" target="_blank"> this episode of the Ruby Rogues featuring John Sonmez</a>, I've been inspired to blog a little more often.<br />
<br />
<b>Problem</b>: You use git and might use some tools that generate files that other people on your team don't use. For example, you might use vim and create a Session.vim file. Rather than clutter the .gitignore with these files, there is another elegant solution.<br />
<br />
<b>Solution</b>: You can put these entries into .git/info/exclude and git will ignore them, just as if you had placed them in .gitignore. There is one difference, however: .gitignore is usually committed, but .git/info/exclude is a file that exists in your working copy of the repo and it is not committed. Therefore, if you clone the repo to another location on your computer, you'll have to add the entries to .git/info/exclude again.<br />
<br />
There are advantages and disadvantages to each method -- don't fret about it too much though. You can always revert your changes and try the other technique.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-16478513914693885062014-12-09T07:11:00.000-08:002015-06-01T06:42:14.792-07:00tmux crash courseSo you've probably heard about tmux and want to get started. It might sound intimidating but after you follow this tutorial, you'll find that it's really not that bad.<br />
<br />
Here's a basic crash course, written so that you can follow along, step-by-step. <br />
<br />
<b>Installation on OS X</b><br />
<br />
<span style="font-family: monospace;">brew install tmux</span><br />
<span style="font-family: monospace;"><br /></span>
<div>
<code><div style="font-family: Times;">
<b>Basic commands</b></div>
<div style="font-family: Times;">
<b><br /></b></div>
</code></div>
<code>tmux new-session -s foo</code><br />
<br />
Creates a session named foo.<br />
<br />
Congrats! You are now attached to a session and you should see one tmux window. <br />
<br />
A bit of terminology: you create a <b>session</b> which can have one or more <b>windows</b>, which we'll see below. Within a window, you can split it into <b>panes</b>. <br />
<br />
(I'll use ^ to indicate "Ctrl", so ^b means Ctrl+b)<br />
<br />
<code>^b c</code><br />
will create a new window. You should see a status bar at the bottom of your terminal listing out the current windows. Do it again to create another.<br />
<br />
Now you have multiple ways to switch between windows:<br />
<br />
<table>
<tbody>
<tr><td><code>^b 1</code></td><td> switches to window 1</td></tr>
<tr><td><code>^b 2</code></td><td> switches to window 2</td></tr>
<tr><td><code>^b p</code></td><td> previous window</td></tr>
<tr><td><code>^b n</code></td><td> next window</td></tr>
<tr><td><code>^b w</code></td><td> choose window from a list</td></tr>
<tr><td><code>^b l</code></td><td> (lower case "L") go to last selected window </td></tr>
</tbody></table>
<br />
Next, you probably want to split your current window into <b>panes</b>.<br />
<table>
<tbody>
<tr><td><code>^b "</code></td><td> Split vertically</td></tr>
<tr><td><code>^b %</code></td><td> Split horizontally</td></tr>
</tbody>
</table>
<br />
To switch panes:
<br />
<table>
<tbody>
<tr><td><code>^b o</code></td><td> Go to the "next" pane</td></tr>
<tr><td><code>^b up</code></td><td> Go to the pane above. Try left, right, and down as well.</td></tr>
</tbody>
</table>
<br />
Here's a cool feature of tmux that you might be familiar with if you've ever used screen. You can detach from a session and reattach at a later time, with all of your windows and panes intact!<br />
<table>
<tbody>
<tr><td><code>^b d .</code></td><td> Detach from current session</td></tr>
</tbody>
</table>
<br />
Finally, to reattach to a session<br />
<table>
<tbody>
<tr><td><code>tmux attach -t foo</code></td><td> Reattach to a session named foo</td></tr>
</tbody>
</table>
<br />
Hope you found this to be useful. Please let me know if you have any questions. Thanks!<br />
<br />Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-75072091349196987342014-11-14T11:55:00.003-08:002015-01-14T12:19:14.697-08:00TDD: Test behaviors, not methods<b>What I observed when a developer tests methods instead behavior</b><br />
One of my favorite books, <a href="http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627" rel="nofollow" target="_blank">Growing Object Oriented Software, Guided by Tests</a> by Steve Freeman and Nat Pryce mentions that you should test behavior<b>, </b>not methods. The book, also referred to many as "GOOS", states on page 43:<br />
<blockquote class="tr_bq">
We do better when we focus on the <i>features</i>
that the object under test should provide, each of which may require
collaboration with its neighbors and calling more than one of its
methods. We need to know how to use the class to achieve a goal, not
how to exercise all the paths through its code.</blockquote>
<b>When this advice isn't followed</b><br />
A few years ago, I coached a fellow developer in TDD. Although I showed how to "write the code you wish you had" and how the tests drive the design, they refused to write the tests first, which is okay -- it was a big improvement from before when there were no tests.<br />
<br />
My observations were that the specs described methods, and it was hard to figure out what the class actually did. Also, one of the core behaviors of the class was never tested!<br />
<br />
Another problem was when my team and I wanted to actually use an instance of the class, we couldn't quickly figure out which method, or set of methods, we should call to get the job done. The specs read like a list of methods, not how an instance actually <i>behaved</i>.<br />
<br />
What are your experiences? Do you prefer to test methods, or behavior?Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-18418666918670871002014-11-11T12:57:00.000-08:002015-01-07T21:06:10.230-08:00Proxy Pattern -- one way out of many towards Clean Architecture<br />
Earlier this year, I bought several of the<a href="https://cleancoders.com/" target="_blank"> Clean Coders screencasts</a>, which motivated me to implement a clean architecture in Rails. It also motivated me to read Uncle Bob's classic text, <i><a href="http://www.amazon.com/Software-Development-Principles-Patterns-Practices/dp/0135974445" target="_blank">Agile Software Development: Principles, Practices, and Patterns</a>. </i>I've known about the SOLID principles, but the book really shines once you read past those initial chapters.<br />
<br />
<br />
For example, here's a great quote from Uncle Bob Martin's PPP, regarding the PROXY pattern:<br />
<blockquote class="tr_bq">
"It is a way to keep the business rule assets of your project separate from the implementation mechanisms that are currently in vogue." (page 345) </blockquote>
However, this isn't the only way to accomplish this. After reading and understanding the principles in the book, I've found that:<br />
<ul>
<li>By following the D in the SOLID principles (Dependency Inversion Principle), it naturally leads you to design principles such as the PROXY pattern.</li>
<li>You have no fear of frameworks polluting your code because the SOLID principles will ensure that the dependencies point in the correct direction</li>
<li>Your tests will run extremely fast</li>
<li>The only slow tests you have will be integration tests with external resources (database, web services, file system, etc.) and frameworks</li>
<li>It's easier to upgrade since you only need to worry about integration failures, not the interaction between business logic and the new framework API. </li>
</ul>
If you haven't read the entire book yet, I highly recommend checking it out. It will change the way you think about writing software forever. Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-83189953904297171192013-10-18T20:18:00.001-07:002014-11-14T12:00:55.025-08:00Book Review: iOS 6 Programming Cookbook By Vandad Nahavandipoor, O'Reilly Media<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 12.800000190734863px;">
I reviewed this book as part of the O'Reilly blogger program. </div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 12.800000190734863px;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 12.800000190734863px;">
The format of the book consists of concise recipes which state the problem and show how to implement a solution with easy to follow code samples. I love how the e-book has code samples in color with syntax-highlighting, and I found that the code was easy to translate to use with the Ruby Motion framework. Of course, the recipes work fine with native Cocoa as well.</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 12.800000190734863px;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 12.800000190734863px;">
Being a cookbook, I don't think this book was intended to be read cover to cover, although I did just that when reviewing it. You could do that as well, but it might serve you better to use it as a reference. The good thing is that this book is organized almost like a non-cookbook; i.e. it has beginner topics in the first chapter(s) and gets progressively more advanced as you go on.</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 12.800000190734863px;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 12.800000190734863px;">
Although iOS 7 is available now, I would still highly recommend this book.<br />
Read more about this book on its <a href="http://shop.oreilly.com/product/0636920027683.do" target="_blank">product page</a>.</div>
Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-17442113291535237562012-10-06T13:11:00.001-07:002012-10-06T13:13:12.418-07:00Book Review: Code Simplicity: The Fundamentals of Software, by Max Kanat-Alexander, O'Reilly MediaWriting code seems like an easy task, and perhaps it is. However, it can be difficult to write simple, clean code.<br />
<br />
The book, "Code Simplicity: The Fundamentals of Software", explains:<br />
<br />
<ul>
<li>Why do you want to write simple code?</li>
<li>How do you write simple code?</li>
</ul>
<div>
However, you will not find any code samples in this book. While this may not be appealing to some readers, I did not feel that this lowered the quality of the book. </div>
<div>
<br /></div>
<div>
It contains many guidelines and principles that experienced software craftsmen already know and might pass on to their apprentices. Some of these principles:</div>
<div>
<ul>
<li>Don't write code that isn't needed</li>
<li>Make the code easy to change</li>
<li>Comments -- should you add them? Why/why not?</li>
</ul>
</div>
<div>
A very experienced crafstman may not get much out of this book, but if you consider yourself a beginner or intermediate software developer, then I'd highly recommend this book. It's full of great tips that will benefit you immediately and in the future.<br />
<br />
You can find more about Code Simplicity on its <a href="http://shop.oreilly.com/product/0636920022251.do" target="_blank">product page on O'Reilly.</a></div>
Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-58827916203735249822012-03-01T09:44:00.001-08:002012-03-01T09:46:57.132-08:00Review: "The Little Book on CoffeeScript" by Alex MacCaw, O'Reilly MediaThis book might be "little", but don't let that mislead you; it's packed with enough content so that you'll understand all of what CoffeeScript has to offer.<br />
<br />
Alex MacCaw does a great job of covering the major features of CoffeeScript in six short, but detailed chapters.<br />
<br />
He starts off covering the basic syntax, and then moves on to cover something that is frowned upon by many in JavaScript, but not so much in CoffeeScript: classes. Initially, I was hesitant to use CoffeeScript's classes prior to reading this book, but after seeing how they are implemented, and how easy they are to use, I was sold.<br />
<br />
After covering classes in Chapter 2, you'll learn about CoffeeScript idioms in Chapter 3, such as: each, map, select, min/max, etc. Chapter 4 covers the Cake build system and shows you how to build and deploy CoffeeScript client-side applications, which is pretty awesome.<br />
<br />
The book winds down in Chapter 5 talking about what CoffeeScript improved upon in JavaScript, and what it did not. The final chapter is written by the creator of CoffeeScript, Jeremy Ashkenas. It basically talks about the philosophy of CoffeeScript and invites you to create your own special language as well.<br />
<br />
My thoughts on the book:<br />
<ul><li>It's short and very easy to read.</li>
<li>You'll walk away feeling ready to write some CoffeeScript apps or sprinkle it in your Rails apps.</li>
<li>The one negative about the book is that in some parts, some syntax was explained after the fact, which made it difficult to understand some of the examples.</li>
<li>Overall, I'd highly recommend <a href="http://shop.oreilly.com/product/0636920024309.do" target="_blank">picking up a copy</a> as it's concise and easy to read.</li>
</ul>Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-49270802595312443772012-02-03T22:25:00.000-08:002012-02-03T22:25:57.768-08:00Book Review: "The Book of CSS 3" by Peter GasstonDisclaimer: As part of the O'Reilly Blogger Review Program, I chose to review this book. More details can be found <a href="http://shop.oreilly.com/product/9781593272869.do" target="_blank">here</a>.<br />
<br />
<br />
<div><span id="internal-source-marker_0.4624615602660924">The ideal audience for this book is a web developer who is familiar with CSS and has designed several websites. In other words, you won't learn how to design a nice layout but you will learn all of the details about CSS 3.</span></div><div><span><br />
</span></div><div><span>The things I liked about this book are that there are numerous examples in every chapter, with pictures that demonstrate different CSS properties. Of course, what good is a book about CSS without pictures?<br />
Another thing that you will find useful is at the end of every chapter, Peter provides a chart outlining how well the major browsers support a particular feature. </span></div><div><span><br />
</span></div><div><span>There aren't many bad things about this book. My suggestion is that you do not read it cover to cover, as I believe it would be better used as a reference book. The only other thing that I didn't like about this book is that the examples are in black & white; it would've been nice to see the images in color, especially in the PDF version of this book.<br />
<br />
<span style="font-family: Arial; font-size: 15px; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span><span style="font-family: Arial; font-size: 15px; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Overall, it’s a great book to get to learn how to implement the latest cool features in CSS 3. The numerous examples in the book are very helpful, and it will serve as a great reference book to keep on your desk.</span></span></div>Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-78074560281942663192011-04-16T11:59:00.000-07:002015-01-07T21:07:10.722-08:00Replace Prototype with jQuery in Rails 3Note: I'm using Rails 3.0.3.<br />
<br />
I decided to use jQuery instead of Protoype on my personal Rails 3 project. At first, I naively thought that I could simply include jQuery instead of Prototype, and everything would run just fine. Instead, I noticed that Chrome was reporting an error in rails.js, which eventually led me to <a href="http://joshhuckabee.com/jquery-rails-3">Josh Huckabee's blog post</a>, as well as the official <a href="https://github.com/rails/jquery-ujs">jquery-rails gem</a>.<br />
<br />
The installation instructions on the github page are straightforward and simple, so I won't reproduce them here. After you add the gem to your Gemfile and install it, and you run the command:<br />
<span class="Apple-style-span" style="color: #444444; font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 16px; white-space: pre;"> rails generate jquery:install</span><br />
it will pull down the latest version of jQuery. You should answer "yes" when it asks if you want to overwrite rails.js.<br />
<br />
I modified my default layout (application.html.erb) to include this line:<br />
<%= javascript_include_tag "jquery-1.5.2.min", "jquery.jeditable.mini.js", "rails", "application" %><br />
<br />
Of course, you might not need some of these, and you can include additional files as well.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-46423016533047002392010-12-31T07:36:00.000-08:002010-12-31T07:37:51.439-08:00vim tip: searching for word under cursorI was motivated to use vim a few years ago, after watching <a href="http://www.coreyhaines.com/">Corey Haines</a> do his <a href="http://katas.softwarecraftsmanship.org/?p=12">number to LCD kata</a> at the <a href="http://sdtconf.com/">Simple Design and Testing Conference</a> (SDTConf). Although I learned the basics while I was in college, I never really tried to progress beyond that until recently.<br />
<br />
Now I try to make a habit of whenever I am doing something that just seems like it's the hard way, I'll google it and learn how to do it better.<br />
<br />
Today, I was thinking: there has to be a better way to search for things rather than typing "/thing_to_search_for". So I found out how to search for the word under the cursor, which is # for searching backwards, and * for searching forwards.<br />
<br />
Hope this helps, and motivates you to keep learning something new everyday.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-24485943520896992812010-12-23T07:48:00.000-08:002015-01-07T21:07:32.146-08:00Installing ruby 1.9.2 with rvmI've been having trouble installing ruby 1.9.2 with rvm on Mac OS X.<br />
Although there are lots of <a href="http://www.markhneedham.com/blog/2010/07/08/installing-ruby-1-9-2-with-rvm-on-snow-leopard/trackback/">great</a> <a href="http://blog.plataformatec.com.br/2010/04/rails-3-with-rvm-ftw/">blog</a> posts with solutions, for some reason, none of them worked for me.<br />
<br />
The <a href="http://rvm.beginrescueend.com/packages/iconv/">rvm page</a> and many posts say to pass <code>--with-iconv-dir</code> to <code>rvm install</code>.<br />
However, I kept getting errors about Tcl/Tk not being 64-bit, and iconv also not being 64-bit.<br />
Why would it be complaining about iconv, especially since I used rvm to install it?<br />
<br />
<script src="https://gist.github.com/753317.js"> </script><br />
<br />
I noticed the config.log spit this out:<br />
<br />
<code>configure: WARNING: unrecognized options: --with-iconv-dir<br />
</code><br />
<div>
<br /></div>
<div>
I tried many options that were in configure, but none of them pointed the makefile to rvm's version of iconv.</div>
<div>
<br /></div>
<div>
So I took a look at /usr/local/lib/libiconv.2.dylib and noticed it was a symlink.<br />
Perhaps this is taking the easy way out, but I backed it up by renaming it, and relinking that to the version inside $rvm_path.</div>
<div>
After that, I recompiled by running:</div>
<code><br />
rvm install 1.9.2 -C --enable-shared<br />
</code><br />
<br />
Success!<br />
The output: <br />
<script src="https://gist.github.com/753320.js"> </script><br />
<br />
Hopefully, this helps some of you out there with similar problems.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-91203397493259840542010-12-05T17:40:00.000-08:002010-12-05T17:40:34.743-08:00Installing Nokogiri with bundlerI recently decided to start contributing to open source, so I chose to look at one of my favorite Ruby gems, <a href="https://github.com/rspec/rspec-dev">rspec</a>.<br />
The instructions to get you started are fairly straightforward; however, in the rspec-core repository, bundler was failing to install nokogiri. Although the instructions <a href="http://www.pervasivecode.com/blog/2010/03/17/making-bundler-0-8-5-install-nokogiri-on-leopard-with-a-newish-libxml/trackback/">here</a> worked for some, it didn't work for me. So based on the instructions on the Nokogiri homepage, I used macports to install libxml2 and libxlst, re-ran rake, and finally, bundler was able to install nokogiri, with no problems.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-49447242705025792782010-10-15T21:51:00.000-07:002010-10-16T07:08:36.217-07:00"Failure of State" by Uncle Bob - SCNA 2010<div><div>This is the first of many blog posts to come, with my notes on the talks given at SCNA 2010.</div><div><br /></div><div>This morning, on the first day, Uncle Bob gave a talk titled "Failure of State." My notes on the talk are below. </div><div><br /></div><div><b>SICP -</b> Uncle Bob has mentioned this book many times, and I finally put it on my Kindle today. As a craftsman, you should definitely read this book. It's free but if you can, buy it to support the authors. There are also free lectures available as well.</div><div><br /></div><div><b>The substitution model</b> - you can replace function calls repeatedly, ending up with a "silly" version but one that is also stateless and thread-safe. The example given was a program that printed the squares of the first twenty (20) integers. </div><div><br /></div><div>Many stateful programs exhibit <b>temporal coupling</b>; that is one statement (function/method/etc) must be called before another. In other words, time matters. For example, opening a file, then closing it.</div><div><br /></div><div>However; in functional programming, y=f(x) no matter when you call it and every time you call it. </div><div><br /></div><div>Programming has seen three failures so far: 1) the GOTO statement; 2) pointers to functions, and 3) state. Finally, Uncle Bob showed the CQRS pattern, where CRUD is separated into CUD and R. </div></div>Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-79557014166603772982010-09-28T11:44:00.001-07:002014-11-14T12:01:15.356-08:00JavaScript documentationI am doing my part to help others find good JavaScript documentation and tutorials.<br />
<br />
Googling "JavaScript tutorial" or "JavaScript documentation" doesn't provide any good links.<br />
<br />
The Promote JS campaign aims to change this, so that we all can find better JavaScript documentation, such as the docs <a href="https://developer.mozilla.org/en/JavaScript">here</a>.<br />
<br />
Please spread the word! Go to <a href="http://promotejs.com/">http://promotejs.com/</a> for more information, and place a link and banner on your blog or homepage.<br />
<a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function" title="JavaScript JS Documentation: JS Function length, JavaScript Function length, JS Function .length, JavaScript Function .length"><img alt="JavaScript JS Documentation: JS Function length, JavaScript Function length, JS Function .length, JavaScript Function .length" src="http://static.jsconf.us/promotejsvs.png" height="280" width="160" /></a>Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-53334917597108890102009-11-18T10:56:00.000-08:002009-11-20T11:32:32.272-08:00Objective-C Object InstantiationToday we'll go over the syntax to create an instance of a class.<br /><br /><span style="font-weight: bold;">New? </span><br />In Java (and C++, to dynamically allocate an instance of a class), you use the <span style="font-weight: bold;">new</span> keyword. Objective-C's equivalent is the <span style="font-weight: bold;">alloc</span> keyword.<br />I wish I could say that's the end of the story, but there is a bit more.<br /><br /><span style="font-weight: bold;">Initializers</span><br />As in Java and C++, a constructor, and its superclass' constructor, and the superclass' superclass' constructor, and so on, are called in order from superclass to subclass to its subclass, etc.<br />In Objective-C, constructors are called <span style="font-style: italic;">initializers</span>, and you can consider the init: method to be equivalent to a default initializer; i.e. one that takes no arguments and is supplied by the compiler unless you specify one yourself.<br /><br />What if you wanted to create initializers that take arguments? By convention, it's recommended to:<br /><ol><li>begin the initializer name with init</li><li>name the initializer to include the word "with"</li></ol>An example might be on a Person class: initWithGivenName: (NSString*) name<br />Another convention is that the initializer initializes only the attributes that need to be initialized, and any other values can be set w/setter methods or through other means.<br /><br /><span style="font-weight: bold;">Return type</span><br />A"gotcha" compared to C++ and Java: the return type on these initializers have a return type of (id), not the name of the current class.<br /><br /><span style="font-weight: bold;">Designated initializers</span><br />Objective-C has the concept of a designated initializer. This is defined as the one that guarantees that all instance variables are initialized. While your subclass does not necessarily have to invoke a designated initializer on <span style="font-style: italic;">its</span> class, it eventually must call a superclass' designated initializer. NSObject, the superclass of all classes, which is similar to Object in Java, contains a designated initializer called simply, init:.<br /><br /><span style="font-weight: bold;">What to return in an initalizer</span><br />An initializer either returns "self" which is like "this" in Java and C++, upon successful initialization, or nil if a failure occured.<br /><br /><span style="font-weight: bold;">Ok, so how do I put this all together?</span><br />Although you <span style="font-style: italic;">could</span> make two separate calls and "throw away" the value of alloc, it's not recommended. The convention is to chain the calls together on one line like this:<br /><br />SomeClass *pointerToSomeClass = [[ SomeClass alloc] init];Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-37387310861698869072009-09-19T09:04:00.000-07:002009-11-18T10:02:56.164-08:00Agile 2009 summary<img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 213px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv4Q7ey1KhuOny-heWgaArYU6cbiJV1x38vUHeLUgbHY_t7HX570J3KQG1oPERKeSi6XzzDGnOmOD6EFUNC-EAbqcSD_Rcs9TEnXrzhwjk8EREqCK0LbSxe99qizOqWAjbM70s/s320/DSC_0495.jpg" alt="" id="BLOGGER_PHOTO_ID_5390047916882895570" border="0" /><br />I guess it's better late than never, but here's some of the highlights from Agile 2009.<br /><br /><span style="font-weight: bold;"></span><div><b>Clean Code Craftsmanship </b>by "Uncle Bob" Martin</div><div>This was an excellent talk about software craftsmanship; some of the points that I particularly enjoyed:</div><div><ul><li>Plans are useless, but planning is indispensable.</li><li>In software, cost of change is low, so the later you think about them, the better.</li><li>No grand redesigns.</li><li>The only way to go fast... is to go well. Basically, you have to put in quality, which contrary to popular opinion, does not slow you down but in fact allows you to go faster. Code doesn't rot; we make it that way and it's our responsibility to keep the code clean.</li><li>Green band: Uncle Bob wears a green wristband to remind him to always keep the code clean, and you can get one <a href="http://butunclebob.com/ArticleS.UncleBob.GreenWristBand">here</a>.</li><li>TDD: By following the <a href="http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd">three laws of TDD</a>, you can always have clean, simple, testable code.</li><li>Most attendees had short iterations of either one week or 2 weeks. Uncle Bob said that perhaps when he asks again next time, iterations may be even shorter!</li></ul><div><b>Debugging Pair Programming </b>by Matt Wynne</div><div>Although I couldn't stay for the entire session, since I had to leave to prepare for another day of <a href="http://agile2009.agilealliance.org/programmingwiththestars">Programming with the Stars</a>, I thought the session started out okay by identifying the benefits of pair programming. </div><div><ul><li>High truck number: I've never heard of this phrase before this session. Basically it means that when you pair, you are spreading the knowledge so that it's not just one person who's the expert as in most traditional projects. So if that expert were to get hit (god forbid) by a truck, the team would still be okay. So you can have more people hit by trucks, and the team can still function.</li><li>Free training </li><li>Instant code reviews</li><li>Team building: cheaper than going out for paintball, and less painful.</li></ul></div><div>Each table had a large sheet of paper, some sticky notes, markers, and a persona. This persona was basically someone that may or may not have heard of pair programming, and listed their reasons for not adopting it. Our goal was to list the reasons why they may be afraid to adopt pair programming.</div><div><br /></div><div>My first table was fine since everyone took a sticky and shared their thoughts. Then we were asked to keep one person at the table, and everyone else move to another table. The person remaining was to explain what we talked about and then discuss how to overcome those barriers.</div><div><br /></div><div>So, at the second table, I think because there were no moderators, each discussion ended up turning into arguments. Also, some participants' views were not being recorded since the sticky notes weren't being used and it seemed like the guy at the table was filtering out comments. It may have been unintentional but it would have been good to get everyone's input.</div><div><br /></div><div><b><a href="http://www.infoq.com/presentations/integration-tests-scam">Integration Tests are a Scam</a> </b>by <a href="http://www.jbrains.ca/">J.B. Rainsberger</a></div><div>Originally, I had recorded the audio on my iPhone, and I was going to listen to the whole thing and write down the key points but I think it's unnecessary now since I'd be repeating what everyone else has already written.</div><div><br /></div><div>To sum it up in a few sentences: basically with integration tests, you end up with a lot of duplication. The tests become slow and brittle, and as we all know, slow tests end up not being run. We want to make sure that in our unit tests that communicate with collaborators, that we are:</div><div><ol><li>mocking out the collaborators</li><li>making sure we are sending messages (parameters) that they can actually handle</li><li>ensuring that they respond the way we think they do</li></ol><div>This is done with collaboration and contract tests. </div><div><br /></div><div>This is not to say acceptance tests are useless, because they test the entire system from end-to-end. It's that with the right collaboration and contract tests, you do not need to write any integration tests, and therefore, keep your tests DRY.<br /><br /></div><div><b><a href="http://agile2009.agilealliance.org/programmingwiththestars">Programming with the Stars 2009</a></b><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 213px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOsXnb4q-vr0vcrYOWyVxVohOBloX3B5UX55LnXXw4cYtNC_reSiu0mZWuTnshOc2lRUsuonmeV4GNiwHgaSddDiU92wMk8680k6aWnur12Jf03QDVxiFvDmQrELtdb6SmKzNF/s320/DSC_0481.jpg" alt="" id="BLOGGER_PHOTO_ID_5390048214865710242" border="0" /></div><div>I was lucky enough to be selected as a participant in Programming with the Stars 2009, and the star I was paired with was <a href="http://www.renaissancesoftware.net/blog/">James Grenning</a>, the creator of planning poker and an expert at TDD in C and C++, especially in embedded software.</div><div><br /></div><div><i>First day</i></div><div>The first day, we were tasked with refactoring existing code. I hadn't programmed in C and C++ in over 5 years, so I had a lot of catching up to do. Thanks to James, I was able to get up to speed in running unit tests, refactoring, etc in Eclipse. We were given only 3 minutes to perform. When you're up there pair programming in front of a live audience, the time really flies!</div><div><br /></div><div><i>Day 2</i></div><div>We made it to day 2, where our task was TDD from scratch. It was another exciting day, but both James and I performed on an empty stomach since the competition was far away from lunch. We were given 5 minutes this time.</div><div><br /></div><div><i>Day 3</i></div><div>Somehow, we survived day 2 and made it to day 3, where our task was a 6-minute SDD performance. We used FitNesse and CSlim to show the development of a home automation user story. I was amazed at how FitNesse could integrate with so many languages.</div><div>It was a close call this day, as we were in the bottom two pairs, but thanks to the audience, we were saved.</div><div><br /></div><div><i>Final Day</i></div><div>The final day's assignment was a 6-minute freestyle performance. There was a coin toss to see which team would go second since throughout the competition, it seemed like going first was a disadvantage.</div><div><br /></div><div>So it would be the team of Gerard Meszaros and Ola Ellnestam, or Grenning/Chien. The non-star partners were called up to call heads or tails. Ola called tails, but during the coin toss, it hit the podium and I called "interference." :)</div><div><br /></div><div>James and I decided to recap what we did throughout the whole week. Some of the judges liked the idea; others didn't. It was okay; we were only down by 2 points. After the scoring,the audience was asked to vote by writing down their score, from 1 to 10 for each of the pairs. While that was going on, the bonus round was announced: write "Hello Programming with the Stars" to the console using any language, but with the following conditions:</div><div><ol><li>Leave the computer in its current state</li><li>Disable the mouse</li><li>The star can only type with his left hand, typing only the keys that the left hand normally types. The other partner has to type with his right hand, typing only the letters/keys that the right hand normally types.</li></ol><div>While Meszaros/Ellnestam were performing, the audience's votes, averaged and multiplied by three gave Meszaros/Ellnestam an additional lead of three more points. </div><div>James and I were thinking of what language to use and decided on C. I had already typed it up and executed it on my personal laptop, using vi and the terminal. </div><div><br /></div><div>However, when we went up there, I was confused since we wrote it in Eclipse. Although we finally figured out how to run the program, we were a little too late. The other team finished in 1:28; we finished in 2:49.</div><div><br /></div><div>Although we ended up with second place, I thought the entire competition was a lot of fun. It was great working with James Grenning, and meeting the other stars and competitors, as well the hosts and judges. I learned a lot, and it was an experience that I'll never forget. </div><div><br /></div><div><b>Overall summary of Agile 2009</b></div><div>This was my first time attending an Agile conference, and I really enjoyed it. I made a lot of friends, learned a lot of new things, and I'd definitely recommend going to this conference if you've never gone. Hope to see you next year at <a href="https://www.agile2010.org/home">Agile 2010</a>!</div></div><div><br /></div></div></div>Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-40878764173455501622009-06-12T16:58:00.000-07:002009-06-12T17:00:49.965-07:00We're back!Geekyninja is back, after a long hiatus! I'll be blogging both here and at <a href="http://criticalphase.com">Critical Phase</a>. Check out my new entry regarding Spring MVC 2.5 and all that annotated controller goodness: <a href="http://69.89.10.41/?p=39">Fun with Spring MVC 2.5 Annotations</a>.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-62974947740749093612008-12-19T11:38:00.000-08:002008-12-19T21:19:49.728-08:00Easy dependency management with m2eclipseIf you've ever used Maven, or are currently using it, you know that most of the time, it can be a pain to add a new dependency.<br /><br />So you know how it goes. You need a new JAR; you fire up your browser of choice, go to the central repository and hunt for the jar that you need. You finally find it after digging through all the folders, then open up pom.xml and add the group id, artifact id, optional version number, etc., and finally, run maven to get the new jar.<br />Easy huh? ;)<br /><br />With the m2eclipse plugin, (available at <a href="http://m2eclipse.sonatype.org/update/" target="_new">http://m2eclipse.sonatype.org/update/</a>), you no longer have to go through that multi-step process.<br /><br />If you haven't added the update site before, you'll have to add it manually.<br />1. Go to Help -> Software Updates -> Find and install<br />2. Choose the "Search for new features to install" option and click Next<br />3. Click "New Remote Site..."<br />4. Enter "m2eclipse" for the name and enter the URL http://m2eclipse.sonatype.org/update/<br /><br />Now you add dependencies automatically when:<br /><span style="font-weight: bold;">Right clicking on the project</span> and going to Maven -> Add dependency.<br />and<br /><span style="font-weight: bold;">During coding</span>: code as you normally do, and when Eclipse complains that the class can't be found, you can click on the red "x" and find the dependency by going through the central repository!<br /><br /><br />In the example below, I added the @RequestMapping annotation to my Spring 2.5 Controller, and since I didn't have the jar in my local repository, Eclipse notified me of the error. (<span style="font-style: italic;">Figure 1</span>)<br /><br /><br />Clicking on "Search dependency for RequestMapping" then searched the repository, and provided a listing of potential matching jars. Select the one you want and the rest is automatically taken care of! (<span style="font-style: italic;">Figure 2</span>)<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixsuK_08qkCUupifzafJkt3iaxCSKdrJRWozN5X5Arjzgp3_zRDeScfgde3Lnmy6Hq5IKlVMaN_DjEa2e4PVjAcWAH0pUUD1txuAPP8k448IJK-mHe6hXscrXzBOFhVlwaTZjB/s1600-h/m2a.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 161px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixsuK_08qkCUupifzafJkt3iaxCSKdrJRWozN5X5Arjzgp3_zRDeScfgde3Lnmy6Hq5IKlVMaN_DjEa2e4PVjAcWAH0pUUD1txuAPP8k448IJK-mHe6hXscrXzBOFhVlwaTZjB/s320/m2a.jpg" alt="" id="BLOGGER_PHOTO_ID_5281605884269740610" border="0" /></a><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight: bold;">Figure 1: </span>Clicking on the red "x" brings up a context menu where you can search the Maven central repository<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdbtVDH-fQcJtGubkkDMCRhl_l-F0Grh7o2K_anXq3TDUzyG7SRXx4rMMx2Q76wFkrNT21fF94tb2Gs8MqhOw4rhzQlwH0cp6UtS_T1U_Z8zRj35k4MSbzMpHPs0EUsBHjFH6b/s1600-h/m2b.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 97px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdbtVDH-fQcJtGubkkDMCRhl_l-F0Grh7o2K_anXq3TDUzyG7SRXx4rMMx2Q76wFkrNT21fF94tb2Gs8MqhOw4rhzQlwH0cp6UtS_T1U_Z8zRj35k4MSbzMpHPs0EUsBHjFH6b/s320/m2b.jpg" alt="" id="BLOGGER_PHOTO_ID_5281606152289348290" border="0" /></a><br /><br /><br /><br /><br /><br /><span style="font-weight: bold;">Figure 2:</span> The class name is automatically entered, and a list of jars that contain that class is shown.<br /><br />m2eclipse will take care of downloading the required jars and adding them to your classpath. That's it!Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-57253063497114089862008-12-12T19:17:00.000-08:002008-12-13T08:23:33.204-08:00SpringOne 2008I missed The Spring Experience 2007, but was able to return in 2008, and it has been renamed to springOne. During Adrian Colyer's keynote, he posted this hilarious photo:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi59RY4KIhDhQZberNzmBUhFGt4tCPmxdNOrZADMvHbMhDrXexIqRAhj9Wup_qqxvAzHpLDJKmEmuj9-EZCihDQ6Xol6cSeO05mfo7vbWbavfg_5aITrz_mDL_q5gadmmSsViLc/s1600-h/iloveejb.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi59RY4KIhDhQZberNzmBUhFGt4tCPmxdNOrZADMvHbMhDrXexIqRAhj9Wup_qqxvAzHpLDJKmEmuj9-EZCihDQ6Xol6cSeO05mfo7vbWbavfg_5aITrz_mDL_q5gadmmSsViLc/s320/iloveejb.JPG" alt="" id="BLOGGER_PHOTO_ID_5279109246224379682" border="0" /></a>Yes, that's the Rod Johnson bobblehead doll! I'm so jealous of everyone who was able to attend in 2007. Hopefully they give out something like this in 2009.<br /><br />On a more serious note, some of the highlights of the conference:<br /><br /><span style="font-weight: bold;">Managing the war on complexity:</span> This was the theme of Rod Johnson's keynote, and I'm glad he explicitly said this, as Spring is truly one of the best solutions to making Java EE web apps simple to maintain and develop.<br /><br /><span style="font-weight: bold;">OSGi: </span>Becoming very popular, and something worth looking into.<br /><br /><span style="font-weight: bold;">Spring MVC:</span> The old Controller hierarchy is going away, and moving towards the annotation based Controllers found in 2.5. Also, Spring 3.0 will have native REST support!<br /><br /><span style="font-weight: bold;">Grails: </span>If you follow the Grails scene, then you know that G2One, the company behind Grails, has been acquired by SpringOne. Rod just reiterated this to let the community know that Grails will have even better Spring support now that they are the same company.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-69250158877661717282008-07-10T17:30:00.000-07:002009-06-18T15:25:53.327-07:00Grails Eclipse pluginSo I was messing around with Grails the other day, and heard about the wonderful Eclipse plugin. Like the documentation says, grails generates all the necessary files for Eclipse to recognize your project. <br /><br />This is great and all, but a lot of people I spoke to encountered the same problem I did.<br />There's a file for your Spring DSL code, called resources.groovy located in<br /><your-app>/grails-app/conf/spring.<br /><br />Many people will then receive the following error:<br /><code><br />Invalid Package declaration in script: <path-to-your-project>/grails-app/conf/spring/resources.groovy is not in a source folder matching the package declaration: DonutStore/grails-app/conf/spring resources.groovy<br /></code><br /><br />I don't know enough Grails at the moment, but a quick fix is to add:<br /><code><br />package spring;<br /></code><br />to the top of the file.<br /><br /><span style="font-weight:bold;">Update:</span>I've been coding Grails apps for several months now, and realize that this is just an error with the Eclipse plugin. Since I develop on the Mac, I prefer TextMate anyway. However, if you're an Eclipse fan, be glad that the SpringSource guys are working on a new and improved plugin and it should be available later this year.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-30926084149566570962008-07-08T09:53:00.000-07:002010-12-23T10:43:21.484-08:00Spring method injectionI recently inherited some legacy code and it's been extremely difficult to refactor. It's a catch-22: you can't refactor without unit tests in place, but it's difficult to unit test since it wasn't written to be testable. [TDD can cure this. :)]<br />
<br />
So after much hair-pulling and thought, I was able to extract a few interfaces and configure some of the business logic classes as Spring managed beans. The problem was that some of the dependencies were still being acquired via the "new" keyword, and it had to remain that way. <br />
<br />
In other words, I had a singleton bean which required a non-singleton, or prototype. Not just once, at bean creation time, but a new instance <i>every</i> time. How could this be done, without mucking up my code with the Spring API? We definitely do not want a reference to a BeanFactory or ApplicationContext in our bean.<br />
<br />
Enter one of the rarer forms of dependency injection: <a href="http://static.springframework.org/spring/docs/2.0.x/reference/beans.html">Method Injection </a> (see section 3.3.8).<br />
<br />
The recipe is:<br />
<ol><li>Create a method for the dependency and either make it protected abstract, or public.<br />
</li>
<li>In your applicationContext.xml, instead of specifying <property name="someProperty">, you use<br />
<lookup-method name="theMethodWhichReturnsYourPrototype" bean="idOfPrototypeBean"/><br />
</li>
</ol><br />
<br />
Let's look at an example:<br />
<br />
We have a class Homer, which wants a new instance of another bean, a Donut, every time, instead of reusing the same Donut over and over again.<br />
<script src="https://gist.github.com/753369.js"> </script><br />
<br />
Now, for the applicationContext.xml:<br />
<code><br />
</code><pre><!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="donut" class="demo.DonutImpl" scope="prototype">
<!-- inject dependencies here as required -->
</bean>
<!-- homer (singleton) uses donut (prototype) -->
<bean id="homer" class="demo.Homer">
<lookup-method name="getDonut" bean="donut"/>
</bean>
</pre><br />
<br />
<br />
So what's going on here? To quote the Spring docs:<br />
<blockquote>The Spring Framework implements this method injection by dynamically generating a subclass overriding the method, using bytecode generation via the CGLIB library.</blockquote><br />
<br />
So when Homer asks for a donut via getDonut(), the subclassed Homer, generated via CGLIB, will return a new instance of Donut, which has its dependencies injected by Spring.<br />
<br />
Pros of this approach: we are decoupled from BeanFactory and the Spring API<br />
Cons: making the bean abstract makes testing a little difficult, since you have to subclass the class, however, making it concrete and implementing the getter method, you avoid this.Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-19683536557141391492008-02-28T11:31:00.000-08:002008-02-29T13:57:27.282-08:00Multiline /newline Button label in Flex 3I was having the hardest time getting a newline to appear in my Button component. I followed the documentation in the <a href="http://livedocs.adobe.com/flex/3/html/help.html?content=mxmlSyntax_3.html">Adobe Flex 3 docs</a> to use <span style="font-weight: bold;">&13; </span>but that still did not work.<br /><br />I got some e-mails from Matt Horn of Adobe Flex Docs, and he gave me several things to try, including using the standard "\n" character escape sequence, and the HTML "<br/>". Finally, he gave me a link to a blog entry by Alex Harui titled "<a href="http://blogs.adobe.com/aharui/2007/04/multiline_buttons.html">Multiline Buttons</a>".<br /><br />The code needed a little tweaking for Flex 3, but all I did was extend the Button class, and use the same exact code Alex used in his MultilineRadioButton.<br /><br />That being said, here's my MultilineButton.<br />You can use this component like a regular button; the difference now is that if you include "&13;" in your label, it will render a newline! <br /><br />Enjoy.<br /><br /><pre class="code"><code><br />package <br />{<br />import flash.display.DisplayObject;<br />import flash.text.TextLineMetrics;<br /><br />import mx.controls.Button;<br />import mx.core.IFlexDisplayObject;<br />import mx.core.mx_internal;<br />use namespace mx_internal;<br /><br /><br /> public class MultilineButton extends Button<br /> {<br /> public function MultilineButton()<br /> {<br /> //TODO: implement function<br /> super();<br /> }<br /> <br /> override protected function createChildren():void<br /> {<br /> if (!textField)<br /> {<br /> textField = new NoTruncationUITextField();<br /> textField.styleName = this;<br /> addChild(DisplayObject(textField)); //cast required for Flex 3; if in Flex 2; remove<br /> }<br /> <br /> super.createChildren();<br /> <br /> textField.multiline = true;<br /> textField.wordWrap = true;<br /> }<br /><br /> override protected function measure():void<br /> {<br /> if (!isNaN(explicitWidth))<br /> {<br /> var tempIcon:IFlexDisplayObject = getCurrentIcon();<br /> var w:Number = explicitWidth;<br /> if (tempIcon)<br /> w -= tempIcon.width + getStyle("horizontalGap") + getStyle("paddingLeft") + getStyle("paddingRight");<br /> textField.width = w;<br /> }<br /> super.measure();<br /> <br /> }<br /><br /> override public function measureText(s:String):TextLineMetrics<br /> {<br /> textField.text = s;<br /> var lineMetrics:TextLineMetrics = textField.getLineMetrics(0);<br /> lineMetrics.width = textField.textWidth + 4;<br /> lineMetrics.height = textField.textHeight + 4;<br /> return lineMetrics;<br /> }<br /> }<br />}<br /></code><br /></pre>Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com2tag:blogger.com,1999:blog-20096602.post-40669064302280021942008-02-26T09:58:00.000-08:002008-12-09T01:52:04.695-08:00Flex Day 2 (or 3, if you count Sunday)<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNlqBRTIKR8n7PmpMLacdv8XWFqc8qSdkdQCQfavh5eg2oqF1XyKazDV-zOdD1vEcZwznXFc3AT0r04XolCjaQ6Qv6-KDjkF4i5LQ476xTTnkpLkGn4AZUe1pVkAl3bwXdAmsA/s1600-h/atl_bling_75.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNlqBRTIKR8n7PmpMLacdv8XWFqc8qSdkdQCQfavh5eg2oqF1XyKazDV-zOdD1vEcZwznXFc3AT0r04XolCjaQ6Qv6-KDjkF4i5LQ476xTTnkpLkGn4AZUe1pVkAl3bwXdAmsA/s320/atl_bling_75.png" alt="" id="BLOGGER_PHOTO_ID_5171353100753961954" border="0" /></a><br /><br /><br />The nightly parties at 360|Flex have been awesome, as well as the sessions.<br />Here's a review of some sessions I attended.<br /><br /><span style="font-weight: bold;">QTIndexSwapper and more Flash H.264 Fun - </span>Renaun Erickson<br /><ul><li>Renaun showed his custom code which reindexes QuickTime movies so that the movie plays while downloading, AND the metadata is available sooner, rather than waiting for the entire movie to download</li><li>Check out his blog and link to his Google code: <a href="http://www.renaun.com/blog/">http://www.renaun.com/blog/</a><br /></li></ul><br /><span style="font-weight: bold;">Future of Flex</span> - Deepa Subramaniam<br /><ul><li>Flex for Mobile<br /></li><li>Thermo - RIA Design tool; easy for designers and developers to create revolutionary and interactive interfaces that can be taken directly into production</li><ul><li>Feels like an Adobe Creative Suite product<br /></li></ul><li>MXML-G, a new graphics library</li><li>Flex 4 components - has a new MVC model, where the skin (defined via CSS) is considered the view<br /></li><ul><li>Deepa showed a demo where a button changed its look dynamically<br /></li></ul></ul>Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0tag:blogger.com,1999:blog-20096602.post-71952450083567677812008-02-24T11:54:00.000-08:002008-02-24T11:55:43.979-08:00360 Flex AtlantaI'm here in Atlanta for the 360 Flex Conference. It's a little cold here in ATL, but I'm in the comfort of the Omni Hotel, taking the Flex 101 course. We're building a photo application. I'll post more later!Kenhttp://www.blogger.com/profile/04466467747514374651noreply@blogger.com0